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