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