]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkpixmap-x11.c
New function gdk_pixmap_foreign_new(). (gtk-blizzard-981005-0. Christopher
[~andy/gtk] / gdk / x11 / gdkpixmap-x11.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 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 #include "../config.h"
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 /* Needed for SEEK_END in SunOS */
24 #include <unistd.h>
25 #include <X11/Xlib.h>
26
27 #include "gdk.h"
28 #include "gdkprivate.h"
29
30 typedef struct
31 {
32   gchar *color_string;
33   GdkColor color;
34   gint transparent;
35 } _GdkPixmapColor;
36
37 typedef struct
38 {
39   guint ncolors;
40   GdkColormap *colormap;
41   gulong pixels[1];
42 } _GdkPixmapInfo;
43
44 GdkPixmap*
45 gdk_pixmap_new (GdkWindow *window,
46                 gint       width,
47                 gint       height,
48                 gint       depth)
49 {
50   GdkPixmap *pixmap;
51   GdkWindowPrivate *private;
52   GdkWindowPrivate *window_private;
53
54   g_return_val_if_fail ((window != NULL) || (depth != -1), NULL);
55   g_return_val_if_fail ((width != 0) && (height != 0), NULL);
56
57   if (!window)
58     window = (GdkWindow*) &gdk_root_parent;
59
60   window_private = (GdkWindowPrivate*) window;
61   if (window_private->destroyed)
62     return NULL;
63
64   if (depth == -1)
65     depth = gdk_window_get_visual (window)->depth;
66
67   private = g_new (GdkWindowPrivate, 1);
68   pixmap = (GdkPixmap*) private;
69
70   private->xdisplay = window_private->xdisplay;
71   private->window_type = GDK_WINDOW_PIXMAP;
72   private->xwindow = XCreatePixmap (private->xdisplay, window_private->xwindow,
73                                     width, height, depth);
74   private->colormap = NULL;
75   private->parent = NULL;
76   private->x = 0;
77   private->y = 0;
78   private->width = width;
79   private->height = height;
80   private->resize_count = 0;
81   private->ref_count = 1;
82   private->destroyed = 0;
83
84   gdk_xid_table_insert (&private->xwindow, pixmap);
85
86   return pixmap;
87 }
88
89 GdkPixmap *
90 gdk_bitmap_create_from_data (GdkWindow *window,
91                              gchar     *data,
92                              gint       width,
93                              gint       height)
94 {
95   GdkPixmap *pixmap;
96   GdkWindowPrivate *private;
97   GdkWindowPrivate *window_private;
98
99   g_return_val_if_fail (data != NULL, NULL);
100   g_return_val_if_fail ((width != 0) && (height != 0), NULL);
101
102   if (!window)
103     window = (GdkWindow*) &gdk_root_parent;
104
105   window_private = (GdkWindowPrivate*) window;
106   if (window_private->destroyed)
107     return NULL;
108
109   private = g_new (GdkWindowPrivate, 1);
110   pixmap = (GdkPixmap*) private;
111
112   private->parent = NULL;
113   private->xdisplay = window_private->xdisplay;
114   private->window_type = GDK_WINDOW_PIXMAP;
115   private->x = 0;
116   private->y = 0;
117   private->width = width;
118   private->height = height;
119   private->resize_count = 0;
120   private->ref_count = 1;
121   private->destroyed = FALSE;
122
123   private->xwindow = XCreateBitmapFromData (private->xdisplay,
124                                             window_private->xwindow,
125                                             data, width, height);
126
127   gdk_xid_table_insert (&private->xwindow, pixmap);
128
129   return pixmap;
130 }
131
132 GdkPixmap*
133 gdk_pixmap_create_from_data (GdkWindow *window,
134                              gchar     *data,
135                              gint       width,
136                              gint       height,
137                              gint       depth,
138                              GdkColor  *fg,
139                              GdkColor  *bg)
140 {
141   GdkPixmap *pixmap;
142   GdkWindowPrivate *private;
143   GdkWindowPrivate *window_private;
144
145   g_return_val_if_fail (data != NULL, NULL);
146   g_return_val_if_fail (fg != NULL, NULL);
147   g_return_val_if_fail (bg != NULL, NULL);
148   g_return_val_if_fail ((window != NULL) || (depth != -1), NULL);
149   g_return_val_if_fail ((width != 0) && (height != 0), NULL);
150
151   if (!window)
152     window = (GdkWindow*) &gdk_root_parent;
153
154   window_private = (GdkWindowPrivate*) window;
155   if (window_private->destroyed)
156     return NULL;
157
158   if (depth == -1)
159     depth = gdk_window_get_visual (window)->depth;
160
161   private = g_new (GdkWindowPrivate, 1);
162   pixmap = (GdkPixmap*) private;
163
164   private->parent = NULL;
165   private->xdisplay = window_private->xdisplay;
166   private->window_type = GDK_WINDOW_PIXMAP;
167   private->x = 0;
168   private->y = 0;
169   private->width = width;
170   private->height = height;
171   private->resize_count = 0;
172   private->ref_count = 1;
173   private->destroyed = FALSE;
174
175   private->xwindow = XCreatePixmapFromBitmapData (private->xdisplay,
176                                                   window_private->xwindow,
177                                                   data, width, height,
178                                                   fg->pixel, bg->pixel, depth);
179
180   gdk_xid_table_insert (&private->xwindow, pixmap);
181
182   return pixmap;
183 }
184
185 static gint
186 gdk_pixmap_seek_string (FILE  *infile,
187                         const gchar *str,
188                         gint   skip_comments)
189 {
190   char instr[1024];
191
192   while (!feof (infile))
193     {
194       fscanf (infile, "%1023s", instr);
195       if (skip_comments == TRUE && strcmp (instr, "/*") == 0)
196         {
197           fscanf (infile, "%1023s", instr);
198           while (!feof (infile) && strcmp (instr, "*/") != 0)
199             fscanf (infile, "%1023s", instr);
200           fscanf(infile, "%1023s", instr);
201         }
202       if (strcmp (instr, str)==0)
203         return TRUE;
204     }
205
206   return FALSE;
207 }
208
209 static gint
210 gdk_pixmap_seek_char (FILE  *infile,
211                       gchar  c)
212 {
213   gint b, oldb;
214
215   while ((b = getc(infile)) != EOF)
216     {
217       if (c != b && b == '/')
218         {
219           b = getc (infile);
220           if (b == EOF)
221             return FALSE;
222           else if (b == '*')    /* we have a comment */
223             {
224               b = -1;
225               do
226                 {
227                   oldb = b;
228                   b = getc (infile);
229                   if (b == EOF)
230                     return FALSE;
231                 }
232               while (!(oldb == '*' && b == '/'));
233             }
234         }
235       else if (c == b)
236         return TRUE;
237     }
238   return FALSE;
239 }
240
241 static gint
242 gdk_pixmap_read_string (FILE  *infile,
243                         gchar **buffer,
244                         guint *buffer_size)
245 {
246   gint c;
247   guint cnt = 0, bufsiz, ret = FALSE;
248   gchar *buf;
249
250   buf = *buffer;
251   bufsiz = *buffer_size;
252   if (buf == NULL)
253     {
254       bufsiz = 10 * sizeof (gchar);
255       buf = g_new(gchar, bufsiz);
256     }
257
258   do
259     c = getc (infile);
260   while (c != EOF && c != '"');
261
262   if (c != '"')
263     goto out;
264
265   while ((c = getc(infile)) != EOF)
266     {
267       if (cnt == bufsiz)
268         {
269           guint new_size = bufsiz * 2;
270           if (new_size > bufsiz)
271             bufsiz = new_size;
272           else
273             goto out;
274           
275           buf = (gchar *) g_realloc (buf, bufsiz);
276           buf[bufsiz-1] = '\0';
277         }
278
279       if (c != '"')
280         buf[cnt++] = c;
281       else
282         {
283           buf[cnt] = 0;
284           ret = TRUE;
285           break;
286         }
287     }
288
289  out:
290   buf[bufsiz-1] = '\0';         /* ensure null termination for errors */
291   *buffer = buf;
292   *buffer_size = bufsiz;
293   return ret;
294 }
295
296 static gchar*
297 gdk_pixmap_skip_whitespaces (gchar *buffer)
298 {
299   gint32 index = 0;
300
301   while (buffer[index] != 0 && (buffer[index] == 0x20 || buffer[index] == 0x09))
302     index++;
303
304   return &buffer[index];
305 }
306
307 static gchar*
308 gdk_pixmap_skip_string (gchar *buffer)
309 {
310   gint32 index = 0;
311
312   while (buffer[index] != 0 && buffer[index] != 0x20 && buffer[index] != 0x09)
313     index++;
314
315   return &buffer[index];
316 }
317
318 /* Xlib crashed ince at a color name lengths around 125 */
319 #define MAX_COLOR_LEN 120
320
321 static gchar*
322 gdk_pixmap_extract_color (gchar *buffer)
323 {
324   gint counter, numnames;
325   gchar *ptr = NULL, ch, temp[128];
326   gchar color[MAX_COLOR_LEN], *retcol;
327   gint space;
328
329   counter = 0;
330   while (ptr == NULL)
331     {
332       if (buffer[counter] == 'c')
333         {
334           ch = buffer[counter + 1];
335           if (ch == 0x20 || ch == 0x09)
336             ptr = &buffer[counter + 1];
337         }
338       else if (buffer[counter] == 0)
339         return NULL;
340
341       counter++;
342     }
343
344   ptr = gdk_pixmap_skip_whitespaces (ptr);
345
346   if (ptr[0] == 0)
347     return NULL;
348   else if (ptr[0] == '#')
349     {
350       counter = 1;
351       while (ptr[counter] != 0 && 
352              ((ptr[counter] >= '0' && ptr[counter] <= '9') ||
353               (ptr[counter] >= 'a' && ptr[counter] <= 'f') ||
354               (ptr[counter] >= 'A' && ptr[counter] <= 'F')))
355         counter++;
356
357       retcol = g_new (gchar, counter+1);
358       strncpy (retcol, ptr, counter);
359
360       retcol[counter] = 0;
361       
362       return retcol;
363     }
364
365   color[0] = 0;
366   numnames = 0;
367
368   space = MAX_COLOR_LEN - 1;
369   while (space > 0)
370     {
371       sscanf (ptr, "%127s", temp);
372
373       if (((gint)ptr[0] == 0) ||
374           (strcmp ("s", temp) == 0) || (strcmp ("m", temp) == 0) ||
375           (strcmp ("g", temp) == 0) || (strcmp ("g4", temp) == 0))
376         {
377           break;
378         }
379       else
380         {
381           if (numnames > 0)
382             {
383               space -= 1;
384               strcat (color, " ");
385             }
386           strncat (color, temp, space);
387           space -= MIN (space, strlen (temp));
388           ptr = gdk_pixmap_skip_string (ptr);
389           ptr = gdk_pixmap_skip_whitespaces (ptr);
390           numnames++;
391         }
392     }
393
394   retcol = g_strdup (color);
395   return retcol;
396 }
397
398
399 enum buffer_op
400 {
401   op_header,
402   op_cmap,
403   op_body
404 };
405   
406
407 static void 
408 gdk_xpm_destroy_notify (gpointer data)
409 {
410   _GdkPixmapInfo *info = (_GdkPixmapInfo *)data;
411   GdkColor color;
412   int i;
413
414   for (i=0; i<info->ncolors; i++)
415     {
416       color.pixel = info->pixels[i];
417       gdk_colormap_free_colors (info->colormap, &color, 1);
418     }
419
420   gdk_colormap_unref (info->colormap);
421   g_free (info);
422 }
423   
424 static GdkPixmap *
425 _gdk_pixmap_create_from_xpm (GdkWindow  *window,
426                              GdkColormap *colormap,
427                              GdkBitmap **mask,
428                              GdkColor   *transparent_color,
429                              gchar *   (*get_buf) (enum buffer_op op,
430                                                    gpointer       handle),
431                              gpointer    handle)
432 {
433   GdkPixmap *pixmap = NULL;
434   GdkImage *image = NULL;
435   GdkVisual *visual;
436   GdkGC *gc = NULL;
437   GdkColor tmp_color;
438   gint width, height, num_cols, cpp, n, ns, cnt, xcnt, ycnt, wbytes;
439   gchar *buffer, pixel_str[32];
440   gchar *name_buf;
441   _GdkPixmapColor *color = NULL, *fallbackcolor = NULL;
442   _GdkPixmapColor *colors = NULL;
443   gulong index;
444   GHashTable *color_hash = NULL;
445   _GdkPixmapInfo *color_info = NULL;
446   
447   if ((window == NULL) && (colormap == NULL))
448     g_warning ("Creating pixmap from xpm with NULL window and colormap");
449   
450   if (window == NULL)
451     window = (GdkWindow *)&gdk_root_parent;
452   
453   if (colormap == NULL)
454     {
455       colormap = gdk_window_get_colormap (window);
456       visual = gdk_window_get_visual (window);
457     }
458   else
459     visual = ((GdkColormapPrivate *)colormap)->visual;
460   
461   buffer = (*get_buf) (op_header, handle);
462   if (buffer == NULL)
463     return NULL;
464   
465   sscanf (buffer,"%d %d %d %d", &width, &height, &num_cols, &cpp);
466   if (cpp >= 32)
467     {
468       g_warning ("Pixmap has more than 31 characters per color\n");
469       return NULL;
470     }
471   
472   color_hash = g_hash_table_new (g_str_hash, g_str_equal);
473   
474   if (transparent_color == NULL)
475     {
476       gdk_color_white (colormap, &tmp_color);
477       transparent_color = &tmp_color;
478     }
479
480   /* For pseudo-color and grayscale visuals, we have to remember
481    * the colors we allocated, so we can free them later.
482    */
483   if ((visual->type == GDK_VISUAL_PSEUDO_COLOR) ||
484       (visual->type == GDK_VISUAL_GRAYSCALE))
485     {
486       color_info = g_malloc (sizeof (_GdkPixmapInfo) + 
487                              sizeof(gulong) * (num_cols - 1));
488       color_info->ncolors = num_cols;
489       color_info->colormap = colormap;
490       gdk_colormap_ref (colormap);
491     }
492
493   name_buf = g_new (gchar, num_cols * (cpp+1));
494   colors = g_new (_GdkPixmapColor, num_cols);
495
496   for (cnt = 0; cnt < num_cols; cnt++)
497     {
498       gchar *color_name;
499       
500       buffer = (*get_buf) (op_cmap, handle);
501       if (buffer == NULL)
502         goto error;
503       
504       color = &colors[cnt];
505       color->color_string = &name_buf [cnt * (cpp + 1)];
506       strncpy (color->color_string, buffer, cpp);
507       color->color_string[cpp] = 0;
508       buffer += strlen (color->color_string);
509       color->transparent = FALSE;
510       
511       color_name = gdk_pixmap_extract_color (buffer);
512       
513       if (color_name == NULL ||
514           gdk_color_parse (color_name, &color->color) == FALSE)
515         {
516           color->color = *transparent_color;
517           color->transparent = TRUE;
518         }
519       
520       g_free (color_name);
521       
522       /* FIXME: The remaining slowness appears to happen in this
523          function. */
524       gdk_color_alloc (colormap, &color->color);
525
526       if (color_info)
527         color_info->pixels[cnt] = color->color.pixel;
528       
529       g_hash_table_insert (color_hash, color->color_string, color);
530       if (cnt == 0)
531         fallbackcolor = color;
532     }
533   
534   index = 0;
535   image = gdk_image_new (GDK_IMAGE_FASTEST, visual, width, height);
536   
537   if (mask)
538     {
539       /* The pixmap mask is just a bits pattern.
540        * Color 0 is used for background and 1 for foreground.
541        * We don't care about the colormap, we just need 0 and 1.
542        */
543       GdkColor mask_pattern;
544       
545       *mask = gdk_pixmap_new (window, width, height, 1);
546       gc = gdk_gc_new (*mask);
547       
548       mask_pattern.pixel = 0;
549       gdk_gc_set_foreground (gc, &mask_pattern);
550       gdk_draw_rectangle (*mask, gc, TRUE, 0, 0, -1, -1);
551       
552       mask_pattern.pixel = 1;
553       gdk_gc_set_foreground (gc, &mask_pattern);
554     }
555   
556   wbytes = width * cpp;
557   for (ycnt = 0; ycnt < height; ycnt++)
558     {
559       buffer = (*get_buf) (op_body, handle);
560       
561       /* FIXME: this slows things down a little - it could be
562        * integrated into the strncpy below, perhaps. OTOH, strlen
563        * is fast.
564        */
565       if ((buffer == NULL) || strlen (buffer) < wbytes)
566         continue;
567       
568       for (n = 0, cnt = 0, xcnt = 0; n < wbytes; n += cpp, xcnt++)
569         {
570           strncpy (pixel_str, &buffer[n], cpp);
571           pixel_str[cpp] = 0;
572           ns = 0;
573           
574           color = g_hash_table_lookup (color_hash, pixel_str);
575           
576           if (!color) /* screwed up XPM file */
577             color = fallbackcolor;
578           
579           gdk_image_put_pixel (image, xcnt, ycnt, color->color.pixel);
580           
581           if (mask && color->transparent)
582             {
583               if (cnt < xcnt)
584                 gdk_draw_line (*mask, gc, cnt, ycnt, xcnt - 1, ycnt);
585               cnt = xcnt + 1;
586             }
587         }
588       
589       if (mask && (cnt < xcnt))
590         gdk_draw_line (*mask, gc, cnt, ycnt, xcnt - 1, ycnt);
591     }
592   
593  error:
594   
595   if (mask)
596     gdk_gc_destroy (gc);
597   
598   if (image != NULL)
599     {
600       pixmap = gdk_pixmap_new (window, width, height, visual->depth);
601
602       if (color_info)
603         gdk_drawable_set_data (pixmap, "gdk-xpm", color_info, 
604                                gdk_xpm_destroy_notify);
605       
606       gc = gdk_gc_new (pixmap);
607       gdk_gc_set_foreground (gc, transparent_color);
608       gdk_draw_image (pixmap, gc, image, 0, 0, 0, 0, image->width, image->height);
609       gdk_gc_destroy (gc);
610       gdk_image_destroy (image);
611     }
612   else if (color_info)
613     gdk_xpm_destroy_notify (color_info);
614   
615   if (color_hash != NULL)
616     g_hash_table_destroy (color_hash);
617
618   if (colors != NULL)
619     g_free (colors);
620
621   if (name_buf != NULL)
622     g_free (name_buf);
623
624   return pixmap;
625 }
626
627
628 struct file_handle
629 {
630   FILE *infile;
631   gchar *buffer;
632   guint buffer_size;
633 };
634
635
636 static gchar *
637 file_buffer (enum buffer_op op, gpointer handle)
638 {
639   struct file_handle *h = handle;
640
641   switch (op)
642     {
643     case op_header:
644       if (gdk_pixmap_seek_string (h->infile, "XPM", FALSE) != TRUE)
645         break;
646
647       if (gdk_pixmap_seek_char (h->infile,'{') != TRUE)
648         break;
649       /* Fall through to the next gdk_pixmap_seek_char. */
650
651     case op_cmap:
652       gdk_pixmap_seek_char (h->infile, '"');
653       fseek (h->infile, -1, SEEK_CUR);
654       /* Fall through to the gdk_pixmap_read_string. */
655
656     case op_body:
657       gdk_pixmap_read_string (h->infile, &h->buffer, &h->buffer_size);
658       return h->buffer;
659     }
660   return 0;
661 }
662
663
664 GdkPixmap*
665 gdk_pixmap_colormap_create_from_xpm (GdkWindow   *window,
666                                      GdkColormap *colormap,
667                                      GdkBitmap  **mask,
668                                      GdkColor    *transparent_color,
669                                      const gchar *filename)
670 {
671   struct file_handle h;
672   GdkPixmap *pixmap = NULL;
673
674   memset (&h, 0, sizeof (h));
675   h.infile = fopen (filename, "rb");
676   if (h.infile != NULL)
677     {
678       pixmap = _gdk_pixmap_create_from_xpm (window, colormap, mask,
679                                             transparent_color,
680                                             file_buffer, &h);
681       fclose (h.infile);
682       g_free (h.buffer);
683     }
684
685   return pixmap;
686 }
687
688 GdkPixmap*
689 gdk_pixmap_create_from_xpm (GdkWindow  *window,
690                             GdkBitmap **mask,
691                             GdkColor   *transparent_color,
692                             const gchar *filename)
693 {
694   return gdk_pixmap_colormap_create_from_xpm (window, NULL, mask,
695                                        transparent_color, filename);
696 }
697
698
699 struct mem_handle
700 {
701   gchar **data;
702   int offset;
703 };
704
705
706 static gchar *
707 mem_buffer (enum buffer_op op, gpointer handle)
708 {
709   struct mem_handle *h = handle;
710   switch (op)
711     {
712     case op_header:
713     case op_cmap:
714     case op_body:
715       if (h->data[h->offset])
716         return h->data[h->offset ++];
717     }
718   return 0;
719 }
720
721
722 GdkPixmap*
723 gdk_pixmap_colormap_create_from_xpm_d (GdkWindow  *window,
724                                        GdkColormap *colormap,
725                                        GdkBitmap **mask,
726                                        GdkColor   *transparent_color,
727                                        gchar     **data)
728 {
729   struct mem_handle h;
730   GdkPixmap *pixmap = NULL;
731
732   memset (&h, 0, sizeof (h));
733   h.data = data;
734   pixmap = _gdk_pixmap_create_from_xpm (window, colormap, mask,
735                                         transparent_color,
736                                         mem_buffer, &h);
737   return pixmap;
738 }
739
740
741 GdkPixmap*
742 gdk_pixmap_create_from_xpm_d (GdkWindow  *window,
743                               GdkBitmap **mask,
744                               GdkColor   *transparent_color,
745                               gchar     **data)
746 {
747   return gdk_pixmap_colormap_create_from_xpm_d (window, NULL, mask,
748                                                 transparent_color, data);
749 }
750
751 GdkPixmap*
752 gdk_pixmap_foreign_new (guint32 anid)
753 {
754   GdkPixmap *pixmap;
755   GdkWindowPrivate *window_private;
756   GdkWindowPrivate *private;
757   Pixmap xpixmap;
758   Window root_return;
759   unsigned int x_ret, y_ret, w_ret, h_ret, bw_ret, depth_ret;
760
761   /* check to make sure we were passed something at
762      least a little sane */
763   g_return_val_if_fail((anid != 0), NULL);
764   
765   /* set the pixmap to the passed in value */
766   xpixmap = anid;
767   /* get the root window */
768   window_private = &gdk_root_parent;
769
770   /* get information about the Pixmap to fill in the structure for
771      the gdk window */
772   if (!XGetGeometry(window_private->xdisplay, xpixmap, &root_return,
773                     &x_ret, &y_ret, &w_ret, &h_ret, &bw_ret, &depth_ret))
774       return NULL;
775       
776   /* allocate a new gdk pixmap */
777   private = g_new(GdkWindowPrivate, 1);
778   pixmap = (GdkPixmap *)private;
779
780   private->xdisplay = window_private->xdisplay;
781   private->window_type = GDK_WINDOW_PIXMAP;
782   private->xwindow = xpixmap;
783   private->colormap = NULL;
784   private->parent = NULL;
785   private->x = 0;
786   private->y = 0;
787   private->width = w_ret;
788   private->height = h_ret;
789   private->resize_count = 0;
790   private->ref_count = 1;
791   private->destroyed = 0;
792   
793   gdk_xid_table_insert(&private->xwindow, pixmap);
794
795   return pixmap;
796 }
797
798 GdkPixmap*
799 gdk_pixmap_ref (GdkPixmap *pixmap)
800 {
801   GdkWindowPrivate *private = (GdkWindowPrivate *)pixmap;
802   g_return_val_if_fail (pixmap != NULL, NULL);
803
804   private->ref_count += 1;
805   return pixmap;
806 }
807
808 void
809 gdk_pixmap_unref (GdkPixmap *pixmap)
810 {
811   GdkWindowPrivate *private = (GdkWindowPrivate *)pixmap;
812   g_return_if_fail(pixmap != NULL);
813
814   private->ref_count -= 1;
815   if (private->ref_count == 0)
816     {
817       XFreePixmap (private->xdisplay, private->xwindow);
818       gdk_xid_table_remove (private->xwindow);
819       g_dataset_destroy (private);
820       g_free (private);
821     }
822 }
823
824 GdkBitmap *
825 gdk_bitmap_ref (GdkBitmap *bitmap)
826 {
827   return (GdkBitmap *)gdk_pixmap_ref ((GdkPixmap *)bitmap);
828 }
829
830 void
831 gdk_bitmap_unref (GdkBitmap *bitmap)
832 {
833   gdk_pixmap_unref ((GdkPixmap *)bitmap);
834 }