1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
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.
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.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
27 #undef GTK_DISABLE_DEPRECATED
31 #include "gdk/gdkkeysyms.h"
32 #include "gdk/gdki18n.h"
33 #include "gtkclipboard.h"
34 #include "gtkoldeditable.h"
36 #include "gtkmarshalers.h"
37 #include "gtkselection.h"
38 #include "gtksignal.h"
42 #define MIN_EDITABLE_WIDTH 150
43 #define DRAW_TIMEOUT 20
44 #define INNER_BORDER 2
70 /* values for selection info */
78 static void gtk_old_editable_class_init (GtkOldEditableClass *klass);
79 static void gtk_old_editable_editable_init (GtkEditableClass *iface);
80 static void gtk_old_editable_init (GtkOldEditable *editable);
81 static void gtk_old_editable_set_arg (GtkObject *object,
84 static void gtk_old_editable_get_arg (GtkObject *object,
87 static void *gtk_old_editable_get_public_chars (GtkOldEditable *old_editable,
91 static gint gtk_old_editable_selection_clear (GtkWidget *widget,
92 GdkEventSelection *event);
93 static void gtk_old_editable_selection_get (GtkWidget *widget,
94 GtkSelectionData *selection_data,
97 static void gtk_old_editable_selection_received (GtkWidget *widget,
98 GtkSelectionData *selection_data,
101 static void gtk_old_editable_set_selection (GtkOldEditable *old_editable,
105 static void gtk_old_editable_real_set_editable (GtkOldEditable *old_editable,
106 gboolean is_editable);
107 static void gtk_old_editable_real_cut_clipboard (GtkOldEditable *old_editable);
108 static void gtk_old_editable_real_copy_clipboard (GtkOldEditable *old_editable);
109 static void gtk_old_editable_real_paste_clipboard (GtkOldEditable *old_editable);
111 static void gtk_old_editable_insert_text (GtkEditable *editable,
112 const gchar *new_text,
113 gint new_text_length,
115 static void gtk_old_editable_delete_text (GtkEditable *editable,
118 static gchar * gtk_old_editable_get_chars (GtkEditable *editable,
121 static void gtk_old_editable_set_selection_bounds (GtkEditable *editable,
124 static gboolean gtk_old_editable_get_selection_bounds (GtkEditable *editable,
127 static void gtk_old_editable_set_position (GtkEditable *editable,
129 static gint gtk_old_editable_get_position (GtkEditable *editable);
131 static GtkWidgetClass *parent_class = NULL;
132 static guint editable_signals[LAST_SIGNAL] = { 0 };
135 gtk_old_editable_get_type (void)
137 static GtkType old_editable_type = 0;
139 if (!old_editable_type)
141 static const GTypeInfo old_editable_info =
143 sizeof (GtkOldEditableClass),
144 NULL, /* base_init */
145 NULL, /* base_finalize */
146 (GClassInitFunc) gtk_old_editable_class_init,
147 NULL, /* class_finalize */
148 NULL, /* class_data */
149 sizeof (GtkOldEditable),
151 (GInstanceInitFunc) gtk_old_editable_init,
152 NULL, /* value_table */
155 static const GInterfaceInfo editable_info =
157 (GInterfaceInitFunc) gtk_old_editable_editable_init, /* interface_init */
158 NULL, /* interface_finalize */
159 NULL /* interface_data */
162 old_editable_type = g_type_register_static (GTK_TYPE_WIDGET, I_("GtkOldEditable"),
163 &old_editable_info, G_TYPE_FLAG_ABSTRACT);
164 g_type_add_interface_static (old_editable_type,
169 return old_editable_type;
173 gtk_old_editable_class_init (GtkOldEditableClass *class)
175 GtkObjectClass *object_class;
176 GtkWidgetClass *widget_class;
178 object_class = (GtkObjectClass*) class;
179 widget_class = (GtkWidgetClass*) class;
181 parent_class = gtk_type_class (GTK_TYPE_WIDGET);
183 object_class->set_arg = gtk_old_editable_set_arg;
184 object_class->get_arg = gtk_old_editable_get_arg;
186 widget_class->selection_clear_event = gtk_old_editable_selection_clear;
187 widget_class->selection_received = gtk_old_editable_selection_received;
188 widget_class->selection_get = gtk_old_editable_selection_get;
190 class->activate = NULL;
191 class->set_editable = gtk_old_editable_real_set_editable;
193 class->move_cursor = NULL;
194 class->move_word = NULL;
195 class->move_page = NULL;
196 class->move_to_row = NULL;
197 class->move_to_column = NULL;
199 class->kill_char = NULL;
200 class->kill_word = NULL;
201 class->kill_line = NULL;
203 class->cut_clipboard = gtk_old_editable_real_cut_clipboard;
204 class->copy_clipboard = gtk_old_editable_real_copy_clipboard;
205 class->paste_clipboard = gtk_old_editable_real_paste_clipboard;
207 class->update_text = NULL;
208 class->get_chars = NULL;
209 class->set_selection = NULL;
210 class->set_position = NULL;
212 editable_signals[ACTIVATE] =
213 gtk_signal_new (I_("activate"),
214 GTK_RUN_LAST | GTK_RUN_ACTION,
215 GTK_CLASS_TYPE (object_class),
216 GTK_SIGNAL_OFFSET (GtkOldEditableClass, activate),
217 _gtk_marshal_NONE__NONE,
219 widget_class->activate_signal = editable_signals[ACTIVATE];
221 editable_signals[SET_EDITABLE] =
222 gtk_signal_new (I_("set-editable"),
223 GTK_RUN_LAST | GTK_RUN_ACTION,
224 GTK_CLASS_TYPE (object_class),
225 GTK_SIGNAL_OFFSET (GtkOldEditableClass, set_editable),
226 _gtk_marshal_NONE__BOOLEAN,
230 editable_signals[MOVE_CURSOR] =
231 gtk_signal_new (I_("move_cursor"),
232 GTK_RUN_LAST | GTK_RUN_ACTION,
233 GTK_CLASS_TYPE (object_class),
234 GTK_SIGNAL_OFFSET (GtkOldEditableClass, move_cursor),
235 _gtk_marshal_NONE__INT_INT,
240 editable_signals[MOVE_WORD] =
241 gtk_signal_new (I_("move_word"),
242 GTK_RUN_LAST | GTK_RUN_ACTION,
243 GTK_CLASS_TYPE (object_class),
244 GTK_SIGNAL_OFFSET (GtkOldEditableClass, move_word),
245 _gtk_marshal_NONE__INT,
249 editable_signals[MOVE_PAGE] =
250 gtk_signal_new (I_("move_page"),
251 GTK_RUN_LAST | GTK_RUN_ACTION,
252 GTK_CLASS_TYPE (object_class),
253 GTK_SIGNAL_OFFSET (GtkOldEditableClass, move_page),
254 _gtk_marshal_NONE__INT_INT,
259 editable_signals[MOVE_TO_ROW] =
260 gtk_signal_new (I_("move_to_row"),
261 GTK_RUN_LAST | GTK_RUN_ACTION,
262 GTK_CLASS_TYPE (object_class),
263 GTK_SIGNAL_OFFSET (GtkOldEditableClass, move_to_row),
264 _gtk_marshal_NONE__INT,
268 editable_signals[MOVE_TO_COLUMN] =
269 gtk_signal_new (I_("move_to_column"),
270 GTK_RUN_LAST | GTK_RUN_ACTION,
271 GTK_CLASS_TYPE (object_class),
272 GTK_SIGNAL_OFFSET (GtkOldEditableClass, move_to_column),
273 _gtk_marshal_NONE__INT,
277 editable_signals[KILL_CHAR] =
278 gtk_signal_new (I_("kill_char"),
279 GTK_RUN_LAST | GTK_RUN_ACTION,
280 GTK_CLASS_TYPE (object_class),
281 GTK_SIGNAL_OFFSET (GtkOldEditableClass, kill_char),
282 _gtk_marshal_NONE__INT,
286 editable_signals[KILL_WORD] =
287 gtk_signal_new (I_("kill_word"),
288 GTK_RUN_LAST | GTK_RUN_ACTION,
289 GTK_CLASS_TYPE (object_class),
290 GTK_SIGNAL_OFFSET (GtkOldEditableClass, kill_word),
291 _gtk_marshal_NONE__INT,
295 editable_signals[KILL_LINE] =
296 gtk_signal_new (I_("kill_line"),
297 GTK_RUN_LAST | GTK_RUN_ACTION,
298 GTK_CLASS_TYPE (object_class),
299 GTK_SIGNAL_OFFSET (GtkOldEditableClass, kill_line),
300 _gtk_marshal_NONE__INT,
304 editable_signals[CUT_CLIPBOARD] =
305 gtk_signal_new (I_("cut_clipboard"),
306 GTK_RUN_LAST | GTK_RUN_ACTION,
307 GTK_CLASS_TYPE (object_class),
308 GTK_SIGNAL_OFFSET (GtkOldEditableClass, cut_clipboard),
309 _gtk_marshal_NONE__NONE,
312 editable_signals[COPY_CLIPBOARD] =
313 gtk_signal_new (I_("copy_clipboard"),
314 GTK_RUN_LAST | GTK_RUN_ACTION,
315 GTK_CLASS_TYPE (object_class),
316 GTK_SIGNAL_OFFSET (GtkOldEditableClass, copy_clipboard),
317 _gtk_marshal_NONE__NONE,
320 editable_signals[PASTE_CLIPBOARD] =
321 gtk_signal_new (I_("paste_clipboard"),
322 GTK_RUN_LAST | GTK_RUN_ACTION,
323 GTK_CLASS_TYPE (object_class),
324 GTK_SIGNAL_OFFSET (GtkOldEditableClass, paste_clipboard),
325 _gtk_marshal_NONE__NONE,
328 gtk_object_add_arg_type ("GtkOldEditable::text-position", GTK_TYPE_INT, GTK_ARG_READWRITE | G_PARAM_STATIC_NAME, ARG_TEXT_POSITION);
329 gtk_object_add_arg_type ("GtkOldEditable::editable", GTK_TYPE_BOOL, GTK_ARG_READWRITE | G_PARAM_STATIC_NAME, ARG_EDITABLE);
333 gtk_old_editable_editable_init (GtkEditableClass *iface)
335 iface->do_insert_text = gtk_old_editable_insert_text;
336 iface->do_delete_text = gtk_old_editable_delete_text;
337 iface->get_chars = gtk_old_editable_get_chars;
338 iface->set_selection_bounds = gtk_old_editable_set_selection_bounds;
339 iface->get_selection_bounds = gtk_old_editable_get_selection_bounds;
340 iface->set_position = gtk_old_editable_set_position;
341 iface->get_position = gtk_old_editable_get_position;
345 gtk_old_editable_set_arg (GtkObject *object,
349 GtkEditable *editable = GTK_EDITABLE (object);
353 case ARG_TEXT_POSITION:
354 gtk_editable_set_position (editable, GTK_VALUE_INT (*arg));
357 gtk_signal_emit (object, editable_signals[SET_EDITABLE],
358 GTK_VALUE_BOOL (*arg) != FALSE);
366 gtk_old_editable_get_arg (GtkObject *object,
370 GtkOldEditable *old_editable;
372 old_editable = GTK_OLD_EDITABLE (object);
376 case ARG_TEXT_POSITION:
377 GTK_VALUE_INT (*arg) = old_editable->current_pos;
380 GTK_VALUE_BOOL (*arg) = old_editable->editable;
383 arg->type = GTK_TYPE_INVALID;
389 gtk_old_editable_init (GtkOldEditable *old_editable)
391 static const GtkTargetEntry targets[] = {
392 { "UTF8_STRING", 0, 0 },
395 { "COMPOUND_TEXT", 0, 0 }
398 GTK_WIDGET_SET_FLAGS (old_editable, GTK_CAN_FOCUS);
400 old_editable->selection_start_pos = 0;
401 old_editable->selection_end_pos = 0;
402 old_editable->has_selection = FALSE;
403 old_editable->editable = 1;
404 old_editable->visible = 1;
405 old_editable->clipboard_text = NULL;
407 gtk_selection_add_targets (GTK_WIDGET (old_editable), GDK_SELECTION_PRIMARY,
408 targets, G_N_ELEMENTS (targets));
412 gtk_old_editable_insert_text (GtkEditable *editable,
413 const gchar *new_text,
414 gint new_text_length,
420 gtk_widget_ref (GTK_WIDGET (editable));
422 if (new_text_length <= 63)
425 text = g_new (gchar, new_text_length + 1);
427 text[new_text_length] = '\0';
428 strncpy (text, new_text, new_text_length);
430 g_signal_emit_by_name (editable, "insert_text", text, new_text_length,
432 g_signal_emit_by_name (editable, "changed");
434 if (new_text_length > 63)
437 gtk_widget_unref (GTK_WIDGET (editable));
441 gtk_old_editable_delete_text (GtkEditable *editable,
445 GtkOldEditable *old_editable = GTK_OLD_EDITABLE (editable);
447 gtk_widget_ref (GTK_WIDGET (old_editable));
449 g_signal_emit_by_name (editable, "delete_text", start_pos, end_pos);
450 g_signal_emit_by_name (editable, "changed");
452 if (old_editable->selection_start_pos == old_editable->selection_end_pos &&
453 old_editable->has_selection)
454 gtk_old_editable_claim_selection (old_editable, FALSE, GDK_CURRENT_TIME);
456 gtk_widget_unref (GTK_WIDGET (old_editable));
460 gtk_old_editable_update_text (GtkOldEditable *old_editable,
464 GtkOldEditableClass *klass = GTK_OLD_EDITABLE_GET_CLASS (old_editable);
465 klass->update_text (GTK_OLD_EDITABLE (old_editable), start_pos, end_pos);
469 gtk_old_editable_get_chars (GtkEditable *editable,
473 GtkOldEditableClass *klass = GTK_OLD_EDITABLE_GET_CLASS (editable);
474 return klass->get_chars (GTK_OLD_EDITABLE (editable), start, end);
478 * Like gtk_editable_get_chars, but if the editable is not
479 * visible, return asterisks; also convert result to UTF-8.
482 gtk_old_editable_get_public_chars (GtkOldEditable *old_editable,
487 const gchar *charset;
488 gboolean need_conversion = !g_get_charset (&charset);
490 if (old_editable->visible)
492 GError *error = NULL;
493 gchar *tmp = gtk_editable_get_chars (GTK_EDITABLE (old_editable), start, end);
497 str = g_convert (tmp, -1,
503 g_warning ("Cannot convert text from charset to UTF-8 %s: %s", charset, error->message);
504 g_error_free (error);
515 gint nchars = end - start;
520 str = g_new (gchar, nchars + 1);
521 for (i = 0; i<nchars; i++)
530 gtk_old_editable_set_selection (GtkOldEditable *old_editable,
534 GtkOldEditableClass *klass = GTK_OLD_EDITABLE_GET_CLASS (old_editable);
535 klass->set_selection (old_editable, start_pos, end_pos);
539 gtk_old_editable_set_position (GtkEditable *editable,
542 GtkOldEditableClass *klass = GTK_OLD_EDITABLE_GET_CLASS (editable);
544 klass->set_position (GTK_OLD_EDITABLE (editable), position);
548 gtk_old_editable_get_position (GtkEditable *editable)
550 return GTK_OLD_EDITABLE (editable)->current_pos;
554 gtk_old_editable_selection_clear (GtkWidget *widget,
555 GdkEventSelection *event)
557 GtkOldEditable *old_editable = GTK_OLD_EDITABLE (widget);
559 /* Let the selection handling code know that the selection
560 * has been changed, since we've overriden the default handler */
561 if (!parent_class->selection_clear_event (widget, event))
564 if (old_editable->has_selection)
566 old_editable->has_selection = FALSE;
567 gtk_old_editable_update_text (old_editable, old_editable->selection_start_pos,
568 old_editable->selection_end_pos);
575 gtk_old_editable_selection_get (GtkWidget *widget,
576 GtkSelectionData *selection_data,
580 GtkOldEditable *old_editable = GTK_OLD_EDITABLE (widget);
581 gint selection_start_pos;
582 gint selection_end_pos;
586 selection_start_pos = MIN (old_editable->selection_start_pos, old_editable->selection_end_pos);
587 selection_end_pos = MAX (old_editable->selection_start_pos, old_editable->selection_end_pos);
589 str = gtk_old_editable_get_public_chars (old_editable,
595 gtk_selection_data_set_text (selection_data, str, -1);
601 gtk_old_editable_paste_received (GtkOldEditable *old_editable,
603 gboolean is_clipboard)
605 const gchar *str = NULL;
606 const gchar *charset;
607 gboolean need_conversion = FALSE;
611 GError *error = NULL;
613 need_conversion = !g_get_charset (&charset);
617 str = g_convert_with_fallback (text, -1,
618 charset, "UTF-8", NULL,
622 g_warning ("Cannot convert text from UTF-8 to %s: %s",
623 charset, error->message);
624 g_error_free (error);
640 if ((old_editable->selection_start_pos != old_editable->selection_end_pos) &&
641 (!old_editable->has_selection || is_clipboard))
645 /* Don't want to call gtk_editable_delete_selection here if we are going
646 * to reclaim the selection to avoid extra server traffic */
647 if (old_editable->has_selection)
649 gtk_editable_delete_text (GTK_EDITABLE (old_editable),
650 MIN (old_editable->selection_start_pos, old_editable->selection_end_pos),
651 MAX (old_editable->selection_start_pos, old_editable->selection_end_pos));
654 gtk_editable_delete_selection (GTK_EDITABLE (old_editable));
657 tmp_pos = old_pos = old_editable->current_pos;
659 gtk_editable_insert_text (GTK_EDITABLE (old_editable), str, -1, &tmp_pos);
662 gtk_old_editable_set_selection (old_editable, old_pos, old_editable->current_pos);
664 if (str && str != text)
665 g_free ((gchar *) str);
670 gtk_old_editable_selection_received (GtkWidget *widget,
671 GtkSelectionData *selection_data,
674 GtkOldEditable *old_editable = GTK_OLD_EDITABLE (widget);
676 gchar *text = gtk_selection_data_get_text (selection_data);
680 /* If we asked for UTF8 and didn't get it, try text; if we asked
681 * for text and didn't get it, try string. If we asked for
682 * anything else and didn't get it, give up.
684 if (selection_data->target == gdk_atom_intern_static_string ("UTF8_STRING"))
686 gtk_selection_convert (widget, GDK_SELECTION_PRIMARY,
687 gdk_atom_intern_static_string ("TEXT"),
691 else if (selection_data->target == gdk_atom_intern_static_string ("TEXT"))
693 gtk_selection_convert (widget, GDK_SELECTION_PRIMARY,
702 gtk_old_editable_paste_received (old_editable, text, FALSE);
708 old_editable_text_received_cb (GtkClipboard *clipboard,
712 GtkOldEditable *old_editable = GTK_OLD_EDITABLE (data);
714 gtk_old_editable_paste_received (old_editable, text, TRUE);
715 g_object_unref (G_OBJECT (old_editable));
719 * gtk_old_editable_claim_selection:
720 * @old_editable: a #GtkOldEditable
721 * @claim: if %TRUE, claim ownership of the selection, if %FALSE, give
723 * @time_: timestamp for this operation
725 * Claims or gives up ownership of the selection.
728 gtk_old_editable_claim_selection (GtkOldEditable *old_editable,
732 GtkWidget *widget = GTK_WIDGET (old_editable);
733 GdkDisplay *display = gtk_widget_get_display (widget);
735 g_return_if_fail (GTK_IS_OLD_EDITABLE (old_editable));
736 g_return_if_fail (GTK_WIDGET_REALIZED (old_editable));
738 old_editable->has_selection = FALSE;
742 if (gtk_selection_owner_set_for_display (display, widget,
743 GDK_SELECTION_PRIMARY, time))
744 old_editable->has_selection = TRUE;
748 if (gdk_selection_owner_get_for_display (display, GDK_SELECTION_PRIMARY) == widget->window)
749 gtk_selection_owner_set_for_display (display,
751 GDK_SELECTION_PRIMARY, time);
756 gtk_old_editable_set_selection_bounds (GtkEditable *editable,
760 GtkOldEditable *old_editable = GTK_OLD_EDITABLE (editable);
762 if (GTK_WIDGET_REALIZED (editable))
763 gtk_old_editable_claim_selection (old_editable, start != end, GDK_CURRENT_TIME);
765 gtk_old_editable_set_selection (old_editable, start, end);
769 gtk_old_editable_get_selection_bounds (GtkEditable *editable,
773 GtkOldEditable *old_editable = GTK_OLD_EDITABLE (editable);
775 *start = old_editable->selection_start_pos;
776 *end = old_editable->selection_end_pos;
778 return (old_editable->selection_start_pos != old_editable->selection_end_pos);
782 gtk_old_editable_real_set_editable (GtkOldEditable *old_editable,
783 gboolean is_editable)
785 is_editable = is_editable != FALSE;
787 if (old_editable->editable != is_editable)
789 old_editable->editable = is_editable;
790 gtk_widget_queue_draw (GTK_WIDGET (old_editable));
795 gtk_old_editable_real_cut_clipboard (GtkOldEditable *old_editable)
797 gtk_old_editable_real_copy_clipboard (old_editable);
798 gtk_editable_delete_selection (GTK_EDITABLE (old_editable));
802 gtk_old_editable_real_copy_clipboard (GtkOldEditable *old_editable)
804 gint selection_start_pos;
805 gint selection_end_pos;
807 selection_start_pos = MIN (old_editable->selection_start_pos, old_editable->selection_end_pos);
808 selection_end_pos = MAX (old_editable->selection_start_pos, old_editable->selection_end_pos);
810 if (selection_start_pos != selection_end_pos)
812 gchar *text = gtk_old_editable_get_public_chars (old_editable,
818 GtkClipboard *clipboard = gtk_widget_get_clipboard (GTK_WIDGET (old_editable),
819 GDK_SELECTION_CLIPBOARD);
821 gtk_clipboard_set_text (clipboard, text, -1);
828 gtk_old_editable_real_paste_clipboard (GtkOldEditable *old_editable)
830 GtkClipboard *clipboard = gtk_widget_get_clipboard (GTK_WIDGET (old_editable),
831 GDK_SELECTION_CLIPBOARD);
833 g_object_ref (G_OBJECT (old_editable));
834 gtk_clipboard_request_text (clipboard, old_editable_text_received_cb, old_editable);
838 * gtk_old_editable_changed:
839 * @old_editable: a #GtkOldEditable
841 * Emits the ::changed signal on @old_editable.
844 gtk_old_editable_changed (GtkOldEditable *old_editable)
846 g_return_if_fail (GTK_IS_OLD_EDITABLE (old_editable));
848 g_signal_emit_by_name (old_editable, "changed");
851 #define __GTK_OLD_EDITABLE_C__
852 #include "gtkaliasdef.c"