1 | /* GTK - The GIMP Toolkit |
2 | * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald |
3 | * |
4 | * This library is free software; you can redistribute it and/or |
5 | * modify it under the terms of the GNU Lesser General Public |
6 | * License as published by the Free Software Foundation; either |
7 | * version 2 of the License, or (at your option) any later version. |
8 | * |
9 | * This library is distributed in the hope that it will be useful, |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | * Lesser General Public License for more details. |
13 | * |
14 | * You should have received a copy of the GNU Lesser General Public |
15 | * License along with this library. If not, see <http://www.gnu.org/licenses/>. |
16 | */ |
17 | |
18 | /* |
19 | * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS |
20 | * file for a list of people on the GTK+ Team. See the ChangeLog |
21 | * files for a list of changes. These files are distributed with |
22 | * GTK+ at ftp://ftp.gtk.org/pub/gtk/. |
23 | */ |
24 | |
25 | /** |
26 | * GtkEditable: |
27 | * |
28 | * `GtkEditable` is an interface for text editing widgets. |
29 | * |
30 | * Typical examples of editable widgets are [class@Gtk.Entry] and |
31 | * [class@Gtk.SpinButton]. It contains functions for generically manipulating |
32 | * an editable widget, a large number of action signals used for key bindings, |
33 | * and several signals that an application can connect to modify the behavior |
34 | * of a widget. |
35 | * |
36 | * As an example of the latter usage, by connecting the following handler to |
37 | * [signal@Gtk.Editable::insert-text], an application can convert all entry |
38 | * into a widget into uppercase. |
39 | * |
40 | * ## Forcing entry to uppercase. |
41 | * |
42 | * ```c |
43 | * #include <ctype.h> |
44 | * |
45 | * void |
46 | * insert_text_handler (GtkEditable *editable, |
47 | * const char *text, |
48 | * int length, |
49 | * int *position, |
50 | * gpointer data) |
51 | * { |
52 | * char *result = g_utf8_strup (text, length); |
53 | * |
54 | * g_signal_handlers_block_by_func (editable, |
55 | * (gpointer) insert_text_handler, data); |
56 | * gtk_editable_insert_text (editable, result, length, position); |
57 | * g_signal_handlers_unblock_by_func (editable, |
58 | * (gpointer) insert_text_handler, data); |
59 | * |
60 | * g_signal_stop_emission_by_name (editable, "insert_text"); |
61 | * |
62 | * g_free (result); |
63 | * } |
64 | * ``` |
65 | * |
66 | * ## Implementing GtkEditable |
67 | * |
68 | * The most likely scenario for implementing `GtkEditable` on your own widget |
69 | * is that you will embed a `GtkText` inside a complex widget, and want to |
70 | * delegate the editable functionality to that text widget. `GtkEditable` |
71 | * provides some utility functions to make this easy. |
72 | * |
73 | * In your class_init function, call [func@Gtk.Editable.install_properties], |
74 | * passing the first available property ID: |
75 | * |
76 | * ```c |
77 | * static void |
78 | * my_class_init (MyClass *class) |
79 | * { |
80 | * ... |
81 | * g_object_class_install_properties (object_class, NUM_PROPERTIES, props); |
82 | * gtk_editable_install_properties (object_clas, NUM_PROPERTIES); |
83 | * ... |
84 | * } |
85 | * ``` |
86 | * |
87 | * In your interface_init function for the `GtkEditable` interface, provide |
88 | * an implementation for the get_delegate vfunc that returns your text widget: |
89 | * |
90 | * ```c |
91 | * GtkEditable * |
92 | * get_editable_delegate (GtkEditable *editable) |
93 | * { |
94 | * return GTK_EDITABLE (MY_WIDGET (editable)->text_widget); |
95 | * } |
96 | * |
97 | * static void |
98 | * my_editable_init (GtkEditableInterface *iface) |
99 | * { |
100 | * iface->get_delegate = get_editable_delegate; |
101 | * } |
102 | * ``` |
103 | * |
104 | * You don't need to provide any other vfuncs. The default implementations |
105 | * work by forwarding to the delegate that the GtkEditableInterface.get_delegate() |
106 | * vfunc returns. |
107 | * |
108 | * In your instance_init function, create your text widget, and then call |
109 | * [method@Gtk.Editable.init_delegate]: |
110 | * |
111 | * ```c |
112 | * static void |
113 | * my_widget_init (MyWidget *self) |
114 | * { |
115 | * ... |
116 | * self->text_widget = gtk_text_new (); |
117 | * gtk_editable_init_delegate (GTK_EDITABLE (self)); |
118 | * ... |
119 | * } |
120 | * ``` |
121 | * |
122 | * In your dispose function, call [method@Gtk.Editable.finish_delegate] before |
123 | * destroying your text widget: |
124 | * |
125 | * ```c |
126 | * static void |
127 | * my_widget_dispose (GObject *object) |
128 | * { |
129 | * ... |
130 | * gtk_editable_finish_delegate (GTK_EDITABLE (self)); |
131 | * g_clear_pointer (&self->text_widget, gtk_widget_unparent); |
132 | * ... |
133 | * } |
134 | * ``` |
135 | * |
136 | * Finally, use [func@Gtk.Editable.delegate_set_property] in your `set_property` |
137 | * function (and similar for `get_property`), to set the editable properties: |
138 | * |
139 | * ```c |
140 | * ... |
141 | * if (gtk_editable_delegate_set_property (object, prop_id, value, pspec)) |
142 | * return; |
143 | * |
144 | * switch (prop_id) |
145 | * ... |
146 | * ``` |
147 | * |
148 | * It is important to note that if you create a `GtkEditable` that uses |
149 | * a delegate, the low level [signal@Gtk.Editable::insert-text] and |
150 | * [signal@Gtk.Editable::delete-text] signals will be propagated from the |
151 | * "wrapper" editable to the delegate, but they will not be propagated from |
152 | * the delegate to the "wrapper" editable, as they would cause an infinite |
153 | * recursion. If you wish to connect to the [signal@Gtk.Editable::insert-text] |
154 | * and [signal@Gtk.Editable::delete-text] signals, you will need to connect |
155 | * to them on the delegate obtained via [method@Gtk.Editable.get_delegate]. |
156 | */ |
157 | |
158 | #include "config.h" |
159 | #include <string.h> |
160 | |
161 | #include "gtkeditable.h" |
162 | #include "gtkentrybuffer.h" |
163 | #include "gtkmarshalers.h" |
164 | #include "gtkintl.h" |
165 | #include "gtkprivate.h" |
166 | |
167 | G_DEFINE_INTERFACE (GtkEditable, gtk_editable, GTK_TYPE_WIDGET) |
168 | |
169 | enum { |
170 | CHANGED, |
171 | DELETE_TEXT, |
172 | INSERT_TEXT, |
173 | N_SIGNALS |
174 | }; |
175 | |
176 | static GQuark quark_editable_data; |
177 | static guint signals[N_SIGNALS]; |
178 | |
179 | static GtkEditable * |
180 | get_delegate (GtkEditable *editable) |
181 | { |
182 | GtkEditableInterface *iface = GTK_EDITABLE_GET_IFACE (editable); |
183 | |
184 | if (iface->get_delegate) |
185 | return iface->get_delegate (editable); |
186 | |
187 | return NULL; |
188 | } |
189 | |
190 | static void |
191 | gtk_editable_default_do_insert_text (GtkEditable *editable, |
192 | const char *text, |
193 | int length, |
194 | int *position) |
195 | { |
196 | g_signal_emit (instance: editable, signal_id: signals[INSERT_TEXT], detail: 0, text, length, position); |
197 | } |
198 | |
199 | #define warn_no_delegate(func) \ |
200 | g_critical ("GtkEditable %s: default implementation called without a delegate", func); |
201 | |
202 | static void |
203 | gtk_editable_default_insert_text (GtkEditable *editable, |
204 | const char *text, |
205 | int length, |
206 | int *position) |
207 | { |
208 | GtkEditable *delegate = get_delegate (editable); |
209 | |
210 | if (delegate) |
211 | gtk_editable_insert_text (editable: delegate, text, length, position); |
212 | else |
213 | warn_no_delegate ("insert_text" ); |
214 | } |
215 | |
216 | static void |
217 | gtk_editable_default_do_delete_text (GtkEditable *editable, |
218 | int start_pos, |
219 | int end_pos) |
220 | { |
221 | g_signal_emit (instance: editable, signal_id: signals[DELETE_TEXT], detail: 0, start_pos, end_pos); |
222 | } |
223 | |
224 | static void |
225 | gtk_editable_default_delete_text (GtkEditable *editable, |
226 | int start_pos, |
227 | int end_pos) |
228 | { |
229 | GtkEditable *delegate = get_delegate (editable); |
230 | |
231 | if (delegate) |
232 | gtk_editable_delete_text (editable: delegate, start_pos, end_pos); |
233 | else |
234 | warn_no_delegate ("delete_text" ); |
235 | } |
236 | |
237 | static const char * |
238 | gtk_editable_default_get_text (GtkEditable *editable) |
239 | { |
240 | GtkEditable *delegate = get_delegate (editable); |
241 | |
242 | if (delegate) |
243 | return gtk_editable_get_text (editable: delegate); |
244 | else |
245 | warn_no_delegate ("get_text" ); |
246 | |
247 | return NULL; |
248 | } |
249 | |
250 | static void |
251 | gtk_editable_default_set_selection_bounds (GtkEditable *editable, |
252 | int start_pos, |
253 | int end_pos) |
254 | { |
255 | GtkEditable *delegate = get_delegate (editable); |
256 | |
257 | if (delegate) |
258 | gtk_editable_select_region (editable: delegate, start_pos, end_pos); |
259 | else |
260 | warn_no_delegate ("select_region" ); |
261 | } |
262 | |
263 | static gboolean |
264 | gtk_editable_default_get_selection_bounds (GtkEditable *editable, |
265 | int *start_pos, |
266 | int *end_pos) |
267 | { |
268 | GtkEditable *delegate = get_delegate (editable); |
269 | |
270 | if (delegate) |
271 | return gtk_editable_get_selection_bounds (editable: delegate, start_pos, end_pos); |
272 | else |
273 | warn_no_delegate ("select_region" ); |
274 | |
275 | return FALSE; |
276 | } |
277 | |
278 | static void |
279 | gtk_editable_default_init (GtkEditableInterface *iface) |
280 | { |
281 | quark_editable_data = g_quark_from_static_string (string: "GtkEditable-data" ); |
282 | |
283 | iface->insert_text = gtk_editable_default_insert_text; |
284 | iface->delete_text = gtk_editable_default_delete_text; |
285 | iface->get_text = gtk_editable_default_get_text; |
286 | iface->do_insert_text = gtk_editable_default_do_insert_text; |
287 | iface->do_delete_text = gtk_editable_default_do_delete_text; |
288 | iface->get_selection_bounds = gtk_editable_default_get_selection_bounds; |
289 | iface->set_selection_bounds = gtk_editable_default_set_selection_bounds; |
290 | |
291 | /** |
292 | * GtkEditable::insert-text: |
293 | * @editable: the object which received the signal |
294 | * @text: the new text to insert |
295 | * @length: the length of the new text, in bytes, |
296 | * or -1 if new_text is nul-terminated |
297 | * @position: (inout) (type int): the position, in characters, |
298 | * at which to insert the new text. this is an in-out |
299 | * parameter. After the signal emission is finished, it |
300 | * should point after the newly inserted text. |
301 | * |
302 | * Emitted when text is inserted into the widget by the user. |
303 | * |
304 | * The default handler for this signal will normally be responsible |
305 | * for inserting the text, so by connecting to this signal and then |
306 | * stopping the signal with g_signal_stop_emission(), it is possible |
307 | * to modify the inserted text, or prevent it from being inserted entirely. |
308 | */ |
309 | signals[INSERT_TEXT] = |
310 | g_signal_new (I_("insert-text" ), |
311 | GTK_TYPE_EDITABLE, |
312 | signal_flags: G_SIGNAL_RUN_LAST, |
313 | G_STRUCT_OFFSET (GtkEditableInterface, insert_text), |
314 | NULL, NULL, |
315 | c_marshaller: _gtk_marshal_VOID__STRING_INT_POINTER, |
316 | G_TYPE_NONE, n_params: 3, |
317 | G_TYPE_STRING, |
318 | G_TYPE_INT, |
319 | G_TYPE_POINTER); |
320 | g_signal_set_va_marshaller (signal_id: signals[INSERT_TEXT], |
321 | G_TYPE_FROM_INTERFACE (iface), |
322 | va_marshaller: _gtk_marshal_VOID__STRING_INT_POINTERv); |
323 | |
324 | /** |
325 | * GtkEditable::delete-text: |
326 | * @editable: the object which received the signal |
327 | * @start_pos: the starting position |
328 | * @end_pos: the end position |
329 | * |
330 | * Emitted when text is deleted from the widget by the user. |
331 | * |
332 | * The default handler for this signal will normally be responsible for |
333 | * deleting the text, so by connecting to this signal and then stopping |
334 | * the signal with g_signal_stop_emission(), it is possible to modify the |
335 | * range of deleted text, or prevent it from being deleted entirely. |
336 | * |
337 | * The @start_pos and @end_pos parameters are interpreted as for |
338 | * [method@Gtk.Editable.delete_text]. |
339 | */ |
340 | signals[DELETE_TEXT] = |
341 | g_signal_new (I_("delete-text" ), |
342 | GTK_TYPE_EDITABLE, |
343 | signal_flags: G_SIGNAL_RUN_LAST, |
344 | G_STRUCT_OFFSET (GtkEditableInterface, delete_text), |
345 | NULL, NULL, |
346 | c_marshaller: _gtk_marshal_VOID__INT_INT, |
347 | G_TYPE_NONE, n_params: 2, |
348 | G_TYPE_INT, |
349 | G_TYPE_INT); |
350 | g_signal_set_va_marshaller (signal_id: signals[DELETE_TEXT], |
351 | G_TYPE_FROM_INTERFACE (iface), |
352 | va_marshaller: _gtk_marshal_VOID__INT_INTv); |
353 | |
354 | /** |
355 | * GtkEditable::changed: |
356 | * @editable: the object which received the signal |
357 | * |
358 | * Emitted at the end of a single user-visible operation on the |
359 | * contents. |
360 | * |
361 | * E.g., a paste operation that replaces the contents of the |
362 | * selection will cause only one signal emission (even though it |
363 | * is implemented by first deleting the selection, then inserting |
364 | * the new content, and may cause multiple ::notify::text signals |
365 | * to be emitted). |
366 | */ |
367 | signals[CHANGED] = |
368 | g_signal_new (I_("changed" ), |
369 | GTK_TYPE_EDITABLE, |
370 | signal_flags: G_SIGNAL_RUN_LAST, |
371 | G_STRUCT_OFFSET (GtkEditableInterface, changed), |
372 | NULL, NULL, |
373 | NULL, |
374 | G_TYPE_NONE, n_params: 0); |
375 | |
376 | /** |
377 | * GtkEditable:text: (attributes org.gtk.Property.get=gtk_editable_get_text org.gtk.Property.set=gtk_editable_set_text) |
378 | * |
379 | * The contents of the entry. |
380 | */ |
381 | g_object_interface_install_property (g_iface: iface, |
382 | pspec: g_param_spec_string (name: "text" , |
383 | P_("Text" ), |
384 | P_("The contents of the entry" ), |
385 | default_value: "" , |
386 | GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY)); |
387 | |
388 | /** |
389 | * GtkEditable:cursor-position: (attributes org.gtk.Property.get=gtk_editable_get_position org.gtk.Property.set=gtk_editable_set_position) |
390 | * |
391 | * The current position of the insertion cursor in chars. |
392 | */ |
393 | g_object_interface_install_property (g_iface: iface, |
394 | pspec: g_param_spec_int (name: "cursor-position" , |
395 | P_("Cursor Position" ), |
396 | P_("The current position of the insertion cursor in chars" ), |
397 | minimum: 0, GTK_ENTRY_BUFFER_MAX_SIZE, |
398 | default_value: 0, |
399 | GTK_PARAM_READABLE)); |
400 | |
401 | /** |
402 | * GtkEditable:enable-undo: (attributes org.gtk.Property.get=gtk_editable_get_enable_undo org.gtk.Property.setg=gtk_editable_set_enable_undo) |
403 | * |
404 | * If undo/redo should be enabled for the editable. |
405 | */ |
406 | g_object_interface_install_property (g_iface: iface, |
407 | pspec: g_param_spec_boolean (name: "enable-undo" , |
408 | P_("Enable Undo" ), |
409 | P_("If undo/redo should be enabled for the editable" ), |
410 | TRUE, |
411 | GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY)); |
412 | |
413 | /** |
414 | * GtkEditable:selection-bound: |
415 | * |
416 | * The position of the opposite end of the selection from the cursor in chars. |
417 | */ |
418 | g_object_interface_install_property (g_iface: iface, |
419 | pspec: g_param_spec_int (name: "selection-bound" , |
420 | P_("Selection Bound" ), |
421 | P_("The position of the opposite end of the selection from the cursor in chars" ), |
422 | minimum: 0, GTK_ENTRY_BUFFER_MAX_SIZE, |
423 | default_value: 0, |
424 | GTK_PARAM_READABLE)); |
425 | |
426 | /** |
427 | * GtkEditable:editable: (attributes org.gtk.Property.get=gtk_editable_get_editable org.gtk.Property.set=gtk_editable_set_editable) |
428 | * |
429 | * Whether the entry contents can be edited. |
430 | */ |
431 | g_object_interface_install_property (g_iface: iface, |
432 | pspec: g_param_spec_boolean (name: "editable" , |
433 | P_("Editable" ), |
434 | P_("Whether the entry contents can be edited" ), |
435 | TRUE, |
436 | GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY)); |
437 | |
438 | /** |
439 | * GtkEditable:width-chars: (attributes org.gtk.Property.get=gtk_editable_get_width_chars org.gtk.Property.set=gtk_editable_set_width_chars) |
440 | * |
441 | * Number of characters to leave space for in the entry. |
442 | */ |
443 | g_object_interface_install_property (g_iface: iface, |
444 | pspec: g_param_spec_int (name: "width-chars" , |
445 | P_("Width in chars" ), |
446 | P_("Number of characters to leave space for in the entry" ), |
447 | minimum: -1, G_MAXINT, |
448 | default_value: -1, |
449 | GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY)); |
450 | |
451 | /** |
452 | * GtkEditable:max-width-chars: (attributes org.gtk.Property.get=gtk_editable_get_max_width_chars org.gtk.Property.set=gtk_editable_set_max_width_chars) |
453 | * |
454 | * The desired maximum width of the entry, in characters. |
455 | */ |
456 | g_object_interface_install_property (g_iface: iface, |
457 | pspec: g_param_spec_int (name: "max-width-chars" , |
458 | P_("Maximum width in characters" ), |
459 | P_("The desired maximum width of the entry, in characters" ), |
460 | minimum: -1, G_MAXINT, |
461 | default_value: -1, |
462 | GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY)); |
463 | |
464 | /** |
465 | * GtkEditable:xalign: (attributes org.gtk.Property.get=gtk_editable_get_alignment org.gtk.Property.set=gtk_editable_set_alignment) |
466 | * |
467 | * The horizontal alignment, from 0 (left) to 1 (right). |
468 | * |
469 | * Reversed for RTL layouts. |
470 | */ |
471 | g_object_interface_install_property (g_iface: iface, |
472 | pspec: g_param_spec_float (name: "xalign" , |
473 | P_("X align" ), |
474 | P_("The horizontal alignment, from 0 (left) to 1 (right). Reversed for RTL layouts." ), |
475 | minimum: 0.0, maximum: 1.0, |
476 | default_value: 0.0, |
477 | GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY)); |
478 | } |
479 | |
480 | /** |
481 | * gtk_editable_insert_text: (virtual do_insert_text) |
482 | * @editable: a `GtkEditable` |
483 | * @text: the text to append |
484 | * @length: the length of the text in bytes, or -1 |
485 | * @position: (inout): location of the position text will be inserted at |
486 | * |
487 | * Inserts @length bytes of @text into the contents of the |
488 | * widget, at position @position. |
489 | * |
490 | * Note that the position is in characters, not in bytes. |
491 | * The function updates @position to point after the newly |
492 | * inserted text. |
493 | */ |
494 | void |
495 | gtk_editable_insert_text (GtkEditable *editable, |
496 | const char *text, |
497 | int length, |
498 | int *position) |
499 | { |
500 | g_return_if_fail (GTK_IS_EDITABLE (editable)); |
501 | g_return_if_fail (position != NULL); |
502 | |
503 | if (length < 0) |
504 | length = strlen (s: text); |
505 | |
506 | GTK_EDITABLE_GET_IFACE (editable)->do_insert_text (editable, text, length, position); |
507 | } |
508 | |
509 | /** |
510 | * gtk_editable_delete_text: (virtual do_delete_text) |
511 | * @editable: a `GtkEditable` |
512 | * @start_pos: start position |
513 | * @end_pos: end position |
514 | * |
515 | * Deletes a sequence of characters. |
516 | * |
517 | * The characters that are deleted are those characters at positions |
518 | * from @start_pos up to, but not including @end_pos. If @end_pos is |
519 | * negative, then the characters deleted are those from @start_pos to |
520 | * the end of the text. |
521 | * |
522 | * Note that the positions are specified in characters, not bytes. |
523 | */ |
524 | void |
525 | gtk_editable_delete_text (GtkEditable *editable, |
526 | int start_pos, |
527 | int end_pos) |
528 | { |
529 | g_return_if_fail (GTK_IS_EDITABLE (editable)); |
530 | |
531 | GTK_EDITABLE_GET_IFACE (editable)->do_delete_text (editable, start_pos, end_pos); |
532 | } |
533 | |
534 | /** |
535 | * gtk_editable_get_chars: |
536 | * @editable: a `GtkEditable` |
537 | * @start_pos: start of text |
538 | * @end_pos: end of text |
539 | * |
540 | * Retrieves a sequence of characters. |
541 | * |
542 | * The characters that are retrieved are those characters at positions |
543 | * from @start_pos up to, but not including @end_pos. If @end_pos is negative, |
544 | * then the characters retrieved are those characters from @start_pos to |
545 | * the end of the text. |
546 | * |
547 | * Note that positions are specified in characters, not bytes. |
548 | * |
549 | * Returns: (transfer full): a pointer to the contents of the widget as a |
550 | * string. This string is allocated by the `GtkEditable` implementation |
551 | * and should be freed by the caller. |
552 | */ |
553 | char * |
554 | gtk_editable_get_chars (GtkEditable *editable, |
555 | int start_pos, |
556 | int end_pos) |
557 | { |
558 | const char *text; |
559 | int length; |
560 | int start_index,end_index; |
561 | |
562 | g_return_val_if_fail (GTK_IS_EDITABLE (editable), NULL); |
563 | |
564 | text = GTK_EDITABLE_GET_IFACE (editable)->get_text (editable); |
565 | length = g_utf8_strlen (p: text, max: -1); |
566 | |
567 | if (end_pos < 0) |
568 | end_pos = length; |
569 | |
570 | start_pos = MIN (length, start_pos); |
571 | end_pos = MIN (length, end_pos); |
572 | |
573 | start_index = g_utf8_offset_to_pointer (str: text, offset: start_pos) - text; |
574 | end_index = g_utf8_offset_to_pointer (str: text, offset: end_pos) - text; |
575 | |
576 | return g_strndup (str: text + start_index, n: end_index - start_index); |
577 | } |
578 | |
579 | /** |
580 | * gtk_editable_get_text: (attributes org.gtk.Method.get_property=text) |
581 | * @editable: a `GtkEditable` |
582 | * |
583 | * Retrieves the contents of @editable. |
584 | * |
585 | * The returned string is owned by GTK and must not be modified or freed. |
586 | * |
587 | * Returns: (transfer none): a pointer to the contents of the editable |
588 | */ |
589 | const char * |
590 | gtk_editable_get_text (GtkEditable *editable) |
591 | { |
592 | g_return_val_if_fail (GTK_IS_EDITABLE (editable), NULL); |
593 | |
594 | return GTK_EDITABLE_GET_IFACE (editable)->get_text (editable); |
595 | } |
596 | |
597 | /** |
598 | * gtk_editable_set_text: (attributes org.gtk.Method.set_property=text) |
599 | * @editable: a `GtkEditable` |
600 | * @text: the text to set |
601 | * |
602 | * Sets the text in the editable to the given value. |
603 | * |
604 | * This is replacing the current contents. |
605 | */ |
606 | void |
607 | gtk_editable_set_text (GtkEditable *editable, |
608 | const char *text) |
609 | { |
610 | int pos; |
611 | |
612 | g_return_if_fail (GTK_IS_EDITABLE (editable)); |
613 | |
614 | g_object_freeze_notify (G_OBJECT (editable)); |
615 | gtk_editable_delete_text (editable, start_pos: 0, end_pos: -1); |
616 | pos = 0; |
617 | gtk_editable_insert_text (editable, text, length: -1, position: &pos); |
618 | g_object_thaw_notify (G_OBJECT (editable)); |
619 | } |
620 | |
621 | /** |
622 | * gtk_editable_set_position: (attributes org.gtk.Method.set_property=cursor-position) |
623 | * @editable: a `GtkEditable` |
624 | * @position: the position of the cursor |
625 | * |
626 | * Sets the cursor position in the editable to the given value. |
627 | * |
628 | * The cursor is displayed before the character with the given (base 0) |
629 | * index in the contents of the editable. The value must be less than |
630 | * or equal to the number of characters in the editable. A value of -1 |
631 | * indicates that the position should be set after the last character |
632 | * of the editable. Note that @position is in characters, not in bytes. |
633 | */ |
634 | void |
635 | gtk_editable_set_position (GtkEditable *editable, |
636 | int position) |
637 | { |
638 | g_return_if_fail (GTK_IS_EDITABLE (editable)); |
639 | |
640 | GTK_EDITABLE_GET_IFACE (editable)->set_selection_bounds (editable, position, position); |
641 | } |
642 | |
643 | /** |
644 | * gtk_editable_get_position: (attributes org.gtk.Method.get_property=cursor-position) |
645 | * @editable: a `GtkEditable` |
646 | * |
647 | * Retrieves the current position of the cursor relative |
648 | * to the start of the content of the editable. |
649 | * |
650 | * Note that this position is in characters, not in bytes. |
651 | * |
652 | * Returns: the cursor position |
653 | */ |
654 | int |
655 | gtk_editable_get_position (GtkEditable *editable) |
656 | { |
657 | int start, end; |
658 | |
659 | g_return_val_if_fail (GTK_IS_EDITABLE (editable), 0); |
660 | |
661 | GTK_EDITABLE_GET_IFACE (editable)->get_selection_bounds (editable, &start, &end); |
662 | |
663 | return end; |
664 | } |
665 | |
666 | /** |
667 | * gtk_editable_get_selection_bounds: |
668 | * @editable: a `GtkEditable` |
669 | * @start_pos: (out) (optional): location to store the starting position |
670 | * @end_pos: (out) (optional): location to store the end position |
671 | * |
672 | * Retrieves the selection bound of the editable. |
673 | * |
674 | * @start_pos will be filled with the start of the selection and |
675 | * @end_pos with end. If no text was selected both will be identical |
676 | * and %FALSE will be returned. |
677 | * |
678 | * Note that positions are specified in characters, not bytes. |
679 | * |
680 | * Returns: %TRUE if there is a non-empty selection, %FALSE otherwise |
681 | */ |
682 | gboolean |
683 | gtk_editable_get_selection_bounds (GtkEditable *editable, |
684 | int *start_pos, |
685 | int *end_pos) |
686 | { |
687 | int tmp_start, tmp_end; |
688 | gboolean result; |
689 | |
690 | g_return_val_if_fail (GTK_IS_EDITABLE (editable), FALSE); |
691 | |
692 | result = GTK_EDITABLE_GET_IFACE (editable)->get_selection_bounds (editable, &tmp_start, &tmp_end); |
693 | |
694 | if (start_pos) |
695 | *start_pos = MIN (tmp_start, tmp_end); |
696 | if (end_pos) |
697 | *end_pos = MAX (tmp_start, tmp_end); |
698 | |
699 | return result; |
700 | } |
701 | |
702 | /** |
703 | * gtk_editable_delete_selection: |
704 | * @editable: a `GtkEditable` |
705 | * |
706 | * Deletes the currently selected text of the editable. |
707 | * |
708 | * This call doesn’t do anything if there is no selected text. |
709 | */ |
710 | void |
711 | gtk_editable_delete_selection (GtkEditable *editable) |
712 | { |
713 | int start, end; |
714 | |
715 | g_return_if_fail (GTK_IS_EDITABLE (editable)); |
716 | |
717 | if (gtk_editable_get_selection_bounds (editable, start_pos: &start, end_pos: &end)) |
718 | gtk_editable_delete_text (editable, start_pos: start, end_pos: end); |
719 | } |
720 | |
721 | /** |
722 | * gtk_editable_select_region: (virtual set_selection_bounds) |
723 | * @editable: a `GtkEditable` |
724 | * @start_pos: start of region |
725 | * @end_pos: end of region |
726 | * |
727 | * Selects a region of text. |
728 | * |
729 | * The characters that are selected are those characters at positions |
730 | * from @start_pos up to, but not including @end_pos. If @end_pos is |
731 | * negative, then the characters selected are those characters from |
732 | * @start_pos to the end of the text. |
733 | * |
734 | * Note that positions are specified in characters, not bytes. |
735 | */ |
736 | void |
737 | gtk_editable_select_region (GtkEditable *editable, |
738 | int start_pos, |
739 | int end_pos) |
740 | { |
741 | g_return_if_fail (GTK_IS_EDITABLE (editable)); |
742 | |
743 | GTK_EDITABLE_GET_IFACE (editable)->set_selection_bounds (editable, start_pos, end_pos); |
744 | } |
745 | |
746 | /** |
747 | * gtk_editable_set_editable: (attributes org.gtk.Method.set_property=editable) |
748 | * @editable: a `GtkEditable` |
749 | * @is_editable: %TRUE if the user is allowed to edit the text |
750 | * in the widget |
751 | * |
752 | * Determines if the user can edit the text in the editable widget. |
753 | */ |
754 | void |
755 | gtk_editable_set_editable (GtkEditable *editable, |
756 | gboolean is_editable) |
757 | { |
758 | g_return_if_fail (GTK_IS_EDITABLE (editable)); |
759 | |
760 | g_object_set (object: editable, first_property_name: "editable" , is_editable, NULL); |
761 | } |
762 | |
763 | /** |
764 | * gtk_editable_get_editable: (attributes org.gtk.Method.get_property=editable) |
765 | * @editable: a `GtkEditable` |
766 | * |
767 | * Retrieves whether @editable is editable. |
768 | * |
769 | * Returns: %TRUE if @editable is editable. |
770 | */ |
771 | gboolean |
772 | gtk_editable_get_editable (GtkEditable *editable) |
773 | { |
774 | gboolean is_editable; |
775 | |
776 | g_return_val_if_fail (GTK_IS_EDITABLE (editable), FALSE); |
777 | |
778 | g_object_get (object: editable, first_property_name: "editable" , &is_editable, NULL); |
779 | |
780 | return is_editable; |
781 | } |
782 | |
783 | |
784 | /** |
785 | * gtk_editable_get_alignment: (attributes org.gtk.Method.get_property=xalign) |
786 | * @editable: a `GtkEditable` |
787 | * |
788 | * Gets the alignment of the editable. |
789 | * |
790 | * Returns: the alignment |
791 | */ |
792 | float |
793 | gtk_editable_get_alignment (GtkEditable *editable) |
794 | { |
795 | float xalign; |
796 | |
797 | g_return_val_if_fail (GTK_IS_EDITABLE (editable), 0); |
798 | |
799 | g_object_get (object: editable, first_property_name: "xalign" , &xalign, NULL); |
800 | |
801 | return xalign; |
802 | } |
803 | |
804 | /** |
805 | * gtk_editable_set_alignment: (attributes org.gtk.Method.set_property=xalign) |
806 | * @editable: a `GtkEditable` |
807 | * @xalign: The horizontal alignment, from 0 (left) to 1 (right). |
808 | * Reversed for RTL layouts |
809 | * |
810 | * Sets the alignment for the contents of the editable. |
811 | * |
812 | * This controls the horizontal positioning of the contents when |
813 | * the displayed text is shorter than the width of the editable. |
814 | */ |
815 | void |
816 | gtk_editable_set_alignment (GtkEditable *editable, |
817 | float xalign) |
818 | { |
819 | g_return_if_fail (GTK_IS_EDITABLE (editable)); |
820 | |
821 | g_object_set (object: editable, first_property_name: "xalign" , xalign, NULL); |
822 | } |
823 | |
824 | /** |
825 | * gtk_editable_get_width_chars: (attributes org.gtk.Method.get_property=width-chars) |
826 | * @editable: a `GtkEditable` |
827 | * |
828 | * Gets the number of characters of space reserved |
829 | * for the contents of the editable. |
830 | * |
831 | * Returns: number of chars to request space for, or negative if unset |
832 | */ |
833 | int |
834 | gtk_editable_get_width_chars (GtkEditable *editable) |
835 | { |
836 | int width_chars; |
837 | |
838 | g_return_val_if_fail (GTK_IS_EDITABLE (editable), 0); |
839 | |
840 | g_object_get (object: editable, first_property_name: "width-chars" , &width_chars, NULL); |
841 | |
842 | return width_chars; |
843 | } |
844 | |
845 | /** |
846 | * gtk_editable_set_width_chars: (attributes org.gtk.Method.set_property=width-chars) |
847 | * @editable: a `GtkEditable` |
848 | * @n_chars: width in chars |
849 | * |
850 | * Changes the size request of the editable to be about the |
851 | * right size for @n_chars characters. |
852 | * |
853 | * Note that it changes the size request, the size can still |
854 | * be affected by how you pack the widget into containers. |
855 | * If @n_chars is -1, the size reverts to the default size. |
856 | */ |
857 | void |
858 | gtk_editable_set_width_chars (GtkEditable *editable, |
859 | int n_chars) |
860 | { |
861 | g_return_if_fail (GTK_IS_EDITABLE (editable)); |
862 | |
863 | g_object_set (object: editable, first_property_name: "width-chars" , n_chars, NULL); |
864 | } |
865 | |
866 | /** |
867 | * gtk_editable_get_max_width_chars: (attributes org.gtk.Method.get_property=max-width-chars) |
868 | * @editable: a `GtkEditable` |
869 | * |
870 | * Retrieves the desired maximum width of @editable, in characters. |
871 | * |
872 | * Returns: the maximum width of the entry, in characters |
873 | */ |
874 | int |
875 | gtk_editable_get_max_width_chars (GtkEditable *editable) |
876 | { |
877 | int max_width_chars; |
878 | |
879 | g_return_val_if_fail (GTK_IS_EDITABLE (editable), 0); |
880 | |
881 | g_object_get (object: editable, first_property_name: "max-width-chars" , &max_width_chars, NULL); |
882 | |
883 | return max_width_chars; |
884 | } |
885 | |
886 | /** |
887 | * gtk_editable_set_max_width_chars: (attributes org.gtk.Method.set_property=max-width-chars) |
888 | * @editable: a `GtkEditable` |
889 | * @n_chars: the new desired maximum width, in characters |
890 | * |
891 | * Sets the desired maximum width in characters of @editable. |
892 | */ |
893 | void |
894 | gtk_editable_set_max_width_chars (GtkEditable *editable, |
895 | int n_chars) |
896 | { |
897 | g_return_if_fail (GTK_IS_EDITABLE (editable)); |
898 | |
899 | g_object_set (object: editable, first_property_name: "max-width-chars" , n_chars, NULL); |
900 | } |
901 | |
902 | /** |
903 | * gtk_editable_get_enable_undo: (attributes org.gtk.Method.get_property=enable-undo) |
904 | * @editable: a `GtkEditable` |
905 | * |
906 | * Gets if undo/redo actions are enabled for @editable |
907 | * |
908 | * Returns: %TRUE if undo is enabled |
909 | */ |
910 | gboolean |
911 | gtk_editable_get_enable_undo (GtkEditable *editable) |
912 | { |
913 | gboolean enable_undo; |
914 | |
915 | g_return_val_if_fail (GTK_IS_EDITABLE (editable), 0); |
916 | |
917 | g_object_get (object: editable, first_property_name: "enable-undo" , &enable_undo, NULL); |
918 | |
919 | return enable_undo; |
920 | } |
921 | |
922 | /** |
923 | * gtk_editable_set_enable_undo: (attributes org.gtk.Method.set_property=enable-undo) |
924 | * @editable: a `GtkEditable` |
925 | * @enable_undo: if undo/redo should be enabled |
926 | * |
927 | * If enabled, changes to @editable will be saved for undo/redo |
928 | * actions. |
929 | * |
930 | * This results in an additional copy of text changes and are not |
931 | * stored in secure memory. As such, undo is forcefully disabled |
932 | * when [property@Gtk.Text:visibility] is set to %FALSE. |
933 | */ |
934 | void |
935 | gtk_editable_set_enable_undo (GtkEditable *editable, |
936 | gboolean enable_undo) |
937 | { |
938 | g_return_if_fail (GTK_IS_EDITABLE (editable)); |
939 | |
940 | g_object_set (object: editable, first_property_name: "enable-undo" , enable_undo, NULL); |
941 | } |
942 | |
943 | /** |
944 | * gtk_editable_install_properties: |
945 | * @object_class: a `GObjectClass` |
946 | * @first_prop: property ID to use for the first property |
947 | * |
948 | * Overrides the `GtkEditable` properties for @class. |
949 | * |
950 | * This is a helper function that should be called in class_init, |
951 | * after installing your own properties. |
952 | * |
953 | * Note that your class must have "text", "cursor-position", |
954 | * "selection-bound", "editable", "width-chars", "max-width-chars", |
955 | * "xalign" and "enable-undo" properties for this function to work. |
956 | * |
957 | * To handle the properties in your set_property and get_property |
958 | * functions, you can either use [func@Gtk.Editable.delegate_set_property] |
959 | * and [func@Gtk.Editable.delegate_get_property] (if you are using |
960 | * a delegate), or remember the @first_prop offset and add it to the |
961 | * values in the [enum@Gtk.EditableProperties] enumeration to get the |
962 | * property IDs for these properties. |
963 | * |
964 | * Returns: the number of properties that were installed |
965 | */ |
966 | guint |
967 | gtk_editable_install_properties (GObjectClass *object_class, |
968 | guint first_prop) |
969 | { |
970 | g_type_set_qdata (G_TYPE_FROM_CLASS (object_class), |
971 | quark: quark_editable_data, |
972 | GUINT_TO_POINTER (first_prop)); |
973 | |
974 | g_object_class_override_property (oclass: object_class, property_id: first_prop + GTK_EDITABLE_PROP_TEXT, name: "text" ); |
975 | g_object_class_override_property (oclass: object_class, property_id: first_prop + GTK_EDITABLE_PROP_CURSOR_POSITION, name: "cursor-position" ); |
976 | g_object_class_override_property (oclass: object_class, property_id: first_prop + GTK_EDITABLE_PROP_SELECTION_BOUND, name: "selection-bound" ); |
977 | g_object_class_override_property (oclass: object_class, property_id: first_prop + GTK_EDITABLE_PROP_EDITABLE, name: "editable" ); |
978 | g_object_class_override_property (oclass: object_class, property_id: first_prop + GTK_EDITABLE_PROP_WIDTH_CHARS, name: "width-chars" ); |
979 | g_object_class_override_property (oclass: object_class, property_id: first_prop + GTK_EDITABLE_PROP_MAX_WIDTH_CHARS, name: "max-width-chars" ); |
980 | g_object_class_override_property (oclass: object_class, property_id: first_prop + GTK_EDITABLE_PROP_XALIGN, name: "xalign" ); |
981 | g_object_class_override_property (oclass: object_class, property_id: first_prop + GTK_EDITABLE_PROP_ENABLE_UNDO, name: "enable-undo" ); |
982 | |
983 | return GTK_EDITABLE_NUM_PROPERTIES; |
984 | } |
985 | |
986 | static void |
987 | delegate_changed (GtkEditable *delegate, |
988 | gpointer editable) |
989 | { |
990 | g_signal_emit (instance: editable, signal_id: signals[CHANGED], detail: 0); |
991 | } |
992 | |
993 | static void |
994 | delegate_notify (GObject *object, |
995 | GParamSpec *pspec, |
996 | gpointer data) |
997 | { |
998 | gpointer iface; |
999 | |
1000 | iface = g_type_interface_peek (instance_class: g_type_class_peek (G_OBJECT_TYPE (object)), iface_type: gtk_editable_get_type ()); |
1001 | if (g_object_interface_find_property (g_iface: iface, property_name: pspec->name)) |
1002 | g_object_notify (object: data, property_name: pspec->name); |
1003 | } |
1004 | |
1005 | /** |
1006 | * gtk_editable_get_delegate: |
1007 | * @editable: a `GtkEditable` |
1008 | * |
1009 | * Gets the `GtkEditable` that @editable is delegating its |
1010 | * implementation to. |
1011 | * |
1012 | * Typically, the delegate is a [class@Gtk.Text] widget. |
1013 | * |
1014 | * Returns: (nullable) (transfer none): the delegate `GtkEditable` |
1015 | */ |
1016 | GtkEditable * |
1017 | gtk_editable_get_delegate (GtkEditable *editable) |
1018 | { |
1019 | return get_delegate (editable); |
1020 | } |
1021 | |
1022 | /** |
1023 | * gtk_editable_init_delegate: |
1024 | * @editable: a `GtkEditable` |
1025 | * |
1026 | * Sets up a delegate for `GtkEditable`. |
1027 | * |
1028 | * This is assuming that the get_delegate vfunc in the `GtkEditable` |
1029 | * interface has been set up for the @editable's type. |
1030 | * |
1031 | * This is a helper function that should be called in instance init, |
1032 | * after creating the delegate object. |
1033 | */ |
1034 | void |
1035 | gtk_editable_init_delegate (GtkEditable *editable) |
1036 | { |
1037 | GtkEditable *delegate = get_delegate (editable); |
1038 | g_signal_connect (delegate, "notify" , G_CALLBACK (delegate_notify), editable); |
1039 | g_signal_connect (delegate, "changed" , G_CALLBACK (delegate_changed), editable); |
1040 | } |
1041 | |
1042 | /** |
1043 | * gtk_editable_finish_delegate: |
1044 | * @editable: a `GtkEditable` |
1045 | * |
1046 | * Undoes the setup done by [method@Gtk.Editable.init_delegate]. |
1047 | * |
1048 | * This is a helper function that should be called from dispose, |
1049 | * before removing the delegate object. |
1050 | */ |
1051 | void |
1052 | gtk_editable_finish_delegate (GtkEditable *editable) |
1053 | { |
1054 | GtkEditable *delegate = get_delegate (editable); |
1055 | g_signal_handlers_disconnect_by_func (delegate, delegate_notify, editable); |
1056 | g_signal_handlers_disconnect_by_func (delegate, delegate_changed, editable); |
1057 | } |
1058 | |
1059 | /** |
1060 | * gtk_editable_delegate_set_property: |
1061 | * @object: a `GObject` |
1062 | * @prop_id: a property ID |
1063 | * @value: value to set |
1064 | * @pspec: the `GParamSpec` for the property |
1065 | * |
1066 | * Sets a property on the `GtkEditable` delegate for @object. |
1067 | * |
1068 | * This is a helper function that should be called in the `set_property` |
1069 | * function of your `GtkEditable` implementation, before handling your |
1070 | * own properties. |
1071 | * |
1072 | * Returns: %TRUE if the property was found |
1073 | */ |
1074 | gboolean |
1075 | gtk_editable_delegate_set_property (GObject *object, |
1076 | guint prop_id, |
1077 | const GValue *value, |
1078 | GParamSpec *pspec) |
1079 | { |
1080 | GtkEditable *delegate = get_delegate (GTK_EDITABLE (object)); |
1081 | GType type = G_TYPE_FROM_INSTANCE (object); |
1082 | guint first_prop; |
1083 | |
1084 | do { |
1085 | first_prop = GPOINTER_TO_UINT (g_type_get_qdata (type, quark_editable_data)); |
1086 | type = g_type_parent (type); |
1087 | } while (first_prop == 0 && type != 0); |
1088 | |
1089 | if (prop_id < first_prop) |
1090 | return FALSE; |
1091 | |
1092 | switch (prop_id - first_prop) |
1093 | { |
1094 | case GTK_EDITABLE_PROP_TEXT: |
1095 | gtk_editable_set_text (editable: delegate, text: g_value_get_string (value)); |
1096 | break; |
1097 | |
1098 | case GTK_EDITABLE_PROP_EDITABLE: |
1099 | gtk_editable_set_editable (editable: delegate, is_editable: g_value_get_boolean (value)); |
1100 | break; |
1101 | |
1102 | case GTK_EDITABLE_PROP_WIDTH_CHARS: |
1103 | gtk_editable_set_width_chars (editable: delegate, n_chars: g_value_get_int (value)); |
1104 | break; |
1105 | |
1106 | case GTK_EDITABLE_PROP_MAX_WIDTH_CHARS: |
1107 | gtk_editable_set_max_width_chars (editable: delegate, n_chars: g_value_get_int (value)); |
1108 | break; |
1109 | |
1110 | case GTK_EDITABLE_PROP_XALIGN: |
1111 | gtk_editable_set_alignment (editable: delegate, xalign: g_value_get_float (value)); |
1112 | break; |
1113 | |
1114 | case GTK_EDITABLE_PROP_ENABLE_UNDO: |
1115 | gtk_editable_set_enable_undo (editable: delegate, enable_undo: g_value_get_boolean (value)); |
1116 | break; |
1117 | |
1118 | default: |
1119 | return FALSE; |
1120 | } |
1121 | |
1122 | return TRUE; |
1123 | } |
1124 | |
1125 | /** |
1126 | * gtk_editable_delegate_get_property: |
1127 | * @object: a `GObject` |
1128 | * @prop_id: a property ID |
1129 | * @value: value to set |
1130 | * @pspec: the `GParamSpec` for the property |
1131 | * |
1132 | * Gets a property of the `GtkEditable` delegate for @object. |
1133 | * |
1134 | * This is helper function that should be called in the `get_property` |
1135 | * function of your `GtkEditable` implementation, before handling your |
1136 | * own properties. |
1137 | * |
1138 | * Returns: %TRUE if the property was found |
1139 | */ |
1140 | gboolean |
1141 | gtk_editable_delegate_get_property (GObject *object, |
1142 | guint prop_id, |
1143 | GValue *value, |
1144 | GParamSpec *pspec) |
1145 | { |
1146 | GtkEditable *delegate = get_delegate (GTK_EDITABLE (object)); |
1147 | int cursor_position, selection_bound; |
1148 | GType type = G_TYPE_FROM_INSTANCE (object); |
1149 | guint first_prop; |
1150 | |
1151 | do { |
1152 | first_prop = GPOINTER_TO_UINT (g_type_get_qdata (type, quark_editable_data)); |
1153 | type = g_type_parent (type); |
1154 | } while (first_prop == 0 && type != 0); |
1155 | |
1156 | if (prop_id < first_prop) |
1157 | return FALSE; |
1158 | |
1159 | switch (prop_id - first_prop) |
1160 | { |
1161 | case GTK_EDITABLE_PROP_TEXT: |
1162 | g_value_set_string (value, v_string: gtk_editable_get_text (editable: delegate)); |
1163 | break; |
1164 | |
1165 | case GTK_EDITABLE_PROP_CURSOR_POSITION: |
1166 | gtk_editable_get_selection_bounds (editable: delegate, start_pos: &cursor_position, end_pos: &selection_bound); |
1167 | g_value_set_int (value, v_int: cursor_position); |
1168 | break; |
1169 | |
1170 | case GTK_EDITABLE_PROP_SELECTION_BOUND: |
1171 | gtk_editable_get_selection_bounds (editable: delegate, start_pos: &cursor_position, end_pos: &selection_bound); |
1172 | g_value_set_int (value, v_int: selection_bound); |
1173 | break; |
1174 | |
1175 | case GTK_EDITABLE_PROP_EDITABLE: |
1176 | g_value_set_boolean (value, v_boolean: gtk_editable_get_editable (editable: delegate)); |
1177 | break; |
1178 | |
1179 | case GTK_EDITABLE_PROP_WIDTH_CHARS: |
1180 | g_value_set_int (value, v_int: gtk_editable_get_width_chars (editable: delegate)); |
1181 | break; |
1182 | |
1183 | case GTK_EDITABLE_PROP_MAX_WIDTH_CHARS: |
1184 | g_value_set_int (value, v_int: gtk_editable_get_max_width_chars (editable: delegate)); |
1185 | break; |
1186 | |
1187 | case GTK_EDITABLE_PROP_XALIGN: |
1188 | g_value_set_float (value, v_float: gtk_editable_get_alignment (editable: delegate)); |
1189 | break; |
1190 | |
1191 | case GTK_EDITABLE_PROP_ENABLE_UNDO: |
1192 | g_value_set_boolean (value, v_boolean: gtk_editable_get_enable_undo (editable: delegate)); |
1193 | break; |
1194 | |
1195 | default: |
1196 | return FALSE; |
1197 | } |
1198 | |
1199 | return TRUE; |
1200 | } |
1201 | |