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