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