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