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