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