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