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