]> Pileus Git - ~andy/gtk/blob - tests/testselection.c
add -DGTK_DISABLE_DEPRECATED. #undef it at the top of gtktypebuiltins.c.
[~andy/gtk] / tests / testselection.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 <stdio.h>
30 #include <string.h>
31 #define GTK_ENABLE_BROKEN
32 #include "gtk/gtk.h"
33
34 typedef enum {
35   SEL_TYPE_NONE,
36   APPLE_PICT,
37   ATOM,
38   ATOM_PAIR,
39   BITMAP,
40   C_STRING,
41   COLORMAP,
42   COMPOUND_TEXT,
43   DRAWABLE,
44   INTEGER,
45   PIXEL,
46   PIXMAP,
47   SPAN,
48   STRING,
49   TEXT,
50   WINDOW,
51   LAST_SEL_TYPE
52 } SelType;
53
54 GdkAtom seltypes[LAST_SEL_TYPE];
55
56 typedef struct _Target {
57   gchar *target_name;
58   SelType type;
59   GdkAtom target;
60   gint format;
61 } Target;
62
63 /* The following is a list of all the selection targets defined
64    in the ICCCM */
65
66 static Target targets[] = {
67   { "ADOBE_PORTABLE_DOCUMENT_FORMAT",       STRING,        0, 8 },
68   { "APPLE_PICT",                           APPLE_PICT,    0, 8 },
69   { "BACKGROUND",                           PIXEL,         0, 32 },
70   { "BITMAP",                               BITMAP,        0, 32 },
71   { "CHARACTER_POSITION",                   SPAN,          0, 32 },
72   { "CLASS",                                TEXT,          0, 8 },
73   { "CLIENT_WINDOW",                        WINDOW,        0, 32 },
74   { "COLORMAP",                             COLORMAP,      0, 32 },
75   { "COLUMN_NUMBER",                        SPAN,          0, 32 },
76   { "COMPOUND_TEXT",                        COMPOUND_TEXT, 0, 8 },
77   /*  { "DELETE", "NULL", 0, ? }, */
78   { "DRAWABLE",                             DRAWABLE,      0, 32 },
79   { "ENCAPSULATED_POSTSCRIPT",              STRING,        0, 8 },
80   { "ENCAPSULATED_POSTSCRIPT_INTERCHANGE",  STRING,        0, 8 },
81   { "FILE_NAME",                            TEXT,          0, 8 },
82   { "FOREGROUND",                           PIXEL,         0, 32 },
83   { "HOST_NAME",                            TEXT,          0, 8 },
84   /*  { "INSERT_PROPERTY", "NULL", 0, ? NULL }, */
85   /*  { "INSERT_SELECTION", "NULL", 0, ? NULL }, */
86   { "LENGTH",                               INTEGER,       0, 32 },
87   { "LINE_NUMBER",                          SPAN,          0, 32 },
88   { "LIST_LENGTH",                          INTEGER,       0, 32 },
89   { "MODULE",                               TEXT,          0, 8 },
90   /*  { "MULTIPLE", "ATOM_PAIR", 0, 32 }, */
91   { "NAME",                                 TEXT,          0, 8 },
92   { "ODIF",                                 TEXT,          0, 8 },
93   { "OWNER_OS",                             TEXT,          0, 8 },
94   { "PIXMAP",                               PIXMAP,        0, 32 },
95   { "POSTSCRIPT",                           STRING,        0, 8 },
96   { "PROCEDURE",                            TEXT,          0, 8 },
97   { "PROCESS",                              INTEGER,       0, 32 },
98   { "STRING",                               STRING,        0, 8 },
99   { "TARGETS",                              ATOM,          0, 32 },
100   { "TASK",                                 INTEGER,       0, 32 },
101   { "TEXT",                                 TEXT,          0, 8  },
102   { "TIMESTAMP",                            INTEGER,       0, 32 },
103   { "USER",                                 TEXT,          0, 8 },
104 };
105
106 static int num_targets = sizeof(targets)/sizeof(Target);
107
108 static int have_selection = FALSE;
109
110 GtkWidget *selection_widget;
111 GtkWidget *selection_text;
112 GtkWidget *selection_button;
113 GString *selection_string = NULL;
114
115 static void
116 init_atoms (void)
117 {
118   int i;
119
120   seltypes[SEL_TYPE_NONE] = GDK_NONE;
121   seltypes[APPLE_PICT] = gdk_atom_intern ("APPLE_PICT",FALSE);
122   seltypes[ATOM]       = gdk_atom_intern ("ATOM",FALSE);
123   seltypes[ATOM_PAIR]  = gdk_atom_intern ("ATOM_PAIR",FALSE);
124   seltypes[BITMAP]     = gdk_atom_intern ("BITMAP",FALSE);
125   seltypes[C_STRING]   = gdk_atom_intern ("C_STRING",FALSE);
126   seltypes[COLORMAP]   = gdk_atom_intern ("COLORMAP",FALSE);
127   seltypes[COMPOUND_TEXT] = gdk_atom_intern ("COMPOUND_TEXT",FALSE);
128   seltypes[DRAWABLE]   = gdk_atom_intern ("DRAWABLE",FALSE);
129   seltypes[INTEGER]    = gdk_atom_intern ("INTEGER",FALSE);
130   seltypes[PIXEL]      = gdk_atom_intern ("PIXEL",FALSE);
131   seltypes[PIXMAP]     = gdk_atom_intern ("PIXMAP",FALSE);
132   seltypes[SPAN]       = gdk_atom_intern ("SPAN",FALSE);
133   seltypes[STRING]     = gdk_atom_intern ("STRING",FALSE);
134   seltypes[TEXT]       = gdk_atom_intern ("TEXT",FALSE);
135   seltypes[WINDOW]     = gdk_atom_intern ("WINDOW",FALSE);
136
137   for (i=0; i<num_targets; i++)
138     targets[i].target = gdk_atom_intern (targets[i].target_name, FALSE);
139 }
140
141 void
142 selection_toggled (GtkWidget *widget)
143 {
144   if (GTK_TOGGLE_BUTTON(widget)->active)
145     {
146       have_selection = gtk_selection_owner_set (selection_widget,
147                                                 GDK_SELECTION_PRIMARY,
148                                                 GDK_CURRENT_TIME);
149       if (!have_selection)
150         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(widget), FALSE);
151     }
152   else
153     {
154       if (have_selection)
155         {
156           if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window)
157             gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY,
158                                      GDK_CURRENT_TIME);
159           have_selection = FALSE;
160         }
161     }
162 }
163
164 void
165 selection_get (GtkWidget *widget, 
166                GtkSelectionData *selection_data,
167                guint      info,
168                guint      time,
169                gpointer   data)
170 {
171   guchar *buffer;
172   gint len;
173   GdkAtom type = GDK_NONE;
174
175   if (!selection_string)
176     {
177       buffer = NULL;
178       len = 0;
179     }      
180   else
181     {
182       buffer = (guchar *)selection_string->str;
183       len = selection_string->len;
184     }
185
186   switch (info)
187     {
188     case COMPOUND_TEXT:
189     case TEXT:
190       type = seltypes[COMPOUND_TEXT];
191     case STRING:
192       type = seltypes[STRING];
193     }
194   
195   gtk_selection_data_set (selection_data, type, 8, buffer, len);
196 }
197
198 gint
199 selection_clear (GtkWidget *widget, GdkEventSelection *event)
200 {
201   have_selection = FALSE;
202   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(selection_button), FALSE);
203
204   return TRUE;
205 }
206
207 gchar *
208 stringify_atom (guchar *data, gint *position)
209 {
210   gchar *str = gdk_atom_name (*(GdkAtom *)(data+*position));
211   *position += sizeof(GdkAtom);
212     
213   return str;
214 }
215
216 gchar *
217 stringify_text (guchar *data, gint *position)
218 {
219   gchar *str = g_strdup ((gchar *)(data+*position));
220   *position += strlen (str) + 1;
221     
222   return str;
223 }
224
225 gchar *
226 stringify_xid (guchar *data, gint *position)
227 {
228   gchar buffer[20];
229   gchar *str;
230
231   sprintf(buffer,"0x%x",*(guint32 *)(data+*position));
232   str = g_strdup (buffer);
233
234   *position += sizeof(guint32);
235     
236   return str;
237 }
238
239 gchar *
240 stringify_integer (guchar *data, gint *position)
241 {
242   gchar buffer[20];
243   gchar *str;
244
245   sprintf(buffer,"%d",*(int *)(data+*position));
246   str = g_strdup (buffer);
247
248   *position += sizeof(int);
249     
250   return str;
251 }
252
253 gchar *
254 stringify_span (guchar *data, gint *position)
255 {
256   gchar buffer[42];
257   gchar *str;
258
259   sprintf(buffer,"%d - %d",((int *)(data+*position))[0],
260           ((int *)(data+*position))[1]);
261   str = g_strdup (buffer);
262
263   *position += 2*sizeof(int);
264     
265   return str;
266 }
267
268 void
269 selection_received (GtkWidget *widget, GtkSelectionData *data)
270 {
271   int position;
272   int i;
273   SelType seltype;
274   char *str;
275   
276   if (data->length < 0)
277     {
278       g_print("Error retrieving selection\n");
279       return;
280     }
281
282   seltype = SEL_TYPE_NONE;
283   for (i=0; i<LAST_SEL_TYPE; i++)
284     {
285       if (seltypes[i] == data->type)
286         {
287           seltype = i;
288           break;
289         }
290     }
291
292   if (seltype == SEL_TYPE_NONE)
293     {
294       char *name = gdk_atom_name (data->type);
295       g_print("Don't know how to handle type: %s\n",
296               name?name:"<unknown>");
297       return;
298     }
299
300   if (selection_string != NULL)
301     g_string_free (selection_string, TRUE);
302
303   selection_string = g_string_new (NULL);
304
305   gtk_text_freeze (GTK_TEXT (selection_text));
306   gtk_text_set_point (GTK_TEXT (selection_text), 0);
307   gtk_text_forward_delete (GTK_TEXT (selection_text), 
308                            gtk_text_get_length (GTK_TEXT (selection_text)));
309
310   position = 0;
311   while (position < data->length)
312     {
313       switch (seltype)
314         {
315         case ATOM:
316           str = stringify_atom (data->data, &position);
317           break;
318         case COMPOUND_TEXT:
319         case STRING:
320         case TEXT:
321           str = stringify_text (data->data, &position);
322           break;
323         case BITMAP:
324         case DRAWABLE:
325         case PIXMAP:
326         case WINDOW:
327         case COLORMAP:
328           str = stringify_xid (data->data, &position);
329           break;
330         case INTEGER:
331         case PIXEL:
332           str = stringify_integer (data->data, &position);
333           break;
334         case SPAN:
335           str = stringify_span (data->data, &position);
336           break;
337         default:
338           {
339             char *name = gdk_atom_name (data->type);
340             g_print("Can't convert type %s to string\n",
341                     name?name:"<unknown>");
342             position = data->length;
343             continue;
344           }
345         }
346       gtk_text_insert (GTK_TEXT (selection_text), NULL, 
347                        &selection_text->style->black, 
348                        NULL, str, -1);
349       gtk_text_insert (GTK_TEXT (selection_text), NULL, 
350                        &selection_text->style->black, 
351                        NULL, "\n", -1);
352       g_string_append (selection_string, str);
353       g_free (str);
354     }
355   gtk_text_thaw (GTK_TEXT (selection_text));
356 }
357
358 void
359 paste (GtkWidget *widget, GtkWidget *entry)
360 {
361   const char *name;
362   GdkAtom atom;
363
364   name = gtk_entry_get_text (GTK_ENTRY(entry));
365   atom = gdk_atom_intern (name, FALSE);
366
367   if (atom == GDK_NONE)
368     {
369       g_print("Could not create atom: \"%s\"\n",name);
370       return;
371     }
372
373   gtk_selection_convert (selection_widget, GDK_SELECTION_PRIMARY, atom, 
374                          GDK_CURRENT_TIME);
375 }
376
377 void
378 quit (void)
379 {
380   gtk_exit (0);
381 }
382
383 int
384 main (int argc, char *argv[])
385 {
386   GtkWidget *dialog;
387   GtkWidget *button;
388   GtkWidget *table;
389   GtkWidget *label;
390   GtkWidget *entry;
391   GtkWidget *hscrollbar;
392   GtkWidget *vscrollbar;
393   GtkWidget *hbox;
394
395   static GtkTargetEntry targetlist[] = {
396     { "STRING",        0, STRING },
397     { "TEXT",          0, TEXT },
398     { "COMPOUND_TEXT", 0, COMPOUND_TEXT }
399   };
400   static gint ntargets = sizeof(targetlist) / sizeof(targetlist[0]);
401   
402   gtk_init (&argc, &argv);
403
404   init_atoms();
405
406   selection_widget = gtk_invisible_new ();
407
408   dialog = gtk_dialog_new ();
409   gtk_widget_set_name (dialog, "Test Input");
410   gtk_container_set_border_width (GTK_CONTAINER(dialog), 0);
411
412   g_signal_connect (dialog, "destroy",
413                     G_CALLBACK (quit), NULL);
414
415   table = gtk_table_new (4, 2, FALSE);
416   gtk_container_set_border_width (GTK_CONTAINER(table), 10);
417
418   gtk_table_set_row_spacing (GTK_TABLE (table), 0, 5);
419   gtk_table_set_row_spacing (GTK_TABLE (table), 1, 2);
420   gtk_table_set_row_spacing (GTK_TABLE (table), 2, 2);
421   gtk_table_set_col_spacing (GTK_TABLE (table), 0, 2);
422   gtk_box_pack_start (GTK_BOX (GTK_DIALOG(dialog)->vbox), 
423                       table, TRUE, TRUE, 0);
424   gtk_widget_show (table);
425   
426   selection_button = gtk_toggle_button_new_with_label ("Claim Selection");
427   gtk_table_attach (GTK_TABLE (table), selection_button, 0, 2, 0, 1,
428                     GTK_EXPAND | GTK_FILL, 0, 0, 0);
429   gtk_widget_show (selection_button);
430
431   g_signal_connect (selection_button, "toggled",
432                     G_CALLBACK (selection_toggled), NULL);
433   g_signal_connect (selection_widget, "selection_clear_event",
434                     G_CALLBACK (selection_clear), NULL);
435   g_signal_connect (selection_widget, "selection_received",
436                     G_CALLBACK (selection_received), NULL);
437
438   gtk_selection_add_targets (selection_widget, GDK_SELECTION_PRIMARY,
439                              targetlist, ntargets);
440
441   g_signal_connect (selection_widget, "selection_get",
442                     G_CALLBACK (selection_get), NULL);
443
444   selection_text = gtk_text_new (NULL, NULL);
445   gtk_table_attach_defaults (GTK_TABLE (table), selection_text, 0, 1, 1, 2);
446   gtk_widget_show (selection_text);
447   
448   hscrollbar = gtk_hscrollbar_new (GTK_TEXT (selection_text)->hadj);
449   gtk_table_attach (GTK_TABLE (table), hscrollbar, 0, 1, 2, 3,
450                     GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
451   gtk_widget_show (hscrollbar);
452   
453   vscrollbar = gtk_vscrollbar_new (GTK_TEXT (selection_text)->vadj);
454   gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 1, 2,
455                     GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
456   gtk_widget_show (vscrollbar);
457
458   hbox = gtk_hbox_new (FALSE, 2);
459   gtk_table_attach (GTK_TABLE (table), hbox, 0, 2, 3, 4,
460                     GTK_EXPAND | GTK_FILL, 0, 0, 0);
461   gtk_widget_show (hbox);
462
463   label = gtk_label_new ("Target:");
464   gtk_box_pack_start (GTK_BOX(hbox), label, FALSE, FALSE, 0);
465   gtk_widget_show (label);
466
467   entry = gtk_entry_new ();
468   gtk_box_pack_start (GTK_BOX(hbox), entry, TRUE, TRUE, 0);
469   gtk_widget_show (entry);
470
471   /* .. And create some buttons */
472   button = gtk_button_new_with_label ("Paste");
473   gtk_box_pack_start (GTK_BOX (GTK_DIALOG(dialog)->action_area), 
474                       button, TRUE, TRUE, 0);
475   g_signal_connect (button, "clicked",
476                     G_CALLBACK (paste), entry);
477   gtk_widget_show (button);
478
479   button = gtk_button_new_with_label ("Quit");
480   gtk_box_pack_start (GTK_BOX (GTK_DIALOG(dialog)->action_area), 
481                       button, TRUE, TRUE, 0);
482
483   g_signal_connect_swapped (button, "clicked",
484                             G_CALLBACK (gtk_widget_destroy), dialog);
485   gtk_widget_show (button);
486
487   gtk_widget_show (dialog);
488
489   gtk_main ();
490
491   return 0;
492 }