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