]> Pileus Git - ~andy/gtk/blob - gdk/linux-fb/gdkproperty-fb.c
Fixes #136082 and #135265, patch by Morten Welinder.
[~andy/gtk] / gdk / linux-fb / gdkproperty-fb.c
1 /* GDK - The GIMP Drawing Kit
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 <config.h>
28 #include <string.h>
29 #include <time.h>
30
31 #include "gdkfb.h"
32 #include "gdkproperty.h"
33 #include "gdkprivate.h"
34 #include "gdkprivate-fb.h"
35
36 GdkAtom
37 gdk_atom_intern (const gchar *atom_name,
38                  gboolean     only_if_exists)
39 {
40   g_return_val_if_fail (atom_name != NULL, GDK_NONE);
41
42   if (strcmp (atom_name, "PRIMARY") == 0)
43     return GDK_SELECTION_PRIMARY;
44   else if (strcmp (atom_name, "SECONDARY") == 0)
45     return GDK_SELECTION_SECONDARY;
46   else if (strcmp (atom_name, "CLIPBOARD") == 0)
47     return GDK_SELECTION_CLIPBOARD;
48   else if (strcmp (atom_name, "ATOM") == 0)
49     return GDK_SELECTION_TYPE_ATOM;
50   else if (strcmp (atom_name, "BITMAP") == 0)
51     return GDK_SELECTION_TYPE_BITMAP;
52   else if (strcmp (atom_name, "COLORMAP") == 0)
53     return GDK_SELECTION_TYPE_COLORMAP;
54   else if (strcmp (atom_name, "DRAWABLE") == 0)
55     return GDK_SELECTION_TYPE_DRAWABLE;
56   else if (strcmp (atom_name, "INTEGER") == 0)
57     return GDK_SELECTION_TYPE_INTEGER;
58   else if (strcmp (atom_name, "PIXMAP") == 0)
59     return GDK_SELECTION_TYPE_PIXMAP;
60   else if (strcmp (atom_name, "WINDOW") == 0)
61     return GDK_SELECTION_TYPE_WINDOW;
62   else if (strcmp (atom_name, "STRING") == 0)
63     return GDK_SELECTION_TYPE_STRING;
64   else
65     return GUINT_TO_POINTER (256 + g_quark_from_string (atom_name));
66 }
67
68 gchar*
69 gdk_atom_name (GdkAtom atom)
70 {
71   if (GPOINTER_TO_UINT (atom) < 256)
72     {
73       
74       switch (GPOINTER_TO_UINT (atom))
75         {
76         case GPOINTER_TO_UINT (GDK_SELECTION_PRIMARY):
77           return g_strdup ("PRIMARY");
78         case GPOINTER_TO_UINT (GDK_SELECTION_SECONDARY):
79           return g_strdup ("SECONDARY");
80         case GPOINTER_TO_UINT (GDK_SELECTION_CLIPBOARD):
81           return g_strdup ("CLIPBOARD");
82         case GPOINTER_TO_UINT (GDK_SELECTION_TYPE_ATOM):
83           return g_strdup ("ATOM");
84         case GPOINTER_TO_UINT (GDK_SELECTION_TYPE_BITMAP):
85           return g_strdup ("BITMAP");
86         case GPOINTER_TO_UINT (GDK_SELECTION_TYPE_COLORMAP):
87           return g_strdup ("COLORMAP");
88         case GPOINTER_TO_UINT (GDK_SELECTION_TYPE_DRAWABLE):
89           return g_strdup ("DRAWABLE");
90         case GPOINTER_TO_UINT (GDK_SELECTION_TYPE_INTEGER):
91           return g_strdup ("INTEGER");
92         case GPOINTER_TO_UINT (GDK_SELECTION_TYPE_PIXMAP):
93           return g_strdup ("PIXMAP");
94         case GPOINTER_TO_UINT (GDK_SELECTION_TYPE_WINDOW):
95           return g_strdup ("WINDOW");
96         case GPOINTER_TO_UINT (GDK_SELECTION_TYPE_STRING):
97           return g_strdup ("STRING");
98         default:
99           g_warning (G_STRLOC "Invalid atom");
100           return g_strdup ("<invalid>");
101         }
102     }
103   else
104     return g_strdup (g_quark_to_string (GPOINTER_TO_UINT (atom) - 256));
105 }
106
107 static void
108 gdk_property_delete_2 (GdkWindow *window,
109                        GdkAtom property,
110                        GdkWindowProperty *prop)
111 {
112   GdkWindowFBData *fbd = GDK_WINDOW_IMPL_FBDATA(window);
113   GdkEvent *event;
114   GdkWindow *event_window;
115   
116   g_hash_table_remove (fbd->properties, GUINT_TO_POINTER (property));
117   g_free (prop);
118
119   event_window = gdk_fb_other_event_window (window, GDK_PROPERTY_NOTIFY);
120   if (event_window)
121     {
122       event = gdk_event_make (event_window, GDK_PROPERTY_NOTIFY, TRUE);
123       event->property.atom = property;
124       event->property.state = GDK_PROPERTY_DELETE;
125     }
126 }
127
128 void
129 gdk_property_delete (GdkWindow *window,
130                      GdkAtom    property)
131 {
132   GdkWindowFBData *fbd = GDK_WINDOW_FBDATA (window);
133   GdkWindowProperty *prop;
134
135   g_return_if_fail (window != NULL);
136   g_return_if_fail (GDK_IS_WINDOW (window));
137
138   if (!fbd->properties)
139     return;
140
141   prop = g_hash_table_lookup (fbd->properties, GUINT_TO_POINTER(property));
142   if (!prop)
143     return;
144
145   gdk_property_delete_2 (window, property, prop);
146 }
147
148 gint
149 gdk_property_get (GdkWindow   *window,
150                   GdkAtom      property,
151                   GdkAtom      type,
152                   gulong       offset,
153                   gulong       length,
154                   gint         pdelete,
155                   GdkAtom     *actual_property_type,
156                   gint        *actual_format_type,
157                   gint        *actual_length,
158                   guchar     **data)
159 {
160   GdkWindowFBData *fbd = GDK_WINDOW_FBDATA (window);
161   GdkWindowProperty *prop;
162   int nbytes;
163
164   g_return_val_if_fail (window != NULL, FALSE);
165   g_return_val_if_fail (data != NULL, FALSE);
166   g_return_val_if_fail (actual_length != NULL, FALSE);
167   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
168
169   if (!fbd->properties)
170     return FALSE;
171
172   prop = g_hash_table_lookup (fbd->properties, GUINT_TO_POINTER (property));
173   if (!prop)
174     return FALSE;
175
176   nbytes = (offset + length * (prop->format >> 3)) - prop->length;
177   nbytes = MAX (nbytes, 0);
178   if (nbytes > 0)
179     {
180       *data = g_malloc (nbytes+1);
181       memcpy (*data, prop->data + offset, nbytes);
182       (*data)[nbytes] = 0;
183     }
184   else
185     *data = NULL;
186   *actual_length = nbytes / (prop->format >> 3);
187   *actual_property_type = prop->type;
188   *actual_format_type = prop->format;
189
190   if (pdelete)
191     gdk_property_delete_2 (window, property, prop);
192
193   return TRUE;
194 }
195
196 void
197 gdk_property_change (GdkWindow   *window,
198                      GdkAtom      property,
199                      GdkAtom      type,
200                      gint         format,
201                      GdkPropMode  mode,
202                      const guchar *data,
203                      gint         nelements)
204 {
205   GdkWindowFBData *fbd = GDK_WINDOW_FBDATA (window);
206   GdkWindowProperty *prop, *new_prop;
207   int new_size = 0;
208   GdkEvent *event;
209   GdkWindow *event_window;
210
211   g_return_if_fail (window != NULL);
212   g_return_if_fail (GDK_IS_WINDOW (window));
213
214   if (!fbd->properties)
215     fbd->properties = g_hash_table_new (NULL, NULL);
216
217   prop = g_hash_table_lookup (fbd->properties, GUINT_TO_POINTER (property));
218
219   switch(mode)
220     {
221     case GDK_PROP_MODE_REPLACE:
222       new_size = nelements * (format >> 3);
223       break;
224     case GDK_PROP_MODE_PREPEND:
225     case GDK_PROP_MODE_APPEND:
226       new_size = nelements * (format >> 3);
227       if (prop)
228         new_size += prop->length;
229     default:
230       break;
231     }
232
233   new_prop = g_malloc (G_STRUCT_OFFSET (GdkWindowProperty, data) + new_size);
234   new_prop->length = new_size;
235   new_prop->type = type;
236   new_prop->format = format;
237
238   switch (mode)
239     {
240     case GDK_PROP_MODE_REPLACE:
241       memcpy (new_prop->data, data, new_size);
242       break;
243     case GDK_PROP_MODE_APPEND:
244       if (prop)
245         memcpy (new_prop->data, prop->data, prop->length);
246       memcpy (new_prop->data + prop->length, data, (nelements * (format >> 3)));
247       break;
248     case GDK_PROP_MODE_PREPEND:
249       memcpy (new_prop->data, data, (nelements * (format >> 3)));
250       if (prop)
251         memcpy (new_prop->data + (nelements * (format >> 3)), prop->data, prop->length);
252       break;
253     }
254
255   g_hash_table_insert (fbd->properties, GUINT_TO_POINTER (property), new_prop);
256   g_free (prop);
257
258   event_window = gdk_fb_other_event_window (window, GDK_PROPERTY_NOTIFY);
259   if (event_window)
260     {
261       event = gdk_event_make (event_window, GDK_PROPERTY_NOTIFY, TRUE);
262       event->property.atom = property;
263       event->property.state = GDK_PROPERTY_NEW_VALUE;
264     }
265 }