]> Pileus Git - ~andy/gtk/blob - gtk/gtkoldeditable.c
Deprecation cleanup
[~andy/gtk] / gtk / gtkoldeditable.c
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, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
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/. 
25  */
26
27 #include <string.h>
28 #include "gdk/gdkkeysyms.h"
29 #include "gdk/gdki18n.h"
30 #include "gtkclipboard.h"
31 #include "gtkoldeditable.h"
32 #include "gtkmain.h"
33 #include "gtkmarshalers.h"
34 #include "gtkselection.h"
35 #include "gtksignal.h"
36
37 #define MIN_EDITABLE_WIDTH  150
38 #define DRAW_TIMEOUT     20
39 #define INNER_BORDER     2
40
41 enum {
42   /* Binding actions */
43   ACTIVATE,
44   SET_EDITABLE,
45   MOVE_CURSOR,
46   MOVE_WORD,
47   MOVE_PAGE,
48   MOVE_TO_ROW,
49   MOVE_TO_COLUMN,
50   KILL_CHAR,
51   KILL_WORD,
52   KILL_LINE,
53   CUT_CLIPBOARD,
54   COPY_CLIPBOARD,
55   PASTE_CLIPBOARD,
56   LAST_SIGNAL
57 };
58
59 enum {
60   ARG_0,
61   ARG_TEXT_POSITION,
62   ARG_EDITABLE
63 };
64
65 /* values for selection info */
66
67 enum {
68   TARGET_STRING,
69   TARGET_TEXT,
70   TARGET_COMPOUND_TEXT
71 };
72
73 static void  gtk_old_editable_class_init           (GtkOldEditableClass *klass);
74 static void  gtk_old_editable_editable_init        (GtkEditableClass    *iface);
75 static void  gtk_old_editable_init                 (GtkOldEditable      *editable);
76 static void  gtk_old_editable_set_arg              (GtkObject           *object,
77                                                     GtkArg              *arg,
78                                                     guint                arg_id);
79 static void  gtk_old_editable_get_arg              (GtkObject           *object,
80                                                     GtkArg              *arg,
81                                                     guint                arg_id);
82 static void *gtk_old_editable_get_public_chars     (GtkOldEditable      *old_editable,
83                                                     gint                 start,
84                                                     gint                 end);
85
86 static gint gtk_old_editable_selection_clear    (GtkWidget         *widget,
87                                                  GdkEventSelection *event);
88 static void gtk_old_editable_selection_get      (GtkWidget         *widget,
89                                                  GtkSelectionData  *selection_data,
90                                                  guint              info,
91                                                  guint              time);
92 static void gtk_old_editable_selection_received (GtkWidget         *widget,
93                                                  GtkSelectionData  *selection_data,
94                                                  guint              time);
95
96 static void  gtk_old_editable_set_selection        (GtkOldEditable      *old_editable,
97                                                     gint                 start,
98                                                     gint                 end);
99
100 static void gtk_old_editable_real_set_editable    (GtkOldEditable *old_editable,
101                                                    gboolean        is_editable);
102 static void gtk_old_editable_real_cut_clipboard   (GtkOldEditable *old_editable);
103 static void gtk_old_editable_real_copy_clipboard  (GtkOldEditable *old_editable);
104 static void gtk_old_editable_real_paste_clipboard (GtkOldEditable *old_editable);
105
106 static void     gtk_old_editable_insert_text         (GtkEditable *editable,
107                                                       const gchar *new_text,
108                                                       gint         new_text_length,
109                                                       gint        *position);
110 static void     gtk_old_editable_delete_text         (GtkEditable *editable,
111                                                       gint         start_pos,
112                                                       gint         end_pos);
113 static gchar *  gtk_old_editable_get_chars           (GtkEditable *editable,
114                                                       gint         start,
115                                                       gint         end);
116 static void     gtk_old_editable_set_selection_bounds (GtkEditable *editable,
117                                                        gint         start,
118                                                        gint         end);
119 static gboolean gtk_old_editable_get_selection_bounds (GtkEditable *editable,
120                                                        gint        *start,
121                                                        gint        *end);
122 static void     gtk_old_editable_set_position        (GtkEditable *editable,
123                                                       gint         position);
124 static gint     gtk_old_editable_get_position        (GtkEditable *editable);
125
126 static GtkWidgetClass *parent_class = NULL;
127 static guint editable_signals[LAST_SIGNAL] = { 0 };
128
129 GtkType
130 gtk_old_editable_get_type (void)
131 {
132   static GtkType old_editable_type = 0;
133
134   if (!old_editable_type)
135     {
136       static const GTypeInfo old_editable_info =
137       {
138         sizeof (GtkOldEditableClass),
139         NULL,           /* base_init */
140         NULL,           /* base_finalize */
141         (GClassInitFunc) gtk_old_editable_class_init,
142         NULL,           /* class_finalize */
143         NULL,           /* class_data */
144         sizeof (GtkOldEditable),
145         0,              /* n_preallocs */
146         (GInstanceInitFunc) gtk_old_editable_init,
147         NULL,           /* value_table */
148       };
149
150       static const GInterfaceInfo editable_info =
151       {
152         (GInterfaceInitFunc) gtk_old_editable_editable_init,     /* interface_init */
153         NULL,                                                    /* interface_finalize */
154         NULL                                                     /* interface_data */
155       };
156
157       old_editable_type = g_type_register_static (GTK_TYPE_WIDGET, "GtkOldEditable",
158                                                   &old_editable_info, G_TYPE_FLAG_ABSTRACT);
159       g_type_add_interface_static (old_editable_type,
160                                    GTK_TYPE_EDITABLE,
161                                    &editable_info);
162     }
163
164   return old_editable_type;
165 }
166
167 static void
168 gtk_old_editable_class_init (GtkOldEditableClass *class)
169 {
170   GtkObjectClass *object_class;
171   GtkWidgetClass *widget_class;
172
173   object_class = (GtkObjectClass*) class;
174   widget_class = (GtkWidgetClass*) class;
175
176   parent_class = gtk_type_class (GTK_TYPE_WIDGET);
177     
178   object_class->set_arg = gtk_old_editable_set_arg;
179   object_class->get_arg = gtk_old_editable_get_arg;
180
181   widget_class->selection_clear_event = gtk_old_editable_selection_clear;
182   widget_class->selection_received = gtk_old_editable_selection_received;
183   widget_class->selection_get = gtk_old_editable_selection_get;
184
185   class->activate = NULL;
186   class->set_editable = gtk_old_editable_real_set_editable;
187
188   class->move_cursor = NULL;
189   class->move_word = NULL;
190   class->move_page = NULL;
191   class->move_to_row = NULL;
192   class->move_to_column = NULL;
193
194   class->kill_char = NULL;
195   class->kill_word = NULL;
196   class->kill_line = NULL;
197
198   class->cut_clipboard = gtk_old_editable_real_cut_clipboard;
199   class->copy_clipboard = gtk_old_editable_real_copy_clipboard;
200   class->paste_clipboard = gtk_old_editable_real_paste_clipboard;
201
202   class->update_text = NULL;
203   class->get_chars = NULL;
204   class->set_selection = NULL;
205   class->set_position = NULL;
206
207   editable_signals[ACTIVATE] =
208     gtk_signal_new ("activate",
209                     GTK_RUN_LAST | GTK_RUN_ACTION,
210                     GTK_CLASS_TYPE (object_class),
211                     GTK_SIGNAL_OFFSET (GtkOldEditableClass, activate),
212                     _gtk_marshal_NONE__NONE,
213                     GTK_TYPE_NONE, 0);
214   widget_class->activate_signal = editable_signals[ACTIVATE];
215
216   editable_signals[SET_EDITABLE] =
217     gtk_signal_new ("set-editable",
218                     GTK_RUN_LAST | GTK_RUN_ACTION,
219                     GTK_CLASS_TYPE (object_class),
220                     GTK_SIGNAL_OFFSET (GtkOldEditableClass, set_editable),
221                     _gtk_marshal_NONE__BOOLEAN,
222                     GTK_TYPE_NONE, 1,
223                     GTK_TYPE_BOOL);
224
225   editable_signals[MOVE_CURSOR] =
226     gtk_signal_new ("move_cursor",
227                     GTK_RUN_LAST | GTK_RUN_ACTION,
228                     GTK_CLASS_TYPE (object_class),
229                     GTK_SIGNAL_OFFSET (GtkOldEditableClass, move_cursor),
230                     _gtk_marshal_NONE__INT_INT,
231                     GTK_TYPE_NONE, 2, 
232                     GTK_TYPE_INT, 
233                     GTK_TYPE_INT);
234
235   editable_signals[MOVE_WORD] =
236     gtk_signal_new ("move_word",
237                     GTK_RUN_LAST | GTK_RUN_ACTION,
238                     GTK_CLASS_TYPE (object_class),
239                     GTK_SIGNAL_OFFSET (GtkOldEditableClass, move_word),
240                     _gtk_marshal_NONE__INT,
241                     GTK_TYPE_NONE, 1, 
242                     GTK_TYPE_INT);
243
244   editable_signals[MOVE_PAGE] =
245     gtk_signal_new ("move_page",
246                     GTK_RUN_LAST | GTK_RUN_ACTION,
247                     GTK_CLASS_TYPE (object_class),
248                     GTK_SIGNAL_OFFSET (GtkOldEditableClass, move_page),
249                     _gtk_marshal_NONE__INT_INT,
250                     GTK_TYPE_NONE, 2, 
251                     GTK_TYPE_INT, 
252                     GTK_TYPE_INT);
253
254   editable_signals[MOVE_TO_ROW] =
255     gtk_signal_new ("move_to_row",
256                     GTK_RUN_LAST | GTK_RUN_ACTION,
257                     GTK_CLASS_TYPE (object_class),
258                     GTK_SIGNAL_OFFSET (GtkOldEditableClass, move_to_row),
259                     _gtk_marshal_NONE__INT,
260                     GTK_TYPE_NONE, 1, 
261                     GTK_TYPE_INT);
262
263   editable_signals[MOVE_TO_COLUMN] =
264     gtk_signal_new ("move_to_column",
265                     GTK_RUN_LAST | GTK_RUN_ACTION,
266                     GTK_CLASS_TYPE (object_class),
267                     GTK_SIGNAL_OFFSET (GtkOldEditableClass, move_to_column),
268                     _gtk_marshal_NONE__INT,
269                     GTK_TYPE_NONE, 1, 
270                     GTK_TYPE_INT);
271
272   editable_signals[KILL_CHAR] =
273     gtk_signal_new ("kill_char",
274                     GTK_RUN_LAST | GTK_RUN_ACTION,
275                     GTK_CLASS_TYPE (object_class),
276                     GTK_SIGNAL_OFFSET (GtkOldEditableClass, kill_char),
277                     _gtk_marshal_NONE__INT,
278                     GTK_TYPE_NONE, 1, 
279                     GTK_TYPE_INT);
280
281   editable_signals[KILL_WORD] =
282     gtk_signal_new ("kill_word",
283                     GTK_RUN_LAST | GTK_RUN_ACTION,
284                     GTK_CLASS_TYPE (object_class),
285                     GTK_SIGNAL_OFFSET (GtkOldEditableClass, kill_word),
286                     _gtk_marshal_NONE__INT,
287                     GTK_TYPE_NONE, 1, 
288                     GTK_TYPE_INT);
289
290   editable_signals[KILL_LINE] =
291     gtk_signal_new ("kill_line",
292                     GTK_RUN_LAST | GTK_RUN_ACTION,
293                     GTK_CLASS_TYPE (object_class),
294                     GTK_SIGNAL_OFFSET (GtkOldEditableClass, kill_line),
295                     _gtk_marshal_NONE__INT,
296                     GTK_TYPE_NONE, 1, 
297                     GTK_TYPE_INT);
298
299   editable_signals[CUT_CLIPBOARD] =
300     gtk_signal_new ("cut_clipboard",
301                     GTK_RUN_LAST | GTK_RUN_ACTION,
302                     GTK_CLASS_TYPE (object_class),
303                     GTK_SIGNAL_OFFSET (GtkOldEditableClass, cut_clipboard),
304                     _gtk_marshal_NONE__NONE,
305                     GTK_TYPE_NONE, 0);
306
307   editable_signals[COPY_CLIPBOARD] =
308     gtk_signal_new ("copy_clipboard",
309                     GTK_RUN_LAST | GTK_RUN_ACTION,
310                     GTK_CLASS_TYPE (object_class),
311                     GTK_SIGNAL_OFFSET (GtkOldEditableClass, copy_clipboard),
312                     _gtk_marshal_NONE__NONE,
313                     GTK_TYPE_NONE, 0);
314
315   editable_signals[PASTE_CLIPBOARD] =
316     gtk_signal_new ("paste_clipboard",
317                     GTK_RUN_LAST | GTK_RUN_ACTION,
318                     GTK_CLASS_TYPE (object_class),
319                     GTK_SIGNAL_OFFSET (GtkOldEditableClass, paste_clipboard),
320                     _gtk_marshal_NONE__NONE,
321                     GTK_TYPE_NONE, 0);
322
323   gtk_object_add_arg_type ("GtkOldEditable::text_position", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_TEXT_POSITION);
324   gtk_object_add_arg_type ("GtkOldEditable::editable", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_EDITABLE);
325 }
326
327 static void
328 gtk_old_editable_editable_init (GtkEditableClass *iface)
329 {
330   iface->do_insert_text = gtk_old_editable_insert_text;
331   iface->do_delete_text = gtk_old_editable_delete_text;
332   iface->get_chars = gtk_old_editable_get_chars;
333   iface->set_selection_bounds = gtk_old_editable_set_selection_bounds;
334   iface->get_selection_bounds = gtk_old_editable_get_selection_bounds;
335   iface->set_position = gtk_old_editable_set_position;
336   iface->get_position = gtk_old_editable_get_position;
337 }
338
339 static void
340 gtk_old_editable_set_arg (GtkObject *object,
341                           GtkArg    *arg,
342                           guint      arg_id)
343 {
344   GtkEditable *editable = GTK_EDITABLE (object);
345
346   switch (arg_id)
347     {
348     case ARG_TEXT_POSITION:
349       gtk_editable_set_position (editable, GTK_VALUE_INT (*arg));
350       break;
351     case ARG_EDITABLE:
352       gtk_signal_emit (object, editable_signals[SET_EDITABLE],
353                        GTK_VALUE_BOOL (*arg) != FALSE);
354       break;
355     default:
356       break;
357     }
358 }
359
360 static void
361 gtk_old_editable_get_arg (GtkObject *object,
362                           GtkArg    *arg,
363                           guint      arg_id)
364 {
365   GtkOldEditable *old_editable;
366
367   old_editable = GTK_OLD_EDITABLE (object);
368
369   switch (arg_id)
370     {
371     case ARG_TEXT_POSITION:
372       GTK_VALUE_INT (*arg) = old_editable->current_pos;
373       break;
374     case ARG_EDITABLE:
375       GTK_VALUE_BOOL (*arg) = old_editable->editable;
376       break;
377     default:
378       arg->type = GTK_TYPE_INVALID;
379       break;
380     }
381 }
382
383 static void
384 gtk_old_editable_init (GtkOldEditable *old_editable)
385 {
386   static const GtkTargetEntry targets[] = {
387     { "UTF8_STRING", 0, 0 },
388     { "STRING", 0, 0 },
389     { "TEXT",   0, 0 }, 
390     { "COMPOUND_TEXT", 0, 0 }
391   };
392
393   GTK_WIDGET_SET_FLAGS (old_editable, GTK_CAN_FOCUS);
394
395   old_editable->selection_start_pos = 0;
396   old_editable->selection_end_pos = 0;
397   old_editable->has_selection = FALSE;
398   old_editable->editable = 1;
399   old_editable->visible = 1;
400   old_editable->clipboard_text = NULL;
401
402   gtk_selection_add_targets (GTK_WIDGET (old_editable), GDK_SELECTION_PRIMARY,
403                              targets, G_N_ELEMENTS (targets));
404 }
405
406 static void
407 gtk_old_editable_insert_text (GtkEditable *editable,
408                               const gchar *new_text,
409                               gint         new_text_length,
410                               gint        *position)
411 {
412   gchar buf[64];
413   gchar *text;
414
415   gtk_widget_ref (GTK_WIDGET (editable));
416
417   if (new_text_length <= 63)
418     text = buf;
419   else
420     text = g_new (gchar, new_text_length + 1);
421
422   text[new_text_length] = '\0';
423   strncpy (text, new_text, new_text_length);
424   
425   g_signal_emit_by_name (editable, "insert_text", text, new_text_length,
426                          position);
427   g_signal_emit_by_name (editable, "changed");
428   
429   if (new_text_length > 63)
430     g_free (text);
431
432   gtk_widget_unref (GTK_WIDGET (editable));
433 }
434
435 static void
436 gtk_old_editable_delete_text (GtkEditable *editable,
437                               gint         start_pos,
438                               gint         end_pos)
439 {
440   GtkOldEditable *old_editable = GTK_OLD_EDITABLE (editable);
441
442   gtk_widget_ref (GTK_WIDGET (old_editable));
443
444   g_signal_emit_by_name (editable, "delete_text", start_pos, end_pos);
445   g_signal_emit_by_name (editable, "changed");
446
447   if (old_editable->selection_start_pos == old_editable->selection_end_pos &&
448       old_editable->has_selection)
449     gtk_old_editable_claim_selection (old_editable, FALSE, GDK_CURRENT_TIME);
450   
451   gtk_widget_unref (GTK_WIDGET (old_editable));
452 }
453
454 static void
455 gtk_old_editable_update_text (GtkOldEditable *old_editable,
456                               gint            start_pos,
457                               gint            end_pos)
458 {
459   GtkOldEditableClass *klass = GTK_OLD_EDITABLE_GET_CLASS (old_editable);
460   klass->update_text (GTK_OLD_EDITABLE (old_editable), start_pos, end_pos);
461 }
462
463 static gchar *    
464 gtk_old_editable_get_chars  (GtkEditable      *editable,
465                              gint              start,
466                              gint              end)
467 {
468   GtkOldEditableClass *klass = GTK_OLD_EDITABLE_GET_CLASS (editable);
469   return klass->get_chars (GTK_OLD_EDITABLE (editable), start, end);
470 }
471
472 /*
473  * Like gtk_editable_get_chars, but if the editable is not
474  * visible, return asterisks; also convert result to UTF-8.
475  */
476 static void *    
477 gtk_old_editable_get_public_chars (GtkOldEditable   *old_editable,
478                                    gint              start,
479                                    gint              end)
480 {
481   gchar *str = NULL;
482   const gchar *charset;
483   gboolean need_conversion = !g_get_charset (&charset);
484
485   if (old_editable->visible)
486     {
487       GError *error = NULL;
488       gchar *tmp = gtk_editable_get_chars (GTK_EDITABLE (old_editable), start, end);
489
490       if (need_conversion)
491         {
492           str = g_convert (tmp, -1,
493                            "UTF-8", charset,
494                            NULL, NULL, &error);
495           
496           if (!str)
497             {
498               g_warning ("Cannot convert text from charset to UTF-8 %s: %s", charset, error->message);
499               g_error_free (error);
500             }
501
502           g_free (tmp);
503         }
504       else
505         str = tmp;
506     }
507   else
508     {
509       gint i;
510       gint nchars = end - start;
511        
512       if (nchars < 0)
513         nchars = -nchars;
514
515       str = g_new (gchar, nchars + 1);
516       for (i = 0; i<nchars; i++)
517         str[i] = '*';
518       str[i] = '\0';
519     }
520
521   return str;
522 }
523
524 static void
525 gtk_old_editable_set_selection (GtkOldEditable *old_editable,
526                                 gint            start_pos,
527                                 gint            end_pos)
528 {
529   GtkOldEditableClass *klass = GTK_OLD_EDITABLE_GET_CLASS (old_editable);
530   klass->set_selection (old_editable, start_pos, end_pos);
531 }
532
533 static void
534 gtk_old_editable_set_position (GtkEditable *editable,
535                                gint            position)
536 {
537   GtkOldEditableClass *klass = GTK_OLD_EDITABLE_GET_CLASS (editable);
538
539   klass->set_position (GTK_OLD_EDITABLE (editable), position);
540 }
541
542 static gint
543 gtk_old_editable_get_position (GtkEditable *editable)
544 {
545   return GTK_OLD_EDITABLE (editable)->current_pos;
546 }
547
548 static gint
549 gtk_old_editable_selection_clear (GtkWidget         *widget,
550                                   GdkEventSelection *event)
551 {
552   GtkOldEditable *old_editable = GTK_OLD_EDITABLE (widget);
553   
554   /* Let the selection handling code know that the selection
555    * has been changed, since we've overriden the default handler */
556   if (!parent_class->selection_clear_event (widget, event))
557     return FALSE;
558   
559   if (old_editable->has_selection)
560     {
561       old_editable->has_selection = FALSE;
562       gtk_old_editable_update_text (old_editable, old_editable->selection_start_pos,
563                                     old_editable->selection_end_pos);
564     }
565   
566   return TRUE;
567 }
568
569 static void
570 gtk_old_editable_selection_get (GtkWidget        *widget,
571                                 GtkSelectionData *selection_data,
572                                 guint             info,
573                                 guint             time)
574 {
575   GtkOldEditable *old_editable = GTK_OLD_EDITABLE (widget);
576   gint selection_start_pos;
577   gint selection_end_pos;
578
579   gchar *str;
580
581   selection_start_pos = MIN (old_editable->selection_start_pos, old_editable->selection_end_pos);
582   selection_end_pos = MAX (old_editable->selection_start_pos, old_editable->selection_end_pos);
583
584   str = gtk_old_editable_get_public_chars (old_editable, 
585                                            selection_start_pos, 
586                                            selection_end_pos);
587
588   if (str)
589     {
590       gtk_selection_data_set_text (selection_data, str, -1);
591       g_free (str);
592     }
593 }
594
595 static void
596 gtk_old_editable_paste_received (GtkOldEditable *old_editable,
597                                  const gchar    *text,
598                                  gboolean        is_clipboard)
599 {
600   const gchar *str = NULL;
601   const gchar *charset;
602   gboolean need_conversion = FALSE;
603
604   if (text)
605     {
606       GError *error = NULL;
607       
608       need_conversion = !g_get_charset (&charset);
609
610       if (need_conversion)
611         {
612           str = g_convert_with_fallback (text, -1,
613                                          charset, "UTF-8", NULL,
614                                          NULL, NULL, &error);
615           if (!str)
616             {
617               g_warning ("Cannot convert text from UTF-8 to %s: %s",
618                          charset, error->message);
619               g_error_free (error);
620               return;
621             }
622         }
623       else
624         str = text;
625     }
626
627   if (str)
628     {
629       gboolean reselect;
630       gint old_pos;
631       gint tmp_pos;
632   
633       reselect = FALSE;
634
635       if ((old_editable->selection_start_pos != old_editable->selection_end_pos) && 
636           (!old_editable->has_selection || is_clipboard))
637         {
638           reselect = TRUE;
639           
640           /* Don't want to call gtk_editable_delete_selection here if we are going
641            * to reclaim the selection to avoid extra server traffic */
642           if (old_editable->has_selection)
643             {
644               gtk_editable_delete_text (GTK_EDITABLE (old_editable),
645                                         MIN (old_editable->selection_start_pos, old_editable->selection_end_pos),
646                                         MAX (old_editable->selection_start_pos, old_editable->selection_end_pos));
647             }
648           else
649             gtk_editable_delete_selection (GTK_EDITABLE (old_editable));
650         }
651       
652       tmp_pos = old_pos = old_editable->current_pos;
653       
654       gtk_editable_insert_text (GTK_EDITABLE (old_editable), str, -1, &tmp_pos);
655
656       if (reselect)
657         gtk_old_editable_set_selection (old_editable, old_pos, old_editable->current_pos);
658
659       if (str && str != text)
660         g_free ((gchar *) str);
661     }
662 }
663
664 static void
665 gtk_old_editable_selection_received  (GtkWidget         *widget,
666                                       GtkSelectionData  *selection_data,
667                                       guint              time)
668 {
669   GtkOldEditable *old_editable = GTK_OLD_EDITABLE (widget);
670
671   gchar *text = gtk_selection_data_get_text (selection_data);
672
673   if (!text)
674     {
675       /* If we asked for UTF8 and didn't get it, try text; if we asked
676        * for text and didn't get it, try string.  If we asked for
677        * anything else and didn't get it, give up.
678        */
679       if (selection_data->target == gdk_atom_intern ("UTF8_STRING", FALSE))
680         {
681           gtk_selection_convert (widget, GDK_SELECTION_PRIMARY,
682                                  gdk_atom_intern ("TEXT", FALSE),
683                                  time);
684           return;
685         }
686       else if (selection_data->target == gdk_atom_intern ("TEXT", FALSE))
687         {
688           gtk_selection_convert (widget, GDK_SELECTION_PRIMARY,
689                                  GDK_TARGET_STRING,
690                                  time);
691           return;
692         }
693     }
694
695   if (text)
696     {
697       gtk_old_editable_paste_received (old_editable, text, FALSE);
698       g_free (text);
699     }
700 }
701
702 static void
703 old_editable_text_received_cb (GtkClipboard *clipboard,
704                                const gchar  *text,
705                                gpointer      data)
706 {
707   GtkOldEditable *old_editable = GTK_OLD_EDITABLE (data);
708
709   gtk_old_editable_paste_received (old_editable, text, TRUE);
710   g_object_unref (G_OBJECT (old_editable));
711 }
712
713 /**
714  * gtk_old_editable_claim_selection:
715  * @old_editable: a #GtkOldEditable
716  * @claim: if %TRUE, claim ownership of the selection, if %FALSE, give
717  *   up ownership
718  * @time: timestamp for this operation
719  * 
720  * Claims or gives up ownership of the selection.
721  */
722 void
723 gtk_old_editable_claim_selection (GtkOldEditable *old_editable, 
724                                   gboolean        claim, 
725                                   guint32         time)
726 {
727   GtkWidget *widget = GTK_WIDGET (old_editable);
728   GdkDisplay *display = gtk_widget_get_display (widget);
729   
730   g_return_if_fail (GTK_IS_OLD_EDITABLE (old_editable));
731   g_return_if_fail (GTK_WIDGET_REALIZED (old_editable));
732
733   old_editable->has_selection = FALSE;
734   
735   if (claim)
736     {
737       if (gtk_selection_owner_set_for_display (display, widget,
738                                                GDK_SELECTION_PRIMARY, time))
739         old_editable->has_selection = TRUE;
740     }
741   else
742     {
743       if (gdk_selection_owner_get_for_display (display, GDK_SELECTION_PRIMARY) == widget->window)
744         gtk_selection_owner_set_for_display (display,
745                                              NULL,
746                                              GDK_SELECTION_PRIMARY, time);
747     }
748 }
749
750 static void
751 gtk_old_editable_set_selection_bounds (GtkEditable *editable,
752                                        gint         start,
753                                        gint         end)
754 {
755   GtkOldEditable *old_editable = GTK_OLD_EDITABLE (editable);
756   
757   if (GTK_WIDGET_REALIZED (editable))
758     gtk_old_editable_claim_selection (old_editable, start != end, GDK_CURRENT_TIME);
759   
760   gtk_old_editable_set_selection (old_editable, start, end);
761 }
762
763 static gboolean
764 gtk_old_editable_get_selection_bounds (GtkEditable *editable,
765                                        gint        *start,
766                                        gint        *end)
767 {
768   GtkOldEditable *old_editable = GTK_OLD_EDITABLE (editable);
769
770   *start = old_editable->selection_start_pos;
771   *end = old_editable->selection_end_pos;
772
773   return (old_editable->selection_start_pos != old_editable->selection_end_pos);
774 }
775
776 static void
777 gtk_old_editable_real_set_editable (GtkOldEditable *old_editable,
778                                     gboolean        is_editable)
779 {
780   is_editable = is_editable != FALSE;
781
782   if (old_editable->editable != is_editable)
783     {
784       old_editable->editable = is_editable;
785       gtk_widget_queue_draw (GTK_WIDGET (old_editable));
786     }
787 }
788
789 static void
790 gtk_old_editable_real_cut_clipboard (GtkOldEditable *old_editable)
791 {
792   gtk_old_editable_real_copy_clipboard (old_editable);
793   gtk_editable_delete_selection (GTK_EDITABLE (old_editable));
794 }
795
796 static void
797 gtk_old_editable_real_copy_clipboard (GtkOldEditable *old_editable)
798 {
799   gint selection_start_pos; 
800   gint selection_end_pos;
801
802   selection_start_pos = MIN (old_editable->selection_start_pos, old_editable->selection_end_pos);
803   selection_end_pos = MAX (old_editable->selection_start_pos, old_editable->selection_end_pos);
804
805   if (selection_start_pos != selection_end_pos)
806     {
807       gchar *text = gtk_old_editable_get_public_chars (old_editable,
808                                                        selection_start_pos,
809                                                        selection_end_pos);
810
811       if (text)
812         {
813           GtkClipboard *clipboard = gtk_widget_get_clipboard (GTK_WIDGET (old_editable),
814                                                               GDK_SELECTION_CLIPBOARD);
815           
816           gtk_clipboard_set_text (clipboard, text, -1);
817           g_free (text);
818         }
819     }
820 }
821
822 static void
823 gtk_old_editable_real_paste_clipboard (GtkOldEditable *old_editable)
824 {
825   GtkClipboard *clipboard = gtk_widget_get_clipboard (GTK_WIDGET (old_editable), 
826                                                       GDK_SELECTION_CLIPBOARD);
827
828   g_object_ref (G_OBJECT (old_editable));
829   gtk_clipboard_request_text (clipboard, old_editable_text_received_cb, old_editable);
830 }
831
832 /**
833  * gtk_old_editable_changed:
834  * @old_editable: a #GtkOldEditable
835  *
836  * Emits the ::changed signal on @old_editable.
837  */
838 void
839 gtk_old_editable_changed (GtkOldEditable *old_editable)
840 {
841   g_return_if_fail (GTK_IS_OLD_EDITABLE (old_editable));
842   
843   g_signal_emit_by_name (old_editable, "changed");
844 }