File: | ctk/ctktextview.c |
Warning: | line 7862, column 20 This statement is never executed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* -*- Mode: C; c-file-style: "gnu"; tab-width: 8 -*- */ |
2 | /* CTK - The GIMP Toolkit |
3 | * ctktextview.c Copyright (C) 2000 Red Hat, Inc. |
4 | * |
5 | * This library is free software; you can redistribute it and/or |
6 | * modify it under the terms of the GNU Lesser General Public |
7 | * License as published by the Free Software Foundation; either |
8 | * version 2 of the License, or (at your option) any later version. |
9 | * |
10 | * This library is distributed in the hope that it will be useful, |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | * Lesser General Public License for more details. |
14 | * |
15 | * You should have received a copy of the GNU Lesser General Public |
16 | * License along with this library. If not, see <http://www.gnu.org/licenses/>. |
17 | */ |
18 | |
19 | /* |
20 | * Modified by the CTK+ Team and others 1997-2000. See the AUTHORS |
21 | * file for a list of people on the CTK+ Team. See the ChangeLog |
22 | * files for a list of changes. These files are distributed with |
23 | * CTK+ at ftp://ftp.ctk.org/pub/ctk/. |
24 | */ |
25 | |
26 | #include "config.h" |
27 | |
28 | #include <string.h> |
29 | |
30 | #define CTK_TEXT_USE_INTERNAL_UNSUPPORTED_API |
31 | #include "ctkadjustmentprivate.h" |
32 | #include "ctkbindings.h" |
33 | #include "ctkdnd.h" |
34 | #include "ctkdebug.h" |
35 | #include "ctkintl.h" |
36 | #include "ctkmain.h" |
37 | #include "ctkmarshalers.h" |
38 | #include "ctkmenu.h" |
39 | #include "ctkmenuitem.h" |
40 | #include "ctkrenderbackgroundprivate.h" |
41 | #include "ctkseparatormenuitem.h" |
42 | #include "ctksettings.h" |
43 | #include "ctkselectionprivate.h" |
44 | #include "ctktextbufferrichtext.h" |
45 | #include "ctktextdisplay.h" |
46 | #include "ctktextview.h" |
47 | #include "ctkimmulticontext.h" |
48 | #include "ctkprivate.h" |
49 | #include "ctktextutil.h" |
50 | #include "ctkwidgetprivate.h" |
51 | #include "ctkwindow.h" |
52 | #include "ctkscrollable.h" |
53 | #include "ctktypebuiltins.h" |
54 | #include "ctktexthandleprivate.h" |
55 | #include "ctkcssstylepropertyprivate.h" |
56 | #include "ctkpopover.h" |
57 | #include "ctktoolbar.h" |
58 | #include "ctkpixelcacheprivate.h" |
59 | #include "ctkmagnifierprivate.h" |
60 | #include "ctkemojichooser.h" |
61 | #include "ctkpango.h" |
62 | |
63 | #include "a11y/ctktextviewaccessibleprivate.h" |
64 | |
65 | /** |
66 | * SECTION:ctktextview |
67 | * @Short_description: Widget that displays a CtkTextBuffer |
68 | * @Title: CtkTextView |
69 | * @See_also: #CtkTextBuffer, #CtkTextIter |
70 | * |
71 | * You may wish to begin by reading the |
72 | * [text widget conceptual overview][TextWidget] |
73 | * which gives an overview of all the objects and data |
74 | * types related to the text widget and how they work together. |
75 | * |
76 | * # CSS nodes |
77 | * |
78 | * |[<!-- language="plain" --> |
79 | * textview.view |
80 | * ├── border.top |
81 | * ├── border.left |
82 | * ├── text |
83 | * │ ╰── [selection] |
84 | * ├── border.right |
85 | * ├── border.bottom |
86 | * ╰── [window.popup] |
87 | * ]| |
88 | * |
89 | * CtkTextView has a main css node with name textview and style class .view, |
90 | * and subnodes for each of the border windows, and the main text area, |
91 | * with names border and text, respectively. The border nodes each get |
92 | * one of the style classes .left, .right, .top or .bottom. |
93 | * |
94 | * A node representing the selection will appear below the text node. |
95 | * |
96 | * If a context menu is opened, the window node will appear as a subnode |
97 | * of the main node. |
98 | */ |
99 | |
100 | |
101 | /* How scrolling, validation, exposes, etc. work. |
102 | * |
103 | * The expose_event handler has the invariant that the onscreen lines |
104 | * have been validated. |
105 | * |
106 | * There are two ways that onscreen lines can become invalid. The first |
107 | * is to change which lines are onscreen. This happens when the value |
108 | * of a scroll adjustment changes. So the code path begins in |
109 | * ctk_text_view_value_changed() and goes like this: |
110 | * - cdk_window_scroll() to reflect the new adjustment value |
111 | * - validate the lines that were moved onscreen |
112 | * - cdk_window_process_updates() to handle the exposes immediately |
113 | * |
114 | * The second way is that you get the “invalidated” signal from the layout, |
115 | * indicating that lines have become invalid. This code path begins in |
116 | * invalidated_handler() and goes like this: |
117 | * - install high-priority idle which does the rest of the steps |
118 | * - if a scroll is pending from scroll_to_mark(), do the scroll, |
119 | * jumping to the ctk_text_view_value_changed() code path |
120 | * - otherwise, validate the onscreen lines |
121 | * - DO NOT process updates |
122 | * |
123 | * In both cases, validating the onscreen lines can trigger a scroll |
124 | * due to maintaining the first_para on the top of the screen. |
125 | * If validation triggers a scroll, we jump to the top of the code path |
126 | * for value_changed, and bail out of the current code path. |
127 | * |
128 | * Also, in size_allocate, if we invalidate some lines from changing |
129 | * the layout width, we need to go ahead and run the high-priority idle, |
130 | * because CTK sends exposes right after doing the size allocates without |
131 | * returning to the main loop. This is also why the high-priority idle |
132 | * is at a higher priority than resizing. |
133 | * |
134 | */ |
135 | |
136 | #if 0 |
137 | #define DEBUG_VALIDATION_AND_SCROLLING |
138 | #endif |
139 | |
140 | #ifdef DEBUG_VALIDATION_AND_SCROLLING |
141 | #define DV(x) (x) |
142 | #else |
143 | #define DV(x) |
144 | #endif |
145 | |
146 | #define SCREEN_WIDTH(widget)text_window_get_width (((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((widget)), ((ctk_text_view_get_type ()))) )))->priv->text_window) text_window_get_width (CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ()))))))->priv->text_window) |
147 | #define SCREEN_HEIGHT(widget)text_window_get_height (((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((widget)), ((ctk_text_view_get_type ()))) )))->priv->text_window) text_window_get_height (CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ()))))))->priv->text_window) |
148 | |
149 | #define SPACE_FOR_CURSOR1 1 |
150 | |
151 | #define CTK_TEXT_VIEW_GET_PRIVATE(obj)(((CtkTextViewPrivate*) g_type_instance_get_private ((GTypeInstance *) ((obj)), ((ctk_text_view_get_type ())))) GCC warning "Deprecated pre-processor symbol: replace with \"G_ADD_PRIVATE\"" ) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), CTK_TYPE_TEXT_VIEW, CtkTextViewPrivate)((CtkTextViewPrivate*) g_type_instance_get_private ((GTypeInstance *) ((obj)), ((ctk_text_view_get_type ())))) GCC warning "Deprecated pre-processor symbol: replace with \"G_ADD_PRIVATE\"" ) |
152 | |
153 | typedef struct _CtkTextWindow CtkTextWindow; |
154 | typedef struct _CtkTextPendingScroll CtkTextPendingScroll; |
155 | |
156 | struct _CtkTextViewPrivate |
157 | { |
158 | CtkTextLayout *layout; |
159 | CtkTextBuffer *buffer; |
160 | |
161 | guint blink_time; /* time in msec the cursor has blinked since last user event */ |
162 | guint im_spot_idle; |
163 | gchar *im_module; |
164 | |
165 | gint dnd_x; |
166 | gint dnd_y; |
167 | |
168 | CtkTextHandle *text_handle; |
169 | CtkWidget *selection_bubble; |
170 | guint selection_bubble_timeout_id; |
171 | |
172 | CtkWidget *magnifier_popover; |
173 | CtkWidget *magnifier; |
174 | |
175 | CtkTextWindow *text_window; |
176 | CtkTextWindow *left_window; |
177 | CtkTextWindow *right_window; |
178 | CtkTextWindow *top_window; |
179 | CtkTextWindow *bottom_window; |
180 | |
181 | CtkAdjustment *hadjustment; |
182 | CtkAdjustment *vadjustment; |
183 | |
184 | /* X offset between widget coordinates and buffer coordinates |
185 | * taking left_padding in account |
186 | */ |
187 | gint xoffset; |
188 | |
189 | /* Y offset between widget coordinates and buffer coordinates |
190 | * taking top_padding and top_margin in account |
191 | */ |
192 | gint yoffset; |
193 | |
194 | /* Width and height of the buffer */ |
195 | gint width; |
196 | gint height; |
197 | |
198 | /* This is used to monitor the overall size request |
199 | * and decide whether we need to queue resizes when |
200 | * the buffer content changes. |
201 | * |
202 | * FIXME: This could be done in a simpler way by |
203 | * consulting the above width/height of the buffer + some |
204 | * padding values, however all of this request code needs |
205 | * to be changed to use CtkWidget Iface and deserves |
206 | * more attention. |
207 | */ |
208 | CtkRequisition cached_size_request; |
209 | |
210 | /* The virtual cursor position is normally the same as the |
211 | * actual (strong) cursor position, except in two circumstances: |
212 | * |
213 | * a) When the cursor is moved vertically with the keyboard |
214 | * b) When the text view is scrolled with the keyboard |
215 | * |
216 | * In case a), virtual_cursor_x is preserved, but not virtual_cursor_y |
217 | * In case b), both virtual_cursor_x and virtual_cursor_y are preserved. |
218 | */ |
219 | gint virtual_cursor_x; /* -1 means use actual cursor position */ |
220 | gint virtual_cursor_y; /* -1 means use actual cursor position */ |
221 | |
222 | CtkTextMark *first_para_mark; /* Mark at the beginning of the first onscreen paragraph */ |
223 | gint first_para_pixels; /* Offset of top of screen in the first onscreen paragraph */ |
224 | |
225 | guint blink_timeout; |
226 | guint scroll_timeout; |
227 | |
228 | guint first_validate_idle; /* Idle to revalidate onscreen portion, runs before resize */ |
229 | guint incremental_validate_idle; /* Idle to revalidate offscreen portions, runs after redraw */ |
230 | |
231 | CtkTextMark *dnd_mark; |
232 | |
233 | CtkIMContext *im_context; |
234 | CtkWidget *popup_menu; |
235 | |
236 | GSList *children; |
237 | |
238 | CtkTextPendingScroll *pending_scroll; |
239 | |
240 | CtkPixelCache *pixel_cache; |
241 | |
242 | CtkGesture *multipress_gesture; |
243 | CtkGesture *drag_gesture; |
244 | |
245 | CtkCssNode *selection_node; |
246 | |
247 | /* Default style settings */ |
248 | gint pixels_above_lines; |
249 | gint pixels_below_lines; |
250 | gint pixels_inside_wrap; |
251 | CtkWrapMode wrap_mode; |
252 | CtkJustification justify; |
253 | |
254 | gint left_margin; |
255 | gint right_margin; |
256 | gint top_margin; |
257 | gint bottom_margin; |
258 | gint left_padding; |
259 | gint right_padding; |
260 | gint top_padding; |
261 | gint bottom_padding; |
262 | gint top_border; |
263 | gint bottom_border; |
264 | gint left_border; |
265 | gint right_border; |
266 | |
267 | gint indent; |
268 | gint64 handle_place_time; |
269 | PangoTabArray *tabs; |
270 | guint editable : 1; |
271 | |
272 | guint overwrite_mode : 1; |
273 | guint cursor_visible : 1; |
274 | |
275 | /* if we have reset the IM since the last character entered */ |
276 | guint need_im_reset : 1; |
277 | |
278 | guint accepts_tab : 1; |
279 | |
280 | guint width_changed : 1; |
281 | |
282 | /* debug flag - means that we've validated onscreen since the |
283 | * last "invalidate" signal from the layout |
284 | */ |
285 | guint onscreen_validated : 1; |
286 | |
287 | guint mouse_cursor_obscured : 1; |
288 | |
289 | guint scroll_after_paste : 1; |
290 | |
291 | /* CtkScrollablePolicy needs to be checked when |
292 | * driving the scrollable adjustment values */ |
293 | guint hscroll_policy : 1; |
294 | guint vscroll_policy : 1; |
295 | guint cursor_handle_dragged : 1; |
296 | guint selection_handle_dragged : 1; |
297 | guint populate_all : 1; |
298 | |
299 | guint in_scroll : 1; |
300 | guint handling_key_event : 1; |
301 | }; |
302 | |
303 | struct _CtkTextPendingScroll |
304 | { |
305 | CtkTextMark *mark; |
306 | gdouble within_margin; |
307 | gboolean use_align; |
308 | gdouble xalign; |
309 | gdouble yalign; |
310 | }; |
311 | |
312 | typedef enum |
313 | { |
314 | SELECT_CHARACTERS, |
315 | SELECT_WORDS, |
316 | SELECT_LINES |
317 | } SelectionGranularity; |
318 | |
319 | enum |
320 | { |
321 | POPULATE_POPUP, |
322 | MOVE_CURSOR, |
323 | PAGE_HORIZONTALLY, |
324 | SET_ANCHOR, |
325 | INSERT_AT_CURSOR, |
326 | DELETE_FROM_CURSOR, |
327 | BACKSPACE, |
328 | CUT_CLIPBOARD, |
329 | COPY_CLIPBOARD, |
330 | PASTE_CLIPBOARD, |
331 | TOGGLE_OVERWRITE, |
332 | MOVE_VIEWPORT, |
333 | SELECT_ALL, |
334 | TOGGLE_CURSOR_VISIBLE, |
335 | PREEDIT_CHANGED, |
336 | EXTEND_SELECTION, |
337 | INSERT_EMOJI, |
338 | LAST_SIGNAL |
339 | }; |
340 | |
341 | enum |
342 | { |
343 | PROP_0, |
344 | PROP_PIXELS_ABOVE_LINES, |
345 | PROP_PIXELS_BELOW_LINES, |
346 | PROP_PIXELS_INSIDE_WRAP, |
347 | PROP_EDITABLE, |
348 | PROP_WRAP_MODE, |
349 | PROP_JUSTIFICATION, |
350 | PROP_LEFT_MARGIN, |
351 | PROP_RIGHT_MARGIN, |
352 | PROP_TOP_MARGIN, |
353 | PROP_BOTTOM_MARGIN, |
354 | PROP_INDENT, |
355 | PROP_TABS, |
356 | PROP_CURSOR_VISIBLE, |
357 | PROP_BUFFER, |
358 | PROP_OVERWRITE, |
359 | PROP_ACCEPTS_TAB, |
360 | PROP_IM_MODULE, |
361 | PROP_HADJUSTMENT, |
362 | PROP_VADJUSTMENT, |
363 | PROP_HSCROLL_POLICY, |
364 | PROP_VSCROLL_POLICY, |
365 | PROP_INPUT_PURPOSE, |
366 | PROP_INPUT_HINTS, |
367 | PROP_POPULATE_ALL, |
368 | PROP_MONOSPACE |
369 | }; |
370 | |
371 | static GQuark quark_text_selection_data = 0; |
372 | static GQuark quark_ctk_signal = 0; |
373 | static GQuark quark_text_view_child = 0; |
374 | |
375 | static void ctk_text_view_finalize (GObject *object); |
376 | static void ctk_text_view_set_property (GObject *object, |
377 | guint prop_id, |
378 | const GValue *value, |
379 | GParamSpec *pspec); |
380 | static void ctk_text_view_get_property (GObject *object, |
381 | guint prop_id, |
382 | GValue *value, |
383 | GParamSpec *pspec); |
384 | static void ctk_text_view_destroy (CtkWidget *widget); |
385 | static void ctk_text_view_size_request (CtkWidget *widget, |
386 | CtkRequisition *requisition); |
387 | static void ctk_text_view_get_preferred_width (CtkWidget *widget, |
388 | gint *minimum, |
389 | gint *natural); |
390 | static void ctk_text_view_get_preferred_height (CtkWidget *widget, |
391 | gint *minimum, |
392 | gint *natural); |
393 | static void ctk_text_view_size_allocate (CtkWidget *widget, |
394 | CtkAllocation *allocation); |
395 | static void ctk_text_view_map (CtkWidget *widget); |
396 | static void ctk_text_view_unmap (CtkWidget *widget); |
397 | static void ctk_text_view_realize (CtkWidget *widget); |
398 | static void ctk_text_view_unrealize (CtkWidget *widget); |
399 | static void ctk_text_view_style_updated (CtkWidget *widget); |
400 | static void ctk_text_view_direction_changed (CtkWidget *widget, |
401 | CtkTextDirection previous_direction); |
402 | static void ctk_text_view_state_flags_changed (CtkWidget *widget, |
403 | CtkStateFlags previous_state); |
404 | |
405 | static void ctk_text_view_multipress_gesture_pressed (CtkGestureMultiPress *gesture, |
406 | gint n_press, |
407 | gdouble x, |
408 | gdouble y, |
409 | CtkTextView *text_view); |
410 | static void ctk_text_view_drag_gesture_update (CtkGestureDrag *gesture, |
411 | gdouble offset_x, |
412 | gdouble offset_y, |
413 | CtkTextView *text_view); |
414 | static void ctk_text_view_drag_gesture_end (CtkGestureDrag *gesture, |
415 | gdouble offset_x, |
416 | gdouble offset_y, |
417 | CtkTextView *text_view); |
418 | |
419 | static gint ctk_text_view_event (CtkWidget *widget, |
420 | CdkEvent *event); |
421 | static gint ctk_text_view_key_press_event (CtkWidget *widget, |
422 | CdkEventKey *event); |
423 | static gint ctk_text_view_key_release_event (CtkWidget *widget, |
424 | CdkEventKey *event); |
425 | static gint ctk_text_view_focus_in_event (CtkWidget *widget, |
426 | CdkEventFocus *event); |
427 | static gint ctk_text_view_focus_out_event (CtkWidget *widget, |
428 | CdkEventFocus *event); |
429 | static gint ctk_text_view_motion_event (CtkWidget *widget, |
430 | CdkEventMotion *event); |
431 | static gint ctk_text_view_draw (CtkWidget *widget, |
432 | cairo_t *cr); |
433 | static gboolean ctk_text_view_focus (CtkWidget *widget, |
434 | CtkDirectionType direction); |
435 | static void ctk_text_view_select_all (CtkWidget *widget, |
436 | gboolean select); |
437 | static gboolean get_middle_click_paste (CtkTextView *text_view); |
438 | |
439 | static CtkTextBuffer* ctk_text_view_create_buffer (CtkTextView *text_view); |
440 | |
441 | /* Source side drag signals */ |
442 | static void ctk_text_view_drag_begin (CtkWidget *widget, |
443 | CdkDragContext *context); |
444 | static void ctk_text_view_drag_end (CtkWidget *widget, |
445 | CdkDragContext *context); |
446 | static void ctk_text_view_drag_data_get (CtkWidget *widget, |
447 | CdkDragContext *context, |
448 | CtkSelectionData *selection_data, |
449 | guint info, |
450 | guint time); |
451 | static void ctk_text_view_drag_data_delete (CtkWidget *widget, |
452 | CdkDragContext *context); |
453 | |
454 | /* Target side drag signals */ |
455 | static void ctk_text_view_drag_leave (CtkWidget *widget, |
456 | CdkDragContext *context, |
457 | guint time); |
458 | static gboolean ctk_text_view_drag_motion (CtkWidget *widget, |
459 | CdkDragContext *context, |
460 | gint x, |
461 | gint y, |
462 | guint time); |
463 | static gboolean ctk_text_view_drag_drop (CtkWidget *widget, |
464 | CdkDragContext *context, |
465 | gint x, |
466 | gint y, |
467 | guint time); |
468 | static void ctk_text_view_drag_data_received (CtkWidget *widget, |
469 | CdkDragContext *context, |
470 | gint x, |
471 | gint y, |
472 | CtkSelectionData *selection_data, |
473 | guint info, |
474 | guint time); |
475 | |
476 | static gboolean ctk_text_view_popup_menu (CtkWidget *widget); |
477 | |
478 | static void ctk_text_view_move_cursor (CtkTextView *text_view, |
479 | CtkMovementStep step, |
480 | gint count, |
481 | gboolean extend_selection); |
482 | static void ctk_text_view_move_viewport (CtkTextView *text_view, |
483 | CtkScrollStep step, |
484 | gint count); |
485 | static void ctk_text_view_set_anchor (CtkTextView *text_view); |
486 | static gboolean ctk_text_view_scroll_pages (CtkTextView *text_view, |
487 | gint count, |
488 | gboolean extend_selection); |
489 | static gboolean ctk_text_view_scroll_hpages(CtkTextView *text_view, |
490 | gint count, |
491 | gboolean extend_selection); |
492 | static void ctk_text_view_insert_at_cursor (CtkTextView *text_view, |
493 | const gchar *str); |
494 | static void ctk_text_view_delete_from_cursor (CtkTextView *text_view, |
495 | CtkDeleteType type, |
496 | gint count); |
497 | static void ctk_text_view_backspace (CtkTextView *text_view); |
498 | static void ctk_text_view_cut_clipboard (CtkTextView *text_view); |
499 | static void ctk_text_view_copy_clipboard (CtkTextView *text_view); |
500 | static void ctk_text_view_paste_clipboard (CtkTextView *text_view); |
501 | static void ctk_text_view_toggle_overwrite (CtkTextView *text_view); |
502 | static void ctk_text_view_toggle_cursor_visible (CtkTextView *text_view); |
503 | |
504 | static void ctk_text_view_unselect (CtkTextView *text_view); |
505 | |
506 | static void ctk_text_view_validate_onscreen (CtkTextView *text_view); |
507 | static void ctk_text_view_get_first_para_iter (CtkTextView *text_view, |
508 | CtkTextIter *iter); |
509 | static void ctk_text_view_update_layout_width (CtkTextView *text_view); |
510 | static void ctk_text_view_set_attributes_from_style (CtkTextView *text_view, |
511 | CtkTextAttributes *values); |
512 | static void ctk_text_view_ensure_layout (CtkTextView *text_view); |
513 | static void ctk_text_view_destroy_layout (CtkTextView *text_view); |
514 | static void ctk_text_view_check_keymap_direction (CtkTextView *text_view); |
515 | static void ctk_text_view_start_selection_drag (CtkTextView *text_view, |
516 | const CtkTextIter *iter, |
517 | SelectionGranularity granularity, |
518 | gboolean extends); |
519 | static gboolean ctk_text_view_end_selection_drag (CtkTextView *text_view); |
520 | static void ctk_text_view_start_selection_dnd (CtkTextView *text_view, |
521 | const CtkTextIter *iter, |
522 | const CdkEvent *event, |
523 | gint x, |
524 | gint y); |
525 | static void ctk_text_view_check_cursor_blink (CtkTextView *text_view); |
526 | static void ctk_text_view_pend_cursor_blink (CtkTextView *text_view); |
527 | static void ctk_text_view_stop_cursor_blink (CtkTextView *text_view); |
528 | static void ctk_text_view_reset_blink_time (CtkTextView *text_view); |
529 | |
530 | static void ctk_text_view_value_changed (CtkAdjustment *adjustment, |
531 | CtkTextView *view); |
532 | static void ctk_text_view_commit_handler (CtkIMContext *context, |
533 | const gchar *str, |
534 | CtkTextView *text_view); |
535 | static void ctk_text_view_commit_text (CtkTextView *text_view, |
536 | const gchar *text); |
537 | static void ctk_text_view_preedit_changed_handler (CtkIMContext *context, |
538 | CtkTextView *text_view); |
539 | static gboolean ctk_text_view_retrieve_surrounding_handler (CtkIMContext *context, |
540 | CtkTextView *text_view); |
541 | static gboolean ctk_text_view_delete_surrounding_handler (CtkIMContext *context, |
542 | gint offset, |
543 | gint n_chars, |
544 | CtkTextView *text_view); |
545 | |
546 | static void ctk_text_view_mark_set_handler (CtkTextBuffer *buffer, |
547 | const CtkTextIter *location, |
548 | CtkTextMark *mark, |
549 | gpointer data); |
550 | static void ctk_text_view_target_list_notify (CtkTextBuffer *buffer, |
551 | const GParamSpec *pspec, |
552 | gpointer data); |
553 | static void ctk_text_view_paste_done_handler (CtkTextBuffer *buffer, |
554 | CtkClipboard *clipboard, |
555 | gpointer data); |
556 | static void ctk_text_view_buffer_changed_handler (CtkTextBuffer *buffer, |
557 | gpointer data); |
558 | static void ctk_text_view_get_virtual_cursor_pos (CtkTextView *text_view, |
559 | CtkTextIter *cursor, |
560 | gint *x, |
561 | gint *y); |
562 | static void ctk_text_view_set_virtual_cursor_pos (CtkTextView *text_view, |
563 | gint x, |
564 | gint y); |
565 | |
566 | static void ctk_text_view_do_popup (CtkTextView *text_view, |
567 | const CdkEvent *event); |
568 | |
569 | static void cancel_pending_scroll (CtkTextView *text_view); |
570 | static void ctk_text_view_queue_scroll (CtkTextView *text_view, |
571 | CtkTextMark *mark, |
572 | gdouble within_margin, |
573 | gboolean use_align, |
574 | gdouble xalign, |
575 | gdouble yalign); |
576 | |
577 | static gboolean ctk_text_view_flush_scroll (CtkTextView *text_view); |
578 | static void ctk_text_view_update_adjustments (CtkTextView *text_view); |
579 | static void ctk_text_view_invalidate (CtkTextView *text_view); |
580 | static void ctk_text_view_flush_first_validate (CtkTextView *text_view); |
581 | |
582 | static void ctk_text_view_set_hadjustment (CtkTextView *text_view, |
583 | CtkAdjustment *adjustment); |
584 | static void ctk_text_view_set_vadjustment (CtkTextView *text_view, |
585 | CtkAdjustment *adjustment); |
586 | static void ctk_text_view_set_hadjustment_values (CtkTextView *text_view); |
587 | static void ctk_text_view_set_vadjustment_values (CtkTextView *text_view); |
588 | |
589 | static void ctk_text_view_update_im_spot_location (CtkTextView *text_view); |
590 | static void ctk_text_view_insert_emoji (CtkTextView *text_view); |
591 | |
592 | /* Container methods */ |
593 | static void ctk_text_view_add (CtkContainer *container, |
594 | CtkWidget *child); |
595 | static void ctk_text_view_remove (CtkContainer *container, |
596 | CtkWidget *child); |
597 | static void ctk_text_view_forall (CtkContainer *container, |
598 | gboolean include_internals, |
599 | CtkCallback callback, |
600 | gpointer callback_data); |
601 | |
602 | /* CtkTextHandle handlers */ |
603 | static void ctk_text_view_handle_drag_started (CtkTextHandle *handle, |
604 | CtkTextHandlePosition pos, |
605 | CtkTextView *text_view); |
606 | static void ctk_text_view_handle_dragged (CtkTextHandle *handle, |
607 | CtkTextHandlePosition pos, |
608 | gint x, |
609 | gint y, |
610 | CtkTextView *text_view); |
611 | static void ctk_text_view_handle_drag_finished (CtkTextHandle *handle, |
612 | CtkTextHandlePosition pos, |
613 | CtkTextView *text_view); |
614 | static void ctk_text_view_update_handles (CtkTextView *text_view, |
615 | CtkTextHandleMode mode); |
616 | |
617 | static void ctk_text_view_selection_bubble_popup_unset (CtkTextView *text_view); |
618 | static void ctk_text_view_selection_bubble_popup_set (CtkTextView *text_view); |
619 | |
620 | static void ctk_text_view_queue_draw_region (CtkWidget *widget, |
621 | const cairo_region_t *region); |
622 | |
623 | static void ctk_text_view_get_rendered_rect (CtkTextView *text_view, |
624 | CdkRectangle *rect); |
625 | |
626 | static gboolean ctk_text_view_extend_selection (CtkTextView *text_view, |
627 | CtkTextExtendSelection granularity, |
628 | const CtkTextIter *location, |
629 | CtkTextIter *start, |
630 | CtkTextIter *end); |
631 | static void extend_selection (CtkTextView *text_view, |
632 | SelectionGranularity granularity, |
633 | const CtkTextIter *location, |
634 | CtkTextIter *start, |
635 | CtkTextIter *end); |
636 | |
637 | |
638 | |
639 | /* FIXME probably need the focus methods. */ |
640 | |
641 | typedef struct _CtkTextViewChild CtkTextViewChild; |
642 | |
643 | struct _CtkTextViewChild |
644 | { |
645 | CtkWidget *widget; |
646 | |
647 | CtkTextChildAnchor *anchor; |
648 | |
649 | gint from_top_of_line; |
650 | gint from_left_of_buffer; |
651 | |
652 | /* These are ignored if anchor != NULL */ |
653 | CtkTextWindowType type; |
654 | gint x; |
655 | gint y; |
656 | }; |
657 | |
658 | static CtkTextViewChild* text_view_child_new_anchored (CtkWidget *child, |
659 | CtkTextChildAnchor *anchor, |
660 | CtkTextLayout *layout); |
661 | static CtkTextViewChild* text_view_child_new_window (CtkWidget *child, |
662 | CtkTextWindowType type, |
663 | gint x, |
664 | gint y); |
665 | static void text_view_child_free (CtkTextViewChild *child); |
666 | static void text_view_child_set_parent_window (CtkTextView *text_view, |
667 | CtkTextViewChild *child); |
668 | |
669 | struct _CtkTextWindow |
670 | { |
671 | CtkTextWindowType type; |
672 | CtkWidget *widget; |
673 | CdkWindow *window; |
674 | CdkWindow *bin_window; |
675 | CtkCssNode *css_node; |
676 | CtkRequisition requisition; |
677 | CdkRectangle allocation; |
678 | }; |
679 | |
680 | static CtkTextWindow *text_window_new (CtkTextWindowType type, |
681 | CtkWidget *widget, |
682 | gint width_request, |
683 | gint height_request); |
684 | static void text_window_free (CtkTextWindow *win); |
685 | static void text_window_realize (CtkTextWindow *win, |
686 | CtkWidget *widget); |
687 | static void text_window_unrealize (CtkTextWindow *win); |
688 | static void text_window_size_allocate (CtkTextWindow *win, |
689 | CdkRectangle *rect); |
690 | static void text_window_scroll (CtkTextWindow *win, |
691 | gint dx, |
692 | gint dy); |
693 | static void text_window_invalidate_rect (CtkTextWindow *win, |
694 | CdkRectangle *rect); |
695 | static void text_window_invalidate_cursors (CtkTextWindow *win); |
696 | |
697 | static gint text_window_get_width (CtkTextWindow *win); |
698 | static gint text_window_get_height (CtkTextWindow *win); |
699 | |
700 | |
701 | static guint signals[LAST_SIGNAL] = { 0 }; |
702 | |
703 | G_DEFINE_TYPE_WITH_CODE (CtkTextView, ctk_text_view, CTK_TYPE_CONTAINER,static void ctk_text_view_init (CtkTextView *self); static void ctk_text_view_class_init (CtkTextViewClass *klass); static GType ctk_text_view_get_type_once (void); static gpointer ctk_text_view_parent_class = ((void*)0); static gint CtkTextView_private_offset; static void ctk_text_view_class_intern_init (gpointer klass) { ctk_text_view_parent_class = g_type_class_peek_parent (klass); if (CtkTextView_private_offset != 0) g_type_class_adjust_private_offset (klass, &CtkTextView_private_offset ); ctk_text_view_class_init ((CtkTextViewClass*) klass); } __attribute__ ((__unused__)) static inline gpointer ctk_text_view_get_instance_private (CtkTextView *self) { return (((gpointer) ((guint8*) (self) + (glong) (CtkTextView_private_offset)))); } GType ctk_text_view_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_text_view_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_text_view_get_type_once (void ) { GType g_define_type_id = g_type_register_static_simple (( ctk_container_get_type ()), g_intern_static_string ("CtkTextView" ), sizeof (CtkTextViewClass), (GClassInitFunc)(void (*)(void) ) ctk_text_view_class_intern_init, sizeof (CtkTextView), (GInstanceInitFunc )(void (*)(void)) ctk_text_view_init, (GTypeFlags) 0); { {{ CtkTextView_private_offset = g_type_add_instance_private (g_define_type_id, sizeof (CtkTextViewPrivate )); } { const GInterfaceInfo g_implement_interface_info = { ( GInterfaceInitFunc)(void (*)(void)) ((void*)0), ((void*)0), ( (void*)0) }; g_type_add_interface_static (g_define_type_id, ( ctk_scrollable_get_type ()), &g_implement_interface_info) ; };} } return g_define_type_id; } |
704 | G_ADD_PRIVATE (CtkTextView)static void ctk_text_view_init (CtkTextView *self); static void ctk_text_view_class_init (CtkTextViewClass *klass); static GType ctk_text_view_get_type_once (void); static gpointer ctk_text_view_parent_class = ((void*)0); static gint CtkTextView_private_offset; static void ctk_text_view_class_intern_init (gpointer klass) { ctk_text_view_parent_class = g_type_class_peek_parent (klass); if (CtkTextView_private_offset != 0) g_type_class_adjust_private_offset (klass, &CtkTextView_private_offset ); ctk_text_view_class_init ((CtkTextViewClass*) klass); } __attribute__ ((__unused__)) static inline gpointer ctk_text_view_get_instance_private (CtkTextView *self) { return (((gpointer) ((guint8*) (self) + (glong) (CtkTextView_private_offset)))); } GType ctk_text_view_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_text_view_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_text_view_get_type_once (void ) { GType g_define_type_id = g_type_register_static_simple (( ctk_container_get_type ()), g_intern_static_string ("CtkTextView" ), sizeof (CtkTextViewClass), (GClassInitFunc)(void (*)(void) ) ctk_text_view_class_intern_init, sizeof (CtkTextView), (GInstanceInitFunc )(void (*)(void)) ctk_text_view_init, (GTypeFlags) 0); { {{ CtkTextView_private_offset = g_type_add_instance_private (g_define_type_id, sizeof (CtkTextViewPrivate )); } { const GInterfaceInfo g_implement_interface_info = { ( GInterfaceInitFunc)(void (*)(void)) ((void*)0), ((void*)0), ( (void*)0) }; g_type_add_interface_static (g_define_type_id, ( ctk_scrollable_get_type ()), &g_implement_interface_info) ; };} } return g_define_type_id; } |
705 | G_IMPLEMENT_INTERFACE (CTK_TYPE_SCROLLABLE, NULL))static void ctk_text_view_init (CtkTextView *self); static void ctk_text_view_class_init (CtkTextViewClass *klass); static GType ctk_text_view_get_type_once (void); static gpointer ctk_text_view_parent_class = ((void*)0); static gint CtkTextView_private_offset; static void ctk_text_view_class_intern_init (gpointer klass) { ctk_text_view_parent_class = g_type_class_peek_parent (klass); if (CtkTextView_private_offset != 0) g_type_class_adjust_private_offset (klass, &CtkTextView_private_offset ); ctk_text_view_class_init ((CtkTextViewClass*) klass); } __attribute__ ((__unused__)) static inline gpointer ctk_text_view_get_instance_private (CtkTextView *self) { return (((gpointer) ((guint8*) (self) + (glong) (CtkTextView_private_offset)))); } GType ctk_text_view_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_text_view_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_text_view_get_type_once (void ) { GType g_define_type_id = g_type_register_static_simple (( ctk_container_get_type ()), g_intern_static_string ("CtkTextView" ), sizeof (CtkTextViewClass), (GClassInitFunc)(void (*)(void) ) ctk_text_view_class_intern_init, sizeof (CtkTextView), (GInstanceInitFunc )(void (*)(void)) ctk_text_view_init, (GTypeFlags) 0); { {{ CtkTextView_private_offset = g_type_add_instance_private (g_define_type_id, sizeof (CtkTextViewPrivate )); } { const GInterfaceInfo g_implement_interface_info = { ( GInterfaceInitFunc)(void (*)(void)) ((void*)0), ((void*)0), ( (void*)0) }; g_type_add_interface_static (g_define_type_id, ( ctk_scrollable_get_type ()), &g_implement_interface_info) ; };} } return g_define_type_id; } |
706 | |
707 | static void |
708 | add_move_binding (CtkBindingSet *binding_set, |
709 | guint keyval, |
710 | guint modmask, |
711 | CtkMovementStep step, |
712 | gint count) |
713 | { |
714 | g_assert ((modmask & CDK_SHIFT_MASK) == 0)do { if ((modmask & CDK_SHIFT_MASK) == 0) ; else g_assertion_message_expr ("Ctk", "ctktextview.c", 714, ((const char*) (__func__)), "(modmask & CDK_SHIFT_MASK) == 0" ); } while (0); |
715 | |
716 | ctk_binding_entry_add_signal (binding_set, keyval, modmask, |
717 | "move-cursor", 3, |
718 | G_TYPE_ENUM((GType) ((12) << (2))), step, |
719 | G_TYPE_INT((GType) ((6) << (2))), count, |
720 | G_TYPE_BOOLEAN((GType) ((5) << (2))), FALSE(0)); |
721 | |
722 | /* Selection-extending version */ |
723 | ctk_binding_entry_add_signal (binding_set, keyval, modmask | CDK_SHIFT_MASK, |
724 | "move-cursor", 3, |
725 | G_TYPE_ENUM((GType) ((12) << (2))), step, |
726 | G_TYPE_INT((GType) ((6) << (2))), count, |
727 | G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0))); |
728 | } |
729 | |
730 | static void |
731 | ctk_text_view_class_init (CtkTextViewClass *klass) |
732 | { |
733 | GObjectClass *gobject_class = G_OBJECT_CLASS (klass)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((klass)), (((GType) ((20) << (2)))))))); |
734 | CtkWidgetClass *widget_class = CTK_WIDGET_CLASS (klass)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((klass)), ((ctk_widget_get_type ())))))); |
735 | CtkContainerClass *container_class = CTK_CONTAINER_CLASS (klass)((((CtkContainerClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((klass)), ((ctk_container_get_type ())))))); |
736 | CtkBindingSet *binding_set; |
737 | |
738 | /* Default handlers and virtual methods |
739 | */ |
740 | gobject_class->set_property = ctk_text_view_set_property; |
741 | gobject_class->get_property = ctk_text_view_get_property; |
742 | gobject_class->finalize = ctk_text_view_finalize; |
743 | |
744 | widget_class->destroy = ctk_text_view_destroy; |
745 | widget_class->map = ctk_text_view_map; |
746 | widget_class->unmap = ctk_text_view_unmap; |
747 | widget_class->realize = ctk_text_view_realize; |
748 | widget_class->unrealize = ctk_text_view_unrealize; |
749 | widget_class->style_updated = ctk_text_view_style_updated; |
750 | widget_class->direction_changed = ctk_text_view_direction_changed; |
751 | widget_class->state_flags_changed = ctk_text_view_state_flags_changed; |
752 | widget_class->get_preferred_width = ctk_text_view_get_preferred_width; |
753 | widget_class->get_preferred_height = ctk_text_view_get_preferred_height; |
754 | widget_class->size_allocate = ctk_text_view_size_allocate; |
755 | widget_class->event = ctk_text_view_event; |
756 | widget_class->key_press_event = ctk_text_view_key_press_event; |
757 | widget_class->key_release_event = ctk_text_view_key_release_event; |
758 | widget_class->focus_in_event = ctk_text_view_focus_in_event; |
759 | widget_class->focus_out_event = ctk_text_view_focus_out_event; |
760 | widget_class->motion_notify_event = ctk_text_view_motion_event; |
761 | widget_class->draw = ctk_text_view_draw; |
762 | widget_class->focus = ctk_text_view_focus; |
763 | widget_class->drag_begin = ctk_text_view_drag_begin; |
764 | widget_class->drag_end = ctk_text_view_drag_end; |
765 | widget_class->drag_data_get = ctk_text_view_drag_data_get; |
766 | widget_class->drag_data_delete = ctk_text_view_drag_data_delete; |
767 | |
768 | widget_class->drag_leave = ctk_text_view_drag_leave; |
769 | widget_class->drag_motion = ctk_text_view_drag_motion; |
770 | widget_class->drag_drop = ctk_text_view_drag_drop; |
771 | widget_class->drag_data_received = ctk_text_view_drag_data_received; |
772 | |
773 | widget_class->popup_menu = ctk_text_view_popup_menu; |
774 | |
775 | widget_class->queue_draw_region = ctk_text_view_queue_draw_region; |
776 | |
777 | container_class->add = ctk_text_view_add; |
778 | container_class->remove = ctk_text_view_remove; |
779 | container_class->forall = ctk_text_view_forall; |
780 | |
781 | klass->move_cursor = ctk_text_view_move_cursor; |
782 | klass->set_anchor = ctk_text_view_set_anchor; |
783 | klass->insert_at_cursor = ctk_text_view_insert_at_cursor; |
784 | klass->delete_from_cursor = ctk_text_view_delete_from_cursor; |
785 | klass->backspace = ctk_text_view_backspace; |
786 | klass->cut_clipboard = ctk_text_view_cut_clipboard; |
787 | klass->copy_clipboard = ctk_text_view_copy_clipboard; |
788 | klass->paste_clipboard = ctk_text_view_paste_clipboard; |
789 | klass->toggle_overwrite = ctk_text_view_toggle_overwrite; |
790 | klass->create_buffer = ctk_text_view_create_buffer; |
791 | klass->extend_selection = ctk_text_view_extend_selection; |
792 | klass->insert_emoji = ctk_text_view_insert_emoji; |
793 | |
794 | /* |
795 | * Properties |
796 | */ |
797 | |
798 | g_object_class_install_property (gobject_class, |
799 | PROP_PIXELS_ABOVE_LINES, |
800 | g_param_spec_int ("pixels-above-lines", |
801 | P_("Pixels Above Lines")g_dgettext("ctk30" "-properties","Pixels Above Lines"), |
802 | P_("Pixels of blank space above paragraphs")g_dgettext("ctk30" "-properties","Pixels of blank space above paragraphs" ), |
803 | 0, G_MAXINT2147483647, 0, |
804 | CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY)); |
805 | |
806 | g_object_class_install_property (gobject_class, |
807 | PROP_PIXELS_BELOW_LINES, |
808 | g_param_spec_int ("pixels-below-lines", |
809 | P_("Pixels Below Lines")g_dgettext("ctk30" "-properties","Pixels Below Lines"), |
810 | P_("Pixels of blank space below paragraphs")g_dgettext("ctk30" "-properties","Pixels of blank space below paragraphs" ), |
811 | 0, G_MAXINT2147483647, 0, |
812 | CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY)); |
813 | |
814 | g_object_class_install_property (gobject_class, |
815 | PROP_PIXELS_INSIDE_WRAP, |
816 | g_param_spec_int ("pixels-inside-wrap", |
817 | P_("Pixels Inside Wrap")g_dgettext("ctk30" "-properties","Pixels Inside Wrap"), |
818 | P_("Pixels of blank space between wrapped lines in a paragraph")g_dgettext("ctk30" "-properties","Pixels of blank space between wrapped lines in a paragraph" ), |
819 | 0, G_MAXINT2147483647, 0, |
820 | CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY)); |
821 | |
822 | g_object_class_install_property (gobject_class, |
823 | PROP_EDITABLE, |
824 | g_param_spec_boolean ("editable", |
825 | P_("Editable")g_dgettext("ctk30" "-properties","Editable"), |
826 | P_("Whether the text can be modified by the user")g_dgettext("ctk30" "-properties","Whether the text can be modified by the user" ), |
827 | TRUE(!(0)), |
828 | CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY)); |
829 | |
830 | g_object_class_install_property (gobject_class, |
831 | PROP_WRAP_MODE, |
832 | g_param_spec_enum ("wrap-mode", |
833 | P_("Wrap Mode")g_dgettext("ctk30" "-properties","Wrap Mode"), |
834 | P_("Whether to wrap lines never, at word boundaries, or at character boundaries")g_dgettext("ctk30" "-properties","Whether to wrap lines never, at word boundaries, or at character boundaries" ), |
835 | CTK_TYPE_WRAP_MODE(ctk_wrap_mode_get_type ()), |
836 | CTK_WRAP_NONE, |
837 | CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY)); |
838 | |
839 | g_object_class_install_property (gobject_class, |
840 | PROP_JUSTIFICATION, |
841 | g_param_spec_enum ("justification", |
842 | P_("Justification")g_dgettext("ctk30" "-properties","Justification"), |
843 | P_("Left, right, or center justification")g_dgettext("ctk30" "-properties","Left, right, or center justification" ), |
844 | CTK_TYPE_JUSTIFICATION(ctk_justification_get_type ()), |
845 | CTK_JUSTIFY_LEFT, |
846 | CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY)); |
847 | |
848 | /** |
849 | * CtkTextView:left-margin: |
850 | * |
851 | * The default left margin for text in the text view. |
852 | * Tags in the buffer may override the default. |
853 | * |
854 | * Note that this property is confusingly named. In CSS terms, |
855 | * the value set here is padding, and it is applied in addition |
856 | * to the padding from the theme. |
857 | * |
858 | * Don't confuse this property with #CtkWidget:margin-left. |
859 | */ |
860 | g_object_class_install_property (gobject_class, |
861 | PROP_LEFT_MARGIN, |
862 | g_param_spec_int ("left-margin", |
863 | P_("Left Margin")g_dgettext("ctk30" "-properties","Left Margin"), |
864 | P_("Width of the left margin in pixels")g_dgettext("ctk30" "-properties","Width of the left margin in pixels" ), |
865 | 0, G_MAXINT2147483647, 0, |
866 | CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY)); |
867 | |
868 | /** |
869 | * CtkTextView:right-margin: |
870 | * |
871 | * The default right margin for text in the text view. |
872 | * Tags in the buffer may override the default. |
873 | * |
874 | * Note that this property is confusingly named. In CSS terms, |
875 | * the value set here is padding, and it is applied in addition |
876 | * to the padding from the theme. |
877 | * |
878 | * Don't confuse this property with #CtkWidget:margin-right. |
879 | */ |
880 | g_object_class_install_property (gobject_class, |
881 | PROP_RIGHT_MARGIN, |
882 | g_param_spec_int ("right-margin", |
883 | P_("Right Margin")g_dgettext("ctk30" "-properties","Right Margin"), |
884 | P_("Width of the right margin in pixels")g_dgettext("ctk30" "-properties","Width of the right margin in pixels" ), |
885 | 0, G_MAXINT2147483647, 0, |
886 | CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY)); |
887 | |
888 | /** |
889 | * CtkTextView:top-margin: |
890 | * |
891 | * The top margin for text in the text view. |
892 | * |
893 | * Note that this property is confusingly named. In CSS terms, |
894 | * the value set here is padding, and it is applied in addition |
895 | * to the padding from the theme. |
896 | * |
897 | * Don't confuse this property with #CtkWidget:margin-top. |
898 | * |
899 | * Since: 3.18 |
900 | */ |
901 | g_object_class_install_property (gobject_class, |
902 | PROP_TOP_MARGIN, |
903 | g_param_spec_int ("top-margin", |
904 | P_("Top Margin")g_dgettext("ctk30" "-properties","Top Margin"), |
905 | P_("Height of the top margin in pixels")g_dgettext("ctk30" "-properties","Height of the top margin in pixels" ), |
906 | 0, G_MAXINT2147483647, 0, |
907 | CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY)); |
908 | |
909 | /** |
910 | * CtkTextView:bottom-margin: |
911 | * |
912 | * The bottom margin for text in the text view. |
913 | * |
914 | * Note that this property is confusingly named. In CSS terms, |
915 | * the value set here is padding, and it is applied in addition |
916 | * to the padding from the theme. |
917 | * |
918 | * Don't confuse this property with #CtkWidget:margin-bottom. |
919 | * |
920 | * Since: 3.18 |
921 | */ |
922 | g_object_class_install_property (gobject_class, |
923 | PROP_BOTTOM_MARGIN, |
924 | g_param_spec_int ("bottom-margin", |
925 | P_("Bottom Margin")g_dgettext("ctk30" "-properties","Bottom Margin"), |
926 | P_("Height of the bottom margin in pixels")g_dgettext("ctk30" "-properties","Height of the bottom margin in pixels" ), |
927 | 0, G_MAXINT2147483647, 0, |
928 | CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY)); |
929 | |
930 | g_object_class_install_property (gobject_class, |
931 | PROP_INDENT, |
932 | g_param_spec_int ("indent", |
933 | P_("Indent")g_dgettext("ctk30" "-properties","Indent"), |
934 | P_("Amount to indent the paragraph, in pixels")g_dgettext("ctk30" "-properties","Amount to indent the paragraph, in pixels" ), |
935 | G_MININT(-2147483647 -1), G_MAXINT2147483647, 0, |
936 | CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY)); |
937 | |
938 | g_object_class_install_property (gobject_class, |
939 | PROP_TABS, |
940 | g_param_spec_boxed ("tabs", |
941 | P_("Tabs")g_dgettext("ctk30" "-properties","Tabs"), |
942 | P_("Custom tabs for this text")g_dgettext("ctk30" "-properties","Custom tabs for this text"), |
943 | PANGO_TYPE_TAB_ARRAY(pango_tab_array_get_type ()), |
944 | CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB)); |
945 | |
946 | g_object_class_install_property (gobject_class, |
947 | PROP_CURSOR_VISIBLE, |
948 | g_param_spec_boolean ("cursor-visible", |
949 | P_("Cursor Visible")g_dgettext("ctk30" "-properties","Cursor Visible"), |
950 | P_("If the insertion cursor is shown")g_dgettext("ctk30" "-properties","If the insertion cursor is shown" ), |
951 | TRUE(!(0)), |
952 | CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY)); |
953 | |
954 | g_object_class_install_property (gobject_class, |
955 | PROP_BUFFER, |
956 | g_param_spec_object ("buffer", |
957 | P_("Buffer")g_dgettext("ctk30" "-properties","Buffer"), |
958 | P_("The buffer which is displayed")g_dgettext("ctk30" "-properties","The buffer which is displayed" ), |
959 | CTK_TYPE_TEXT_BUFFER(ctk_text_buffer_get_type ()), |
960 | CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB)); |
961 | |
962 | g_object_class_install_property (gobject_class, |
963 | PROP_OVERWRITE, |
964 | g_param_spec_boolean ("overwrite", |
965 | P_("Overwrite mode")g_dgettext("ctk30" "-properties","Overwrite mode"), |
966 | P_("Whether entered text overwrites existing contents")g_dgettext("ctk30" "-properties","Whether entered text overwrites existing contents" ), |
967 | FALSE(0), |
968 | CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY)); |
969 | |
970 | g_object_class_install_property (gobject_class, |
971 | PROP_ACCEPTS_TAB, |
972 | g_param_spec_boolean ("accepts-tab", |
973 | P_("Accepts tab")g_dgettext("ctk30" "-properties","Accepts tab"), |
974 | P_("Whether Tab will result in a tab character being entered")g_dgettext("ctk30" "-properties","Whether Tab will result in a tab character being entered" ), |
975 | TRUE(!(0)), |
976 | CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY)); |
977 | |
978 | /** |
979 | * CtkTextView:im-module: |
980 | * |
981 | * Which IM (input method) module should be used for this text_view. |
982 | * See #CtkIMContext. |
983 | * |
984 | * Setting this to a non-%NULL value overrides the |
985 | * system-wide IM module setting. See the CtkSettings |
986 | * #CtkSettings:ctk-im-module property. |
987 | * |
988 | * Since: 2.16 |
989 | */ |
990 | g_object_class_install_property (gobject_class, |
991 | PROP_IM_MODULE, |
992 | g_param_spec_string ("im-module", |
993 | P_("IM module")g_dgettext("ctk30" "-properties","IM module"), |
994 | P_("Which IM module should be used")g_dgettext("ctk30" "-properties","Which IM module should be used" ), |
995 | NULL((void*)0), |
996 | CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB)); |
997 | |
998 | /** |
999 | * CtkTextView:input-purpose: |
1000 | * |
1001 | * The purpose of this text field. |
1002 | * |
1003 | * This property can be used by on-screen keyboards and other input |
1004 | * methods to adjust their behaviour. |
1005 | * |
1006 | * Since: 3.6 |
1007 | */ |
1008 | g_object_class_install_property (gobject_class, |
1009 | PROP_INPUT_PURPOSE, |
1010 | g_param_spec_enum ("input-purpose", |
1011 | P_("Purpose")g_dgettext("ctk30" "-properties","Purpose"), |
1012 | P_("Purpose of the text field")g_dgettext("ctk30" "-properties","Purpose of the text field"), |
1013 | CTK_TYPE_INPUT_PURPOSE(ctk_input_purpose_get_type ()), |
1014 | CTK_INPUT_PURPOSE_FREE_FORM, |
1015 | CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY)); |
1016 | |
1017 | |
1018 | /** |
1019 | * CtkTextView:input-hints: |
1020 | * |
1021 | * Additional hints (beyond #CtkTextView:input-purpose) that |
1022 | * allow input methods to fine-tune their behaviour. |
1023 | * |
1024 | * Since: 3.6 |
1025 | */ |
1026 | g_object_class_install_property (gobject_class, |
1027 | PROP_INPUT_HINTS, |
1028 | g_param_spec_flags ("input-hints", |
1029 | P_("hints")g_dgettext("ctk30" "-properties","hints"), |
1030 | P_("Hints for the text field behaviour")g_dgettext("ctk30" "-properties","Hints for the text field behaviour" ), |
1031 | CTK_TYPE_INPUT_HINTS(ctk_input_hints_get_type ()), |
1032 | CTK_INPUT_HINT_NONE, |
1033 | CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY)); |
1034 | |
1035 | /** |
1036 | * CtkTextView:populate-all: |
1037 | * |
1038 | * If :populate-all is %TRUE, the #CtkTextView::populate-popup |
1039 | * signal is also emitted for touch popups. |
1040 | * |
1041 | * Since: 3.8 |
1042 | */ |
1043 | g_object_class_install_property (gobject_class, |
1044 | PROP_POPULATE_ALL, |
1045 | g_param_spec_boolean ("populate-all", |
1046 | P_("Populate all")g_dgettext("ctk30" "-properties","Populate all"), |
1047 | P_("Whether to emit ::populate-popup for touch popups")g_dgettext("ctk30" "-properties","Whether to emit ::populate-popup for touch popups" ), |
1048 | FALSE(0), |
1049 | CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY)); |
1050 | |
1051 | /** |
1052 | * CtkTextview:monospace: |
1053 | * |
1054 | * If %TRUE, set the %CTK_STYLE_CLASS_MONOSPACE style class on the |
1055 | * text view to indicate that a monospace font is desired. |
1056 | * |
1057 | * Since: 3.16 |
1058 | */ |
1059 | g_object_class_install_property (gobject_class, |
1060 | PROP_MONOSPACE, |
1061 | g_param_spec_boolean ("monospace", |
1062 | P_("Monospace")g_dgettext("ctk30" "-properties","Monospace"), |
1063 | P_("Whether to use a monospace font")g_dgettext("ctk30" "-properties","Whether to use a monospace font" ), |
1064 | FALSE(0), |
1065 | CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY)); |
1066 | |
1067 | |
1068 | |
1069 | /* CtkScrollable interface */ |
1070 | g_object_class_override_property (gobject_class, PROP_HADJUSTMENT, "hadjustment"); |
1071 | g_object_class_override_property (gobject_class, PROP_VADJUSTMENT, "vadjustment"); |
1072 | g_object_class_override_property (gobject_class, PROP_HSCROLL_POLICY, "hscroll-policy"); |
1073 | g_object_class_override_property (gobject_class, PROP_VSCROLL_POLICY, "vscroll-policy"); |
1074 | |
1075 | /* |
1076 | * Style properties |
1077 | */ |
1078 | ctk_widget_class_install_style_property (widget_class, |
1079 | g_param_spec_boxed ("error-underline-color", |
1080 | P_("Error underline color")g_dgettext("ctk30" "-properties","Error underline color"), |
1081 | P_("Color with which to draw error-indication underlines")g_dgettext("ctk30" "-properties","Color with which to draw error-indication underlines" ), |
1082 | CDK_TYPE_COLOR(cdk_color_get_type ()), |
1083 | CTK_PARAM_READABLEG_PARAM_READABLE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB)); |
1084 | |
1085 | /* |
1086 | * Signals |
1087 | */ |
1088 | |
1089 | /** |
1090 | * CtkTextView::move-cursor: |
1091 | * @text_view: the object which received the signal |
1092 | * @step: the granularity of the move, as a #CtkMovementStep |
1093 | * @count: the number of @step units to move |
1094 | * @extend_selection: %TRUE if the move should extend the selection |
1095 | * |
1096 | * The ::move-cursor signal is a |
1097 | * [keybinding signal][CtkBindingSignal] |
1098 | * which gets emitted when the user initiates a cursor movement. |
1099 | * If the cursor is not visible in @text_view, this signal causes |
1100 | * the viewport to be moved instead. |
1101 | * |
1102 | * Applications should not connect to it, but may emit it with |
1103 | * g_signal_emit_by_name() if they need to control the cursor |
1104 | * programmatically. |
1105 | * |
1106 | * The default bindings for this signal come in two variants, |
1107 | * the variant with the Shift modifier extends the selection, |
1108 | * the variant without the Shift modifer does not. |
1109 | * There are too many key combinations to list them all here. |
1110 | * - Arrow keys move by individual characters/lines |
1111 | * - Ctrl-arrow key combinations move by words/paragraphs |
1112 | * - Home/End keys move to the ends of the buffer |
1113 | * - PageUp/PageDown keys move vertically by pages |
1114 | * - Ctrl-PageUp/PageDown keys move horizontally by pages |
1115 | */ |
1116 | signals[MOVE_CURSOR] = |
1117 | g_signal_new (I_("move-cursor")g_intern_static_string ("move-cursor"), |
1118 | G_OBJECT_CLASS_TYPE (gobject_class)((((GTypeClass*) (gobject_class))->g_type)), |
1119 | G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, |
1120 | G_STRUCT_OFFSET (CtkTextViewClass, move_cursor)((glong) __builtin_offsetof(CtkTextViewClass, move_cursor)), |
1121 | NULL((void*)0), NULL((void*)0), |
1122 | _ctk_marshal_VOID__ENUM_INT_BOOLEAN, |
1123 | G_TYPE_NONE((GType) ((1) << (2))), 3, |
1124 | CTK_TYPE_MOVEMENT_STEP(ctk_movement_step_get_type ()), |
1125 | G_TYPE_INT((GType) ((6) << (2))), |
1126 | G_TYPE_BOOLEAN((GType) ((5) << (2)))); |
1127 | g_signal_set_va_marshaller (signals[MOVE_CURSOR], |
1128 | G_OBJECT_CLASS_TYPE (gobject_class)((((GTypeClass*) (gobject_class))->g_type)), |
1129 | _ctk_marshal_VOID__ENUM_INT_BOOLEANv); |
1130 | |
1131 | /** |
1132 | * CtkTextView::move-viewport: |
1133 | * @text_view: the object which received the signal |
1134 | * @step: the granularity of the movement, as a #CtkScrollStep |
1135 | * @count: the number of @step units to move |
1136 | * |
1137 | * The ::move-viewport signal is a |
1138 | * [keybinding signal][CtkBindingSignal] |
1139 | * which can be bound to key combinations to allow the user |
1140 | * to move the viewport, i.e. change what part of the text view |
1141 | * is visible in a containing scrolled window. |
1142 | * |
1143 | * There are no default bindings for this signal. |
1144 | */ |
1145 | signals[MOVE_VIEWPORT] = |
1146 | g_signal_new_class_handler (I_("move-viewport")g_intern_static_string ("move-viewport"), |
1147 | G_OBJECT_CLASS_TYPE (gobject_class)((((GTypeClass*) (gobject_class))->g_type)), |
1148 | G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, |
1149 | G_CALLBACK (ctk_text_view_move_viewport)((GCallback) (ctk_text_view_move_viewport)), |
1150 | NULL((void*)0), NULL((void*)0), |
1151 | _ctk_marshal_VOID__ENUM_INT, |
1152 | G_TYPE_NONE((GType) ((1) << (2))), 2, |
1153 | CTK_TYPE_SCROLL_STEP(ctk_scroll_step_get_type ()), |
1154 | G_TYPE_INT((GType) ((6) << (2)))); |
1155 | g_signal_set_va_marshaller (signals[MOVE_VIEWPORT], |
1156 | G_OBJECT_CLASS_TYPE (gobject_class)((((GTypeClass*) (gobject_class))->g_type)), |
1157 | _ctk_marshal_VOID__ENUM_INTv); |
1158 | |
1159 | /** |
1160 | * CtkTextView::set-anchor: |
1161 | * @text_view: the object which received the signal |
1162 | * |
1163 | * The ::set-anchor signal is a |
1164 | * [keybinding signal][CtkBindingSignal] |
1165 | * which gets emitted when the user initiates setting the "anchor" |
1166 | * mark. The "anchor" mark gets placed at the same position as the |
1167 | * "insert" mark. |
1168 | * |
1169 | * This signal has no default bindings. |
1170 | */ |
1171 | signals[SET_ANCHOR] = |
1172 | g_signal_new (I_("set-anchor")g_intern_static_string ("set-anchor"), |
1173 | G_OBJECT_CLASS_TYPE (gobject_class)((((GTypeClass*) (gobject_class))->g_type)), |
1174 | G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, |
1175 | G_STRUCT_OFFSET (CtkTextViewClass, set_anchor)((glong) __builtin_offsetof(CtkTextViewClass, set_anchor)), |
1176 | NULL((void*)0), NULL((void*)0), |
1177 | NULL((void*)0), |
1178 | G_TYPE_NONE((GType) ((1) << (2))), 0); |
1179 | |
1180 | /** |
1181 | * CtkTextView::insert-at-cursor: |
1182 | * @text_view: the object which received the signal |
1183 | * @string: the string to insert |
1184 | * |
1185 | * The ::insert-at-cursor signal is a |
1186 | * [keybinding signal][CtkBindingSignal] |
1187 | * which gets emitted when the user initiates the insertion of a |
1188 | * fixed string at the cursor. |
1189 | * |
1190 | * This signal has no default bindings. |
1191 | */ |
1192 | signals[INSERT_AT_CURSOR] = |
1193 | g_signal_new (I_("insert-at-cursor")g_intern_static_string ("insert-at-cursor"), |
1194 | G_OBJECT_CLASS_TYPE (gobject_class)((((GTypeClass*) (gobject_class))->g_type)), |
1195 | G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, |
1196 | G_STRUCT_OFFSET (CtkTextViewClass, insert_at_cursor)((glong) __builtin_offsetof(CtkTextViewClass, insert_at_cursor )), |
1197 | NULL((void*)0), NULL((void*)0), |
1198 | NULL((void*)0), |
1199 | G_TYPE_NONE((GType) ((1) << (2))), 1, |
1200 | G_TYPE_STRING((GType) ((16) << (2)))); |
1201 | |
1202 | /** |
1203 | * CtkTextView::delete-from-cursor: |
1204 | * @text_view: the object which received the signal |
1205 | * @type: the granularity of the deletion, as a #CtkDeleteType |
1206 | * @count: the number of @type units to delete |
1207 | * |
1208 | * The ::delete-from-cursor signal is a |
1209 | * [keybinding signal][CtkBindingSignal] |
1210 | * which gets emitted when the user initiates a text deletion. |
1211 | * |
1212 | * If the @type is %CTK_DELETE_CHARS, CTK+ deletes the selection |
1213 | * if there is one, otherwise it deletes the requested number |
1214 | * of characters. |
1215 | * |
1216 | * The default bindings for this signal are |
1217 | * Delete for deleting a character, Ctrl-Delete for |
1218 | * deleting a word and Ctrl-Backspace for deleting a word |
1219 | * backwords. |
1220 | */ |
1221 | signals[DELETE_FROM_CURSOR] = |
1222 | g_signal_new (I_("delete-from-cursor")g_intern_static_string ("delete-from-cursor"), |
1223 | G_OBJECT_CLASS_TYPE (gobject_class)((((GTypeClass*) (gobject_class))->g_type)), |
1224 | G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, |
1225 | G_STRUCT_OFFSET (CtkTextViewClass, delete_from_cursor)((glong) __builtin_offsetof(CtkTextViewClass, delete_from_cursor )), |
1226 | NULL((void*)0), NULL((void*)0), |
1227 | _ctk_marshal_VOID__ENUM_INT, |
1228 | G_TYPE_NONE((GType) ((1) << (2))), 2, |
1229 | CTK_TYPE_DELETE_TYPE(ctk_delete_type_get_type ()), |
1230 | G_TYPE_INT((GType) ((6) << (2)))); |
1231 | g_signal_set_va_marshaller (signals[DELETE_FROM_CURSOR], |
1232 | G_OBJECT_CLASS_TYPE (gobject_class)((((GTypeClass*) (gobject_class))->g_type)), |
1233 | _ctk_marshal_VOID__ENUM_INTv); |
1234 | |
1235 | /** |
1236 | * CtkTextView::backspace: |
1237 | * @text_view: the object which received the signal |
1238 | * |
1239 | * The ::backspace signal is a |
1240 | * [keybinding signal][CtkBindingSignal] |
1241 | * which gets emitted when the user asks for it. |
1242 | * |
1243 | * The default bindings for this signal are |
1244 | * Backspace and Shift-Backspace. |
1245 | */ |
1246 | signals[BACKSPACE] = |
1247 | g_signal_new (I_("backspace")g_intern_static_string ("backspace"), |
1248 | G_OBJECT_CLASS_TYPE (gobject_class)((((GTypeClass*) (gobject_class))->g_type)), |
1249 | G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, |
1250 | G_STRUCT_OFFSET (CtkTextViewClass, backspace)((glong) __builtin_offsetof(CtkTextViewClass, backspace)), |
1251 | NULL((void*)0), NULL((void*)0), |
1252 | NULL((void*)0), |
1253 | G_TYPE_NONE((GType) ((1) << (2))), 0); |
1254 | |
1255 | /** |
1256 | * CtkTextView::cut-clipboard: |
1257 | * @text_view: the object which received the signal |
1258 | * |
1259 | * The ::cut-clipboard signal is a |
1260 | * [keybinding signal][CtkBindingSignal] |
1261 | * which gets emitted to cut the selection to the clipboard. |
1262 | * |
1263 | * The default bindings for this signal are |
1264 | * Ctrl-x and Shift-Delete. |
1265 | */ |
1266 | signals[CUT_CLIPBOARD] = |
1267 | g_signal_new (I_("cut-clipboard")g_intern_static_string ("cut-clipboard"), |
1268 | G_OBJECT_CLASS_TYPE (gobject_class)((((GTypeClass*) (gobject_class))->g_type)), |
1269 | G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, |
1270 | G_STRUCT_OFFSET (CtkTextViewClass, cut_clipboard)((glong) __builtin_offsetof(CtkTextViewClass, cut_clipboard)), |
1271 | NULL((void*)0), NULL((void*)0), |
1272 | NULL((void*)0), |
1273 | G_TYPE_NONE((GType) ((1) << (2))), 0); |
1274 | |
1275 | /** |
1276 | * CtkTextView::copy-clipboard: |
1277 | * @text_view: the object which received the signal |
1278 | * |
1279 | * The ::copy-clipboard signal is a |
1280 | * [keybinding signal][CtkBindingSignal] |
1281 | * which gets emitted to copy the selection to the clipboard. |
1282 | * |
1283 | * The default bindings for this signal are |
1284 | * Ctrl-c and Ctrl-Insert. |
1285 | */ |
1286 | signals[COPY_CLIPBOARD] = |
1287 | g_signal_new (I_("copy-clipboard")g_intern_static_string ("copy-clipboard"), |
1288 | G_OBJECT_CLASS_TYPE (gobject_class)((((GTypeClass*) (gobject_class))->g_type)), |
1289 | G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, |
1290 | G_STRUCT_OFFSET (CtkTextViewClass, copy_clipboard)((glong) __builtin_offsetof(CtkTextViewClass, copy_clipboard) ), |
1291 | NULL((void*)0), NULL((void*)0), |
1292 | NULL((void*)0), |
1293 | G_TYPE_NONE((GType) ((1) << (2))), 0); |
1294 | |
1295 | /** |
1296 | * CtkTextView::paste-clipboard: |
1297 | * @text_view: the object which received the signal |
1298 | * |
1299 | * The ::paste-clipboard signal is a |
1300 | * [keybinding signal][CtkBindingSignal] |
1301 | * which gets emitted to paste the contents of the clipboard |
1302 | * into the text view. |
1303 | * |
1304 | * The default bindings for this signal are |
1305 | * Ctrl-v and Shift-Insert. |
1306 | */ |
1307 | signals[PASTE_CLIPBOARD] = |
1308 | g_signal_new (I_("paste-clipboard")g_intern_static_string ("paste-clipboard"), |
1309 | G_OBJECT_CLASS_TYPE (gobject_class)((((GTypeClass*) (gobject_class))->g_type)), |
1310 | G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, |
1311 | G_STRUCT_OFFSET (CtkTextViewClass, paste_clipboard)((glong) __builtin_offsetof(CtkTextViewClass, paste_clipboard )), |
1312 | NULL((void*)0), NULL((void*)0), |
1313 | NULL((void*)0), |
1314 | G_TYPE_NONE((GType) ((1) << (2))), 0); |
1315 | |
1316 | /** |
1317 | * CtkTextView::toggle-overwrite: |
1318 | * @text_view: the object which received the signal |
1319 | * |
1320 | * The ::toggle-overwrite signal is a |
1321 | * [keybinding signal][CtkBindingSignal] |
1322 | * which gets emitted to toggle the overwrite mode of the text view. |
1323 | * |
1324 | * The default bindings for this signal is Insert. |
1325 | */ |
1326 | signals[TOGGLE_OVERWRITE] = |
1327 | g_signal_new (I_("toggle-overwrite")g_intern_static_string ("toggle-overwrite"), |
1328 | G_OBJECT_CLASS_TYPE (gobject_class)((((GTypeClass*) (gobject_class))->g_type)), |
1329 | G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, |
1330 | G_STRUCT_OFFSET (CtkTextViewClass, toggle_overwrite)((glong) __builtin_offsetof(CtkTextViewClass, toggle_overwrite )), |
1331 | NULL((void*)0), NULL((void*)0), |
1332 | NULL((void*)0), |
1333 | G_TYPE_NONE((GType) ((1) << (2))), 0); |
1334 | |
1335 | /** |
1336 | * CtkTextView::populate-popup: |
1337 | * @text_view: The text view on which the signal is emitted |
1338 | * @popup: the container that is being populated |
1339 | * |
1340 | * The ::populate-popup signal gets emitted before showing the |
1341 | * context menu of the text view. |
1342 | * |
1343 | * If you need to add items to the context menu, connect |
1344 | * to this signal and append your items to the @popup, which |
1345 | * will be a #CtkMenu in this case. |
1346 | * |
1347 | * If #CtkTextView:populate-all is %TRUE, this signal will |
1348 | * also be emitted to populate touch popups. In this case, |
1349 | * @popup will be a different container, e.g. a #CtkToolbar. |
1350 | * |
1351 | * The signal handler should not make assumptions about the |
1352 | * type of @widget, but check whether @popup is a #CtkMenu |
1353 | * or #CtkToolbar or another kind of container. |
1354 | */ |
1355 | signals[POPULATE_POPUP] = |
1356 | g_signal_new (I_("populate-popup")g_intern_static_string ("populate-popup"), |
1357 | G_OBJECT_CLASS_TYPE (gobject_class)((((GTypeClass*) (gobject_class))->g_type)), |
1358 | G_SIGNAL_RUN_LAST, |
1359 | G_STRUCT_OFFSET (CtkTextViewClass, populate_popup)((glong) __builtin_offsetof(CtkTextViewClass, populate_popup) ), |
1360 | NULL((void*)0), NULL((void*)0), |
1361 | NULL((void*)0), |
1362 | G_TYPE_NONE((GType) ((1) << (2))), 1, |
1363 | CTK_TYPE_WIDGET(ctk_widget_get_type ())); |
1364 | |
1365 | /** |
1366 | * CtkTextView::select-all: |
1367 | * @text_view: the object which received the signal |
1368 | * @select: %TRUE to select, %FALSE to unselect |
1369 | * |
1370 | * The ::select-all signal is a |
1371 | * [keybinding signal][CtkBindingSignal] |
1372 | * which gets emitted to select or unselect the complete |
1373 | * contents of the text view. |
1374 | * |
1375 | * The default bindings for this signal are Ctrl-a and Ctrl-/ |
1376 | * for selecting and Shift-Ctrl-a and Ctrl-\ for unselecting. |
1377 | */ |
1378 | signals[SELECT_ALL] = |
1379 | g_signal_new_class_handler (I_("select-all")g_intern_static_string ("select-all"), |
1380 | G_OBJECT_CLASS_TYPE (gobject_class)((((GTypeClass*) (gobject_class))->g_type)), |
1381 | G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, |
1382 | G_CALLBACK (ctk_text_view_select_all)((GCallback) (ctk_text_view_select_all)), |
1383 | NULL((void*)0), NULL((void*)0), |
1384 | NULL((void*)0), |
1385 | G_TYPE_NONE((GType) ((1) << (2))), 1, G_TYPE_BOOLEAN((GType) ((5) << (2)))); |
1386 | |
1387 | /** |
1388 | * CtkTextView::toggle-cursor-visible: |
1389 | * @text_view: the object which received the signal |
1390 | * |
1391 | * The ::toggle-cursor-visible signal is a |
1392 | * [keybinding signal][CtkBindingSignal] |
1393 | * which gets emitted to toggle the #CtkTextView:cursor-visible |
1394 | * property. |
1395 | * |
1396 | * The default binding for this signal is F7. |
1397 | */ |
1398 | signals[TOGGLE_CURSOR_VISIBLE] = |
1399 | g_signal_new_class_handler (I_("toggle-cursor-visible")g_intern_static_string ("toggle-cursor-visible"), |
1400 | G_OBJECT_CLASS_TYPE (gobject_class)((((GTypeClass*) (gobject_class))->g_type)), |
1401 | G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, |
1402 | G_CALLBACK (ctk_text_view_toggle_cursor_visible)((GCallback) (ctk_text_view_toggle_cursor_visible)), |
1403 | NULL((void*)0), NULL((void*)0), |
1404 | NULL((void*)0), |
1405 | G_TYPE_NONE((GType) ((1) << (2))), 0); |
1406 | |
1407 | /** |
1408 | * CtkTextView::preedit-changed: |
1409 | * @text_view: the object which received the signal |
1410 | * @preedit: the current preedit string |
1411 | * |
1412 | * If an input method is used, the typed text will not immediately |
1413 | * be committed to the buffer. So if you are interested in the text, |
1414 | * connect to this signal. |
1415 | * |
1416 | * This signal is only emitted if the text at the given position |
1417 | * is actually editable. |
1418 | * |
1419 | * Since: 2.20 |
1420 | */ |
1421 | signals[PREEDIT_CHANGED] = |
1422 | g_signal_new_class_handler (I_("preedit-changed")g_intern_static_string ("preedit-changed"), |
1423 | G_OBJECT_CLASS_TYPE (gobject_class)((((GTypeClass*) (gobject_class))->g_type)), |
1424 | G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, |
1425 | NULL((void*)0), |
1426 | NULL((void*)0), NULL((void*)0), |
1427 | NULL((void*)0), |
1428 | G_TYPE_NONE((GType) ((1) << (2))), 1, |
1429 | G_TYPE_STRING((GType) ((16) << (2)))); |
1430 | |
1431 | /** |
1432 | * CtkTextView::extend-selection: |
1433 | * @text_view: the object which received the signal |
1434 | * @granularity: the granularity type |
1435 | * @location: the location where to extend the selection |
1436 | * @start: where the selection should start |
1437 | * @end: where the selection should end |
1438 | * |
1439 | * The ::extend-selection signal is emitted when the selection needs to be |
1440 | * extended at @location. |
1441 | * |
1442 | * Returns: %CDK_EVENT_STOP to stop other handlers from being invoked for the |
1443 | * event. %CDK_EVENT_PROPAGATE to propagate the event further. |
1444 | * Since: 3.16 |
1445 | */ |
1446 | signals[EXTEND_SELECTION] = |
1447 | g_signal_new (I_("extend-selection")g_intern_static_string ("extend-selection"), |
1448 | G_OBJECT_CLASS_TYPE (gobject_class)((((GTypeClass*) (gobject_class))->g_type)), |
1449 | G_SIGNAL_RUN_LAST, |
1450 | G_STRUCT_OFFSET (CtkTextViewClass, extend_selection)((glong) __builtin_offsetof(CtkTextViewClass, extend_selection )), |
1451 | _ctk_boolean_handled_accumulator, NULL((void*)0), |
1452 | _ctk_marshal_BOOLEAN__ENUM_BOXED_BOXED_BOXED, |
1453 | G_TYPE_BOOLEAN((GType) ((5) << (2))), 4, |
1454 | CTK_TYPE_TEXT_EXTEND_SELECTION(ctk_text_extend_selection_get_type ()), |
1455 | CTK_TYPE_TEXT_ITER(ctk_text_iter_get_type ()) | G_SIGNAL_TYPE_STATIC_SCOPE(((GType) (1 << 0))), |
1456 | CTK_TYPE_TEXT_ITER(ctk_text_iter_get_type ()) | G_SIGNAL_TYPE_STATIC_SCOPE(((GType) (1 << 0))), |
1457 | CTK_TYPE_TEXT_ITER(ctk_text_iter_get_type ()) | G_SIGNAL_TYPE_STATIC_SCOPE(((GType) (1 << 0)))); |
1458 | g_signal_set_va_marshaller (signals[EXTEND_SELECTION], |
1459 | G_TYPE_FROM_CLASS (klass)(((GTypeClass*) (klass))->g_type), |
1460 | _ctk_marshal_BOOLEAN__ENUM_BOXED_BOXED_BOXEDv); |
1461 | |
1462 | /** |
1463 | * CtkTextView::insert-emoji: |
1464 | * @text_view: the object which received the signal |
1465 | * |
1466 | * The ::insert-emoji signal is a |
1467 | * [keybinding signal][CtkBindingSignal] |
1468 | * which gets emitted to present the Emoji chooser for the @text_view. |
1469 | * |
1470 | * The default bindings for this signal are Ctrl-. and Ctrl-; |
1471 | * |
1472 | * Since: 3.22.27 |
1473 | */ |
1474 | signals[INSERT_EMOJI] = |
1475 | g_signal_new (I_("insert-emoji")g_intern_static_string ("insert-emoji"), |
1476 | G_OBJECT_CLASS_TYPE (gobject_class)((((GTypeClass*) (gobject_class))->g_type)), |
1477 | G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, |
1478 | G_STRUCT_OFFSET (CtkTextViewClass, insert_emoji)((glong) __builtin_offsetof(CtkTextViewClass, insert_emoji)), |
1479 | NULL((void*)0), NULL((void*)0), |
1480 | NULL((void*)0), |
1481 | G_TYPE_NONE((GType) ((1) << (2))), 0); |
1482 | |
1483 | /* |
1484 | * Key bindings |
1485 | */ |
1486 | |
1487 | binding_set = ctk_binding_set_by_class (klass); |
1488 | |
1489 | /* Moving the insertion point */ |
1490 | add_move_binding (binding_set, CDK_KEY_Right0xff53, 0, |
1491 | CTK_MOVEMENT_VISUAL_POSITIONS, 1); |
1492 | |
1493 | add_move_binding (binding_set, CDK_KEY_KP_Right0xff98, 0, |
1494 | CTK_MOVEMENT_VISUAL_POSITIONS, 1); |
1495 | |
1496 | add_move_binding (binding_set, CDK_KEY_Left0xff51, 0, |
1497 | CTK_MOVEMENT_VISUAL_POSITIONS, -1); |
1498 | |
1499 | add_move_binding (binding_set, CDK_KEY_KP_Left0xff96, 0, |
1500 | CTK_MOVEMENT_VISUAL_POSITIONS, -1); |
1501 | |
1502 | add_move_binding (binding_set, CDK_KEY_Right0xff53, CDK_CONTROL_MASK, |
1503 | CTK_MOVEMENT_WORDS, 1); |
1504 | |
1505 | add_move_binding (binding_set, CDK_KEY_KP_Right0xff98, CDK_CONTROL_MASK, |
1506 | CTK_MOVEMENT_WORDS, 1); |
1507 | |
1508 | add_move_binding (binding_set, CDK_KEY_Left0xff51, CDK_CONTROL_MASK, |
1509 | CTK_MOVEMENT_WORDS, -1); |
1510 | |
1511 | add_move_binding (binding_set, CDK_KEY_KP_Left0xff96, CDK_CONTROL_MASK, |
1512 | CTK_MOVEMENT_WORDS, -1); |
1513 | |
1514 | add_move_binding (binding_set, CDK_KEY_Up0xff52, 0, |
1515 | CTK_MOVEMENT_DISPLAY_LINES, -1); |
1516 | |
1517 | add_move_binding (binding_set, CDK_KEY_KP_Up0xff97, 0, |
1518 | CTK_MOVEMENT_DISPLAY_LINES, -1); |
1519 | |
1520 | add_move_binding (binding_set, CDK_KEY_Down0xff54, 0, |
1521 | CTK_MOVEMENT_DISPLAY_LINES, 1); |
1522 | |
1523 | add_move_binding (binding_set, CDK_KEY_KP_Down0xff99, 0, |
1524 | CTK_MOVEMENT_DISPLAY_LINES, 1); |
1525 | |
1526 | add_move_binding (binding_set, CDK_KEY_Up0xff52, CDK_CONTROL_MASK, |
1527 | CTK_MOVEMENT_PARAGRAPHS, -1); |
1528 | |
1529 | add_move_binding (binding_set, CDK_KEY_KP_Up0xff97, CDK_CONTROL_MASK, |
1530 | CTK_MOVEMENT_PARAGRAPHS, -1); |
1531 | |
1532 | add_move_binding (binding_set, CDK_KEY_Down0xff54, CDK_CONTROL_MASK, |
1533 | CTK_MOVEMENT_PARAGRAPHS, 1); |
1534 | |
1535 | add_move_binding (binding_set, CDK_KEY_KP_Down0xff99, CDK_CONTROL_MASK, |
1536 | CTK_MOVEMENT_PARAGRAPHS, 1); |
1537 | |
1538 | add_move_binding (binding_set, CDK_KEY_Home0xff50, 0, |
1539 | CTK_MOVEMENT_DISPLAY_LINE_ENDS, -1); |
1540 | |
1541 | add_move_binding (binding_set, CDK_KEY_KP_Home0xff95, 0, |
1542 | CTK_MOVEMENT_DISPLAY_LINE_ENDS, -1); |
1543 | |
1544 | add_move_binding (binding_set, CDK_KEY_End0xff57, 0, |
1545 | CTK_MOVEMENT_DISPLAY_LINE_ENDS, 1); |
1546 | |
1547 | add_move_binding (binding_set, CDK_KEY_KP_End0xff9c, 0, |
1548 | CTK_MOVEMENT_DISPLAY_LINE_ENDS, 1); |
1549 | |
1550 | add_move_binding (binding_set, CDK_KEY_Home0xff50, CDK_CONTROL_MASK, |
1551 | CTK_MOVEMENT_BUFFER_ENDS, -1); |
1552 | |
1553 | add_move_binding (binding_set, CDK_KEY_KP_Home0xff95, CDK_CONTROL_MASK, |
1554 | CTK_MOVEMENT_BUFFER_ENDS, -1); |
1555 | |
1556 | add_move_binding (binding_set, CDK_KEY_End0xff57, CDK_CONTROL_MASK, |
1557 | CTK_MOVEMENT_BUFFER_ENDS, 1); |
1558 | |
1559 | add_move_binding (binding_set, CDK_KEY_KP_End0xff9c, CDK_CONTROL_MASK, |
1560 | CTK_MOVEMENT_BUFFER_ENDS, 1); |
1561 | |
1562 | add_move_binding (binding_set, CDK_KEY_Page_Up0xff55, 0, |
1563 | CTK_MOVEMENT_PAGES, -1); |
1564 | |
1565 | add_move_binding (binding_set, CDK_KEY_KP_Page_Up0xff9a, 0, |
1566 | CTK_MOVEMENT_PAGES, -1); |
1567 | |
1568 | add_move_binding (binding_set, CDK_KEY_Page_Down0xff56, 0, |
1569 | CTK_MOVEMENT_PAGES, 1); |
1570 | |
1571 | add_move_binding (binding_set, CDK_KEY_KP_Page_Down0xff9b, 0, |
1572 | CTK_MOVEMENT_PAGES, 1); |
1573 | |
1574 | add_move_binding (binding_set, CDK_KEY_Page_Up0xff55, CDK_CONTROL_MASK, |
1575 | CTK_MOVEMENT_HORIZONTAL_PAGES, -1); |
1576 | |
1577 | add_move_binding (binding_set, CDK_KEY_KP_Page_Up0xff9a, CDK_CONTROL_MASK, |
1578 | CTK_MOVEMENT_HORIZONTAL_PAGES, -1); |
1579 | |
1580 | add_move_binding (binding_set, CDK_KEY_Page_Down0xff56, CDK_CONTROL_MASK, |
1581 | CTK_MOVEMENT_HORIZONTAL_PAGES, 1); |
1582 | |
1583 | add_move_binding (binding_set, CDK_KEY_KP_Page_Down0xff9b, CDK_CONTROL_MASK, |
1584 | CTK_MOVEMENT_HORIZONTAL_PAGES, 1); |
1585 | |
1586 | /* Select all */ |
1587 | ctk_binding_entry_add_signal (binding_set, CDK_KEY_a0x061, CDK_CONTROL_MASK, |
1588 | "select-all", 1, |
1589 | G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0))); |
1590 | |
1591 | ctk_binding_entry_add_signal (binding_set, CDK_KEY_slash0x02f, CDK_CONTROL_MASK, |
1592 | "select-all", 1, |
1593 | G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0))); |
1594 | |
1595 | /* Unselect all */ |
1596 | ctk_binding_entry_add_signal (binding_set, CDK_KEY_backslash0x05c, CDK_CONTROL_MASK, |
1597 | "select-all", 1, |
1598 | G_TYPE_BOOLEAN((GType) ((5) << (2))), FALSE(0)); |
1599 | |
1600 | ctk_binding_entry_add_signal (binding_set, CDK_KEY_a0x061, CDK_SHIFT_MASK | CDK_CONTROL_MASK, |
1601 | "select-all", 1, |
1602 | G_TYPE_BOOLEAN((GType) ((5) << (2))), FALSE(0)); |
1603 | |
1604 | /* Deleting text */ |
1605 | ctk_binding_entry_add_signal (binding_set, CDK_KEY_Delete0xffff, 0, |
1606 | "delete-from-cursor", 2, |
1607 | G_TYPE_ENUM((GType) ((12) << (2))), CTK_DELETE_CHARS, |
1608 | G_TYPE_INT((GType) ((6) << (2))), 1); |
1609 | |
1610 | ctk_binding_entry_add_signal (binding_set, CDK_KEY_KP_Delete0xff9f, 0, |
1611 | "delete-from-cursor", 2, |
1612 | G_TYPE_ENUM((GType) ((12) << (2))), CTK_DELETE_CHARS, |
1613 | G_TYPE_INT((GType) ((6) << (2))), 1); |
1614 | |
1615 | ctk_binding_entry_add_signal (binding_set, CDK_KEY_BackSpace0xff08, 0, |
1616 | "backspace", 0); |
1617 | |
1618 | /* Make this do the same as Backspace, to help with mis-typing */ |
1619 | ctk_binding_entry_add_signal (binding_set, CDK_KEY_BackSpace0xff08, CDK_SHIFT_MASK, |
1620 | "backspace", 0); |
1621 | |
1622 | ctk_binding_entry_add_signal (binding_set, CDK_KEY_Delete0xffff, CDK_CONTROL_MASK, |
1623 | "delete-from-cursor", 2, |
1624 | G_TYPE_ENUM((GType) ((12) << (2))), CTK_DELETE_WORD_ENDS, |
1625 | G_TYPE_INT((GType) ((6) << (2))), 1); |
1626 | |
1627 | ctk_binding_entry_add_signal (binding_set, CDK_KEY_KP_Delete0xff9f, CDK_CONTROL_MASK, |
1628 | "delete-from-cursor", 2, |
1629 | G_TYPE_ENUM((GType) ((12) << (2))), CTK_DELETE_WORD_ENDS, |
1630 | G_TYPE_INT((GType) ((6) << (2))), 1); |
1631 | |
1632 | ctk_binding_entry_add_signal (binding_set, CDK_KEY_BackSpace0xff08, CDK_CONTROL_MASK, |
1633 | "delete-from-cursor", 2, |
1634 | G_TYPE_ENUM((GType) ((12) << (2))), CTK_DELETE_WORD_ENDS, |
1635 | G_TYPE_INT((GType) ((6) << (2))), -1); |
1636 | |
1637 | ctk_binding_entry_add_signal (binding_set, CDK_KEY_Delete0xffff, CDK_SHIFT_MASK | CDK_CONTROL_MASK, |
1638 | "delete-from-cursor", 2, |
1639 | G_TYPE_ENUM((GType) ((12) << (2))), CTK_DELETE_PARAGRAPH_ENDS, |
1640 | G_TYPE_INT((GType) ((6) << (2))), 1); |
1641 | |
1642 | ctk_binding_entry_add_signal (binding_set, CDK_KEY_KP_Delete0xff9f, CDK_SHIFT_MASK | CDK_CONTROL_MASK, |
1643 | "delete-from-cursor", 2, |
1644 | G_TYPE_ENUM((GType) ((12) << (2))), CTK_DELETE_PARAGRAPH_ENDS, |
1645 | G_TYPE_INT((GType) ((6) << (2))), 1); |
1646 | |
1647 | ctk_binding_entry_add_signal (binding_set, CDK_KEY_BackSpace0xff08, CDK_SHIFT_MASK | CDK_CONTROL_MASK, |
1648 | "delete-from-cursor", 2, |
1649 | G_TYPE_ENUM((GType) ((12) << (2))), CTK_DELETE_PARAGRAPH_ENDS, |
1650 | G_TYPE_INT((GType) ((6) << (2))), -1); |
1651 | |
1652 | /* Cut/copy/paste */ |
1653 | |
1654 | ctk_binding_entry_add_signal (binding_set, CDK_KEY_x0x078, CDK_CONTROL_MASK, |
1655 | "cut-clipboard", 0); |
1656 | ctk_binding_entry_add_signal (binding_set, CDK_KEY_c0x063, CDK_CONTROL_MASK, |
1657 | "copy-clipboard", 0); |
1658 | ctk_binding_entry_add_signal (binding_set, CDK_KEY_v0x076, CDK_CONTROL_MASK, |
1659 | "paste-clipboard", 0); |
1660 | |
1661 | ctk_binding_entry_add_signal (binding_set, CDK_KEY_KP_Delete0xff9f, CDK_SHIFT_MASK, |
1662 | "cut-clipboard", 0); |
1663 | ctk_binding_entry_add_signal (binding_set, CDK_KEY_KP_Insert0xff9e, CDK_CONTROL_MASK, |
1664 | "copy-clipboard", 0); |
1665 | ctk_binding_entry_add_signal (binding_set, CDK_KEY_KP_Insert0xff9e, CDK_SHIFT_MASK, |
1666 | "paste-clipboard", 0); |
1667 | |
1668 | ctk_binding_entry_add_signal (binding_set, CDK_KEY_Delete0xffff, CDK_SHIFT_MASK, |
1669 | "cut-clipboard", 0); |
1670 | ctk_binding_entry_add_signal (binding_set, CDK_KEY_Insert0xff63, CDK_CONTROL_MASK, |
1671 | "copy-clipboard", 0); |
1672 | ctk_binding_entry_add_signal (binding_set, CDK_KEY_Insert0xff63, CDK_SHIFT_MASK, |
1673 | "paste-clipboard", 0); |
1674 | |
1675 | /* Overwrite */ |
1676 | ctk_binding_entry_add_signal (binding_set, CDK_KEY_Insert0xff63, 0, |
1677 | "toggle-overwrite", 0); |
1678 | ctk_binding_entry_add_signal (binding_set, CDK_KEY_KP_Insert0xff9e, 0, |
1679 | "toggle-overwrite", 0); |
1680 | |
1681 | /* Emoji */ |
1682 | ctk_binding_entry_add_signal (binding_set, CDK_KEY_period0x02e, CDK_CONTROL_MASK, |
1683 | "insert-emoji", 0); |
1684 | ctk_binding_entry_add_signal (binding_set, CDK_KEY_semicolon0x03b, CDK_CONTROL_MASK, |
1685 | "insert-emoji", 0); |
1686 | |
1687 | /* Caret mode */ |
1688 | ctk_binding_entry_add_signal (binding_set, CDK_KEY_F70xffc4, 0, |
1689 | "toggle-cursor-visible", 0); |
1690 | |
1691 | /* Control-tab focus motion */ |
1692 | ctk_binding_entry_add_signal (binding_set, CDK_KEY_Tab0xff09, CDK_CONTROL_MASK, |
1693 | "move-focus", 1, |
1694 | CTK_TYPE_DIRECTION_TYPE(ctk_direction_type_get_type ()), CTK_DIR_TAB_FORWARD); |
1695 | ctk_binding_entry_add_signal (binding_set, CDK_KEY_KP_Tab0xff89, CDK_CONTROL_MASK, |
1696 | "move-focus", 1, |
1697 | CTK_TYPE_DIRECTION_TYPE(ctk_direction_type_get_type ()), CTK_DIR_TAB_FORWARD); |
1698 | |
1699 | ctk_binding_entry_add_signal (binding_set, CDK_KEY_Tab0xff09, CDK_SHIFT_MASK | CDK_CONTROL_MASK, |
1700 | "move-focus", 1, |
1701 | CTK_TYPE_DIRECTION_TYPE(ctk_direction_type_get_type ()), CTK_DIR_TAB_BACKWARD); |
1702 | ctk_binding_entry_add_signal (binding_set, CDK_KEY_KP_Tab0xff89, CDK_SHIFT_MASK | CDK_CONTROL_MASK, |
1703 | "move-focus", 1, |
1704 | CTK_TYPE_DIRECTION_TYPE(ctk_direction_type_get_type ()), CTK_DIR_TAB_BACKWARD); |
1705 | |
1706 | ctk_widget_class_set_accessible_type (widget_class, CTK_TYPE_TEXT_VIEW_ACCESSIBLE(ctk_text_view_accessible_get_type ())); |
1707 | ctk_widget_class_set_css_name (widget_class, "textview"); |
1708 | |
1709 | quark_text_selection_data = g_quark_from_static_string ("ctk-text-view-text-selection-data"); |
1710 | quark_ctk_signal = g_quark_from_static_string ("ctk-signal"); |
1711 | quark_text_view_child = g_quark_from_static_string ("ctk-text-view-child"); |
1712 | } |
1713 | |
1714 | static void |
1715 | ctk_text_view_init (CtkTextView *text_view) |
1716 | { |
1717 | CtkWidget *widget = CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))); |
1718 | CtkTargetList *target_list; |
1719 | CtkTextViewPrivate *priv; |
1720 | CtkStyleContext *context; |
1721 | |
1722 | text_view->priv = ctk_text_view_get_instance_private (text_view); |
1723 | priv = text_view->priv; |
1724 | |
1725 | ctk_widget_set_can_focus (widget, TRUE(!(0))); |
1726 | |
1727 | priv->pixel_cache = _ctk_pixel_cache_new (); |
1728 | |
1729 | context = ctk_widget_get_style_context (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
1730 | ctk_style_context_add_class (context, CTK_STYLE_CLASS_VIEW"view"); |
1731 | |
1732 | /* Set up default style */ |
1733 | priv->wrap_mode = CTK_WRAP_NONE; |
1734 | priv->pixels_above_lines = 0; |
1735 | priv->pixels_below_lines = 0; |
1736 | priv->pixels_inside_wrap = 0; |
1737 | priv->justify = CTK_JUSTIFY_LEFT; |
1738 | priv->indent = 0; |
1739 | priv->tabs = NULL((void*)0); |
1740 | priv->editable = TRUE(!(0)); |
1741 | |
1742 | priv->scroll_after_paste = FALSE(0); |
1743 | |
1744 | ctk_drag_dest_set (widget, 0, NULL((void*)0), 0, |
1745 | CDK_ACTION_COPY | CDK_ACTION_MOVE); |
1746 | |
1747 | target_list = ctk_target_list_new (NULL((void*)0), 0); |
1748 | ctk_drag_dest_set_target_list (widget, target_list); |
1749 | ctk_target_list_unref (target_list); |
1750 | |
1751 | priv->virtual_cursor_x = -1; |
1752 | priv->virtual_cursor_y = -1; |
1753 | |
1754 | /* This object is completely private. No external entity can gain a reference |
1755 | * to it; so we create it here and destroy it in finalize (). |
1756 | */ |
1757 | priv->im_context = ctk_im_multicontext_new (); |
1758 | |
1759 | g_signal_connect (priv->im_context, "commit",g_signal_connect_data ((priv->im_context), ("commit"), ((( GCallback) (ctk_text_view_commit_handler))), (text_view), ((void *)0), (GConnectFlags) 0) |
1760 | G_CALLBACK (ctk_text_view_commit_handler), text_view)g_signal_connect_data ((priv->im_context), ("commit"), ((( GCallback) (ctk_text_view_commit_handler))), (text_view), ((void *)0), (GConnectFlags) 0); |
1761 | g_signal_connect (priv->im_context, "preedit-changed",g_signal_connect_data ((priv->im_context), ("preedit-changed" ), (((GCallback) (ctk_text_view_preedit_changed_handler))), ( text_view), ((void*)0), (GConnectFlags) 0) |
1762 | G_CALLBACK (ctk_text_view_preedit_changed_handler), text_view)g_signal_connect_data ((priv->im_context), ("preedit-changed" ), (((GCallback) (ctk_text_view_preedit_changed_handler))), ( text_view), ((void*)0), (GConnectFlags) 0); |
1763 | g_signal_connect (priv->im_context, "retrieve-surrounding",g_signal_connect_data ((priv->im_context), ("retrieve-surrounding" ), (((GCallback) (ctk_text_view_retrieve_surrounding_handler) )), (text_view), ((void*)0), (GConnectFlags) 0) |
1764 | G_CALLBACK (ctk_text_view_retrieve_surrounding_handler), text_view)g_signal_connect_data ((priv->im_context), ("retrieve-surrounding" ), (((GCallback) (ctk_text_view_retrieve_surrounding_handler) )), (text_view), ((void*)0), (GConnectFlags) 0); |
1765 | g_signal_connect (priv->im_context, "delete-surrounding",g_signal_connect_data ((priv->im_context), ("delete-surrounding" ), (((GCallback) (ctk_text_view_delete_surrounding_handler))) , (text_view), ((void*)0), (GConnectFlags) 0) |
1766 | G_CALLBACK (ctk_text_view_delete_surrounding_handler), text_view)g_signal_connect_data ((priv->im_context), ("delete-surrounding" ), (((GCallback) (ctk_text_view_delete_surrounding_handler))) , (text_view), ((void*)0), (GConnectFlags) 0); |
1767 | |
1768 | priv->cursor_visible = TRUE(!(0)); |
1769 | |
1770 | priv->accepts_tab = TRUE(!(0)); |
1771 | |
1772 | priv->text_window = text_window_new (CTK_TEXT_WINDOW_TEXT, |
1773 | widget, 200, 200); |
1774 | |
1775 | priv->multipress_gesture = ctk_gesture_multi_press_new (widget); |
1776 | ctk_gesture_single_set_button (CTK_GESTURE_SINGLE (priv->multipress_gesture)((((CtkGestureSingle*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((priv->multipress_gesture)), ((ctk_gesture_single_get_type ())))))), 0); |
1777 | g_signal_connect (priv->multipress_gesture, "pressed",g_signal_connect_data ((priv->multipress_gesture), ("pressed" ), (((GCallback) (ctk_text_view_multipress_gesture_pressed))) , (widget), ((void*)0), (GConnectFlags) 0) |
1778 | G_CALLBACK (ctk_text_view_multipress_gesture_pressed),g_signal_connect_data ((priv->multipress_gesture), ("pressed" ), (((GCallback) (ctk_text_view_multipress_gesture_pressed))) , (widget), ((void*)0), (GConnectFlags) 0) |
1779 | widget)g_signal_connect_data ((priv->multipress_gesture), ("pressed" ), (((GCallback) (ctk_text_view_multipress_gesture_pressed))) , (widget), ((void*)0), (GConnectFlags) 0); |
1780 | |
1781 | priv->drag_gesture = ctk_gesture_drag_new (widget); |
1782 | g_signal_connect (priv->drag_gesture, "drag-update",g_signal_connect_data ((priv->drag_gesture), ("drag-update" ), (((GCallback) (ctk_text_view_drag_gesture_update))), (widget ), ((void*)0), (GConnectFlags) 0) |
1783 | G_CALLBACK (ctk_text_view_drag_gesture_update),g_signal_connect_data ((priv->drag_gesture), ("drag-update" ), (((GCallback) (ctk_text_view_drag_gesture_update))), (widget ), ((void*)0), (GConnectFlags) 0) |
1784 | widget)g_signal_connect_data ((priv->drag_gesture), ("drag-update" ), (((GCallback) (ctk_text_view_drag_gesture_update))), (widget ), ((void*)0), (GConnectFlags) 0); |
1785 | g_signal_connect (priv->drag_gesture, "drag-end",g_signal_connect_data ((priv->drag_gesture), ("drag-end"), (((GCallback) (ctk_text_view_drag_gesture_end))), (widget), ( (void*)0), (GConnectFlags) 0) |
1786 | G_CALLBACK (ctk_text_view_drag_gesture_end),g_signal_connect_data ((priv->drag_gesture), ("drag-end"), (((GCallback) (ctk_text_view_drag_gesture_end))), (widget), ( (void*)0), (GConnectFlags) 0) |
1787 | widget)g_signal_connect_data ((priv->drag_gesture), ("drag-end"), (((GCallback) (ctk_text_view_drag_gesture_end))), (widget), ( (void*)0), (GConnectFlags) 0); |
1788 | |
1789 | priv->selection_node = ctk_css_node_new (); |
1790 | ctk_css_node_set_name (priv->selection_node, I_("selection")g_intern_static_string ("selection")); |
1791 | ctk_css_node_set_parent (priv->selection_node, priv->text_window->css_node); |
1792 | ctk_css_node_set_state (priv->selection_node, |
1793 | ctk_css_node_get_state (priv->text_window->css_node) & ~CTK_STATE_FLAG_DROP_ACTIVE); |
1794 | ctk_css_node_set_visible (priv->selection_node, FALSE(0)); |
1795 | g_object_unref (priv->selection_node); |
1796 | } |
1797 | |
1798 | CtkCssNode * |
1799 | ctk_text_view_get_text_node (CtkTextView *text_view) |
1800 | { |
1801 | return text_view->priv->text_window->css_node; |
1802 | } |
1803 | |
1804 | CtkCssNode * |
1805 | ctk_text_view_get_selection_node (CtkTextView *text_view) |
1806 | { |
1807 | return text_view->priv->selection_node; |
1808 | } |
1809 | |
1810 | static void |
1811 | _ctk_text_view_ensure_text_handles (CtkTextView *text_view) |
1812 | { |
1813 | CtkTextViewPrivate *priv = text_view->priv; |
1814 | |
1815 | if (priv->text_handle) |
1816 | return; |
1817 | |
1818 | priv->text_handle = _ctk_text_handle_new (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
1819 | g_signal_connect (priv->text_handle, "drag-started",g_signal_connect_data ((priv->text_handle), ("drag-started" ), (((GCallback) (ctk_text_view_handle_drag_started))), (text_view ), ((void*)0), (GConnectFlags) 0) |
1820 | G_CALLBACK (ctk_text_view_handle_drag_started), text_view)g_signal_connect_data ((priv->text_handle), ("drag-started" ), (((GCallback) (ctk_text_view_handle_drag_started))), (text_view ), ((void*)0), (GConnectFlags) 0); |
1821 | g_signal_connect (priv->text_handle, "handle-dragged",g_signal_connect_data ((priv->text_handle), ("handle-dragged" ), (((GCallback) (ctk_text_view_handle_dragged))), (text_view ), ((void*)0), (GConnectFlags) 0) |
1822 | G_CALLBACK (ctk_text_view_handle_dragged), text_view)g_signal_connect_data ((priv->text_handle), ("handle-dragged" ), (((GCallback) (ctk_text_view_handle_dragged))), (text_view ), ((void*)0), (GConnectFlags) 0); |
1823 | g_signal_connect (priv->text_handle, "drag-finished",g_signal_connect_data ((priv->text_handle), ("drag-finished" ), (((GCallback) (ctk_text_view_handle_drag_finished))), (text_view ), ((void*)0), (GConnectFlags) 0) |
1824 | G_CALLBACK (ctk_text_view_handle_drag_finished), text_view)g_signal_connect_data ((priv->text_handle), ("drag-finished" ), (((GCallback) (ctk_text_view_handle_drag_finished))), (text_view ), ((void*)0), (GConnectFlags) 0); |
1825 | } |
1826 | |
1827 | static void |
1828 | _ctk_text_view_ensure_magnifier (CtkTextView *text_view) |
1829 | { |
1830 | CtkTextViewPrivate *priv = text_view->priv; |
1831 | |
1832 | if (priv->magnifier_popover) |
1833 | return; |
1834 | |
1835 | priv->magnifier = _ctk_magnifier_new (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
1836 | _ctk_magnifier_set_magnification (CTK_MAGNIFIER (priv->magnifier)((((CtkMagnifier*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((priv->magnifier)), ((_ctk_magnifier_get_type ())))))), 2.0); |
1837 | priv->magnifier_popover = ctk_popover_new (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
1838 | ctk_style_context_add_class (ctk_widget_get_style_context (priv->magnifier_popover), |
1839 | "magnifier"); |
1840 | ctk_popover_set_modal (CTK_POPOVER (priv->magnifier_popover)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((priv->magnifier_popover)), ((ctk_popover_get_type ()) ))))), FALSE(0)); |
1841 | ctk_container_add (CTK_CONTAINER (priv->magnifier_popover)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((priv->magnifier_popover)), ((ctk_container_get_type ( ))))))), |
1842 | priv->magnifier); |
1843 | ctk_container_set_border_width (CTK_CONTAINER (priv->magnifier_popover)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((priv->magnifier_popover)), ((ctk_container_get_type ( ))))))), 4); |
1844 | ctk_widget_show (priv->magnifier); |
1845 | } |
1846 | |
1847 | /** |
1848 | * ctk_text_view_new: |
1849 | * |
1850 | * Creates a new #CtkTextView. If you don’t call ctk_text_view_set_buffer() |
1851 | * before using the text view, an empty default buffer will be created |
1852 | * for you. Get the buffer with ctk_text_view_get_buffer(). If you want |
1853 | * to specify your own buffer, consider ctk_text_view_new_with_buffer(). |
1854 | * |
1855 | * Returns: a new #CtkTextView |
1856 | **/ |
1857 | CtkWidget* |
1858 | ctk_text_view_new (void) |
1859 | { |
1860 | return g_object_new (CTK_TYPE_TEXT_VIEW(ctk_text_view_get_type ()), NULL((void*)0)); |
1861 | } |
1862 | |
1863 | /** |
1864 | * ctk_text_view_new_with_buffer: |
1865 | * @buffer: a #CtkTextBuffer |
1866 | * |
1867 | * Creates a new #CtkTextView widget displaying the buffer |
1868 | * @buffer. One buffer can be shared among many widgets. |
1869 | * @buffer may be %NULL to create a default buffer, in which case |
1870 | * this function is equivalent to ctk_text_view_new(). The |
1871 | * text view adds its own reference count to the buffer; it does not |
1872 | * take over an existing reference. |
1873 | * |
1874 | * Returns: a new #CtkTextView. |
1875 | **/ |
1876 | CtkWidget* |
1877 | ctk_text_view_new_with_buffer (CtkTextBuffer *buffer) |
1878 | { |
1879 | CtkTextView *text_view; |
1880 | |
1881 | text_view = (CtkTextView*)ctk_text_view_new (); |
1882 | |
1883 | ctk_text_view_set_buffer (text_view, buffer); |
1884 | |
1885 | return CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))); |
1886 | } |
1887 | |
1888 | /** |
1889 | * ctk_text_view_set_buffer: |
1890 | * @text_view: a #CtkTextView |
1891 | * @buffer: (allow-none): a #CtkTextBuffer |
1892 | * |
1893 | * Sets @buffer as the buffer being displayed by @text_view. The previous |
1894 | * buffer displayed by the text view is unreferenced, and a reference is |
1895 | * added to @buffer. If you owned a reference to @buffer before passing it |
1896 | * to this function, you must remove that reference yourself; #CtkTextView |
1897 | * will not “adopt” it. |
1898 | **/ |
1899 | void |
1900 | ctk_text_view_set_buffer (CtkTextView *text_view, |
1901 | CtkTextBuffer *buffer) |
1902 | { |
1903 | CtkTextViewPrivate *priv; |
1904 | CtkTextBuffer *old_buffer; |
1905 | |
1906 | g_return_if_fail (CTK_IS_TEXT_VIEW (text_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return; } } while (0); |
1907 | g_return_if_fail (buffer == NULL || CTK_IS_TEXT_BUFFER (buffer))do { if ((buffer == ((void*)0) || (((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ((buffer)); GType __t = ((ctk_text_buffer_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__)), "buffer == NULL || CTK_IS_TEXT_BUFFER (buffer)" ); return; } } while (0); |
1908 | |
1909 | priv = text_view->priv; |
1910 | |
1911 | if (priv->buffer == buffer) |
1912 | return; |
1913 | |
1914 | old_buffer = priv->buffer; |
1915 | if (priv->buffer != NULL((void*)0)) |
1916 | { |
1917 | /* Destroy all anchored children */ |
1918 | GSList *tmp_list; |
1919 | GSList *copy; |
1920 | |
1921 | copy = g_slist_copy (priv->children); |
1922 | tmp_list = copy; |
1923 | while (tmp_list != NULL((void*)0)) |
1924 | { |
1925 | CtkTextViewChild *vc = tmp_list->data; |
1926 | |
1927 | if (vc->anchor) |
1928 | { |
1929 | ctk_widget_destroy (vc->widget); |
1930 | /* vc may now be invalid! */ |
1931 | } |
1932 | |
1933 | tmp_list = tmp_list->next; |
1934 | } |
1935 | |
1936 | g_slist_free (copy); |
1937 | |
1938 | g_signal_handlers_disconnect_by_func (priv->buffer,g_signal_handlers_disconnect_matched ((priv->buffer), (GSignalMatchType ) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*) 0), (ctk_text_view_mark_set_handler), (text_view)) |
1939 | ctk_text_view_mark_set_handler,g_signal_handlers_disconnect_matched ((priv->buffer), (GSignalMatchType ) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*) 0), (ctk_text_view_mark_set_handler), (text_view)) |
1940 | text_view)g_signal_handlers_disconnect_matched ((priv->buffer), (GSignalMatchType ) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*) 0), (ctk_text_view_mark_set_handler), (text_view)); |
1941 | g_signal_handlers_disconnect_by_func (priv->buffer,g_signal_handlers_disconnect_matched ((priv->buffer), (GSignalMatchType ) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*) 0), (ctk_text_view_target_list_notify), (text_view)) |
1942 | ctk_text_view_target_list_notify,g_signal_handlers_disconnect_matched ((priv->buffer), (GSignalMatchType ) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*) 0), (ctk_text_view_target_list_notify), (text_view)) |
1943 | text_view)g_signal_handlers_disconnect_matched ((priv->buffer), (GSignalMatchType ) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*) 0), (ctk_text_view_target_list_notify), (text_view)); |
1944 | g_signal_handlers_disconnect_by_func (priv->buffer,g_signal_handlers_disconnect_matched ((priv->buffer), (GSignalMatchType ) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*) 0), (ctk_text_view_paste_done_handler), (text_view)) |
1945 | ctk_text_view_paste_done_handler,g_signal_handlers_disconnect_matched ((priv->buffer), (GSignalMatchType ) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*) 0), (ctk_text_view_paste_done_handler), (text_view)) |
1946 | text_view)g_signal_handlers_disconnect_matched ((priv->buffer), (GSignalMatchType ) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*) 0), (ctk_text_view_paste_done_handler), (text_view)); |
1947 | g_signal_handlers_disconnect_by_func (priv->buffer,g_signal_handlers_disconnect_matched ((priv->buffer), (GSignalMatchType ) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*) 0), (ctk_text_view_buffer_changed_handler), (text_view)) |
1948 | ctk_text_view_buffer_changed_handler,g_signal_handlers_disconnect_matched ((priv->buffer), (GSignalMatchType ) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*) 0), (ctk_text_view_buffer_changed_handler), (text_view)) |
1949 | text_view)g_signal_handlers_disconnect_matched ((priv->buffer), (GSignalMatchType ) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*) 0), (ctk_text_view_buffer_changed_handler), (text_view)); |
1950 | |
1951 | if (ctk_widget_get_realized (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))))) |
1952 | { |
1953 | CtkClipboard *clipboard = ctk_widget_get_clipboard (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))), |
1954 | CDK_SELECTION_PRIMARY((CdkAtom)((gpointer) (gulong) (1)))); |
1955 | ctk_text_buffer_remove_selection_clipboard (priv->buffer, clipboard); |
1956 | } |
1957 | |
1958 | if (priv->layout) |
1959 | ctk_text_layout_set_buffer (priv->layout, NULL((void*)0)); |
1960 | |
1961 | priv->dnd_mark = NULL((void*)0); |
1962 | priv->first_para_mark = NULL((void*)0); |
1963 | cancel_pending_scroll (text_view); |
1964 | } |
1965 | |
1966 | priv->buffer = buffer; |
1967 | |
1968 | if (priv->layout) |
1969 | ctk_text_layout_set_buffer (priv->layout, buffer); |
1970 | |
1971 | if (buffer != NULL((void*)0)) |
1972 | { |
1973 | CtkTextIter start; |
1974 | |
1975 | g_object_ref (buffer)((__typeof__ (buffer)) (g_object_ref) (buffer)); |
1976 | |
1977 | ctk_text_buffer_get_iter_at_offset (priv->buffer, &start, 0); |
1978 | |
1979 | priv->dnd_mark = ctk_text_buffer_create_mark (priv->buffer, |
1980 | "ctk_drag_target", |
1981 | &start, FALSE(0)); |
1982 | |
1983 | priv->first_para_mark = ctk_text_buffer_create_mark (priv->buffer, |
1984 | NULL((void*)0), |
1985 | &start, TRUE(!(0))); |
1986 | |
1987 | priv->first_para_pixels = 0; |
1988 | |
1989 | |
1990 | g_signal_connect (priv->buffer, "mark-set",g_signal_connect_data ((priv->buffer), ("mark-set"), (((GCallback ) (ctk_text_view_mark_set_handler))), (text_view), ((void*)0) , (GConnectFlags) 0) |
1991 | G_CALLBACK (ctk_text_view_mark_set_handler),g_signal_connect_data ((priv->buffer), ("mark-set"), (((GCallback ) (ctk_text_view_mark_set_handler))), (text_view), ((void*)0) , (GConnectFlags) 0) |
1992 | text_view)g_signal_connect_data ((priv->buffer), ("mark-set"), (((GCallback ) (ctk_text_view_mark_set_handler))), (text_view), ((void*)0) , (GConnectFlags) 0); |
1993 | g_signal_connect (priv->buffer, "notify::paste-target-list",g_signal_connect_data ((priv->buffer), ("notify::paste-target-list" ), (((GCallback) (ctk_text_view_target_list_notify))), (text_view ), ((void*)0), (GConnectFlags) 0) |
1994 | G_CALLBACK (ctk_text_view_target_list_notify),g_signal_connect_data ((priv->buffer), ("notify::paste-target-list" ), (((GCallback) (ctk_text_view_target_list_notify))), (text_view ), ((void*)0), (GConnectFlags) 0) |
1995 | text_view)g_signal_connect_data ((priv->buffer), ("notify::paste-target-list" ), (((GCallback) (ctk_text_view_target_list_notify))), (text_view ), ((void*)0), (GConnectFlags) 0); |
1996 | g_signal_connect (priv->buffer, "paste-done",g_signal_connect_data ((priv->buffer), ("paste-done"), ((( GCallback) (ctk_text_view_paste_done_handler))), (text_view), ((void*)0), (GConnectFlags) 0) |
1997 | G_CALLBACK (ctk_text_view_paste_done_handler),g_signal_connect_data ((priv->buffer), ("paste-done"), ((( GCallback) (ctk_text_view_paste_done_handler))), (text_view), ((void*)0), (GConnectFlags) 0) |
1998 | text_view)g_signal_connect_data ((priv->buffer), ("paste-done"), ((( GCallback) (ctk_text_view_paste_done_handler))), (text_view), ((void*)0), (GConnectFlags) 0); |
1999 | g_signal_connect (priv->buffer, "changed",g_signal_connect_data ((priv->buffer), ("changed"), (((GCallback ) (ctk_text_view_buffer_changed_handler))), (text_view), ((void *)0), (GConnectFlags) 0) |
2000 | G_CALLBACK (ctk_text_view_buffer_changed_handler),g_signal_connect_data ((priv->buffer), ("changed"), (((GCallback ) (ctk_text_view_buffer_changed_handler))), (text_view), ((void *)0), (GConnectFlags) 0) |
2001 | text_view)g_signal_connect_data ((priv->buffer), ("changed"), (((GCallback ) (ctk_text_view_buffer_changed_handler))), (text_view), ((void *)0), (GConnectFlags) 0); |
2002 | |
2003 | ctk_text_view_target_list_notify (priv->buffer, NULL((void*)0), text_view); |
2004 | |
2005 | if (ctk_widget_get_realized (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))))) |
2006 | { |
2007 | CtkClipboard *clipboard = ctk_widget_get_clipboard (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))), |
2008 | CDK_SELECTION_PRIMARY((CdkAtom)((gpointer) (gulong) (1)))); |
2009 | ctk_text_buffer_add_selection_clipboard (priv->buffer, clipboard); |
2010 | } |
2011 | |
2012 | if (priv->text_handle) |
2013 | ctk_text_view_update_handles (text_view, CTK_TEXT_HANDLE_MODE_NONE); |
2014 | } |
2015 | |
2016 | _ctk_text_view_accessible_set_buffer (text_view, old_buffer); |
2017 | if (old_buffer) |
2018 | g_object_unref (old_buffer); |
2019 | |
2020 | g_object_notify (G_OBJECT (text_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), (((GType) ((20) << (2)))))))), "buffer"); |
2021 | |
2022 | if (ctk_widget_get_visible (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))))) |
2023 | ctk_widget_queue_draw (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
2024 | |
2025 | DV(g_print ("Invalidating due to set_buffer\n")); |
2026 | ctk_text_view_invalidate (text_view); |
2027 | } |
2028 | |
2029 | static CtkTextBuffer* |
2030 | ctk_text_view_create_buffer (CtkTextView *text_view G_GNUC_UNUSED__attribute__ ((__unused__))) |
2031 | { |
2032 | return ctk_text_buffer_new (NULL((void*)0)); |
2033 | } |
2034 | |
2035 | static CtkTextBuffer* |
2036 | get_buffer (CtkTextView *text_view) |
2037 | { |
2038 | if (text_view->priv->buffer == NULL((void*)0)) |
2039 | { |
2040 | CtkTextBuffer *b; |
2041 | b = CTK_TEXT_VIEW_GET_CLASS (text_view)((((CtkTextViewClass*) (((GTypeInstance*) ((text_view)))-> g_class))))->create_buffer (text_view); |
2042 | ctk_text_view_set_buffer (text_view, b); |
2043 | g_object_unref (b); |
2044 | } |
2045 | |
2046 | return text_view->priv->buffer; |
2047 | } |
2048 | |
2049 | /** |
2050 | * ctk_text_view_get_buffer: |
2051 | * @text_view: a #CtkTextView |
2052 | * |
2053 | * Returns the #CtkTextBuffer being displayed by this text view. |
2054 | * The reference count on the buffer is not incremented; the caller |
2055 | * of this function won’t own a new reference. |
2056 | * |
2057 | * Returns: (transfer none): a #CtkTextBuffer |
2058 | **/ |
2059 | CtkTextBuffer* |
2060 | ctk_text_view_get_buffer (CtkTextView *text_view) |
2061 | { |
2062 | g_return_val_if_fail (CTK_IS_TEXT_VIEW (text_view), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return (((void*)0)); } } while (0); |
2063 | |
2064 | return get_buffer (text_view); |
2065 | } |
2066 | |
2067 | /** |
2068 | * ctk_text_view_get_cursor_locations: |
2069 | * @text_view: a #CtkTextView |
2070 | * @iter: (allow-none): a #CtkTextIter |
2071 | * @strong: (out) (allow-none): location to store the strong |
2072 | * cursor position (may be %NULL) |
2073 | * @weak: (out) (allow-none): location to store the weak |
2074 | * cursor position (may be %NULL) |
2075 | * |
2076 | * Given an @iter within a text layout, determine the positions of the |
2077 | * strong and weak cursors if the insertion point is at that |
2078 | * iterator. The position of each cursor is stored as a zero-width |
2079 | * rectangle. The strong cursor location is the location where |
2080 | * characters of the directionality equal to the base direction of the |
2081 | * paragraph are inserted. The weak cursor location is the location |
2082 | * where characters of the directionality opposite to the base |
2083 | * direction of the paragraph are inserted. |
2084 | * |
2085 | * If @iter is %NULL, the actual cursor position is used. |
2086 | * |
2087 | * Note that if @iter happens to be the actual cursor position, and |
2088 | * there is currently an IM preedit sequence being entered, the |
2089 | * returned locations will be adjusted to account for the preedit |
2090 | * cursor’s offset within the preedit sequence. |
2091 | * |
2092 | * The rectangle position is in buffer coordinates; use |
2093 | * ctk_text_view_buffer_to_window_coords() to convert these |
2094 | * coordinates to coordinates for one of the windows in the text view. |
2095 | * |
2096 | * Since: 3.0 |
2097 | **/ |
2098 | void |
2099 | ctk_text_view_get_cursor_locations (CtkTextView *text_view, |
2100 | const CtkTextIter *iter, |
2101 | CdkRectangle *strong, |
2102 | CdkRectangle *weak) |
2103 | { |
2104 | CtkTextIter insert; |
2105 | |
2106 | g_return_if_fail (CTK_IS_TEXT_VIEW (text_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return; } } while (0); |
2107 | g_return_if_fail (iter == NULL ||do { if ((iter == ((void*)0) || ctk_text_iter_get_buffer (iter ) == get_buffer (text_view))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "iter == NULL || ctk_text_iter_get_buffer (iter) == get_buffer (text_view)" ); return; } } while (0) |
2108 | ctk_text_iter_get_buffer (iter) == get_buffer (text_view))do { if ((iter == ((void*)0) || ctk_text_iter_get_buffer (iter ) == get_buffer (text_view))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "iter == NULL || ctk_text_iter_get_buffer (iter) == get_buffer (text_view)" ); return; } } while (0); |
2109 | |
2110 | ctk_text_view_ensure_layout (text_view); |
2111 | |
2112 | if (iter) |
2113 | insert = *iter; |
2114 | else |
2115 | ctk_text_buffer_get_iter_at_mark (get_buffer (text_view), &insert, |
2116 | ctk_text_buffer_get_insert (get_buffer (text_view))); |
2117 | |
2118 | ctk_text_layout_get_cursor_locations (text_view->priv->layout, &insert, |
2119 | strong, weak); |
2120 | } |
2121 | |
2122 | /** |
2123 | * ctk_text_view_get_iter_at_location: |
2124 | * @text_view: a #CtkTextView |
2125 | * @iter: (out): a #CtkTextIter |
2126 | * @x: x position, in buffer coordinates |
2127 | * @y: y position, in buffer coordinates |
2128 | * |
2129 | * Retrieves the iterator at buffer coordinates @x and @y. Buffer |
2130 | * coordinates are coordinates for the entire buffer, not just the |
2131 | * currently-displayed portion. If you have coordinates from an |
2132 | * event, you have to convert those to buffer coordinates with |
2133 | * ctk_text_view_window_to_buffer_coords(). |
2134 | * |
2135 | * Returns: %TRUE if the position is over text |
2136 | */ |
2137 | gboolean |
2138 | ctk_text_view_get_iter_at_location (CtkTextView *text_view, |
2139 | CtkTextIter *iter, |
2140 | gint x, |
2141 | gint y) |
2142 | { |
2143 | g_return_val_if_fail (CTK_IS_TEXT_VIEW (text_view), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return ((0)); } } while ( 0); |
2144 | g_return_val_if_fail (iter != NULL, FALSE)do { if ((iter != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "iter != NULL"); return ( (0)); } } while (0); |
2145 | |
2146 | ctk_text_view_ensure_layout (text_view); |
2147 | |
2148 | return ctk_text_layout_get_iter_at_pixel (text_view->priv->layout, iter, x, y); |
2149 | } |
2150 | |
2151 | /** |
2152 | * ctk_text_view_get_iter_at_position: |
2153 | * @text_view: a #CtkTextView |
2154 | * @iter: (out): a #CtkTextIter |
2155 | * @trailing: (out) (allow-none): if non-%NULL, location to store an integer indicating where |
2156 | * in the grapheme the user clicked. It will either be |
2157 | * zero, or the number of characters in the grapheme. |
2158 | * 0 represents the trailing edge of the grapheme. |
2159 | * @x: x position, in buffer coordinates |
2160 | * @y: y position, in buffer coordinates |
2161 | * |
2162 | * Retrieves the iterator pointing to the character at buffer |
2163 | * coordinates @x and @y. Buffer coordinates are coordinates for |
2164 | * the entire buffer, not just the currently-displayed portion. |
2165 | * If you have coordinates from an event, you have to convert |
2166 | * those to buffer coordinates with |
2167 | * ctk_text_view_window_to_buffer_coords(). |
2168 | * |
2169 | * Note that this is different from ctk_text_view_get_iter_at_location(), |
2170 | * which returns cursor locations, i.e. positions between |
2171 | * characters. |
2172 | * |
2173 | * Returns: %TRUE if the position is over text |
2174 | * |
2175 | * Since: 2.6 |
2176 | **/ |
2177 | gboolean |
2178 | ctk_text_view_get_iter_at_position (CtkTextView *text_view, |
2179 | CtkTextIter *iter, |
2180 | gint *trailing, |
2181 | gint x, |
2182 | gint y) |
2183 | { |
2184 | g_return_val_if_fail (CTK_IS_TEXT_VIEW (text_view), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return ((0)); } } while ( 0); |
2185 | g_return_val_if_fail (iter != NULL, FALSE)do { if ((iter != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "iter != NULL"); return ( (0)); } } while (0); |
2186 | |
2187 | ctk_text_view_ensure_layout (text_view); |
2188 | |
2189 | return ctk_text_layout_get_iter_at_position (text_view->priv->layout, iter, trailing, x, y); |
2190 | } |
2191 | |
2192 | /** |
2193 | * ctk_text_view_get_iter_location: |
2194 | * @text_view: a #CtkTextView |
2195 | * @iter: a #CtkTextIter |
2196 | * @location: (out): bounds of the character at @iter |
2197 | * |
2198 | * Gets a rectangle which roughly contains the character at @iter. |
2199 | * The rectangle position is in buffer coordinates; use |
2200 | * ctk_text_view_buffer_to_window_coords() to convert these |
2201 | * coordinates to coordinates for one of the windows in the text view. |
2202 | **/ |
2203 | void |
2204 | ctk_text_view_get_iter_location (CtkTextView *text_view, |
2205 | const CtkTextIter *iter, |
2206 | CdkRectangle *location) |
2207 | { |
2208 | g_return_if_fail (CTK_IS_TEXT_VIEW (text_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return; } } while (0); |
2209 | g_return_if_fail (ctk_text_iter_get_buffer (iter) == get_buffer (text_view))do { if ((ctk_text_iter_get_buffer (iter) == get_buffer (text_view ))) { } else { g_return_if_fail_warning ("Ctk", ((const char* ) (__func__)), "ctk_text_iter_get_buffer (iter) == get_buffer (text_view)" ); return; } } while (0); |
2210 | |
2211 | ctk_text_view_ensure_layout (text_view); |
2212 | |
2213 | ctk_text_layout_get_iter_location (text_view->priv->layout, iter, location); |
2214 | } |
2215 | |
2216 | /** |
2217 | * ctk_text_view_get_line_yrange: |
2218 | * @text_view: a #CtkTextView |
2219 | * @iter: a #CtkTextIter |
2220 | * @y: (out): return location for a y coordinate |
2221 | * @height: (out): return location for a height |
2222 | * |
2223 | * Gets the y coordinate of the top of the line containing @iter, |
2224 | * and the height of the line. The coordinate is a buffer coordinate; |
2225 | * convert to window coordinates with ctk_text_view_buffer_to_window_coords(). |
2226 | **/ |
2227 | void |
2228 | ctk_text_view_get_line_yrange (CtkTextView *text_view, |
2229 | const CtkTextIter *iter, |
2230 | gint *y, |
2231 | gint *height) |
2232 | { |
2233 | g_return_if_fail (CTK_IS_TEXT_VIEW (text_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return; } } while (0); |
2234 | g_return_if_fail (ctk_text_iter_get_buffer (iter) == get_buffer (text_view))do { if ((ctk_text_iter_get_buffer (iter) == get_buffer (text_view ))) { } else { g_return_if_fail_warning ("Ctk", ((const char* ) (__func__)), "ctk_text_iter_get_buffer (iter) == get_buffer (text_view)" ); return; } } while (0); |
2235 | |
2236 | ctk_text_view_ensure_layout (text_view); |
2237 | |
2238 | ctk_text_layout_get_line_yrange (text_view->priv->layout, |
2239 | iter, |
2240 | y, |
2241 | height); |
2242 | } |
2243 | |
2244 | /** |
2245 | * ctk_text_view_get_line_at_y: |
2246 | * @text_view: a #CtkTextView |
2247 | * @target_iter: (out): a #CtkTextIter |
2248 | * @y: a y coordinate |
2249 | * @line_top: (out): return location for top coordinate of the line |
2250 | * |
2251 | * Gets the #CtkTextIter at the start of the line containing |
2252 | * the coordinate @y. @y is in buffer coordinates, convert from |
2253 | * window coordinates with ctk_text_view_window_to_buffer_coords(). |
2254 | * If non-%NULL, @line_top will be filled with the coordinate of the top |
2255 | * edge of the line. |
2256 | **/ |
2257 | void |
2258 | ctk_text_view_get_line_at_y (CtkTextView *text_view, |
2259 | CtkTextIter *target_iter, |
2260 | gint y, |
2261 | gint *line_top) |
2262 | { |
2263 | g_return_if_fail (CTK_IS_TEXT_VIEW (text_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return; } } while (0); |
2264 | |
2265 | ctk_text_view_ensure_layout (text_view); |
2266 | |
2267 | ctk_text_layout_get_line_at_y (text_view->priv->layout, |
2268 | target_iter, |
2269 | y, |
2270 | line_top); |
2271 | } |
2272 | |
2273 | /* Same as ctk_text_view_scroll_to_iter but deal with |
2274 | * (top_margin / top_padding) and (bottom_margin / bottom_padding). |
2275 | * When with_border == TRUE and you scroll on the edges, |
2276 | * all borders are shown for the corresponding edge. |
2277 | * When with_border == FALSE, only left margin and right_margin |
2278 | * can be seen because they can be can be overwritten by tags. |
2279 | */ |
2280 | static gboolean |
2281 | _ctk_text_view_scroll_to_iter (CtkTextView *text_view, |
2282 | CtkTextIter *iter, |
2283 | gdouble within_margin, |
2284 | gboolean use_align, |
2285 | gdouble xalign, |
2286 | gdouble yalign, |
2287 | gboolean with_border) |
2288 | { |
2289 | CtkTextViewPrivate *priv = text_view->priv; |
2290 | CtkWidget *widget; |
2291 | |
2292 | CdkRectangle cursor; |
2293 | gint cursor_bottom; |
2294 | gint cursor_right; |
2295 | |
2296 | CdkRectangle screen; |
2297 | CdkRectangle screen_dest; |
2298 | |
2299 | gint screen_inner_left; |
2300 | gint screen_inner_right; |
2301 | gint screen_inner_top; |
2302 | gint screen_inner_bottom; |
2303 | |
2304 | gint border_xoffset = 0; |
2305 | gint border_yoffset = 0; |
2306 | gint within_margin_xoffset; |
2307 | gint within_margin_yoffset; |
2308 | |
2309 | gint buffer_bottom; |
2310 | gint buffer_right; |
2311 | |
2312 | gboolean retval = FALSE(0); |
2313 | |
2314 | /* FIXME why don't we do the validate-at-scroll-destination thing |
2315 | * from flush_scroll in this function? I think it wasn't done before |
2316 | * because changed_handler was screwed up, but I could be wrong. |
2317 | */ |
2318 | |
2319 | g_return_val_if_fail (CTK_IS_TEXT_VIEW (text_view), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return ((0)); } } while ( 0); |
2320 | g_return_val_if_fail (iter != NULL, FALSE)do { if ((iter != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "iter != NULL"); return ( (0)); } } while (0); |
2321 | g_return_val_if_fail (within_margin >= 0.0 && within_margin < 0.5, FALSE)do { if ((within_margin >= 0.0 && within_margin < 0.5)) { } else { g_return_if_fail_warning ("Ctk", ((const char *) (__func__)), "within_margin >= 0.0 && within_margin < 0.5" ); return ((0)); } } while (0); |
2322 | g_return_val_if_fail (xalign >= 0.0 && xalign <= 1.0, FALSE)do { if ((xalign >= 0.0 && xalign <= 1.0)) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__) ), "xalign >= 0.0 && xalign <= 1.0"); return (( 0)); } } while (0); |
2323 | g_return_val_if_fail (yalign >= 0.0 && yalign <= 1.0, FALSE)do { if ((yalign >= 0.0 && yalign <= 1.0)) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__) ), "yalign >= 0.0 && yalign <= 1.0"); return (( 0)); } } while (0); |
2324 | |
2325 | widget = CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))); |
2326 | |
2327 | DV(g_print(G_STRLOC"\n")); |
2328 | |
2329 | ctk_text_layout_get_iter_location (priv->layout, |
2330 | iter, |
2331 | &cursor); |
2332 | |
2333 | DV (g_print (" target cursor %d,%d %d x %d\n", cursor.x, cursor.y, cursor.width, cursor.height)); |
2334 | |
2335 | /* In each direction, *_border are the addition of *_padding and *_margin |
2336 | * |
2337 | * Vadjustment value: |
2338 | * (-priv->top_border) [top padding][top margin] (0) [text][bottom margin][bottom padding] |
2339 | * |
2340 | * Hadjustment value: |
2341 | * (-priv->left_padding) [left padding] (0) [left margin][text][right margin][right padding] |
2342 | * |
2343 | * Buffer coordinates: |
2344 | * on x: (0) [left margin][text][right margin] |
2345 | * on y: (0) [text] |
2346 | * |
2347 | * left margin and right margin are part of the x buffer coordinate |
2348 | * because they are part of the pango layout so that they can be |
2349 | * overwritten by tags. |
2350 | * |
2351 | * Canvas coordinates: |
2352 | * (the canvas is the virtual window where the content of the buffer is drawn ) |
2353 | * |
2354 | * on x: (-priv->left_padding) [left padding] (0) [left margin][text][right margin][right padding] |
2355 | * on y: (-priv->top_border) [top margin][top padding] (0) [text][bottom margin][bottom padding] |
2356 | * |
2357 | * (priv->xoffset, priv->yoffset) is the origin of the view (visible part of the canvas) |
2358 | * in canvas coordinates. |
2359 | * As you can see, canvas coordinates and buffer coordinates are compatible but the canvas |
2360 | * can be larger than the buffer depending of the border size. |
2361 | */ |
2362 | |
2363 | cursor_bottom = cursor.y + cursor.height; |
2364 | cursor_right = cursor.x + cursor.width; |
2365 | |
2366 | /* Current position of the view in canvas coordinates */ |
2367 | screen.x = priv->xoffset; |
2368 | screen.y = priv->yoffset; |
2369 | screen.width = SCREEN_WIDTH (widget)text_window_get_width (((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((widget)), ((ctk_text_view_get_type ()))) )))->priv->text_window); |
2370 | screen.height = SCREEN_HEIGHT (widget)text_window_get_height (((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((widget)), ((ctk_text_view_get_type ()))) )))->priv->text_window); |
2371 | |
2372 | within_margin_xoffset = screen.width * within_margin; |
2373 | within_margin_yoffset = screen.height * within_margin; |
2374 | |
2375 | screen_inner_left = screen.x + within_margin_xoffset; |
2376 | screen_inner_top = screen.y + within_margin_yoffset; |
2377 | screen_inner_right = screen.x + screen.width - within_margin_xoffset; |
2378 | screen_inner_bottom = screen.y + screen.height - within_margin_yoffset; |
2379 | |
2380 | buffer_bottom = priv->height - priv->bottom_border; |
2381 | buffer_right = priv->width - priv->right_margin - priv->left_padding - 1; |
2382 | |
2383 | screen_dest.x = screen.x; |
2384 | screen_dest.y = screen.y; |
2385 | screen_dest.width = screen.width - within_margin_xoffset * 2; |
2386 | screen_dest.height = screen.height - within_margin_yoffset * 2; |
2387 | |
2388 | /* Minimum authorised size check */ |
2389 | if (screen_dest.width < 1) |
2390 | screen_dest.width = 1; |
2391 | if (screen_dest.height < 1) |
2392 | screen_dest.height = 1; |
2393 | |
2394 | /* The alignment affects the point in the target character that we |
2395 | * choose to align. If we're doing right/bottom alignment, we align |
2396 | * the right/bottom edge of the character the mark is at; if we're |
2397 | * doing left/top we align the left/top edge of the character; if |
2398 | * we're doing center alignment we align the center of the |
2399 | * character. |
2400 | * |
2401 | * The differents cases handle on each direction: |
2402 | * 1. cursor outside of the inner area define by within_margin |
2403 | * 2. if use_align == TRUE, alignment with xalign and yalign |
2404 | * 3. scrolling on the edges dependent of with_border |
2405 | */ |
2406 | |
2407 | /* Vertical scroll */ |
2408 | if (use_align) |
2409 | { |
2410 | gint cursor_y_alignment_offset; |
2411 | |
2412 | cursor_y_alignment_offset = (cursor.height * yalign) - (screen_dest.height * yalign); |
2413 | screen_dest.y = cursor.y + cursor_y_alignment_offset - within_margin_yoffset; |
2414 | } |
2415 | else |
2416 | { |
2417 | /* move minimum to get onscreen, showing the |
2418 | * top_border or bottom_border when necessary |
2419 | */ |
2420 | if (cursor.y < screen_inner_top) |
2421 | { |
2422 | if (cursor.y == 0) |
2423 | border_yoffset = (with_border) ? priv->top_padding : 0; |
2424 | |
2425 | screen_dest.y = cursor.y - MAX (within_margin_yoffset, border_yoffset)(((within_margin_yoffset) > (border_yoffset)) ? (within_margin_yoffset ) : (border_yoffset)); |
2426 | } |
2427 | else if (cursor_bottom > screen_inner_bottom) |
2428 | { |
2429 | if (cursor_bottom == buffer_bottom - priv->top_border) |
2430 | border_yoffset = (with_border) ? priv->bottom_padding : 0; |
2431 | |
2432 | screen_dest.y = cursor_bottom - screen_dest.height + |
2433 | MAX (within_margin_yoffset, border_yoffset)(((within_margin_yoffset) > (border_yoffset)) ? (within_margin_yoffset ) : (border_yoffset)); |
2434 | } |
2435 | } |
2436 | |
2437 | if (screen_dest.y != screen.y) |
2438 | { |
2439 | ctk_adjustment_animate_to_value (priv->vadjustment, screen_dest.y + priv->top_border); |
2440 | |
2441 | DV (g_print (" vert increment %d\n", screen_dest.y - screen.y)); |
2442 | } |
2443 | |
2444 | /* Horizontal scroll */ |
2445 | |
2446 | if (use_align) |
2447 | { |
2448 | gint cursor_x_alignment_offset; |
2449 | |
2450 | cursor_x_alignment_offset = (cursor.width * xalign) - (screen_dest.width * xalign); |
2451 | screen_dest.x = cursor.x + cursor_x_alignment_offset - within_margin_xoffset; |
2452 | } |
2453 | else |
2454 | { |
2455 | /* move minimum to get onscreen, showing the |
2456 | * left_border or right_border when necessary |
2457 | */ |
2458 | if (cursor.x < screen_inner_left) |
2459 | { |
2460 | if (cursor.x == priv->left_margin) |
2461 | border_xoffset = (with_border) ? priv->left_padding : 0; |
2462 | |
2463 | screen_dest.x = cursor.x - MAX (within_margin_xoffset, border_xoffset)(((within_margin_xoffset) > (border_xoffset)) ? (within_margin_xoffset ) : (border_xoffset)); |
2464 | } |
2465 | else if (cursor_right >= screen_inner_right - 1) |
2466 | { |
2467 | if (cursor.x >= buffer_right - priv->right_padding) |
2468 | border_xoffset = (with_border) ? priv->right_padding : 0; |
2469 | |
2470 | screen_dest.x = cursor_right - screen_dest.width + |
2471 | MAX (within_margin_xoffset, border_xoffset)(((within_margin_xoffset) > (border_xoffset)) ? (within_margin_xoffset ) : (border_xoffset)) + 1; |
2472 | } |
2473 | } |
2474 | |
2475 | if (screen_dest.x != screen.x) |
2476 | { |
2477 | ctk_adjustment_animate_to_value (priv->hadjustment, screen_dest.x + priv->left_padding); |
2478 | |
2479 | DV (g_print (" horiz increment %d\n", screen_dest.x - screen.x)); |
2480 | } |
2481 | |
2482 | retval = (screen.y != screen_dest.y) || (screen.x != screen_dest.x); |
2483 | |
2484 | DV(g_print (">%s ("G_STRLOC")\n", retval ? "Actually scrolled" : "Didn't end up scrolling")); |
2485 | |
2486 | return retval; |
2487 | } |
2488 | |
2489 | /** |
2490 | * ctk_text_view_scroll_to_iter: |
2491 | * @text_view: a #CtkTextView |
2492 | * @iter: a #CtkTextIter |
2493 | * @within_margin: margin as a [0.0,0.5) fraction of screen size |
2494 | * @use_align: whether to use alignment arguments (if %FALSE, |
2495 | * just get the mark onscreen) |
2496 | * @xalign: horizontal alignment of mark within visible area |
2497 | * @yalign: vertical alignment of mark within visible area |
2498 | * |
2499 | * Scrolls @text_view so that @iter is on the screen in the position |
2500 | * indicated by @xalign and @yalign. An alignment of 0.0 indicates |
2501 | * left or top, 1.0 indicates right or bottom, 0.5 means center. |
2502 | * If @use_align is %FALSE, the text scrolls the minimal distance to |
2503 | * get the mark onscreen, possibly not scrolling at all. The effective |
2504 | * screen for purposes of this function is reduced by a margin of size |
2505 | * @within_margin. |
2506 | * |
2507 | * Note that this function uses the currently-computed height of the |
2508 | * lines in the text buffer. Line heights are computed in an idle |
2509 | * handler; so this function may not have the desired effect if it’s |
2510 | * called before the height computations. To avoid oddness, consider |
2511 | * using ctk_text_view_scroll_to_mark() which saves a point to be |
2512 | * scrolled to after line validation. |
2513 | * |
2514 | * Returns: %TRUE if scrolling occurred |
2515 | **/ |
2516 | gboolean |
2517 | ctk_text_view_scroll_to_iter (CtkTextView *text_view, |
2518 | CtkTextIter *iter, |
2519 | gdouble within_margin, |
2520 | gboolean use_align, |
2521 | gdouble xalign, |
2522 | gdouble yalign) |
2523 | { |
2524 | return _ctk_text_view_scroll_to_iter (text_view, |
2525 | iter, |
2526 | within_margin, |
2527 | use_align, |
2528 | xalign, |
2529 | yalign, |
2530 | FALSE(0)); |
2531 | } |
2532 | |
2533 | static void |
2534 | free_pending_scroll (CtkTextPendingScroll *scroll) |
2535 | { |
2536 | if (!ctk_text_mark_get_deleted (scroll->mark)) |
2537 | ctk_text_buffer_delete_mark (ctk_text_mark_get_buffer (scroll->mark), |
2538 | scroll->mark); |
2539 | g_object_unref (scroll->mark); |
2540 | g_slice_free (CtkTextPendingScroll, scroll)do { if (1) g_slice_free1 (sizeof (CtkTextPendingScroll), (scroll )); else (void) ((CtkTextPendingScroll*) 0 == (scroll)); } while (0); |
2541 | } |
2542 | |
2543 | static void |
2544 | cancel_pending_scroll (CtkTextView *text_view) |
2545 | { |
2546 | if (text_view->priv->pending_scroll) |
2547 | { |
2548 | free_pending_scroll (text_view->priv->pending_scroll); |
2549 | text_view->priv->pending_scroll = NULL((void*)0); |
2550 | } |
2551 | } |
2552 | |
2553 | static void |
2554 | ctk_text_view_queue_scroll (CtkTextView *text_view, |
2555 | CtkTextMark *mark, |
2556 | gdouble within_margin, |
2557 | gboolean use_align, |
2558 | gdouble xalign, |
2559 | gdouble yalign) |
2560 | { |
2561 | CtkTextIter iter; |
2562 | CtkTextPendingScroll *scroll; |
2563 | |
2564 | DV(g_print(G_STRLOC"\n")); |
2565 | |
2566 | scroll = g_slice_new (CtkTextPendingScroll)((CtkTextPendingScroll*) g_slice_alloc (sizeof (CtkTextPendingScroll ))); |
2567 | |
2568 | scroll->within_margin = within_margin; |
2569 | scroll->use_align = use_align; |
2570 | scroll->xalign = xalign; |
2571 | scroll->yalign = yalign; |
2572 | |
2573 | ctk_text_buffer_get_iter_at_mark (get_buffer (text_view), &iter, mark); |
2574 | |
2575 | scroll->mark = ctk_text_buffer_create_mark (get_buffer (text_view), |
2576 | NULL((void*)0), |
2577 | &iter, |
2578 | ctk_text_mark_get_left_gravity (mark)); |
2579 | |
2580 | g_object_ref (scroll->mark)((__typeof__ (scroll->mark)) (g_object_ref) (scroll->mark )); |
2581 | |
2582 | cancel_pending_scroll (text_view); |
2583 | |
2584 | text_view->priv->pending_scroll = scroll; |
2585 | } |
2586 | |
2587 | static gboolean |
2588 | ctk_text_view_flush_scroll (CtkTextView *text_view) |
2589 | { |
2590 | CtkAllocation allocation; |
2591 | CtkTextIter iter; |
2592 | CtkTextPendingScroll *scroll; |
2593 | gboolean retval; |
2594 | CtkWidget *widget; |
2595 | |
2596 | widget = CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))); |
2597 | |
2598 | DV(g_print(G_STRLOC"\n")); |
2599 | |
2600 | if (text_view->priv->pending_scroll == NULL((void*)0)) |
2601 | { |
2602 | DV (g_print ("in flush scroll, no pending scroll\n")); |
2603 | return FALSE(0); |
2604 | } |
2605 | |
2606 | scroll = text_view->priv->pending_scroll; |
2607 | |
2608 | /* avoid recursion */ |
2609 | text_view->priv->pending_scroll = NULL((void*)0); |
2610 | |
2611 | ctk_text_buffer_get_iter_at_mark (get_buffer (text_view), &iter, scroll->mark); |
2612 | |
2613 | /* Validate area around the scroll destination, so the adjustment |
2614 | * can meaningfully point into that area. We must validate |
2615 | * enough area to be sure that after we scroll, everything onscreen |
2616 | * is valid; otherwise, validation will maintain the first para |
2617 | * in one place, but may push the target iter off the bottom of |
2618 | * the screen. |
2619 | */ |
2620 | DV(g_print (">Validating scroll destination ("G_STRLOC")\n")); |
2621 | ctk_widget_get_allocation (widget, &allocation); |
2622 | ctk_text_layout_validate_yrange (text_view->priv->layout, &iter, |
2623 | -(allocation.height * 2), |
2624 | allocation.height * 2); |
2625 | |
2626 | DV(g_print (">Done validating scroll destination ("G_STRLOC")\n")); |
2627 | |
2628 | /* Ensure we have updated width/height */ |
2629 | ctk_text_view_update_adjustments (text_view); |
2630 | |
2631 | retval = _ctk_text_view_scroll_to_iter (text_view, |
2632 | &iter, |
2633 | scroll->within_margin, |
2634 | scroll->use_align, |
2635 | scroll->xalign, |
2636 | scroll->yalign, |
2637 | TRUE(!(0))); |
2638 | |
2639 | if (text_view->priv->text_handle) |
2640 | ctk_text_view_update_handles (text_view, |
2641 | _ctk_text_handle_get_mode (text_view->priv->text_handle)); |
2642 | |
2643 | free_pending_scroll (scroll); |
2644 | |
2645 | return retval; |
2646 | } |
2647 | |
2648 | static void |
2649 | ctk_text_view_update_adjustments (CtkTextView *text_view) |
2650 | { |
2651 | CtkTextViewPrivate *priv; |
2652 | gint width = 0, height = 0; |
2653 | |
2654 | DV(g_print(">Updating adjustments ("G_STRLOC")\n")); |
2655 | |
2656 | priv = text_view->priv; |
2657 | |
2658 | if (priv->layout) |
2659 | ctk_text_layout_get_size (priv->layout, &width, &height); |
2660 | |
2661 | /* Make room for the cursor after the last character in the widest line */ |
2662 | width += SPACE_FOR_CURSOR1; |
2663 | height += priv->top_border + priv->bottom_border; |
2664 | |
2665 | if (priv->width != width || priv->height != height) |
2666 | { |
2667 | if (priv->width != width) |
2668 | priv->width_changed = TRUE(!(0)); |
2669 | |
2670 | priv->width = width; |
2671 | priv->height = height; |
2672 | |
2673 | ctk_text_view_set_hadjustment_values (text_view); |
2674 | ctk_text_view_set_vadjustment_values (text_view); |
2675 | } |
2676 | } |
2677 | |
2678 | static void |
2679 | ctk_text_view_update_layout_width (CtkTextView *text_view) |
2680 | { |
2681 | DV(g_print(">Updating layout width ("G_STRLOC")\n")); |
2682 | |
2683 | ctk_text_view_ensure_layout (text_view); |
2684 | |
2685 | ctk_text_layout_set_screen_width (text_view->priv->layout, |
2686 | MAX (1, SCREEN_WIDTH (text_view) - SPACE_FOR_CURSOR)(((1) > (text_window_get_width (((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((text_view)), ( (ctk_text_view_get_type ()))))))->priv->text_window) - 1 )) ? (1) : (text_window_get_width (((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((text_view)), ( (ctk_text_view_get_type ()))))))->priv->text_window) - 1 ))); |
2687 | } |
2688 | |
2689 | static void |
2690 | ctk_text_view_update_im_spot_location (CtkTextView *text_view) |
2691 | { |
2692 | CdkRectangle area; |
2693 | |
2694 | if (text_view->priv->layout == NULL((void*)0)) |
2695 | return; |
2696 | |
2697 | ctk_text_view_get_cursor_locations (text_view, NULL((void*)0), &area, NULL((void*)0)); |
2698 | |
2699 | area.x -= text_view->priv->xoffset; |
2700 | area.y -= text_view->priv->yoffset; |
2701 | |
2702 | /* Width returned by Pango indicates direction of cursor, |
2703 | * by its sign more than the size of cursor. |
2704 | */ |
2705 | area.width = 0; |
2706 | |
2707 | ctk_im_context_set_cursor_location (text_view->priv->im_context, &area); |
2708 | } |
2709 | |
2710 | static gboolean |
2711 | do_update_im_spot_location (gpointer text_view) |
2712 | { |
2713 | CtkTextViewPrivate *priv; |
2714 | |
2715 | priv = CTK_TEXT_VIEW (text_view)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_text_view_get_type ()))))))->priv; |
2716 | priv->im_spot_idle = 0; |
2717 | |
2718 | ctk_text_view_update_im_spot_location (text_view); |
2719 | return FALSE(0); |
2720 | } |
2721 | |
2722 | static void |
2723 | queue_update_im_spot_location (CtkTextView *text_view) |
2724 | { |
2725 | CtkTextViewPrivate *priv; |
2726 | |
2727 | priv = text_view->priv; |
2728 | |
2729 | /* Use priority a little higher than CTK_TEXT_VIEW_PRIORITY_VALIDATE, |
2730 | * so we don't wait until the entire buffer has been validated. */ |
2731 | if (!priv->im_spot_idle) |
2732 | { |
2733 | priv->im_spot_idle = cdk_threads_add_idle_full (CTK_TEXT_VIEW_PRIORITY_VALIDATE((100 + 20) + 5) - 1, |
2734 | do_update_im_spot_location, |
2735 | text_view, |
2736 | NULL((void*)0)); |
2737 | g_source_set_name_by_id (priv->im_spot_idle, "[ctk+] do_update_im_spot_location"); |
2738 | } |
2739 | } |
2740 | |
2741 | static void |
2742 | flush_update_im_spot_location (CtkTextView *text_view) |
2743 | { |
2744 | CtkTextViewPrivate *priv; |
2745 | |
2746 | priv = text_view->priv; |
2747 | |
2748 | if (priv->im_spot_idle) |
2749 | { |
2750 | g_source_remove (priv->im_spot_idle); |
2751 | priv->im_spot_idle = 0; |
2752 | ctk_text_view_update_im_spot_location (text_view); |
2753 | } |
2754 | } |
2755 | |
2756 | /** |
2757 | * ctk_text_view_scroll_to_mark: |
2758 | * @text_view: a #CtkTextView |
2759 | * @mark: a #CtkTextMark |
2760 | * @within_margin: margin as a [0.0,0.5) fraction of screen size |
2761 | * @use_align: whether to use alignment arguments (if %FALSE, just |
2762 | * get the mark onscreen) |
2763 | * @xalign: horizontal alignment of mark within visible area |
2764 | * @yalign: vertical alignment of mark within visible area |
2765 | * |
2766 | * Scrolls @text_view so that @mark is on the screen in the position |
2767 | * indicated by @xalign and @yalign. An alignment of 0.0 indicates |
2768 | * left or top, 1.0 indicates right or bottom, 0.5 means center. |
2769 | * If @use_align is %FALSE, the text scrolls the minimal distance to |
2770 | * get the mark onscreen, possibly not scrolling at all. The effective |
2771 | * screen for purposes of this function is reduced by a margin of size |
2772 | * @within_margin. |
2773 | **/ |
2774 | void |
2775 | ctk_text_view_scroll_to_mark (CtkTextView *text_view, |
2776 | CtkTextMark *mark, |
2777 | gdouble within_margin, |
2778 | gboolean use_align, |
2779 | gdouble xalign, |
2780 | gdouble yalign) |
2781 | { |
2782 | g_return_if_fail (CTK_IS_TEXT_VIEW (text_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return; } } while (0); |
2783 | g_return_if_fail (CTK_IS_TEXT_MARK (mark))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((mark)); GType __t = ((ctk_text_mark_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_TEXT_MARK (mark)"); return; } } while (0); |
2784 | g_return_if_fail (within_margin >= 0.0 && within_margin < 0.5)do { if ((within_margin >= 0.0 && within_margin < 0.5)) { } else { g_return_if_fail_warning ("Ctk", ((const char *) (__func__)), "within_margin >= 0.0 && within_margin < 0.5" ); return; } } while (0); |
2785 | g_return_if_fail (xalign >= 0.0 && xalign <= 1.0)do { if ((xalign >= 0.0 && xalign <= 1.0)) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__) ), "xalign >= 0.0 && xalign <= 1.0"); return; } } while (0); |
2786 | g_return_if_fail (yalign >= 0.0 && yalign <= 1.0)do { if ((yalign >= 0.0 && yalign <= 1.0)) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__) ), "yalign >= 0.0 && yalign <= 1.0"); return; } } while (0); |
2787 | |
2788 | /* We need to verify that the buffer contains the mark, otherwise this |
2789 | * can lead to data structure corruption later on. |
2790 | */ |
2791 | g_return_if_fail (get_buffer (text_view) == ctk_text_mark_get_buffer (mark))do { if ((get_buffer (text_view) == ctk_text_mark_get_buffer ( mark))) { } else { g_return_if_fail_warning ("Ctk", ((const char *) (__func__)), "get_buffer (text_view) == ctk_text_mark_get_buffer (mark)" ); return; } } while (0); |
2792 | |
2793 | ctk_text_view_queue_scroll (text_view, mark, |
2794 | within_margin, |
2795 | use_align, |
2796 | xalign, |
2797 | yalign); |
2798 | |
2799 | /* If no validation is pending, we need to go ahead and force an |
2800 | * immediate scroll. |
2801 | */ |
2802 | if (text_view->priv->layout && |
2803 | ctk_text_layout_is_valid (text_view->priv->layout)) |
2804 | ctk_text_view_flush_scroll (text_view); |
2805 | } |
2806 | |
2807 | /** |
2808 | * ctk_text_view_scroll_mark_onscreen: |
2809 | * @text_view: a #CtkTextView |
2810 | * @mark: a mark in the buffer for @text_view |
2811 | * |
2812 | * Scrolls @text_view the minimum distance such that @mark is contained |
2813 | * within the visible area of the widget. |
2814 | **/ |
2815 | void |
2816 | ctk_text_view_scroll_mark_onscreen (CtkTextView *text_view, |
2817 | CtkTextMark *mark) |
2818 | { |
2819 | g_return_if_fail (CTK_IS_TEXT_VIEW (text_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return; } } while (0); |
2820 | g_return_if_fail (CTK_IS_TEXT_MARK (mark))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((mark)); GType __t = ((ctk_text_mark_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_TEXT_MARK (mark)"); return; } } while (0); |
2821 | |
2822 | /* We need to verify that the buffer contains the mark, otherwise this |
2823 | * can lead to data structure corruption later on. |
2824 | */ |
2825 | g_return_if_fail (get_buffer (text_view) == ctk_text_mark_get_buffer (mark))do { if ((get_buffer (text_view) == ctk_text_mark_get_buffer ( mark))) { } else { g_return_if_fail_warning ("Ctk", ((const char *) (__func__)), "get_buffer (text_view) == ctk_text_mark_get_buffer (mark)" ); return; } } while (0); |
2826 | |
2827 | ctk_text_view_scroll_to_mark (text_view, mark, 0.0, FALSE(0), 0.0, 0.0); |
2828 | } |
2829 | |
2830 | static gboolean |
2831 | clamp_iter_onscreen (CtkTextView *text_view, CtkTextIter *iter) |
2832 | { |
2833 | CdkRectangle visible_rect; |
2834 | ctk_text_view_get_visible_rect (text_view, &visible_rect); |
2835 | |
2836 | return ctk_text_layout_clamp_iter_to_vrange (text_view->priv->layout, iter, |
2837 | visible_rect.y, |
2838 | visible_rect.y + visible_rect.height); |
2839 | } |
2840 | |
2841 | /** |
2842 | * ctk_text_view_move_mark_onscreen: |
2843 | * @text_view: a #CtkTextView |
2844 | * @mark: a #CtkTextMark |
2845 | * |
2846 | * Moves a mark within the buffer so that it's |
2847 | * located within the currently-visible text area. |
2848 | * |
2849 | * Returns: %TRUE if the mark moved (wasn’t already onscreen) |
2850 | **/ |
2851 | gboolean |
2852 | ctk_text_view_move_mark_onscreen (CtkTextView *text_view, |
2853 | CtkTextMark *mark) |
2854 | { |
2855 | CtkTextIter iter; |
2856 | |
2857 | g_return_val_if_fail (CTK_IS_TEXT_VIEW (text_view), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return ((0)); } } while ( 0); |
2858 | g_return_val_if_fail (mark != NULL, FALSE)do { if ((mark != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "mark != NULL"); return ( (0)); } } while (0); |
2859 | |
2860 | ctk_text_buffer_get_iter_at_mark (get_buffer (text_view), &iter, mark); |
2861 | |
2862 | if (clamp_iter_onscreen (text_view, &iter)) |
2863 | { |
2864 | ctk_text_buffer_move_mark (get_buffer (text_view), mark, &iter); |
2865 | return TRUE(!(0)); |
2866 | } |
2867 | else |
2868 | return FALSE(0); |
2869 | } |
2870 | |
2871 | /** |
2872 | * ctk_text_view_get_visible_rect: |
2873 | * @text_view: a #CtkTextView |
2874 | * @visible_rect: (out): rectangle to fill |
2875 | * |
2876 | * Fills @visible_rect with the currently-visible |
2877 | * region of the buffer, in buffer coordinates. Convert to window coordinates |
2878 | * with ctk_text_view_buffer_to_window_coords(). |
2879 | **/ |
2880 | void |
2881 | ctk_text_view_get_visible_rect (CtkTextView *text_view, |
2882 | CdkRectangle *visible_rect) |
2883 | { |
2884 | CtkWidget *widget; |
2885 | |
2886 | g_return_if_fail (CTK_IS_TEXT_VIEW (text_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return; } } while (0); |
2887 | |
2888 | widget = CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))); |
2889 | |
2890 | if (visible_rect) |
2891 | { |
2892 | visible_rect->x = text_view->priv->xoffset; |
2893 | visible_rect->y = text_view->priv->yoffset; |
2894 | visible_rect->width = SCREEN_WIDTH (widget)text_window_get_width (((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((widget)), ((ctk_text_view_get_type ()))) )))->priv->text_window); |
2895 | visible_rect->height = SCREEN_HEIGHT (widget)text_window_get_height (((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((widget)), ((ctk_text_view_get_type ()))) )))->priv->text_window); |
2896 | |
2897 | DV(g_print(" visible rect: %d,%d %d x %d\n", |
2898 | visible_rect->x, |
2899 | visible_rect->y, |
2900 | visible_rect->width, |
2901 | visible_rect->height)); |
2902 | } |
2903 | } |
2904 | |
2905 | /** |
2906 | * ctk_text_view_set_wrap_mode: |
2907 | * @text_view: a #CtkTextView |
2908 | * @wrap_mode: a #CtkWrapMode |
2909 | * |
2910 | * Sets the line wrapping for the view. |
2911 | **/ |
2912 | void |
2913 | ctk_text_view_set_wrap_mode (CtkTextView *text_view, |
2914 | CtkWrapMode wrap_mode) |
2915 | { |
2916 | CtkTextViewPrivate *priv; |
2917 | |
2918 | g_return_if_fail (CTK_IS_TEXT_VIEW (text_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return; } } while (0); |
2919 | |
2920 | priv = text_view->priv; |
2921 | |
2922 | if (priv->wrap_mode != wrap_mode) |
2923 | { |
2924 | priv->wrap_mode = wrap_mode; |
2925 | |
2926 | if (priv->layout && priv->layout->default_style) |
2927 | { |
2928 | priv->layout->default_style->wrap_mode = wrap_mode; |
2929 | ctk_text_layout_default_style_changed (priv->layout); |
2930 | } |
2931 | g_object_notify (G_OBJECT (text_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), (((GType) ((20) << (2)))))))), "wrap-mode"); |
2932 | } |
2933 | } |
2934 | |
2935 | /** |
2936 | * ctk_text_view_get_wrap_mode: |
2937 | * @text_view: a #CtkTextView |
2938 | * |
2939 | * Gets the line wrapping for the view. |
2940 | * |
2941 | * Returns: the line wrap setting |
2942 | **/ |
2943 | CtkWrapMode |
2944 | ctk_text_view_get_wrap_mode (CtkTextView *text_view) |
2945 | { |
2946 | g_return_val_if_fail (CTK_IS_TEXT_VIEW (text_view), CTK_WRAP_NONE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return (CTK_WRAP_NONE); } } while (0); |
2947 | |
2948 | return text_view->priv->wrap_mode; |
2949 | } |
2950 | |
2951 | /** |
2952 | * ctk_text_view_set_editable: |
2953 | * @text_view: a #CtkTextView |
2954 | * @setting: whether it’s editable |
2955 | * |
2956 | * Sets the default editability of the #CtkTextView. You can override |
2957 | * this default setting with tags in the buffer, using the “editable” |
2958 | * attribute of tags. |
2959 | **/ |
2960 | void |
2961 | ctk_text_view_set_editable (CtkTextView *text_view, |
2962 | gboolean setting) |
2963 | { |
2964 | CtkTextViewPrivate *priv; |
2965 | |
2966 | g_return_if_fail (CTK_IS_TEXT_VIEW (text_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return; } } while (0); |
2967 | |
2968 | priv = text_view->priv; |
2969 | setting = setting != FALSE(0); |
2970 | |
2971 | if (priv->editable != setting) |
2972 | { |
2973 | if (!setting) |
2974 | { |
2975 | ctk_text_view_reset_im_context(text_view); |
2976 | if (ctk_widget_has_focus (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))))) |
2977 | ctk_im_context_focus_out (priv->im_context); |
2978 | } |
2979 | |
2980 | priv->editable = setting; |
2981 | |
2982 | if (setting && ctk_widget_has_focus (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))))) |
2983 | ctk_im_context_focus_in (priv->im_context); |
2984 | |
2985 | if (priv->layout && priv->layout->default_style) |
2986 | { |
2987 | ctk_text_layout_set_overwrite_mode (priv->layout, |
2988 | priv->overwrite_mode && priv->editable); |
2989 | priv->layout->default_style->editable = priv->editable; |
2990 | ctk_text_layout_default_style_changed (priv->layout); |
2991 | } |
2992 | |
2993 | g_object_notify (G_OBJECT (text_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), (((GType) ((20) << (2)))))))), "editable"); |
2994 | } |
2995 | } |
2996 | |
2997 | /** |
2998 | * ctk_text_view_get_editable: |
2999 | * @text_view: a #CtkTextView |
3000 | * |
3001 | * Returns the default editability of the #CtkTextView. Tags in the |
3002 | * buffer may override this setting for some ranges of text. |
3003 | * |
3004 | * Returns: whether text is editable by default |
3005 | **/ |
3006 | gboolean |
3007 | ctk_text_view_get_editable (CtkTextView *text_view) |
3008 | { |
3009 | g_return_val_if_fail (CTK_IS_TEXT_VIEW (text_view), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return ((0)); } } while ( 0); |
3010 | |
3011 | return text_view->priv->editable; |
3012 | } |
3013 | |
3014 | /** |
3015 | * ctk_text_view_set_pixels_above_lines: |
3016 | * @text_view: a #CtkTextView |
3017 | * @pixels_above_lines: pixels above paragraphs |
3018 | * |
3019 | * Sets the default number of blank pixels above paragraphs in @text_view. |
3020 | * Tags in the buffer for @text_view may override the defaults. |
3021 | **/ |
3022 | void |
3023 | ctk_text_view_set_pixels_above_lines (CtkTextView *text_view, |
3024 | gint pixels_above_lines) |
3025 | { |
3026 | CtkTextViewPrivate *priv; |
3027 | |
3028 | g_return_if_fail (CTK_IS_TEXT_VIEW (text_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return; } } while (0); |
3029 | |
3030 | priv = text_view->priv; |
3031 | |
3032 | if (priv->pixels_above_lines != pixels_above_lines) |
3033 | { |
3034 | priv->pixels_above_lines = pixels_above_lines; |
3035 | |
3036 | if (priv->layout && priv->layout->default_style) |
3037 | { |
3038 | priv->layout->default_style->pixels_above_lines = pixels_above_lines; |
3039 | ctk_text_layout_default_style_changed (priv->layout); |
3040 | } |
3041 | |
3042 | g_object_notify (G_OBJECT (text_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), (((GType) ((20) << (2)))))))), "pixels-above-lines"); |
3043 | } |
3044 | } |
3045 | |
3046 | /** |
3047 | * ctk_text_view_get_pixels_above_lines: |
3048 | * @text_view: a #CtkTextView |
3049 | * |
3050 | * Gets the default number of pixels to put above paragraphs. |
3051 | * Adding this function with ctk_text_view_get_pixels_below_lines() |
3052 | * is equal to the line space between each paragraph. |
3053 | * |
3054 | * Returns: default number of pixels above paragraphs |
3055 | **/ |
3056 | gint |
3057 | ctk_text_view_get_pixels_above_lines (CtkTextView *text_view) |
3058 | { |
3059 | g_return_val_if_fail (CTK_IS_TEXT_VIEW (text_view), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return (0); } } while (0 ); |
3060 | |
3061 | return text_view->priv->pixels_above_lines; |
3062 | } |
3063 | |
3064 | /** |
3065 | * ctk_text_view_set_pixels_below_lines: |
3066 | * @text_view: a #CtkTextView |
3067 | * @pixels_below_lines: pixels below paragraphs |
3068 | * |
3069 | * Sets the default number of pixels of blank space |
3070 | * to put below paragraphs in @text_view. May be overridden |
3071 | * by tags applied to @text_view’s buffer. |
3072 | **/ |
3073 | void |
3074 | ctk_text_view_set_pixels_below_lines (CtkTextView *text_view, |
3075 | gint pixels_below_lines) |
3076 | { |
3077 | CtkTextViewPrivate *priv; |
3078 | |
3079 | g_return_if_fail (CTK_IS_TEXT_VIEW (text_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return; } } while (0); |
3080 | |
3081 | priv = text_view->priv; |
3082 | |
3083 | if (priv->pixels_below_lines != pixels_below_lines) |
3084 | { |
3085 | priv->pixels_below_lines = pixels_below_lines; |
3086 | |
3087 | if (priv->layout && priv->layout->default_style) |
3088 | { |
3089 | priv->layout->default_style->pixels_below_lines = pixels_below_lines; |
3090 | ctk_text_layout_default_style_changed (priv->layout); |
3091 | } |
3092 | |
3093 | g_object_notify (G_OBJECT (text_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), (((GType) ((20) << (2)))))))), "pixels-below-lines"); |
3094 | } |
3095 | } |
3096 | |
3097 | /** |
3098 | * ctk_text_view_get_pixels_below_lines: |
3099 | * @text_view: a #CtkTextView |
3100 | * |
3101 | * Gets the value set by ctk_text_view_set_pixels_below_lines(). |
3102 | * |
3103 | * The line space is the sum of the value returned by this function and the |
3104 | * value returned by ctk_text_view_get_pixels_above_lines(). |
3105 | * |
3106 | * Returns: default number of blank pixels below paragraphs |
3107 | **/ |
3108 | gint |
3109 | ctk_text_view_get_pixels_below_lines (CtkTextView *text_view) |
3110 | { |
3111 | g_return_val_if_fail (CTK_IS_TEXT_VIEW (text_view), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return (0); } } while (0 ); |
3112 | |
3113 | return text_view->priv->pixels_below_lines; |
3114 | } |
3115 | |
3116 | /** |
3117 | * ctk_text_view_set_pixels_inside_wrap: |
3118 | * @text_view: a #CtkTextView |
3119 | * @pixels_inside_wrap: default number of pixels between wrapped lines |
3120 | * |
3121 | * Sets the default number of pixels of blank space to leave between |
3122 | * display/wrapped lines within a paragraph. May be overridden by |
3123 | * tags in @text_view’s buffer. |
3124 | **/ |
3125 | void |
3126 | ctk_text_view_set_pixels_inside_wrap (CtkTextView *text_view, |
3127 | gint pixels_inside_wrap) |
3128 | { |
3129 | CtkTextViewPrivate *priv; |
3130 | |
3131 | g_return_if_fail (CTK_IS_TEXT_VIEW (text_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return; } } while (0); |
3132 | |
3133 | priv = text_view->priv; |
3134 | |
3135 | if (priv->pixels_inside_wrap != pixels_inside_wrap) |
3136 | { |
3137 | priv->pixels_inside_wrap = pixels_inside_wrap; |
3138 | |
3139 | if (priv->layout && priv->layout->default_style) |
3140 | { |
3141 | priv->layout->default_style->pixels_inside_wrap = pixels_inside_wrap; |
3142 | ctk_text_layout_default_style_changed (priv->layout); |
3143 | } |
3144 | |
3145 | g_object_notify (G_OBJECT (text_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), (((GType) ((20) << (2)))))))), "pixels-inside-wrap"); |
3146 | } |
3147 | } |
3148 | |
3149 | /** |
3150 | * ctk_text_view_get_pixels_inside_wrap: |
3151 | * @text_view: a #CtkTextView |
3152 | * |
3153 | * Gets the value set by ctk_text_view_set_pixels_inside_wrap(). |
3154 | * |
3155 | * Returns: default number of pixels of blank space between wrapped lines |
3156 | **/ |
3157 | gint |
3158 | ctk_text_view_get_pixels_inside_wrap (CtkTextView *text_view) |
3159 | { |
3160 | g_return_val_if_fail (CTK_IS_TEXT_VIEW (text_view), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return (0); } } while (0 ); |
3161 | |
3162 | return text_view->priv->pixels_inside_wrap; |
3163 | } |
3164 | |
3165 | /** |
3166 | * ctk_text_view_set_justification: |
3167 | * @text_view: a #CtkTextView |
3168 | * @justification: justification |
3169 | * |
3170 | * Sets the default justification of text in @text_view. |
3171 | * Tags in the view’s buffer may override the default. |
3172 | * |
3173 | **/ |
3174 | void |
3175 | ctk_text_view_set_justification (CtkTextView *text_view, |
3176 | CtkJustification justification) |
3177 | { |
3178 | CtkTextViewPrivate *priv; |
3179 | |
3180 | g_return_if_fail (CTK_IS_TEXT_VIEW (text_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return; } } while (0); |
3181 | |
3182 | priv = text_view->priv; |
3183 | |
3184 | if (priv->justify != justification) |
3185 | { |
3186 | priv->justify = justification; |
3187 | |
3188 | if (priv->layout && priv->layout->default_style) |
3189 | { |
3190 | priv->layout->default_style->justification = justification; |
3191 | ctk_text_layout_default_style_changed (priv->layout); |
3192 | } |
3193 | |
3194 | g_object_notify (G_OBJECT (text_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), (((GType) ((20) << (2)))))))), "justification"); |
3195 | } |
3196 | } |
3197 | |
3198 | /** |
3199 | * ctk_text_view_get_justification: |
3200 | * @text_view: a #CtkTextView |
3201 | * |
3202 | * Gets the default justification of paragraphs in @text_view. |
3203 | * Tags in the buffer may override the default. |
3204 | * |
3205 | * Returns: default justification |
3206 | **/ |
3207 | CtkJustification |
3208 | ctk_text_view_get_justification (CtkTextView *text_view) |
3209 | { |
3210 | g_return_val_if_fail (CTK_IS_TEXT_VIEW (text_view), CTK_JUSTIFY_LEFT)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return (CTK_JUSTIFY_LEFT ); } } while (0); |
3211 | |
3212 | return text_view->priv->justify; |
3213 | } |
3214 | |
3215 | /** |
3216 | * ctk_text_view_set_left_margin: |
3217 | * @text_view: a #CtkTextView |
3218 | * @left_margin: left margin in pixels |
3219 | * |
3220 | * Sets the default left margin for text in @text_view. |
3221 | * Tags in the buffer may override the default. |
3222 | * |
3223 | * Note that this function is confusingly named. |
3224 | * In CSS terms, the value set here is padding. |
3225 | */ |
3226 | void |
3227 | ctk_text_view_set_left_margin (CtkTextView *text_view, |
3228 | gint left_margin) |
3229 | { |
3230 | CtkTextViewPrivate *priv = text_view->priv; |
3231 | |
3232 | g_return_if_fail (CTK_IS_TEXT_VIEW (text_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return; } } while (0); |
3233 | |
3234 | if (priv->left_margin != left_margin) |
3235 | { |
3236 | priv->left_margin = left_margin; |
3237 | priv->left_border = left_margin + priv->left_padding; |
3238 | |
3239 | if (priv->layout && priv->layout->default_style) |
3240 | { |
3241 | priv->layout->default_style->left_margin = left_margin; |
3242 | ctk_text_layout_default_style_changed (priv->layout); |
3243 | } |
3244 | |
3245 | g_object_notify (G_OBJECT (text_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), (((GType) ((20) << (2)))))))), "left-margin"); |
3246 | } |
3247 | } |
3248 | |
3249 | /** |
3250 | * ctk_text_view_get_left_margin: |
3251 | * @text_view: a #CtkTextView |
3252 | * |
3253 | * Gets the default left margin size of paragraphs in the @text_view. |
3254 | * Tags in the buffer may override the default. |
3255 | * |
3256 | * Returns: left margin in pixels |
3257 | */ |
3258 | gint |
3259 | ctk_text_view_get_left_margin (CtkTextView *text_view) |
3260 | { |
3261 | g_return_val_if_fail (CTK_IS_TEXT_VIEW (text_view), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return (0); } } while (0 ); |
3262 | |
3263 | return text_view->priv->left_margin; |
3264 | } |
3265 | |
3266 | /** |
3267 | * ctk_text_view_set_right_margin: |
3268 | * @text_view: a #CtkTextView |
3269 | * @right_margin: right margin in pixels |
3270 | * |
3271 | * Sets the default right margin for text in the text view. |
3272 | * Tags in the buffer may override the default. |
3273 | * |
3274 | * Note that this function is confusingly named. |
3275 | * In CSS terms, the value set here is padding. |
3276 | */ |
3277 | void |
3278 | ctk_text_view_set_right_margin (CtkTextView *text_view, |
3279 | gint right_margin) |
3280 | { |
3281 | CtkTextViewPrivate *priv = text_view->priv; |
3282 | |
3283 | g_return_if_fail (CTK_IS_TEXT_VIEW (text_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return; } } while (0); |
3284 | |
3285 | if (priv->right_margin != right_margin) |
3286 | { |
3287 | priv->right_margin = right_margin; |
3288 | priv->right_border = right_margin + priv->right_padding; |
3289 | |
3290 | if (priv->layout && priv->layout->default_style) |
3291 | { |
3292 | priv->layout->default_style->right_margin = right_margin; |
3293 | ctk_text_layout_default_style_changed (priv->layout); |
3294 | } |
3295 | |
3296 | g_object_notify (G_OBJECT (text_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), (((GType) ((20) << (2)))))))), "right-margin"); |
3297 | } |
3298 | } |
3299 | |
3300 | /** |
3301 | * ctk_text_view_get_right_margin: |
3302 | * @text_view: a #CtkTextView |
3303 | * |
3304 | * Gets the default right margin for text in @text_view. Tags |
3305 | * in the buffer may override the default. |
3306 | * |
3307 | * Returns: right margin in pixels |
3308 | */ |
3309 | gint |
3310 | ctk_text_view_get_right_margin (CtkTextView *text_view) |
3311 | { |
3312 | g_return_val_if_fail (CTK_IS_TEXT_VIEW (text_view), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return (0); } } while (0 ); |
3313 | |
3314 | return text_view->priv->right_margin; |
3315 | } |
3316 | |
3317 | /** |
3318 | * ctk_text_view_set_top_margin: |
3319 | * @text_view: a #CtkTextView |
3320 | * @top_margin: top margin in pixels |
3321 | * |
3322 | * Sets the top margin for text in @text_view. |
3323 | * |
3324 | * Note that this function is confusingly named. |
3325 | * In CSS terms, the value set here is padding. |
3326 | * |
3327 | * Since: 3.18 |
3328 | */ |
3329 | void |
3330 | ctk_text_view_set_top_margin (CtkTextView *text_view, |
3331 | gint top_margin) |
3332 | { |
3333 | CtkTextViewPrivate *priv = text_view->priv; |
3334 | |
3335 | g_return_if_fail (CTK_IS_TEXT_VIEW (text_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return; } } while (0); |
3336 | |
3337 | if (priv->top_margin != top_margin) |
3338 | { |
3339 | priv->yoffset += priv->top_margin - top_margin; |
3340 | |
3341 | priv->top_margin = top_margin; |
3342 | priv->top_border = top_margin + priv->top_padding; |
3343 | |
3344 | if (priv->layout && priv->layout->default_style) |
3345 | ctk_text_layout_default_style_changed (priv->layout); |
3346 | |
3347 | ctk_text_view_invalidate (text_view); |
3348 | |
3349 | g_object_notify (G_OBJECT (text_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), (((GType) ((20) << (2)))))))), "top-margin"); |
3350 | } |
3351 | } |
3352 | |
3353 | /** |
3354 | * ctk_text_view_get_top_margin: |
3355 | * @text_view: a #CtkTextView |
3356 | * |
3357 | * Gets the top margin for text in the @text_view. |
3358 | * |
3359 | * Returns: top margin in pixels |
3360 | * |
3361 | * Since: 3.18 |
3362 | **/ |
3363 | gint |
3364 | ctk_text_view_get_top_margin (CtkTextView *text_view) |
3365 | { |
3366 | g_return_val_if_fail (CTK_IS_TEXT_VIEW (text_view), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return (0); } } while (0 ); |
3367 | |
3368 | return text_view->priv->top_margin; |
3369 | } |
3370 | |
3371 | /** |
3372 | * ctk_text_view_set_bottom_margin: |
3373 | * @text_view: a #CtkTextView |
3374 | * @bottom_margin: bottom margin in pixels |
3375 | * |
3376 | * Sets the bottom margin for text in @text_view. |
3377 | * |
3378 | * Note that this function is confusingly named. |
3379 | * In CSS terms, the value set here is padding. |
3380 | * |
3381 | * Since: 3.18 |
3382 | */ |
3383 | void |
3384 | ctk_text_view_set_bottom_margin (CtkTextView *text_view, |
3385 | gint bottom_margin) |
3386 | { |
3387 | CtkTextViewPrivate *priv = text_view->priv; |
3388 | |
3389 | g_return_if_fail (CTK_IS_TEXT_VIEW (text_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return; } } while (0); |
3390 | |
3391 | if (priv->bottom_margin != bottom_margin) |
3392 | { |
3393 | priv->bottom_margin = bottom_margin; |
3394 | priv->bottom_border = bottom_margin + priv->bottom_padding; |
3395 | |
3396 | if (priv->layout && priv->layout->default_style) |
3397 | ctk_text_layout_default_style_changed (priv->layout); |
3398 | |
3399 | g_object_notify (G_OBJECT (text_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), (((GType) ((20) << (2)))))))), "bottom-margin"); |
3400 | } |
3401 | } |
3402 | |
3403 | /** |
3404 | * ctk_text_view_get_bottom_margin: |
3405 | * @text_view: a #CtkTextView |
3406 | * |
3407 | * Gets the bottom margin for text in the @text_view. |
3408 | * |
3409 | * Returns: bottom margin in pixels |
3410 | * |
3411 | * Since: 3.18 |
3412 | */ |
3413 | gint |
3414 | ctk_text_view_get_bottom_margin (CtkTextView *text_view) |
3415 | { |
3416 | g_return_val_if_fail (CTK_IS_TEXT_VIEW (text_view), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return (0); } } while (0 ); |
3417 | |
3418 | return text_view->priv->bottom_margin; |
3419 | } |
3420 | |
3421 | /** |
3422 | * ctk_text_view_set_indent: |
3423 | * @text_view: a #CtkTextView |
3424 | * @indent: indentation in pixels |
3425 | * |
3426 | * Sets the default indentation for paragraphs in @text_view. |
3427 | * Tags in the buffer may override the default. |
3428 | **/ |
3429 | void |
3430 | ctk_text_view_set_indent (CtkTextView *text_view, |
3431 | gint indent) |
3432 | { |
3433 | CtkTextViewPrivate *priv; |
3434 | |
3435 | g_return_if_fail (CTK_IS_TEXT_VIEW (text_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return; } } while (0); |
3436 | |
3437 | priv = text_view->priv; |
3438 | |
3439 | if (priv->indent != indent) |
3440 | { |
3441 | priv->indent = indent; |
3442 | |
3443 | if (priv->layout && priv->layout->default_style) |
3444 | { |
3445 | priv->layout->default_style->indent = indent; |
3446 | ctk_text_layout_default_style_changed (priv->layout); |
3447 | } |
3448 | |
3449 | g_object_notify (G_OBJECT (text_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), (((GType) ((20) << (2)))))))), "indent"); |
3450 | } |
3451 | } |
3452 | |
3453 | /** |
3454 | * ctk_text_view_get_indent: |
3455 | * @text_view: a #CtkTextView |
3456 | * |
3457 | * Gets the default indentation of paragraphs in @text_view. |
3458 | * Tags in the view’s buffer may override the default. |
3459 | * The indentation may be negative. |
3460 | * |
3461 | * Returns: number of pixels of indentation |
3462 | **/ |
3463 | gint |
3464 | ctk_text_view_get_indent (CtkTextView *text_view) |
3465 | { |
3466 | g_return_val_if_fail (CTK_IS_TEXT_VIEW (text_view), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return (0); } } while (0 ); |
3467 | |
3468 | return text_view->priv->indent; |
3469 | } |
3470 | |
3471 | /** |
3472 | * ctk_text_view_set_tabs: |
3473 | * @text_view: a #CtkTextView |
3474 | * @tabs: tabs as a #PangoTabArray |
3475 | * |
3476 | * Sets the default tab stops for paragraphs in @text_view. |
3477 | * Tags in the buffer may override the default. |
3478 | **/ |
3479 | void |
3480 | ctk_text_view_set_tabs (CtkTextView *text_view, |
3481 | PangoTabArray *tabs) |
3482 | { |
3483 | CtkTextViewPrivate *priv; |
3484 | |
3485 | g_return_if_fail (CTK_IS_TEXT_VIEW (text_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return; } } while (0); |
3486 | |
3487 | priv = text_view->priv; |
3488 | |
3489 | if (priv->tabs) |
3490 | pango_tab_array_free (priv->tabs); |
3491 | |
3492 | priv->tabs = tabs ? pango_tab_array_copy (tabs) : NULL((void*)0); |
3493 | |
3494 | if (priv->layout && priv->layout->default_style) |
3495 | { |
3496 | /* some unkosher futzing in internal struct details... */ |
3497 | if (priv->layout->default_style->tabs) |
3498 | pango_tab_array_free (priv->layout->default_style->tabs); |
3499 | |
3500 | priv->layout->default_style->tabs = |
3501 | priv->tabs ? pango_tab_array_copy (priv->tabs) : NULL((void*)0); |
3502 | |
3503 | ctk_text_layout_default_style_changed (priv->layout); |
3504 | } |
3505 | |
3506 | g_object_notify (G_OBJECT (text_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), (((GType) ((20) << (2)))))))), "tabs"); |
3507 | } |
3508 | |
3509 | /** |
3510 | * ctk_text_view_get_tabs: |
3511 | * @text_view: a #CtkTextView |
3512 | * |
3513 | * Gets the default tabs for @text_view. Tags in the buffer may |
3514 | * override the defaults. The returned array will be %NULL if |
3515 | * “standard” (8-space) tabs are used. Free the return value |
3516 | * with pango_tab_array_free(). |
3517 | * |
3518 | * Returns: (nullable) (transfer full): copy of default tab array, or %NULL if |
3519 | * “standard" tabs are used; must be freed with pango_tab_array_free(). |
3520 | **/ |
3521 | PangoTabArray* |
3522 | ctk_text_view_get_tabs (CtkTextView *text_view) |
3523 | { |
3524 | g_return_val_if_fail (CTK_IS_TEXT_VIEW (text_view), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return (((void*)0)); } } while (0); |
3525 | |
3526 | return text_view->priv->tabs ? pango_tab_array_copy (text_view->priv->tabs) : NULL((void*)0); |
3527 | } |
3528 | |
3529 | static void |
3530 | ctk_text_view_toggle_cursor_visible (CtkTextView *text_view) |
3531 | { |
3532 | ctk_text_view_set_cursor_visible (text_view, !text_view->priv->cursor_visible); |
3533 | } |
3534 | |
3535 | /** |
3536 | * ctk_text_view_set_cursor_visible: |
3537 | * @text_view: a #CtkTextView |
3538 | * @setting: whether to show the insertion cursor |
3539 | * |
3540 | * Toggles whether the insertion point should be displayed. A buffer with |
3541 | * no editable text probably shouldn’t have a visible cursor, so you may |
3542 | * want to turn the cursor off. |
3543 | * |
3544 | * Note that this property may be overridden by the |
3545 | * #CtkSettings:ctk-keynave-use-caret settings. |
3546 | */ |
3547 | void |
3548 | ctk_text_view_set_cursor_visible (CtkTextView *text_view, |
3549 | gboolean setting) |
3550 | { |
3551 | CtkTextViewPrivate *priv; |
3552 | |
3553 | g_return_if_fail (CTK_IS_TEXT_VIEW (text_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return; } } while (0); |
3554 | |
3555 | priv = text_view->priv; |
3556 | setting = (setting != FALSE(0)); |
3557 | |
3558 | if (priv->cursor_visible != setting) |
3559 | { |
3560 | priv->cursor_visible = setting; |
3561 | |
3562 | if (ctk_widget_has_focus (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))))) |
3563 | { |
3564 | if (priv->layout) |
3565 | { |
3566 | ctk_text_layout_set_cursor_visible (priv->layout, setting); |
3567 | ctk_text_view_check_cursor_blink (text_view); |
3568 | } |
3569 | } |
3570 | |
3571 | g_object_notify (G_OBJECT (text_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), (((GType) ((20) << (2)))))))), "cursor-visible"); |
3572 | } |
3573 | } |
3574 | |
3575 | /** |
3576 | * ctk_text_view_get_cursor_visible: |
3577 | * @text_view: a #CtkTextView |
3578 | * |
3579 | * Find out whether the cursor should be displayed. |
3580 | * |
3581 | * Returns: whether the insertion mark is visible |
3582 | */ |
3583 | gboolean |
3584 | ctk_text_view_get_cursor_visible (CtkTextView *text_view) |
3585 | { |
3586 | g_return_val_if_fail (CTK_IS_TEXT_VIEW (text_view), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return ((0)); } } while ( 0); |
3587 | |
3588 | return text_view->priv->cursor_visible; |
3589 | } |
3590 | |
3591 | /** |
3592 | * ctk_text_view_reset_cursor_blink: |
3593 | * @text_view: a #CtkTextView |
3594 | * |
3595 | * Ensures that the cursor is shown (i.e. not in an 'off' blink |
3596 | * interval) and resets the time that it will stay blinking (or |
3597 | * visible, in case blinking is disabled). |
3598 | * |
3599 | * This function should be called in response to user input |
3600 | * (e.g. from derived classes that override the textview's |
3601 | * #CtkWidget::key-press-event handler). |
3602 | * |
3603 | * Since: 3.20 |
3604 | */ |
3605 | void |
3606 | ctk_text_view_reset_cursor_blink (CtkTextView *text_view) |
3607 | { |
3608 | g_return_if_fail (CTK_IS_TEXT_VIEW (text_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return; } } while (0); |
3609 | |
3610 | ctk_text_view_reset_blink_time (text_view); |
3611 | ctk_text_view_pend_cursor_blink (text_view); |
3612 | } |
3613 | |
3614 | /** |
3615 | * ctk_text_view_place_cursor_onscreen: |
3616 | * @text_view: a #CtkTextView |
3617 | * |
3618 | * Moves the cursor to the currently visible region of the |
3619 | * buffer, it it isn’t there already. |
3620 | * |
3621 | * Returns: %TRUE if the cursor had to be moved. |
3622 | **/ |
3623 | gboolean |
3624 | ctk_text_view_place_cursor_onscreen (CtkTextView *text_view) |
3625 | { |
3626 | CtkTextIter insert; |
3627 | |
3628 | g_return_val_if_fail (CTK_IS_TEXT_VIEW (text_view), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return ((0)); } } while ( 0); |
3629 | |
3630 | ctk_text_buffer_get_iter_at_mark (get_buffer (text_view), &insert, |
3631 | ctk_text_buffer_get_insert (get_buffer (text_view))); |
3632 | |
3633 | if (clamp_iter_onscreen (text_view, &insert)) |
3634 | { |
3635 | ctk_text_buffer_place_cursor (get_buffer (text_view), &insert); |
3636 | return TRUE(!(0)); |
3637 | } |
3638 | else |
3639 | return FALSE(0); |
3640 | } |
3641 | |
3642 | static void |
3643 | ctk_text_view_remove_validate_idles (CtkTextView *text_view) |
3644 | { |
3645 | CtkTextViewPrivate *priv = text_view->priv; |
3646 | |
3647 | if (priv->first_validate_idle != 0) |
3648 | { |
3649 | DV (g_print ("Removing first validate idle: %s\n", G_STRLOC)); |
3650 | g_source_remove (priv->first_validate_idle); |
3651 | priv->first_validate_idle = 0; |
3652 | } |
3653 | |
3654 | if (priv->incremental_validate_idle != 0) |
3655 | { |
3656 | g_source_remove (priv->incremental_validate_idle); |
3657 | priv->incremental_validate_idle = 0; |
3658 | } |
3659 | } |
3660 | |
3661 | static void |
3662 | ctk_text_view_destroy (CtkWidget *widget) |
3663 | { |
3664 | CtkTextView *text_view; |
3665 | CtkTextViewPrivate *priv; |
3666 | |
3667 | text_view = CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ())))))); |
3668 | priv = text_view->priv; |
3669 | |
3670 | ctk_text_view_remove_validate_idles (text_view); |
3671 | ctk_text_view_set_buffer (text_view, NULL((void*)0)); |
3672 | ctk_text_view_destroy_layout (text_view); |
3673 | |
3674 | if (text_view->priv->scroll_timeout) |
3675 | { |
3676 | g_source_remove (text_view->priv->scroll_timeout); |
3677 | text_view->priv->scroll_timeout = 0; |
3678 | } |
3679 | |
3680 | if (priv->im_spot_idle) |
3681 | { |
3682 | g_source_remove (priv->im_spot_idle); |
3683 | priv->im_spot_idle = 0; |
3684 | } |
3685 | |
3686 | if (priv->pixel_cache) |
3687 | { |
3688 | _ctk_pixel_cache_free (priv->pixel_cache); |
3689 | priv->pixel_cache = NULL((void*)0); |
3690 | } |
3691 | |
3692 | if (priv->magnifier) |
3693 | _ctk_magnifier_set_inspected (CTK_MAGNIFIER (priv->magnifier)((((CtkMagnifier*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((priv->magnifier)), ((_ctk_magnifier_get_type ())))))), NULL((void*)0)); |
3694 | |
3695 | CTK_WIDGET_CLASS (ctk_text_view_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((ctk_text_view_parent_class)), ((ctk_widget_get_type ())) ))))->destroy (widget); |
3696 | } |
3697 | |
3698 | static void |
3699 | ctk_text_view_finalize (GObject *object) |
3700 | { |
3701 | CtkTextView *text_view; |
3702 | CtkTextViewPrivate *priv; |
3703 | |
3704 | text_view = CTK_TEXT_VIEW (object)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((object)), ((ctk_text_view_get_type ())))))); |
3705 | priv = text_view->priv; |
3706 | |
3707 | ctk_text_view_destroy_layout (text_view); |
3708 | ctk_text_view_set_buffer (text_view, NULL((void*)0)); |
3709 | |
3710 | /* at this point, no "notify::buffer" handler should recreate the buffer. */ |
3711 | g_assert (priv->buffer == NULL)do { if (priv->buffer == ((void*)0)) ; else g_assertion_message_expr ("Ctk", "ctktextview.c", 3711, ((const char*) (__func__)), "priv->buffer == NULL" ); } while (0); |
3712 | |
3713 | cancel_pending_scroll (text_view); |
3714 | |
3715 | g_object_unref (priv->multipress_gesture); |
3716 | g_object_unref (priv->drag_gesture); |
3717 | |
3718 | if (priv->tabs) |
3719 | pango_tab_array_free (priv->tabs); |
3720 | |
3721 | if (priv->hadjustment) |
3722 | g_object_unref (priv->hadjustment); |
3723 | if (priv->vadjustment) |
3724 | g_object_unref (priv->vadjustment); |
3725 | |
3726 | text_window_free (priv->text_window); |
3727 | |
3728 | if (priv->left_window) |
3729 | text_window_free (priv->left_window); |
3730 | |
3731 | if (priv->top_window) |
3732 | text_window_free (priv->top_window); |
3733 | |
3734 | if (priv->right_window) |
3735 | text_window_free (priv->right_window); |
3736 | |
3737 | if (priv->bottom_window) |
3738 | text_window_free (priv->bottom_window); |
3739 | |
3740 | if (priv->selection_bubble) |
3741 | ctk_widget_destroy (priv->selection_bubble); |
3742 | |
3743 | if (priv->magnifier_popover) |
3744 | ctk_widget_destroy (priv->magnifier_popover); |
3745 | if (priv->text_handle) |
3746 | g_object_unref (priv->text_handle); |
3747 | g_object_unref (priv->im_context); |
3748 | |
3749 | g_free (priv->im_module); |
3750 | |
3751 | G_OBJECT_CLASS (ctk_text_view_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((ctk_text_view_parent_class)), (((GType) ((20) << ( 2))))))))->finalize (object); |
3752 | } |
3753 | |
3754 | static void |
3755 | ctk_text_view_set_property (GObject *object, |
3756 | guint prop_id, |
3757 | const GValue *value, |
3758 | GParamSpec *pspec) |
3759 | { |
3760 | CtkTextView *text_view; |
3761 | CtkTextViewPrivate *priv; |
3762 | |
3763 | text_view = CTK_TEXT_VIEW (object)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((object)), ((ctk_text_view_get_type ())))))); |
3764 | priv = text_view->priv; |
3765 | |
3766 | switch (prop_id) |
3767 | { |
3768 | case PROP_PIXELS_ABOVE_LINES: |
3769 | ctk_text_view_set_pixels_above_lines (text_view, g_value_get_int (value)); |
3770 | break; |
3771 | |
3772 | case PROP_PIXELS_BELOW_LINES: |
3773 | ctk_text_view_set_pixels_below_lines (text_view, g_value_get_int (value)); |
3774 | break; |
3775 | |
3776 | case PROP_PIXELS_INSIDE_WRAP: |
3777 | ctk_text_view_set_pixels_inside_wrap (text_view, g_value_get_int (value)); |
3778 | break; |
3779 | |
3780 | case PROP_EDITABLE: |
3781 | ctk_text_view_set_editable (text_view, g_value_get_boolean (value)); |
3782 | break; |
3783 | |
3784 | case PROP_WRAP_MODE: |
3785 | ctk_text_view_set_wrap_mode (text_view, g_value_get_enum (value)); |
3786 | break; |
3787 | |
3788 | case PROP_JUSTIFICATION: |
3789 | ctk_text_view_set_justification (text_view, g_value_get_enum (value)); |
3790 | break; |
3791 | |
3792 | case PROP_LEFT_MARGIN: |
3793 | ctk_text_view_set_left_margin (text_view, g_value_get_int (value)); |
3794 | break; |
3795 | |
3796 | case PROP_RIGHT_MARGIN: |
3797 | ctk_text_view_set_right_margin (text_view, g_value_get_int (value)); |
3798 | break; |
3799 | |
3800 | case PROP_TOP_MARGIN: |
3801 | ctk_text_view_set_top_margin (text_view, g_value_get_int (value)); |
3802 | break; |
3803 | |
3804 | case PROP_BOTTOM_MARGIN: |
3805 | ctk_text_view_set_bottom_margin (text_view, g_value_get_int (value)); |
3806 | break; |
3807 | |
3808 | case PROP_INDENT: |
3809 | ctk_text_view_set_indent (text_view, g_value_get_int (value)); |
3810 | break; |
3811 | |
3812 | case PROP_TABS: |
3813 | ctk_text_view_set_tabs (text_view, g_value_get_boxed (value)); |
3814 | break; |
3815 | |
3816 | case PROP_CURSOR_VISIBLE: |
3817 | ctk_text_view_set_cursor_visible (text_view, g_value_get_boolean (value)); |
3818 | break; |
3819 | |
3820 | case PROP_OVERWRITE: |
3821 | ctk_text_view_set_overwrite (text_view, g_value_get_boolean (value)); |
3822 | break; |
3823 | |
3824 | case PROP_BUFFER: |
3825 | ctk_text_view_set_buffer (text_view, CTK_TEXT_BUFFER (g_value_get_object (value))((((CtkTextBuffer*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((g_value_get_object (value))), ((ctk_text_buffer_get_type ()))))))); |
3826 | break; |
3827 | |
3828 | case PROP_ACCEPTS_TAB: |
3829 | ctk_text_view_set_accepts_tab (text_view, g_value_get_boolean (value)); |
3830 | break; |
3831 | |
3832 | case PROP_IM_MODULE: |
3833 | g_free (priv->im_module); |
3834 | priv->im_module = g_value_dup_string (value); |
3835 | if (CTK_IS_IM_MULTICONTEXT (priv->im_context)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ( (priv->im_context)); GType __t = ((ctk_im_multicontext_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; }))))) |
3836 | ctk_im_multicontext_set_context_id (CTK_IM_MULTICONTEXT (priv->im_context)((((CtkIMMulticontext*) (void *) g_type_check_instance_cast ( (GTypeInstance*) ((priv->im_context)), ((ctk_im_multicontext_get_type ())))))), priv->im_module); |
3837 | break; |
3838 | |
3839 | case PROP_HADJUSTMENT: |
3840 | ctk_text_view_set_hadjustment (text_view, g_value_get_object (value)); |
3841 | break; |
3842 | |
3843 | case PROP_VADJUSTMENT: |
3844 | ctk_text_view_set_vadjustment (text_view, g_value_get_object (value)); |
3845 | break; |
3846 | |
3847 | case PROP_HSCROLL_POLICY: |
3848 | if (priv->hscroll_policy != g_value_get_enum (value)) |
3849 | { |
3850 | priv->hscroll_policy = g_value_get_enum (value); |
3851 | ctk_widget_queue_resize (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
3852 | g_object_notify_by_pspec (object, pspec); |
3853 | } |
3854 | break; |
3855 | |
3856 | case PROP_VSCROLL_POLICY: |
3857 | if (priv->vscroll_policy != g_value_get_enum (value)) |
3858 | { |
3859 | priv->vscroll_policy = g_value_get_enum (value); |
3860 | ctk_widget_queue_resize (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
3861 | g_object_notify_by_pspec (object, pspec); |
3862 | } |
3863 | break; |
3864 | |
3865 | case PROP_INPUT_PURPOSE: |
3866 | ctk_text_view_set_input_purpose (text_view, g_value_get_enum (value)); |
3867 | break; |
3868 | |
3869 | case PROP_INPUT_HINTS: |
3870 | ctk_text_view_set_input_hints (text_view, g_value_get_flags (value)); |
3871 | break; |
3872 | |
3873 | case PROP_POPULATE_ALL: |
3874 | if (text_view->priv->populate_all != g_value_get_boolean (value)) |
3875 | { |
3876 | text_view->priv->populate_all = g_value_get_boolean (value); |
3877 | g_object_notify_by_pspec (object, pspec); |
3878 | } |
3879 | break; |
3880 | case PROP_MONOSPACE: |
3881 | ctk_text_view_set_monospace (text_view, g_value_get_boolean (value)); |
3882 | break; |
3883 | |
3884 | default: |
3885 | 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'" , "ctktextview.c", 3885, ("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); |
3886 | break; |
3887 | } |
3888 | } |
3889 | |
3890 | static void |
3891 | ctk_text_view_get_property (GObject *object, |
3892 | guint prop_id, |
3893 | GValue *value, |
3894 | GParamSpec *pspec) |
3895 | { |
3896 | CtkTextView *text_view; |
3897 | CtkTextViewPrivate *priv; |
3898 | |
3899 | text_view = CTK_TEXT_VIEW (object)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((object)), ((ctk_text_view_get_type ())))))); |
3900 | priv = text_view->priv; |
3901 | |
3902 | switch (prop_id) |
3903 | { |
3904 | case PROP_PIXELS_ABOVE_LINES: |
3905 | g_value_set_int (value, priv->pixels_above_lines); |
3906 | break; |
3907 | |
3908 | case PROP_PIXELS_BELOW_LINES: |
3909 | g_value_set_int (value, priv->pixels_below_lines); |
3910 | break; |
3911 | |
3912 | case PROP_PIXELS_INSIDE_WRAP: |
3913 | g_value_set_int (value, priv->pixels_inside_wrap); |
3914 | break; |
3915 | |
3916 | case PROP_EDITABLE: |
3917 | g_value_set_boolean (value, priv->editable); |
3918 | break; |
3919 | |
3920 | case PROP_WRAP_MODE: |
3921 | g_value_set_enum (value, priv->wrap_mode); |
3922 | break; |
3923 | |
3924 | case PROP_JUSTIFICATION: |
3925 | g_value_set_enum (value, priv->justify); |
3926 | break; |
3927 | |
3928 | case PROP_LEFT_MARGIN: |
3929 | g_value_set_int (value, priv->left_margin); |
3930 | break; |
3931 | |
3932 | case PROP_RIGHT_MARGIN: |
3933 | g_value_set_int (value, priv->right_margin); |
3934 | break; |
3935 | |
3936 | case PROP_TOP_MARGIN: |
3937 | g_value_set_int (value, priv->top_margin); |
3938 | break; |
3939 | |
3940 | case PROP_BOTTOM_MARGIN: |
3941 | g_value_set_int (value, priv->bottom_margin); |
3942 | break; |
3943 | |
3944 | case PROP_INDENT: |
3945 | g_value_set_int (value, priv->indent); |
3946 | break; |
3947 | |
3948 | case PROP_TABS: |
3949 | g_value_set_boxed (value, priv->tabs); |
3950 | break; |
3951 | |
3952 | case PROP_CURSOR_VISIBLE: |
3953 | g_value_set_boolean (value, priv->cursor_visible); |
3954 | break; |
3955 | |
3956 | case PROP_BUFFER: |
3957 | g_value_set_object (value, get_buffer (text_view)); |
3958 | break; |
3959 | |
3960 | case PROP_OVERWRITE: |
3961 | g_value_set_boolean (value, priv->overwrite_mode); |
3962 | break; |
3963 | |
3964 | case PROP_ACCEPTS_TAB: |
3965 | g_value_set_boolean (value, priv->accepts_tab); |
3966 | break; |
3967 | |
3968 | case PROP_IM_MODULE: |
3969 | g_value_set_string (value, priv->im_module); |
3970 | break; |
3971 | |
3972 | case PROP_HADJUSTMENT: |
3973 | g_value_set_object (value, priv->hadjustment); |
3974 | break; |
3975 | |
3976 | case PROP_VADJUSTMENT: |
3977 | g_value_set_object (value, priv->vadjustment); |
3978 | break; |
3979 | |
3980 | case PROP_HSCROLL_POLICY: |
3981 | g_value_set_enum (value, priv->hscroll_policy); |
3982 | break; |
3983 | |
3984 | case PROP_VSCROLL_POLICY: |
3985 | g_value_set_enum (value, priv->vscroll_policy); |
3986 | break; |
3987 | |
3988 | case PROP_INPUT_PURPOSE: |
3989 | g_value_set_enum (value, ctk_text_view_get_input_purpose (text_view)); |
3990 | break; |
3991 | |
3992 | case PROP_INPUT_HINTS: |
3993 | g_value_set_flags (value, ctk_text_view_get_input_hints (text_view)); |
3994 | break; |
3995 | |
3996 | case PROP_POPULATE_ALL: |
3997 | g_value_set_boolean (value, priv->populate_all); |
3998 | break; |
3999 | |
4000 | case PROP_MONOSPACE: |
4001 | g_value_set_boolean (value, ctk_text_view_get_monospace (text_view)); |
4002 | break; |
4003 | |
4004 | default: |
4005 | 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'" , "ctktextview.c", 4005, ("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); |
4006 | break; |
4007 | } |
4008 | } |
4009 | |
4010 | static void |
4011 | ctk_text_view_size_request (CtkWidget *widget, |
4012 | CtkRequisition *requisition) |
4013 | { |
4014 | CtkTextView *text_view; |
4015 | CtkTextViewPrivate *priv; |
4016 | GSList *tmp_list; |
4017 | guint border_width; |
4018 | |
4019 | text_view = CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ())))))); |
4020 | priv = text_view->priv; |
4021 | |
4022 | if (priv->layout) |
4023 | { |
4024 | priv->text_window->requisition.width = priv->layout->width; |
4025 | priv->text_window->requisition.height = priv->layout->height; |
4026 | } |
4027 | else |
4028 | { |
4029 | priv->text_window->requisition.width = 0; |
4030 | priv->text_window->requisition.height = 0; |
4031 | } |
4032 | |
4033 | requisition->width = priv->text_window->requisition.width; |
4034 | requisition->height = priv->text_window->requisition.height; |
4035 | |
4036 | if (priv->left_window) |
4037 | requisition->width += priv->left_window->requisition.width; |
4038 | |
4039 | if (priv->right_window) |
4040 | requisition->width += priv->right_window->requisition.width; |
4041 | |
4042 | if (priv->top_window) |
4043 | requisition->height += priv->top_window->requisition.height; |
4044 | |
4045 | if (priv->bottom_window) |
4046 | requisition->height += priv->bottom_window->requisition.height; |
4047 | |
4048 | border_width = ctk_container_get_border_width (CTK_CONTAINER (text_view)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_container_get_type ()))))))); |
4049 | requisition->width += border_width * 2; |
4050 | requisition->height += border_width * 2; |
4051 | |
4052 | requisition->height += priv->top_border + priv->bottom_border; |
4053 | |
4054 | tmp_list = priv->children; |
4055 | while (tmp_list != NULL((void*)0)) |
4056 | { |
4057 | CtkTextViewChild *child = tmp_list->data; |
4058 | |
4059 | if (child->anchor) |
4060 | { |
4061 | CtkRequisition child_req; |
4062 | CtkRequisition old_req; |
4063 | |
4064 | ctk_widget_get_preferred_size (child->widget, &old_req, NULL((void*)0)); |
4065 | |
4066 | ctk_widget_get_preferred_size (child->widget, &child_req, NULL((void*)0)); |
4067 | |
4068 | /* Invalidate layout lines if required */ |
4069 | if (priv->layout && |
4070 | (old_req.width != child_req.width || |
4071 | old_req.height != child_req.height)) |
4072 | ctk_text_child_anchor_queue_resize (child->anchor, |
4073 | priv->layout); |
4074 | } |
4075 | else |
4076 | { |
4077 | CtkRequisition child_req; |
4078 | |
4079 | ctk_widget_get_preferred_size (child->widget, |
4080 | &child_req, NULL((void*)0)); |
4081 | } |
4082 | |
4083 | tmp_list = tmp_list->next; |
4084 | } |
4085 | |
4086 | /* Cache the requested size of the text view so we can |
4087 | * compare it in the changed_handler() */ |
4088 | priv->cached_size_request = *requisition; |
4089 | } |
4090 | |
4091 | static void |
4092 | ctk_text_view_get_preferred_width (CtkWidget *widget, |
4093 | gint *minimum, |
4094 | gint *natural) |
4095 | { |
4096 | CtkRequisition requisition; |
4097 | |
4098 | ctk_text_view_size_request (widget, &requisition); |
4099 | |
4100 | *minimum = *natural = requisition.width; |
4101 | } |
4102 | |
4103 | static void |
4104 | ctk_text_view_get_preferred_height (CtkWidget *widget, |
4105 | gint *minimum, |
4106 | gint *natural) |
4107 | { |
4108 | CtkRequisition requisition; |
4109 | |
4110 | ctk_text_view_size_request (widget, &requisition); |
4111 | |
4112 | *minimum = *natural = requisition.height; |
4113 | } |
4114 | |
4115 | |
4116 | static void |
4117 | ctk_text_view_compute_child_allocation (CtkTextView *text_view, |
4118 | CtkTextViewChild *vc, |
4119 | CtkAllocation *allocation) |
4120 | { |
4121 | gint buffer_y; |
4122 | CtkTextIter iter; |
4123 | CtkRequisition req; |
4124 | |
4125 | ctk_text_buffer_get_iter_at_child_anchor (get_buffer (text_view), |
4126 | &iter, |
4127 | vc->anchor); |
4128 | |
4129 | ctk_text_layout_get_line_yrange (text_view->priv->layout, &iter, |
4130 | &buffer_y, NULL((void*)0)); |
4131 | |
4132 | buffer_y += vc->from_top_of_line; |
4133 | |
4134 | allocation->x = vc->from_left_of_buffer - text_view->priv->xoffset; |
4135 | allocation->y = buffer_y - text_view->priv->yoffset; |
4136 | |
4137 | ctk_widget_get_preferred_size (vc->widget, &req, NULL((void*)0)); |
4138 | allocation->width = req.width; |
4139 | allocation->height = req.height; |
4140 | } |
4141 | |
4142 | static void |
4143 | ctk_text_view_update_child_allocation (CtkTextView *text_view, |
4144 | CtkTextViewChild *vc) |
4145 | { |
4146 | CtkAllocation allocation; |
4147 | |
4148 | ctk_text_view_compute_child_allocation (text_view, vc, &allocation); |
4149 | |
4150 | ctk_widget_size_allocate (vc->widget, &allocation); |
4151 | |
4152 | #if 0 |
4153 | g_print ("allocation for %p allocated to %d,%d yoffset = %d\n", |
4154 | vc->widget, |
4155 | vc->widget->allocation.x, |
4156 | vc->widget->allocation.y, |
4157 | text_view->priv->yoffset); |
4158 | #endif |
4159 | } |
4160 | |
4161 | static void |
4162 | ctk_text_view_child_allocated (CtkTextLayout *layout G_GNUC_UNUSED__attribute__ ((__unused__)), |
4163 | CtkWidget *child, |
4164 | gint x, |
4165 | gint y, |
4166 | gpointer data) |
4167 | { |
4168 | CtkTextViewChild *vc = NULL((void*)0); |
4169 | CtkTextView *text_view = data; |
4170 | |
4171 | /* x,y is the position of the child from the top of the line, and |
4172 | * from the left of the buffer. We have to translate that into text |
4173 | * window coordinates, then size_allocate the child. |
4174 | */ |
4175 | |
4176 | vc = g_object_get_qdata (G_OBJECT (child)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((child)), (((GType) ((20) << (2)))))))), quark_text_view_child); |
4177 | |
4178 | g_assert (vc != NULL)do { if (vc != ((void*)0)) ; else g_assertion_message_expr ("Ctk" , "ctktextview.c", 4178, ((const char*) (__func__)), "vc != NULL" ); } while (0); |
4179 | |
4180 | DV (g_print ("child allocated at %d,%d\n", x, y)); |
4181 | |
4182 | vc->from_left_of_buffer = x; |
4183 | vc->from_top_of_line = y; |
4184 | |
4185 | ctk_text_view_update_child_allocation (text_view, vc); |
4186 | } |
4187 | |
4188 | static void |
4189 | ctk_text_view_allocate_children (CtkTextView *text_view) |
4190 | { |
4191 | GSList *tmp_list; |
4192 | |
4193 | DV(g_print(G_STRLOC"\n")); |
4194 | |
4195 | tmp_list = text_view->priv->children; |
4196 | while (tmp_list != NULL((void*)0)) |
4197 | { |
4198 | CtkTextViewChild *child = tmp_list->data; |
4199 | |
4200 | g_assert (child != NULL)do { if (child != ((void*)0)) ; else g_assertion_message_expr ("Ctk", "ctktextview.c", 4200, ((const char*) (__func__)), "child != NULL" ); } while (0); |
4201 | |
4202 | if (child->anchor) |
4203 | { |
4204 | /* We need to force-validate the regions containing |
4205 | * children. |
4206 | */ |
4207 | CtkTextIter child_loc; |
4208 | ctk_text_buffer_get_iter_at_child_anchor (get_buffer (text_view), |
4209 | &child_loc, |
4210 | child->anchor); |
4211 | |
4212 | /* Since anchored children are only ever allocated from |
4213 | * ctk_text_layout_get_line_display() we have to make sure |
4214 | * that the display line caching in the layout doesn't |
4215 | * get in the way. Invalidating the layout around the anchor |
4216 | * achieves this. |
4217 | */ |
4218 | if (_ctk_widget_get_alloc_needed (child->widget)) |
4219 | { |
4220 | CtkTextIter end = child_loc; |
4221 | ctk_text_iter_forward_char (&end); |
4222 | ctk_text_layout_invalidate (text_view->priv->layout, &child_loc, &end); |
4223 | } |
4224 | |
4225 | ctk_text_layout_validate_yrange (text_view->priv->layout, |
4226 | &child_loc, |
4227 | 0, 1); |
4228 | } |
4229 | else |
4230 | { |
4231 | CtkAllocation allocation; |
4232 | CtkRequisition child_req; |
4233 | |
4234 | allocation.x = child->x; |
4235 | allocation.y = child->y; |
4236 | |
4237 | if (child->type == CTK_TEXT_WINDOW_TEXT || |
4238 | child->type == CTK_TEXT_WINDOW_LEFT || |
4239 | child->type == CTK_TEXT_WINDOW_RIGHT) |
4240 | allocation.y -= text_view->priv->yoffset; |
4241 | if (child->type == CTK_TEXT_WINDOW_TEXT || |
4242 | child->type == CTK_TEXT_WINDOW_TOP || |
4243 | child->type == CTK_TEXT_WINDOW_BOTTOM) |
4244 | allocation.x -= text_view->priv->xoffset; |
4245 | |
4246 | ctk_widget_get_preferred_size (child->widget, &child_req, NULL((void*)0)); |
4247 | |
4248 | allocation.width = child_req.width; |
4249 | allocation.height = child_req.height; |
4250 | |
4251 | ctk_widget_size_allocate (child->widget, &allocation); |
4252 | } |
4253 | |
4254 | tmp_list = tmp_list->next; |
4255 | } |
4256 | } |
4257 | |
4258 | static void |
4259 | ctk_text_view_size_allocate (CtkWidget *widget, |
4260 | CtkAllocation *allocation) |
4261 | { |
4262 | CtkAllocation widget_allocation; |
4263 | CtkTextView *text_view; |
4264 | CtkTextViewPrivate *priv; |
4265 | gint width, height; |
4266 | CdkRectangle text_rect; |
4267 | CdkRectangle left_rect; |
4268 | CdkRectangle right_rect; |
4269 | CdkRectangle top_rect; |
4270 | CdkRectangle bottom_rect; |
4271 | guint border_width; |
4272 | gboolean size_changed; |
4273 | |
4274 | text_view = CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ())))))); |
4275 | priv = text_view->priv; |
4276 | |
4277 | DV(g_print(G_STRLOC"\n")); |
4278 | |
4279 | _ctk_pixel_cache_set_extra_size (priv->pixel_cache, 64, |
4280 | allocation->height / 2 + priv->top_border); |
4281 | |
4282 | ctk_widget_get_allocation (widget, &widget_allocation); |
4283 | size_changed = |
4284 | widget_allocation.width != allocation->width || |
4285 | widget_allocation.height != allocation->height; |
4286 | |
4287 | border_width = ctk_container_get_border_width (CTK_CONTAINER (text_view)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_container_get_type ()))))))); |
4288 | |
4289 | ctk_widget_set_allocation (widget, allocation); |
4290 | |
4291 | if (ctk_widget_get_realized (widget)) |
4292 | { |
4293 | cdk_window_move_resize (ctk_widget_get_window (widget), |
4294 | allocation->x, allocation->y, |
4295 | allocation->width, allocation->height); |
4296 | } |
4297 | |
4298 | /* distribute width/height among child windows. Ensure all |
4299 | * windows get at least a 1x1 allocation. |
4300 | */ |
4301 | |
4302 | width = allocation->width - border_width * 2; |
4303 | |
4304 | if (priv->left_window) |
4305 | left_rect.width = priv->left_window->requisition.width; |
4306 | else |
4307 | left_rect.width = 0; |
4308 | |
4309 | width -= left_rect.width; |
4310 | |
4311 | if (priv->right_window) |
4312 | right_rect.width = priv->right_window->requisition.width; |
4313 | else |
4314 | right_rect.width = 0; |
4315 | |
4316 | width -= right_rect.width; |
4317 | |
4318 | text_rect.width = MAX (1, width)(((1) > (width)) ? (1) : (width)); |
4319 | |
4320 | top_rect.width = text_rect.width; |
4321 | bottom_rect.width = text_rect.width; |
4322 | |
4323 | height = allocation->height - border_width * 2; |
4324 | |
4325 | if (priv->top_window) |
4326 | top_rect.height = priv->top_window->requisition.height; |
4327 | else |
4328 | top_rect.height = 0; |
4329 | |
4330 | height -= top_rect.height; |
4331 | |
4332 | if (priv->bottom_window) |
4333 | bottom_rect.height = priv->bottom_window->requisition.height; |
4334 | else |
4335 | bottom_rect.height = 0; |
4336 | |
4337 | height -= bottom_rect.height; |
4338 | |
4339 | text_rect.height = MAX (1, height)(((1) > (height)) ? (1) : (height)); |
4340 | |
4341 | left_rect.height = text_rect.height; |
4342 | right_rect.height = text_rect.height; |
4343 | |
4344 | /* Origins */ |
4345 | left_rect.x = border_width; |
4346 | top_rect.y = border_width; |
4347 | |
4348 | text_rect.x = left_rect.x + left_rect.width; |
4349 | text_rect.y = top_rect.y + top_rect.height; |
4350 | |
4351 | left_rect.y = text_rect.y; |
4352 | right_rect.y = text_rect.y; |
4353 | |
4354 | top_rect.x = text_rect.x; |
4355 | bottom_rect.x = text_rect.x; |
4356 | |
4357 | right_rect.x = text_rect.x + text_rect.width; |
4358 | bottom_rect.y = text_rect.y + text_rect.height; |
4359 | |
4360 | text_window_size_allocate (priv->text_window, |
4361 | &text_rect); |
4362 | |
4363 | if (priv->left_window) |
4364 | text_window_size_allocate (priv->left_window, |
4365 | &left_rect); |
4366 | |
4367 | if (priv->right_window) |
4368 | text_window_size_allocate (priv->right_window, |
4369 | &right_rect); |
4370 | |
4371 | if (priv->top_window) |
4372 | text_window_size_allocate (priv->top_window, |
4373 | &top_rect); |
4374 | |
4375 | if (priv->bottom_window) |
4376 | text_window_size_allocate (priv->bottom_window, |
4377 | &bottom_rect); |
4378 | |
4379 | ctk_text_view_update_layout_width (text_view); |
4380 | |
4381 | /* Note that this will do some layout validation */ |
4382 | ctk_text_view_allocate_children (text_view); |
4383 | |
4384 | /* Update adjustments */ |
4385 | if (!ctk_adjustment_is_animating (priv->hadjustment)) |
4386 | ctk_text_view_set_hadjustment_values (text_view); |
4387 | if (!ctk_adjustment_is_animating (priv->vadjustment)) |
4388 | ctk_text_view_set_vadjustment_values (text_view); |
4389 | |
4390 | /* The CTK resize loop processes all the pending exposes right |
4391 | * after doing the resize stuff, so the idle sizer won't have a |
4392 | * chance to run. So we do the work here. |
4393 | */ |
4394 | ctk_text_view_flush_first_validate (text_view); |
4395 | |
4396 | /* widget->window doesn't get auto-redrawn as the layout is computed, so has to |
4397 | * be invalidated |
4398 | */ |
4399 | if (size_changed && ctk_widget_get_realized (widget)) |
4400 | cdk_window_invalidate_rect (ctk_widget_get_window (widget), NULL((void*)0), FALSE(0)); |
4401 | } |
4402 | |
4403 | static void |
4404 | ctk_text_view_get_first_para_iter (CtkTextView *text_view, |
4405 | CtkTextIter *iter) |
4406 | { |
4407 | ctk_text_buffer_get_iter_at_mark (get_buffer (text_view), iter, |
4408 | text_view->priv->first_para_mark); |
4409 | } |
4410 | |
4411 | static void |
4412 | ctk_text_view_validate_onscreen (CtkTextView *text_view) |
4413 | { |
4414 | CtkWidget *widget; |
4415 | CtkTextViewPrivate *priv; |
4416 | |
4417 | widget = CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))); |
4418 | priv = text_view->priv; |
4419 | |
4420 | DV(g_print(">Validating onscreen ("G_STRLOC")\n")); |
4421 | |
4422 | if (SCREEN_HEIGHT (widget)text_window_get_height (((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((widget)), ((ctk_text_view_get_type ()))) )))->priv->text_window) > 0) |
4423 | { |
4424 | CtkTextIter first_para; |
4425 | |
4426 | /* Be sure we've validated the stuff onscreen; if we |
4427 | * scrolled, these calls won't have any effect, because |
4428 | * they were called in the recursive validate_onscreen |
4429 | */ |
4430 | ctk_text_view_get_first_para_iter (text_view, &first_para); |
4431 | |
4432 | ctk_text_layout_validate_yrange (priv->layout, |
4433 | &first_para, |
4434 | 0, |
4435 | priv->first_para_pixels + |
4436 | SCREEN_HEIGHT (widget)text_window_get_height (((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((widget)), ((ctk_text_view_get_type ()))) )))->priv->text_window)); |
4437 | } |
4438 | |
4439 | priv->onscreen_validated = TRUE(!(0)); |
4440 | |
4441 | DV(g_print(">Done validating onscreen, onscreen_validated = TRUE ("G_STRLOC")\n")); |
4442 | |
4443 | /* This can have the odd side effect of triggering a scroll, which should |
4444 | * flip "onscreen_validated" back to FALSE, but should also get us |
4445 | * back into this function to turn it on again. |
4446 | */ |
4447 | ctk_text_view_update_adjustments (text_view); |
4448 | |
4449 | g_assert (priv->onscreen_validated)do { if (priv->onscreen_validated) ; else g_assertion_message_expr ("Ctk", "ctktextview.c", 4449, ((const char*) (__func__)), "priv->onscreen_validated" ); } while (0); |
4450 | } |
4451 | |
4452 | static void |
4453 | ctk_text_view_flush_first_validate (CtkTextView *text_view) |
4454 | { |
4455 | CtkTextViewPrivate *priv = text_view->priv; |
4456 | |
4457 | if (priv->first_validate_idle == 0) |
4458 | return; |
4459 | |
4460 | /* Do this first, which means that if an "invalidate" |
4461 | * occurs during any of this process, a new first_validate_callback |
4462 | * will be installed, and we'll start again. |
4463 | */ |
4464 | DV (g_print ("removing first validate in %s\n", G_STRLOC)); |
4465 | g_source_remove (priv->first_validate_idle); |
4466 | priv->first_validate_idle = 0; |
4467 | |
4468 | /* be sure we have up-to-date screen size set on the |
4469 | * layout. |
4470 | */ |
4471 | ctk_text_view_update_layout_width (text_view); |
4472 | |
4473 | /* Bail out if we invalidated stuff; scrolling right away will just |
4474 | * confuse the issue. |
4475 | */ |
4476 | if (priv->first_validate_idle != 0) |
4477 | { |
4478 | DV(g_print(">Width change forced requeue ("G_STRLOC")\n")); |
4479 | } |
4480 | else |
4481 | { |
4482 | /* scroll to any marks, if that's pending. This can jump us to |
4483 | * the validation codepath used for scrolling onscreen, if so we |
4484 | * bail out. It won't jump if already in that codepath since |
4485 | * value_changed is not recursive, so also validate if |
4486 | * necessary. |
4487 | */ |
4488 | if (!ctk_text_view_flush_scroll (text_view) || |
4489 | !priv->onscreen_validated) |
4490 | ctk_text_view_validate_onscreen (text_view); |
4491 | |
4492 | DV(g_print(">Leaving first validate idle ("G_STRLOC")\n")); |
4493 | |
4494 | g_assert (priv->onscreen_validated)do { if (priv->onscreen_validated) ; else g_assertion_message_expr ("Ctk", "ctktextview.c", 4494, ((const char*) (__func__)), "priv->onscreen_validated" ); } while (0); |
4495 | } |
4496 | } |
4497 | |
4498 | static gboolean |
4499 | first_validate_callback (gpointer data) |
4500 | { |
4501 | CtkTextView *text_view = data; |
4502 | |
4503 | /* Note that some of this code is duplicated at the end of size_allocate, |
4504 | * keep in sync with that. |
4505 | */ |
4506 | |
4507 | DV(g_print(G_STRLOC"\n")); |
4508 | |
4509 | ctk_text_view_flush_first_validate (text_view); |
4510 | |
4511 | return FALSE(0); |
4512 | } |
4513 | |
4514 | static gboolean |
4515 | incremental_validate_callback (gpointer data) |
4516 | { |
4517 | CtkTextView *text_view = data; |
4518 | gboolean result = TRUE(!(0)); |
4519 | |
4520 | DV(g_print(G_STRLOC"\n")); |
4521 | |
4522 | ctk_text_layout_validate (text_view->priv->layout, 2000); |
4523 | |
4524 | ctk_text_view_update_adjustments (text_view); |
4525 | |
4526 | if (ctk_text_layout_is_valid (text_view->priv->layout)) |
4527 | { |
4528 | text_view->priv->incremental_validate_idle = 0; |
4529 | result = FALSE(0); |
4530 | } |
4531 | |
4532 | return result; |
4533 | } |
4534 | |
4535 | static void |
4536 | ctk_text_view_invalidate (CtkTextView *text_view) |
4537 | { |
4538 | CtkTextViewPrivate *priv = text_view->priv; |
4539 | |
4540 | DV (g_print (">Invalidate, onscreen_validated = %d now FALSE ("G_STRLOC")\n", |
4541 | priv->onscreen_validated)); |
4542 | |
4543 | priv->onscreen_validated = FALSE(0); |
4544 | |
4545 | /* We'll invalidate when the layout is created */ |
4546 | if (priv->layout == NULL((void*)0)) |
4547 | return; |
4548 | |
4549 | if (!priv->first_validate_idle) |
4550 | { |
4551 | priv->first_validate_idle = cdk_threads_add_idle_full (CTK_PRIORITY_RESIZE(100 + 10) - 2, first_validate_callback, text_view, NULL((void*)0)); |
4552 | g_source_set_name_by_id (priv->first_validate_idle, "[ctk+] first_validate_callback"); |
4553 | DV (g_print (G_STRLOC": adding first validate idle %d\n", |
4554 | priv->first_validate_idle)); |
4555 | } |
4556 | |
4557 | if (!priv->incremental_validate_idle) |
4558 | { |
4559 | priv->incremental_validate_idle = cdk_threads_add_idle_full (CTK_TEXT_VIEW_PRIORITY_VALIDATE((100 + 20) + 5), incremental_validate_callback, text_view, NULL((void*)0)); |
4560 | g_source_set_name_by_id (priv->incremental_validate_idle, "[ctk+] incremental_validate_callback"); |
4561 | DV (g_print (G_STRLOC": adding incremental validate idle %d\n", |
4562 | priv->incremental_validate_idle)); |
4563 | } |
4564 | } |
4565 | |
4566 | static void |
4567 | invalidated_handler (CtkTextLayout *layout G_GNUC_UNUSED__attribute__ ((__unused__)), |
4568 | gpointer data) |
4569 | { |
4570 | CtkTextView *text_view; |
4571 | |
4572 | text_view = CTK_TEXT_VIEW (data)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((data)), ((ctk_text_view_get_type ())))))); |
4573 | |
4574 | DV (g_print ("Invalidating due to layout invalidate signal\n")); |
4575 | ctk_text_view_invalidate (text_view); |
4576 | } |
4577 | |
4578 | static void |
4579 | changed_handler (CtkTextLayout *layout, |
4580 | gint start_y, |
4581 | gint old_height, |
4582 | gint new_height, |
4583 | gpointer data) |
4584 | { |
4585 | CtkTextView *text_view; |
4586 | CtkTextViewPrivate *priv; |
4587 | CtkWidget *widget; |
4588 | CdkRectangle visible_rect; |
4589 | CdkRectangle redraw_rect; |
4590 | |
4591 | text_view = CTK_TEXT_VIEW (data)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((data)), ((ctk_text_view_get_type ())))))); |
4592 | priv = text_view->priv; |
4593 | widget = CTK_WIDGET (data)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((data)), ((ctk_widget_get_type ())))))); |
4594 | |
4595 | DV(g_print(">Lines Validated ("G_STRLOC")\n")); |
4596 | |
4597 | if (ctk_widget_get_realized (widget)) |
4598 | { |
4599 | ctk_text_view_get_rendered_rect (text_view, &visible_rect); |
4600 | |
4601 | redraw_rect.x = visible_rect.x; |
4602 | redraw_rect.width = visible_rect.width; |
4603 | redraw_rect.y = start_y; |
4604 | |
4605 | if (old_height == new_height) |
4606 | redraw_rect.height = old_height; |
4607 | else if (start_y + old_height > visible_rect.y) |
4608 | redraw_rect.height = MAX (0, visible_rect.y + visible_rect.height - start_y)(((0) > (visible_rect.y + visible_rect.height - start_y)) ? (0) : (visible_rect.y + visible_rect.height - start_y)); |
4609 | else |
4610 | redraw_rect.height = 0; |
4611 | |
4612 | if (cdk_rectangle_intersect (&redraw_rect, &visible_rect, &redraw_rect)) |
4613 | { |
4614 | /* text_window_invalidate_rect() takes buffer coordinates */ |
4615 | text_window_invalidate_rect (priv->text_window, |
4616 | &redraw_rect); |
4617 | |
4618 | DV(g_print(" invalidated rect: %d,%d %d x %d\n", |
4619 | redraw_rect.x, |
4620 | redraw_rect.y, |
4621 | redraw_rect.width, |
4622 | redraw_rect.height)); |
4623 | |
4624 | if (priv->left_window) |
4625 | text_window_invalidate_rect (priv->left_window, |
4626 | &redraw_rect); |
4627 | if (priv->right_window) |
4628 | text_window_invalidate_rect (priv->right_window, |
4629 | &redraw_rect); |
4630 | if (priv->top_window) |
4631 | text_window_invalidate_rect (priv->top_window, |
4632 | &redraw_rect); |
4633 | if (priv->bottom_window) |
4634 | text_window_invalidate_rect (priv->bottom_window, |
4635 | &redraw_rect); |
4636 | |
4637 | queue_update_im_spot_location (text_view); |
4638 | } |
4639 | } |
4640 | |
4641 | if (old_height != new_height) |
4642 | { |
4643 | GSList *tmp_list; |
4644 | int new_first_para_top; |
4645 | int old_first_para_top; |
4646 | CtkTextIter first; |
4647 | |
4648 | /* If the bottom of the old area was above the top of the |
4649 | * screen, we need to scroll to keep the current top of the |
4650 | * screen in place. Remember that first_para_pixels is the |
4651 | * position of the top of the screen in coordinates relative to |
4652 | * the first paragraph onscreen. |
4653 | * |
4654 | * In short we are adding the height delta of the portion of the |
4655 | * changed region above first_para_mark to priv->yoffset. |
4656 | */ |
4657 | ctk_text_buffer_get_iter_at_mark (get_buffer (text_view), &first, |
4658 | priv->first_para_mark); |
4659 | |
4660 | ctk_text_layout_get_line_yrange (layout, &first, &new_first_para_top, NULL((void*)0)); |
4661 | |
4662 | old_first_para_top = priv->yoffset - priv->first_para_pixels + priv->top_border; |
4663 | |
4664 | if (new_first_para_top != old_first_para_top) |
4665 | { |
4666 | priv->yoffset += new_first_para_top - old_first_para_top; |
4667 | |
4668 | ctk_adjustment_set_value (text_view->priv->vadjustment, priv->yoffset); |
4669 | |
4670 | /* If the height changed above our current position, then we |
4671 | * need to discard the pixelcache because things wont line nup |
4672 | * anymore (even if we adjust the vadjustment). |
4673 | * |
4674 | * Generally this doesn't happen interactively because we keep |
4675 | * the insert cursor on screen when making changes. It can |
4676 | * happen when code changes the first line, for example, in an |
4677 | * automated fashion. |
4678 | * |
4679 | * There is one case where this could be optimized out such as |
4680 | * when delete-range is followed by insert-text and whole lines |
4681 | * are removed. API consumers can always work around that by |
4682 | * avoiding the removal of a \n so no effort is made here to |
4683 | * handle that. |
4684 | */ |
4685 | if (ctk_widget_get_realized (widget)) |
4686 | _ctk_pixel_cache_invalidate (text_view->priv->pixel_cache, NULL((void*)0)); |
4687 | } |
4688 | |
4689 | /* FIXME be smarter about which anchored widgets we update */ |
4690 | |
4691 | tmp_list = priv->children; |
4692 | while (tmp_list != NULL((void*)0)) |
4693 | { |
4694 | CtkTextViewChild *child = tmp_list->data; |
4695 | |
4696 | if (child->anchor) |
4697 | ctk_text_view_update_child_allocation (text_view, child); |
4698 | |
4699 | tmp_list = tmp_list->next; |
4700 | } |
4701 | } |
4702 | |
4703 | { |
4704 | CtkRequisition old_req = priv->cached_size_request; |
4705 | CtkRequisition new_req; |
4706 | |
4707 | /* Use this instead of ctk_widget_size_request wrapper |
4708 | * to avoid the optimization which just returns widget->requisition |
4709 | * if a resize hasn't been queued. |
4710 | */ |
4711 | ctk_text_view_size_request (widget, &new_req); |
4712 | |
4713 | if (old_req.width != new_req.width || |
4714 | old_req.height != new_req.height) |
4715 | { |
4716 | ctk_widget_queue_resize_no_redraw (widget); |
4717 | } |
4718 | } |
4719 | } |
4720 | |
4721 | static void |
4722 | ctk_text_view_realize (CtkWidget *widget) |
4723 | { |
4724 | CtkAllocation allocation; |
4725 | CtkTextView *text_view; |
4726 | CtkTextViewPrivate *priv; |
4727 | CdkWindow *window; |
4728 | CdkWindowAttr attributes; |
4729 | gint attributes_mask; |
4730 | GSList *tmp_list; |
4731 | |
4732 | text_view = CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ())))))); |
4733 | priv = text_view->priv; |
4734 | |
4735 | ctk_widget_set_realized (widget, TRUE(!(0))); |
4736 | |
4737 | ctk_widget_get_allocation (widget, &allocation); |
4738 | |
4739 | attributes.window_type = CDK_WINDOW_CHILD; |
4740 | attributes.x = allocation.x; |
4741 | attributes.y = allocation.y; |
4742 | attributes.width = allocation.width; |
4743 | attributes.height = allocation.height; |
4744 | attributes.wclass = CDK_INPUT_OUTPUT; |
4745 | attributes.visual = ctk_widget_get_visual (widget); |
4746 | attributes.event_mask = CDK_VISIBILITY_NOTIFY_MASK; |
4747 | |
4748 | attributes_mask = CDK_WA_X | CDK_WA_Y | CDK_WA_VISUAL; |
4749 | |
4750 | window = cdk_window_new (ctk_widget_get_parent_window (widget), |
4751 | &attributes, attributes_mask); |
4752 | ctk_widget_set_window (widget, window); |
4753 | ctk_widget_register_window (widget, window); |
4754 | |
4755 | text_window_realize (priv->text_window, widget); |
4756 | |
4757 | if (priv->left_window) |
4758 | text_window_realize (priv->left_window, widget); |
4759 | |
4760 | if (priv->top_window) |
4761 | text_window_realize (priv->top_window, widget); |
4762 | |
4763 | if (priv->right_window) |
4764 | text_window_realize (priv->right_window, widget); |
4765 | |
4766 | if (priv->bottom_window) |
4767 | text_window_realize (priv->bottom_window, widget); |
4768 | |
4769 | ctk_text_view_ensure_layout (text_view); |
4770 | ctk_text_view_invalidate (text_view); |
4771 | |
4772 | if (priv->buffer) |
4773 | { |
4774 | CtkClipboard *clipboard = ctk_widget_get_clipboard (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))), |
4775 | CDK_SELECTION_PRIMARY((CdkAtom)((gpointer) (gulong) (1)))); |
4776 | ctk_text_buffer_add_selection_clipboard (priv->buffer, clipboard); |
4777 | } |
4778 | |
4779 | tmp_list = priv->children; |
4780 | while (tmp_list != NULL((void*)0)) |
4781 | { |
4782 | CtkTextViewChild *vc = tmp_list->data; |
4783 | |
4784 | text_view_child_set_parent_window (text_view, vc); |
4785 | |
4786 | tmp_list = tmp_list->next; |
4787 | } |
4788 | |
4789 | /* Ensure updating the spot location. */ |
4790 | ctk_text_view_update_im_spot_location (text_view); |
4791 | } |
4792 | |
4793 | static void |
4794 | ctk_text_view_unrealize (CtkWidget *widget) |
4795 | { |
4796 | CtkTextView *text_view; |
4797 | CtkTextViewPrivate *priv; |
4798 | |
4799 | text_view = CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ())))))); |
4800 | priv = text_view->priv; |
4801 | |
4802 | if (priv->buffer) |
4803 | { |
4804 | CtkClipboard *clipboard = ctk_widget_get_clipboard (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))), |
4805 | CDK_SELECTION_PRIMARY((CdkAtom)((gpointer) (gulong) (1)))); |
4806 | ctk_text_buffer_remove_selection_clipboard (priv->buffer, clipboard); |
4807 | } |
4808 | |
4809 | ctk_text_view_remove_validate_idles (text_view); |
4810 | |
4811 | if (priv->popup_menu) |
4812 | { |
4813 | ctk_widget_destroy (priv->popup_menu); |
4814 | priv->popup_menu = NULL((void*)0); |
4815 | } |
4816 | |
4817 | text_window_unrealize (priv->text_window); |
4818 | |
4819 | if (priv->left_window) |
4820 | text_window_unrealize (priv->left_window); |
4821 | |
4822 | if (priv->top_window) |
4823 | text_window_unrealize (priv->top_window); |
4824 | |
4825 | if (priv->right_window) |
4826 | text_window_unrealize (priv->right_window); |
4827 | |
4828 | if (priv->bottom_window) |
4829 | text_window_unrealize (priv->bottom_window); |
4830 | |
4831 | CTK_WIDGET_CLASS (ctk_text_view_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((ctk_text_view_parent_class)), ((ctk_widget_get_type ())) ))))->unrealize (widget); |
4832 | } |
4833 | |
4834 | static void |
4835 | ctk_text_view_map (CtkWidget *widget) |
4836 | { |
4837 | CtkTextView *text_view; |
4838 | CtkTextViewPrivate *priv; |
4839 | |
4840 | text_view = CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ())))))); |
4841 | priv = text_view->priv; |
4842 | |
4843 | _ctk_pixel_cache_map (priv->pixel_cache); |
4844 | |
4845 | CTK_WIDGET_CLASS (ctk_text_view_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((ctk_text_view_parent_class)), ((ctk_widget_get_type ())) ))))->map (widget); |
4846 | } |
4847 | |
4848 | static void |
4849 | ctk_text_view_unmap (CtkWidget *widget) |
4850 | { |
4851 | CtkTextView *text_view; |
4852 | CtkTextViewPrivate *priv; |
4853 | |
4854 | text_view = CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ())))))); |
4855 | priv = text_view->priv; |
4856 | |
4857 | CTK_WIDGET_CLASS (ctk_text_view_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((ctk_text_view_parent_class)), ((ctk_widget_get_type ())) ))))->unmap (widget); |
4858 | |
4859 | _ctk_pixel_cache_unmap (priv->pixel_cache); |
4860 | } |
4861 | |
4862 | static void |
4863 | text_window_set_padding (CtkTextView *text_view, |
4864 | CtkStyleContext *context) |
4865 | { |
4866 | CtkTextViewPrivate *priv; |
4867 | CtkBorder padding, border; |
4868 | |
4869 | priv = text_view->priv; |
4870 | |
4871 | ctk_style_context_get_padding (context, ctk_style_context_get_state (context), &padding); |
4872 | ctk_style_context_get_border (context, ctk_style_context_get_state (context), &border); |
4873 | padding.left += border.left; |
4874 | padding.right += border.right; |
4875 | padding.top += border.top; |
4876 | padding.bottom += border.bottom; |
4877 | |
4878 | if (padding.left != priv->left_padding || |
4879 | padding.right != priv->right_padding || |
4880 | padding.top != priv->top_padding || |
4881 | padding.bottom != priv->bottom_padding) |
4882 | { |
4883 | priv->xoffset += priv->left_padding - padding.left; |
4884 | priv->yoffset += priv->top_padding - padding.top; |
4885 | |
4886 | priv->left_padding = padding.left; |
4887 | priv->right_padding = padding.right; |
4888 | priv->top_padding = padding.top; |
4889 | priv->bottom_padding = padding.bottom; |
4890 | |
4891 | priv->top_border = padding.top + priv->top_margin; |
4892 | priv->bottom_border = padding.bottom + priv->bottom_margin; |
4893 | priv->left_border = padding.left + priv->left_margin; |
4894 | priv->right_border = padding.right + priv->right_margin; |
4895 | |
4896 | if (priv->layout && priv->layout->default_style) |
4897 | { |
4898 | priv->layout->right_padding = priv->right_padding; |
4899 | priv->layout->left_padding = priv->left_padding; |
4900 | |
4901 | ctk_text_layout_default_style_changed (priv->layout); |
4902 | } |
4903 | } |
4904 | } |
4905 | |
4906 | static void |
4907 | ctk_text_view_style_updated (CtkWidget *widget) |
4908 | { |
4909 | CtkTextView *text_view; |
4910 | CtkTextViewPrivate *priv; |
4911 | PangoContext *ltr_context, *rtl_context; |
4912 | CtkStyleContext *style_context; |
4913 | CtkCssStyleChange *change; |
4914 | |
4915 | text_view = CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ())))))); |
4916 | priv = text_view->priv; |
4917 | |
4918 | CTK_WIDGET_CLASS (ctk_text_view_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((ctk_text_view_parent_class)), ((ctk_widget_get_type ())) ))))->style_updated (widget); |
4919 | |
4920 | style_context = ctk_widget_get_style_context (widget); |
4921 | change = ctk_style_context_get_change (style_context); |
4922 | |
4923 | if ((change == NULL((void*)0) || ctk_css_style_change_affects (change, CTK_CSS_AFFECTS_FONT)) && |
4924 | priv->layout && priv->layout->default_style) |
4925 | { |
4926 | ctk_text_view_set_attributes_from_style (text_view, |
4927 | priv->layout->default_style); |
4928 | |
4929 | ltr_context = ctk_widget_create_pango_context (widget); |
4930 | pango_context_set_base_dir (ltr_context, PANGO_DIRECTION_LTR); |
4931 | rtl_context = ctk_widget_create_pango_context (widget); |
4932 | pango_context_set_base_dir (rtl_context, PANGO_DIRECTION_RTL); |
4933 | |
4934 | ctk_text_layout_set_contexts (priv->layout, ltr_context, rtl_context); |
4935 | |
4936 | g_object_unref (ltr_context); |
4937 | g_object_unref (rtl_context); |
4938 | } |
4939 | } |
4940 | |
4941 | static void |
4942 | ctk_text_view_direction_changed (CtkWidget *widget, |
4943 | CtkTextDirection previous_direction G_GNUC_UNUSED__attribute__ ((__unused__))) |
4944 | { |
4945 | CtkTextViewPrivate *priv = CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ()))))))->priv; |
4946 | |
4947 | if (priv->layout && priv->layout->default_style) |
4948 | { |
4949 | priv->layout->default_style->direction = ctk_widget_get_direction (widget); |
4950 | |
4951 | ctk_text_layout_default_style_changed (priv->layout); |
4952 | } |
4953 | } |
4954 | |
4955 | static void |
4956 | ctk_text_view_state_flags_changed (CtkWidget *widget, |
4957 | CtkStateFlags previous_state G_GNUC_UNUSED__attribute__ ((__unused__))) |
4958 | { |
4959 | CtkTextView *text_view = CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ())))))); |
4960 | CtkTextViewPrivate *priv = text_view->priv; |
4961 | CdkCursor *cursor; |
4962 | CtkStateFlags state; |
4963 | |
4964 | if (ctk_widget_get_realized (widget)) |
4965 | { |
4966 | if (ctk_widget_is_sensitive (widget)) |
4967 | cursor = cdk_cursor_new_from_name (ctk_widget_get_display (widget), "text"); |
4968 | else |
4969 | cursor = NULL((void*)0); |
4970 | |
4971 | cdk_window_set_cursor (priv->text_window->bin_window, cursor); |
4972 | |
4973 | if (cursor) |
4974 | g_object_unref (cursor); |
4975 | |
4976 | priv->mouse_cursor_obscured = FALSE(0); |
4977 | } |
4978 | |
4979 | if (!ctk_widget_is_sensitive (widget)) |
4980 | { |
4981 | /* Clear any selection */ |
4982 | ctk_text_view_unselect (text_view); |
4983 | } |
4984 | |
4985 | state = ctk_widget_get_state_flags (widget); |
4986 | ctk_css_node_set_state (priv->text_window->css_node, state); |
4987 | |
4988 | state &= ~CTK_STATE_FLAG_DROP_ACTIVE; |
4989 | |
4990 | ctk_css_node_set_state (priv->selection_node, state); |
4991 | if (priv->left_window) |
4992 | ctk_css_node_set_state (priv->left_window->css_node, state); |
4993 | if (priv->right_window) |
4994 | ctk_css_node_set_state (priv->right_window->css_node, state); |
4995 | if (priv->top_window) |
4996 | ctk_css_node_set_state (priv->top_window->css_node, state); |
4997 | if (priv->bottom_window) |
4998 | ctk_css_node_set_state (priv->bottom_window->css_node, state); |
4999 | |
5000 | ctk_widget_queue_draw (widget); |
5001 | } |
5002 | |
5003 | static void |
5004 | set_invisible_cursor (CdkWindow *window) |
5005 | { |
5006 | CdkDisplay *display; |
5007 | CdkCursor *cursor; |
5008 | |
5009 | display = cdk_window_get_display (window); |
5010 | cursor = cdk_cursor_new_from_name (display, "none"); |
5011 | |
5012 | cdk_window_set_cursor (window, cursor); |
5013 | |
5014 | g_clear_object (&cursor)do { _Static_assert (sizeof *((&cursor)) == sizeof (gpointer ), "Expression evaluates to false"); __typeof__ (((&cursor ))) _pp = ((&cursor)); __typeof__ (*((&cursor))) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref) (_ptr) ; } while (0); |
5015 | } |
5016 | |
5017 | static void |
5018 | ctk_text_view_obscure_mouse_cursor (CtkTextView *text_view) |
5019 | { |
5020 | if (text_view->priv->mouse_cursor_obscured) |
5021 | return; |
5022 | |
5023 | set_invisible_cursor (text_view->priv->text_window->bin_window); |
5024 | |
5025 | text_view->priv->mouse_cursor_obscured = TRUE(!(0)); |
5026 | } |
5027 | |
5028 | static void |
5029 | ctk_text_view_unobscure_mouse_cursor (CtkTextView *text_view) |
5030 | { |
5031 | if (text_view->priv->mouse_cursor_obscured) |
5032 | { |
5033 | CdkDisplay *display; |
5034 | CdkCursor *cursor; |
5035 | |
5036 | display = ctk_widget_get_display (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
5037 | cursor = cdk_cursor_new_from_name (display, "text"); |
5038 | cdk_window_set_cursor (text_view->priv->text_window->bin_window, cursor); |
5039 | g_object_unref (cursor); |
5040 | text_view->priv->mouse_cursor_obscured = FALSE(0); |
5041 | } |
5042 | } |
5043 | |
5044 | /* |
5045 | * Events |
5046 | */ |
5047 | |
5048 | static gboolean |
5049 | get_event_coordinates (CdkEvent *event, gint *x, gint *y) |
5050 | { |
5051 | if (event) |
5052 | switch (event->type) |
5053 | { |
5054 | case CDK_MOTION_NOTIFY: |
5055 | *x = event->motion.x; |
5056 | *y = event->motion.y; |
5057 | return TRUE(!(0)); |
5058 | break; |
5059 | |
5060 | case CDK_BUTTON_PRESS: |
5061 | case CDK_2BUTTON_PRESS: |
5062 | case CDK_3BUTTON_PRESS: |
5063 | case CDK_BUTTON_RELEASE: |
5064 | *x = event->button.x; |
5065 | *y = event->button.y; |
5066 | return TRUE(!(0)); |
5067 | break; |
5068 | |
5069 | case CDK_KEY_PRESS: |
5070 | case CDK_KEY_RELEASE: |
5071 | case CDK_ENTER_NOTIFY: |
5072 | case CDK_LEAVE_NOTIFY: |
5073 | case CDK_PROPERTY_NOTIFY: |
5074 | case CDK_SELECTION_CLEAR: |
5075 | case CDK_SELECTION_REQUEST: |
5076 | case CDK_SELECTION_NOTIFY: |
5077 | case CDK_PROXIMITY_IN: |
5078 | case CDK_PROXIMITY_OUT: |
5079 | case CDK_DRAG_ENTER: |
5080 | case CDK_DRAG_LEAVE: |
5081 | case CDK_DRAG_MOTION: |
5082 | case CDK_DRAG_STATUS: |
5083 | case CDK_DROP_START: |
5084 | case CDK_DROP_FINISHED: |
5085 | default: |
5086 | return FALSE(0); |
5087 | break; |
5088 | } |
5089 | |
5090 | return FALSE(0); |
5091 | } |
5092 | |
5093 | static gint |
5094 | emit_event_on_tags (CtkWidget *widget, |
5095 | CdkEvent *event, |
5096 | CtkTextIter *iter) |
5097 | { |
5098 | GSList *tags; |
5099 | GSList *tmp; |
5100 | gboolean retval = FALSE(0); |
5101 | |
5102 | tags = ctk_text_iter_get_tags (iter); |
5103 | |
5104 | tmp = tags; |
5105 | while (tmp != NULL((void*)0)) |
5106 | { |
5107 | CtkTextTag *tag = tmp->data; |
5108 | |
5109 | if (ctk_text_tag_event (tag, G_OBJECT (widget)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), (((GType) ((20) << (2)))))))), event, iter)) |
5110 | { |
5111 | retval = TRUE(!(0)); |
5112 | break; |
5113 | } |
5114 | |
5115 | tmp = tmp->next; |
5116 | } |
5117 | |
5118 | g_slist_free (tags); |
5119 | |
5120 | return retval; |
5121 | } |
5122 | |
5123 | static void |
5124 | _text_window_to_widget_coords (CtkTextView *text_view, |
5125 | gint *x, |
5126 | gint *y) |
5127 | { |
5128 | CtkTextViewPrivate *priv = text_view->priv; |
5129 | gint border_width = ctk_container_get_border_width (CTK_CONTAINER (text_view)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_container_get_type ()))))))); |
5130 | |
5131 | *x += border_width; |
5132 | *y += border_width; |
5133 | |
5134 | if (priv->top_window) |
5135 | (*y) += priv->top_window->requisition.height; |
5136 | if (priv->left_window) |
5137 | (*x) += priv->left_window->requisition.width; |
5138 | } |
5139 | |
5140 | static void |
5141 | _widget_to_text_window_coords (CtkTextView *text_view, |
5142 | gint *x, |
5143 | gint *y) |
5144 | { |
5145 | CtkTextViewPrivate *priv = text_view->priv; |
5146 | gint border_width = ctk_container_get_border_width (CTK_CONTAINER (text_view)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_container_get_type ()))))))); |
5147 | |
5148 | *x -= border_width; |
5149 | *y -= border_width; |
5150 | |
5151 | if (priv->top_window) |
5152 | (*y) -= priv->top_window->requisition.height; |
5153 | if (priv->left_window) |
5154 | (*x) -= priv->left_window->requisition.width; |
5155 | } |
5156 | |
5157 | static void |
5158 | ctk_text_view_set_handle_position (CtkTextView *text_view, |
5159 | CtkTextIter *iter, |
5160 | CtkTextHandlePosition pos) |
5161 | { |
5162 | CtkTextViewPrivate *priv; |
5163 | CdkRectangle rect; |
5164 | gint x, y; |
5165 | |
5166 | priv = text_view->priv; |
5167 | ctk_text_view_get_cursor_locations (text_view, iter, &rect, NULL((void*)0)); |
5168 | |
5169 | x = rect.x - priv->xoffset; |
5170 | y = rect.y - priv->yoffset; |
5171 | |
5172 | if (!_ctk_text_handle_get_is_dragged (priv->text_handle, pos) && |
5173 | (x < 0 || x > SCREEN_WIDTH (text_view)text_window_get_width (((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((text_view)), ((ctk_text_view_get_type () ))))))->priv->text_window) || |
5174 | y < 0 || y > SCREEN_HEIGHT (text_view)text_window_get_height (((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((text_view)), ((ctk_text_view_get_type () ))))))->priv->text_window))) |
5175 | { |
5176 | /* Hide the handle if it's not being manipulated |
5177 | * and fell outside of the visible text area. |
5178 | */ |
5179 | _ctk_text_handle_set_visible (priv->text_handle, pos, FALSE(0)); |
5180 | } |
5181 | else |
5182 | { |
5183 | CtkTextDirection dir = CTK_TEXT_DIR_LTR; |
5184 | CtkTextAttributes attributes = { 0 }; |
5185 | |
5186 | _ctk_text_handle_set_visible (priv->text_handle, pos, TRUE(!(0))); |
5187 | |
5188 | rect.x = CLAMP (x, 0, SCREEN_WIDTH (text_view))(((x) > (text_window_get_width (((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((text_view)), ( (ctk_text_view_get_type ()))))))->priv->text_window))) ? (text_window_get_width (((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((text_view)), ((ctk_text_view_get_type () ))))))->priv->text_window)) : (((x) < (0)) ? (0) : ( x))); |
5189 | rect.y = CLAMP (y, 0, SCREEN_HEIGHT (text_view))(((y) > (text_window_get_height (((((CtkTextView*) (void * ) g_type_check_instance_cast ((GTypeInstance*) ((text_view)), ((ctk_text_view_get_type ()))))))->priv->text_window)) ) ? (text_window_get_height (((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((text_view)), ((ctk_text_view_get_type () ))))))->priv->text_window)) : (((y) < (0)) ? (0) : ( y))); |
5190 | _text_window_to_widget_coords (text_view, &rect.x, &rect.y); |
5191 | |
5192 | _ctk_text_handle_set_position (priv->text_handle, pos, &rect); |
5193 | |
5194 | if (ctk_text_iter_get_attributes (iter, &attributes)) |
5195 | dir = attributes.direction; |
5196 | |
5197 | _ctk_text_handle_set_direction (priv->text_handle, pos, dir); |
5198 | } |
5199 | } |
5200 | |
5201 | static void |
5202 | ctk_text_view_show_magnifier (CtkTextView *text_view, |
5203 | CtkTextIter *iter, |
5204 | gint x, |
5205 | gint y G_GNUC_UNUSED__attribute__ ((__unused__))) |
5206 | { |
5207 | cairo_rectangle_int_t rect; |
5208 | CtkTextViewPrivate *priv; |
5209 | CtkAllocation allocation; |
5210 | CtkRequisition req; |
5211 | |
5212 | #define N_LINES 1 |
5213 | |
5214 | ctk_widget_get_allocation (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))), &allocation); |
5215 | |
5216 | priv = text_view->priv; |
5217 | _ctk_text_view_ensure_magnifier (text_view); |
5218 | |
5219 | /* Set size/content depending on iter rect */ |
5220 | ctk_text_view_get_iter_location (text_view, iter, |
5221 | (CdkRectangle *) &rect); |
5222 | rect.x = x + priv->xoffset; |
5223 | ctk_text_view_buffer_to_window_coords (text_view, CTK_TEXT_WINDOW_TEXT, |
5224 | rect.x, rect.y, &rect.x, &rect.y); |
5225 | _text_window_to_widget_coords (text_view, &rect.x, &rect.y); |
5226 | req.height = rect.height * N_LINES * |
5227 | _ctk_magnifier_get_magnification (CTK_MAGNIFIER (priv->magnifier)((((CtkMagnifier*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((priv->magnifier)), ((_ctk_magnifier_get_type ()))))))); |
5228 | req.width = MAX ((req.height * 4) / 3, 80)((((req.height * 4) / 3) > (80)) ? ((req.height * 4) / 3) : (80)); |
5229 | ctk_widget_set_size_request (priv->magnifier, req.width, req.height); |
5230 | |
5231 | _ctk_magnifier_set_coords (CTK_MAGNIFIER (priv->magnifier)((((CtkMagnifier*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((priv->magnifier)), ((_ctk_magnifier_get_type ())))))), |
5232 | rect.x, rect.y + rect.height / 2); |
5233 | |
5234 | rect.x = CLAMP (rect.x, 0, allocation.width)(((rect.x) > (allocation.width)) ? (allocation.width) : (( (rect.x) < (0)) ? (0) : (rect.x))); |
5235 | rect.y += rect.height / 4; |
5236 | rect.height -= rect.height / 4; |
5237 | ctk_popover_set_pointing_to (CTK_POPOVER (priv->magnifier_popover)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((priv->magnifier_popover)), ((ctk_popover_get_type ()) ))))), |
5238 | &rect); |
5239 | |
5240 | ctk_popover_popup (CTK_POPOVER (priv->magnifier_popover)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((priv->magnifier_popover)), ((ctk_popover_get_type ()) )))))); |
5241 | |
5242 | #undef N_LINES |
5243 | } |
5244 | |
5245 | static void |
5246 | ctk_text_view_handle_dragged (CtkTextHandle *handle, |
5247 | CtkTextHandlePosition pos, |
5248 | gint x, |
5249 | gint y, |
5250 | CtkTextView *text_view) |
5251 | { |
5252 | CtkTextViewPrivate *priv; |
5253 | CtkTextIter old_cursor, old_bound; |
5254 | CtkTextIter cursor, bound, iter; |
5255 | CtkTextIter *min, *max; |
5256 | CtkTextHandleMode mode; |
5257 | CtkTextBuffer *buffer; |
5258 | CtkTextHandlePosition cursor_pos; |
5259 | |
5260 | priv = text_view->priv; |
5261 | buffer = get_buffer (text_view); |
5262 | mode = _ctk_text_handle_get_mode (handle); |
5263 | |
5264 | _widget_to_text_window_coords (text_view, &x, &y); |
5265 | |
5266 | ctk_text_view_selection_bubble_popup_unset (text_view); |
5267 | ctk_text_layout_get_iter_at_pixel (priv->layout, &iter, |
5268 | x + priv->xoffset, |
5269 | y + priv->yoffset); |
5270 | ctk_text_buffer_get_iter_at_mark (buffer, &old_cursor, |
5271 | ctk_text_buffer_get_insert (buffer)); |
5272 | ctk_text_buffer_get_iter_at_mark (buffer, &old_bound, |
5273 | ctk_text_buffer_get_selection_bound (buffer)); |
5274 | cursor = old_cursor; |
5275 | bound = old_bound; |
5276 | |
5277 | if (mode == CTK_TEXT_HANDLE_MODE_CURSOR || |
5278 | ctk_text_iter_compare (&cursor, &bound) >= 0) |
5279 | { |
5280 | cursor_pos = CTK_TEXT_HANDLE_POSITION_CURSOR; |
5281 | max = &cursor; |
5282 | min = &bound; |
5283 | } |
5284 | else |
5285 | { |
5286 | cursor_pos = CTK_TEXT_HANDLE_POSITION_SELECTION_START; |
5287 | max = &bound; |
5288 | min = &cursor; |
5289 | } |
5290 | |
5291 | if (pos == CTK_TEXT_HANDLE_POSITION_SELECTION_END) |
5292 | { |
5293 | if (mode == CTK_TEXT_HANDLE_MODE_SELECTION && |
5294 | ctk_text_iter_compare (&iter, min) <= 0) |
5295 | { |
5296 | iter = *min; |
5297 | ctk_text_iter_forward_char (&iter); |
5298 | } |
5299 | |
5300 | *max = iter; |
5301 | ctk_text_view_set_handle_position (text_view, &iter, pos); |
5302 | } |
5303 | else |
5304 | { |
5305 | if (mode == CTK_TEXT_HANDLE_MODE_SELECTION && |
5306 | ctk_text_iter_compare (&iter, max) >= 0) |
5307 | { |
5308 | iter = *max; |
5309 | ctk_text_iter_backward_char (&iter); |
5310 | } |
5311 | |
5312 | *min = iter; |
5313 | ctk_text_view_set_handle_position (text_view, &iter, pos); |
5314 | } |
5315 | |
5316 | if (ctk_text_iter_compare (&old_cursor, &cursor) != 0 || |
5317 | ctk_text_iter_compare (&old_bound, &bound) != 0) |
5318 | { |
5319 | if (mode == CTK_TEXT_HANDLE_MODE_CURSOR) |
5320 | ctk_text_buffer_place_cursor (buffer, &cursor); |
5321 | else |
5322 | ctk_text_buffer_select_range (buffer, &cursor, &bound); |
5323 | |
5324 | if (_ctk_text_handle_get_is_dragged (priv->text_handle, cursor_pos)) |
5325 | { |
5326 | text_view->priv->cursor_handle_dragged = TRUE(!(0)); |
5327 | ctk_text_view_scroll_mark_onscreen (text_view, |
5328 | ctk_text_buffer_get_insert (buffer)); |
5329 | } |
5330 | else |
5331 | { |
5332 | text_view->priv->selection_handle_dragged = TRUE(!(0)); |
5333 | ctk_text_view_scroll_mark_onscreen (text_view, |
5334 | ctk_text_buffer_get_selection_bound (buffer)); |
5335 | } |
5336 | } |
5337 | |
5338 | if (_ctk_text_handle_get_is_dragged (priv->text_handle, cursor_pos)) |
5339 | ctk_text_view_show_magnifier (text_view, &cursor, x, y); |
5340 | else |
5341 | ctk_text_view_show_magnifier (text_view, &bound, x, y); |
5342 | } |
5343 | |
5344 | static void |
5345 | ctk_text_view_handle_drag_started (CtkTextHandle *handle G_GNUC_UNUSED__attribute__ ((__unused__)), |
5346 | CtkTextHandlePosition pos G_GNUC_UNUSED__attribute__ ((__unused__)), |
5347 | CtkTextView *text_view) |
5348 | { |
5349 | text_view->priv->cursor_handle_dragged = FALSE(0); |
5350 | text_view->priv->selection_handle_dragged = FALSE(0); |
5351 | } |
5352 | |
5353 | static void |
5354 | ctk_text_view_handle_drag_finished (CtkTextHandle *handle G_GNUC_UNUSED__attribute__ ((__unused__)), |
5355 | CtkTextHandlePosition pos G_GNUC_UNUSED__attribute__ ((__unused__)), |
5356 | CtkTextView *text_view) |
5357 | { |
5358 | CtkTextViewPrivate *priv = text_view->priv; |
5359 | |
5360 | if (!priv->cursor_handle_dragged && !priv->selection_handle_dragged) |
5361 | { |
5362 | CtkTextBuffer *buffer; |
5363 | CtkTextIter cursor, start, end; |
5364 | CtkSettings *settings; |
5365 | guint double_click_time; |
5366 | |
5367 | settings = ctk_widget_get_settings (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
5368 | g_object_get (settings, "ctk-double-click-time", &double_click_time, NULL((void*)0)); |
5369 | if (g_get_monotonic_time() - priv->handle_place_time < double_click_time * 1000) |
5370 | { |
5371 | buffer = get_buffer (text_view); |
5372 | ctk_text_buffer_get_iter_at_mark (buffer, &cursor, |
5373 | ctk_text_buffer_get_insert (buffer)); |
5374 | extend_selection (text_view, SELECT_WORDS, &cursor, &start, &end); |
5375 | ctk_text_buffer_select_range (buffer, &start, &end); |
5376 | |
5377 | ctk_text_view_update_handles (text_view, CTK_TEXT_HANDLE_MODE_SELECTION); |
5378 | } |
5379 | else |
5380 | ctk_text_view_selection_bubble_popup_set (text_view); |
5381 | } |
5382 | |
5383 | if (priv->magnifier_popover) |
5384 | ctk_popover_popdown (CTK_POPOVER (priv->magnifier_popover)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((priv->magnifier_popover)), ((ctk_popover_get_type ()) )))))); |
5385 | } |
5386 | |
5387 | static gboolean cursor_visible (CtkTextView *text_view); |
5388 | |
5389 | static void |
5390 | ctk_text_view_update_handles (CtkTextView *text_view, |
5391 | CtkTextHandleMode mode) |
5392 | { |
5393 | CtkTextViewPrivate *priv = text_view->priv; |
5394 | CtkTextIter cursor, bound, min, max; |
5395 | CtkTextBuffer *buffer; |
5396 | |
5397 | buffer = get_buffer (text_view); |
5398 | |
5399 | ctk_text_buffer_get_iter_at_mark (buffer, &cursor, |
5400 | ctk_text_buffer_get_insert (buffer)); |
5401 | ctk_text_buffer_get_iter_at_mark (buffer, &bound, |
5402 | ctk_text_buffer_get_selection_bound (buffer)); |
5403 | |
5404 | if (mode == CTK_TEXT_HANDLE_MODE_SELECTION && |
5405 | ctk_text_iter_compare (&cursor, &bound) == 0) |
5406 | { |
5407 | mode = CTK_TEXT_HANDLE_MODE_CURSOR; |
5408 | } |
5409 | |
5410 | if (mode == CTK_TEXT_HANDLE_MODE_CURSOR && |
5411 | (!ctk_widget_is_sensitive (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))) || !cursor_visible (text_view))) |
5412 | { |
5413 | mode = CTK_TEXT_HANDLE_MODE_NONE; |
5414 | } |
5415 | |
5416 | _ctk_text_handle_set_mode (priv->text_handle, mode); |
5417 | |
5418 | if (ctk_text_iter_compare (&cursor, &bound) >= 0) |
5419 | { |
5420 | min = bound; |
5421 | max = cursor; |
5422 | } |
5423 | else |
5424 | { |
5425 | min = cursor; |
5426 | max = bound; |
5427 | } |
5428 | |
5429 | if (mode != CTK_TEXT_HANDLE_MODE_NONE) |
5430 | ctk_text_view_set_handle_position (text_view, &max, |
5431 | CTK_TEXT_HANDLE_POSITION_SELECTION_END); |
5432 | |
5433 | if (mode == CTK_TEXT_HANDLE_MODE_SELECTION) |
5434 | ctk_text_view_set_handle_position (text_view, &min, |
5435 | CTK_TEXT_HANDLE_POSITION_SELECTION_START); |
5436 | } |
5437 | |
5438 | static gint |
5439 | ctk_text_view_event (CtkWidget *widget, CdkEvent *event) |
5440 | { |
5441 | CtkTextView *text_view; |
5442 | CtkTextViewPrivate *priv; |
5443 | gint x = 0, y = 0; |
5444 | |
5445 | text_view = CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ())))))); |
5446 | priv = text_view->priv; |
5447 | |
5448 | if (priv->layout == NULL((void*)0) || |
5449 | get_buffer (text_view) == NULL((void*)0)) |
5450 | return FALSE(0); |
5451 | |
5452 | if (event->any.window != priv->text_window->bin_window) |
5453 | return FALSE(0); |
5454 | |
5455 | if (get_event_coordinates (event, &x, &y)) |
5456 | { |
5457 | CtkTextIter iter; |
5458 | |
5459 | x += priv->xoffset; |
5460 | y += priv->yoffset; |
5461 | |
5462 | /* FIXME this is slow and we do it twice per event. |
5463 | * My favorite solution is to have CtkTextLayout cache |
5464 | * the last couple lookups. |
5465 | */ |
5466 | ctk_text_layout_get_iter_at_pixel (priv->layout, |
5467 | &iter, |
5468 | x, y); |
5469 | |
5470 | return emit_event_on_tags (widget, event, &iter); |
5471 | } |
5472 | else if (event->type == CDK_KEY_PRESS || |
5473 | event->type == CDK_KEY_RELEASE) |
5474 | { |
5475 | CtkTextIter iter; |
5476 | |
5477 | ctk_text_buffer_get_iter_at_mark (get_buffer (text_view), &iter, |
5478 | ctk_text_buffer_get_insert (get_buffer (text_view))); |
5479 | |
5480 | return emit_event_on_tags (widget, event, &iter); |
5481 | } |
5482 | else |
5483 | return FALSE(0); |
5484 | } |
5485 | |
5486 | static gint |
5487 | ctk_text_view_key_press_event (CtkWidget *widget, CdkEventKey *event) |
5488 | { |
5489 | CtkTextView *text_view; |
5490 | CtkTextViewPrivate *priv; |
5491 | CtkTextMark *insert; |
5492 | CtkTextIter iter; |
5493 | gboolean can_insert; |
5494 | gboolean retval = FALSE(0); |
5495 | |
5496 | text_view = CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ())))))); |
5497 | priv = text_view->priv; |
5498 | |
5499 | if (priv->layout == NULL((void*)0) || get_buffer (text_view) == NULL((void*)0)) |
5500 | return FALSE(0); |
5501 | |
5502 | priv->handling_key_event = TRUE(!(0)); |
5503 | |
5504 | /* Make sure input method knows where it is */ |
5505 | flush_update_im_spot_location (text_view); |
5506 | |
5507 | insert = ctk_text_buffer_get_insert (get_buffer (text_view)); |
5508 | ctk_text_buffer_get_iter_at_mark (get_buffer (text_view), &iter, insert); |
5509 | can_insert = ctk_text_iter_can_insert (&iter, priv->editable); |
5510 | if (ctk_im_context_filter_keypress (priv->im_context, event)) |
5511 | { |
5512 | priv->need_im_reset = TRUE(!(0)); |
5513 | if (!can_insert) |
5514 | ctk_text_view_reset_im_context (text_view); |
5515 | retval = TRUE(!(0)); |
5516 | } |
5517 | /* Binding set */ |
5518 | else if (CTK_WIDGET_CLASS (ctk_text_view_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((ctk_text_view_parent_class)), ((ctk_widget_get_type ())) ))))->key_press_event (widget, event)) |
5519 | { |
5520 | retval = TRUE(!(0)); |
5521 | } |
5522 | /* use overall editability not can_insert, more predictable for users */ |
5523 | else if (priv->editable && |
5524 | (event->keyval == CDK_KEY_Return0xff0d || |
5525 | event->keyval == CDK_KEY_ISO_Enter0xfe34 || |
5526 | event->keyval == CDK_KEY_KP_Enter0xff8d)) |
5527 | { |
5528 | /* this won't actually insert the newline if the cursor isn't |
5529 | * editable |
5530 | */ |
5531 | ctk_text_view_reset_im_context (text_view); |
5532 | ctk_text_view_commit_text (text_view, "\n"); |
5533 | retval = TRUE(!(0)); |
5534 | } |
5535 | /* Pass through Tab as literal tab, unless Control is held down */ |
5536 | else if ((event->keyval == CDK_KEY_Tab0xff09 || |
5537 | event->keyval == CDK_KEY_KP_Tab0xff89 || |
5538 | event->keyval == CDK_KEY_ISO_Left_Tab0xfe20) && |
5539 | !(event->state & CDK_CONTROL_MASK)) |
5540 | { |
5541 | /* If the text widget isn't editable overall, or if the application |
5542 | * has turned off "accepts_tab", move the focus instead |
5543 | */ |
5544 | if (priv->accepts_tab && priv->editable) |
5545 | { |
5546 | ctk_text_view_reset_im_context (text_view); |
5547 | ctk_text_view_commit_text (text_view, "\t"); |
5548 | } |
5549 | else |
5550 | g_signal_emit_by_name (text_view, "move-focus", |
5551 | (event->state & CDK_SHIFT_MASK) ? |
5552 | CTK_DIR_TAB_BACKWARD : CTK_DIR_TAB_FORWARD); |
5553 | |
5554 | retval = TRUE(!(0)); |
5555 | } |
5556 | else |
5557 | retval = FALSE(0); |
5558 | |
5559 | ctk_text_view_reset_blink_time (text_view); |
5560 | ctk_text_view_pend_cursor_blink (text_view); |
5561 | |
5562 | if (!event->send_event && priv->text_handle) |
5563 | _ctk_text_handle_set_mode (priv->text_handle, |
5564 | CTK_TEXT_HANDLE_MODE_NONE); |
5565 | |
5566 | ctk_text_view_selection_bubble_popup_unset (text_view); |
5567 | |
5568 | priv->handling_key_event = FALSE(0); |
5569 | |
5570 | return retval; |
5571 | } |
5572 | |
5573 | static gint |
5574 | ctk_text_view_key_release_event (CtkWidget *widget, CdkEventKey *event) |
5575 | { |
5576 | CtkTextView *text_view; |
5577 | CtkTextViewPrivate *priv; |
5578 | CtkTextMark *insert; |
5579 | CtkTextIter iter; |
5580 | gboolean retval = FALSE(0); |
5581 | |
5582 | text_view = CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ())))))); |
5583 | priv = text_view->priv; |
5584 | |
5585 | if (priv->layout == NULL((void*)0) || get_buffer (text_view) == NULL((void*)0)) |
5586 | return FALSE(0); |
5587 | |
5588 | priv->handling_key_event = TRUE(!(0)); |
5589 | |
5590 | insert = ctk_text_buffer_get_insert (get_buffer (text_view)); |
5591 | ctk_text_buffer_get_iter_at_mark (get_buffer (text_view), &iter, insert); |
5592 | if (ctk_text_iter_can_insert (&iter, priv->editable) && |
5593 | ctk_im_context_filter_keypress (priv->im_context, event)) |
5594 | { |
5595 | priv->need_im_reset = TRUE(!(0)); |
5596 | retval = TRUE(!(0)); |
5597 | } |
5598 | else |
5599 | retval = CTK_WIDGET_CLASS (ctk_text_view_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((ctk_text_view_parent_class)), ((ctk_widget_get_type ())) ))))->key_release_event (widget, event); |
5600 | |
5601 | priv->handling_key_event = FALSE(0); |
5602 | |
5603 | return retval; |
5604 | } |
5605 | |
5606 | static gboolean |
5607 | get_iter_from_gesture (CtkTextView *text_view, |
5608 | CtkGesture *gesture, |
5609 | CtkTextIter *iter, |
5610 | gint *x, |
5611 | gint *y) |
5612 | { |
5613 | CdkEventSequence *sequence; |
5614 | CtkTextViewPrivate *priv; |
5615 | gint xcoord, ycoord; |
5616 | gdouble px, py; |
5617 | |
5618 | priv = text_view->priv; |
5619 | sequence = |
5620 | ctk_gesture_single_get_current_sequence (CTK_GESTURE_SINGLE (gesture)((((CtkGestureSingle*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((gesture)), ((ctk_gesture_single_get_type () ))))))); |
5621 | |
5622 | if (!ctk_gesture_get_point (gesture, sequence, &px, &py)) |
5623 | return FALSE(0); |
5624 | |
5625 | xcoord = px + priv->xoffset; |
5626 | ycoord = py + priv->yoffset; |
5627 | _widget_to_text_window_coords (text_view, &xcoord, &ycoord); |
5628 | ctk_text_layout_get_iter_at_pixel (priv->layout, iter, xcoord, ycoord); |
5629 | |
5630 | if (x) |
5631 | *x = xcoord; |
5632 | if (y) |
5633 | *y = ycoord; |
5634 | |
5635 | return TRUE(!(0)); |
5636 | } |
5637 | |
5638 | static void |
5639 | ctk_text_view_multipress_gesture_pressed (CtkGestureMultiPress *gesture, |
5640 | gint n_press, |
5641 | gdouble x G_GNUC_UNUSED__attribute__ ((__unused__)), |
5642 | gdouble y G_GNUC_UNUSED__attribute__ ((__unused__)), |
5643 | CtkTextView *text_view) |
5644 | { |
5645 | CdkEventSequence *sequence; |
5646 | CtkTextViewPrivate *priv; |
5647 | const CdkEvent *event; |
5648 | gboolean is_touchscreen; |
5649 | CdkDevice *device; |
5650 | CtkTextIter iter; |
5651 | guint button; |
5652 | |
5653 | priv = text_view->priv; |
5654 | 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 () ))))))); |
5655 | 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 () ))))))); |
5656 | event = ctk_gesture_get_last_event (CTK_GESTURE (gesture)((((CtkGesture*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((gesture)), ((ctk_gesture_get_type ())))))), sequence); |
5657 | |
5658 | ctk_widget_grab_focus (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
5659 | |
5660 | if (cdk_event_get_window (event) != priv->text_window->bin_window) |
5661 | { |
5662 | /* Remove selection if any. */ |
5663 | ctk_text_view_unselect (text_view); |
5664 | return; |
5665 | } |
5666 | |
5667 | ctk_gesture_set_sequence_state (CTK_GESTURE (gesture)((((CtkGesture*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((gesture)), ((ctk_gesture_get_type ())))))), sequence, |
5668 | CTK_EVENT_SEQUENCE_CLAIMED); |
5669 | ctk_text_view_reset_blink_time (text_view); |
5670 | |
5671 | #if 0 |
5672 | /* debug hack */ |
5673 | if (event->button == CDK_BUTTON_SECONDARY(3) && (event->state & CDK_CONTROL_MASK) != 0) |
5674 | _ctk_text_buffer_spew (CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ()))))))->buffer); |
5675 | else if (event->button == CDK_BUTTON_SECONDARY(3)) |
5676 | ctk_text_layout_spew (CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ()))))))->layout); |
5677 | #endif |
5678 | |
5679 | device = cdk_event_get_source_device ((CdkEvent *) event); |
5680 | is_touchscreen = ctk_simulate_touchscreen () || |
5681 | cdk_device_get_source (device) == CDK_SOURCE_TOUCHSCREEN; |
5682 | |
5683 | if (n_press == 1) |
5684 | ctk_text_view_reset_im_context (text_view); |
5685 | |
5686 | if (n_press == 1 && |
5687 | cdk_event_triggers_context_menu (event)) |
5688 | { |
5689 | ctk_text_view_do_popup (text_view, event); |
5690 | } |
5691 | else if (button == CDK_BUTTON_MIDDLE(2) && |
5692 | get_middle_click_paste (text_view)) |
5693 | { |
5694 | get_iter_from_gesture (text_view, priv->multipress_gesture, |
5695 | &iter, NULL((void*)0), NULL((void*)0)); |
5696 | ctk_text_buffer_paste_clipboard (get_buffer (text_view), |
5697 | ctk_widget_get_clipboard (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))), |
5698 | CDK_SELECTION_PRIMARY((CdkAtom)((gpointer) (gulong) (1)))), |
5699 | &iter, |
5700 | priv->editable); |
5701 | } |
5702 | else if (button == CDK_BUTTON_PRIMARY(1)) |
5703 | { |
5704 | CtkTextHandleMode handle_mode = CTK_TEXT_HANDLE_MODE_NONE; |
5705 | gboolean extends = FALSE(0); |
5706 | CdkModifierType state; |
5707 | |
5708 | cdk_event_get_state (event, &state); |
5709 | |
5710 | if (state & |
5711 | ctk_widget_get_modifier_mask (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))), |
5712 | CDK_MODIFIER_INTENT_EXTEND_SELECTION)) |
5713 | extends = TRUE(!(0)); |
5714 | |
5715 | switch (n_press) |
5716 | { |
5717 | case 1: |
5718 | { |
5719 | /* If we're in the selection, start a drag copy/move of the |
5720 | * selection; otherwise, start creating a new selection. |
5721 | */ |
5722 | CtkTextIter start, end; |
5723 | |
5724 | if (is_touchscreen) |
5725 | handle_mode = CTK_TEXT_HANDLE_MODE_CURSOR; |
5726 | |
5727 | get_iter_from_gesture (text_view, priv->multipress_gesture, |
5728 | &iter, NULL((void*)0), NULL((void*)0)); |
5729 | |
5730 | if (ctk_text_buffer_get_selection_bounds (get_buffer (text_view), |
5731 | &start, &end) && |
5732 | ctk_text_iter_in_range (&iter, &start, &end) && !extends) |
5733 | { |
5734 | if (is_touchscreen) |
5735 | { |
5736 | if (!priv->selection_bubble || |
5737 | !ctk_widget_get_visible (priv->selection_bubble)) |
5738 | { |
5739 | ctk_text_view_selection_bubble_popup_set (text_view); |
5740 | handle_mode = CTK_TEXT_HANDLE_MODE_NONE; |
5741 | } |
5742 | else |
5743 | { |
5744 | ctk_text_view_selection_bubble_popup_unset (text_view); |
5745 | handle_mode = CTK_TEXT_HANDLE_MODE_SELECTION; |
5746 | } |
5747 | } |
5748 | else |
5749 | { |
5750 | /* Claim the sequence on the drag gesture, but attach no |
5751 | * selection data, this is a special case to start DnD. |
5752 | */ |
5753 | ctk_gesture_set_state (priv->drag_gesture, |
5754 | CTK_EVENT_SEQUENCE_CLAIMED); |
5755 | } |
5756 | break; |
5757 | } |
5758 | else |
5759 | { |
5760 | ctk_text_view_selection_bubble_popup_unset (text_view); |
5761 | |
5762 | if (is_touchscreen) |
5763 | { |
5764 | ctk_text_buffer_place_cursor (get_buffer (text_view), &iter); |
5765 | priv->handle_place_time = g_get_monotonic_time (); |
5766 | } |
5767 | else |
5768 | ctk_text_view_start_selection_drag (text_view, &iter, |
5769 | SELECT_CHARACTERS, extends); |
5770 | } |
5771 | break; |
5772 | } |
5773 | case 2: |
5774 | case 3: |
5775 | if (is_touchscreen) |
5776 | { |
5777 | handle_mode = CTK_TEXT_HANDLE_MODE_SELECTION; |
5778 | break; |
5779 | } |
5780 | ctk_text_view_end_selection_drag (text_view); |
5781 | |
5782 | get_iter_from_gesture (text_view, priv->multipress_gesture, |
5783 | &iter, NULL((void*)0), NULL((void*)0)); |
5784 | ctk_text_view_start_selection_drag (text_view, &iter, |
5785 | n_press == 2 ? SELECT_WORDS : SELECT_LINES, |
5786 | extends); |
5787 | break; |
5788 | default: |
5789 | break; |
5790 | } |
5791 | |
5792 | _ctk_text_view_ensure_text_handles (text_view); |
5793 | ctk_text_view_update_handles (text_view, handle_mode); |
5794 | } |
5795 | |
5796 | if (n_press >= 3) |
5797 | ctk_event_controller_reset (CTK_EVENT_CONTROLLER (gesture)((((CtkEventController*) (void *) g_type_check_instance_cast ( (GTypeInstance*) ((gesture)), ((ctk_event_controller_get_type ()))))))); |
5798 | } |
5799 | |
5800 | static void |
5801 | keymap_direction_changed (CdkKeymap *keymap G_GNUC_UNUSED__attribute__ ((__unused__)), |
5802 | CtkTextView *text_view) |
5803 | { |
5804 | ctk_text_view_check_keymap_direction (text_view); |
5805 | } |
5806 | |
5807 | static gint |
5808 | ctk_text_view_focus_in_event (CtkWidget *widget, |
5809 | CdkEventFocus *event G_GNUC_UNUSED__attribute__ ((__unused__))) |
5810 | { |
5811 | CtkTextView *text_view; |
5812 | CtkTextViewPrivate *priv; |
5813 | |
5814 | text_view = CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ())))))); |
5815 | priv = text_view->priv; |
5816 | |
5817 | ctk_widget_queue_draw (widget); |
5818 | |
5819 | DV(g_print (G_STRLOC": focus_in_event\n")); |
5820 | |
5821 | ctk_text_view_reset_blink_time (text_view); |
5822 | |
5823 | if (cursor_visible (text_view) && priv->layout) |
5824 | { |
5825 | ctk_text_layout_set_cursor_visible (priv->layout, TRUE(!(0))); |
5826 | ctk_text_view_check_cursor_blink (text_view); |
5827 | } |
5828 | |
5829 | g_signal_connect (cdk_keymap_get_for_display (ctk_widget_get_display (widget)),g_signal_connect_data ((cdk_keymap_get_for_display (ctk_widget_get_display (widget))), ("direction-changed"), (((GCallback) (keymap_direction_changed ))), (text_view), ((void*)0), (GConnectFlags) 0) |
5830 | "direction-changed",g_signal_connect_data ((cdk_keymap_get_for_display (ctk_widget_get_display (widget))), ("direction-changed"), (((GCallback) (keymap_direction_changed ))), (text_view), ((void*)0), (GConnectFlags) 0) |
5831 | G_CALLBACK (keymap_direction_changed), text_view)g_signal_connect_data ((cdk_keymap_get_for_display (ctk_widget_get_display (widget))), ("direction-changed"), (((GCallback) (keymap_direction_changed ))), (text_view), ((void*)0), (GConnectFlags) 0); |
5832 | ctk_text_view_check_keymap_direction (text_view); |
5833 | |
5834 | if (priv->editable) |
5835 | { |
5836 | priv->need_im_reset = TRUE(!(0)); |
5837 | ctk_im_context_focus_in (priv->im_context); |
5838 | } |
5839 | |
5840 | return FALSE(0); |
5841 | } |
5842 | |
5843 | static gint |
5844 | ctk_text_view_focus_out_event (CtkWidget *widget, |
5845 | CdkEventFocus *event G_GNUC_UNUSED__attribute__ ((__unused__))) |
5846 | { |
5847 | CtkTextView *text_view; |
5848 | CtkTextViewPrivate *priv; |
5849 | |
5850 | text_view = CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ())))))); |
5851 | priv = text_view->priv; |
5852 | |
5853 | ctk_text_view_end_selection_drag (text_view); |
5854 | |
5855 | ctk_widget_queue_draw (widget); |
5856 | |
5857 | DV(g_print (G_STRLOC": focus_out_event\n")); |
5858 | |
5859 | if (cursor_visible (text_view) && priv->layout) |
5860 | { |
5861 | ctk_text_view_check_cursor_blink (text_view); |
5862 | ctk_text_layout_set_cursor_visible (priv->layout, FALSE(0)); |
5863 | } |
5864 | |
5865 | g_signal_handlers_disconnect_by_func (cdk_keymap_get_for_display (ctk_widget_get_display (widget)),g_signal_handlers_disconnect_matched ((cdk_keymap_get_for_display (ctk_widget_get_display (widget))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)0), (keymap_direction_changed ), (text_view)) |
5866 | keymap_direction_changed,g_signal_handlers_disconnect_matched ((cdk_keymap_get_for_display (ctk_widget_get_display (widget))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)0), (keymap_direction_changed ), (text_view)) |
5867 | text_view)g_signal_handlers_disconnect_matched ((cdk_keymap_get_for_display (ctk_widget_get_display (widget))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)0), (keymap_direction_changed ), (text_view)); |
5868 | ctk_text_view_selection_bubble_popup_unset (text_view); |
5869 | |
5870 | if (priv->text_handle) |
5871 | _ctk_text_handle_set_mode (priv->text_handle, |
5872 | CTK_TEXT_HANDLE_MODE_NONE); |
5873 | |
5874 | if (priv->editable) |
5875 | { |
5876 | priv->need_im_reset = TRUE(!(0)); |
5877 | ctk_im_context_focus_out (priv->im_context); |
5878 | } |
5879 | |
5880 | return FALSE(0); |
5881 | } |
5882 | |
5883 | static gboolean |
5884 | ctk_text_view_motion_event (CtkWidget *widget, CdkEventMotion *event) |
5885 | { |
5886 | CtkTextView *text_view = CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ())))))); |
5887 | |
5888 | ctk_text_view_unobscure_mouse_cursor (text_view); |
5889 | |
5890 | return CTK_WIDGET_CLASS (ctk_text_view_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((ctk_text_view_parent_class)), ((ctk_widget_get_type ())) ))))->motion_notify_event (widget, event); |
5891 | } |
5892 | |
5893 | static void |
5894 | ctk_text_view_paint (CtkWidget *widget, |
5895 | cairo_t *cr) |
5896 | { |
5897 | CtkTextView *text_view; |
5898 | CtkTextViewPrivate *priv; |
5899 | |
5900 | text_view = CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ())))))); |
5901 | priv = text_view->priv; |
5902 | |
5903 | g_return_if_fail (priv->layout != NULL)do { if ((priv->layout != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "priv->layout != NULL" ); return; } } while (0); |
5904 | g_return_if_fail (priv->xoffset >= - priv->left_padding)do { if ((priv->xoffset >= - priv->left_padding)) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__ )), "priv->xoffset >= - priv->left_padding"); return ; } } while (0); |
5905 | g_return_if_fail (priv->yoffset >= - priv->top_border)do { if ((priv->yoffset >= - priv->top_border)) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__) ), "priv->yoffset >= - priv->top_border"); return; } } while (0); |
5906 | |
5907 | while (priv->first_validate_idle != 0) |
5908 | { |
5909 | DV (g_print (G_STRLOC": first_validate_idle: %d\n", |
5910 | priv->first_validate_idle)); |
5911 | ctk_text_view_flush_first_validate (text_view); |
5912 | } |
5913 | |
5914 | if (!priv->onscreen_validated) |
5915 | { |
5916 | g_warning (G_STRLOC"ctktextview.c" ":" "5916" ": somehow some text lines were modified or scrolling occurred since the last validation of lines on the screen - may be a text widget bug."); |
5917 | g_assert_not_reached ()do { g_assertion_message_expr ("Ctk", "ctktextview.c", 5917, ( (const char*) (__func__)), ((void*)0)); } while (0); |
5918 | } |
5919 | |
5920 | #if 0 |
5921 | printf ("painting %d,%d %d x %d\n", |
5922 | area->x, area->y, |
5923 | area->width, area->height); |
5924 | #endif |
5925 | |
5926 | cairo_save (cr); |
5927 | cairo_translate (cr, -priv->xoffset, -priv->yoffset); |
5928 | |
5929 | ctk_text_layout_draw (priv->layout, |
5930 | widget, |
5931 | cr, |
5932 | NULL((void*)0)); |
5933 | |
5934 | cairo_restore (cr); |
5935 | } |
5936 | |
5937 | static void |
5938 | draw_text (cairo_t *cr, |
5939 | gpointer user_data) |
5940 | { |
5941 | CtkWidget *widget = user_data; |
5942 | CtkTextView *text_view = CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ())))))); |
5943 | CtkTextViewPrivate *priv = text_view->priv; |
5944 | CtkStyleContext *context; |
5945 | |
5946 | context = ctk_widget_get_style_context (widget); |
5947 | ctk_style_context_save_to_node (context, text_view->priv->text_window->css_node); |
5948 | ctk_render_background (context, cr, |
5949 | -priv->xoffset, -priv->yoffset - priv->top_border, |
5950 | MAX (SCREEN_WIDTH (text_view), priv->width)(((text_window_get_width (((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((text_view)), ((ctk_text_view_get_type () ))))))->priv->text_window)) > (priv->width)) ? (text_window_get_width (((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_text_view_get_type ()))))))->priv-> text_window)) : (priv->width)), |
5951 | MAX (SCREEN_HEIGHT (text_view), priv->height)(((text_window_get_height (((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((text_view)), ((ctk_text_view_get_type () ))))))->priv->text_window)) > (priv->height)) ? ( text_window_get_height (((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((text_view)), ((ctk_text_view_get_type () ))))))->priv->text_window)) : (priv->height))); |
5952 | ctk_render_frame (context, cr, |
5953 | -priv->xoffset, -priv->yoffset - priv->top_border, |
5954 | MAX (SCREEN_WIDTH (text_view), priv->width)(((text_window_get_width (((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((text_view)), ((ctk_text_view_get_type () ))))))->priv->text_window)) > (priv->width)) ? (text_window_get_width (((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_text_view_get_type ()))))))->priv-> text_window)) : (priv->width)), |
5955 | MAX (SCREEN_HEIGHT (text_view), priv->height)(((text_window_get_height (((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((text_view)), ((ctk_text_view_get_type () ))))))->priv->text_window)) > (priv->height)) ? ( text_window_get_height (((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((text_view)), ((ctk_text_view_get_type () ))))))->priv->text_window)) : (priv->height))); |
5956 | ctk_style_context_restore (context); |
5957 | |
5958 | if (CTK_TEXT_VIEW_GET_CLASS (text_view)((((CtkTextViewClass*) (((GTypeInstance*) ((text_view)))-> g_class))))->draw_layer != NULL((void*)0)) |
5959 | { |
5960 | cairo_save (cr); |
5961 | CTK_TEXT_VIEW_GET_CLASS (text_view)((((CtkTextViewClass*) (((GTypeInstance*) ((text_view)))-> g_class))))->draw_layer (text_view, CTK_TEXT_VIEW_LAYER_BELOW, cr); |
5962 | cairo_restore (cr); |
5963 | |
5964 | cairo_save (cr); |
5965 | cairo_translate (cr, -priv->xoffset, -priv->yoffset); |
5966 | CTK_TEXT_VIEW_GET_CLASS (text_view)((((CtkTextViewClass*) (((GTypeInstance*) ((text_view)))-> g_class))))->draw_layer (text_view, CTK_TEXT_VIEW_LAYER_BELOW_TEXT, cr); |
5967 | cairo_restore (cr); |
5968 | } |
5969 | |
5970 | ctk_text_view_paint (widget, cr); |
5971 | |
5972 | if (CTK_TEXT_VIEW_GET_CLASS (text_view)((((CtkTextViewClass*) (((GTypeInstance*) ((text_view)))-> g_class))))->draw_layer != NULL((void*)0)) |
5973 | { |
5974 | cairo_save (cr); |
5975 | CTK_TEXT_VIEW_GET_CLASS (text_view)((((CtkTextViewClass*) (((GTypeInstance*) ((text_view)))-> g_class))))->draw_layer (text_view, CTK_TEXT_VIEW_LAYER_ABOVE, cr); |
5976 | cairo_restore (cr); |
5977 | |
5978 | cairo_save (cr); |
5979 | cairo_translate (cr, -priv->xoffset, -priv->yoffset); |
5980 | CTK_TEXT_VIEW_GET_CLASS (text_view)((((CtkTextViewClass*) (((GTypeInstance*) ((text_view)))-> g_class))))->draw_layer (text_view, CTK_TEXT_VIEW_LAYER_ABOVE_TEXT, cr); |
5981 | cairo_restore (cr); |
5982 | } |
5983 | } |
5984 | |
5985 | static void |
5986 | paint_border_window (CtkTextView *text_view, |
5987 | cairo_t *cr, |
5988 | CtkTextWindow *text_window, |
5989 | CtkStyleContext *context) |
5990 | { |
5991 | CdkWindow *window; |
5992 | |
5993 | if (text_window == NULL((void*)0)) |
5994 | return; |
5995 | |
5996 | window = ctk_text_view_get_window (text_view, text_window->type); |
5997 | if (ctk_cairo_should_draw_window (cr, window)) |
5998 | { |
5999 | gint w, h; |
6000 | |
6001 | ctk_style_context_save_to_node (context, text_window->css_node); |
6002 | |
6003 | w = cdk_window_get_width (window); |
6004 | h = cdk_window_get_height (window); |
6005 | |
6006 | cairo_save (cr); |
6007 | ctk_cairo_transform_to_window (cr, CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))), window); |
6008 | ctk_render_background (context, cr, 0, 0, w, h); |
6009 | cairo_restore (cr); |
6010 | |
6011 | ctk_style_context_restore (context); |
6012 | } |
6013 | } |
6014 | |
6015 | static gboolean |
6016 | ctk_text_view_draw (CtkWidget *widget, |
6017 | cairo_t *cr) |
6018 | { |
6019 | CtkTextViewPrivate *priv = ((CtkTextView *)widget)->priv; |
6020 | GSList *tmp_list; |
6021 | CdkWindow *window; |
6022 | CtkStyleContext *context; |
6023 | |
6024 | context = ctk_widget_get_style_context (widget); |
6025 | |
6026 | text_window_set_padding (CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ())))))), context); |
6027 | |
6028 | if (ctk_cairo_should_draw_window (cr, ctk_widget_get_window (widget))) |
6029 | { |
6030 | ctk_render_background (context, cr, |
6031 | 0, 0, |
6032 | ctk_widget_get_allocated_width (widget), |
6033 | ctk_widget_get_allocated_height (widget)); |
6034 | } |
6035 | |
6036 | window = ctk_text_view_get_window (CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ())))))), |
6037 | CTK_TEXT_WINDOW_TEXT); |
6038 | if (ctk_cairo_should_draw_window (cr, window)) |
6039 | { |
6040 | cairo_rectangle_int_t view_rect; |
6041 | cairo_rectangle_int_t canvas_rect; |
6042 | CtkAllocation alloc; |
6043 | |
6044 | DV(g_print (">Exposed ("G_STRLOC")\n")); |
6045 | |
6046 | ctk_widget_get_allocation (widget, &alloc); |
6047 | |
6048 | view_rect.x = 0; |
6049 | view_rect.y = 0; |
6050 | view_rect.width = cdk_window_get_width (window); |
6051 | view_rect.height = cdk_window_get_height (window); |
6052 | |
6053 | canvas_rect.x = -ctk_adjustment_get_value (priv->hadjustment); |
6054 | canvas_rect.y = -ctk_adjustment_get_value (priv->vadjustment); |
6055 | canvas_rect.width = priv->width; |
6056 | canvas_rect.height = priv->height; |
6057 | |
6058 | cairo_save (cr); |
6059 | ctk_cairo_transform_to_window (cr, widget, window); |
6060 | _ctk_pixel_cache_draw (priv->pixel_cache, cr, window, |
6061 | &view_rect, &canvas_rect, |
6062 | draw_text, widget); |
6063 | cairo_restore (cr); |
6064 | } |
6065 | |
6066 | paint_border_window (CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ())))))), cr, priv->left_window, context); |
6067 | paint_border_window (CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ())))))), cr, priv->right_window, context); |
6068 | paint_border_window (CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ())))))), cr, priv->top_window, context); |
6069 | paint_border_window (CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ())))))), cr, priv->bottom_window, context); |
6070 | |
6071 | /* Propagate exposes to all unanchored children. |
6072 | * Anchored children are handled in ctk_text_view_paint(). |
6073 | */ |
6074 | tmp_list = CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ()))))))->priv->children; |
6075 | while (tmp_list != NULL((void*)0)) |
6076 | { |
6077 | CtkTextViewChild *vc = tmp_list->data; |
6078 | |
6079 | /* propagate_draw checks that event->window matches |
6080 | * child->window |
6081 | */ |
6082 | ctk_container_propagate_draw (CTK_CONTAINER (widget)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_container_get_type ())))))), |
6083 | vc->widget, |
6084 | cr); |
6085 | |
6086 | tmp_list = tmp_list->next; |
6087 | } |
6088 | |
6089 | return FALSE(0); |
6090 | } |
6091 | |
6092 | static gboolean |
6093 | ctk_text_view_focus (CtkWidget *widget, |
6094 | CtkDirectionType direction) |
6095 | { |
6096 | CtkContainer *container; |
6097 | gboolean result; |
6098 | |
6099 | container = CTK_CONTAINER (widget)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_container_get_type ())))))); |
6100 | |
6101 | if (!ctk_widget_is_focus (widget) && |
6102 | ctk_container_get_focus_child (container) == NULL((void*)0)) |
6103 | { |
6104 | if (ctk_widget_get_can_focus (widget)) |
6105 | { |
6106 | ctk_widget_grab_focus (widget); |
6107 | return TRUE(!(0)); |
6108 | } |
6109 | |
6110 | return FALSE(0); |
6111 | } |
6112 | else |
6113 | { |
6114 | gboolean can_focus; |
6115 | /* |
6116 | * Unset CAN_FOCUS flag so that ctk_container_focus() allows |
6117 | * children to get the focus |
6118 | */ |
6119 | can_focus = ctk_widget_get_can_focus (widget); |
6120 | ctk_widget_set_can_focus (widget, FALSE(0)); |
6121 | result = CTK_WIDGET_CLASS (ctk_text_view_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((ctk_text_view_parent_class)), ((ctk_widget_get_type ())) ))))->focus (widget, direction); |
6122 | ctk_widget_set_can_focus (widget, can_focus); |
6123 | |
6124 | return result; |
6125 | } |
6126 | } |
6127 | |
6128 | /* |
6129 | * Container |
6130 | */ |
6131 | |
6132 | static void |
6133 | ctk_text_view_add (CtkContainer *container, |
6134 | CtkWidget *child) |
6135 | { |
6136 | /* This is pretty random. */ |
6137 | ctk_text_view_add_child_in_window (CTK_TEXT_VIEW (container)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((container)), ((ctk_text_view_get_type ())))))), |
6138 | child, |
6139 | CTK_TEXT_WINDOW_WIDGET, |
6140 | 0, 0); |
6141 | } |
6142 | |
6143 | static void |
6144 | ctk_text_view_remove (CtkContainer *container, |
6145 | CtkWidget *child) |
6146 | { |
6147 | CtkTextView *text_view; |
6148 | CtkTextViewPrivate *priv; |
6149 | CtkTextViewChild *vc; |
6150 | GSList *iter; |
6151 | |
6152 | text_view = CTK_TEXT_VIEW (container)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((container)), ((ctk_text_view_get_type ())))))); |
6153 | priv = text_view->priv; |
6154 | |
6155 | vc = NULL((void*)0); |
6156 | iter = priv->children; |
6157 | |
6158 | while (iter != NULL((void*)0)) |
6159 | { |
6160 | vc = iter->data; |
6161 | |
6162 | if (vc->widget == child) |
6163 | break; |
6164 | |
6165 | iter = iter->next; |
6166 | } |
6167 | |
6168 | g_assert (iter != NULL)do { if (iter != ((void*)0)) ; else g_assertion_message_expr ( "Ctk", "ctktextview.c", 6168, ((const char*) (__func__)), "iter != NULL" ); } while (0); /* be sure we had the child in the list */ |
6169 | |
6170 | priv->children = g_slist_remove (priv->children, vc); |
6171 | |
6172 | ctk_widget_unparent (vc->widget); |
6173 | |
6174 | text_view_child_free (vc); |
6175 | } |
6176 | |
6177 | static void |
6178 | ctk_text_view_forall (CtkContainer *container, |
6179 | gboolean include_internals G_GNUC_UNUSED__attribute__ ((__unused__)), |
6180 | CtkCallback callback, |
6181 | gpointer callback_data) |
6182 | { |
6183 | GSList *iter; |
6184 | CtkTextView *text_view; |
6185 | GSList *copy; |
6186 | |
6187 | g_return_if_fail (CTK_IS_TEXT_VIEW (container))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((container)); GType __t = ((ctk_text_view_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_TEXT_VIEW (container)"); return; } } while (0); |
6188 | g_return_if_fail (callback != NULL)do { if ((callback != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "callback != NULL"); return ; } } while (0); |
6189 | |
6190 | text_view = CTK_TEXT_VIEW (container)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((container)), ((ctk_text_view_get_type ())))))); |
6191 | |
6192 | copy = g_slist_copy (text_view->priv->children); |
6193 | iter = copy; |
6194 | |
6195 | while (iter != NULL((void*)0)) |
6196 | { |
6197 | CtkTextViewChild *vc = iter->data; |
6198 | |
6199 | (* callback) (vc->widget, callback_data); |
6200 | |
6201 | iter = iter->next; |
6202 | } |
6203 | |
6204 | g_slist_free (copy); |
6205 | } |
6206 | |
6207 | #define CURSOR_ON_MULTIPLIER2 2 |
6208 | #define CURSOR_OFF_MULTIPLIER1 1 |
6209 | #define CURSOR_PEND_MULTIPLIER3 3 |
6210 | #define CURSOR_DIVIDER3 3 |
6211 | |
6212 | static gboolean |
6213 | cursor_blinks (CtkTextView *text_view) |
6214 | { |
6215 | CtkSettings *settings = ctk_widget_get_settings (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
6216 | gboolean blink; |
6217 | |
6218 | #ifdef DEBUG_VALIDATION_AND_SCROLLING |
6219 | return FALSE(0); |
6220 | #endif |
6221 | #ifdef G_ENABLE_DEBUG1 |
6222 | if (CTK_DEBUG_CHECK (UPDATES)(ctk_get_debug_flags () & CTK_DEBUG_UPDATES)) |
6223 | return FALSE(0); |
6224 | #endif |
6225 | |
6226 | g_object_get (settings, "ctk-cursor-blink", &blink, NULL((void*)0)); |
6227 | |
6228 | if (!blink) |
6229 | return FALSE(0); |
6230 | |
6231 | if (text_view->priv->editable) |
6232 | { |
6233 | CtkTextMark *insert; |
6234 | CtkTextIter iter; |
6235 | |
6236 | insert = ctk_text_buffer_get_insert (get_buffer (text_view)); |
6237 | ctk_text_buffer_get_iter_at_mark (get_buffer (text_view), &iter, insert); |
6238 | |
6239 | if (ctk_text_iter_editable (&iter, text_view->priv->editable)) |
6240 | return blink; |
6241 | } |
6242 | |
6243 | return FALSE(0); |
6244 | } |
6245 | |
6246 | static gboolean |
6247 | cursor_visible (CtkTextView *text_view) |
6248 | { |
6249 | CtkSettings *settings = ctk_widget_get_settings (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
6250 | gboolean use_caret; |
6251 | |
6252 | g_object_get (settings, "ctk-keynav-use-caret", &use_caret, NULL((void*)0)); |
6253 | |
6254 | return use_caret || text_view->priv->cursor_visible; |
6255 | } |
6256 | |
6257 | static gboolean |
6258 | get_middle_click_paste (CtkTextView *text_view) |
6259 | { |
6260 | CtkSettings *settings; |
6261 | gboolean paste; |
6262 | |
6263 | settings = ctk_widget_get_settings (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
6264 | g_object_get (settings, "ctk-enable-primary-paste", &paste, NULL((void*)0)); |
6265 | |
6266 | return paste; |
6267 | } |
6268 | |
6269 | static gint |
6270 | get_cursor_time (CtkTextView *text_view) |
6271 | { |
6272 | CtkSettings *settings = ctk_widget_get_settings (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
6273 | gint time; |
6274 | |
6275 | g_object_get (settings, "ctk-cursor-blink-time", &time, NULL((void*)0)); |
6276 | |
6277 | return time; |
6278 | } |
6279 | |
6280 | static gint |
6281 | get_cursor_blink_timeout (CtkTextView *text_view) |
6282 | { |
6283 | CtkSettings *settings = ctk_widget_get_settings (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
6284 | gint time; |
6285 | |
6286 | g_object_get (settings, "ctk-cursor-blink-timeout", &time, NULL((void*)0)); |
6287 | |
6288 | return time; |
6289 | } |
6290 | |
6291 | |
6292 | /* |
6293 | * Blink! |
6294 | */ |
6295 | |
6296 | static gint |
6297 | blink_cb (gpointer data) |
6298 | { |
6299 | CtkTextView *text_view; |
6300 | CtkTextViewPrivate *priv; |
6301 | gboolean visible; |
6302 | gint blink_timeout; |
6303 | |
6304 | text_view = CTK_TEXT_VIEW (data)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((data)), ((ctk_text_view_get_type ())))))); |
6305 | priv = text_view->priv; |
6306 | |
6307 | if (!ctk_widget_has_focus (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))))) |
6308 | { |
6309 | g_warning ("CtkTextView - did not receive focus-out-event. If you\n" |
6310 | "connect a handler to this signal, it must return\n" |
6311 | "FALSE so the text view gets the event as well"); |
6312 | |
6313 | ctk_text_view_check_cursor_blink (text_view); |
6314 | |
6315 | return FALSE(0); |
6316 | } |
6317 | |
6318 | g_assert (priv->layout)do { if (priv->layout) ; else g_assertion_message_expr ("Ctk" , "ctktextview.c", 6318, ((const char*) (__func__)), "priv->layout" ); } while (0); |
6319 | g_assert (cursor_visible (text_view))do { if (cursor_visible (text_view)) ; else g_assertion_message_expr ("Ctk", "ctktextview.c", 6319, ((const char*) (__func__)), "cursor_visible (text_view)" ); } while (0); |
6320 | |
6321 | visible = ctk_text_layout_get_cursor_visible (priv->layout); |
6322 | |
6323 | blink_timeout = get_cursor_blink_timeout (text_view); |
6324 | if (priv->blink_time > 1000 * blink_timeout && |
6325 | blink_timeout < G_MAXINT2147483647/1000) |
6326 | { |
6327 | /* we've blinked enough without the user doing anything, stop blinking */ |
6328 | visible = 0; |
6329 | priv->blink_timeout = 0; |
6330 | } |
6331 | else if (visible) |
6332 | { |
6333 | priv->blink_timeout = cdk_threads_add_timeout (get_cursor_time (text_view) * CURSOR_OFF_MULTIPLIER1 / CURSOR_DIVIDER3, |
6334 | blink_cb, |
6335 | text_view); |
6336 | g_source_set_name_by_id (priv->blink_timeout, "[ctk+] blink_cb"); |
6337 | } |
6338 | else |
6339 | { |
6340 | priv->blink_timeout = cdk_threads_add_timeout (get_cursor_time (text_view) * CURSOR_ON_MULTIPLIER2 / CURSOR_DIVIDER3, |
6341 | blink_cb, |
6342 | text_view); |
6343 | g_source_set_name_by_id (priv->blink_timeout, "[ctk+] blink_cb"); |
6344 | priv->blink_time += get_cursor_time (text_view); |
6345 | } |
6346 | |
6347 | /* Block changed_handler while changing the layout's cursor visibility |
6348 | * because it would expose the whole paragraph. Instead, we expose |
6349 | * the cursor's area(s) manually below. |
6350 | */ |
6351 | g_signal_handlers_block_by_func (priv->layout,g_signal_handlers_block_matched ((priv->layout), (GSignalMatchType ) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*) 0), (changed_handler), (text_view)) |
6352 | changed_handler,g_signal_handlers_block_matched ((priv->layout), (GSignalMatchType ) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*) 0), (changed_handler), (text_view)) |
6353 | text_view)g_signal_handlers_block_matched ((priv->layout), (GSignalMatchType ) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*) 0), (changed_handler), (text_view)); |
6354 | ctk_text_layout_set_cursor_visible (priv->layout, !visible); |
6355 | g_signal_handlers_unblock_by_func (priv->layout,g_signal_handlers_unblock_matched ((priv->layout), (GSignalMatchType ) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*) 0), (changed_handler), (text_view)) |
6356 | changed_handler,g_signal_handlers_unblock_matched ((priv->layout), (GSignalMatchType ) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*) 0), (changed_handler), (text_view)) |
6357 | text_view)g_signal_handlers_unblock_matched ((priv->layout), (GSignalMatchType ) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*) 0), (changed_handler), (text_view)); |
6358 | |
6359 | text_window_invalidate_cursors (priv->text_window); |
6360 | |
6361 | /* Remove ourselves */ |
6362 | return FALSE(0); |
6363 | } |
6364 | |
6365 | |
6366 | static void |
6367 | ctk_text_view_stop_cursor_blink (CtkTextView *text_view) |
6368 | { |
6369 | if (text_view->priv->blink_timeout) |
6370 | { |
6371 | g_source_remove (text_view->priv->blink_timeout); |
6372 | text_view->priv->blink_timeout = 0; |
6373 | } |
6374 | } |
6375 | |
6376 | static void |
6377 | ctk_text_view_check_cursor_blink (CtkTextView *text_view) |
6378 | { |
6379 | CtkTextViewPrivate *priv = text_view->priv; |
6380 | |
6381 | if (priv->layout != NULL((void*)0) && |
6382 | cursor_visible (text_view) && |
6383 | ctk_widget_has_focus (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))))) |
6384 | { |
6385 | if (cursor_blinks (text_view)) |
6386 | { |
6387 | if (priv->blink_timeout == 0) |
6388 | { |
6389 | ctk_text_layout_set_cursor_visible (priv->layout, TRUE(!(0))); |
6390 | |
6391 | priv->blink_timeout = cdk_threads_add_timeout (get_cursor_time (text_view) * CURSOR_OFF_MULTIPLIER1 / CURSOR_DIVIDER3, |
6392 | blink_cb, |
6393 | text_view); |
6394 | g_source_set_name_by_id (priv->blink_timeout, "[ctk+] blink_cb"); |
6395 | } |
6396 | } |
6397 | else |
6398 | { |
6399 | ctk_text_view_stop_cursor_blink (text_view); |
6400 | ctk_text_layout_set_cursor_visible (priv->layout, TRUE(!(0))); |
6401 | } |
6402 | } |
6403 | else |
6404 | { |
6405 | ctk_text_view_stop_cursor_blink (text_view); |
6406 | ctk_text_layout_set_cursor_visible (priv->layout, FALSE(0)); |
6407 | } |
6408 | } |
6409 | |
6410 | static void |
6411 | ctk_text_view_pend_cursor_blink (CtkTextView *text_view) |
6412 | { |
6413 | CtkTextViewPrivate *priv = text_view->priv; |
6414 | |
6415 | if (priv->layout != NULL((void*)0) && |
6416 | cursor_visible (text_view) && |
6417 | ctk_widget_has_focus (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))) && |
6418 | cursor_blinks (text_view)) |
6419 | { |
6420 | ctk_text_view_stop_cursor_blink (text_view); |
6421 | ctk_text_layout_set_cursor_visible (priv->layout, TRUE(!(0))); |
6422 | |
6423 | priv->blink_timeout = cdk_threads_add_timeout (get_cursor_time (text_view) * CURSOR_PEND_MULTIPLIER3 / CURSOR_DIVIDER3, |
6424 | blink_cb, |
6425 | text_view); |
6426 | g_source_set_name_by_id (priv->blink_timeout, "[ctk+] blink_cb"); |
6427 | } |
6428 | } |
6429 | |
6430 | static void |
6431 | ctk_text_view_reset_blink_time (CtkTextView *text_view) |
6432 | { |
6433 | CtkTextViewPrivate *priv = text_view->priv; |
6434 | |
6435 | priv->blink_time = 0; |
6436 | } |
6437 | |
6438 | |
6439 | /* |
6440 | * Key binding handlers |
6441 | */ |
6442 | |
6443 | static gboolean |
6444 | ctk_text_view_move_iter_by_lines (CtkTextView *text_view, |
6445 | CtkTextIter *newplace, |
6446 | gint count) |
6447 | { |
6448 | gboolean ret = TRUE(!(0)); |
6449 | |
6450 | while (count < 0) |
6451 | { |
6452 | ret = ctk_text_layout_move_iter_to_previous_line (text_view->priv->layout, newplace); |
6453 | count++; |
6454 | } |
6455 | |
6456 | while (count > 0) |
6457 | { |
6458 | ret = ctk_text_layout_move_iter_to_next_line (text_view->priv->layout, newplace); |
6459 | count--; |
6460 | } |
6461 | |
6462 | return ret; |
6463 | } |
6464 | |
6465 | static void |
6466 | move_cursor (CtkTextView *text_view, |
6467 | const CtkTextIter *new_location, |
6468 | gboolean extend_selection) |
6469 | { |
6470 | if (extend_selection) |
6471 | ctk_text_buffer_move_mark_by_name (get_buffer (text_view), |
6472 | "insert", |
6473 | new_location); |
6474 | else |
6475 | ctk_text_buffer_place_cursor (get_buffer (text_view), |
6476 | new_location); |
6477 | ctk_text_view_check_cursor_blink (text_view); |
6478 | } |
6479 | |
6480 | static gboolean |
6481 | iter_line_is_rtl (const CtkTextIter *iter) |
6482 | { |
6483 | CtkTextIter start, end; |
6484 | char *text; |
6485 | PangoDirection direction; |
6486 | |
6487 | start = end = *iter; |
6488 | ctk_text_iter_set_line_offset (&start, 0); |
6489 | ctk_text_iter_forward_line (&end); |
6490 | text = ctk_text_iter_get_visible_text (&start, &end); |
6491 | direction = _ctk_pango_find_base_dir (text, -1); |
6492 | |
6493 | g_free (text); |
6494 | |
6495 | return direction == PANGO_DIRECTION_RTL; |
6496 | } |
6497 | |
6498 | static void |
6499 | ctk_text_view_move_cursor (CtkTextView *text_view, |
6500 | CtkMovementStep step, |
6501 | gint count, |
6502 | gboolean extend_selection) |
6503 | { |
6504 | CtkTextViewPrivate *priv; |
6505 | CtkTextIter insert; |
6506 | CtkTextIter newplace; |
6507 | gboolean cancel_selection = FALSE(0); |
6508 | gint cursor_x_pos = 0; |
6509 | CtkDirectionType leave_direction = -1; |
6510 | |
6511 | priv = text_view->priv; |
6512 | |
6513 | if (!cursor_visible (text_view)) |
6514 | { |
6515 | CtkScrollStep scroll_step; |
6516 | gdouble old_xpos, old_ypos; |
6517 | |
6518 | switch (step) |
6519 | { |
6520 | case CTK_MOVEMENT_VISUAL_POSITIONS: |
6521 | leave_direction = count > 0 ? CTK_DIR_RIGHT : CTK_DIR_LEFT; |
6522 | /* fall through */ |
6523 | case CTK_MOVEMENT_LOGICAL_POSITIONS: |
6524 | case CTK_MOVEMENT_WORDS: |
6525 | scroll_step = CTK_SCROLL_HORIZONTAL_STEPS; |
6526 | break; |
6527 | case CTK_MOVEMENT_DISPLAY_LINE_ENDS: |
6528 | scroll_step = CTK_SCROLL_HORIZONTAL_ENDS; |
6529 | break; |
6530 | case CTK_MOVEMENT_DISPLAY_LINES: |
6531 | leave_direction = count > 0 ? CTK_DIR_DOWN : CTK_DIR_UP; |
6532 | /* fall through */ |
6533 | case CTK_MOVEMENT_PARAGRAPHS: |
6534 | case CTK_MOVEMENT_PARAGRAPH_ENDS: |
6535 | scroll_step = CTK_SCROLL_STEPS; |
6536 | break; |
6537 | case CTK_MOVEMENT_PAGES: |
6538 | scroll_step = CTK_SCROLL_PAGES; |
6539 | break; |
6540 | case CTK_MOVEMENT_HORIZONTAL_PAGES: |
6541 | scroll_step = CTK_SCROLL_HORIZONTAL_PAGES; |
6542 | break; |
6543 | case CTK_MOVEMENT_BUFFER_ENDS: |
6544 | scroll_step = CTK_SCROLL_ENDS; |
6545 | break; |
6546 | default: |
6547 | scroll_step = CTK_SCROLL_PAGES; |
6548 | break; |
6549 | } |
6550 | |
6551 | old_xpos = ctk_adjustment_get_value (priv->hadjustment); |
6552 | old_ypos = ctk_adjustment_get_value (priv->vadjustment); |
6553 | ctk_text_view_move_viewport (text_view, scroll_step, count); |
6554 | if ((old_xpos == ctk_adjustment_get_target_value (priv->hadjustment) && |
6555 | old_ypos == ctk_adjustment_get_target_value (priv->vadjustment)) && |
6556 | leave_direction != (CtkDirectionType)-1 && |
6557 | !ctk_widget_keynav_failed (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))), |
6558 | leave_direction)) |
6559 | { |
6560 | g_signal_emit_by_name (text_view, "move-focus", leave_direction); |
6561 | } |
6562 | |
6563 | return; |
6564 | } |
6565 | |
6566 | ctk_text_view_reset_im_context (text_view); |
6567 | |
6568 | if (step == CTK_MOVEMENT_PAGES) |
6569 | { |
6570 | if (!ctk_text_view_scroll_pages (text_view, count, extend_selection)) |
6571 | ctk_widget_error_bell (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
6572 | |
6573 | ctk_text_view_check_cursor_blink (text_view); |
6574 | ctk_text_view_pend_cursor_blink (text_view); |
6575 | return; |
6576 | } |
6577 | else if (step == CTK_MOVEMENT_HORIZONTAL_PAGES) |
6578 | { |
6579 | if (!ctk_text_view_scroll_hpages (text_view, count, extend_selection)) |
6580 | ctk_widget_error_bell (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
6581 | |
6582 | ctk_text_view_check_cursor_blink (text_view); |
6583 | ctk_text_view_pend_cursor_blink (text_view); |
6584 | return; |
6585 | } |
6586 | |
6587 | ctk_text_buffer_get_iter_at_mark (get_buffer (text_view), &insert, |
6588 | ctk_text_buffer_get_insert (get_buffer (text_view))); |
6589 | |
6590 | if (! extend_selection) |
6591 | { |
6592 | gboolean move_forward = count > 0; |
6593 | CtkTextIter sel_bound; |
6594 | |
6595 | ctk_text_buffer_get_iter_at_mark (get_buffer (text_view), &sel_bound, |
6596 | ctk_text_buffer_get_selection_bound (get_buffer (text_view))); |
6597 | |
6598 | if (iter_line_is_rtl (&insert)) |
6599 | move_forward = !move_forward; |
6600 | |
6601 | /* if we move forward, assume the cursor is at the end of the selection; |
6602 | * if we move backward, assume the cursor is at the start |
6603 | */ |
6604 | if (move_forward) |
6605 | ctk_text_iter_order (&sel_bound, &insert); |
6606 | else |
6607 | ctk_text_iter_order (&insert, &sel_bound); |
6608 | |
6609 | /* if we actually have a selection, just move *to* the beginning/end |
6610 | * of the selection and not *from* there on LOGICAL_POSITIONS |
6611 | * and VISUAL_POSITIONS movement |
6612 | */ |
6613 | if (! ctk_text_iter_equal (&sel_bound, &insert)) |
6614 | cancel_selection = TRUE(!(0)); |
6615 | } |
6616 | |
6617 | newplace = insert; |
6618 | |
6619 | if (step == CTK_MOVEMENT_DISPLAY_LINES) |
6620 | ctk_text_view_get_virtual_cursor_pos (text_view, &insert, &cursor_x_pos, NULL((void*)0)); |
6621 | |
6622 | switch (step) |
6623 | { |
6624 | case CTK_MOVEMENT_LOGICAL_POSITIONS: |
6625 | if (! cancel_selection) |
6626 | ctk_text_iter_forward_visible_cursor_positions (&newplace, count); |
6627 | break; |
6628 | |
6629 | case CTK_MOVEMENT_VISUAL_POSITIONS: |
6630 | if (! cancel_selection) |
6631 | ctk_text_layout_move_iter_visually (priv->layout, |
6632 | &newplace, count); |
6633 | break; |
6634 | |
6635 | case CTK_MOVEMENT_WORDS: |
6636 | if (iter_line_is_rtl (&newplace)) |
6637 | count *= -1; |
6638 | |
6639 | if (count < 0) |
6640 | ctk_text_iter_backward_visible_word_starts (&newplace, -count); |
6641 | else if (count > 0) |
6642 | { |
6643 | if (!ctk_text_iter_forward_visible_word_ends (&newplace, count)) |
6644 | ctk_text_iter_forward_to_line_end (&newplace); |
6645 | } |
6646 | break; |
6647 | |
6648 | case CTK_MOVEMENT_DISPLAY_LINES: |
6649 | if (count < 0) |
6650 | { |
6651 | leave_direction = CTK_DIR_UP; |
6652 | |
6653 | if (ctk_text_view_move_iter_by_lines (text_view, &newplace, count)) |
6654 | ctk_text_layout_move_iter_to_x (priv->layout, &newplace, cursor_x_pos); |
6655 | else |
6656 | ctk_text_iter_set_line_offset (&newplace, 0); |
6657 | } |
6658 | if (count > 0) |
6659 | { |
6660 | leave_direction = CTK_DIR_DOWN; |
6661 | |
6662 | if (ctk_text_view_move_iter_by_lines (text_view, &newplace, count)) |
6663 | ctk_text_layout_move_iter_to_x (priv->layout, &newplace, cursor_x_pos); |
6664 | else |
6665 | ctk_text_iter_forward_to_line_end (&newplace); |
6666 | } |
6667 | break; |
6668 | |
6669 | case CTK_MOVEMENT_DISPLAY_LINE_ENDS: |
6670 | if (count > 1) |
6671 | ctk_text_view_move_iter_by_lines (text_view, &newplace, --count); |
6672 | else if (count < -1) |
6673 | ctk_text_view_move_iter_by_lines (text_view, &newplace, ++count); |
6674 | |
6675 | if (count != 0) |
6676 | ctk_text_layout_move_iter_to_line_end (priv->layout, &newplace, count); |
6677 | break; |
6678 | |
6679 | case CTK_MOVEMENT_PARAGRAPHS: |
6680 | if (count > 0) |
6681 | { |
6682 | if (!ctk_text_iter_ends_line (&newplace)) |
6683 | { |
6684 | ctk_text_iter_forward_to_line_end (&newplace); |
6685 | --count; |
6686 | } |
6687 | ctk_text_iter_forward_visible_lines (&newplace, count); |
6688 | ctk_text_iter_forward_to_line_end (&newplace); |
6689 | } |
6690 | else if (count < 0) |
6691 | { |
6692 | if (ctk_text_iter_get_line_offset (&newplace) > 0) |
6693 | ctk_text_iter_set_line_offset (&newplace, 0); |
6694 | ctk_text_iter_forward_visible_lines (&newplace, count); |
6695 | ctk_text_iter_set_line_offset (&newplace, 0); |
6696 | } |
6697 | break; |
6698 | |
6699 | case CTK_MOVEMENT_PARAGRAPH_ENDS: |
6700 | if (count > 0) |
6701 | { |
6702 | if (!ctk_text_iter_ends_line (&newplace)) |
6703 | ctk_text_iter_forward_to_line_end (&newplace); |
6704 | } |
6705 | else if (count < 0) |
6706 | { |
6707 | ctk_text_iter_set_line_offset (&newplace, 0); |
6708 | } |
6709 | break; |
6710 | |
6711 | case CTK_MOVEMENT_BUFFER_ENDS: |
6712 | if (count > 0) |
6713 | ctk_text_buffer_get_end_iter (get_buffer (text_view), &newplace); |
6714 | else if (count < 0) |
6715 | ctk_text_buffer_get_iter_at_offset (get_buffer (text_view), &newplace, 0); |
6716 | break; |
6717 | |
6718 | default: |
6719 | break; |
6720 | } |
6721 | |
6722 | /* call move_cursor() even if the cursor hasn't moved, since it |
6723 | cancels the selection |
6724 | */ |
6725 | move_cursor (text_view, &newplace, extend_selection); |
6726 | |
6727 | if (!ctk_text_iter_equal (&insert, &newplace)) |
6728 | { |
6729 | DV(g_print (G_STRLOC": scrolling onscreen\n")); |
6730 | ctk_text_view_scroll_mark_onscreen (text_view, |
6731 | ctk_text_buffer_get_insert (get_buffer (text_view))); |
6732 | |
6733 | if (step == CTK_MOVEMENT_DISPLAY_LINES) |
6734 | ctk_text_view_set_virtual_cursor_pos (text_view, cursor_x_pos, -1); |
6735 | } |
6736 | else if (leave_direction != (CtkDirectionType)-1) |
6737 | { |
6738 | if (!ctk_widget_keynav_failed (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))), |
6739 | leave_direction)) |
6740 | { |
6741 | g_signal_emit_by_name (text_view, "move-focus", leave_direction); |
6742 | } |
6743 | } |
6744 | else if (! cancel_selection) |
6745 | { |
6746 | ctk_widget_error_bell (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
6747 | } |
6748 | |
6749 | ctk_text_view_check_cursor_blink (text_view); |
6750 | ctk_text_view_pend_cursor_blink (text_view); |
6751 | } |
6752 | |
6753 | static void |
6754 | ctk_text_view_move_viewport (CtkTextView *text_view, |
6755 | CtkScrollStep step, |
6756 | gint count) |
6757 | { |
6758 | CtkAdjustment *adjustment; |
6759 | gdouble increment; |
6760 | |
6761 | switch (step) |
6762 | { |
6763 | case CTK_SCROLL_STEPS: |
6764 | case CTK_SCROLL_PAGES: |
6765 | case CTK_SCROLL_ENDS: |
6766 | adjustment = text_view->priv->vadjustment; |
6767 | break; |
6768 | case CTK_SCROLL_HORIZONTAL_STEPS: |
6769 | case CTK_SCROLL_HORIZONTAL_PAGES: |
6770 | case CTK_SCROLL_HORIZONTAL_ENDS: |
6771 | adjustment = text_view->priv->hadjustment; |
6772 | break; |
6773 | default: |
6774 | adjustment = text_view->priv->vadjustment; |
6775 | break; |
6776 | } |
6777 | |
6778 | switch (step) |
6779 | { |
6780 | case CTK_SCROLL_STEPS: |
6781 | case CTK_SCROLL_HORIZONTAL_STEPS: |
6782 | increment = ctk_adjustment_get_step_increment (adjustment); |
6783 | break; |
6784 | case CTK_SCROLL_PAGES: |
6785 | case CTK_SCROLL_HORIZONTAL_PAGES: |
6786 | increment = ctk_adjustment_get_page_increment (adjustment); |
6787 | break; |
6788 | case CTK_SCROLL_ENDS: |
6789 | case CTK_SCROLL_HORIZONTAL_ENDS: |
6790 | increment = ctk_adjustment_get_upper (adjustment) - ctk_adjustment_get_lower (adjustment); |
6791 | break; |
6792 | default: |
6793 | increment = 0.0; |
6794 | break; |
6795 | } |
6796 | |
6797 | ctk_adjustment_animate_to_value (adjustment, ctk_adjustment_get_value (adjustment) + count * increment); |
6798 | } |
6799 | |
6800 | static void |
6801 | ctk_text_view_set_anchor (CtkTextView *text_view) |
6802 | { |
6803 | CtkTextIter insert; |
6804 | |
6805 | ctk_text_buffer_get_iter_at_mark (get_buffer (text_view), &insert, |
6806 | ctk_text_buffer_get_insert (get_buffer (text_view))); |
6807 | |
6808 | ctk_text_buffer_create_mark (get_buffer (text_view), "anchor", &insert, TRUE(!(0))); |
6809 | } |
6810 | |
6811 | static gboolean |
6812 | ctk_text_view_scroll_pages (CtkTextView *text_view, |
6813 | gint count, |
6814 | gboolean extend_selection) |
6815 | { |
6816 | CtkTextViewPrivate *priv; |
6817 | CtkAdjustment *adjustment; |
6818 | gint cursor_x_pos, cursor_y_pos; |
6819 | CtkTextMark *insert_mark; |
6820 | CtkTextIter old_insert; |
6821 | CtkTextIter new_insert; |
6822 | CtkTextIter anchor; |
6823 | gdouble newval; |
6824 | gdouble oldval; |
6825 | gint y0, y1; |
6826 | |
6827 | priv = text_view->priv; |
6828 | |
6829 | g_return_val_if_fail (priv->vadjustment != NULL, FALSE)do { if ((priv->vadjustment != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "priv->vadjustment != NULL" ); return ((0)); } } while (0); |
6830 | |
6831 | adjustment = priv->vadjustment; |
6832 | |
6833 | insert_mark = ctk_text_buffer_get_insert (get_buffer (text_view)); |
6834 | |
6835 | /* Make sure we start from the current cursor position, even |
6836 | * if it was offscreen, but don't queue more scrolls if we're |
6837 | * already behind. |
6838 | */ |
6839 | if (priv->pending_scroll) |
6840 | cancel_pending_scroll (text_view); |
6841 | else |
6842 | ctk_text_view_scroll_mark_onscreen (text_view, insert_mark); |
6843 | |
6844 | /* Validate the region that will be brought into view by the cursor motion |
6845 | */ |
6846 | ctk_text_buffer_get_iter_at_mark (get_buffer (text_view), |
6847 | &old_insert, insert_mark); |
6848 | |
6849 | if (count < 0) |
6850 | { |
6851 | ctk_text_view_get_first_para_iter (text_view, &anchor); |
6852 | y0 = ctk_adjustment_get_page_size (adjustment); |
6853 | y1 = ctk_adjustment_get_page_size (adjustment) + count * ctk_adjustment_get_page_increment (adjustment); |
6854 | } |
6855 | else |
6856 | { |
6857 | ctk_text_view_get_first_para_iter (text_view, &anchor); |
6858 | y0 = count * ctk_adjustment_get_page_increment (adjustment) + ctk_adjustment_get_page_size (adjustment); |
6859 | y1 = 0; |
6860 | } |
6861 | |
6862 | ctk_text_layout_validate_yrange (priv->layout, &anchor, y0, y1); |
6863 | /* FIXME do we need to update the adjustment ranges here? */ |
6864 | |
6865 | new_insert = old_insert; |
6866 | |
6867 | if (count < 0 && ctk_adjustment_get_value (adjustment) <= (ctk_adjustment_get_lower (adjustment) + 1e-12)) |
6868 | { |
6869 | /* already at top, just be sure we are at offset 0 */ |
6870 | ctk_text_buffer_get_start_iter (get_buffer (text_view), &new_insert); |
6871 | move_cursor (text_view, &new_insert, extend_selection); |
6872 | } |
6873 | else if (count > 0 && ctk_adjustment_get_value (adjustment) >= (ctk_adjustment_get_upper (adjustment) - ctk_adjustment_get_page_size (adjustment) - 1e-12)) |
6874 | { |
6875 | /* already at bottom, just be sure we are at the end */ |
6876 | ctk_text_buffer_get_end_iter (get_buffer (text_view), &new_insert); |
6877 | move_cursor (text_view, &new_insert, extend_selection); |
6878 | } |
6879 | else |
6880 | { |
6881 | ctk_text_view_get_virtual_cursor_pos (text_view, NULL((void*)0), &cursor_x_pos, &cursor_y_pos); |
6882 | |
6883 | oldval = newval = ctk_adjustment_get_target_value (adjustment); |
6884 | newval += count * ctk_adjustment_get_page_increment (adjustment); |
6885 | |
6886 | ctk_adjustment_animate_to_value (adjustment, newval); |
6887 | cursor_y_pos += newval - oldval; |
6888 | |
6889 | ctk_text_layout_get_iter_at_pixel (priv->layout, &new_insert, cursor_x_pos, cursor_y_pos); |
6890 | |
6891 | move_cursor (text_view, &new_insert, extend_selection); |
6892 | |
6893 | ctk_text_view_set_virtual_cursor_pos (text_view, cursor_x_pos, cursor_y_pos); |
6894 | } |
6895 | |
6896 | /* Adjust to have the cursor _entirely_ onscreen, move_mark_onscreen |
6897 | * only guarantees 1 pixel onscreen. |
6898 | */ |
6899 | DV(g_print (G_STRLOC": scrolling onscreen\n")); |
6900 | |
6901 | return !ctk_text_iter_equal (&old_insert, &new_insert); |
6902 | } |
6903 | |
6904 | static gboolean |
6905 | ctk_text_view_scroll_hpages (CtkTextView *text_view, |
6906 | gint count, |
6907 | gboolean extend_selection) |
6908 | { |
6909 | CtkTextViewPrivate *priv; |
6910 | CtkAdjustment *adjustment; |
6911 | gint cursor_x_pos, cursor_y_pos; |
6912 | CtkTextMark *insert_mark; |
6913 | CtkTextIter old_insert; |
6914 | CtkTextIter new_insert; |
6915 | gdouble newval; |
6916 | gdouble oldval; |
6917 | gint y, height; |
6918 | |
6919 | priv = text_view->priv; |
6920 | |
6921 | g_return_val_if_fail (priv->hadjustment != NULL, FALSE)do { if ((priv->hadjustment != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "priv->hadjustment != NULL" ); return ((0)); } } while (0); |
6922 | |
6923 | adjustment = priv->hadjustment; |
6924 | |
6925 | insert_mark = ctk_text_buffer_get_insert (get_buffer (text_view)); |
6926 | |
6927 | /* Make sure we start from the current cursor position, even |
6928 | * if it was offscreen, but don't queue more scrolls if we're |
6929 | * already behind. |
6930 | */ |
6931 | if (priv->pending_scroll) |
6932 | cancel_pending_scroll (text_view); |
6933 | else |
6934 | ctk_text_view_scroll_mark_onscreen (text_view, insert_mark); |
6935 | |
6936 | /* Validate the line that we're moving within. |
6937 | */ |
6938 | ctk_text_buffer_get_iter_at_mark (get_buffer (text_view), |
6939 | &old_insert, insert_mark); |
6940 | |
6941 | ctk_text_layout_get_line_yrange (priv->layout, &old_insert, &y, &height); |
6942 | ctk_text_layout_validate_yrange (priv->layout, &old_insert, y, y + height); |
6943 | /* FIXME do we need to update the adjustment ranges here? */ |
6944 | |
6945 | new_insert = old_insert; |
6946 | |
6947 | if (count < 0 && ctk_adjustment_get_value (adjustment) <= (ctk_adjustment_get_lower (adjustment) + 1e-12)) |
6948 | { |
6949 | /* already at far left, just be sure we are at offset 0 */ |
6950 | ctk_text_iter_set_line_offset (&new_insert, 0); |
6951 | move_cursor (text_view, &new_insert, extend_selection); |
6952 | } |
6953 | else if (count > 0 && ctk_adjustment_get_value (adjustment) >= (ctk_adjustment_get_upper (adjustment) - ctk_adjustment_get_page_size (adjustment) - 1e-12)) |
6954 | { |
6955 | /* already at far right, just be sure we are at the end */ |
6956 | if (!ctk_text_iter_ends_line (&new_insert)) |
6957 | ctk_text_iter_forward_to_line_end (&new_insert); |
6958 | move_cursor (text_view, &new_insert, extend_selection); |
6959 | } |
6960 | else |
6961 | { |
6962 | ctk_text_view_get_virtual_cursor_pos (text_view, NULL((void*)0), &cursor_x_pos, &cursor_y_pos); |
6963 | |
6964 | oldval = newval = ctk_adjustment_get_target_value (adjustment); |
6965 | newval += count * ctk_adjustment_get_page_increment (adjustment); |
6966 | |
6967 | ctk_adjustment_animate_to_value (adjustment, newval); |
6968 | cursor_x_pos += newval - oldval; |
6969 | |
6970 | ctk_text_layout_get_iter_at_pixel (priv->layout, &new_insert, cursor_x_pos, cursor_y_pos); |
6971 | move_cursor (text_view, &new_insert, extend_selection); |
6972 | |
6973 | ctk_text_view_set_virtual_cursor_pos (text_view, cursor_x_pos, cursor_y_pos); |
6974 | } |
6975 | |
6976 | /* FIXME for lines shorter than the overall widget width, this results in a |
6977 | * "bounce" effect as we scroll to the right of the widget, then scroll |
6978 | * back to get the end of the line onscreen. |
6979 | * http://bugzilla.gnome.org/show_bug.cgi?id=68963 |
6980 | */ |
6981 | |
6982 | /* Adjust to have the cursor _entirely_ onscreen, move_mark_onscreen |
6983 | * only guarantees 1 pixel onscreen. |
6984 | */ |
6985 | DV(g_print (G_STRLOC": scrolling onscreen\n")); |
6986 | |
6987 | return !ctk_text_iter_equal (&old_insert, &new_insert); |
6988 | } |
6989 | |
6990 | static gboolean |
6991 | whitespace (gunichar ch, |
6992 | gpointer user_data G_GNUC_UNUSED__attribute__ ((__unused__))) |
6993 | { |
6994 | return (ch == ' ' || ch == '\t'); |
6995 | } |
6996 | |
6997 | static gboolean |
6998 | not_whitespace (gunichar ch, gpointer user_data) |
6999 | { |
7000 | return !whitespace (ch, user_data); |
7001 | } |
7002 | |
7003 | static gboolean |
7004 | find_whitepace_region (const CtkTextIter *center, |
7005 | CtkTextIter *start, CtkTextIter *end) |
7006 | { |
7007 | *start = *center; |
7008 | *end = *center; |
7009 | |
7010 | if (ctk_text_iter_backward_find_char (start, not_whitespace, NULL((void*)0), NULL((void*)0))) |
7011 | ctk_text_iter_forward_char (start); /* we want the first whitespace... */ |
7012 | if (whitespace (ctk_text_iter_get_char (end), NULL((void*)0))) |
7013 | ctk_text_iter_forward_find_char (end, not_whitespace, NULL((void*)0), NULL((void*)0)); |
7014 | |
7015 | return !ctk_text_iter_equal (start, end); |
7016 | } |
7017 | |
7018 | static void |
7019 | ctk_text_view_insert_at_cursor (CtkTextView *text_view, |
7020 | const gchar *str) |
7021 | { |
7022 | if (!ctk_text_buffer_insert_interactive_at_cursor (get_buffer (text_view), str, -1, |
7023 | text_view->priv->editable)) |
7024 | { |
7025 | ctk_widget_error_bell (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
7026 | } |
7027 | } |
7028 | |
7029 | static void |
7030 | ctk_text_view_delete_from_cursor (CtkTextView *text_view, |
7031 | CtkDeleteType type, |
7032 | gint count) |
7033 | { |
7034 | CtkTextViewPrivate *priv; |
7035 | CtkTextIter insert; |
7036 | CtkTextIter start; |
7037 | CtkTextIter end; |
7038 | gboolean leave_one = FALSE(0); |
7039 | |
7040 | priv = text_view->priv; |
7041 | |
7042 | ctk_text_view_reset_im_context (text_view); |
7043 | |
7044 | if (type == CTK_DELETE_CHARS) |
7045 | { |
7046 | /* Char delete deletes the selection, if one exists */ |
7047 | if (ctk_text_buffer_delete_selection (get_buffer (text_view), TRUE(!(0)), |
7048 | priv->editable)) |
7049 | return; |
7050 | } |
7051 | |
7052 | ctk_text_buffer_get_iter_at_mark (get_buffer (text_view), &insert, |
7053 | ctk_text_buffer_get_insert (get_buffer (text_view))); |
7054 | |
7055 | start = insert; |
7056 | end = insert; |
7057 | |
7058 | switch (type) |
7059 | { |
7060 | case CTK_DELETE_CHARS: |
7061 | ctk_text_iter_forward_cursor_positions (&end, count); |
7062 | break; |
7063 | |
7064 | case CTK_DELETE_WORD_ENDS: |
7065 | if (count > 0) |
7066 | ctk_text_iter_forward_word_ends (&end, count); |
7067 | else if (count < 0) |
7068 | ctk_text_iter_backward_word_starts (&start, 0 - count); |
7069 | break; |
7070 | |
7071 | case CTK_DELETE_WORDS: |
7072 | break; |
7073 | |
7074 | case CTK_DELETE_DISPLAY_LINE_ENDS: |
7075 | break; |
7076 | |
7077 | case CTK_DELETE_DISPLAY_LINES: |
7078 | break; |
7079 | |
7080 | case CTK_DELETE_PARAGRAPH_ENDS: |
7081 | if (count > 0) |
7082 | { |
7083 | /* If we're already at a newline, we need to |
7084 | * simply delete that newline, instead of |
7085 | * moving to the next one. |
7086 | */ |
7087 | if (ctk_text_iter_ends_line (&end)) |
7088 | { |
7089 | ctk_text_iter_forward_line (&end); |
7090 | --count; |
7091 | } |
7092 | |
7093 | while (count > 0) |
7094 | { |
7095 | if (!ctk_text_iter_forward_to_line_end (&end)) |
7096 | break; |
7097 | |
7098 | --count; |
7099 | } |
7100 | } |
7101 | else if (count < 0) |
7102 | { |
7103 | if (ctk_text_iter_starts_line (&start)) |
7104 | { |
7105 | ctk_text_iter_backward_line (&start); |
7106 | if (!ctk_text_iter_ends_line (&end)) |
7107 | ctk_text_iter_forward_to_line_end (&start); |
7108 | } |
7109 | else |
7110 | { |
7111 | ctk_text_iter_set_line_offset (&start, 0); |
7112 | } |
7113 | ++count; |
7114 | |
7115 | ctk_text_iter_backward_lines (&start, -count); |
7116 | } |
7117 | break; |
7118 | |
7119 | case CTK_DELETE_PARAGRAPHS: |
7120 | if (count > 0) |
7121 | { |
7122 | ctk_text_iter_set_line_offset (&start, 0); |
7123 | ctk_text_iter_forward_to_line_end (&end); |
7124 | |
7125 | /* Do the lines beyond the first. */ |
7126 | while (count > 1) |
7127 | { |
7128 | ctk_text_iter_forward_to_line_end (&end); |
7129 | |
7130 | --count; |
7131 | } |
7132 | } |
7133 | |
7134 | /* FIXME negative count? */ |
7135 | |
7136 | break; |
7137 | |
7138 | case CTK_DELETE_WHITESPACE: |
7139 | { |
7140 | find_whitepace_region (&insert, &start, &end); |
7141 | } |
7142 | break; |
7143 | |
7144 | default: |
7145 | break; |
7146 | } |
7147 | |
7148 | if (!ctk_text_iter_equal (&start, &end)) |
7149 | { |
7150 | ctk_text_buffer_begin_user_action (get_buffer (text_view)); |
7151 | |
7152 | if (ctk_text_buffer_delete_interactive (get_buffer (text_view), &start, &end, |
7153 | priv->editable)) |
7154 | { |
7155 | if (leave_one) |
7156 | ctk_text_buffer_insert_interactive_at_cursor (get_buffer (text_view), |
7157 | " ", 1, |
7158 | priv->editable); |
7159 | } |
7160 | else |
7161 | { |
7162 | ctk_widget_error_bell (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
7163 | } |
7164 | |
7165 | ctk_text_buffer_end_user_action (get_buffer (text_view)); |
7166 | ctk_text_view_set_virtual_cursor_pos (text_view, -1, -1); |
7167 | |
7168 | DV(g_print (G_STRLOC": scrolling onscreen\n")); |
7169 | ctk_text_view_scroll_mark_onscreen (text_view, |
7170 | ctk_text_buffer_get_insert (get_buffer (text_view))); |
7171 | } |
7172 | else |
7173 | { |
7174 | ctk_widget_error_bell (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
7175 | } |
7176 | } |
7177 | |
7178 | static void |
7179 | ctk_text_view_backspace (CtkTextView *text_view) |
7180 | { |
7181 | CtkTextViewPrivate *priv; |
7182 | CtkTextIter insert; |
7183 | |
7184 | priv = text_view->priv; |
7185 | |
7186 | ctk_text_view_reset_im_context (text_view); |
7187 | |
7188 | /* Backspace deletes the selection, if one exists */ |
7189 | if (ctk_text_buffer_delete_selection (get_buffer (text_view), TRUE(!(0)), |
7190 | priv->editable)) |
7191 | return; |
7192 | |
7193 | ctk_text_buffer_get_iter_at_mark (get_buffer (text_view), |
7194 | &insert, |
7195 | ctk_text_buffer_get_insert (get_buffer (text_view))); |
7196 | |
7197 | if (ctk_text_buffer_backspace (get_buffer (text_view), &insert, |
7198 | TRUE(!(0)), priv->editable)) |
7199 | { |
7200 | ctk_text_view_set_virtual_cursor_pos (text_view, -1, -1); |
7201 | DV(g_print (G_STRLOC": scrolling onscreen\n")); |
7202 | ctk_text_view_scroll_mark_onscreen (text_view, |
7203 | ctk_text_buffer_get_insert (get_buffer (text_view))); |
7204 | } |
7205 | else |
7206 | { |
7207 | ctk_widget_error_bell (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
7208 | } |
7209 | } |
7210 | |
7211 | static void |
7212 | ctk_text_view_cut_clipboard (CtkTextView *text_view) |
7213 | { |
7214 | CtkClipboard *clipboard = ctk_widget_get_clipboard (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))), |
7215 | CDK_SELECTION_CLIPBOARD((CdkAtom)((gpointer) (gulong) (69)))); |
7216 | |
7217 | ctk_text_buffer_cut_clipboard (get_buffer (text_view), |
7218 | clipboard, |
7219 | text_view->priv->editable); |
7220 | DV(g_print (G_STRLOC": scrolling onscreen\n")); |
7221 | ctk_text_view_scroll_mark_onscreen (text_view, |
7222 | ctk_text_buffer_get_insert (get_buffer (text_view))); |
7223 | ctk_text_view_selection_bubble_popup_unset (text_view); |
7224 | } |
7225 | |
7226 | static void |
7227 | ctk_text_view_copy_clipboard (CtkTextView *text_view) |
7228 | { |
7229 | CtkClipboard *clipboard = ctk_widget_get_clipboard (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))), |
7230 | CDK_SELECTION_CLIPBOARD((CdkAtom)((gpointer) (gulong) (69)))); |
7231 | |
7232 | ctk_text_buffer_copy_clipboard (get_buffer (text_view), |
7233 | clipboard); |
7234 | |
7235 | /* on copy do not scroll, we are already onscreen */ |
7236 | } |
7237 | |
7238 | static void |
7239 | ctk_text_view_paste_clipboard (CtkTextView *text_view) |
7240 | { |
7241 | CtkClipboard *clipboard = ctk_widget_get_clipboard (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))), |
7242 | CDK_SELECTION_CLIPBOARD((CdkAtom)((gpointer) (gulong) (69)))); |
7243 | |
7244 | text_view->priv->scroll_after_paste = TRUE(!(0)); |
7245 | |
7246 | ctk_text_buffer_paste_clipboard (get_buffer (text_view), |
7247 | clipboard, |
7248 | NULL((void*)0), |
7249 | text_view->priv->editable); |
7250 | } |
7251 | |
7252 | static void |
7253 | ctk_text_view_paste_done_handler (CtkTextBuffer *buffer, |
7254 | CtkClipboard *clipboard G_GNUC_UNUSED__attribute__ ((__unused__)), |
7255 | gpointer data) |
7256 | { |
7257 | CtkTextView *text_view = data; |
7258 | CtkTextViewPrivate *priv; |
7259 | |
7260 | priv = text_view->priv; |
7261 | |
7262 | if (priv->scroll_after_paste) |
7263 | { |
7264 | DV(g_print (G_STRLOC": scrolling onscreen\n")); |
7265 | ctk_text_view_scroll_mark_onscreen (text_view, ctk_text_buffer_get_insert (buffer)); |
7266 | } |
7267 | |
7268 | priv->scroll_after_paste = FALSE(0); |
7269 | } |
7270 | |
7271 | static void |
7272 | ctk_text_view_buffer_changed_handler (CtkTextBuffer *buffer G_GNUC_UNUSED__attribute__ ((__unused__)), |
7273 | gpointer data) |
7274 | { |
7275 | CtkTextView *text_view = data; |
7276 | CtkTextViewPrivate *priv = text_view->priv; |
7277 | |
7278 | if (priv->handling_key_event) |
7279 | ctk_text_view_obscure_mouse_cursor (text_view); |
7280 | |
7281 | if (priv->text_handle) |
7282 | ctk_text_view_update_handles (text_view, |
7283 | _ctk_text_handle_get_mode (priv->text_handle)); |
7284 | } |
7285 | |
7286 | static void |
7287 | ctk_text_view_toggle_overwrite (CtkTextView *text_view) |
7288 | { |
7289 | CtkTextViewPrivate *priv = text_view->priv; |
7290 | |
7291 | if (priv->text_window) |
7292 | text_window_invalidate_cursors (priv->text_window); |
7293 | |
7294 | priv->overwrite_mode = !priv->overwrite_mode; |
7295 | |
7296 | if (priv->layout) |
7297 | ctk_text_layout_set_overwrite_mode (priv->layout, |
7298 | priv->overwrite_mode && priv->editable); |
7299 | |
7300 | if (priv->text_window) |
7301 | text_window_invalidate_cursors (priv->text_window); |
7302 | |
7303 | ctk_text_view_pend_cursor_blink (text_view); |
7304 | |
7305 | g_object_notify (G_OBJECT (text_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), (((GType) ((20) << (2)))))))), "overwrite"); |
7306 | } |
7307 | |
7308 | /** |
7309 | * ctk_text_view_get_overwrite: |
7310 | * @text_view: a #CtkTextView |
7311 | * |
7312 | * Returns whether the #CtkTextView is in overwrite mode or not. |
7313 | * |
7314 | * Returns: whether @text_view is in overwrite mode or not. |
7315 | * |
7316 | * Since: 2.4 |
7317 | **/ |
7318 | gboolean |
7319 | ctk_text_view_get_overwrite (CtkTextView *text_view) |
7320 | { |
7321 | g_return_val_if_fail (CTK_IS_TEXT_VIEW (text_view), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return ((0)); } } while ( 0); |
7322 | |
7323 | return text_view->priv->overwrite_mode; |
7324 | } |
7325 | |
7326 | /** |
7327 | * ctk_text_view_set_overwrite: |
7328 | * @text_view: a #CtkTextView |
7329 | * @overwrite: %TRUE to turn on overwrite mode, %FALSE to turn it off |
7330 | * |
7331 | * Changes the #CtkTextView overwrite mode. |
7332 | * |
7333 | * Since: 2.4 |
7334 | **/ |
7335 | void |
7336 | ctk_text_view_set_overwrite (CtkTextView *text_view, |
7337 | gboolean overwrite) |
7338 | { |
7339 | g_return_if_fail (CTK_IS_TEXT_VIEW (text_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return; } } while (0); |
7340 | overwrite = overwrite != FALSE(0); |
7341 | |
7342 | if (text_view->priv->overwrite_mode != overwrite) |
7343 | ctk_text_view_toggle_overwrite (text_view); |
7344 | } |
7345 | |
7346 | /** |
7347 | * ctk_text_view_set_accepts_tab: |
7348 | * @text_view: A #CtkTextView |
7349 | * @accepts_tab: %TRUE if pressing the Tab key should insert a tab |
7350 | * character, %FALSE, if pressing the Tab key should move the |
7351 | * keyboard focus. |
7352 | * |
7353 | * Sets the behavior of the text widget when the Tab key is pressed. |
7354 | * If @accepts_tab is %TRUE, a tab character is inserted. If @accepts_tab |
7355 | * is %FALSE the keyboard focus is moved to the next widget in the focus |
7356 | * chain. |
7357 | * |
7358 | * Since: 2.4 |
7359 | **/ |
7360 | void |
7361 | ctk_text_view_set_accepts_tab (CtkTextView *text_view, |
7362 | gboolean accepts_tab) |
7363 | { |
7364 | g_return_if_fail (CTK_IS_TEXT_VIEW (text_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return; } } while (0); |
7365 | |
7366 | accepts_tab = accepts_tab != FALSE(0); |
7367 | |
7368 | if (text_view->priv->accepts_tab != accepts_tab) |
7369 | { |
7370 | text_view->priv->accepts_tab = accepts_tab; |
7371 | |
7372 | g_object_notify (G_OBJECT (text_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), (((GType) ((20) << (2)))))))), "accepts-tab"); |
7373 | } |
7374 | } |
7375 | |
7376 | /** |
7377 | * ctk_text_view_get_accepts_tab: |
7378 | * @text_view: A #CtkTextView |
7379 | * |
7380 | * Returns whether pressing the Tab key inserts a tab characters. |
7381 | * ctk_text_view_set_accepts_tab(). |
7382 | * |
7383 | * Returns: %TRUE if pressing the Tab key inserts a tab character, |
7384 | * %FALSE if pressing the Tab key moves the keyboard focus. |
7385 | * |
7386 | * Since: 2.4 |
7387 | **/ |
7388 | gboolean |
7389 | ctk_text_view_get_accepts_tab (CtkTextView *text_view) |
7390 | { |
7391 | g_return_val_if_fail (CTK_IS_TEXT_VIEW (text_view), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return ((0)); } } while ( 0); |
7392 | |
7393 | return text_view->priv->accepts_tab; |
7394 | } |
7395 | |
7396 | /* |
7397 | * Selections |
7398 | */ |
7399 | |
7400 | static void |
7401 | ctk_text_view_unselect (CtkTextView *text_view) |
7402 | { |
7403 | CtkTextIter insert; |
7404 | |
7405 | ctk_text_buffer_get_iter_at_mark (get_buffer (text_view), &insert, |
7406 | ctk_text_buffer_get_insert (get_buffer (text_view))); |
7407 | |
7408 | ctk_text_buffer_move_mark (get_buffer (text_view), |
7409 | ctk_text_buffer_get_selection_bound (get_buffer (text_view)), |
7410 | &insert); |
7411 | } |
7412 | |
7413 | static void |
7414 | move_mark_to_pointer_and_scroll (CtkTextView *text_view, |
7415 | const gchar *mark_name) |
7416 | { |
7417 | CtkTextIter newplace; |
7418 | CtkTextBuffer *buffer; |
7419 | CtkTextMark *mark; |
7420 | |
7421 | buffer = get_buffer (text_view); |
7422 | get_iter_from_gesture (text_view, text_view->priv->drag_gesture, |
7423 | &newplace, NULL((void*)0), NULL((void*)0)); |
7424 | |
7425 | mark = ctk_text_buffer_get_mark (buffer, mark_name); |
7426 | |
7427 | /* This may invalidate the layout */ |
7428 | DV(g_print (G_STRLOC": move mark\n")); |
7429 | |
7430 | ctk_text_buffer_move_mark (buffer, mark, &newplace); |
7431 | |
7432 | DV(g_print (G_STRLOC": scrolling onscreen\n")); |
7433 | ctk_text_view_scroll_mark_onscreen (text_view, mark); |
7434 | |
7435 | DV (g_print ("first validate idle leaving %s is %d\n", |
7436 | G_STRLOC, text_view->priv->first_validate_idle)); |
7437 | } |
7438 | |
7439 | static gboolean |
7440 | selection_scan_timeout (gpointer data) |
7441 | { |
7442 | CtkTextView *text_view; |
7443 | |
7444 | text_view = CTK_TEXT_VIEW (data)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((data)), ((ctk_text_view_get_type ())))))); |
7445 | |
7446 | ctk_text_view_scroll_mark_onscreen (text_view, |
7447 | ctk_text_buffer_get_insert (get_buffer (text_view))); |
7448 | |
7449 | return TRUE(!(0)); /* remain installed. */ |
7450 | } |
7451 | |
7452 | #define UPPER_OFFSET_ANCHOR0.8 0.8 |
7453 | #define LOWER_OFFSET_ANCHOR0.2 0.2 |
7454 | |
7455 | static gboolean |
7456 | check_scroll (gdouble offset, CtkAdjustment *adjustment) |
7457 | { |
7458 | if ((offset > UPPER_OFFSET_ANCHOR0.8 && |
7459 | ctk_adjustment_get_value (adjustment) + ctk_adjustment_get_page_size (adjustment) < ctk_adjustment_get_upper (adjustment)) || |
7460 | (offset < LOWER_OFFSET_ANCHOR0.2 && |
7461 | ctk_adjustment_get_value (adjustment) > ctk_adjustment_get_lower (adjustment))) |
7462 | return TRUE(!(0)); |
7463 | |
7464 | return FALSE(0); |
7465 | } |
7466 | |
7467 | static gint |
7468 | drag_scan_timeout (gpointer data) |
7469 | { |
7470 | CtkTextView *text_view; |
7471 | CtkTextViewPrivate *priv; |
7472 | CtkTextIter newplace; |
7473 | gdouble pointer_xoffset, pointer_yoffset; |
7474 | |
7475 | text_view = CTK_TEXT_VIEW (data)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((data)), ((ctk_text_view_get_type ())))))); |
7476 | priv = text_view->priv; |
7477 | |
7478 | ctk_text_layout_get_iter_at_pixel (priv->layout, |
7479 | &newplace, |
7480 | priv->dnd_x + priv->xoffset, |
7481 | priv->dnd_y + priv->yoffset); |
7482 | |
7483 | ctk_text_buffer_move_mark (get_buffer (text_view), |
7484 | priv->dnd_mark, |
7485 | &newplace); |
7486 | |
7487 | pointer_xoffset = (gdouble) priv->dnd_x / cdk_window_get_width (priv->text_window->bin_window); |
7488 | pointer_yoffset = (gdouble) priv->dnd_y / cdk_window_get_height (priv->text_window->bin_window); |
7489 | |
7490 | if (check_scroll (pointer_xoffset, priv->hadjustment) || |
7491 | check_scroll (pointer_yoffset, priv->vadjustment)) |
7492 | { |
7493 | /* do not make offsets surpass lower nor upper anchors, this makes |
7494 | * scrolling speed relative to the distance of the pointer to the |
7495 | * anchors when it moves beyond them. |
7496 | */ |
7497 | pointer_xoffset = CLAMP (pointer_xoffset, LOWER_OFFSET_ANCHOR, UPPER_OFFSET_ANCHOR)(((pointer_xoffset) > (0.8)) ? (0.8) : (((pointer_xoffset) < (0.2)) ? (0.2) : (pointer_xoffset))); |
7498 | pointer_yoffset = CLAMP (pointer_yoffset, LOWER_OFFSET_ANCHOR, UPPER_OFFSET_ANCHOR)(((pointer_yoffset) > (0.8)) ? (0.8) : (((pointer_yoffset) < (0.2)) ? (0.2) : (pointer_yoffset))); |
7499 | |
7500 | ctk_text_view_scroll_to_mark (text_view, |
7501 | priv->dnd_mark, |
7502 | 0., TRUE(!(0)), pointer_xoffset, pointer_yoffset); |
7503 | } |
7504 | |
7505 | return TRUE(!(0)); |
7506 | } |
7507 | |
7508 | static void |
7509 | extend_selection (CtkTextView *text_view, |
7510 | SelectionGranularity granularity, |
7511 | const CtkTextIter *location, |
7512 | CtkTextIter *start, |
7513 | CtkTextIter *end) |
7514 | { |
7515 | CtkTextExtendSelection extend_selection_granularity; |
7516 | gboolean handled = FALSE(0); |
7517 | |
7518 | switch (granularity) |
7519 | { |
7520 | case SELECT_CHARACTERS: |
7521 | *start = *location; |
7522 | *end = *location; |
7523 | return; |
7524 | |
7525 | case SELECT_WORDS: |
7526 | extend_selection_granularity = CTK_TEXT_EXTEND_SELECTION_WORD; |
7527 | break; |
7528 | |
7529 | case SELECT_LINES: |
7530 | extend_selection_granularity = CTK_TEXT_EXTEND_SELECTION_LINE; |
7531 | break; |
7532 | |
7533 | default: |
7534 | g_assert_not_reached ()do { g_assertion_message_expr ("Ctk", "ctktextview.c", 7534, ( (const char*) (__func__)), ((void*)0)); } while (0); |
7535 | } |
7536 | |
7537 | g_signal_emit (text_view, |
7538 | signals[EXTEND_SELECTION], 0, |
7539 | extend_selection_granularity, |
7540 | location, |
7541 | start, |
7542 | end, |
7543 | &handled); |
7544 | |
7545 | if (!handled) |
7546 | { |
7547 | *start = *location; |
7548 | *end = *location; |
7549 | } |
7550 | } |
7551 | |
7552 | static gboolean |
7553 | ctk_text_view_extend_selection (CtkTextView *text_view, |
7554 | CtkTextExtendSelection granularity, |
7555 | const CtkTextIter *location, |
7556 | CtkTextIter *start, |
7557 | CtkTextIter *end) |
7558 | { |
7559 | *start = *location; |
7560 | *end = *location; |
7561 | |
7562 | switch (granularity) |
7563 | { |
7564 | case CTK_TEXT_EXTEND_SELECTION_WORD: |
7565 | if (ctk_text_iter_inside_word (start)) |
7566 | { |
7567 | if (!ctk_text_iter_starts_word (start)) |
7568 | ctk_text_iter_backward_visible_word_start (start); |
7569 | |
7570 | if (!ctk_text_iter_ends_word (end)) |
7571 | { |
7572 | if (!ctk_text_iter_forward_visible_word_end (end)) |
7573 | ctk_text_iter_forward_to_end (end); |
7574 | } |
7575 | } |
7576 | else |
7577 | { |
7578 | CtkTextIter tmp; |
7579 | |
7580 | /* @start is not contained in a word: the selection is extended to all |
7581 | * the white spaces between the end of the word preceding @start and |
7582 | * the start of the one following. |
7583 | */ |
7584 | |
7585 | tmp = *start; |
7586 | if (ctk_text_iter_backward_visible_word_start (&tmp)) |
7587 | ctk_text_iter_forward_visible_word_end (&tmp); |
7588 | |
7589 | if (ctk_text_iter_get_line (&tmp) == ctk_text_iter_get_line (start)) |
7590 | *start = tmp; |
7591 | else |
7592 | ctk_text_iter_set_line_offset (start, 0); |
7593 | |
7594 | tmp = *end; |
7595 | if (!ctk_text_iter_forward_visible_word_end (&tmp)) |
7596 | ctk_text_iter_forward_to_end (&tmp); |
7597 | |
7598 | if (ctk_text_iter_ends_word (&tmp)) |
7599 | ctk_text_iter_backward_visible_word_start (&tmp); |
7600 | |
7601 | if (ctk_text_iter_get_line (&tmp) == ctk_text_iter_get_line (end)) |
7602 | *end = tmp; |
7603 | else |
7604 | ctk_text_iter_forward_to_line_end (end); |
7605 | } |
7606 | break; |
7607 | |
7608 | case CTK_TEXT_EXTEND_SELECTION_LINE: |
7609 | if (ctk_text_view_starts_display_line (text_view, start)) |
7610 | { |
7611 | /* If on a display line boundary, we assume the user |
7612 | * clicked off the end of a line and we therefore select |
7613 | * the line before the boundary. |
7614 | */ |
7615 | ctk_text_view_backward_display_line_start (text_view, start); |
7616 | } |
7617 | else |
7618 | { |
7619 | /* start isn't on the start of a line, so we move it to the |
7620 | * start, and move end to the end unless it's already there. |
7621 | */ |
7622 | ctk_text_view_backward_display_line_start (text_view, start); |
7623 | |
7624 | if (!ctk_text_view_starts_display_line (text_view, end)) |
7625 | ctk_text_view_forward_display_line_end (text_view, end); |
7626 | } |
7627 | break; |
7628 | |
7629 | default: |
7630 | g_return_val_if_reached (CDK_EVENT_STOP)do { g_log ("Ctk", G_LOG_LEVEL_CRITICAL, "file %s: line %d (%s): should not be reached" , "ctktextview.c", 7630, ((const char*) (__func__))); return ( ((!(0)))); } while (0); |
7631 | } |
7632 | |
7633 | return CDK_EVENT_STOP((!(0))); |
7634 | } |
7635 | |
7636 | typedef struct |
7637 | { |
7638 | SelectionGranularity granularity; |
7639 | CtkTextMark *orig_start; |
7640 | CtkTextMark *orig_end; |
7641 | CtkTextBuffer *buffer; |
7642 | } SelectionData; |
7643 | |
7644 | static void |
7645 | selection_data_free (SelectionData *data) |
7646 | { |
7647 | if (data->orig_start != NULL((void*)0)) |
7648 | ctk_text_buffer_delete_mark (data->buffer, data->orig_start); |
7649 | |
7650 | if (data->orig_end != NULL((void*)0)) |
7651 | ctk_text_buffer_delete_mark (data->buffer, data->orig_end); |
7652 | |
7653 | g_object_unref (data->buffer); |
7654 | |
7655 | g_slice_free (SelectionData, data)do { if (1) g_slice_free1 (sizeof (SelectionData), (data)); else (void) ((SelectionData*) 0 == (data)); } while (0); |
7656 | } |
7657 | |
7658 | static gboolean |
7659 | drag_gesture_get_text_window_coords (CtkGestureDrag *gesture, |
7660 | CtkTextView *text_view, |
7661 | gint *start_x, |
7662 | gint *start_y, |
7663 | gint *x, |
7664 | gint *y) |
7665 | { |
7666 | gdouble sx, sy, ox, oy; |
7667 | |
7668 | if (!ctk_gesture_drag_get_start_point (gesture, &sx, &sy) || |
7669 | !ctk_gesture_drag_get_offset (gesture, &ox, &oy)) |
7670 | return FALSE(0); |
7671 | |
7672 | *start_x = sx; |
7673 | *start_y = sy; |
7674 | _widget_to_text_window_coords (text_view, start_x, start_y); |
7675 | |
7676 | *x = sx + ox; |
7677 | *y = sy + oy; |
7678 | _widget_to_text_window_coords (text_view, x, y); |
7679 | |
7680 | return TRUE(!(0)); |
7681 | } |
7682 | |
7683 | static void |
7684 | ctk_text_view_drag_gesture_update (CtkGestureDrag *gesture, |
7685 | gdouble offset_x G_GNUC_UNUSED__attribute__ ((__unused__)), |
7686 | gdouble offset_y G_GNUC_UNUSED__attribute__ ((__unused__)), |
7687 | CtkTextView *text_view) |
7688 | { |
7689 | gint start_x, start_y, x, y; |
7690 | CdkEventSequence *sequence; |
7691 | gboolean is_touchscreen; |
7692 | const CdkEvent *event; |
7693 | SelectionData *data; |
7694 | CdkDevice *device; |
7695 | CtkTextIter cursor; |
7696 | |
7697 | data = g_object_get_qdata (G_OBJECT (gesture)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((gesture)), (((GType) ((20) << (2)))))))), quark_text_selection_data); |
7698 | 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 () ))))))); |
7699 | event = ctk_gesture_get_last_event (CTK_GESTURE (gesture)((((CtkGesture*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((gesture)), ((ctk_gesture_get_type ())))))), sequence); |
7700 | drag_gesture_get_text_window_coords (gesture, text_view, |
7701 | &start_x, &start_y, &x, &y); |
7702 | |
7703 | device = cdk_event_get_source_device (event); |
7704 | |
7705 | is_touchscreen = ctk_simulate_touchscreen () || |
7706 | cdk_device_get_source (device) == CDK_SOURCE_TOUCHSCREEN; |
7707 | |
7708 | get_iter_from_gesture (text_view, text_view->priv->drag_gesture, |
7709 | &cursor, NULL((void*)0), NULL((void*)0)); |
7710 | |
7711 | if (!data) |
7712 | { |
7713 | /* If no data is attached, the initial press happened within the current |
7714 | * text selection, check for drag and drop to be initiated. |
7715 | */ |
7716 | if (ctk_drag_check_threshold (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))), |
7717 | start_x, start_y, x, y)) |
7718 | { |
7719 | if (!is_touchscreen) |
7720 | { |
7721 | CtkTextIter iter; |
7722 | gint buffer_x, buffer_y; |
7723 | |
7724 | ctk_text_view_window_to_buffer_coords (text_view, |
7725 | CTK_TEXT_WINDOW_TEXT, |
7726 | start_x, start_y, |
7727 | &buffer_x, |
7728 | &buffer_y); |
7729 | |
7730 | ctk_text_layout_get_iter_at_pixel (text_view->priv->layout, |
7731 | &iter, buffer_x, buffer_y); |
7732 | |
7733 | ctk_text_view_start_selection_dnd (text_view, &iter, event, |
7734 | start_x, start_y); |
7735 | return; |
7736 | } |
7737 | else |
7738 | { |
7739 | ctk_text_view_start_selection_drag (text_view, &cursor, |
7740 | SELECT_WORDS, TRUE(!(0))); |
7741 | data = g_object_get_qdata (G_OBJECT (gesture)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((gesture)), (((GType) ((20) << (2)))))))), quark_text_selection_data); |
7742 | } |
7743 | } |
7744 | else |
7745 | return; |
7746 | } |
7747 | |
7748 | /* Text selection */ |
7749 | if (data->granularity == SELECT_CHARACTERS) |
7750 | { |
7751 | move_mark_to_pointer_and_scroll (text_view, "insert"); |
7752 | } |
7753 | else |
7754 | { |
7755 | CtkTextIter start, end; |
7756 | CtkTextIter orig_start, orig_end; |
7757 | CtkTextBuffer *buffer; |
7758 | |
7759 | buffer = get_buffer (text_view); |
7760 | |
7761 | ctk_text_buffer_get_iter_at_mark (buffer, &orig_start, data->orig_start); |
7762 | ctk_text_buffer_get_iter_at_mark (buffer, &orig_end, data->orig_end); |
7763 | |
7764 | get_iter_from_gesture (text_view, text_view->priv->drag_gesture, |
7765 | &cursor, NULL((void*)0), NULL((void*)0)); |
7766 | |
7767 | extend_selection (text_view, data->granularity, &cursor, &start, &end); |
7768 | |
7769 | /* either the selection extends to the front, or end (or not) */ |
7770 | if (ctk_text_iter_compare (&orig_start, &start) < 0) |
7771 | start = orig_start; |
7772 | if (ctk_text_iter_compare (&orig_end, &end) > 0) |
7773 | end = orig_end; |
7774 | ctk_text_buffer_select_range (buffer, &start, &end); |
7775 | |
7776 | ctk_text_view_scroll_mark_onscreen (text_view, |
7777 | ctk_text_buffer_get_insert (buffer)); |
7778 | } |
7779 | |
7780 | /* If we had to scroll offscreen, insert a timeout to do so |
7781 | * again. Note that in the timeout, even if the mouse doesn't |
7782 | * move, due to this scroll xoffset/yoffset will have changed |
7783 | * and we'll need to scroll again. |
7784 | */ |
7785 | if (text_view->priv->scroll_timeout != 0) /* reset on every motion event */ |
7786 | g_source_remove (text_view->priv->scroll_timeout); |
7787 | |
7788 | text_view->priv->scroll_timeout = |
7789 | cdk_threads_add_timeout (50, selection_scan_timeout, text_view); |
7790 | g_source_set_name_by_id (text_view->priv->scroll_timeout, "[ctk+] selection_scan_timeout"); |
7791 | |
7792 | ctk_text_view_selection_bubble_popup_unset (text_view); |
7793 | |
7794 | if (is_touchscreen) |
7795 | { |
7796 | _ctk_text_view_ensure_text_handles (text_view); |
7797 | ctk_text_view_update_handles (text_view, CTK_TEXT_HANDLE_MODE_SELECTION); |
7798 | ctk_text_view_show_magnifier (text_view, &cursor, x, y); |
7799 | } |
7800 | } |
7801 | |
7802 | static void |
7803 | ctk_text_view_drag_gesture_end (CtkGestureDrag *gesture, |
7804 | gdouble offset_x G_GNUC_UNUSED__attribute__ ((__unused__)), |
7805 | gdouble offset_y G_GNUC_UNUSED__attribute__ ((__unused__)), |
7806 | CtkTextView *text_view) |
7807 | { |
7808 | gboolean is_touchscreen, clicked_in_selection; |
7809 | gint start_x, start_y, x, y; |
7810 | CdkEventSequence *sequence; |
7811 | CtkTextViewPrivate *priv; |
7812 | const CdkEvent *event; |
7813 | CdkDevice *device; |
7814 | |
7815 | priv = text_view->priv; |
7816 | 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 () ))))))); |
7817 | drag_gesture_get_text_window_coords (gesture, text_view, |
7818 | &start_x, &start_y, &x, &y); |
7819 | |
7820 | clicked_in_selection = |
7821 | g_object_get_qdata (G_OBJECT (gesture)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((gesture)), (((GType) ((20) << (2)))))))), quark_text_selection_data) == NULL((void*)0); |
7822 | g_object_set_qdata (G_OBJECT (gesture)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((gesture)), (((GType) ((20) << (2)))))))), quark_text_selection_data, NULL((void*)0)); |
7823 | ctk_text_view_unobscure_mouse_cursor (text_view); |
7824 | |
7825 | if (priv->scroll_timeout != 0) |
7826 | { |
7827 | g_source_remove (priv->scroll_timeout); |
7828 | priv->scroll_timeout = 0; |
7829 | } |
7830 | |
7831 | if (priv->magnifier_popover) |
7832 | ctk_widget_hide (priv->magnifier_popover); |
7833 | |
7834 | /* Check whether the drag was cancelled rather than finished */ |
7835 | if (!ctk_gesture_handles_sequence (CTK_GESTURE (gesture)((((CtkGesture*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((gesture)), ((ctk_gesture_get_type ())))))), sequence)) |
7836 | return; |
7837 | |
7838 | event = ctk_gesture_get_last_event (CTK_GESTURE (gesture)((((CtkGesture*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((gesture)), ((ctk_gesture_get_type ())))))), sequence); |
7839 | device = cdk_event_get_source_device (event); |
7840 | is_touchscreen = ctk_simulate_touchscreen () || |
7841 | cdk_device_get_source (device) == CDK_SOURCE_TOUCHSCREEN; |
7842 | |
7843 | if (!is_touchscreen && clicked_in_selection && |
7844 | !ctk_drag_check_threshold (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))), start_x, start_y, x, y)) |
7845 | { |
7846 | CtkTextHandleMode mode = CTK_TEXT_HANDLE_MODE_NONE; |
7847 | CtkTextIter iter; |
7848 | |
7849 | /* Unselect everything; we clicked inside selection, but |
7850 | * didn't move by the drag threshold, so just clear selection |
7851 | * and place cursor. |
7852 | */ |
7853 | ctk_text_layout_get_iter_at_pixel (priv->layout, &iter, |
7854 | x + priv->xoffset, y + priv->yoffset); |
7855 | |
7856 | ctk_text_buffer_place_cursor (get_buffer (text_view), &iter); |
7857 | ctk_text_view_check_cursor_blink (text_view); |
7858 | |
7859 | if (priv->text_handle) |
7860 | { |
7861 | if (is_touchscreen) |
7862 | mode = CTK_TEXT_HANDLE_MODE_CURSOR; |
This statement is never executed | |
7863 | |
7864 | ctk_text_view_update_handles (text_view, mode); |
7865 | } |
7866 | } |
7867 | } |
7868 | |
7869 | static void |
7870 | ctk_text_view_start_selection_drag (CtkTextView *text_view, |
7871 | const CtkTextIter *iter, |
7872 | SelectionGranularity granularity, |
7873 | gboolean extend) |
7874 | { |
7875 | CtkTextViewPrivate *priv; |
7876 | CtkTextIter cursor, ins, bound; |
7877 | CtkTextIter orig_start, orig_end; |
7878 | CtkTextBuffer *buffer; |
7879 | SelectionData *data; |
7880 | |
7881 | priv = text_view->priv; |
7882 | data = g_slice_new0 (SelectionData)((SelectionData*) g_slice_alloc0 (sizeof (SelectionData))); |
7883 | data->granularity = granularity; |
7884 | |
7885 | buffer = get_buffer (text_view); |
7886 | |
7887 | cursor = *iter; |
7888 | extend_selection (text_view, data->granularity, &cursor, &ins, &bound); |
7889 | |
7890 | orig_start = ins; |
7891 | orig_end = bound; |
7892 | |
7893 | if (extend) |
7894 | { |
7895 | /* Extend selection */ |
7896 | CtkTextIter old_ins, old_bound; |
7897 | CtkTextIter old_start, old_end; |
7898 | |
7899 | ctk_text_buffer_get_iter_at_mark (buffer, &old_ins, ctk_text_buffer_get_insert (buffer)); |
7900 | ctk_text_buffer_get_iter_at_mark (buffer, &old_bound, ctk_text_buffer_get_selection_bound (buffer)); |
7901 | old_start = old_ins; |
7902 | old_end = old_bound; |
7903 | ctk_text_iter_order (&old_start, &old_end); |
7904 | |
7905 | /* move the front cursor, if the mouse is in front of the selection. Should the |
7906 | * cursor however be inside the selection (this happens on tripple click) then we |
7907 | * move the side which was last moved (current insert mark) */ |
7908 | if (ctk_text_iter_compare (&cursor, &old_start) <= 0 || |
7909 | (ctk_text_iter_compare (&cursor, &old_end) < 0 && |
7910 | ctk_text_iter_compare (&old_ins, &old_bound) <= 0)) |
7911 | { |
7912 | bound = old_end; |
7913 | } |
7914 | else |
7915 | { |
7916 | ins = bound; |
7917 | bound = old_start; |
7918 | } |
7919 | |
7920 | /* Store any previous selection */ |
7921 | if (ctk_text_iter_compare (&old_start, &old_end) != 0) |
7922 | { |
7923 | orig_start = old_ins; |
7924 | orig_end = old_bound; |
7925 | } |
7926 | } |
7927 | |
7928 | ctk_text_buffer_select_range (buffer, &ins, &bound); |
7929 | |
7930 | ctk_text_iter_order (&orig_start, &orig_end); |
7931 | data->orig_start = ctk_text_buffer_create_mark (buffer, NULL((void*)0), |
7932 | &orig_start, TRUE(!(0))); |
7933 | data->orig_end = ctk_text_buffer_create_mark (buffer, NULL((void*)0), |
7934 | &orig_end, TRUE(!(0))); |
7935 | data->buffer = g_object_ref (buffer)((__typeof__ (buffer)) (g_object_ref) (buffer)); |
7936 | ctk_text_view_check_cursor_blink (text_view); |
7937 | |
7938 | g_object_set_qdata_full (G_OBJECT (priv->drag_gesture)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((priv->drag_gesture)), (((GType) ((20) << (2)))) )))), |
7939 | quark_text_selection_data, |
7940 | data, (GDestroyNotify) selection_data_free); |
7941 | ctk_gesture_set_state (priv->drag_gesture, |
7942 | CTK_EVENT_SEQUENCE_CLAIMED); |
7943 | } |
7944 | |
7945 | /* returns whether we were really dragging */ |
7946 | static gboolean |
7947 | ctk_text_view_end_selection_drag (CtkTextView *text_view) |
7948 | { |
7949 | CtkTextViewPrivate *priv; |
7950 | |
7951 | priv = text_view->priv; |
7952 | |
7953 | if (!ctk_gesture_is_active (priv->drag_gesture)) |
7954 | return FALSE(0); |
7955 | |
7956 | if (priv->scroll_timeout != 0) |
7957 | { |
7958 | g_source_remove (priv->scroll_timeout); |
7959 | priv->scroll_timeout = 0; |
7960 | } |
7961 | |
7962 | if (priv->magnifier_popover) |
7963 | ctk_widget_hide (priv->magnifier_popover); |
7964 | |
7965 | return TRUE(!(0)); |
7966 | } |
7967 | |
7968 | /* |
7969 | * Layout utils |
7970 | */ |
7971 | |
7972 | static void |
7973 | ctk_text_view_set_attributes_from_style (CtkTextView *text_view, |
7974 | CtkTextAttributes *values) |
7975 | { |
7976 | CtkStyleContext *context; |
7977 | CdkRGBA bg_color, fg_color; |
7978 | CtkStateFlags state; |
7979 | |
7980 | context = ctk_widget_get_style_context (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
7981 | state = ctk_style_context_get_state (context); |
7982 | |
7983 | ctk_style_context_get_background_color (context, state, &bg_color); |
7984 | ctk_style_context_get_color (context, state, &fg_color); |
7985 | |
7986 | values->appearance.bg_color.red = CLAMP (bg_color.red * 65535. + 0.5, 0, 65535)(((bg_color.red * 65535. + 0.5) > (65535)) ? (65535) : ((( bg_color.red * 65535. + 0.5) < (0)) ? (0) : (bg_color.red * 65535. + 0.5))); |
7987 | values->appearance.bg_color.green = CLAMP (bg_color.green * 65535. + 0.5, 0, 65535)(((bg_color.green * 65535. + 0.5) > (65535)) ? (65535) : ( ((bg_color.green * 65535. + 0.5) < (0)) ? (0) : (bg_color. green * 65535. + 0.5))); |
7988 | values->appearance.bg_color.blue = CLAMP (bg_color.blue * 65535. + 0.5, 0, 65535)(((bg_color.blue * 65535. + 0.5) > (65535)) ? (65535) : (( (bg_color.blue * 65535. + 0.5) < (0)) ? (0) : (bg_color.blue * 65535. + 0.5))); |
7989 | |
7990 | values->appearance.fg_color.red = CLAMP (fg_color.red * 65535. + 0.5, 0, 65535)(((fg_color.red * 65535. + 0.5) > (65535)) ? (65535) : ((( fg_color.red * 65535. + 0.5) < (0)) ? (0) : (fg_color.red * 65535. + 0.5))); |
7991 | values->appearance.fg_color.green = CLAMP (fg_color.green * 65535. + 0.5, 0, 65535)(((fg_color.green * 65535. + 0.5) > (65535)) ? (65535) : ( ((fg_color.green * 65535. + 0.5) < (0)) ? (0) : (fg_color. green * 65535. + 0.5))); |
7992 | values->appearance.fg_color.blue = CLAMP (fg_color.blue * 65535. + 0.5, 0, 65535)(((fg_color.blue * 65535. + 0.5) > (65535)) ? (65535) : (( (fg_color.blue * 65535. + 0.5) < (0)) ? (0) : (fg_color.blue * 65535. + 0.5))); |
7993 | |
7994 | if (values->font) |
7995 | pango_font_description_free (values->font); |
7996 | |
7997 | ctk_style_context_get (context, state, "font", &values->font, NULL((void*)0)); |
7998 | } |
7999 | |
8000 | static void |
8001 | ctk_text_view_check_keymap_direction (CtkTextView *text_view) |
8002 | { |
8003 | CtkTextViewPrivate *priv = text_view->priv; |
8004 | |
8005 | if (priv->layout) |
8006 | { |
8007 | CtkSettings *settings = ctk_widget_get_settings (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
8008 | CdkKeymap *keymap = cdk_keymap_get_for_display (ctk_widget_get_display (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))))); |
8009 | CtkTextDirection new_cursor_dir; |
8010 | CtkTextDirection new_keyboard_dir; |
8011 | gboolean split_cursor; |
8012 | |
8013 | g_object_get (settings, |
8014 | "ctk-split-cursor", &split_cursor, |
8015 | NULL((void*)0)); |
8016 | |
8017 | if (cdk_keymap_get_direction (keymap) == PANGO_DIRECTION_RTL) |
8018 | new_keyboard_dir = CTK_TEXT_DIR_RTL; |
8019 | else |
8020 | new_keyboard_dir = CTK_TEXT_DIR_LTR; |
8021 | |
8022 | if (split_cursor) |
8023 | new_cursor_dir = CTK_TEXT_DIR_NONE; |
8024 | else |
8025 | new_cursor_dir = new_keyboard_dir; |
8026 | |
8027 | ctk_text_layout_set_cursor_direction (priv->layout, new_cursor_dir); |
8028 | ctk_text_layout_set_keyboard_direction (priv->layout, new_keyboard_dir); |
8029 | } |
8030 | } |
8031 | |
8032 | static void |
8033 | ctk_text_view_ensure_layout (CtkTextView *text_view) |
8034 | { |
8035 | CtkWidget *widget; |
8036 | CtkTextViewPrivate *priv; |
8037 | |
8038 | widget = CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))); |
8039 | priv = text_view->priv; |
8040 | |
8041 | if (priv->layout == NULL((void*)0)) |
8042 | { |
8043 | CtkTextAttributes *style; |
8044 | PangoContext *ltr_context, *rtl_context; |
8045 | GSList *tmp_list; |
8046 | |
8047 | DV(g_print(G_STRLOC"\n")); |
8048 | |
8049 | priv->layout = ctk_text_layout_new (); |
8050 | |
8051 | g_signal_connect (priv->layout,g_signal_connect_data ((priv->layout), ("invalidated"), (( (GCallback) (invalidated_handler))), (text_view), ((void*)0), (GConnectFlags) 0) |
8052 | "invalidated",g_signal_connect_data ((priv->layout), ("invalidated"), (( (GCallback) (invalidated_handler))), (text_view), ((void*)0), (GConnectFlags) 0) |
8053 | G_CALLBACK (invalidated_handler),g_signal_connect_data ((priv->layout), ("invalidated"), (( (GCallback) (invalidated_handler))), (text_view), ((void*)0), (GConnectFlags) 0) |
8054 | text_view)g_signal_connect_data ((priv->layout), ("invalidated"), (( (GCallback) (invalidated_handler))), (text_view), ((void*)0), (GConnectFlags) 0); |
8055 | |
8056 | g_signal_connect (priv->layout,g_signal_connect_data ((priv->layout), ("changed"), (((GCallback ) (changed_handler))), (text_view), ((void*)0), (GConnectFlags ) 0) |
8057 | "changed",g_signal_connect_data ((priv->layout), ("changed"), (((GCallback ) (changed_handler))), (text_view), ((void*)0), (GConnectFlags ) 0) |
8058 | G_CALLBACK (changed_handler),g_signal_connect_data ((priv->layout), ("changed"), (((GCallback ) (changed_handler))), (text_view), ((void*)0), (GConnectFlags ) 0) |
8059 | text_view)g_signal_connect_data ((priv->layout), ("changed"), (((GCallback ) (changed_handler))), (text_view), ((void*)0), (GConnectFlags ) 0); |
8060 | |
8061 | g_signal_connect (priv->layout,g_signal_connect_data ((priv->layout), ("allocate-child"), (((GCallback) (ctk_text_view_child_allocated))), (text_view) , ((void*)0), (GConnectFlags) 0) |
8062 | "allocate-child",g_signal_connect_data ((priv->layout), ("allocate-child"), (((GCallback) (ctk_text_view_child_allocated))), (text_view) , ((void*)0), (GConnectFlags) 0) |
8063 | G_CALLBACK (ctk_text_view_child_allocated),g_signal_connect_data ((priv->layout), ("allocate-child"), (((GCallback) (ctk_text_view_child_allocated))), (text_view) , ((void*)0), (GConnectFlags) 0) |
8064 | text_view)g_signal_connect_data ((priv->layout), ("allocate-child"), (((GCallback) (ctk_text_view_child_allocated))), (text_view) , ((void*)0), (GConnectFlags) 0); |
8065 | |
8066 | if (get_buffer (text_view)) |
8067 | ctk_text_layout_set_buffer (priv->layout, get_buffer (text_view)); |
8068 | |
8069 | if ((ctk_widget_has_focus (widget) && cursor_visible (text_view))) |
8070 | ctk_text_view_pend_cursor_blink (text_view); |
8071 | else |
8072 | ctk_text_layout_set_cursor_visible (priv->layout, FALSE(0)); |
8073 | |
8074 | ctk_text_layout_set_overwrite_mode (priv->layout, |
8075 | priv->overwrite_mode && priv->editable); |
8076 | |
8077 | ltr_context = ctk_widget_create_pango_context (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
8078 | pango_context_set_base_dir (ltr_context, PANGO_DIRECTION_LTR); |
8079 | rtl_context = ctk_widget_create_pango_context (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
8080 | pango_context_set_base_dir (rtl_context, PANGO_DIRECTION_RTL); |
8081 | |
8082 | ctk_text_layout_set_contexts (priv->layout, ltr_context, rtl_context); |
8083 | |
8084 | g_object_unref (ltr_context); |
8085 | g_object_unref (rtl_context); |
8086 | |
8087 | ctk_text_view_check_keymap_direction (text_view); |
8088 | |
8089 | style = ctk_text_attributes_new (); |
8090 | |
8091 | ctk_text_view_set_attributes_from_style (text_view, style); |
8092 | |
8093 | style->pixels_above_lines = priv->pixels_above_lines; |
8094 | style->pixels_below_lines = priv->pixels_below_lines; |
8095 | style->pixels_inside_wrap = priv->pixels_inside_wrap; |
8096 | |
8097 | style->left_margin = priv->left_margin; |
8098 | style->right_margin = priv->right_margin; |
8099 | priv->layout->right_padding = priv->right_padding; |
8100 | priv->layout->left_padding = priv->left_padding; |
8101 | |
8102 | style->indent = priv->indent; |
8103 | style->tabs = priv->tabs ? pango_tab_array_copy (priv->tabs) : NULL((void*)0); |
8104 | |
8105 | style->wrap_mode = priv->wrap_mode; |
8106 | style->justification = priv->justify; |
8107 | style->direction = ctk_widget_get_direction (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
8108 | |
8109 | ctk_text_layout_set_default_style (priv->layout, style); |
8110 | |
8111 | ctk_text_attributes_unref (style); |
8112 | |
8113 | /* Set layout for all anchored children */ |
8114 | |
8115 | tmp_list = priv->children; |
8116 | while (tmp_list != NULL((void*)0)) |
8117 | { |
8118 | CtkTextViewChild *vc = tmp_list->data; |
8119 | |
8120 | if (vc->anchor) |
8121 | { |
8122 | ctk_text_anchored_child_set_layout (vc->widget, |
8123 | priv->layout); |
8124 | /* vc may now be invalid! */ |
8125 | } |
8126 | |
8127 | tmp_list = tmp_list->next; |
8128 | } |
8129 | } |
8130 | } |
8131 | |
8132 | /** |
8133 | * ctk_text_view_get_default_attributes: |
8134 | * @text_view: a #CtkTextView |
8135 | * |
8136 | * Obtains a copy of the default text attributes. These are the |
8137 | * attributes used for text unless a tag overrides them. |
8138 | * You’d typically pass the default attributes in to |
8139 | * ctk_text_iter_get_attributes() in order to get the |
8140 | * attributes in effect at a given text position. |
8141 | * |
8142 | * The return value is a copy owned by the caller of this function, |
8143 | * and should be freed with ctk_text_attributes_unref(). |
8144 | * |
8145 | * Returns: a new #CtkTextAttributes |
8146 | **/ |
8147 | CtkTextAttributes* |
8148 | ctk_text_view_get_default_attributes (CtkTextView *text_view) |
8149 | { |
8150 | g_return_val_if_fail (CTK_IS_TEXT_VIEW (text_view), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return (((void*)0)); } } while (0); |
8151 | |
8152 | ctk_text_view_ensure_layout (text_view); |
8153 | |
8154 | return ctk_text_attributes_copy (text_view->priv->layout->default_style); |
8155 | } |
8156 | |
8157 | static void |
8158 | ctk_text_view_destroy_layout (CtkTextView *text_view) |
8159 | { |
8160 | CtkTextViewPrivate *priv = text_view->priv; |
8161 | |
8162 | if (priv->layout) |
8163 | { |
8164 | GSList *tmp_list; |
8165 | |
8166 | ctk_text_view_remove_validate_idles (text_view); |
8167 | |
8168 | g_signal_handlers_disconnect_by_func (priv->layout,g_signal_handlers_disconnect_matched ((priv->layout), (GSignalMatchType ) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*) 0), (invalidated_handler), (text_view)) |
8169 | invalidated_handler,g_signal_handlers_disconnect_matched ((priv->layout), (GSignalMatchType ) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*) 0), (invalidated_handler), (text_view)) |
8170 | text_view)g_signal_handlers_disconnect_matched ((priv->layout), (GSignalMatchType ) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*) 0), (invalidated_handler), (text_view)); |
8171 | g_signal_handlers_disconnect_by_func (priv->layout,g_signal_handlers_disconnect_matched ((priv->layout), (GSignalMatchType ) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*) 0), (changed_handler), (text_view)) |
8172 | changed_handler,g_signal_handlers_disconnect_matched ((priv->layout), (GSignalMatchType ) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*) 0), (changed_handler), (text_view)) |
8173 | text_view)g_signal_handlers_disconnect_matched ((priv->layout), (GSignalMatchType ) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*) 0), (changed_handler), (text_view)); |
8174 | |
8175 | /* Remove layout from all anchored children */ |
8176 | tmp_list = priv->children; |
8177 | while (tmp_list != NULL((void*)0)) |
8178 | { |
8179 | CtkTextViewChild *vc = tmp_list->data; |
8180 | |
8181 | if (vc->anchor) |
8182 | { |
8183 | ctk_text_anchored_child_set_layout (vc->widget, NULL((void*)0)); |
8184 | /* vc may now be invalid! */ |
8185 | } |
8186 | |
8187 | tmp_list = tmp_list->next; |
8188 | } |
8189 | |
8190 | ctk_text_view_stop_cursor_blink (text_view); |
8191 | ctk_text_view_end_selection_drag (text_view); |
8192 | |
8193 | g_object_unref (priv->layout); |
8194 | priv->layout = NULL((void*)0); |
8195 | } |
8196 | } |
8197 | |
8198 | /** |
8199 | * ctk_text_view_reset_im_context: |
8200 | * @text_view: a #CtkTextView |
8201 | * |
8202 | * Reset the input method context of the text view if needed. |
8203 | * |
8204 | * This can be necessary in the case where modifying the buffer |
8205 | * would confuse on-going input method behavior. |
8206 | * |
8207 | * Since: 2.22 |
8208 | */ |
8209 | void |
8210 | ctk_text_view_reset_im_context (CtkTextView *text_view) |
8211 | { |
8212 | g_return_if_fail (CTK_IS_TEXT_VIEW (text_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return; } } while (0); |
8213 | |
8214 | if (text_view->priv->need_im_reset) |
8215 | { |
8216 | text_view->priv->need_im_reset = FALSE(0); |
8217 | ctk_im_context_reset (text_view->priv->im_context); |
8218 | } |
8219 | } |
8220 | |
8221 | /** |
8222 | * ctk_text_view_im_context_filter_keypress: |
8223 | * @text_view: a #CtkTextView |
8224 | * @event: the key event |
8225 | * |
8226 | * Allow the #CtkTextView input method to internally handle key press |
8227 | * and release events. If this function returns %TRUE, then no further |
8228 | * processing should be done for this key event. See |
8229 | * ctk_im_context_filter_keypress(). |
8230 | * |
8231 | * Note that you are expected to call this function from your handler |
8232 | * when overriding key event handling. This is needed in the case when |
8233 | * you need to insert your own key handling between the input method |
8234 | * and the default key event handling of the #CtkTextView. |
8235 | * |
8236 | * |[<!-- language="C" --> |
8237 | * static gboolean |
8238 | * ctk_foo_bar_key_press_event (CtkWidget *widget, |
8239 | * CdkEventKey *event) |
8240 | * { |
8241 | * guint keyval; |
8242 | * |
8243 | * cdk_event_get_keyval ((CdkEvent*)event, &keyval); |
8244 | * |
8245 | * if (keyval == CDK_KEY_Return || keyval == CDK_KEY_KP_Enter) |
8246 | * { |
8247 | * if (ctk_text_view_im_context_filter_keypress (CTK_TEXT_VIEW (widget), event)) |
8248 | * return TRUE; |
8249 | * } |
8250 | * |
8251 | * // Do some stuff |
8252 | * |
8253 | * return CTK_WIDGET_CLASS (ctk_foo_bar_parent_class)->key_press_event (widget, event); |
8254 | * } |
8255 | * ]| |
8256 | * |
8257 | * Returns: %TRUE if the input method handled the key event. |
8258 | * |
8259 | * Since: 2.22 |
8260 | */ |
8261 | gboolean |
8262 | ctk_text_view_im_context_filter_keypress (CtkTextView *text_view, |
8263 | CdkEventKey *event) |
8264 | { |
8265 | g_return_val_if_fail (CTK_IS_TEXT_VIEW (text_view), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return ((0)); } } while ( 0); |
8266 | |
8267 | return ctk_im_context_filter_keypress (text_view->priv->im_context, event); |
8268 | } |
8269 | |
8270 | /* |
8271 | * DND feature |
8272 | */ |
8273 | |
8274 | static void |
8275 | drag_begin_cb (CtkWidget *widget, |
8276 | CdkDragContext *context, |
8277 | gpointer data G_GNUC_UNUSED__attribute__ ((__unused__))) |
8278 | { |
8279 | CtkTextView *text_view = CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ())))))); |
8280 | CtkTextBuffer *buffer = ctk_text_view_get_buffer (text_view); |
8281 | CtkTextIter start; |
8282 | CtkTextIter end; |
8283 | cairo_surface_t *surface = NULL((void*)0); |
8284 | |
8285 | 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))); |
8286 | |
8287 | if (ctk_text_buffer_get_selection_bounds (buffer, &start, &end)) |
8288 | surface = _ctk_text_util_create_rich_drag_icon (widget, buffer, &start, &end); |
8289 | |
8290 | if (surface) |
8291 | { |
8292 | ctk_drag_set_icon_surface (context, surface); |
8293 | cairo_surface_destroy (surface); |
8294 | } |
8295 | else |
8296 | { |
8297 | ctk_drag_set_icon_default (context); |
8298 | } |
8299 | } |
8300 | |
8301 | static void |
8302 | ctk_text_view_start_selection_dnd (CtkTextView *text_view, |
8303 | const CtkTextIter *iter G_GNUC_UNUSED__attribute__ ((__unused__)), |
8304 | const CdkEvent *event, |
8305 | gint x, |
8306 | gint y) |
8307 | { |
8308 | CtkTargetList *target_list; |
8309 | |
8310 | target_list = ctk_text_buffer_get_copy_target_list (get_buffer (text_view)); |
8311 | |
8312 | g_signal_connect (text_view, "drag-begin",g_signal_connect_data ((text_view), ("drag-begin"), (((GCallback ) (drag_begin_cb))), (((void*)0)), ((void*)0), (GConnectFlags ) 0) |
8313 | G_CALLBACK (drag_begin_cb), NULL)g_signal_connect_data ((text_view), ("drag-begin"), (((GCallback ) (drag_begin_cb))), (((void*)0)), ((void*)0), (GConnectFlags ) 0); |
8314 | ctk_drag_begin_with_coordinates (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))), target_list, |
8315 | CDK_ACTION_COPY | CDK_ACTION_MOVE, |
8316 | 1, (CdkEvent*) event, x, y); |
8317 | } |
8318 | |
8319 | static void |
8320 | ctk_text_view_drag_begin (CtkWidget *widget G_GNUC_UNUSED__attribute__ ((__unused__)), |
8321 | CdkDragContext *context G_GNUC_UNUSED__attribute__ ((__unused__))) |
8322 | { |
8323 | /* do nothing */ |
8324 | } |
8325 | |
8326 | static void |
8327 | ctk_text_view_drag_end (CtkWidget *widget, |
8328 | CdkDragContext *context G_GNUC_UNUSED__attribute__ ((__unused__))) |
8329 | { |
8330 | CtkTextView *text_view; |
8331 | |
8332 | text_view = CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ())))))); |
8333 | text_view->priv->dnd_x = text_view->priv->dnd_y = -1; |
8334 | } |
8335 | |
8336 | static void |
8337 | ctk_text_view_drag_data_get (CtkWidget *widget, |
8338 | CdkDragContext *context G_GNUC_UNUSED__attribute__ ((__unused__)), |
8339 | CtkSelectionData *selection_data, |
8340 | guint info, |
8341 | guint time G_GNUC_UNUSED__attribute__ ((__unused__))) |
8342 | { |
8343 | CtkTextView *text_view = CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ())))))); |
8344 | CtkTextBuffer *buffer = ctk_text_view_get_buffer (text_view); |
8345 | |
8346 | if (info == CTK_TEXT_BUFFER_TARGET_INFO_BUFFER_CONTENTS) |
8347 | { |
8348 | ctk_selection_data_set (selection_data, |
8349 | cdk_atom_intern_static_string ("CTK_TEXT_BUFFER_CONTENTS"), |
8350 | 8, /* bytes */ |
8351 | (void*)&buffer, |
8352 | sizeof (buffer)); |
8353 | } |
8354 | else if (info == CTK_TEXT_BUFFER_TARGET_INFO_RICH_TEXT) |
8355 | { |
8356 | CtkTextIter start; |
8357 | CtkTextIter end; |
8358 | guint8 *str = NULL((void*)0); |
8359 | gsize len; |
8360 | |
8361 | if (ctk_text_buffer_get_selection_bounds (buffer, &start, &end)) |
8362 | { |
8363 | /* Extract the selected text */ |
8364 | str = ctk_text_buffer_serialize (buffer, buffer, |
8365 | ctk_selection_data_get_target (selection_data), |
8366 | &start, &end, |
8367 | &len); |
8368 | } |
8369 | |
8370 | if (str) |
8371 | { |
8372 | ctk_selection_data_set (selection_data, |
8373 | ctk_selection_data_get_target (selection_data), |
8374 | 8, /* bytes */ |
8375 | (guchar *) str, len); |
8376 | g_free (str); |
8377 | } |
8378 | } |
8379 | else |
8380 | { |
8381 | CtkTextIter start; |
8382 | CtkTextIter end; |
8383 | gchar *str = NULL((void*)0); |
8384 | |
8385 | if (ctk_text_buffer_get_selection_bounds (buffer, &start, &end)) |
8386 | { |
8387 | /* Extract the selected text */ |
8388 | str = ctk_text_iter_get_visible_text (&start, &end); |
8389 | } |
8390 | |
8391 | if (str) |
8392 | { |
8393 | ctk_selection_data_set_text (selection_data, str, -1); |
8394 | g_free (str); |
8395 | } |
8396 | } |
8397 | } |
8398 | |
8399 | static void |
8400 | ctk_text_view_drag_data_delete (CtkWidget *widget, |
8401 | CdkDragContext *context G_GNUC_UNUSED__attribute__ ((__unused__))) |
8402 | { |
8403 | ctk_text_buffer_delete_selection (CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ()))))))->priv->buffer, |
8404 | TRUE(!(0)), CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ()))))))->priv->editable); |
8405 | } |
8406 | |
8407 | static void |
8408 | ctk_text_view_drag_leave (CtkWidget *widget, |
8409 | CdkDragContext *context G_GNUC_UNUSED__attribute__ ((__unused__)), |
8410 | guint time G_GNUC_UNUSED__attribute__ ((__unused__))) |
8411 | { |
8412 | CtkTextView *text_view; |
8413 | CtkTextViewPrivate *priv; |
8414 | |
8415 | text_view = CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ())))))); |
8416 | priv = text_view->priv; |
8417 | |
8418 | ctk_text_mark_set_visible (priv->dnd_mark, FALSE(0)); |
8419 | |
8420 | priv->dnd_x = priv->dnd_y = -1; |
8421 | |
8422 | if (priv->scroll_timeout != 0) |
8423 | g_source_remove (priv->scroll_timeout); |
8424 | |
8425 | priv->scroll_timeout = 0; |
8426 | |
8427 | ctk_drag_unhighlight (widget); |
8428 | } |
8429 | |
8430 | static gboolean |
8431 | ctk_text_view_drag_motion (CtkWidget *widget, |
8432 | CdkDragContext *context, |
8433 | gint x, |
8434 | gint y, |
8435 | guint time) |
8436 | { |
8437 | CtkTextIter newplace; |
8438 | CtkTextView *text_view; |
8439 | CtkTextViewPrivate *priv; |
8440 | CtkTextIter start; |
8441 | CtkTextIter end; |
8442 | CdkRectangle target_rect; |
8443 | gint bx, by; |
8444 | CdkAtom target; |
8445 | CdkDragAction suggested_action = 0; |
8446 | |
8447 | text_view = CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ())))))); |
8448 | priv = text_view->priv; |
8449 | |
8450 | target_rect = priv->text_window->allocation; |
8451 | |
8452 | if (x < target_rect.x || |
8453 | y < target_rect.y || |
8454 | x > (target_rect.x + target_rect.width) || |
8455 | y > (target_rect.y + target_rect.height)) |
8456 | return FALSE(0); /* outside the text window, allow parent widgets to handle event */ |
8457 | |
8458 | ctk_text_view_window_to_buffer_coords (text_view, |
8459 | CTK_TEXT_WINDOW_WIDGET, |
8460 | x, y, |
8461 | &bx, &by); |
8462 | |
8463 | ctk_text_layout_get_iter_at_pixel (priv->layout, |
8464 | &newplace, |
8465 | bx, by); |
8466 | |
8467 | target = ctk_drag_dest_find_target (widget, context, |
8468 | ctk_drag_dest_get_target_list (widget)); |
8469 | |
8470 | if (target == CDK_NONE((CdkAtom)((gpointer) (gulong) (0)))) |
8471 | { |
8472 | /* can't accept any of the offered targets */ |
8473 | } |
8474 | else if (ctk_text_buffer_get_selection_bounds (get_buffer (text_view), |
8475 | &start, &end) && |
8476 | ctk_text_iter_compare (&newplace, &start) >= 0 && |
8477 | ctk_text_iter_compare (&newplace, &end) <= 0) |
8478 | { |
8479 | /* We're inside the selection. */ |
8480 | } |
8481 | else |
8482 | { |
8483 | if (ctk_text_iter_can_insert (&newplace, priv->editable)) |
8484 | { |
8485 | CtkWidget *source_widget; |
8486 | |
8487 | suggested_action = cdk_drag_context_get_suggested_action (context); |
8488 | |
8489 | source_widget = ctk_drag_get_source_widget (context); |
8490 | |
8491 | if (source_widget == widget) |
8492 | { |
8493 | /* Default to MOVE, unless the user has |
8494 | * pressed ctrl or alt to affect available actions |
8495 | */ |
8496 | if ((cdk_drag_context_get_actions (context) & CDK_ACTION_MOVE) != 0) |
8497 | suggested_action = CDK_ACTION_MOVE; |
8498 | } |
8499 | } |
8500 | else |
8501 | { |
8502 | /* Can't drop here. */ |
8503 | } |
8504 | } |
8505 | |
8506 | if (suggested_action != 0) |
8507 | { |
8508 | ctk_text_mark_set_visible (priv->dnd_mark, cursor_visible (text_view)); |
8509 | cdk_drag_status (context, suggested_action, time); |
8510 | } |
8511 | else |
8512 | { |
8513 | cdk_drag_status (context, 0, time); |
8514 | ctk_text_mark_set_visible (priv->dnd_mark, FALSE(0)); |
8515 | } |
8516 | |
8517 | /* DnD uses text window coords, so subtract extra widget |
8518 | * coords that happen e.g. when displaying line numbers. |
8519 | */ |
8520 | priv->dnd_x = x - target_rect.x; |
8521 | priv->dnd_y = y - target_rect.y; |
8522 | |
8523 | if (!priv->scroll_timeout) |
8524 | { |
8525 | priv->scroll_timeout = |
8526 | cdk_threads_add_timeout (100, drag_scan_timeout, text_view); |
8527 | g_source_set_name_by_id (text_view->priv->scroll_timeout, "[ctk+] drag_scan_timeout"); |
8528 | } |
8529 | |
8530 | ctk_drag_highlight (widget); |
8531 | |
8532 | /* TRUE return means don't propagate the drag motion to parent |
8533 | * widgets that may also be drop sites. |
8534 | */ |
8535 | return TRUE(!(0)); |
8536 | } |
8537 | |
8538 | static gboolean |
8539 | ctk_text_view_drag_drop (CtkWidget *widget, |
8540 | CdkDragContext *context, |
8541 | gint x G_GNUC_UNUSED__attribute__ ((__unused__)), |
8542 | gint y G_GNUC_UNUSED__attribute__ ((__unused__)), |
8543 | guint time) |
8544 | { |
8545 | CtkTextView *text_view; |
8546 | CtkTextViewPrivate *priv; |
8547 | CtkTextIter drop_point; |
8548 | CdkAtom target = CDK_NONE((CdkAtom)((gpointer) (gulong) (0))); |
8549 | |
8550 | text_view = CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ())))))); |
8551 | priv = text_view->priv; |
8552 | |
8553 | if (priv->scroll_timeout != 0) |
8554 | g_source_remove (priv->scroll_timeout); |
8555 | |
8556 | priv->scroll_timeout = 0; |
8557 | |
8558 | ctk_text_mark_set_visible (priv->dnd_mark, FALSE(0)); |
8559 | |
8560 | ctk_text_buffer_get_iter_at_mark (get_buffer (text_view), |
8561 | &drop_point, |
8562 | priv->dnd_mark); |
8563 | |
8564 | if (ctk_text_iter_can_insert (&drop_point, priv->editable)) |
8565 | target = ctk_drag_dest_find_target (widget, context, NULL((void*)0)); |
8566 | |
8567 | if (target != CDK_NONE((CdkAtom)((gpointer) (gulong) (0)))) |
8568 | ctk_drag_get_data (widget, context, target, time); |
8569 | else |
8570 | ctk_drag_finish (context, FALSE(0), FALSE(0), time); |
8571 | |
8572 | return TRUE(!(0)); |
8573 | } |
8574 | |
8575 | static void |
8576 | insert_text_data (CtkTextView *text_view, |
8577 | CtkTextIter *drop_point, |
8578 | CtkSelectionData *selection_data) |
8579 | { |
8580 | guchar *str; |
8581 | |
8582 | str = ctk_selection_data_get_text (selection_data); |
8583 | |
8584 | if (str) |
8585 | { |
8586 | if (!ctk_text_buffer_insert_interactive (get_buffer (text_view), |
8587 | drop_point, (gchar *) str, -1, |
8588 | text_view->priv->editable)) |
8589 | { |
8590 | ctk_widget_error_bell (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
8591 | } |
8592 | |
8593 | g_free (str); |
8594 | } |
8595 | } |
8596 | |
8597 | static void |
8598 | ctk_text_view_drag_data_received (CtkWidget *widget, |
8599 | CdkDragContext *context, |
8600 | gint x G_GNUC_UNUSED__attribute__ ((__unused__)), |
8601 | gint y G_GNUC_UNUSED__attribute__ ((__unused__)), |
8602 | CtkSelectionData *selection_data, |
8603 | guint info, |
8604 | guint time) |
8605 | { |
8606 | CtkTextIter drop_point; |
8607 | CtkTextView *text_view; |
8608 | CtkTextViewPrivate *priv; |
8609 | gboolean success = FALSE(0); |
8610 | CtkTextBuffer *buffer = NULL((void*)0); |
8611 | |
8612 | text_view = CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ())))))); |
8613 | priv = text_view->priv; |
8614 | |
8615 | if (!priv->dnd_mark) |
8616 | goto done; |
8617 | |
8618 | buffer = get_buffer (text_view); |
8619 | |
8620 | ctk_text_buffer_get_iter_at_mark (buffer, |
8621 | &drop_point, |
8622 | priv->dnd_mark); |
8623 | |
8624 | if (!ctk_text_iter_can_insert (&drop_point, priv->editable)) |
8625 | goto done; |
8626 | |
8627 | success = TRUE(!(0)); |
8628 | |
8629 | ctk_text_buffer_begin_user_action (buffer); |
8630 | |
8631 | if (info == CTK_TEXT_BUFFER_TARGET_INFO_BUFFER_CONTENTS) |
8632 | { |
8633 | CtkTextBuffer *src_buffer = NULL((void*)0); |
8634 | CtkTextIter start, end; |
8635 | gboolean copy_tags = TRUE(!(0)); |
8636 | |
8637 | if (ctk_selection_data_get_length (selection_data) != sizeof (src_buffer)) |
8638 | return; |
8639 | |
8640 | memcpy (&src_buffer, ctk_selection_data_get_data (selection_data), sizeof (src_buffer)); |
8641 | |
8642 | if (src_buffer == NULL((void*)0)) |
8643 | return; |
8644 | |
8645 | g_return_if_fail (CTK_IS_TEXT_BUFFER (src_buffer))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((src_buffer)); GType __t = ((ctk_text_buffer_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_TEXT_BUFFER (src_buffer)"); return ; } } while (0); |
8646 | |
8647 | if (ctk_text_buffer_get_tag_table (src_buffer) != |
8648 | ctk_text_buffer_get_tag_table (buffer)) |
8649 | { |
8650 | /* try to find a suitable rich text target instead */ |
8651 | CdkAtom *atoms; |
8652 | gint n_atoms; |
8653 | GList *list; |
8654 | CdkAtom target = CDK_NONE((CdkAtom)((gpointer) (gulong) (0))); |
8655 | |
8656 | copy_tags = FALSE(0); |
8657 | |
8658 | atoms = ctk_text_buffer_get_deserialize_formats (buffer, &n_atoms); |
8659 | |
8660 | for (list = cdk_drag_context_list_targets (context); list; list = list->next) |
8661 | { |
8662 | gint i; |
8663 | |
8664 | for (i = 0; i < n_atoms; i++) |
8665 | if (GUINT_TO_POINTER (atoms[i])((gpointer) (gulong) (atoms[i])) == list->data) |
8666 | { |
8667 | target = atoms[i]; |
8668 | break; |
8669 | } |
8670 | } |
8671 | |
8672 | g_free (atoms); |
8673 | |
8674 | if (target != CDK_NONE((CdkAtom)((gpointer) (gulong) (0)))) |
8675 | { |
8676 | ctk_drag_get_data (widget, context, target, time); |
8677 | ctk_text_buffer_end_user_action (buffer); |
8678 | return; |
8679 | } |
8680 | } |
8681 | |
8682 | if (ctk_text_buffer_get_selection_bounds (src_buffer, |
8683 | &start, |
8684 | &end)) |
8685 | { |
8686 | if (copy_tags) |
8687 | ctk_text_buffer_insert_range_interactive (buffer, |
8688 | &drop_point, |
8689 | &start, |
8690 | &end, |
8691 | priv->editable); |
8692 | else |
8693 | { |
8694 | gchar *str; |
8695 | |
8696 | str = ctk_text_iter_get_visible_text (&start, &end); |
8697 | ctk_text_buffer_insert_interactive (buffer, |
8698 | &drop_point, str, -1, |
8699 | priv->editable); |
8700 | g_free (str); |
8701 | } |
8702 | } |
8703 | } |
8704 | else if (ctk_selection_data_get_length (selection_data) > 0 && |
8705 | info == CTK_TEXT_BUFFER_TARGET_INFO_RICH_TEXT) |
8706 | { |
8707 | gboolean retval; |
8708 | GError *error = NULL((void*)0); |
8709 | |
8710 | retval = ctk_text_buffer_deserialize (buffer, buffer, |
8711 | ctk_selection_data_get_target (selection_data), |
8712 | &drop_point, |
8713 | (guint8 *) ctk_selection_data_get_data (selection_data), |
8714 | ctk_selection_data_get_length (selection_data), |
8715 | &error); |
8716 | |
8717 | if (!retval) |
8718 | { |
8719 | g_warning ("error pasting: %s", error->message); |
8720 | g_clear_error (&error); |
8721 | } |
8722 | } |
8723 | else |
8724 | insert_text_data (text_view, &drop_point, selection_data); |
8725 | |
8726 | done: |
8727 | ctk_drag_finish (context, success, |
8728 | success && cdk_drag_context_get_selected_action (context) == CDK_ACTION_MOVE, |
8729 | time); |
8730 | |
8731 | if (success) |
8732 | { |
8733 | ctk_text_buffer_get_iter_at_mark (buffer, |
8734 | &drop_point, |
8735 | priv->dnd_mark); |
8736 | ctk_text_buffer_place_cursor (buffer, &drop_point); |
8737 | |
8738 | ctk_text_buffer_end_user_action (buffer); |
8739 | } |
8740 | } |
8741 | |
8742 | /** |
8743 | * ctk_text_view_get_hadjustment: |
8744 | * @text_view: a #CtkTextView |
8745 | * |
8746 | * Gets the horizontal-scrolling #CtkAdjustment. |
8747 | * |
8748 | * Returns: (transfer none): pointer to the horizontal #CtkAdjustment |
8749 | * |
8750 | * Since: 2.22 |
8751 | * |
8752 | * Deprecated: 3.0: Use ctk_scrollable_get_hadjustment() |
8753 | **/ |
8754 | CtkAdjustment* |
8755 | ctk_text_view_get_hadjustment (CtkTextView *text_view) |
8756 | { |
8757 | g_return_val_if_fail (CTK_IS_TEXT_VIEW (text_view), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return (((void*)0)); } } while (0); |
8758 | |
8759 | return text_view->priv->hadjustment; |
8760 | } |
8761 | |
8762 | static void |
8763 | ctk_text_view_set_hadjustment (CtkTextView *text_view, |
8764 | CtkAdjustment *adjustment) |
8765 | { |
8766 | CtkTextViewPrivate *priv = text_view->priv; |
8767 | |
8768 | if (adjustment && priv->hadjustment == adjustment) |
8769 | return; |
8770 | |
8771 | if (priv->hadjustment != NULL((void*)0)) |
8772 | { |
8773 | g_signal_handlers_disconnect_by_func (priv->hadjustment,g_signal_handlers_disconnect_matched ((priv->hadjustment), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA ), 0, 0, ((void*)0), (ctk_text_view_value_changed), (text_view )) |
8774 | ctk_text_view_value_changed,g_signal_handlers_disconnect_matched ((priv->hadjustment), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA ), 0, 0, ((void*)0), (ctk_text_view_value_changed), (text_view )) |
8775 | text_view)g_signal_handlers_disconnect_matched ((priv->hadjustment), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA ), 0, 0, ((void*)0), (ctk_text_view_value_changed), (text_view )); |
8776 | g_object_unref (priv->hadjustment); |
8777 | } |
8778 | |
8779 | if (adjustment == NULL((void*)0)) |
8780 | adjustment = ctk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0); |
8781 | |
8782 | g_signal_connect (adjustment, "value-changed",g_signal_connect_data ((adjustment), ("value-changed"), (((GCallback ) (ctk_text_view_value_changed))), (text_view), ((void*)0), ( GConnectFlags) 0) |
8783 | G_CALLBACK (ctk_text_view_value_changed), text_view)g_signal_connect_data ((adjustment), ("value-changed"), (((GCallback ) (ctk_text_view_value_changed))), (text_view), ((void*)0), ( GConnectFlags) 0); |
8784 | priv->hadjustment = g_object_ref_sink (adjustment)((__typeof__ (adjustment)) (g_object_ref_sink) (adjustment)); |
8785 | ctk_text_view_set_hadjustment_values (text_view); |
8786 | |
8787 | g_object_notify (G_OBJECT (text_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), (((GType) ((20) << (2)))))))), "hadjustment"); |
8788 | } |
8789 | |
8790 | /** |
8791 | * ctk_text_view_get_vadjustment: |
8792 | * @text_view: a #CtkTextView |
8793 | * |
8794 | * Gets the vertical-scrolling #CtkAdjustment. |
8795 | * |
8796 | * Returns: (transfer none): pointer to the vertical #CtkAdjustment |
8797 | * |
8798 | * Since: 2.22 |
8799 | * |
8800 | * Deprecated: 3.0: Use ctk_scrollable_get_vadjustment() |
8801 | **/ |
8802 | CtkAdjustment* |
8803 | ctk_text_view_get_vadjustment (CtkTextView *text_view) |
8804 | { |
8805 | g_return_val_if_fail (CTK_IS_TEXT_VIEW (text_view), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return (((void*)0)); } } while (0); |
8806 | |
8807 | return text_view->priv->vadjustment; |
8808 | } |
8809 | |
8810 | static void |
8811 | ctk_text_view_set_vadjustment (CtkTextView *text_view, |
8812 | CtkAdjustment *adjustment) |
8813 | { |
8814 | CtkTextViewPrivate *priv = text_view->priv; |
8815 | |
8816 | if (adjustment && priv->vadjustment == adjustment) |
8817 | return; |
8818 | |
8819 | if (priv->vadjustment != NULL((void*)0)) |
8820 | { |
8821 | g_signal_handlers_disconnect_by_func (priv->vadjustment,g_signal_handlers_disconnect_matched ((priv->vadjustment), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA ), 0, 0, ((void*)0), (ctk_text_view_value_changed), (text_view )) |
8822 | ctk_text_view_value_changed,g_signal_handlers_disconnect_matched ((priv->vadjustment), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA ), 0, 0, ((void*)0), (ctk_text_view_value_changed), (text_view )) |
8823 | text_view)g_signal_handlers_disconnect_matched ((priv->vadjustment), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA ), 0, 0, ((void*)0), (ctk_text_view_value_changed), (text_view )); |
8824 | g_object_unref (priv->vadjustment); |
8825 | } |
8826 | |
8827 | if (adjustment == NULL((void*)0)) |
8828 | adjustment = ctk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0); |
8829 | |
8830 | g_signal_connect (adjustment, "value-changed",g_signal_connect_data ((adjustment), ("value-changed"), (((GCallback ) (ctk_text_view_value_changed))), (text_view), ((void*)0), ( GConnectFlags) 0) |
8831 | G_CALLBACK (ctk_text_view_value_changed), text_view)g_signal_connect_data ((adjustment), ("value-changed"), (((GCallback ) (ctk_text_view_value_changed))), (text_view), ((void*)0), ( GConnectFlags) 0); |
8832 | priv->vadjustment = g_object_ref_sink (adjustment)((__typeof__ (adjustment)) (g_object_ref_sink) (adjustment)); |
8833 | ctk_text_view_set_vadjustment_values (text_view); |
8834 | |
8835 | g_object_notify (G_OBJECT (text_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), (((GType) ((20) << (2)))))))), "vadjustment"); |
8836 | } |
8837 | |
8838 | static void |
8839 | ctk_text_view_set_hadjustment_values (CtkTextView *text_view) |
8840 | { |
8841 | CtkTextViewPrivate *priv; |
8842 | gint screen_width; |
8843 | gdouble old_value; |
8844 | gdouble new_value; |
8845 | gdouble new_upper; |
8846 | |
8847 | priv = text_view->priv; |
8848 | |
8849 | screen_width = SCREEN_WIDTH (text_view)text_window_get_width (((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((text_view)), ((ctk_text_view_get_type () ))))))->priv->text_window); |
8850 | old_value = ctk_adjustment_get_value (priv->hadjustment); |
8851 | new_upper = MAX (screen_width, priv->width)(((screen_width) > (priv->width)) ? (screen_width) : (priv ->width)); |
8852 | |
8853 | g_object_set (priv->hadjustment, |
8854 | "lower", 0.0, |
8855 | "upper", new_upper, |
8856 | "page-size", (gdouble)screen_width, |
8857 | "step-increment", screen_width * 0.1, |
8858 | "page-increment", screen_width * 0.9, |
8859 | NULL((void*)0)); |
8860 | |
8861 | new_value = CLAMP (old_value, 0, new_upper - screen_width)(((old_value) > (new_upper - screen_width)) ? (new_upper - screen_width) : (((old_value) < (0)) ? (0) : (old_value)) ); |
8862 | if (new_value != old_value) |
8863 | ctk_adjustment_set_value (priv->hadjustment, new_value); |
8864 | } |
8865 | |
8866 | static void |
8867 | ctk_text_view_set_vadjustment_values (CtkTextView *text_view) |
8868 | { |
8869 | CtkTextViewPrivate *priv; |
8870 | CtkTextIter first_para; |
8871 | gint screen_height; |
8872 | gint y; |
8873 | gdouble old_value; |
8874 | gdouble new_value; |
8875 | gdouble new_upper; |
8876 | |
8877 | priv = text_view->priv; |
8878 | |
8879 | screen_height = SCREEN_HEIGHT (text_view)text_window_get_height (((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((text_view)), ((ctk_text_view_get_type () ))))))->priv->text_window); |
8880 | old_value = ctk_adjustment_get_value (priv->vadjustment); |
8881 | new_upper = MAX (screen_height, priv->height)(((screen_height) > (priv->height)) ? (screen_height) : (priv->height)); |
8882 | |
8883 | g_object_set (priv->vadjustment, |
8884 | "lower", 0.0, |
8885 | "upper", new_upper, |
8886 | "page-size", (gdouble)screen_height, |
8887 | "step-increment", screen_height * 0.1, |
8888 | "page-increment", screen_height * 0.9, |
8889 | NULL((void*)0)); |
8890 | |
8891 | /* Now adjust the value of the adjustment to keep the cursor at the |
8892 | * same place in the buffer */ |
8893 | ctk_text_view_ensure_layout (text_view); |
8894 | ctk_text_view_get_first_para_iter (text_view, &first_para); |
8895 | ctk_text_layout_get_line_yrange (priv->layout, &first_para, &y, NULL((void*)0)); |
8896 | |
8897 | y += priv->first_para_pixels; |
8898 | |
8899 | new_value = CLAMP (y, 0, new_upper - screen_height)(((y) > (new_upper - screen_height)) ? (new_upper - screen_height ) : (((y) < (0)) ? (0) : (y))); |
8900 | if (new_value != old_value) |
8901 | ctk_adjustment_set_value (priv->vadjustment, new_value); |
8902 | } |
8903 | |
8904 | static void |
8905 | adjust_allocation (CtkWidget *widget, |
8906 | int dx, |
8907 | int dy) |
8908 | { |
8909 | CtkAllocation allocation; |
8910 | |
8911 | if (!ctk_widget_is_drawable (widget)) |
8912 | return; |
8913 | |
8914 | ctk_widget_get_allocation (widget, &allocation); |
8915 | allocation.x += dx; |
8916 | allocation.y += dy; |
8917 | ctk_widget_size_allocate (widget, &allocation); |
8918 | } |
8919 | |
8920 | static void |
8921 | ctk_text_view_value_changed (CtkAdjustment *adjustment, |
8922 | CtkTextView *text_view) |
8923 | { |
8924 | CtkTextViewPrivate *priv; |
8925 | CtkTextIter iter; |
8926 | gint line_top; |
8927 | gint dx = 0; |
8928 | gint dy = 0; |
8929 | |
8930 | priv = text_view->priv; |
8931 | |
8932 | /* Note that we oddly call this function with adjustment == NULL |
8933 | * sometimes |
8934 | */ |
8935 | |
8936 | priv->onscreen_validated = FALSE(0); |
8937 | |
8938 | DV(g_print(">Scroll offset changed %s/%g, onscreen_validated = FALSE ("G_STRLOC")\n", |
8939 | adjustment == priv->hadjustment ? "hadjustment" : adjustment == priv->vadjustment ? "vadjustment" : "none", |
8940 | adjustment ? ctk_adjustment_get_value (adjustment) : 0.0)); |
8941 | |
8942 | if (adjustment == priv->hadjustment) |
8943 | { |
8944 | dx = priv->xoffset - (gint)ctk_adjustment_get_value (adjustment); |
8945 | priv->xoffset = (gint)ctk_adjustment_get_value (adjustment) - priv->left_padding; |
8946 | |
8947 | /* If the change is due to a size change we need |
8948 | * to invalidate the entire text window because there might be |
8949 | * right-aligned or centered text |
8950 | */ |
8951 | if (priv->width_changed) |
8952 | { |
8953 | if (ctk_widget_get_realized (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))))) |
8954 | cdk_window_invalidate_rect (priv->text_window->bin_window, NULL((void*)0), FALSE(0)); |
8955 | |
8956 | priv->width_changed = FALSE(0); |
8957 | } |
8958 | } |
8959 | else if (adjustment == priv->vadjustment) |
8960 | { |
8961 | dy = priv->yoffset - (gint)ctk_adjustment_get_value (adjustment) + priv->top_border ; |
8962 | priv->yoffset -= dy; |
8963 | |
8964 | if (priv->layout) |
8965 | { |
8966 | ctk_text_layout_get_line_at_y (priv->layout, &iter, ctk_adjustment_get_value (adjustment), &line_top); |
8967 | |
8968 | ctk_text_buffer_move_mark (get_buffer (text_view), priv->first_para_mark, &iter); |
8969 | |
8970 | priv->first_para_pixels = ctk_adjustment_get_value (adjustment) - line_top; |
8971 | } |
8972 | } |
8973 | |
8974 | if (dx != 0 || dy != 0) |
8975 | { |
8976 | GSList *tmp_list; |
8977 | |
8978 | if (ctk_widget_get_realized (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))))) |
8979 | { |
8980 | if (dy != 0) |
8981 | { |
8982 | if (priv->left_window) |
8983 | text_window_scroll (priv->left_window, 0, dy); |
8984 | if (priv->right_window) |
8985 | text_window_scroll (priv->right_window, 0, dy); |
8986 | } |
8987 | |
8988 | if (dx != 0) |
8989 | { |
8990 | if (priv->top_window) |
8991 | text_window_scroll (priv->top_window, dx, 0); |
8992 | if (priv->bottom_window) |
8993 | text_window_scroll (priv->bottom_window, dx, 0); |
8994 | } |
8995 | |
8996 | /* It looks nicer to scroll the main area last, because |
8997 | * it takes a while, and making the side areas update |
8998 | * afterward emphasizes the slowness of scrolling the |
8999 | * main area. |
9000 | */ |
9001 | text_window_scroll (priv->text_window, dx, dy); |
9002 | } |
9003 | |
9004 | /* Children are now "moved" in the text window, poke |
9005 | * into widget->allocation for each child |
9006 | */ |
9007 | tmp_list = priv->children; |
9008 | while (tmp_list != NULL((void*)0)) |
9009 | { |
9010 | CtkTextViewChild *child = tmp_list->data; |
9011 | gint child_dx = 0, child_dy = 0; |
9012 | |
9013 | if (child->anchor) |
9014 | { |
9015 | child_dx = dx; |
9016 | child_dy = dy; |
9017 | } |
9018 | else |
9019 | { |
9020 | if (child->type == CTK_TEXT_WINDOW_TEXT || |
9021 | child->type == CTK_TEXT_WINDOW_LEFT || |
9022 | child->type == CTK_TEXT_WINDOW_RIGHT) |
9023 | child_dy = dy; |
9024 | if (child->type == CTK_TEXT_WINDOW_TEXT || |
9025 | child->type == CTK_TEXT_WINDOW_TOP || |
9026 | child->type == CTK_TEXT_WINDOW_BOTTOM) |
9027 | child_dx = dx; |
9028 | } |
9029 | |
9030 | if (child_dx != 0 || child_dy != 0) |
9031 | adjust_allocation (child->widget, child_dx, child_dy); |
9032 | |
9033 | tmp_list = tmp_list->next; |
9034 | } |
9035 | } |
9036 | |
9037 | /* This could result in invalidation, which would install the |
9038 | * first_validate_idle, which would validate onscreen; |
9039 | * but we're going to go ahead and validate here, so |
9040 | * first_validate_idle shouldn't have anything to do. |
9041 | */ |
9042 | ctk_text_view_update_layout_width (text_view); |
9043 | |
9044 | /* We also update the IM spot location here, since the IM context |
9045 | * might do something that leads to validation. |
9046 | */ |
9047 | ctk_text_view_update_im_spot_location (text_view); |
9048 | |
9049 | /* note that validation of onscreen could invoke this function |
9050 | * recursively, by scrolling to maintain first_para, or in response |
9051 | * to updating the layout width, however there is no problem with |
9052 | * that, or shouldn't be. |
9053 | */ |
9054 | ctk_text_view_validate_onscreen (text_view); |
9055 | |
9056 | /* If this got installed, get rid of it, it's just a waste of time. */ |
9057 | if (priv->first_validate_idle != 0) |
9058 | { |
9059 | g_source_remove (priv->first_validate_idle); |
9060 | priv->first_validate_idle = 0; |
9061 | } |
9062 | |
9063 | /* Allow to extend selection with mouse scrollwheel. Bug 710612 */ |
9064 | if (ctk_gesture_is_active (priv->drag_gesture)) |
9065 | { |
9066 | CdkEvent *current_event; |
9067 | current_event = ctk_get_current_event (); |
9068 | if (current_event != NULL((void*)0)) |
9069 | { |
9070 | if (current_event->type == CDK_SCROLL) |
9071 | move_mark_to_pointer_and_scroll (text_view, "insert"); |
9072 | |
9073 | cdk_event_free (current_event); |
9074 | } |
9075 | } |
9076 | |
9077 | /* Finally we update the IM cursor location again, to ensure any |
9078 | * changes made by the validation are pushed through. |
9079 | */ |
9080 | ctk_text_view_update_im_spot_location (text_view); |
9081 | |
9082 | if (priv->text_handle) |
9083 | ctk_text_view_update_handles (text_view, |
9084 | _ctk_text_handle_get_mode (priv->text_handle)); |
9085 | |
9086 | DV(g_print(">End scroll offset changed handler ("G_STRLOC")\n")); |
9087 | } |
9088 | |
9089 | static void |
9090 | ctk_text_view_commit_handler (CtkIMContext *context G_GNUC_UNUSED__attribute__ ((__unused__)), |
9091 | const gchar *str, |
9092 | CtkTextView *text_view) |
9093 | { |
9094 | ctk_text_view_commit_text (text_view, str); |
9095 | } |
9096 | |
9097 | static void |
9098 | ctk_text_view_commit_text (CtkTextView *text_view, |
9099 | const gchar *str) |
9100 | { |
9101 | CtkTextViewPrivate *priv; |
9102 | gboolean had_selection; |
9103 | |
9104 | priv = text_view->priv; |
9105 | |
9106 | ctk_text_buffer_begin_user_action (get_buffer (text_view)); |
9107 | |
9108 | had_selection = ctk_text_buffer_get_selection_bounds (get_buffer (text_view), |
9109 | NULL((void*)0), NULL((void*)0)); |
9110 | |
9111 | ctk_text_buffer_delete_selection (get_buffer (text_view), TRUE(!(0)), |
9112 | priv->editable); |
9113 | |
9114 | if (!strcmp (str, "\n")) |
9115 | { |
9116 | if (!ctk_text_buffer_insert_interactive_at_cursor (get_buffer (text_view), "\n", 1, |
9117 | priv->editable)) |
9118 | { |
9119 | ctk_widget_error_bell (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
9120 | } |
9121 | } |
9122 | else |
9123 | { |
9124 | if (!had_selection && priv->overwrite_mode) |
9125 | { |
9126 | CtkTextIter insert; |
9127 | |
9128 | ctk_text_buffer_get_iter_at_mark (get_buffer (text_view), |
9129 | &insert, |
9130 | ctk_text_buffer_get_insert (get_buffer (text_view))); |
9131 | if (!ctk_text_iter_ends_line (&insert)) |
9132 | ctk_text_view_delete_from_cursor (text_view, CTK_DELETE_CHARS, 1); |
9133 | } |
9134 | |
9135 | if (!ctk_text_buffer_insert_interactive_at_cursor (get_buffer (text_view), str, -1, |
9136 | priv->editable)) |
9137 | { |
9138 | ctk_widget_error_bell (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
9139 | } |
9140 | } |
9141 | |
9142 | ctk_text_buffer_end_user_action (get_buffer (text_view)); |
9143 | |
9144 | ctk_text_view_set_virtual_cursor_pos (text_view, -1, -1); |
9145 | DV(g_print (G_STRLOC": scrolling onscreen\n")); |
9146 | ctk_text_view_scroll_mark_onscreen (text_view, |
9147 | ctk_text_buffer_get_insert (get_buffer (text_view))); |
9148 | } |
9149 | |
9150 | static void |
9151 | ctk_text_view_preedit_changed_handler (CtkIMContext *context, |
9152 | CtkTextView *text_view) |
9153 | { |
9154 | CtkTextViewPrivate *priv; |
9155 | gchar *str; |
9156 | PangoAttrList *attrs; |
9157 | gint cursor_pos; |
9158 | CtkTextIter iter; |
9159 | |
9160 | priv = text_view->priv; |
9161 | |
9162 | ctk_text_buffer_get_iter_at_mark (priv->buffer, &iter, |
9163 | ctk_text_buffer_get_insert (priv->buffer)); |
9164 | |
9165 | /* Keypress events are passed to input method even if cursor position is |
9166 | * not editable; so beep here if it's multi-key input sequence, input |
9167 | * method will be reset in key-press-event handler. |
9168 | */ |
9169 | ctk_im_context_get_preedit_string (context, &str, &attrs, &cursor_pos); |
9170 | |
9171 | if (str && str[0] && !ctk_text_iter_can_insert (&iter, priv->editable)) |
9172 | { |
9173 | ctk_widget_error_bell (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
9174 | goto out; |
9175 | } |
9176 | |
9177 | g_signal_emit (text_view, signals[PREEDIT_CHANGED], 0, str); |
9178 | |
9179 | if (priv->layout) |
9180 | ctk_text_layout_set_preedit_string (priv->layout, str, attrs, cursor_pos); |
9181 | if (ctk_widget_has_focus (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))))) |
9182 | ctk_text_view_scroll_mark_onscreen (text_view, |
9183 | ctk_text_buffer_get_insert (get_buffer (text_view))); |
9184 | |
9185 | out: |
9186 | pango_attr_list_unref (attrs); |
9187 | g_free (str); |
9188 | } |
9189 | |
9190 | static gboolean |
9191 | ctk_text_view_retrieve_surrounding_handler (CtkIMContext *context, |
9192 | CtkTextView *text_view) |
9193 | { |
9194 | CtkTextIter start; |
9195 | CtkTextIter end; |
9196 | gint pos; |
9197 | gchar *text; |
9198 | |
9199 | ctk_text_buffer_get_iter_at_mark (text_view->priv->buffer, &start, |
9200 | ctk_text_buffer_get_insert (text_view->priv->buffer)); |
9201 | end = start; |
9202 | |
9203 | pos = ctk_text_iter_get_line_index (&start); |
9204 | ctk_text_iter_set_line_offset (&start, 0); |
9205 | ctk_text_iter_forward_to_line_end (&end); |
9206 | |
9207 | text = ctk_text_iter_get_slice (&start, &end); |
9208 | ctk_im_context_set_surrounding (context, text, -1, pos); |
9209 | g_free (text); |
9210 | |
9211 | return TRUE(!(0)); |
9212 | } |
9213 | |
9214 | static gboolean |
9215 | ctk_text_view_delete_surrounding_handler (CtkIMContext *context G_GNUC_UNUSED__attribute__ ((__unused__)), |
9216 | gint offset, |
9217 | gint n_chars, |
9218 | CtkTextView *text_view) |
9219 | { |
9220 | CtkTextViewPrivate *priv; |
9221 | CtkTextIter start; |
9222 | CtkTextIter end; |
9223 | |
9224 | priv = text_view->priv; |
9225 | |
9226 | ctk_text_buffer_get_iter_at_mark (priv->buffer, &start, |
9227 | ctk_text_buffer_get_insert (priv->buffer)); |
9228 | end = start; |
9229 | |
9230 | ctk_text_iter_forward_chars (&start, offset); |
9231 | ctk_text_iter_forward_chars (&end, offset + n_chars); |
9232 | |
9233 | ctk_text_buffer_delete_interactive (priv->buffer, &start, &end, |
9234 | priv->editable); |
9235 | |
9236 | return TRUE(!(0)); |
9237 | } |
9238 | |
9239 | static void |
9240 | ctk_text_view_mark_set_handler (CtkTextBuffer *buffer, |
9241 | const CtkTextIter *location G_GNUC_UNUSED__attribute__ ((__unused__)), |
9242 | CtkTextMark *mark, |
9243 | gpointer data) |
9244 | { |
9245 | CtkTextView *text_view = CTK_TEXT_VIEW (data)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((data)), ((ctk_text_view_get_type ())))))); |
9246 | gboolean need_reset = FALSE(0); |
9247 | gboolean has_selection; |
9248 | |
9249 | if (mark == ctk_text_buffer_get_insert (buffer)) |
9250 | { |
9251 | text_view->priv->virtual_cursor_x = -1; |
9252 | text_view->priv->virtual_cursor_y = -1; |
9253 | ctk_text_view_update_im_spot_location (text_view); |
9254 | need_reset = TRUE(!(0)); |
9255 | } |
9256 | else if (mark == ctk_text_buffer_get_selection_bound (buffer)) |
9257 | { |
9258 | need_reset = TRUE(!(0)); |
9259 | } |
9260 | |
9261 | if (need_reset) |
9262 | { |
9263 | ctk_text_view_reset_im_context (text_view); |
9264 | if (text_view->priv->text_handle) |
9265 | ctk_text_view_update_handles (text_view, |
9266 | _ctk_text_handle_get_mode (text_view->priv->text_handle)); |
9267 | |
9268 | has_selection = ctk_text_buffer_get_selection_bounds (get_buffer (text_view), NULL((void*)0), NULL((void*)0)); |
9269 | ctk_css_node_set_visible (text_view->priv->selection_node, has_selection); |
9270 | } |
9271 | } |
9272 | |
9273 | static void |
9274 | ctk_text_view_target_list_notify (CtkTextBuffer *buffer, |
9275 | const GParamSpec *pspec G_GNUC_UNUSED__attribute__ ((__unused__)), |
9276 | gpointer data) |
9277 | { |
9278 | CtkWidget *widget = CTK_WIDGET (data)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((data)), ((ctk_widget_get_type ())))))); |
9279 | CtkTargetList *view_list; |
9280 | CtkTargetList *buffer_list; |
9281 | GList *list; |
9282 | |
9283 | view_list = ctk_drag_dest_get_target_list (widget); |
9284 | buffer_list = ctk_text_buffer_get_paste_target_list (buffer); |
9285 | |
9286 | if (view_list) |
9287 | ctk_target_list_ref (view_list); |
9288 | else |
9289 | view_list = ctk_target_list_new (NULL((void*)0), 0); |
9290 | |
9291 | list = view_list->list; |
9292 | while (list) |
9293 | { |
9294 | CtkTargetPair *pair = list->data; |
9295 | |
9296 | list = list->next; /* get next element before removing */ |
9297 | |
9298 | if (pair->info >= CTK_TEXT_BUFFER_TARGET_INFO_TEXT && |
9299 | pair->info <= CTK_TEXT_BUFFER_TARGET_INFO_BUFFER_CONTENTS) |
9300 | { |
9301 | ctk_target_list_remove (view_list, pair->target); |
9302 | } |
9303 | } |
9304 | |
9305 | for (list = buffer_list->list; list; list = list->next) |
9306 | { |
9307 | CtkTargetPair *pair = list->data; |
9308 | |
9309 | ctk_target_list_add (view_list, pair->target, pair->flags, pair->info); |
9310 | } |
9311 | |
9312 | ctk_drag_dest_set_target_list (widget, view_list); |
9313 | ctk_target_list_unref (view_list); |
9314 | } |
9315 | |
9316 | static void |
9317 | ctk_text_view_get_virtual_cursor_pos (CtkTextView *text_view, |
9318 | CtkTextIter *cursor, |
9319 | gint *x, |
9320 | gint *y) |
9321 | { |
9322 | CtkTextViewPrivate *priv; |
9323 | CtkTextIter insert; |
9324 | CdkRectangle pos; |
9325 | |
9326 | priv = text_view->priv; |
9327 | |
9328 | if (cursor) |
9329 | insert = *cursor; |
9330 | else |
9331 | ctk_text_buffer_get_iter_at_mark (get_buffer (text_view), &insert, |
9332 | ctk_text_buffer_get_insert (get_buffer (text_view))); |
9333 | |
9334 | if ((x && priv->virtual_cursor_x == -1) || |
9335 | (y && priv->virtual_cursor_y == -1)) |
9336 | ctk_text_layout_get_cursor_locations (priv->layout, &insert, &pos, NULL((void*)0)); |
9337 | |
9338 | if (x) |
9339 | { |
9340 | if (priv->virtual_cursor_x != -1) |
9341 | *x = priv->virtual_cursor_x; |
9342 | else |
9343 | *x = pos.x; |
9344 | } |
9345 | |
9346 | if (y) |
9347 | { |
9348 | if (priv->virtual_cursor_y != -1) |
9349 | *y = priv->virtual_cursor_y; |
9350 | else |
9351 | *y = pos.y + pos.height / 2; |
9352 | } |
9353 | } |
9354 | |
9355 | static void |
9356 | ctk_text_view_set_virtual_cursor_pos (CtkTextView *text_view, |
9357 | gint x, |
9358 | gint y) |
9359 | { |
9360 | CdkRectangle pos; |
9361 | |
9362 | if (!text_view->priv->layout) |
9363 | return; |
9364 | |
9365 | if (x == -1 || y == -1) |
9366 | ctk_text_view_get_cursor_locations (text_view, NULL((void*)0), &pos, NULL((void*)0)); |
9367 | |
9368 | text_view->priv->virtual_cursor_x = (x == -1) ? pos.x : x; |
9369 | text_view->priv->virtual_cursor_y = (y == -1) ? pos.y + pos.height / 2 : y; |
9370 | } |
9371 | |
9372 | /* Quick hack of a popup menu |
9373 | */ |
9374 | static void |
9375 | activate_cb (CtkWidget *menuitem, |
9376 | CtkTextView *text_view) |
9377 | { |
9378 | const gchar *signal; |
9379 | |
9380 | signal = g_object_get_qdata (G_OBJECT (menuitem)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((menuitem)), (((GType) ((20) << (2)))))))), quark_ctk_signal); |
9381 | g_signal_emit_by_name (text_view, signal); |
9382 | } |
9383 | |
9384 | static void |
9385 | append_action_signal (CtkTextView *text_view, |
9386 | CtkWidget *menu, |
9387 | const gchar *label, |
9388 | const gchar *signal, |
9389 | gboolean sensitive) |
9390 | { |
9391 | CtkWidget *menuitem = ctk_menu_item_new_with_mnemonic (label); |
9392 | |
9393 | g_object_set_qdata (G_OBJECT (menuitem)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((menuitem)), (((GType) ((20) << (2)))))))), quark_ctk_signal, (char *)signal); |
9394 | g_signal_connect (menuitem, "activate",g_signal_connect_data ((menuitem), ("activate"), (((GCallback ) (activate_cb))), (text_view), ((void*)0), (GConnectFlags) 0 ) |
9395 | G_CALLBACK (activate_cb), text_view)g_signal_connect_data ((menuitem), ("activate"), (((GCallback ) (activate_cb))), (text_view), ((void*)0), (GConnectFlags) 0 ); |
9396 | |
9397 | ctk_widget_set_sensitive (menuitem, sensitive); |
9398 | |
9399 | ctk_widget_show (menuitem); |
9400 | ctk_menu_shell_append (CTK_MENU_SHELL (menu)((((CtkMenuShell*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((menu)), ((ctk_menu_shell_get_type ())))))), menuitem); |
9401 | } |
9402 | |
9403 | static void |
9404 | ctk_text_view_select_all (CtkWidget *widget, |
9405 | gboolean select) |
9406 | { |
9407 | CtkTextView *text_view = CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ())))))); |
9408 | CtkTextBuffer *buffer; |
9409 | CtkTextIter start_iter, end_iter, insert; |
9410 | |
9411 | buffer = text_view->priv->buffer; |
9412 | if (select) |
9413 | { |
9414 | ctk_text_buffer_get_bounds (buffer, &start_iter, &end_iter); |
9415 | ctk_text_buffer_select_range (buffer, &start_iter, &end_iter); |
9416 | } |
9417 | else |
9418 | { |
9419 | ctk_text_buffer_get_iter_at_mark (buffer, &insert, |
9420 | ctk_text_buffer_get_insert (buffer)); |
9421 | ctk_text_buffer_move_mark_by_name (buffer, "selection_bound", &insert); |
9422 | } |
9423 | } |
9424 | |
9425 | static void |
9426 | select_all_cb (CtkWidget *menuitem G_GNUC_UNUSED__attribute__ ((__unused__)), |
9427 | CtkTextView *text_view) |
9428 | { |
9429 | ctk_text_view_select_all (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))), TRUE(!(0))); |
9430 | } |
9431 | |
9432 | static void |
9433 | delete_cb (CtkTextView *text_view) |
9434 | { |
9435 | ctk_text_buffer_delete_selection (get_buffer (text_view), TRUE(!(0)), |
9436 | text_view->priv->editable); |
9437 | } |
9438 | |
9439 | static void |
9440 | popup_menu_detach (CtkWidget *attach_widget, |
9441 | CtkMenu *menu G_GNUC_UNUSED__attribute__ ((__unused__))) |
9442 | { |
9443 | CTK_TEXT_VIEW (attach_widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((attach_widget)), ((ctk_text_view_get_type ()))))))->priv->popup_menu = NULL((void*)0); |
9444 | } |
9445 | |
9446 | typedef struct |
9447 | { |
9448 | CtkTextView *text_view; |
9449 | CdkEvent *trigger_event; |
9450 | } PopupInfo; |
9451 | |
9452 | static gboolean |
9453 | range_contains_editable_text (const CtkTextIter *start, |
9454 | const CtkTextIter *end, |
9455 | gboolean default_editability) |
9456 | { |
9457 | CtkTextIter iter = *start; |
9458 | |
9459 | while (ctk_text_iter_compare (&iter, end) < 0) |
9460 | { |
9461 | if (ctk_text_iter_editable (&iter, default_editability)) |
9462 | return TRUE(!(0)); |
9463 | |
9464 | ctk_text_iter_forward_to_tag_toggle (&iter, NULL((void*)0)); |
9465 | } |
9466 | |
9467 | return FALSE(0); |
9468 | } |
9469 | |
9470 | static void |
9471 | popup_targets_received (CtkClipboard *clipboard G_GNUC_UNUSED__attribute__ ((__unused__)), |
9472 | CtkSelectionData *data, |
9473 | gpointer user_data) |
9474 | { |
9475 | PopupInfo *info = user_data; |
9476 | CtkTextView *text_view; |
9477 | CtkTextViewPrivate *priv; |
9478 | |
9479 | text_view = info->text_view; |
9480 | priv = text_view->priv; |
9481 | |
9482 | if (ctk_widget_get_realized (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))))) |
9483 | { |
9484 | /* We implicitely rely here on the fact that if we are pasting ourself, we'll |
9485 | * have text targets as well as the private CTK_TEXT_BUFFER_CONTENTS target. |
9486 | */ |
9487 | gboolean clipboard_contains_text; |
9488 | CtkWidget *menuitem; |
9489 | gboolean have_selection; |
9490 | gboolean can_insert; |
9491 | CtkTextIter iter; |
9492 | CtkTextIter sel_start, sel_end; |
9493 | CdkRectangle iter_location; |
9494 | CdkRectangle visible_rect; |
9495 | gboolean is_visible; |
9496 | |
9497 | clipboard_contains_text = ctk_selection_data_targets_include_text (data); |
9498 | |
9499 | if (priv->popup_menu) |
9500 | ctk_widget_destroy (priv->popup_menu); |
9501 | |
9502 | priv->popup_menu = ctk_menu_new (); |
9503 | ctk_style_context_add_class (ctk_widget_get_style_context (priv->popup_menu), |
9504 | CTK_STYLE_CLASS_CONTEXT_MENU"context-menu"); |
9505 | |
9506 | ctk_menu_attach_to_widget (CTK_MENU (priv->popup_menu)((((CtkMenu*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((priv->popup_menu)), ((ctk_menu_get_type ())))))), |
9507 | CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))), |
9508 | popup_menu_detach); |
9509 | |
9510 | have_selection = ctk_text_buffer_get_selection_bounds (get_buffer (text_view), |
9511 | &sel_start, &sel_end); |
9512 | |
9513 | ctk_text_buffer_get_iter_at_mark (get_buffer (text_view), |
9514 | &iter, |
9515 | ctk_text_buffer_get_insert (get_buffer (text_view))); |
9516 | |
9517 | can_insert = ctk_text_iter_can_insert (&iter, priv->editable); |
9518 | |
9519 | append_action_signal (text_view, priv->popup_menu, _("Cu_t")((char *) g_dgettext ("ctk30", "Cu_t")), "cut-clipboard", |
9520 | have_selection && |
9521 | range_contains_editable_text (&sel_start, &sel_end, |
9522 | priv->editable)); |
9523 | append_action_signal (text_view, priv->popup_menu, _("_Copy")((char *) g_dgettext ("ctk30", "_Copy")), "copy-clipboard", |
9524 | have_selection); |
9525 | append_action_signal (text_view, priv->popup_menu, _("_Paste")((char *) g_dgettext ("ctk30", "_Paste")), "paste-clipboard", |
9526 | can_insert && clipboard_contains_text); |
9527 | |
9528 | menuitem = ctk_menu_item_new_with_mnemonic (_("_Delete")((char *) g_dgettext ("ctk30", "_Delete"))); |
9529 | ctk_widget_set_sensitive (menuitem, |
9530 | have_selection && |
9531 | range_contains_editable_text (&sel_start, &sel_end, |
9532 | priv->editable)); |
9533 | g_signal_connect_swapped (menuitem, "activate",g_signal_connect_data ((menuitem), ("activate"), (((GCallback ) (delete_cb))), (text_view), ((void*)0), G_CONNECT_SWAPPED) |
9534 | G_CALLBACK (delete_cb), text_view)g_signal_connect_data ((menuitem), ("activate"), (((GCallback ) (delete_cb))), (text_view), ((void*)0), G_CONNECT_SWAPPED); |
9535 | ctk_widget_show (menuitem); |
9536 | ctk_menu_shell_append (CTK_MENU_SHELL (priv->popup_menu)((((CtkMenuShell*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((priv->popup_menu)), ((ctk_menu_shell_get_type ()))))) ), menuitem); |
9537 | |
9538 | menuitem = ctk_separator_menu_item_new (); |
9539 | ctk_widget_show (menuitem); |
9540 | ctk_menu_shell_append (CTK_MENU_SHELL (priv->popup_menu)((((CtkMenuShell*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((priv->popup_menu)), ((ctk_menu_shell_get_type ()))))) ), menuitem); |
9541 | |
9542 | menuitem = ctk_menu_item_new_with_mnemonic (_("Select _All")((char *) g_dgettext ("ctk30", "Select _All"))); |
9543 | ctk_widget_set_sensitive (menuitem, |
9544 | ctk_text_buffer_get_char_count (priv->buffer) > 0); |
9545 | g_signal_connect (menuitem, "activate",g_signal_connect_data ((menuitem), ("activate"), (((GCallback ) (select_all_cb))), (text_view), ((void*)0), (GConnectFlags) 0) |
9546 | G_CALLBACK (select_all_cb), text_view)g_signal_connect_data ((menuitem), ("activate"), (((GCallback ) (select_all_cb))), (text_view), ((void*)0), (GConnectFlags) 0); |
9547 | ctk_widget_show (menuitem); |
9548 | ctk_menu_shell_append (CTK_MENU_SHELL (priv->popup_menu)((((CtkMenuShell*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((priv->popup_menu)), ((ctk_menu_shell_get_type ()))))) ), menuitem); |
9549 | |
9550 | if ((ctk_text_view_get_input_hints (text_view) & CTK_INPUT_HINT_NO_EMOJI) == 0) |
9551 | { |
9552 | menuitem = ctk_menu_item_new_with_mnemonic (_("Insert _Emoji")((char *) g_dgettext ("ctk30", "Insert _Emoji"))); |
9553 | ctk_widget_set_sensitive (menuitem, can_insert); |
9554 | g_signal_connect_swapped (menuitem, "activate",g_signal_connect_data ((menuitem), ("activate"), (((GCallback ) (ctk_text_view_insert_emoji))), (text_view), ((void*)0), G_CONNECT_SWAPPED ) |
9555 | G_CALLBACK (ctk_text_view_insert_emoji), text_view)g_signal_connect_data ((menuitem), ("activate"), (((GCallback ) (ctk_text_view_insert_emoji))), (text_view), ((void*)0), G_CONNECT_SWAPPED ); |
9556 | ctk_widget_show (menuitem); |
9557 | ctk_menu_shell_append (CTK_MENU_SHELL (priv->popup_menu)((((CtkMenuShell*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((priv->popup_menu)), ((ctk_menu_shell_get_type ()))))) ), menuitem); |
9558 | } |
9559 | |
9560 | g_signal_emit (text_view, signals[POPULATE_POPUP], |
9561 | 0, priv->popup_menu); |
9562 | |
9563 | if (info->trigger_event && cdk_event_triggers_context_menu (info->trigger_event)) |
9564 | ctk_menu_popup_at_pointer (CTK_MENU (priv->popup_menu)((((CtkMenu*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((priv->popup_menu)), ((ctk_menu_get_type ())))))), info->trigger_event); |
9565 | else |
9566 | { |
9567 | ctk_text_view_get_iter_location (text_view, &iter, &iter_location); |
9568 | ctk_text_view_get_visible_rect (text_view, &visible_rect); |
9569 | |
9570 | is_visible = (iter_location.x + iter_location.width > visible_rect.x && |
9571 | iter_location.x < visible_rect.x + visible_rect.width && |
9572 | iter_location.y + iter_location.height > visible_rect.y && |
9573 | iter_location.y < visible_rect.y + visible_rect.height); |
9574 | |
9575 | if (is_visible) |
9576 | { |
9577 | ctk_text_view_buffer_to_window_coords (text_view, |
9578 | CTK_TEXT_WINDOW_WIDGET, |
9579 | iter_location.x, |
9580 | iter_location.y, |
9581 | &iter_location.x, |
9582 | &iter_location.y); |
9583 | |
9584 | ctk_menu_popup_at_rect (CTK_MENU (priv->popup_menu)((((CtkMenu*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((priv->popup_menu)), ((ctk_menu_get_type ())))))), |
9585 | ctk_widget_get_window (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))), |
9586 | &iter_location, |
9587 | CDK_GRAVITY_SOUTH_EAST, |
9588 | CDK_GRAVITY_NORTH_WEST, |
9589 | info->trigger_event); |
9590 | } |
9591 | else |
9592 | ctk_menu_popup_at_widget (CTK_MENU (priv->popup_menu)((((CtkMenu*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((priv->popup_menu)), ((ctk_menu_get_type ())))))), |
9593 | CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))), |
9594 | CDK_GRAVITY_CENTER, |
9595 | CDK_GRAVITY_CENTER, |
9596 | info->trigger_event); |
9597 | |
9598 | ctk_menu_shell_select_first (CTK_MENU_SHELL (priv->popup_menu)((((CtkMenuShell*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((priv->popup_menu)), ((ctk_menu_shell_get_type ()))))) ), FALSE(0)); |
9599 | } |
9600 | } |
9601 | |
9602 | g_clear_pointer (&info->trigger_event, cdk_event_free)do { _Static_assert (sizeof *(&info->trigger_event) == sizeof (gpointer), "Expression evaluates to false"); __typeof__ ((&info->trigger_event)) _pp = (&info->trigger_event ); __typeof__ (*(&info->trigger_event)) _ptr = *_pp; * _pp = ((void*)0); if (_ptr) (cdk_event_free) (_ptr); } while ( 0); |
9603 | g_object_unref (text_view); |
9604 | g_slice_free (PopupInfo, info)do { if (1) g_slice_free1 (sizeof (PopupInfo), (info)); else ( void) ((PopupInfo*) 0 == (info)); } while (0); |
9605 | } |
9606 | |
9607 | static void |
9608 | ctk_text_view_do_popup (CtkTextView *text_view, |
9609 | const CdkEvent *event) |
9610 | { |
9611 | PopupInfo *info = g_slice_new (PopupInfo)((PopupInfo*) g_slice_alloc (sizeof (PopupInfo))); |
9612 | |
9613 | /* In order to know what entries we should make sensitive, we |
9614 | * ask for the current targets of the clipboard, and when |
9615 | * we get them, then we actually pop up the menu. |
9616 | */ |
9617 | info->text_view = g_object_ref (text_view)((__typeof__ (text_view)) (g_object_ref) (text_view)); |
9618 | info->trigger_event = event ? cdk_event_copy (event) : ctk_get_current_event (); |
9619 | |
9620 | ctk_clipboard_request_contents (ctk_widget_get_clipboard (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))), |
9621 | CDK_SELECTION_CLIPBOARD((CdkAtom)((gpointer) (gulong) (69)))), |
9622 | cdk_atom_intern_static_string ("TARGETS"), |
9623 | popup_targets_received, |
9624 | info); |
9625 | } |
9626 | |
9627 | static gboolean |
9628 | ctk_text_view_popup_menu (CtkWidget *widget) |
9629 | { |
9630 | ctk_text_view_do_popup (CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ())))))), NULL((void*)0)); |
9631 | return TRUE(!(0)); |
9632 | } |
9633 | |
9634 | static void |
9635 | ctk_text_view_get_selection_rect (CtkTextView *text_view, |
9636 | cairo_rectangle_int_t *rect) |
9637 | { |
9638 | cairo_rectangle_int_t rect_cursor, rect_bound; |
9639 | CtkTextIter cursor, bound; |
9640 | CtkTextBuffer *buffer; |
9641 | gint x1, y1, x2, y2; |
9642 | |
9643 | buffer = get_buffer (text_view); |
9644 | ctk_text_buffer_get_iter_at_mark (buffer, &cursor, |
9645 | ctk_text_buffer_get_insert (buffer)); |
9646 | ctk_text_buffer_get_iter_at_mark (buffer, &bound, |
9647 | ctk_text_buffer_get_selection_bound (buffer)); |
9648 | |
9649 | ctk_text_view_get_cursor_locations (text_view, &cursor, &rect_cursor, NULL((void*)0)); |
9650 | ctk_text_view_get_cursor_locations (text_view, &bound, &rect_bound, NULL((void*)0)); |
9651 | |
9652 | x1 = MIN (rect_cursor.x, rect_bound.x)(((rect_cursor.x) < (rect_bound.x)) ? (rect_cursor.x) : (rect_bound .x)); |
9653 | x2 = MAX (rect_cursor.x, rect_bound.x)(((rect_cursor.x) > (rect_bound.x)) ? (rect_cursor.x) : (rect_bound .x)); |
9654 | y1 = MIN (rect_cursor.y, rect_bound.y)(((rect_cursor.y) < (rect_bound.y)) ? (rect_cursor.y) : (rect_bound .y)); |
9655 | y2 = MAX (rect_cursor.y + rect_cursor.height, rect_bound.y + rect_bound.height)(((rect_cursor.y + rect_cursor.height) > (rect_bound.y + rect_bound .height)) ? (rect_cursor.y + rect_cursor.height) : (rect_bound .y + rect_bound.height)); |
9656 | |
9657 | rect->x = x1; |
9658 | rect->y = y1; |
9659 | rect->width = x2 - x1; |
9660 | rect->height = y2 - y1; |
9661 | } |
9662 | |
9663 | static void |
9664 | show_or_hide_handles (CtkWidget *popover, |
9665 | GParamSpec *pspec G_GNUC_UNUSED__attribute__ ((__unused__)), |
9666 | CtkTextView *text_view) |
9667 | { |
9668 | gboolean visible; |
9669 | CtkTextHandle *handle; |
9670 | CtkTextHandleMode mode; |
9671 | |
9672 | visible = ctk_widget_get_visible (popover); |
9673 | |
9674 | handle = text_view->priv->text_handle; |
9675 | mode = _ctk_text_handle_get_mode (handle); |
9676 | |
9677 | if (!visible) |
9678 | ctk_text_view_update_handles (text_view, mode); |
9679 | else |
9680 | { |
9681 | _ctk_text_handle_set_visible (handle, CTK_TEXT_HANDLE_POSITION_SELECTION_START, FALSE(0)); |
9682 | _ctk_text_handle_set_visible (handle, CTK_TEXT_HANDLE_POSITION_SELECTION_END, FALSE(0)); |
9683 | } |
9684 | } |
9685 | |
9686 | static void |
9687 | activate_bubble_cb (CtkWidget *item, |
9688 | CtkTextView *text_view) |
9689 | { |
9690 | const gchar *signal; |
9691 | |
9692 | signal = g_object_get_qdata (G_OBJECT (item)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((item)), (((GType) ((20) << (2)))))))), quark_ctk_signal); |
9693 | ctk_widget_hide (text_view->priv->selection_bubble); |
9694 | |
9695 | if (strcmp (signal, "select-all") == 0) |
9696 | g_signal_emit_by_name (text_view, "select-all", TRUE(!(0))); |
9697 | else |
9698 | g_signal_emit_by_name (text_view, signal); |
9699 | } |
9700 | |
9701 | static void |
9702 | append_bubble_action (CtkTextView *text_view, |
9703 | CtkWidget *toolbar, |
9704 | const gchar *label, |
9705 | const gchar *icon_name, |
9706 | const gchar *signal, |
9707 | gboolean sensitive) |
9708 | { |
9709 | CtkWidget *item; |
9710 | |
9711 | item = ctk_button_new_from_icon_name (icon_name, CTK_ICON_SIZE_MENU); |
9712 | ctk_widget_set_focus_on_click (item, FALSE(0)); |
9713 | ctk_widget_set_tooltip_text (item, label); |
9714 | g_object_set_qdata (G_OBJECT (item)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((item)), (((GType) ((20) << (2)))))))), quark_ctk_signal, (char *)signal); |
9715 | g_signal_connect (item, "clicked", G_CALLBACK (activate_bubble_cb), text_view)g_signal_connect_data ((item), ("clicked"), (((GCallback) (activate_bubble_cb ))), (text_view), ((void*)0), (GConnectFlags) 0); |
9716 | ctk_widget_set_sensitive (CTK_WIDGET (item)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((item)), ((ctk_widget_get_type ())))))), sensitive); |
9717 | ctk_widget_show (item); |
9718 | ctk_container_add (CTK_CONTAINER (toolbar)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((toolbar)), ((ctk_container_get_type ())))))), item); |
9719 | } |
9720 | |
9721 | static void |
9722 | bubble_targets_received (CtkClipboard *clipboard G_GNUC_UNUSED__attribute__ ((__unused__)), |
9723 | CtkSelectionData *data, |
9724 | gpointer user_data) |
9725 | { |
9726 | CtkTextView *text_view = user_data; |
9727 | CtkTextViewPrivate *priv = text_view->priv; |
9728 | cairo_rectangle_int_t rect; |
9729 | gboolean has_selection; |
9730 | gboolean has_clipboard; |
9731 | gboolean can_insert; |
9732 | gboolean all_selected; |
9733 | CtkTextIter iter; |
9734 | CtkTextIter sel_start, sel_end; |
9735 | CtkTextIter start, end; |
9736 | CtkWidget *box; |
9737 | CtkWidget *toolbar; |
9738 | |
9739 | has_selection = ctk_text_buffer_get_selection_bounds (get_buffer (text_view), |
9740 | &sel_start, &sel_end); |
9741 | ctk_text_buffer_get_bounds (get_buffer (text_view), &start, &end); |
9742 | |
9743 | all_selected = ctk_text_iter_equal (&start, &sel_start) && |
9744 | ctk_text_iter_equal (&end, &sel_end); |
9745 | |
9746 | if (!priv->editable && !has_selection) |
9747 | { |
9748 | priv->selection_bubble_timeout_id = 0; |
9749 | return; |
9750 | } |
9751 | |
9752 | if (priv->selection_bubble) |
9753 | ctk_widget_destroy (priv->selection_bubble); |
9754 | |
9755 | priv->selection_bubble = ctk_popover_new (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
9756 | ctk_style_context_add_class (ctk_widget_get_style_context (priv->selection_bubble), |
9757 | CTK_STYLE_CLASS_TOUCH_SELECTION"touch-selection"); |
9758 | ctk_popover_set_position (CTK_POPOVER (priv->selection_bubble)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((priv->selection_bubble)), ((ctk_popover_get_type ())) )))), CTK_POS_BOTTOM); |
9759 | ctk_popover_set_modal (CTK_POPOVER (priv->selection_bubble)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((priv->selection_bubble)), ((ctk_popover_get_type ())) )))), FALSE(0)); |
9760 | g_signal_connect (priv->selection_bubble, "notify::visible",g_signal_connect_data ((priv->selection_bubble), ("notify::visible" ), (((GCallback) (show_or_hide_handles))), (text_view), ((void *)0), (GConnectFlags) 0) |
9761 | G_CALLBACK (show_or_hide_handles), text_view)g_signal_connect_data ((priv->selection_bubble), ("notify::visible" ), (((GCallback) (show_or_hide_handles))), (text_view), ((void *)0), (GConnectFlags) 0); |
9762 | |
9763 | box = ctk_box_new (CTK_ORIENTATION_VERTICAL, 5); |
9764 | g_object_set (box, "margin", 10, NULL((void*)0)); |
9765 | ctk_widget_show (box); |
9766 | toolbar = ctk_box_new (CTK_ORIENTATION_HORIZONTAL, 5); |
9767 | ctk_widget_show (toolbar); |
9768 | ctk_container_add (CTK_CONTAINER (priv->selection_bubble)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((priv->selection_bubble)), ((ctk_container_get_type () )))))), box); |
9769 | ctk_container_add (CTK_CONTAINER (box)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((box)), ((ctk_container_get_type ())))))), toolbar); |
9770 | |
9771 | ctk_text_buffer_get_iter_at_mark (get_buffer (text_view), &iter, |
9772 | ctk_text_buffer_get_insert (get_buffer (text_view))); |
9773 | can_insert = ctk_text_iter_can_insert (&iter, priv->editable); |
9774 | has_clipboard = ctk_selection_data_targets_include_text (data); |
9775 | |
9776 | append_bubble_action (text_view, toolbar, _("Select all")((char *) g_dgettext ("ctk30", "Select all")), "edit-select-all-symbolic", "select-all", !all_selected); |
9777 | |
9778 | if (range_contains_editable_text (&sel_start, &sel_end, priv->editable) && has_selection) |
9779 | append_bubble_action (text_view, toolbar, _("Cut")((char *) g_dgettext ("ctk30", "Cut")), "edit-cut-symbolic", "cut-clipboard", TRUE(!(0))); |
9780 | |
9781 | if (has_selection) |
9782 | append_bubble_action (text_view, toolbar, _("Copy")((char *) g_dgettext ("ctk30", "Copy")), "edit-copy-symbolic", "copy-clipboard", TRUE(!(0))); |
9783 | |
9784 | if (can_insert) |
9785 | append_bubble_action (text_view, toolbar, _("Paste")((char *) g_dgettext ("ctk30", "Paste")), "edit-paste-symbolic", "paste-clipboard", has_clipboard); |
9786 | |
9787 | if (priv->populate_all) |
9788 | g_signal_emit (text_view, signals[POPULATE_POPUP], 0, box); |
9789 | |
9790 | ctk_text_view_get_selection_rect (text_view, &rect); |
9791 | rect.x -= priv->xoffset; |
9792 | rect.y -= priv->yoffset; |
9793 | |
9794 | _text_window_to_widget_coords (text_view, &rect.x, &rect.y); |
9795 | |
9796 | rect.x -= 5; |
9797 | rect.y -= 5; |
9798 | rect.width += 10; |
9799 | rect.height += 10; |
9800 | |
9801 | ctk_popover_set_pointing_to (CTK_POPOVER (priv->selection_bubble)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((priv->selection_bubble)), ((ctk_popover_get_type ())) )))), &rect); |
9802 | ctk_widget_show (priv->selection_bubble); |
9803 | } |
9804 | |
9805 | static gboolean |
9806 | ctk_text_view_selection_bubble_popup_show (gpointer user_data) |
9807 | { |
9808 | CtkTextView *text_view = user_data; |
9809 | ctk_clipboard_request_contents (ctk_widget_get_clipboard (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))), |
9810 | CDK_SELECTION_CLIPBOARD((CdkAtom)((gpointer) (gulong) (69)))), |
9811 | cdk_atom_intern_static_string ("TARGETS"), |
9812 | bubble_targets_received, |
9813 | text_view); |
9814 | text_view->priv->selection_bubble_timeout_id = 0; |
9815 | |
9816 | return G_SOURCE_REMOVE(0); |
9817 | } |
9818 | |
9819 | static void |
9820 | ctk_text_view_selection_bubble_popup_unset (CtkTextView *text_view) |
9821 | { |
9822 | CtkTextViewPrivate *priv; |
9823 | |
9824 | priv = text_view->priv; |
9825 | |
9826 | if (priv->selection_bubble) |
9827 | ctk_widget_hide (priv->selection_bubble); |
9828 | |
9829 | if (priv->selection_bubble_timeout_id) |
9830 | { |
9831 | g_source_remove (priv->selection_bubble_timeout_id); |
9832 | priv->selection_bubble_timeout_id = 0; |
9833 | } |
9834 | } |
9835 | |
9836 | static void |
9837 | ctk_text_view_selection_bubble_popup_set (CtkTextView *text_view) |
9838 | { |
9839 | CtkTextViewPrivate *priv; |
9840 | |
9841 | priv = text_view->priv; |
9842 | |
9843 | if (priv->selection_bubble_timeout_id) |
9844 | g_source_remove (priv->selection_bubble_timeout_id); |
9845 | |
9846 | priv->selection_bubble_timeout_id = |
9847 | cdk_threads_add_timeout (50, ctk_text_view_selection_bubble_popup_show, |
9848 | text_view); |
9849 | g_source_set_name_by_id (priv->selection_bubble_timeout_id, "[ctk+] ctk_text_view_selection_bubble_popup_cb"); |
9850 | } |
9851 | |
9852 | /* Child CdkWindows */ |
9853 | |
9854 | static void |
9855 | node_style_changed_cb (CtkCssNode *node, |
9856 | CtkCssStyleChange *change, |
9857 | CtkWidget *widget) |
9858 | { |
9859 | CtkTextViewPrivate *priv = CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ()))))))->priv; |
9860 | |
9861 | if (ctk_css_style_change_affects (change, CTK_CSS_AFFECTS_SIZE | CTK_CSS_AFFECTS_CLIP)) |
9862 | ctk_widget_queue_resize (widget); |
9863 | else |
9864 | ctk_widget_queue_draw (widget); |
9865 | |
9866 | if (node == priv->text_window->css_node) |
9867 | { |
9868 | CtkCssStyle *style = ctk_css_style_change_get_new_style (change); |
9869 | ctk_pixel_cache_set_is_opaque (priv->pixel_cache, ctk_css_style_render_background_is_opaque (style)); |
9870 | } |
9871 | } |
9872 | |
9873 | static void |
9874 | update_node_ordering (CtkWidget *widget) |
9875 | { |
9876 | CtkTextViewPrivate *priv = CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ()))))))->priv; |
9877 | CtkCssNode *widget_node, *sibling; |
9878 | |
9879 | if (priv->text_window == NULL((void*)0)) |
9880 | return; |
9881 | |
9882 | widget_node = ctk_widget_get_css_node (widget); |
9883 | sibling = priv->text_window->css_node; |
9884 | |
9885 | if (priv->left_window) |
9886 | { |
9887 | ctk_css_node_insert_before (widget_node, priv->left_window->css_node, sibling); |
9888 | sibling = priv->left_window->css_node; |
9889 | } |
9890 | if (priv->top_window) |
9891 | { |
9892 | ctk_css_node_insert_before (widget_node, priv->top_window->css_node, sibling); |
9893 | } |
9894 | |
9895 | sibling = priv->text_window->css_node; |
9896 | if (priv->right_window) |
9897 | { |
9898 | ctk_css_node_insert_after (widget_node, priv->right_window->css_node, sibling); |
9899 | sibling = priv->right_window->css_node; |
9900 | } |
9901 | if (priv->bottom_window) |
9902 | { |
9903 | ctk_css_node_insert_after (widget_node, priv->bottom_window->css_node, sibling); |
9904 | } |
9905 | } |
9906 | |
9907 | static CtkTextWindow* |
9908 | text_window_new (CtkTextWindowType type, |
9909 | CtkWidget *widget, |
9910 | gint width_request, |
9911 | gint height_request) |
9912 | { |
9913 | CtkTextWindow *win; |
9914 | CtkCssNode *widget_node; |
9915 | |
9916 | win = g_slice_new (CtkTextWindow)((CtkTextWindow*) g_slice_alloc (sizeof (CtkTextWindow))); |
9917 | |
9918 | win->type = type; |
9919 | win->widget = widget; |
9920 | win->window = NULL((void*)0); |
9921 | win->bin_window = NULL((void*)0); |
9922 | win->requisition.width = width_request; |
9923 | win->requisition.height = height_request; |
9924 | win->allocation.width = width_request; |
9925 | win->allocation.height = height_request; |
9926 | win->allocation.x = 0; |
9927 | win->allocation.y = 0; |
9928 | |
9929 | widget_node = ctk_widget_get_css_node (widget); |
9930 | win->css_node = ctk_css_node_new (); |
9931 | ctk_css_node_set_parent (win->css_node, widget_node); |
9932 | ctk_css_node_set_state (win->css_node, ctk_css_node_get_state (widget_node)); |
9933 | g_signal_connect_object (win->css_node, "style-changed", G_CALLBACK (node_style_changed_cb)((GCallback) (node_style_changed_cb)), widget, 0); |
9934 | if (type == CTK_TEXT_WINDOW_TEXT) |
9935 | { |
9936 | ctk_css_node_set_name (win->css_node, I_("text")g_intern_static_string ("text")); |
9937 | } |
9938 | else |
9939 | { |
9940 | ctk_css_node_set_name (win->css_node, I_("border")g_intern_static_string ("border")); |
9941 | switch (type) |
9942 | { |
9943 | case CTK_TEXT_WINDOW_LEFT: |
9944 | ctk_css_node_add_class (win->css_node, g_quark_from_static_string (CTK_STYLE_CLASS_LEFT"left")); |
9945 | break; |
9946 | case CTK_TEXT_WINDOW_RIGHT: |
9947 | ctk_css_node_add_class (win->css_node, g_quark_from_static_string (CTK_STYLE_CLASS_RIGHT"right")); |
9948 | break; |
9949 | case CTK_TEXT_WINDOW_TOP: |
9950 | ctk_css_node_add_class (win->css_node, g_quark_from_static_string (CTK_STYLE_CLASS_TOP"top")); |
9951 | break; |
9952 | case CTK_TEXT_WINDOW_BOTTOM: |
9953 | ctk_css_node_add_class (win->css_node, g_quark_from_static_string (CTK_STYLE_CLASS_BOTTOM"bottom")); |
9954 | break; |
9955 | default: /* no extra style class */ ; |
9956 | } |
9957 | } |
9958 | g_object_unref (win->css_node); |
9959 | |
9960 | return win; |
9961 | } |
9962 | |
9963 | static void |
9964 | text_window_free (CtkTextWindow *win) |
9965 | { |
9966 | if (win->window) |
9967 | text_window_unrealize (win); |
9968 | |
9969 | ctk_css_node_set_parent (win->css_node, NULL((void*)0)); |
9970 | |
9971 | g_slice_free (CtkTextWindow, win)do { if (1) g_slice_free1 (sizeof (CtkTextWindow), (win)); else (void) ((CtkTextWindow*) 0 == (win)); } while (0); |
9972 | } |
9973 | |
9974 | static void |
9975 | ctk_text_view_get_rendered_rect (CtkTextView *text_view, |
9976 | CdkRectangle *rect) |
9977 | { |
9978 | CtkTextViewPrivate *priv = text_view->priv; |
9979 | CdkWindow *window; |
9980 | guint extra_w; |
9981 | guint extra_h; |
9982 | |
9983 | _ctk_pixel_cache_get_extra_size (priv->pixel_cache, &extra_w, &extra_h); |
9984 | |
9985 | window = ctk_text_view_get_window (text_view, CTK_TEXT_WINDOW_TEXT); |
9986 | |
9987 | rect->x = ctk_adjustment_get_value (priv->hadjustment) - extra_w; |
9988 | rect->y = ctk_adjustment_get_value (priv->vadjustment) - extra_h - priv->top_border; |
9989 | |
9990 | rect->height = cdk_window_get_height (window) + (extra_h * 2); |
9991 | rect->width = cdk_window_get_width (window) + (extra_w * 2); |
9992 | } |
9993 | |
9994 | static void |
9995 | ctk_text_view_queue_draw_region (CtkWidget *widget, |
9996 | const cairo_region_t *region) |
9997 | { |
9998 | CtkTextView *text_view = CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ())))))); |
9999 | |
10000 | /* There is no way we can know if a region targets the |
10001 | not-currently-visible but in pixel cache region, so we |
10002 | always just invalidate the whole thing whenever the |
10003 | text view gets a queue draw. This doesn't normally happen |
10004 | in normal scrolling cases anyway. */ |
10005 | _ctk_pixel_cache_invalidate (text_view->priv->pixel_cache, NULL((void*)0)); |
10006 | |
10007 | CTK_WIDGET_CLASS (ctk_text_view_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((ctk_text_view_parent_class)), ((ctk_widget_get_type ())) ))))->queue_draw_region (widget, region); |
10008 | } |
10009 | |
10010 | static void |
10011 | text_window_invalidate_handler (CdkWindow *window, |
10012 | cairo_region_t *region) |
10013 | { |
10014 | gpointer widget; |
10015 | CtkTextView *text_view; |
10016 | CtkTextViewPrivate *priv; |
10017 | int x, y; |
10018 | |
10019 | cdk_window_get_user_data (window, &widget); |
10020 | text_view = CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ())))))); |
10021 | priv = text_view->priv; |
10022 | |
10023 | /* Scrolling will invalidate everything in the bin window, |
10024 | * but we already have it in the cache, so we can ignore that */ |
10025 | if (priv->in_scroll) |
10026 | return; |
10027 | |
10028 | x = priv->xoffset; |
10029 | y = priv->yoffset + priv->top_border; |
10030 | |
10031 | cairo_region_translate (region, x, y); |
10032 | _ctk_pixel_cache_invalidate (priv->pixel_cache, region); |
10033 | cairo_region_translate (region, -x, -y); |
10034 | } |
10035 | |
10036 | static void |
10037 | text_window_realize (CtkTextWindow *win, |
10038 | CtkWidget *widget) |
10039 | { |
10040 | CdkWindow *window; |
10041 | CdkWindowAttr attributes; |
10042 | gint attributes_mask; |
10043 | CdkDisplay *display; |
10044 | CdkCursor *cursor; |
10045 | |
10046 | attributes.window_type = CDK_WINDOW_CHILD; |
10047 | attributes.x = win->allocation.x; |
10048 | attributes.y = win->allocation.y; |
10049 | attributes.width = win->allocation.width; |
10050 | attributes.height = win->allocation.height; |
10051 | attributes.wclass = CDK_INPUT_OUTPUT; |
10052 | attributes.visual = ctk_widget_get_visual (win->widget); |
10053 | attributes.event_mask = CDK_VISIBILITY_NOTIFY_MASK; |
10054 | |
10055 | attributes_mask = CDK_WA_X | CDK_WA_Y | CDK_WA_VISUAL; |
10056 | |
10057 | window = ctk_widget_get_window (widget); |
10058 | |
10059 | win->window = cdk_window_new (window, |
10060 | &attributes, attributes_mask); |
10061 | |
10062 | cdk_window_show (win->window); |
10063 | ctk_widget_register_window (win->widget, win->window); |
10064 | cdk_window_lower (win->window); |
10065 | |
10066 | attributes.x = 0; |
10067 | attributes.y = 0; |
10068 | attributes.width = win->allocation.width; |
10069 | attributes.height = win->allocation.height; |
10070 | attributes.event_mask = ctk_widget_get_events (win->widget) |
10071 | | CDK_SCROLL_MASK |
10072 | | CDK_SMOOTH_SCROLL_MASK |
10073 | | CDK_KEY_PRESS_MASK |
10074 | | CDK_BUTTON_PRESS_MASK |
10075 | | CDK_BUTTON_RELEASE_MASK |
10076 | | CDK_POINTER_MOTION_MASK; |
10077 | |
10078 | win->bin_window = cdk_window_new (win->window, |
10079 | &attributes, |
10080 | attributes_mask); |
10081 | |
10082 | ctk_widget_register_window (win->widget, win->bin_window); |
10083 | |
10084 | if (win->type == CTK_TEXT_WINDOW_TEXT) |
10085 | cdk_window_set_invalidate_handler (win->bin_window, |
10086 | text_window_invalidate_handler); |
10087 | |
10088 | cdk_window_show (win->bin_window); |
10089 | |
10090 | switch (win->type) |
10091 | { |
10092 | case CTK_TEXT_WINDOW_TEXT: |
10093 | if (ctk_widget_is_sensitive (widget)) |
10094 | { |
10095 | display = cdk_window_get_display (window); |
10096 | cursor = cdk_cursor_new_from_name (display, "text"); |
10097 | cdk_window_set_cursor (win->bin_window, cursor); |
10098 | g_clear_object (&cursor)do { _Static_assert (sizeof *((&cursor)) == sizeof (gpointer ), "Expression evaluates to false"); __typeof__ (((&cursor ))) _pp = ((&cursor)); __typeof__ (*((&cursor))) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref) (_ptr) ; } while (0); |
10099 | } |
10100 | |
10101 | ctk_im_context_set_client_window (CTK_TEXT_VIEW (widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_text_view_get_type ()))))))->priv->im_context, |
10102 | win->window); |
10103 | break; |
10104 | default: |
10105 | break; |
10106 | } |
10107 | |
10108 | g_object_set_qdata (G_OBJECT (win->window)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((win->window)), (((GType) ((20) << (2)))))))), |
10109 | g_quark_from_static_string ("ctk-text-view-text-window"), |
10110 | win); |
10111 | |
10112 | g_object_set_qdata (G_OBJECT (win->bin_window)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((win->bin_window)), (((GType) ((20) << (2))))))) ), |
10113 | g_quark_from_static_string ("ctk-text-view-text-window"), |
10114 | win); |
10115 | } |
10116 | |
10117 | static void |
10118 | text_window_unrealize (CtkTextWindow *win) |
10119 | { |
10120 | if (win->type == CTK_TEXT_WINDOW_TEXT) |
10121 | { |
10122 | ctk_im_context_set_client_window (CTK_TEXT_VIEW (win->widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((win->widget)), ((ctk_text_view_get_type ()))))))->priv->im_context, |
10123 | NULL((void*)0)); |
10124 | } |
10125 | |
10126 | ctk_widget_unregister_window (win->widget, win->window); |
10127 | ctk_widget_unregister_window (win->widget, win->bin_window); |
10128 | cdk_window_destroy (win->bin_window); |
10129 | cdk_window_destroy (win->window); |
10130 | win->window = NULL((void*)0); |
10131 | win->bin_window = NULL((void*)0); |
10132 | } |
10133 | |
10134 | static void |
10135 | text_window_size_allocate (CtkTextWindow *win, |
10136 | CdkRectangle *rect) |
10137 | { |
10138 | win->allocation = *rect; |
10139 | |
10140 | if (win->window) |
10141 | { |
10142 | cdk_window_move_resize (win->window, |
10143 | rect->x, rect->y, |
10144 | rect->width, rect->height); |
10145 | |
10146 | cdk_window_resize (win->bin_window, |
10147 | rect->width, rect->height); |
10148 | } |
10149 | } |
10150 | |
10151 | static void |
10152 | text_window_scroll (CtkTextWindow *win, |
10153 | gint dx, |
10154 | gint dy) |
10155 | { |
10156 | CtkTextView *view = CTK_TEXT_VIEW (win->widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((win->widget)), ((ctk_text_view_get_type ())))))); |
10157 | CtkTextViewPrivate *priv = view->priv; |
10158 | |
10159 | if (dx != 0 || dy != 0) |
10160 | { |
10161 | if (priv->selection_bubble) |
10162 | ctk_widget_hide (priv->selection_bubble); |
10163 | view->priv->in_scroll = TRUE(!(0)); |
10164 | cdk_window_scroll (win->bin_window, dx, dy); |
10165 | view->priv->in_scroll = FALSE(0); |
10166 | } |
10167 | } |
10168 | |
10169 | static void |
10170 | text_window_invalidate_rect (CtkTextWindow *win, |
10171 | CdkRectangle *rect) |
10172 | { |
10173 | CdkRectangle window_rect; |
10174 | |
10175 | if (!win->bin_window) |
10176 | return; |
10177 | |
10178 | ctk_text_view_buffer_to_window_coords (CTK_TEXT_VIEW (win->widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((win->widget)), ((ctk_text_view_get_type ())))))), |
10179 | win->type, |
10180 | rect->x, |
10181 | rect->y, |
10182 | &window_rect.x, |
10183 | &window_rect.y); |
10184 | |
10185 | window_rect.width = rect->width; |
10186 | window_rect.height = rect->height; |
10187 | |
10188 | /* Adjust the rect as appropriate */ |
10189 | |
10190 | switch (win->type) |
10191 | { |
10192 | case CTK_TEXT_WINDOW_TEXT: |
10193 | break; |
10194 | |
10195 | case CTK_TEXT_WINDOW_LEFT: |
10196 | case CTK_TEXT_WINDOW_RIGHT: |
10197 | window_rect.x = 0; |
10198 | window_rect.width = win->allocation.width; |
10199 | break; |
10200 | |
10201 | case CTK_TEXT_WINDOW_TOP: |
10202 | case CTK_TEXT_WINDOW_BOTTOM: |
10203 | window_rect.y = 0; |
10204 | window_rect.height = win->allocation.height; |
10205 | break; |
10206 | |
10207 | default: |
10208 | g_warning ("%s: bug!", G_STRFUNC((const char*) (__func__))); |
10209 | return; |
10210 | break; |
10211 | } |
10212 | |
10213 | cdk_window_invalidate_rect (win->bin_window, &window_rect, FALSE(0)); |
10214 | |
10215 | #if 0 |
10216 | { |
10217 | cairo_t *cr = cdk_cairo_create (win->bin_window); |
10218 | cdk_cairo_rectangle (cr, &window_rect); |
10219 | cairo_set_source_rgb (cr, 1.0, 0.0, 0.0); /* red */ |
10220 | cairo_fill (cr); |
10221 | cairo_destroy (cr); |
10222 | } |
10223 | #endif |
10224 | } |
10225 | |
10226 | static void |
10227 | text_window_invalidate_cursors (CtkTextWindow *win) |
10228 | { |
10229 | CtkTextView *text_view; |
10230 | CtkTextViewPrivate *priv; |
10231 | CtkTextIter iter; |
10232 | CdkRectangle strong; |
10233 | CdkRectangle weak; |
10234 | gboolean draw_arrow; |
10235 | gfloat cursor_aspect_ratio; |
10236 | gint stem_width; |
10237 | gint arrow_width; |
10238 | |
10239 | text_view = CTK_TEXT_VIEW (win->widget)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((win->widget)), ((ctk_text_view_get_type ())))))); |
10240 | priv = text_view->priv; |
10241 | |
10242 | ctk_text_buffer_get_iter_at_mark (priv->buffer, &iter, |
10243 | ctk_text_buffer_get_insert (priv->buffer)); |
10244 | |
10245 | if (_ctk_text_layout_get_block_cursor (priv->layout, &strong)) |
10246 | { |
10247 | text_window_invalidate_rect (win, &strong); |
10248 | return; |
10249 | } |
10250 | |
10251 | ctk_text_layout_get_cursor_locations (priv->layout, &iter, |
10252 | &strong, &weak); |
10253 | |
10254 | /* cursor width calculation as in ctkstylecontext.c:draw_insertion_cursor(), |
10255 | * ignoring the text direction be exposing both sides of the cursor |
10256 | */ |
10257 | |
10258 | draw_arrow = (strong.x != weak.x || strong.y != weak.y); |
10259 | |
10260 | ctk_widget_style_get (win->widget, |
10261 | "cursor-aspect-ratio", &cursor_aspect_ratio, |
10262 | NULL((void*)0)); |
10263 | |
10264 | stem_width = strong.height * cursor_aspect_ratio + 1; |
10265 | arrow_width = stem_width + 1; |
10266 | |
10267 | strong.width = stem_width; |
10268 | |
10269 | /* round up to the next even number */ |
10270 | if (stem_width & 1) |
10271 | stem_width++; |
10272 | |
10273 | strong.x -= stem_width / 2; |
10274 | strong.width += stem_width; |
10275 | |
10276 | if (draw_arrow) |
10277 | { |
10278 | strong.x -= arrow_width; |
10279 | strong.width += arrow_width * 2; |
10280 | } |
10281 | |
10282 | text_window_invalidate_rect (win, &strong); |
10283 | |
10284 | if (draw_arrow) /* == have weak */ |
10285 | { |
10286 | stem_width = weak.height * cursor_aspect_ratio + 1; |
10287 | arrow_width = stem_width + 1; |
10288 | |
10289 | weak.width = stem_width; |
10290 | |
10291 | /* round up to the next even number */ |
10292 | if (stem_width & 1) |
10293 | stem_width++; |
10294 | |
10295 | weak.x -= stem_width / 2; |
10296 | weak.width += stem_width; |
10297 | |
10298 | weak.x -= arrow_width; |
10299 | weak.width += arrow_width * 2; |
10300 | |
10301 | text_window_invalidate_rect (win, &weak); |
10302 | } |
10303 | } |
10304 | |
10305 | static gint |
10306 | text_window_get_width (CtkTextWindow *win) |
10307 | { |
10308 | return win->allocation.width; |
10309 | } |
10310 | |
10311 | static gint |
10312 | text_window_get_height (CtkTextWindow *win) |
10313 | { |
10314 | return win->allocation.height; |
10315 | } |
10316 | |
10317 | /* Windows */ |
10318 | |
10319 | |
10320 | /** |
10321 | * ctk_text_view_get_window: |
10322 | * @text_view: a #CtkTextView |
10323 | * @win: window to get |
10324 | * |
10325 | * Retrieves the #CdkWindow corresponding to an area of the text view; |
10326 | * possible windows include the overall widget window, child windows |
10327 | * on the left, right, top, bottom, and the window that displays the |
10328 | * text buffer. Windows are %NULL and nonexistent if their width or |
10329 | * height is 0, and are nonexistent before the widget has been |
10330 | * realized. |
10331 | * |
10332 | * Returns: (nullable) (transfer none): a #CdkWindow, or %NULL |
10333 | **/ |
10334 | CdkWindow* |
10335 | ctk_text_view_get_window (CtkTextView *text_view, |
10336 | CtkTextWindowType win) |
10337 | { |
10338 | CtkTextViewPrivate *priv = text_view->priv; |
10339 | |
10340 | g_return_val_if_fail (CTK_IS_TEXT_VIEW (text_view), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return (((void*)0)); } } while (0); |
10341 | |
10342 | switch (win) |
10343 | { |
10344 | case CTK_TEXT_WINDOW_WIDGET: |
10345 | return ctk_widget_get_window (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
10346 | break; |
10347 | |
10348 | case CTK_TEXT_WINDOW_TEXT: |
10349 | return priv->text_window->bin_window; |
10350 | break; |
10351 | |
10352 | case CTK_TEXT_WINDOW_LEFT: |
10353 | if (priv->left_window) |
10354 | return priv->left_window->bin_window; |
10355 | else |
10356 | return NULL((void*)0); |
10357 | break; |
10358 | |
10359 | case CTK_TEXT_WINDOW_RIGHT: |
10360 | if (priv->right_window) |
10361 | return priv->right_window->bin_window; |
10362 | else |
10363 | return NULL((void*)0); |
10364 | break; |
10365 | |
10366 | case CTK_TEXT_WINDOW_TOP: |
10367 | if (priv->top_window) |
10368 | return priv->top_window->bin_window; |
10369 | else |
10370 | return NULL((void*)0); |
10371 | break; |
10372 | |
10373 | case CTK_TEXT_WINDOW_BOTTOM: |
10374 | if (priv->bottom_window) |
10375 | return priv->bottom_window->bin_window; |
10376 | else |
10377 | return NULL((void*)0); |
10378 | break; |
10379 | |
10380 | case CTK_TEXT_WINDOW_PRIVATE: |
10381 | g_warning ("%s: You can't get CTK_TEXT_WINDOW_PRIVATE, it has \"PRIVATE\" in the name because it is private.", G_STRFUNC((const char*) (__func__))); |
10382 | return NULL((void*)0); |
10383 | break; |
10384 | } |
10385 | |
10386 | g_warning ("%s: Unknown CtkTextWindowType", G_STRFUNC((const char*) (__func__))); |
10387 | return NULL((void*)0); |
10388 | } |
10389 | |
10390 | static CtkCssNode * |
10391 | ctk_text_view_get_css_node (CtkTextView *text_view, |
10392 | CtkTextWindowType win) |
10393 | { |
10394 | CtkTextViewPrivate *priv = text_view->priv; |
10395 | |
10396 | switch (win) |
10397 | { |
10398 | case CTK_TEXT_WINDOW_WIDGET: |
10399 | return ctk_widget_get_css_node (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
10400 | |
10401 | case CTK_TEXT_WINDOW_TEXT: |
10402 | return priv->text_window->css_node; |
10403 | |
10404 | case CTK_TEXT_WINDOW_LEFT: |
10405 | if (priv->left_window) |
10406 | return priv->left_window->css_node; |
10407 | break; |
10408 | |
10409 | case CTK_TEXT_WINDOW_RIGHT: |
10410 | if (priv->right_window) |
10411 | return priv->right_window->css_node; |
10412 | break; |
10413 | |
10414 | case CTK_TEXT_WINDOW_TOP: |
10415 | if (priv->top_window) |
10416 | return priv->top_window->css_node; |
10417 | break; |
10418 | |
10419 | case CTK_TEXT_WINDOW_BOTTOM: |
10420 | if (priv->bottom_window) |
10421 | return priv->bottom_window->css_node; |
10422 | break; |
10423 | |
10424 | default: |
10425 | break; |
10426 | } |
10427 | |
10428 | return NULL((void*)0); |
10429 | } |
10430 | |
10431 | /** |
10432 | * ctk_text_view_get_window_type: |
10433 | * @text_view: a #CtkTextView |
10434 | * @window: a window type |
10435 | * |
10436 | * Usually used to find out which window an event corresponds to. |
10437 | * |
10438 | * If you connect to an event signal on @text_view, this function |
10439 | * should be called on `event->window` to see which window it was. |
10440 | * |
10441 | * Returns: the window type. |
10442 | **/ |
10443 | CtkTextWindowType |
10444 | ctk_text_view_get_window_type (CtkTextView *text_view, |
10445 | CdkWindow *window) |
10446 | { |
10447 | CtkTextWindow *win; |
10448 | |
10449 | g_return_val_if_fail (CTK_IS_TEXT_VIEW (text_view), CTK_TEXT_WINDOW_PRIVATE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return (CTK_TEXT_WINDOW_PRIVATE ); } } while (0); |
10450 | g_return_val_if_fail (CDK_IS_WINDOW (window), CTK_TEXT_WINDOW_PRIVATE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((window)); GType __t = ((cdk_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; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__ )), "CDK_IS_WINDOW (window)"); return (CTK_TEXT_WINDOW_PRIVATE ); } } while (0); |
10451 | |
10452 | if (window == ctk_widget_get_window (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))))) |
10453 | return CTK_TEXT_WINDOW_WIDGET; |
10454 | |
10455 | win = g_object_get_qdata (G_OBJECT (window)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((window)), (((GType) ((20) << (2)))))))), |
10456 | g_quark_try_string ("ctk-text-view-text-window")); |
10457 | |
10458 | if (win) |
10459 | return win->type; |
10460 | |
10461 | return CTK_TEXT_WINDOW_PRIVATE; |
10462 | } |
10463 | |
10464 | static void |
10465 | buffer_to_widget (CtkTextView *text_view, |
10466 | gint buffer_x, |
10467 | gint buffer_y, |
10468 | gint *window_x, |
10469 | gint *window_y) |
10470 | { |
10471 | CtkTextViewPrivate *priv = text_view->priv; |
10472 | |
10473 | if (window_x) |
10474 | { |
10475 | *window_x = buffer_x - priv->xoffset; |
10476 | *window_x += priv->text_window->allocation.x; |
10477 | } |
10478 | |
10479 | if (window_y) |
10480 | { |
10481 | *window_y = buffer_y - priv->yoffset; |
10482 | *window_y += priv->text_window->allocation.y; |
10483 | } |
10484 | } |
10485 | |
10486 | static void |
10487 | widget_to_text_window (CtkTextWindow *win, |
10488 | gint widget_x, |
10489 | gint widget_y, |
10490 | gint *window_x, |
10491 | gint *window_y) |
10492 | { |
10493 | if (window_x) |
10494 | *window_x = widget_x - win->allocation.x; |
10495 | |
10496 | if (window_y) |
10497 | *window_y = widget_y - win->allocation.y; |
10498 | } |
10499 | |
10500 | static void |
10501 | buffer_to_text_window (CtkTextView *text_view, |
10502 | CtkTextWindow *win, |
10503 | gint buffer_x, |
10504 | gint buffer_y, |
10505 | gint *window_x, |
10506 | gint *window_y) |
10507 | { |
10508 | if (win == NULL((void*)0)) |
10509 | { |
10510 | g_warning ("Attempt to convert text buffer coordinates to coordinates " |
10511 | "for a nonexistent or private child window of CtkTextView"); |
10512 | return; |
10513 | } |
10514 | |
10515 | buffer_to_widget (text_view, |
10516 | buffer_x, buffer_y, |
10517 | window_x, window_y); |
10518 | |
10519 | widget_to_text_window (win, |
10520 | window_x ? *window_x : 0, |
10521 | window_y ? *window_y : 0, |
10522 | window_x, |
10523 | window_y); |
10524 | } |
10525 | |
10526 | /** |
10527 | * ctk_text_view_buffer_to_window_coords: |
10528 | * @text_view: a #CtkTextView |
10529 | * @win: a #CtkTextWindowType, except %CTK_TEXT_WINDOW_PRIVATE |
10530 | * @buffer_x: buffer x coordinate |
10531 | * @buffer_y: buffer y coordinate |
10532 | * @window_x: (out) (allow-none): window x coordinate return location or %NULL |
10533 | * @window_y: (out) (allow-none): window y coordinate return location or %NULL |
10534 | * |
10535 | * Converts coordinate (@buffer_x, @buffer_y) to coordinates for the window |
10536 | * @win, and stores the result in (@window_x, @window_y). |
10537 | * |
10538 | * Note that you can’t convert coordinates for a nonexisting window (see |
10539 | * ctk_text_view_set_border_window_size()). |
10540 | **/ |
10541 | void |
10542 | ctk_text_view_buffer_to_window_coords (CtkTextView *text_view, |
10543 | CtkTextWindowType win, |
10544 | gint buffer_x, |
10545 | gint buffer_y, |
10546 | gint *window_x, |
10547 | gint *window_y) |
10548 | { |
10549 | CtkTextViewPrivate *priv = text_view->priv; |
10550 | |
10551 | g_return_if_fail (CTK_IS_TEXT_VIEW (text_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return; } } while (0); |
10552 | g_return_if_fail (win != CTK_TEXT_WINDOW_PRIVATE)do { if ((win != CTK_TEXT_WINDOW_PRIVATE)) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "win != CTK_TEXT_WINDOW_PRIVATE" ); return; } } while (0); |
10553 | |
10554 | switch (win) |
10555 | { |
10556 | case CTK_TEXT_WINDOW_WIDGET: |
10557 | buffer_to_widget (text_view, |
10558 | buffer_x, buffer_y, |
10559 | window_x, window_y); |
10560 | break; |
10561 | |
10562 | case CTK_TEXT_WINDOW_TEXT: |
10563 | if (window_x) |
10564 | *window_x = buffer_x - priv->xoffset; |
10565 | if (window_y) |
10566 | *window_y = buffer_y - priv->yoffset; |
10567 | break; |
10568 | |
10569 | case CTK_TEXT_WINDOW_LEFT: |
10570 | buffer_to_text_window (text_view, |
10571 | priv->left_window, |
10572 | buffer_x, buffer_y, |
10573 | window_x, window_y); |
10574 | break; |
10575 | |
10576 | case CTK_TEXT_WINDOW_RIGHT: |
10577 | buffer_to_text_window (text_view, |
10578 | priv->right_window, |
10579 | buffer_x, buffer_y, |
10580 | window_x, window_y); |
10581 | break; |
10582 | |
10583 | case CTK_TEXT_WINDOW_TOP: |
10584 | buffer_to_text_window (text_view, |
10585 | priv->top_window, |
10586 | buffer_x, buffer_y, |
10587 | window_x, window_y); |
10588 | break; |
10589 | |
10590 | case CTK_TEXT_WINDOW_BOTTOM: |
10591 | buffer_to_text_window (text_view, |
10592 | priv->bottom_window, |
10593 | buffer_x, buffer_y, |
10594 | window_x, window_y); |
10595 | break; |
10596 | |
10597 | case CTK_TEXT_WINDOW_PRIVATE: |
10598 | g_warning ("%s: can't get coords for private windows", G_STRFUNC((const char*) (__func__))); |
10599 | break; |
10600 | |
10601 | default: |
10602 | g_warning ("%s: Unknown CtkTextWindowType", G_STRFUNC((const char*) (__func__))); |
10603 | break; |
10604 | } |
10605 | } |
10606 | |
10607 | static void |
10608 | widget_to_buffer (CtkTextView *text_view, |
10609 | gint widget_x, |
10610 | gint widget_y, |
10611 | gint *buffer_x, |
10612 | gint *buffer_y) |
10613 | { |
10614 | CtkTextViewPrivate *priv = text_view->priv; |
10615 | |
10616 | if (buffer_x) |
10617 | { |
10618 | *buffer_x = widget_x + priv->xoffset; |
10619 | *buffer_x -= priv->text_window->allocation.x; |
10620 | } |
10621 | |
10622 | if (buffer_y) |
10623 | { |
10624 | *buffer_y = widget_y + priv->yoffset; |
10625 | *buffer_y -= priv->text_window->allocation.y; |
10626 | } |
10627 | } |
10628 | |
10629 | static void |
10630 | text_window_to_widget (CtkTextWindow *win, |
10631 | gint window_x, |
10632 | gint window_y, |
10633 | gint *widget_x, |
10634 | gint *widget_y) |
10635 | { |
10636 | if (widget_x) |
10637 | *widget_x = window_x + win->allocation.x; |
10638 | |
10639 | if (widget_y) |
10640 | *widget_y = window_y + win->allocation.y; |
10641 | } |
10642 | |
10643 | static void |
10644 | text_window_to_buffer (CtkTextView *text_view, |
10645 | CtkTextWindow *win, |
10646 | gint window_x, |
10647 | gint window_y, |
10648 | gint *buffer_x, |
10649 | gint *buffer_y) |
10650 | { |
10651 | if (win == NULL((void*)0)) |
10652 | { |
10653 | g_warning ("Attempt to convert CtkTextView buffer coordinates into " |
10654 | "coordinates for a nonexistent child window."); |
10655 | return; |
10656 | } |
10657 | |
10658 | text_window_to_widget (win, |
10659 | window_x, |
10660 | window_y, |
10661 | buffer_x, |
10662 | buffer_y); |
10663 | |
10664 | widget_to_buffer (text_view, |
10665 | buffer_x ? *buffer_x : 0, |
10666 | buffer_y ? *buffer_y : 0, |
10667 | buffer_x, |
10668 | buffer_y); |
10669 | } |
10670 | |
10671 | /** |
10672 | * ctk_text_view_window_to_buffer_coords: |
10673 | * @text_view: a #CtkTextView |
10674 | * @win: a #CtkTextWindowType except %CTK_TEXT_WINDOW_PRIVATE |
10675 | * @window_x: window x coordinate |
10676 | * @window_y: window y coordinate |
10677 | * @buffer_x: (out) (allow-none): buffer x coordinate return location or %NULL |
10678 | * @buffer_y: (out) (allow-none): buffer y coordinate return location or %NULL |
10679 | * |
10680 | * Converts coordinates on the window identified by @win to buffer |
10681 | * coordinates, storing the result in (@buffer_x,@buffer_y). |
10682 | * |
10683 | * Note that you can’t convert coordinates for a nonexisting window (see |
10684 | * ctk_text_view_set_border_window_size()). |
10685 | **/ |
10686 | void |
10687 | ctk_text_view_window_to_buffer_coords (CtkTextView *text_view, |
10688 | CtkTextWindowType win, |
10689 | gint window_x, |
10690 | gint window_y, |
10691 | gint *buffer_x, |
10692 | gint *buffer_y) |
10693 | { |
10694 | CtkTextViewPrivate *priv = text_view->priv; |
10695 | |
10696 | g_return_if_fail (CTK_IS_TEXT_VIEW (text_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return; } } while (0); |
10697 | g_return_if_fail (win != CTK_TEXT_WINDOW_PRIVATE)do { if ((win != CTK_TEXT_WINDOW_PRIVATE)) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "win != CTK_TEXT_WINDOW_PRIVATE" ); return; } } while (0); |
10698 | |
10699 | switch (win) |
10700 | { |
10701 | case CTK_TEXT_WINDOW_WIDGET: |
10702 | widget_to_buffer (text_view, |
10703 | window_x, window_y, |
10704 | buffer_x, buffer_y); |
10705 | break; |
10706 | |
10707 | case CTK_TEXT_WINDOW_TEXT: |
10708 | if (buffer_x) |
10709 | *buffer_x = window_x + priv->xoffset; |
10710 | if (buffer_y) |
10711 | *buffer_y = window_y + priv->yoffset; |
10712 | break; |
10713 | |
10714 | case CTK_TEXT_WINDOW_LEFT: |
10715 | text_window_to_buffer (text_view, |
10716 | priv->left_window, |
10717 | window_x, window_y, |
10718 | buffer_x, buffer_y); |
10719 | break; |
10720 | |
10721 | case CTK_TEXT_WINDOW_RIGHT: |
10722 | text_window_to_buffer (text_view, |
10723 | priv->right_window, |
10724 | window_x, window_y, |
10725 | buffer_x, buffer_y); |
10726 | break; |
10727 | |
10728 | case CTK_TEXT_WINDOW_TOP: |
10729 | text_window_to_buffer (text_view, |
10730 | priv->top_window, |
10731 | window_x, window_y, |
10732 | buffer_x, buffer_y); |
10733 | break; |
10734 | |
10735 | case CTK_TEXT_WINDOW_BOTTOM: |
10736 | text_window_to_buffer (text_view, |
10737 | priv->bottom_window, |
10738 | window_x, window_y, |
10739 | buffer_x, buffer_y); |
10740 | break; |
10741 | |
10742 | case CTK_TEXT_WINDOW_PRIVATE: |
10743 | g_warning ("%s: can't get coords for private windows", G_STRFUNC((const char*) (__func__))); |
10744 | break; |
10745 | |
10746 | default: |
10747 | g_warning ("%s: Unknown CtkTextWindowType", G_STRFUNC((const char*) (__func__))); |
10748 | break; |
10749 | } |
10750 | } |
10751 | |
10752 | static void |
10753 | set_window_width (CtkTextView *text_view, |
10754 | gint width, |
10755 | CtkTextWindowType type, |
10756 | CtkTextWindow **winp) |
10757 | { |
10758 | if (width == 0) |
10759 | { |
10760 | if (*winp) |
10761 | { |
10762 | text_window_free (*winp); |
10763 | *winp = NULL((void*)0); |
10764 | ctk_widget_queue_resize (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
10765 | } |
10766 | } |
10767 | else |
10768 | { |
10769 | if (*winp == NULL((void*)0)) |
10770 | { |
10771 | *winp = text_window_new (type, CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))), width, 0); |
10772 | /* if the widget is already realized we need to realize the child manually */ |
10773 | if (ctk_widget_get_realized (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))))) |
10774 | text_window_realize (*winp, CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
10775 | update_node_ordering (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
10776 | } |
10777 | else |
10778 | { |
10779 | if ((*winp)->requisition.width == width) |
10780 | return; |
10781 | |
10782 | (*winp)->requisition.width = width; |
10783 | } |
10784 | |
10785 | ctk_widget_queue_resize (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
10786 | } |
10787 | } |
10788 | |
10789 | |
10790 | static void |
10791 | set_window_height (CtkTextView *text_view, |
10792 | gint height, |
10793 | CtkTextWindowType type, |
10794 | CtkTextWindow **winp) |
10795 | { |
10796 | if (height == 0) |
10797 | { |
10798 | if (*winp) |
10799 | { |
10800 | text_window_free (*winp); |
10801 | *winp = NULL((void*)0); |
10802 | ctk_widget_queue_resize (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
10803 | } |
10804 | } |
10805 | else |
10806 | { |
10807 | if (*winp == NULL((void*)0)) |
10808 | { |
10809 | *winp = text_window_new (type, CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))), 0, height); |
10810 | |
10811 | /* if the widget is already realized we need to realize the child manually */ |
10812 | if (ctk_widget_get_realized (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))))) |
10813 | text_window_realize (*winp, CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
10814 | update_node_ordering (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
10815 | } |
10816 | else |
10817 | { |
10818 | if ((*winp)->requisition.height == height) |
10819 | return; |
10820 | |
10821 | (*winp)->requisition.height = height; |
10822 | } |
10823 | |
10824 | ctk_widget_queue_resize (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
10825 | } |
10826 | } |
10827 | |
10828 | /** |
10829 | * ctk_text_view_set_border_window_size: |
10830 | * @text_view: a #CtkTextView |
10831 | * @type: window to affect |
10832 | * @size: width or height of the window |
10833 | * |
10834 | * Sets the width of %CTK_TEXT_WINDOW_LEFT or %CTK_TEXT_WINDOW_RIGHT, |
10835 | * or the height of %CTK_TEXT_WINDOW_TOP or %CTK_TEXT_WINDOW_BOTTOM. |
10836 | * Automatically destroys the corresponding window if the size is set |
10837 | * to 0, and creates the window if the size is set to non-zero. This |
10838 | * function can only be used for the “border windows”, and it won’t |
10839 | * work with %CTK_TEXT_WINDOW_WIDGET, %CTK_TEXT_WINDOW_TEXT, or |
10840 | * %CTK_TEXT_WINDOW_PRIVATE. |
10841 | **/ |
10842 | void |
10843 | ctk_text_view_set_border_window_size (CtkTextView *text_view, |
10844 | CtkTextWindowType type, |
10845 | gint size) |
10846 | { |
10847 | CtkTextViewPrivate *priv = text_view->priv; |
10848 | |
10849 | g_return_if_fail (CTK_IS_TEXT_VIEW (text_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return; } } while (0); |
10850 | g_return_if_fail (type != CTK_TEXT_WINDOW_PRIVATE)do { if ((type != CTK_TEXT_WINDOW_PRIVATE)) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "type != CTK_TEXT_WINDOW_PRIVATE" ); return; } } while (0); |
10851 | g_return_if_fail (size >= 0)do { if ((size >= 0)) { } else { g_return_if_fail_warning ( "Ctk", ((const char*) (__func__)), "size >= 0"); return; } } while (0); |
10852 | |
10853 | switch (type) |
10854 | { |
10855 | case CTK_TEXT_WINDOW_LEFT: |
10856 | set_window_width (text_view, size, CTK_TEXT_WINDOW_LEFT, |
10857 | &priv->left_window); |
10858 | break; |
10859 | |
10860 | case CTK_TEXT_WINDOW_RIGHT: |
10861 | set_window_width (text_view, size, CTK_TEXT_WINDOW_RIGHT, |
10862 | &priv->right_window); |
10863 | break; |
10864 | |
10865 | case CTK_TEXT_WINDOW_TOP: |
10866 | set_window_height (text_view, size, CTK_TEXT_WINDOW_TOP, |
10867 | &priv->top_window); |
10868 | break; |
10869 | |
10870 | case CTK_TEXT_WINDOW_BOTTOM: |
10871 | set_window_height (text_view, size, CTK_TEXT_WINDOW_BOTTOM, |
10872 | &priv->bottom_window); |
10873 | break; |
10874 | |
10875 | default: |
10876 | g_warning ("Can only set size of left/right/top/bottom border windows with ctk_text_view_set_border_window_size()"); |
10877 | break; |
10878 | } |
10879 | } |
10880 | |
10881 | /** |
10882 | * ctk_text_view_get_border_window_size: |
10883 | * @text_view: a #CtkTextView |
10884 | * @type: window to return size from |
10885 | * |
10886 | * Gets the width of the specified border window. See |
10887 | * ctk_text_view_set_border_window_size(). |
10888 | * |
10889 | * Returns: width of window |
10890 | **/ |
10891 | gint |
10892 | ctk_text_view_get_border_window_size (CtkTextView *text_view, |
10893 | CtkTextWindowType type) |
10894 | { |
10895 | CtkTextViewPrivate *priv = text_view->priv; |
10896 | |
10897 | g_return_val_if_fail (CTK_IS_TEXT_VIEW (text_view), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return (0); } } while (0 ); |
10898 | |
10899 | switch (type) |
10900 | { |
10901 | case CTK_TEXT_WINDOW_LEFT: |
10902 | if (priv->left_window) |
10903 | return priv->left_window->requisition.width; |
10904 | break; |
10905 | |
10906 | case CTK_TEXT_WINDOW_RIGHT: |
10907 | if (priv->right_window) |
10908 | return priv->right_window->requisition.width; |
10909 | break; |
10910 | |
10911 | case CTK_TEXT_WINDOW_TOP: |
10912 | if (priv->top_window) |
10913 | return priv->top_window->requisition.height; |
10914 | break; |
10915 | |
10916 | case CTK_TEXT_WINDOW_BOTTOM: |
10917 | if (priv->bottom_window) |
10918 | return priv->bottom_window->requisition.height; |
10919 | break; |
10920 | |
10921 | default: |
10922 | g_warning ("Can only get size of left/right/top/bottom border windows with ctk_text_view_get_border_window_size()"); |
10923 | break; |
10924 | } |
10925 | |
10926 | return 0; |
10927 | } |
10928 | |
10929 | /* |
10930 | * Child widgets |
10931 | */ |
10932 | |
10933 | static CtkTextViewChild* |
10934 | text_view_child_new_anchored (CtkWidget *child, |
10935 | CtkTextChildAnchor *anchor, |
10936 | CtkTextLayout *layout) |
10937 | { |
10938 | CtkTextViewChild *vc; |
10939 | |
10940 | vc = g_slice_new (CtkTextViewChild)((CtkTextViewChild*) g_slice_alloc (sizeof (CtkTextViewChild) )); |
10941 | |
10942 | vc->type = CTK_TEXT_WINDOW_PRIVATE; |
10943 | vc->widget = child; |
10944 | vc->anchor = anchor; |
10945 | |
10946 | vc->from_top_of_line = 0; |
10947 | vc->from_left_of_buffer = 0; |
10948 | |
10949 | g_object_ref (vc->widget)((__typeof__ (vc->widget)) (g_object_ref) (vc->widget)); |
10950 | g_object_ref (vc->anchor)((__typeof__ (vc->anchor)) (g_object_ref) (vc->anchor)); |
10951 | |
10952 | g_object_set_qdata (G_OBJECT (child)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((child)), (((GType) ((20) << (2)))))))), quark_text_view_child, vc); |
10953 | |
10954 | ctk_text_child_anchor_register_child (anchor, child, layout); |
10955 | |
10956 | return vc; |
10957 | } |
10958 | |
10959 | static CtkTextViewChild* |
10960 | text_view_child_new_window (CtkWidget *child, |
10961 | CtkTextWindowType type, |
10962 | gint x, |
10963 | gint y) |
10964 | { |
10965 | CtkTextViewChild *vc; |
10966 | |
10967 | vc = g_slice_new (CtkTextViewChild)((CtkTextViewChild*) g_slice_alloc (sizeof (CtkTextViewChild) )); |
10968 | |
10969 | vc->widget = child; |
10970 | vc->anchor = NULL((void*)0); |
10971 | |
10972 | vc->from_top_of_line = 0; |
10973 | vc->from_left_of_buffer = 0; |
10974 | |
10975 | g_object_ref (vc->widget)((__typeof__ (vc->widget)) (g_object_ref) (vc->widget)); |
10976 | |
10977 | vc->type = type; |
10978 | vc->x = x; |
10979 | vc->y = y; |
10980 | |
10981 | g_object_set_qdata (G_OBJECT (child)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((child)), (((GType) ((20) << (2)))))))), quark_text_view_child, vc); |
10982 | |
10983 | return vc; |
10984 | } |
10985 | |
10986 | static void |
10987 | text_view_child_free (CtkTextViewChild *child) |
10988 | { |
10989 | g_object_set_qdata (G_OBJECT (child->widget)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((child->widget)), (((GType) ((20) << (2)))))))), quark_text_view_child, NULL((void*)0)); |
10990 | |
10991 | if (child->anchor) |
10992 | { |
10993 | ctk_text_child_anchor_unregister_child (child->anchor, |
10994 | child->widget); |
10995 | g_object_unref (child->anchor); |
10996 | } |
10997 | |
10998 | g_object_unref (child->widget); |
10999 | |
11000 | g_slice_free (CtkTextViewChild, child)do { if (1) g_slice_free1 (sizeof (CtkTextViewChild), (child) ); else (void) ((CtkTextViewChild*) 0 == (child)); } while (0 ); |
11001 | } |
11002 | |
11003 | static void |
11004 | text_view_child_set_parent_window (CtkTextView *text_view, |
11005 | CtkTextViewChild *vc) |
11006 | { |
11007 | if (vc->anchor) |
11008 | ctk_widget_set_parent_window (vc->widget, |
11009 | text_view->priv->text_window->bin_window); |
11010 | else |
11011 | { |
11012 | CdkWindow *window; |
11013 | window = ctk_text_view_get_window (text_view, |
11014 | vc->type); |
11015 | ctk_widget_set_parent_window (vc->widget, window); |
11016 | } |
11017 | } |
11018 | |
11019 | static void |
11020 | add_child (CtkTextView *text_view, |
11021 | CtkTextViewChild *vc) |
11022 | { |
11023 | CtkCssNode *parent; |
11024 | |
11025 | text_view->priv->children = g_slist_prepend (text_view->priv->children, vc); |
11026 | |
11027 | if (ctk_widget_get_realized (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))))) |
11028 | text_view_child_set_parent_window (text_view, vc); |
11029 | |
11030 | parent = ctk_text_view_get_css_node (text_view, vc->type); |
11031 | if (parent == NULL((void*)0)) |
11032 | parent = ctk_widget_get_css_node (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
11033 | |
11034 | ctk_css_node_set_parent (ctk_widget_get_css_node (vc->widget), parent); |
11035 | |
11036 | ctk_widget_set_parent (vc->widget, CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
11037 | } |
11038 | |
11039 | /** |
11040 | * ctk_text_view_add_child_at_anchor: |
11041 | * @text_view: a #CtkTextView |
11042 | * @child: a #CtkWidget |
11043 | * @anchor: a #CtkTextChildAnchor in the #CtkTextBuffer for @text_view |
11044 | * |
11045 | * Adds a child widget in the text buffer, at the given @anchor. |
11046 | **/ |
11047 | void |
11048 | ctk_text_view_add_child_at_anchor (CtkTextView *text_view, |
11049 | CtkWidget *child, |
11050 | CtkTextChildAnchor *anchor) |
11051 | { |
11052 | CtkTextViewChild *vc; |
11053 | |
11054 | g_return_if_fail (CTK_IS_TEXT_VIEW (text_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return; } } while (0); |
11055 | g_return_if_fail (CTK_IS_WIDGET (child))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((child)); 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 (child)"); return; } } while (0); |
11056 | g_return_if_fail (CTK_IS_TEXT_CHILD_ANCHOR (anchor))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((anchor)); GType __t = ((ctk_text_child_anchor_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_TEXT_CHILD_ANCHOR (anchor)"); return ; } } while (0); |
11057 | g_return_if_fail (ctk_widget_get_parent (child) == NULL)do { if ((ctk_widget_get_parent (child) == ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__) ), "ctk_widget_get_parent (child) == NULL"); return; } } while (0); |
11058 | |
11059 | ctk_text_view_ensure_layout (text_view); |
11060 | |
11061 | vc = text_view_child_new_anchored (child, anchor, |
11062 | text_view->priv->layout); |
11063 | |
11064 | add_child (text_view, vc); |
11065 | |
11066 | g_assert (vc->widget == child)do { if (vc->widget == child) ; else g_assertion_message_expr ("Ctk", "ctktextview.c", 11066, ((const char*) (__func__)), "vc->widget == child" ); } while (0); |
11067 | g_assert (ctk_widget_get_parent (child) == CTK_WIDGET (text_view))do { if (ctk_widget_get_parent (child) == ((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((text_view) ), ((ctk_widget_get_type ()))))))) ; else g_assertion_message_expr ("Ctk", "ctktextview.c", 11067, ((const char*) (__func__)), "ctk_widget_get_parent (child) == CTK_WIDGET (text_view)" ); } while (0); |
11068 | } |
11069 | |
11070 | /** |
11071 | * ctk_text_view_add_child_in_window: |
11072 | * @text_view: a #CtkTextView |
11073 | * @child: a #CtkWidget |
11074 | * @which_window: which window the child should appear in |
11075 | * @xpos: X position of child in window coordinates |
11076 | * @ypos: Y position of child in window coordinates |
11077 | * |
11078 | * Adds a child at fixed coordinates in one of the text widget's |
11079 | * windows. |
11080 | * |
11081 | * The window must have nonzero size (see |
11082 | * ctk_text_view_set_border_window_size()). Note that the child |
11083 | * coordinates are given relative to scrolling. When |
11084 | * placing a child in #CTK_TEXT_WINDOW_WIDGET, scrolling is |
11085 | * irrelevant, the child floats above all scrollable areas. But when |
11086 | * placing a child in one of the scrollable windows (border windows or |
11087 | * text window) it will move with the scrolling as needed. |
11088 | */ |
11089 | void |
11090 | ctk_text_view_add_child_in_window (CtkTextView *text_view, |
11091 | CtkWidget *child, |
11092 | CtkTextWindowType which_window, |
11093 | gint xpos, |
11094 | gint ypos) |
11095 | { |
11096 | CtkTextViewChild *vc; |
11097 | |
11098 | g_return_if_fail (CTK_IS_TEXT_VIEW (text_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return; } } while (0); |
11099 | g_return_if_fail (CTK_IS_WIDGET (child))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((child)); 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 (child)"); return; } } while (0); |
11100 | g_return_if_fail (ctk_widget_get_parent (child) == NULL)do { if ((ctk_widget_get_parent (child) == ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__) ), "ctk_widget_get_parent (child) == NULL"); return; } } while (0); |
11101 | |
11102 | vc = text_view_child_new_window (child, which_window, |
11103 | xpos, ypos); |
11104 | |
11105 | add_child (text_view, vc); |
11106 | |
11107 | g_assert (vc->widget == child)do { if (vc->widget == child) ; else g_assertion_message_expr ("Ctk", "ctktextview.c", 11107, ((const char*) (__func__)), "vc->widget == child" ); } while (0); |
11108 | g_assert (ctk_widget_get_parent (child) == CTK_WIDGET (text_view))do { if (ctk_widget_get_parent (child) == ((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((text_view) ), ((ctk_widget_get_type ()))))))) ; else g_assertion_message_expr ("Ctk", "ctktextview.c", 11108, ((const char*) (__func__)), "ctk_widget_get_parent (child) == CTK_WIDGET (text_view)" ); } while (0); |
11109 | } |
11110 | |
11111 | /** |
11112 | * ctk_text_view_move_child: |
11113 | * @text_view: a #CtkTextView |
11114 | * @child: child widget already added to the text view |
11115 | * @xpos: new X position in window coordinates |
11116 | * @ypos: new Y position in window coordinates |
11117 | * |
11118 | * Updates the position of a child, as for ctk_text_view_add_child_in_window(). |
11119 | **/ |
11120 | void |
11121 | ctk_text_view_move_child (CtkTextView *text_view, |
11122 | CtkWidget *child, |
11123 | gint xpos, |
11124 | gint ypos) |
11125 | { |
11126 | CtkTextViewChild *vc; |
11127 | |
11128 | g_return_if_fail (CTK_IS_TEXT_VIEW (text_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return; } } while (0); |
11129 | g_return_if_fail (CTK_IS_WIDGET (child))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((child)); 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 (child)"); return; } } while (0); |
11130 | g_return_if_fail (ctk_widget_get_parent (child) == CTK_WIDGET (text_view))do { if ((ctk_widget_get_parent (child) == ((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((text_view) ), ((ctk_widget_get_type ())))))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "ctk_widget_get_parent (child) == CTK_WIDGET (text_view)" ); return; } } while (0); |
11131 | |
11132 | vc = g_object_get_qdata (G_OBJECT (child)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((child)), (((GType) ((20) << (2)))))))), quark_text_view_child); |
11133 | |
11134 | g_assert (vc != NULL)do { if (vc != ((void*)0)) ; else g_assertion_message_expr ("Ctk" , "ctktextview.c", 11134, ((const char*) (__func__)), "vc != NULL" ); } while (0); |
11135 | |
11136 | if (vc->x == xpos && |
11137 | vc->y == ypos) |
11138 | return; |
11139 | |
11140 | vc->x = xpos; |
11141 | vc->y = ypos; |
11142 | |
11143 | if (ctk_widget_get_visible (child) && |
11144 | ctk_widget_get_visible (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))))) |
11145 | ctk_widget_queue_resize (child); |
11146 | } |
11147 | |
11148 | |
11149 | /* Iterator operations */ |
11150 | |
11151 | /** |
11152 | * ctk_text_view_forward_display_line: |
11153 | * @text_view: a #CtkTextView |
11154 | * @iter: a #CtkTextIter |
11155 | * |
11156 | * Moves the given @iter forward by one display (wrapped) line. |
11157 | * A display line is different from a paragraph. Paragraphs are |
11158 | * separated by newlines or other paragraph separator characters. |
11159 | * Display lines are created by line-wrapping a paragraph. If |
11160 | * wrapping is turned off, display lines and paragraphs will be the |
11161 | * same. Display lines are divided differently for each view, since |
11162 | * they depend on the view’s width; paragraphs are the same in all |
11163 | * views, since they depend on the contents of the #CtkTextBuffer. |
11164 | * |
11165 | * Returns: %TRUE if @iter was moved and is not on the end iterator |
11166 | **/ |
11167 | gboolean |
11168 | ctk_text_view_forward_display_line (CtkTextView *text_view, |
11169 | CtkTextIter *iter) |
11170 | { |
11171 | g_return_val_if_fail (CTK_IS_TEXT_VIEW (text_view), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return ((0)); } } while ( 0); |
11172 | g_return_val_if_fail (iter != NULL, FALSE)do { if ((iter != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "iter != NULL"); return ( (0)); } } while (0); |
11173 | |
11174 | ctk_text_view_ensure_layout (text_view); |
11175 | |
11176 | return ctk_text_layout_move_iter_to_next_line (text_view->priv->layout, iter); |
11177 | } |
11178 | |
11179 | /** |
11180 | * ctk_text_view_backward_display_line: |
11181 | * @text_view: a #CtkTextView |
11182 | * @iter: a #CtkTextIter |
11183 | * |
11184 | * Moves the given @iter backward by one display (wrapped) line. |
11185 | * A display line is different from a paragraph. Paragraphs are |
11186 | * separated by newlines or other paragraph separator characters. |
11187 | * Display lines are created by line-wrapping a paragraph. If |
11188 | * wrapping is turned off, display lines and paragraphs will be the |
11189 | * same. Display lines are divided differently for each view, since |
11190 | * they depend on the view’s width; paragraphs are the same in all |
11191 | * views, since they depend on the contents of the #CtkTextBuffer. |
11192 | * |
11193 | * Returns: %TRUE if @iter was moved and is not on the end iterator |
11194 | **/ |
11195 | gboolean |
11196 | ctk_text_view_backward_display_line (CtkTextView *text_view, |
11197 | CtkTextIter *iter) |
11198 | { |
11199 | g_return_val_if_fail (CTK_IS_TEXT_VIEW (text_view), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return ((0)); } } while ( 0); |
11200 | g_return_val_if_fail (iter != NULL, FALSE)do { if ((iter != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "iter != NULL"); return ( (0)); } } while (0); |
11201 | |
11202 | ctk_text_view_ensure_layout (text_view); |
11203 | |
11204 | return ctk_text_layout_move_iter_to_previous_line (text_view->priv->layout, iter); |
11205 | } |
11206 | |
11207 | /** |
11208 | * ctk_text_view_forward_display_line_end: |
11209 | * @text_view: a #CtkTextView |
11210 | * @iter: a #CtkTextIter |
11211 | * |
11212 | * Moves the given @iter forward to the next display line end. |
11213 | * A display line is different from a paragraph. Paragraphs are |
11214 | * separated by newlines or other paragraph separator characters. |
11215 | * Display lines are created by line-wrapping a paragraph. If |
11216 | * wrapping is turned off, display lines and paragraphs will be the |
11217 | * same. Display lines are divided differently for each view, since |
11218 | * they depend on the view’s width; paragraphs are the same in all |
11219 | * views, since they depend on the contents of the #CtkTextBuffer. |
11220 | * |
11221 | * Returns: %TRUE if @iter was moved and is not on the end iterator |
11222 | **/ |
11223 | gboolean |
11224 | ctk_text_view_forward_display_line_end (CtkTextView *text_view, |
11225 | CtkTextIter *iter) |
11226 | { |
11227 | g_return_val_if_fail (CTK_IS_TEXT_VIEW (text_view), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return ((0)); } } while ( 0); |
11228 | g_return_val_if_fail (iter != NULL, FALSE)do { if ((iter != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "iter != NULL"); return ( (0)); } } while (0); |
11229 | |
11230 | ctk_text_view_ensure_layout (text_view); |
11231 | |
11232 | return ctk_text_layout_move_iter_to_line_end (text_view->priv->layout, iter, 1); |
11233 | } |
11234 | |
11235 | /** |
11236 | * ctk_text_view_backward_display_line_start: |
11237 | * @text_view: a #CtkTextView |
11238 | * @iter: a #CtkTextIter |
11239 | * |
11240 | * Moves the given @iter backward to the next display line start. |
11241 | * A display line is different from a paragraph. Paragraphs are |
11242 | * separated by newlines or other paragraph separator characters. |
11243 | * Display lines are created by line-wrapping a paragraph. If |
11244 | * wrapping is turned off, display lines and paragraphs will be the |
11245 | * same. Display lines are divided differently for each view, since |
11246 | * they depend on the view’s width; paragraphs are the same in all |
11247 | * views, since they depend on the contents of the #CtkTextBuffer. |
11248 | * |
11249 | * Returns: %TRUE if @iter was moved and is not on the end iterator |
11250 | **/ |
11251 | gboolean |
11252 | ctk_text_view_backward_display_line_start (CtkTextView *text_view, |
11253 | CtkTextIter *iter) |
11254 | { |
11255 | g_return_val_if_fail (CTK_IS_TEXT_VIEW (text_view), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return ((0)); } } while ( 0); |
11256 | g_return_val_if_fail (iter != NULL, FALSE)do { if ((iter != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "iter != NULL"); return ( (0)); } } while (0); |
11257 | |
11258 | ctk_text_view_ensure_layout (text_view); |
11259 | |
11260 | return ctk_text_layout_move_iter_to_line_end (text_view->priv->layout, iter, -1); |
11261 | } |
11262 | |
11263 | /** |
11264 | * ctk_text_view_starts_display_line: |
11265 | * @text_view: a #CtkTextView |
11266 | * @iter: a #CtkTextIter |
11267 | * |
11268 | * Determines whether @iter is at the start of a display line. |
11269 | * See ctk_text_view_forward_display_line() for an explanation of |
11270 | * display lines vs. paragraphs. |
11271 | * |
11272 | * Returns: %TRUE if @iter begins a wrapped line |
11273 | **/ |
11274 | gboolean |
11275 | ctk_text_view_starts_display_line (CtkTextView *text_view, |
11276 | const CtkTextIter *iter) |
11277 | { |
11278 | g_return_val_if_fail (CTK_IS_TEXT_VIEW (text_view), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return ((0)); } } while ( 0); |
11279 | g_return_val_if_fail (iter != NULL, FALSE)do { if ((iter != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "iter != NULL"); return ( (0)); } } while (0); |
11280 | |
11281 | ctk_text_view_ensure_layout (text_view); |
11282 | |
11283 | return ctk_text_layout_iter_starts_line (text_view->priv->layout, iter); |
11284 | } |
11285 | |
11286 | /** |
11287 | * ctk_text_view_move_visually: |
11288 | * @text_view: a #CtkTextView |
11289 | * @iter: a #CtkTextIter |
11290 | * @count: number of characters to move (negative moves left, |
11291 | * positive moves right) |
11292 | * |
11293 | * Move the iterator a given number of characters visually, treating |
11294 | * it as the strong cursor position. If @count is positive, then the |
11295 | * new strong cursor position will be @count positions to the right of |
11296 | * the old cursor position. If @count is negative then the new strong |
11297 | * cursor position will be @count positions to the left of the old |
11298 | * cursor position. |
11299 | * |
11300 | * In the presence of bi-directional text, the correspondence |
11301 | * between logical and visual order will depend on the direction |
11302 | * of the current run, and there may be jumps when the cursor |
11303 | * is moved off of the end of a run. |
11304 | * |
11305 | * Returns: %TRUE if @iter moved and is not on the end iterator |
11306 | **/ |
11307 | gboolean |
11308 | ctk_text_view_move_visually (CtkTextView *text_view, |
11309 | CtkTextIter *iter, |
11310 | gint count) |
11311 | { |
11312 | g_return_val_if_fail (CTK_IS_TEXT_VIEW (text_view), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return ((0)); } } while ( 0); |
11313 | g_return_val_if_fail (iter != NULL, FALSE)do { if ((iter != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "iter != NULL"); return ( (0)); } } while (0); |
11314 | |
11315 | ctk_text_view_ensure_layout (text_view); |
11316 | |
11317 | return ctk_text_layout_move_iter_visually (text_view->priv->layout, iter, count); |
11318 | } |
11319 | |
11320 | /** |
11321 | * ctk_text_view_set_input_purpose: |
11322 | * @text_view: a #CtkTextView |
11323 | * @purpose: the purpose |
11324 | * |
11325 | * Sets the #CtkTextView:input-purpose property which |
11326 | * can be used by on-screen keyboards and other input |
11327 | * methods to adjust their behaviour. |
11328 | * |
11329 | * Since: 3.6 |
11330 | */ |
11331 | |
11332 | void |
11333 | ctk_text_view_set_input_purpose (CtkTextView *text_view, |
11334 | CtkInputPurpose purpose) |
11335 | |
11336 | { |
11337 | g_return_if_fail (CTK_IS_TEXT_VIEW (text_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return; } } while (0); |
11338 | |
11339 | if (ctk_text_view_get_input_purpose (text_view) != purpose) |
11340 | { |
11341 | g_object_set (G_OBJECT (text_view->priv->im_context)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view->priv->im_context)), (((GType) ((20) << (2)))))))), |
11342 | "input-purpose", purpose, |
11343 | NULL((void*)0)); |
11344 | |
11345 | g_object_notify (G_OBJECT (text_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), (((GType) ((20) << (2)))))))), "input-purpose"); |
11346 | } |
11347 | } |
11348 | |
11349 | /** |
11350 | * ctk_text_view_get_input_purpose: |
11351 | * @text_view: a #CtkTextView |
11352 | * |
11353 | * Gets the value of the #CtkTextView:input-purpose property. |
11354 | * |
11355 | * Since: 3.6 |
11356 | */ |
11357 | |
11358 | CtkInputPurpose |
11359 | ctk_text_view_get_input_purpose (CtkTextView *text_view) |
11360 | { |
11361 | CtkInputPurpose purpose; |
11362 | |
11363 | g_return_val_if_fail (CTK_IS_TEXT_VIEW (text_view), CTK_INPUT_PURPOSE_FREE_FORM)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return (CTK_INPUT_PURPOSE_FREE_FORM ); } } while (0); |
11364 | |
11365 | g_object_get (G_OBJECT (text_view->priv->im_context)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view->priv->im_context)), (((GType) ((20) << (2)))))))), |
11366 | "input-purpose", &purpose, |
11367 | NULL((void*)0)); |
11368 | |
11369 | return purpose; |
11370 | } |
11371 | |
11372 | /** |
11373 | * ctk_text_view_set_input_hints: |
11374 | * @text_view: a #CtkTextView |
11375 | * @hints: the hints |
11376 | * |
11377 | * Sets the #CtkTextView:input-hints property, which |
11378 | * allows input methods to fine-tune their behaviour. |
11379 | * |
11380 | * Since: 3.6 |
11381 | */ |
11382 | |
11383 | void |
11384 | ctk_text_view_set_input_hints (CtkTextView *text_view, |
11385 | CtkInputHints hints) |
11386 | |
11387 | { |
11388 | g_return_if_fail (CTK_IS_TEXT_VIEW (text_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return; } } while (0); |
11389 | |
11390 | if (ctk_text_view_get_input_hints (text_view) != hints) |
11391 | { |
11392 | g_object_set (G_OBJECT (text_view->priv->im_context)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view->priv->im_context)), (((GType) ((20) << (2)))))))), |
11393 | "input-hints", hints, |
11394 | NULL((void*)0)); |
11395 | |
11396 | g_object_notify (G_OBJECT (text_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), (((GType) ((20) << (2)))))))), "input-hints"); |
11397 | } |
11398 | } |
11399 | |
11400 | /** |
11401 | * ctk_text_view_get_input_hints: |
11402 | * @text_view: a #CtkTextView |
11403 | * |
11404 | * Gets the value of the #CtkTextView:input-hints property. |
11405 | * |
11406 | * Since: 3.6 |
11407 | */ |
11408 | |
11409 | CtkInputHints |
11410 | ctk_text_view_get_input_hints (CtkTextView *text_view) |
11411 | { |
11412 | CtkInputHints hints; |
11413 | |
11414 | g_return_val_if_fail (CTK_IS_TEXT_VIEW (text_view), CTK_INPUT_HINT_NONE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return (CTK_INPUT_HINT_NONE ); } } while (0); |
11415 | |
11416 | g_object_get (G_OBJECT (text_view->priv->im_context)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view->priv->im_context)), (((GType) ((20) << (2)))))))), |
11417 | "input-hints", &hints, |
11418 | NULL((void*)0)); |
11419 | |
11420 | return hints; |
11421 | } |
11422 | |
11423 | /** |
11424 | * ctk_text_view_set_monospace: |
11425 | * @text_view: a #CtkTextView |
11426 | * @monospace: %TRUE to request monospace styling |
11427 | * |
11428 | * Sets the #CtkTextView:monospace property, which |
11429 | * indicates that the text view should use monospace |
11430 | * fonts. |
11431 | * |
11432 | * Since: 3.16 |
11433 | */ |
11434 | void |
11435 | ctk_text_view_set_monospace (CtkTextView *text_view, |
11436 | gboolean monospace) |
11437 | { |
11438 | CtkStyleContext *context; |
11439 | gboolean has_monospace; |
11440 | |
11441 | g_return_if_fail (CTK_IS_TEXT_VIEW (text_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return; } } while (0); |
11442 | |
11443 | context = ctk_widget_get_style_context (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
11444 | has_monospace = ctk_style_context_has_class (context, CTK_STYLE_CLASS_MONOSPACE"monospace"); |
11445 | |
11446 | if (has_monospace != monospace) |
11447 | { |
11448 | if (monospace) |
11449 | ctk_style_context_add_class (context, CTK_STYLE_CLASS_MONOSPACE"monospace"); |
11450 | else |
11451 | ctk_style_context_remove_class (context, CTK_STYLE_CLASS_MONOSPACE"monospace"); |
11452 | g_object_notify (G_OBJECT (text_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), (((GType) ((20) << (2)))))))), "monospace"); |
11453 | } |
11454 | } |
11455 | |
11456 | /** |
11457 | * ctk_text_view_get_monospace: |
11458 | * @text_view: a #CtkTextView |
11459 | * |
11460 | * Gets the value of the #CtkTextView:monospace property. |
11461 | * |
11462 | * Return: %TRUE if monospace fonts are desired |
11463 | * |
11464 | * Since: 3.16 |
11465 | */ |
11466 | gboolean |
11467 | ctk_text_view_get_monospace (CtkTextView *text_view) |
11468 | { |
11469 | CtkStyleContext *context; |
11470 | |
11471 | g_return_val_if_fail (CTK_IS_TEXT_VIEW (text_view), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((text_view)); GType __t = ((ctk_text_view_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_TEXT_VIEW (text_view)"); return ((0)); } } while ( 0); |
11472 | |
11473 | context = ctk_widget_get_style_context (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
11474 | |
11475 | return ctk_style_context_has_class (context, CTK_STYLE_CLASS_MONOSPACE"monospace"); |
11476 | } |
11477 | |
11478 | static void |
11479 | ctk_text_view_insert_emoji (CtkTextView *text_view) |
11480 | { |
11481 | CtkWidget *chooser; |
11482 | CtkTextIter iter; |
11483 | CdkRectangle rect; |
11484 | CtkTextBuffer *buffer; |
11485 | |
11486 | if (ctk_text_view_get_input_hints (text_view) & CTK_INPUT_HINT_NO_EMOJI) |
11487 | return; |
11488 | |
11489 | if (ctk_widget_get_ancestor (CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ())))))), CTK_TYPE_EMOJI_CHOOSER(ctk_emoji_chooser_get_type ())) != NULL((void*)0)) |
11490 | return; |
11491 | |
11492 | chooser = CTK_WIDGET (g_object_get_data (G_OBJECT (text_view), "ctk-emoji-chooser"))((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((g_object_get_data (((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((text_view)), (((GType) ((20) << (2 )))))))), "ctk-emoji-chooser"))), ((ctk_widget_get_type ()))) ))); |
11493 | if (!chooser) |
11494 | { |
11495 | chooser = ctk_emoji_chooser_new (); |
11496 | g_object_set_data (G_OBJECT (text_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), (((GType) ((20) << (2)))))))), "ctk-emoji-chooser", chooser); |
11497 | |
11498 | ctk_popover_set_relative_to (CTK_POPOVER (chooser)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((chooser)), ((ctk_popover_get_type ())))))), CTK_WIDGET (text_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((text_view)), ((ctk_widget_get_type ()))))))); |
11499 | g_signal_connect_swapped (chooser, "emoji-picked",g_signal_connect_data ((chooser), ("emoji-picked"), (((GCallback ) (ctk_text_view_insert_at_cursor))), (text_view), ((void*)0) , G_CONNECT_SWAPPED) |
11500 | G_CALLBACK (ctk_text_view_insert_at_cursor), text_view)g_signal_connect_data ((chooser), ("emoji-picked"), (((GCallback ) (ctk_text_view_insert_at_cursor))), (text_view), ((void*)0) , G_CONNECT_SWAPPED); |
11501 | } |
11502 | |
11503 | buffer = get_buffer (text_view); |
11504 | ctk_text_buffer_get_iter_at_mark (buffer, &iter, |
11505 | ctk_text_buffer_get_insert (buffer)); |
11506 | |
11507 | ctk_text_view_get_iter_location (text_view, &iter, (CdkRectangle *) &rect); |
11508 | ctk_text_view_buffer_to_window_coords (text_view, CTK_TEXT_WINDOW_TEXT, |
11509 | rect.x, rect.y, &rect.x, &rect.y); |
11510 | _text_window_to_widget_coords (text_view, &rect.x, &rect.y); |
11511 | |
11512 | ctk_popover_set_pointing_to (CTK_POPOVER (chooser)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((chooser)), ((ctk_popover_get_type ())))))), &rect); |
11513 | |
11514 | ctk_popover_popup (CTK_POPOVER (chooser)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((chooser)), ((ctk_popover_get_type ()))))))); |
11515 | } |