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_editable_init (GtkEditableClass *iface);
79 static void gtk_old_editable_set_arg (GtkObject *object,
82 static void gtk_old_editable_get_arg (GtkObject *object,
85 static void *gtk_old_editable_get_public_chars (GtkOldEditable *old_editable,
89 static gint gtk_old_editable_selection_clear (GtkWidget *widget,
90 GdkEventSelection *event);
91 static void gtk_old_editable_selection_get (GtkWidget *widget,
92 GtkSelectionData *selection_data,
95 static void gtk_old_editable_selection_received (GtkWidget *widget,
96 GtkSelectionData *selection_data,
99 static void gtk_old_editable_set_selection (GtkOldEditable *old_editable,
103 static void gtk_old_editable_real_set_editable (GtkOldEditable *old_editable,
104 gboolean is_editable);
105 static void gtk_old_editable_real_cut_clipboard (GtkOldEditable *old_editable);
106 static void gtk_old_editable_real_copy_clipboard (GtkOldEditable *old_editable);
107 static void gtk_old_editable_real_paste_clipboard (GtkOldEditable *old_editable);
109 static void gtk_old_editable_insert_text (GtkEditable *editable,
110 const gchar *new_text,
111 gint new_text_length,
113 static void gtk_old_editable_delete_text (GtkEditable *editable,
116 static gchar * gtk_old_editable_get_chars (GtkEditable *editable,
119 static void gtk_old_editable_set_selection_bounds (GtkEditable *editable,
122 static gboolean gtk_old_editable_get_selection_bounds (GtkEditable *editable,
125 static void gtk_old_editable_set_position (GtkEditable *editable,
127 static gint gtk_old_editable_get_position (GtkEditable *editable);
129 static guint editable_signals[LAST_SIGNAL] = { 0 };
131 G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GtkOldEditable, gtk_old_editable, GTK_TYPE_WIDGET,
132 G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE,
133 gtk_old_editable_editable_init))
136 gtk_old_editable_class_init (GtkOldEditableClass *class)
138 GtkObjectClass *object_class;
139 GtkWidgetClass *widget_class;
141 object_class = (GtkObjectClass*) class;
142 widget_class = (GtkWidgetClass*) class;
144 object_class->set_arg = gtk_old_editable_set_arg;
145 object_class->get_arg = gtk_old_editable_get_arg;
147 widget_class->selection_clear_event = gtk_old_editable_selection_clear;
148 widget_class->selection_received = gtk_old_editable_selection_received;
149 widget_class->selection_get = gtk_old_editable_selection_get;
151 class->activate = NULL;
152 class->set_editable = gtk_old_editable_real_set_editable;
154 class->move_cursor = NULL;
155 class->move_word = NULL;
156 class->move_page = NULL;
157 class->move_to_row = NULL;
158 class->move_to_column = NULL;
160 class->kill_char = NULL;
161 class->kill_word = NULL;
162 class->kill_line = NULL;
164 class->cut_clipboard = gtk_old_editable_real_cut_clipboard;
165 class->copy_clipboard = gtk_old_editable_real_copy_clipboard;
166 class->paste_clipboard = gtk_old_editable_real_paste_clipboard;
168 class->update_text = NULL;
169 class->get_chars = NULL;
170 class->set_selection = NULL;
171 class->set_position = NULL;
173 editable_signals[ACTIVATE] =
174 gtk_signal_new (I_("activate"),
175 GTK_RUN_LAST | GTK_RUN_ACTION,
176 GTK_CLASS_TYPE (object_class),
177 GTK_SIGNAL_OFFSET (GtkOldEditableClass, activate),
178 _gtk_marshal_NONE__NONE,
180 widget_class->activate_signal = editable_signals[ACTIVATE];
182 editable_signals[SET_EDITABLE] =
183 gtk_signal_new (I_("set-editable"),
184 GTK_RUN_LAST | GTK_RUN_ACTION,
185 GTK_CLASS_TYPE (object_class),
186 GTK_SIGNAL_OFFSET (GtkOldEditableClass, set_editable),
187 _gtk_marshal_NONE__BOOLEAN,
191 editable_signals[MOVE_CURSOR] =
192 gtk_signal_new (I_("move_cursor"),
193 GTK_RUN_LAST | GTK_RUN_ACTION,
194 GTK_CLASS_TYPE (object_class),
195 GTK_SIGNAL_OFFSET (GtkOldEditableClass, move_cursor),
196 _gtk_marshal_NONE__INT_INT,
201 editable_signals[MOVE_WORD] =
202 gtk_signal_new (I_("move_word"),
203 GTK_RUN_LAST | GTK_RUN_ACTION,
204 GTK_CLASS_TYPE (object_class),
205 GTK_SIGNAL_OFFSET (GtkOldEditableClass, move_word),
206 _gtk_marshal_NONE__INT,
210 editable_signals[MOVE_PAGE] =
211 gtk_signal_new (I_("move_page"),
212 GTK_RUN_LAST | GTK_RUN_ACTION,
213 GTK_CLASS_TYPE (object_class),
214 GTK_SIGNAL_OFFSET (GtkOldEditableClass, move_page),
215 _gtk_marshal_NONE__INT_INT,
220 editable_signals[MOVE_TO_ROW] =
221 gtk_signal_new (I_("move_to_row"),
222 GTK_RUN_LAST | GTK_RUN_ACTION,
223 GTK_CLASS_TYPE (object_class),
224 GTK_SIGNAL_OFFSET (GtkOldEditableClass, move_to_row),
225 _gtk_marshal_NONE__INT,
229 editable_signals[MOVE_TO_COLUMN] =
230 gtk_signal_new (I_("move_to_column"),
231 GTK_RUN_LAST | GTK_RUN_ACTION,
232 GTK_CLASS_TYPE (object_class),
233 GTK_SIGNAL_OFFSET (GtkOldEditableClass, move_to_column),
234 _gtk_marshal_NONE__INT,
238 editable_signals[KILL_CHAR] =
239 gtk_signal_new (I_("kill_char"),
240 GTK_RUN_LAST | GTK_RUN_ACTION,
241 GTK_CLASS_TYPE (object_class),
242 GTK_SIGNAL_OFFSET (GtkOldEditableClass, kill_char),
243 _gtk_marshal_NONE__INT,
247 editable_signals[KILL_WORD] =
248 gtk_signal_new (I_("kill_word"),
249 GTK_RUN_LAST | GTK_RUN_ACTION,
250 GTK_CLASS_TYPE (object_class),
251 GTK_SIGNAL_OFFSET (GtkOldEditableClass, kill_word),
252 _gtk_marshal_NONE__INT,
256 editable_signals[KILL_LINE] =
257 gtk_signal_new (I_("kill_line"),
258 GTK_RUN_LAST | GTK_RUN_ACTION,
259 GTK_CLASS_TYPE (object_class),
260 GTK_SIGNAL_OFFSET (GtkOldEditableClass, kill_line),
261 _gtk_marshal_NONE__INT,
265 editable_signals[CUT_CLIPBOARD] =
266 gtk_signal_new (I_("cut_clipboard"),
267 GTK_RUN_LAST | GTK_RUN_ACTION,
268 GTK_CLASS_TYPE (object_class),
269 GTK_SIGNAL_OFFSET (GtkOldEditableClass, cut_clipboard),
270 _gtk_marshal_NONE__NONE,
273 editable_signals[COPY_CLIPBOARD] =
274 gtk_signal_new (I_("copy_clipboard"),
275 GTK_RUN_LAST | GTK_RUN_ACTION,
276 GTK_CLASS_TYPE (object_class),
277 GTK_SIGNAL_OFFSET (GtkOldEditableClass, copy_clipboard),
278 _gtk_marshal_NONE__NONE,
281 editable_signals[PASTE_CLIPBOARD] =
282 gtk_signal_new (I_("paste_clipboard"),
283 GTK_RUN_LAST | GTK_RUN_ACTION,
284 GTK_CLASS_TYPE (object_class),
285 GTK_SIGNAL_OFFSET (GtkOldEditableClass, paste_clipboard),
286 _gtk_marshal_NONE__NONE,
289 gtk_object_add_arg_type ("GtkOldEditable::text-position", GTK_TYPE_INT, GTK_ARG_READWRITE | G_PARAM_STATIC_NAME, ARG_TEXT_POSITION);
290 gtk_object_add_arg_type ("GtkOldEditable::editable", GTK_TYPE_BOOL, GTK_ARG_READWRITE | G_PARAM_STATIC_NAME, ARG_EDITABLE);
294 gtk_old_editable_editable_init (GtkEditableClass *iface)
296 iface->do_insert_text = gtk_old_editable_insert_text;
297 iface->do_delete_text = gtk_old_editable_delete_text;
298 iface->get_chars = gtk_old_editable_get_chars;
299 iface->set_selection_bounds = gtk_old_editable_set_selection_bounds;
300 iface->get_selection_bounds = gtk_old_editable_get_selection_bounds;
301 iface->set_position = gtk_old_editable_set_position;
302 iface->get_position = gtk_old_editable_get_position;
306 gtk_old_editable_set_arg (GtkObject *object,
310 GtkEditable *editable = GTK_EDITABLE (object);
314 case ARG_TEXT_POSITION:
315 gtk_editable_set_position (editable, GTK_VALUE_INT (*arg));
318 gtk_signal_emit (object, editable_signals[SET_EDITABLE],
319 GTK_VALUE_BOOL (*arg) != FALSE);
327 gtk_old_editable_get_arg (GtkObject *object,
331 GtkOldEditable *old_editable;
333 old_editable = GTK_OLD_EDITABLE (object);
337 case ARG_TEXT_POSITION:
338 GTK_VALUE_INT (*arg) = old_editable->current_pos;
341 GTK_VALUE_BOOL (*arg) = old_editable->editable;
344 arg->type = GTK_TYPE_INVALID;
350 gtk_old_editable_init (GtkOldEditable *old_editable)
352 static const GtkTargetEntry targets[] = {
353 { "UTF8_STRING", 0, 0 },
356 { "COMPOUND_TEXT", 0, 0 }
359 GTK_WIDGET_SET_FLAGS (old_editable, GTK_CAN_FOCUS);
361 old_editable->selection_start_pos = 0;
362 old_editable->selection_end_pos = 0;
363 old_editable->has_selection = FALSE;
364 old_editable->editable = 1;
365 old_editable->visible = 1;
366 old_editable->clipboard_text = NULL;
368 gtk_selection_add_targets (GTK_WIDGET (old_editable), GDK_SELECTION_PRIMARY,
369 targets, G_N_ELEMENTS (targets));
373 gtk_old_editable_insert_text (GtkEditable *editable,
374 const gchar *new_text,
375 gint new_text_length,
381 gtk_widget_ref (GTK_WIDGET (editable));
383 if (new_text_length <= 63)
386 text = g_new (gchar, new_text_length + 1);
388 text[new_text_length] = '\0';
389 strncpy (text, new_text, new_text_length);
391 g_signal_emit_by_name (editable, "insert_text", text, new_text_length,
393 g_signal_emit_by_name (editable, "changed");
395 if (new_text_length > 63)
398 gtk_widget_unref (GTK_WIDGET (editable));
402 gtk_old_editable_delete_text (GtkEditable *editable,
406 GtkOldEditable *old_editable = GTK_OLD_EDITABLE (editable);
408 gtk_widget_ref (GTK_WIDGET (old_editable));
410 g_signal_emit_by_name (editable, "delete_text", start_pos, end_pos);
411 g_signal_emit_by_name (editable, "changed");
413 if (old_editable->selection_start_pos == old_editable->selection_end_pos &&
414 old_editable->has_selection)
415 gtk_old_editable_claim_selection (old_editable, FALSE, GDK_CURRENT_TIME);
417 gtk_widget_unref (GTK_WIDGET (old_editable));
421 gtk_old_editable_update_text (GtkOldEditable *old_editable,
425 GtkOldEditableClass *klass = GTK_OLD_EDITABLE_GET_CLASS (old_editable);
426 klass->update_text (GTK_OLD_EDITABLE (old_editable), start_pos, end_pos);
430 gtk_old_editable_get_chars (GtkEditable *editable,
434 GtkOldEditableClass *klass = GTK_OLD_EDITABLE_GET_CLASS (editable);
435 return klass->get_chars (GTK_OLD_EDITABLE (editable), start, end);
439 * Like gtk_editable_get_chars, but if the editable is not
440 * visible, return asterisks; also convert result to UTF-8.
443 gtk_old_editable_get_public_chars (GtkOldEditable *old_editable,
448 const gchar *charset;
449 gboolean need_conversion = !g_get_charset (&charset);
451 if (old_editable->visible)
453 GError *error = NULL;
454 gchar *tmp = gtk_editable_get_chars (GTK_EDITABLE (old_editable), start, end);
458 str = g_convert (tmp, -1,
464 g_warning ("Cannot convert text from charset to UTF-8 %s: %s", charset, error->message);
465 g_error_free (error);
476 gint nchars = end - start;
481 str = g_new (gchar, nchars + 1);
482 for (i = 0; i<nchars; i++)
491 gtk_old_editable_set_selection (GtkOldEditable *old_editable,
495 GtkOldEditableClass *klass = GTK_OLD_EDITABLE_GET_CLASS (old_editable);
496 klass->set_selection (old_editable, start_pos, end_pos);
500 gtk_old_editable_set_position (GtkEditable *editable,
503 GtkOldEditableClass *klass = GTK_OLD_EDITABLE_GET_CLASS (editable);
505 klass->set_position (GTK_OLD_EDITABLE (editable), position);
509 gtk_old_editable_get_position (GtkEditable *editable)
511 return GTK_OLD_EDITABLE (editable)->current_pos;
515 gtk_old_editable_selection_clear (GtkWidget *widget,
516 GdkEventSelection *event)
518 GtkOldEditable *old_editable = GTK_OLD_EDITABLE (widget);
520 /* Let the selection handling code know that the selection
521 * has been changed, since we've overriden the default handler */
522 if (!GTK_WIDGET_CLASS (gtk_old_editable_parent_class)->selection_clear_event (widget, event))
525 if (old_editable->has_selection)
527 old_editable->has_selection = FALSE;
528 gtk_old_editable_update_text (old_editable, old_editable->selection_start_pos,
529 old_editable->selection_end_pos);
536 gtk_old_editable_selection_get (GtkWidget *widget,
537 GtkSelectionData *selection_data,
541 GtkOldEditable *old_editable = GTK_OLD_EDITABLE (widget);
542 gint selection_start_pos;
543 gint selection_end_pos;
547 selection_start_pos = MIN (old_editable->selection_start_pos, old_editable->selection_end_pos);
548 selection_end_pos = MAX (old_editable->selection_start_pos, old_editable->selection_end_pos);
550 str = gtk_old_editable_get_public_chars (old_editable,
556 gtk_selection_data_set_text (selection_data, str, -1);
562 gtk_old_editable_paste_received (GtkOldEditable *old_editable,
564 gboolean is_clipboard)
566 const gchar *str = NULL;
567 const gchar *charset;
568 gboolean need_conversion = FALSE;
572 GError *error = NULL;
574 need_conversion = !g_get_charset (&charset);
578 str = g_convert_with_fallback (text, -1,
579 charset, "UTF-8", NULL,
583 g_warning ("Cannot convert text from UTF-8 to %s: %s",
584 charset, error->message);
585 g_error_free (error);
601 if ((old_editable->selection_start_pos != old_editable->selection_end_pos) &&
602 (!old_editable->has_selection || is_clipboard))
606 /* Don't want to call gtk_editable_delete_selection here if we are going
607 * to reclaim the selection to avoid extra server traffic */
608 if (old_editable->has_selection)
610 gtk_editable_delete_text (GTK_EDITABLE (old_editable),
611 MIN (old_editable->selection_start_pos, old_editable->selection_end_pos),
612 MAX (old_editable->selection_start_pos, old_editable->selection_end_pos));
615 gtk_editable_delete_selection (GTK_EDITABLE (old_editable));
618 tmp_pos = old_pos = old_editable->current_pos;
620 gtk_editable_insert_text (GTK_EDITABLE (old_editable), str, -1, &tmp_pos);
623 gtk_old_editable_set_selection (old_editable, old_pos, old_editable->current_pos);
625 if (str && str != text)
626 g_free ((gchar *) str);
631 gtk_old_editable_selection_received (GtkWidget *widget,
632 GtkSelectionData *selection_data,
635 GtkOldEditable *old_editable = GTK_OLD_EDITABLE (widget);
637 gchar *text = gtk_selection_data_get_text (selection_data);
641 /* If we asked for UTF8 and didn't get it, try text; if we asked
642 * for text and didn't get it, try string. If we asked for
643 * anything else and didn't get it, give up.
645 if (selection_data->target == gdk_atom_intern_static_string ("UTF8_STRING"))
647 gtk_selection_convert (widget, GDK_SELECTION_PRIMARY,
648 gdk_atom_intern_static_string ("TEXT"),
652 else if (selection_data->target == gdk_atom_intern_static_string ("TEXT"))
654 gtk_selection_convert (widget, GDK_SELECTION_PRIMARY,
663 gtk_old_editable_paste_received (old_editable, text, FALSE);
669 old_editable_text_received_cb (GtkClipboard *clipboard,
673 GtkOldEditable *old_editable = GTK_OLD_EDITABLE (data);
675 gtk_old_editable_paste_received (old_editable, text, TRUE);
676 g_object_unref (G_OBJECT (old_editable));
680 * gtk_old_editable_claim_selection:
681 * @old_editable: a #GtkOldEditable
682 * @claim: if %TRUE, claim ownership of the selection, if %FALSE, give
684 * @time_: timestamp for this operation
686 * Claims or gives up ownership of the selection.
689 gtk_old_editable_claim_selection (GtkOldEditable *old_editable,
693 GtkWidget *widget = GTK_WIDGET (old_editable);
694 GdkDisplay *display = gtk_widget_get_display (widget);
696 g_return_if_fail (GTK_IS_OLD_EDITABLE (old_editable));
697 g_return_if_fail (GTK_WIDGET_REALIZED (old_editable));
699 old_editable->has_selection = FALSE;
703 if (gtk_selection_owner_set_for_display (display, widget,
704 GDK_SELECTION_PRIMARY, time))
705 old_editable->has_selection = TRUE;
709 if (gdk_selection_owner_get_for_display (display, GDK_SELECTION_PRIMARY) == widget->window)
710 gtk_selection_owner_set_for_display (display,
712 GDK_SELECTION_PRIMARY, time);
717 gtk_old_editable_set_selection_bounds (GtkEditable *editable,
721 GtkOldEditable *old_editable = GTK_OLD_EDITABLE (editable);
723 if (GTK_WIDGET_REALIZED (editable))
724 gtk_old_editable_claim_selection (old_editable, start != end, GDK_CURRENT_TIME);
726 gtk_old_editable_set_selection (old_editable, start, end);
730 gtk_old_editable_get_selection_bounds (GtkEditable *editable,
734 GtkOldEditable *old_editable = GTK_OLD_EDITABLE (editable);
736 *start = old_editable->selection_start_pos;
737 *end = old_editable->selection_end_pos;
739 return (old_editable->selection_start_pos != old_editable->selection_end_pos);
743 gtk_old_editable_real_set_editable (GtkOldEditable *old_editable,
744 gboolean is_editable)
746 is_editable = is_editable != FALSE;
748 if (old_editable->editable != is_editable)
750 old_editable->editable = is_editable;
751 gtk_widget_queue_draw (GTK_WIDGET (old_editable));
756 gtk_old_editable_real_cut_clipboard (GtkOldEditable *old_editable)
758 gtk_old_editable_real_copy_clipboard (old_editable);
759 gtk_editable_delete_selection (GTK_EDITABLE (old_editable));
763 gtk_old_editable_real_copy_clipboard (GtkOldEditable *old_editable)
765 gint selection_start_pos;
766 gint selection_end_pos;
768 selection_start_pos = MIN (old_editable->selection_start_pos, old_editable->selection_end_pos);
769 selection_end_pos = MAX (old_editable->selection_start_pos, old_editable->selection_end_pos);
771 if (selection_start_pos != selection_end_pos)
773 gchar *text = gtk_old_editable_get_public_chars (old_editable,
779 GtkClipboard *clipboard = gtk_widget_get_clipboard (GTK_WIDGET (old_editable),
780 GDK_SELECTION_CLIPBOARD);
782 gtk_clipboard_set_text (clipboard, text, -1);
789 gtk_old_editable_real_paste_clipboard (GtkOldEditable *old_editable)
791 GtkClipboard *clipboard = gtk_widget_get_clipboard (GTK_WIDGET (old_editable),
792 GDK_SELECTION_CLIPBOARD);
794 g_object_ref (G_OBJECT (old_editable));
795 gtk_clipboard_request_text (clipboard, old_editable_text_received_cb, old_editable);
799 * gtk_old_editable_changed:
800 * @old_editable: a #GtkOldEditable
802 * Emits the ::changed signal on @old_editable.
805 gtk_old_editable_changed (GtkOldEditable *old_editable)
807 g_return_if_fail (GTK_IS_OLD_EDITABLE (old_editable));
809 g_signal_emit_by_name (old_editable, "changed");
812 #define __GTK_OLD_EDITABLE_C__
813 #include "gtkaliasdef.c"