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.
23  */
24 
25 /*
26  * GTK+ DirectFB backend
27  * Copyright (C) 2001-2002  convergence integrated media GmbH
28  * Copyright (C) 2002-2004  convergence GmbH
29  * Written by Denis Oliver Kropp <dok@convergence.de> and
30  *            Sven Neumann <sven@convergence.de>
31  */
32 
33 #include "config.h"
34 #include "gdk.h"
35 
36 #include <string.h>
37 
38 #include "gdkproperty.h"
39 
40 #include "gdkdirectfb.h"
41 #include "gdkprivate-directfb.h"
42 
43 #include "gdkinternals.h"
44 
45 #include "gdkalias.h"
46 
47 static GHashTable *names_to_atoms;
48 static GPtrArray  *atoms_to_names;
49 
50 static const gchar xatoms_string[] =
51   /* These are all the standard predefined X atoms */
52   "NONE\0"
53   "PRIMARY\0"
54   "SECONDARY\0"
55   "ARC\0"
56   "ATOM\0"
57   "BITMAP\0"
58   "CARDINAL\0"
59   "COLORMAP\0"
60   "CURSOR\0"
61   "CUT_BUFFER0\0"
62   "CUT_BUFFER1\0"
63   "CUT_BUFFER2\0"
64   "CUT_BUFFER3\0"
65   "CUT_BUFFER4\0"
66   "CUT_BUFFER5\0"
67   "CUT_BUFFER6\0"
68   "CUT_BUFFER7\0"
69   "DRAWABLE\0"
70   "FONT\0"
71   "INTEGER\0"
72   "PIXMAP\0"
73   "POINT\0"
74   "RECTANGLE\0"
75   "RESOURCE_MANAGER\0"
76   "RGB_COLOR_MAP\0"
77   "RGB_BEST_MAP\0"
78   "RGB_BLUE_MAP\0"
79   "RGB_DEFAULT_MAP\0"
80   "RGB_GRAY_MAP\0"
81   "RGB_GREEN_MAP\0"
82   "RGB_RED_MAP\0"
83   "STRING\0"
84   "VISUALID\0"
85   "WINDOW\0"
86   "WM_COMMAND\0"
87   "WM_HINTS\0"
88   "WM_CLIENT_MACHINE\0"
89   "WM_ICON_NAME\0"
90   "WM_ICON_SIZE\0"
91   "WM_NAME\0"
92   "WM_NORMAL_HINTS\0"
93   "WM_SIZE_HINTS\0"
94   "WM_ZOOM_HINTS\0"
95   "MIN_SPACE\0"
96   "NORM_SPACE\0"
97   "MAX_SPACE\0"
98   "END_SPACE\0"
99   "SUPERSCRIPT_X\0"
100   "SUPERSCRIPT_Y\0"
101   "SUBSCRIPT_X\0"
102   "SUBSCRIPT_Y\0"
103   "UNDERLINE_POSITION\0"
104   "UNDERLINE_THICKNESS\0"
105   "STRIKEOUT_ASCENT\0"
106   "STRIKEOUT_DESCENT\0"
107   "ITALIC_ANGLE\0"
108   "X_HEIGHT\0"
109   "QUAD_WIDTH\0"
110   "WEIGHT\0"
111   "POINT_SIZE\0"
112   "RESOLUTION\0"
113   "COPYRIGHT\0"
114   "NOTICE\0"
115   "FONT_NAME\0"
116   "FAMILY_NAME\0"
117   "FULL_NAME\0"
118   "CAP_HEIGHT\0"
119   "WM_CLASS\0"
120   "WM_TRANSIENT_FOR\0"
121 ;
122 
123 static const gint xatoms_offset[] = {
124     0,   5,  13,  23,  27,  32,  39,  48,  57,  64,  76,  88,
125   100, 112, 124, 136, 148, 160, 169, 174, 182, 189, 195, 205,
126   222, 236, 249, 262, 278, 291, 305, 317, 324, 333, 340, 351,
127   360, 378, 391, 404, 412, 428, 442, 456, 466, 477, 487, 497,
128   511, 525, 537, 549, 568, 588, 605, 623, 636, 645, 656, 663,
129   674, 685, 695, 702, 712, 724, 734, 745, 754
130 };
131 
132 #define N_CUSTOM_PREDEFINED 1
133 
134 static void
ensure_atom_tables(void)135 ensure_atom_tables (void)
136 {
137   int i;
138 
139   if (names_to_atoms)
140     return;
141 
142   names_to_atoms = g_hash_table_new (g_str_hash, g_str_equal);
143   atoms_to_names = g_ptr_array_sized_new (G_N_ELEMENTS (xatoms_offset));
144 
145   for (i = 0; i < G_N_ELEMENTS (xatoms_offset); i++)
146     {
147       g_hash_table_insert (names_to_atoms,
148                            (gchar *)xatoms_string + xatoms_offset[i],
149                            GINT_TO_POINTER (i));
150       g_ptr_array_add (atoms_to_names,
151                        (gchar *)xatoms_string + xatoms_offset[i]);
152     }
153 }
154 
155 static GdkAtom
intern_atom_internal(const gchar * atom_name,gboolean allocate)156 intern_atom_internal (const gchar *atom_name, gboolean allocate)
157 {
158   gpointer  result;
159   gchar    *name;
160 
161   g_return_val_if_fail (atom_name != NULL, GDK_NONE);
162 
163   ensure_atom_tables ();
164 
165   if (g_hash_table_lookup_extended (names_to_atoms, atom_name, NULL, &result))
166     return result;
167 
168   result = GINT_TO_POINTER (atoms_to_names->len);
169   name   = allocate ? g_strdup (atom_name) : (gchar *)atom_name;
170   g_hash_table_insert (names_to_atoms, name, result);
171   g_ptr_array_add (atoms_to_names, name);
172 
173   return result;
174 }
175 
176 GdkAtom
gdk_atom_intern(const gchar * atom_name,gboolean only_if_exists)177 gdk_atom_intern (const gchar *atom_name,
178 		 gboolean     only_if_exists)
179 {
180   return intern_atom_internal (atom_name, TRUE);
181 }
182 
183 GdkAtom
gdk_atom_intern_static_string(const gchar * atom_name)184 gdk_atom_intern_static_string (const gchar *atom_name)
185 {
186   return intern_atom_internal (atom_name, FALSE);
187 }
188 
189 
190 gchar *
gdk_atom_name(GdkAtom atom)191 gdk_atom_name (GdkAtom atom)
192 {
193   if (!atoms_to_names)
194     return NULL;
195 
196   if (GPOINTER_TO_INT (atom) >= atoms_to_names->len)
197     return NULL;
198 
199   return g_strdup (g_ptr_array_index (atoms_to_names, GPOINTER_TO_INT (atom)));
200 }
201 
202 
203 static void
gdk_property_delete_2(GdkWindow * window,GdkAtom property,GdkWindowProperty * prop)204 gdk_property_delete_2 (GdkWindow         *window,
205                        GdkAtom            property,
206                        GdkWindowProperty *prop)
207 {
208   GdkWindowImplDirectFB *impl;
209   GdkEvent              *event;
210   GdkWindow             *event_window;
211 
212   impl = GDK_WINDOW_IMPL_DIRECTFB (GDK_WINDOW_OBJECT (window)->impl);
213 
214   g_hash_table_remove (impl->properties, GUINT_TO_POINTER (property));
215   g_free (prop);
216 
217   event_window = gdk_directfb_other_event_window (window, GDK_PROPERTY_NOTIFY);
218 
219   if (event_window)
220     {
221       event                 = gdk_directfb_event_make (event_window, GDK_PROPERTY_NOTIFY);
222       event->property.atom  = property;
223       event->property.state = GDK_PROPERTY_DELETE;
224     }
225 }
226 
227 void
gdk_property_delete(GdkWindow * window,GdkAtom property)228 gdk_property_delete (GdkWindow *window,
229                      GdkAtom    property)
230 {
231   GdkWindowImplDirectFB *impl;
232   GdkWindowProperty     *prop;
233 
234   g_return_if_fail (GDK_IS_WINDOW (window));
235 
236   impl = GDK_WINDOW_IMPL_DIRECTFB (GDK_WINDOW_OBJECT (window)->impl);
237 
238   if (!impl->properties)
239     return;
240 
241   prop = g_hash_table_lookup (impl->properties, GUINT_TO_POINTER (property));
242   if (!prop)
243     return;
244 
245   gdk_property_delete_2 (window, property, prop);
246 }
247 
248 gboolean
gdk_property_get(GdkWindow * window,GdkAtom property,GdkAtom type,gulong offset,gulong length,gint pdelete,GdkAtom * actual_property_type,gint * actual_format_type,gint * actual_length,guchar ** data)249 gdk_property_get (GdkWindow  *window,
250                   GdkAtom     property,
251                   GdkAtom     type,
252                   gulong      offset,
253                   gulong      length,
254                   gint        pdelete,
255                   GdkAtom    *actual_property_type,
256                   gint       *actual_format_type,
257                   gint       *actual_length,
258                   guchar    **data)
259 {
260   GdkWindowImplDirectFB *impl;
261   GdkWindowProperty     *prop;
262   gint                   nbytes = 0;
263 
264   g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), FALSE);
265   g_return_val_if_fail (data != NULL, FALSE);
266 
267   if (!window)
268     window = _gdk_parent_root;
269 
270   if (GDK_WINDOW_DESTROYED (window))
271     return FALSE;
272 
273   impl = GDK_WINDOW_IMPL_DIRECTFB (GDK_WINDOW_OBJECT (window)->impl);
274 
275   if (!impl->properties)
276     return FALSE;
277 
278   prop = g_hash_table_lookup (impl->properties, GUINT_TO_POINTER (property));
279   if (!prop)
280     {
281       if (actual_property_type)
282         *actual_property_type = GDK_NONE;
283       return FALSE;
284     }
285 
286   nbytes = CLAMP (length, 0, prop->length - offset * 4);
287 
288   if (nbytes > 0 &&
289       (prop->type == 0 /* AnyPropertyType */ || prop->type == type))
290     {
291       *data = g_malloc (nbytes + 1);
292       memcpy (*data, prop->data + offset, nbytes);
293       (*data)[nbytes] = 0;
294     }
295   else
296     {
297       *data = NULL;
298     }
299 
300   if (actual_length)
301     *actual_length        = nbytes;
302   if (actual_property_type)
303     *actual_property_type = prop->type;
304   if (actual_format_type)
305     *actual_format_type   = prop->format;
306 
307   /* only delete the property if it was completely retrieved */
308   if (pdelete && length >= *actual_length && *data != NULL)
309     {
310       gdk_property_delete_2 (window, property, prop);
311     }
312 
313   return TRUE;
314 }
315 
316 void
gdk_property_change(GdkWindow * window,GdkAtom property,GdkAtom type,gint format,GdkPropMode mode,const guchar * data,gint nelements)317 gdk_property_change (GdkWindow    *window,
318                      GdkAtom       property,
319                      GdkAtom       type,
320                      gint          format,
321                      GdkPropMode   mode,
322                      const guchar *data,
323                      gint          nelements)
324 {
325   GdkWindowImplDirectFB *impl;
326   GdkWindowProperty     *prop;
327   GdkWindowProperty     *new_prop;
328   gint                   new_size = 0;
329   GdkEvent              *event;
330   GdkWindow             *event_window;
331 
332   g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
333 
334   if (!window)
335     window = _gdk_parent_root;
336 
337   if (GDK_WINDOW_DESTROYED (window))
338     return;
339 
340   impl = GDK_WINDOW_IMPL_DIRECTFB (GDK_WINDOW_OBJECT (window)->impl);
341 
342   if (!impl->properties)
343     impl->properties = g_hash_table_new (NULL, NULL);
344 
345   prop = g_hash_table_lookup (impl->properties, GUINT_TO_POINTER (property));
346 
347   switch (mode)
348     {
349     case GDK_PROP_MODE_REPLACE:
350       new_size = nelements * (format >> 3);
351       break;
352 
353     case GDK_PROP_MODE_PREPEND:
354     case GDK_PROP_MODE_APPEND:
355       new_size = nelements * (format >> 3);
356       if (prop)
357         {
358           if (type != prop->type || format != prop->format)
359             return;
360           new_size += prop->length;
361         }
362       break;
363     }
364 
365   new_prop         = g_malloc (G_STRUCT_OFFSET (GdkWindowProperty, data) + new_size);
366   new_prop->length = new_size;
367   new_prop->type   = type;
368   new_prop->format = format;
369 
370   switch (mode)
371     {
372     case GDK_PROP_MODE_REPLACE:
373       memcpy (new_prop->data, data, new_size);
374       break;
375 
376     case GDK_PROP_MODE_APPEND:
377       if (prop)
378         memcpy (new_prop->data, prop->data, prop->length);
379       memcpy (new_prop->data + new_prop->length,
380               data, (nelements * (format >> 3)));
381       break;
382 
383     case GDK_PROP_MODE_PREPEND:
384       memcpy (new_prop->data, data, (nelements * (format >> 3)));
385       if (prop)
386         memcpy (new_prop->data + (nelements * (format >> 3)),
387                 prop->data, prop->length);
388       break;
389     }
390 
391   g_hash_table_insert (impl->properties,
392                        GUINT_TO_POINTER (property), new_prop);
393   g_free (prop);
394 
395   event_window = gdk_directfb_other_event_window (window, GDK_PROPERTY_NOTIFY);
396 
397   if (event_window)
398     {
399       event                 = gdk_directfb_event_make (event_window, GDK_PROPERTY_NOTIFY);
400       event->property.atom  = property;
401       event->property.state = GDK_PROPERTY_NEW_VALUE;
402     }
403 }
404 
405 #define __GDK_PROPERTY_X11_C__
406 #include "gdkaliasdef.c"
407