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