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