]> Pileus Git - ~andy/gtk/blob - tests/testselection.c
stylecontext: Do invalidation on first resize container
[~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, see <http://www.gnu.org/licenses/>.
16  */
17
18 /*
19  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
20  * file for a list of people on the GTK+ Team.  See the ChangeLog
21  * files for a list of changes.  These files are distributed with
22  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
23  */
24
25
26 #include "config.h"
27 #include <stdio.h>
28 #include <string.h>
29 #include "gtk/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,        NULL, 8 },
65   { "APPLE_PICT",                           APPLE_PICT,    NULL, 8 },
66   { "BACKGROUND",                           PIXEL,         NULL, 32 },
67   { "BITMAP",                               BITMAP,        NULL, 32 },
68   { "CHARACTER_POSITION",                   SPAN,          NULL, 32 },
69   { "CLASS",                                TEXT,          NULL, 8 },
70   { "CLIENT_WINDOW",                        WINDOW,        NULL, 32 },
71   { "COLORMAP",                             COLORMAP,      NULL, 32 },
72   { "COLUMN_NUMBER",                        SPAN,          NULL, 32 },
73   { "COMPOUND_TEXT",                        COMPOUND_TEXT, NULL, 8 },
74   /*  { "DELETE", "NULL", 0, ? }, */
75   { "DRAWABLE",                             DRAWABLE,      NULL, 32 },
76   { "ENCAPSULATED_POSTSCRIPT",              STRING,        NULL, 8 },
77   { "ENCAPSULATED_POSTSCRIPT_INTERCHANGE",  STRING,        NULL, 8 },
78   { "FILE_NAME",                            TEXT,          NULL, 8 },
79   { "FOREGROUND",                           PIXEL,         NULL, 32 },
80   { "HOST_NAME",                            TEXT,          NULL, 8 },
81   /*  { "INSERT_PROPERTY", "NULL", 0, ? NULL }, */
82   /*  { "INSERT_SELECTION", "NULL", 0, ? NULL }, */
83   { "LENGTH",                               INTEGER,       NULL, 32 },
84   { "LINE_NUMBER",                          SPAN,          NULL, 32 },
85   { "LIST_LENGTH",                          INTEGER,       NULL, 32 },
86   { "MODULE",                               TEXT,          NULL, 8 },
87   /*  { "MULTIPLE", "ATOM_PAIR", 0, 32 }, */
88   { "NAME",                                 TEXT,          NULL, 8 },
89   { "ODIF",                                 TEXT,          NULL, 8 },
90   { "OWNER_OS",                             TEXT,          NULL, 8 },
91   { "PIXMAP",                               PIXMAP,        NULL, 32 },
92   { "POSTSCRIPT",                           STRING,        NULL, 8 },
93   { "PROCEDURE",                            TEXT,          NULL, 8 },
94   { "PROCESS",                              INTEGER,       NULL, 32 },
95   { "STRING",                               STRING,        NULL, 8 },
96   { "TARGETS",                              ATOM,          NULL, 32 },
97   { "TASK",                                 INTEGER,       NULL, 32 },
98   { "TEXT",                                 TEXT,          NULL, 8  },
99   { "TIMESTAMP",                            INTEGER,       NULL, 32 },
100   { "USER",                                 TEXT,          NULL, 8 },
101 };
102
103 static int num_targets = sizeof(targets)/sizeof(Target);
104
105 static int have_selection = FALSE;
106
107 GtkWidget *selection_widget;
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_get_active (GTK_TOGGLE_BUTTON (widget)))
142     {
143       have_selection = gtk_selection_owner_set (selection_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) == gtk_widget_get_window (widget))
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(selection_button), 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 *selection_data)
267 {
268   int position;
269   int i;
270   SelType seltype;
271   char *str;
272   guchar *data;
273   GtkTextBuffer *buffer;
274   GdkAtom type;
275
276   if (gtk_selection_data_get_length (selection_data) < 0)
277     {
278       g_print("Error retrieving selection\n");
279       return;
280     }
281
282   type = gtk_selection_data_get_data_type (selection_data);
283
284   seltype = SEL_TYPE_NONE;
285   for (i=0; i<LAST_SEL_TYPE; i++)
286     {
287       if (seltypes[i] == type)
288         {
289           seltype = i;
290           break;
291         }
292     }
293
294   if (seltype == SEL_TYPE_NONE)
295     {
296       char *name = gdk_atom_name (type);
297       g_print("Don't know how to handle type: %s\n",
298               name?name:"<unknown>");
299       return;
300     }
301
302   if (selection_string != NULL)
303     g_string_free (selection_string, TRUE);
304
305   selection_string = g_string_new (NULL);
306
307   buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (selection_text));
308   gtk_text_buffer_set_text (buffer, "", -1);
309
310   position = 0;
311   while (position < gtk_selection_data_get_length (selection_data))
312     {
313       data = (guchar *) gtk_selection_data_get_data (selection_data);
314       switch (seltype)
315         {
316         case ATOM:
317           str = stringify_atom (data, &position);
318           break;
319         case COMPOUND_TEXT:
320         case STRING:
321         case TEXT:
322           str = stringify_text (data, &position);
323           break;
324         case BITMAP:
325         case DRAWABLE:
326         case PIXMAP:
327         case WINDOW:
328         case COLORMAP:
329           str = stringify_xid (data, &position);
330           break;
331         case INTEGER:
332         case PIXEL:
333           str = stringify_integer (data, &position);
334           break;
335         case SPAN:
336           str = stringify_span (data, &position);
337           break;
338         default:
339           {
340             char *name = gdk_atom_name (gtk_selection_data_get_data_type (selection_data));
341             g_print("Can't convert type %s to string\n",
342                     name?name:"<unknown>");
343             position = gtk_selection_data_get_length (selection_data);
344             continue;
345           }
346         }
347       gtk_text_buffer_insert_at_cursor (buffer, str, -1);
348       gtk_text_buffer_insert_at_cursor (buffer, "\n", -1);
349       g_string_append (selection_string, str);
350       g_free (str);
351     }
352 }
353
354 void
355 paste (GtkWidget *widget, GtkWidget *entry)
356 {
357   const char *name;
358   GdkAtom atom;
359
360   name = gtk_entry_get_text (GTK_ENTRY(entry));
361   atom = gdk_atom_intern (name, FALSE);
362
363   if (atom == GDK_NONE)
364     {
365       g_print("Could not create atom: \"%s\"\n",name);
366       return;
367     }
368
369   gtk_selection_convert (selection_widget, GDK_SELECTION_PRIMARY, atom, 
370                          GDK_CURRENT_TIME);
371 }
372
373 void
374 quit (void)
375 {
376   gtk_main_quit ();
377 }
378
379 int
380 main (int argc, char *argv[])
381 {
382   GtkWidget *action_area, *content_area;
383   GtkWidget *dialog;
384   GtkWidget *button;
385   GtkWidget *vbox;
386   GtkWidget *label;
387   GtkWidget *entry;
388   GtkWidget *hbox;
389   GtkWidget *scrolled;
390
391   static GtkTargetEntry targetlist[] = {
392     { "STRING",        0, STRING },
393     { "TEXT",          0, TEXT },
394     { "COMPOUND_TEXT", 0, COMPOUND_TEXT }
395   };
396   static gint ntargets = sizeof(targetlist) / sizeof(targetlist[0]);
397   
398   gtk_init (&argc, &argv);
399
400   init_atoms();
401
402   selection_widget = gtk_invisible_new ();
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   g_signal_connect (dialog, "destroy",
409                     G_CALLBACK (quit), NULL);
410
411   content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
412   action_area = gtk_dialog_get_action_area (GTK_DIALOG (dialog));
413
414   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
415   gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
416
417   gtk_box_pack_start (GTK_BOX (content_area), vbox, TRUE, TRUE, 0);
418   gtk_widget_show (vbox);
419   
420   selection_button = gtk_toggle_button_new_with_label ("Claim Selection");
421   gtk_container_add (GTK_CONTAINER (vbox), selection_button);
422   gtk_widget_show (selection_button);
423
424   g_signal_connect (selection_button, "toggled",
425                     G_CALLBACK (selection_toggled), NULL);
426   g_signal_connect (selection_widget, "selection_clear_event",
427                     G_CALLBACK (selection_clear), NULL);
428   g_signal_connect (selection_widget, "selection_received",
429                     G_CALLBACK (selection_received), NULL);
430
431   gtk_selection_add_targets (selection_widget, GDK_SELECTION_PRIMARY,
432                              targetlist, ntargets);
433
434   g_signal_connect (selection_widget, "selection_get",
435                     G_CALLBACK (selection_get), NULL);
436
437   selection_text = gtk_text_view_new ();
438   scrolled = gtk_scrolled_window_new (NULL, NULL);
439   gtk_container_add (GTK_CONTAINER (scrolled), selection_text);
440   gtk_container_add (GTK_CONTAINER (vbox), scrolled);
441   gtk_widget_show (selection_text);
442
443   hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
444   gtk_container_add (GTK_CONTAINER (vbox), hbox);
445   gtk_widget_show (hbox);
446
447   label = gtk_label_new ("Target:");
448   gtk_box_pack_start (GTK_BOX(hbox), label, FALSE, FALSE, 0);
449   gtk_widget_show (label);
450
451   entry = gtk_entry_new ();
452   gtk_box_pack_start (GTK_BOX(hbox), entry, TRUE, TRUE, 0);
453   gtk_widget_show (entry);
454
455   /* .. And create some buttons */
456   button = gtk_button_new_with_label ("Paste");
457   gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
458   g_signal_connect (button, "clicked",
459                     G_CALLBACK (paste), entry);
460   gtk_widget_show (button);
461
462   button = gtk_button_new_with_label ("Quit");
463   gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
464
465   g_signal_connect_swapped (button, "clicked",
466                             G_CALLBACK (gtk_widget_destroy), dialog);
467   gtk_widget_show (button);
468
469   gtk_widget_show (dialog);
470
471   gtk_main ();
472
473   return 0;
474 }