Change to the linux kernel coding style
[wmaker-crm.git] / wrlib / xutil.c
1 /* xutil.c - utility functions for X
2  *
3  * Raster graphics library
4  *
5  * Copyright (c) 1997-2003 Alfredo K. Kojima
6  *
7  *  This library is free software; you can redistribute it and/or
8  *  modify it under the terms of the GNU Library General Public
9  *  License as published by the Free Software Foundation; either
10  *  version 2 of the License, or (at your option) any later version.
11  *
12  *  This library is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  *  Library General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Library General Public
18  *  License along with this library; if not, write to the Free
19  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21
22 #include <config.h>
23
24 #include <X11/Xlib.h>
25 #include <X11/Xutil.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <string.h>
29
30 #include <assert.h>
31
32 #ifdef XSHM
33 #include <sys/ipc.h>
34 #include <sys/shm.h>
35 #endif                          /* XSHM */
36
37 #include "wraster.h"
38
39 #ifdef XSHM
40
41 static int shmError;
42
43 static int (*oldErrorHandler) ();
44
45 static int errorHandler(Display * dpy, XErrorEvent * err)
46 {
47         shmError = 1;
48         if (err->error_code != BadAccess)
49                 (*oldErrorHandler) (dpy, err);
50
51         return 0;
52 }
53
54 #endif
55
56 RXImage *RCreateXImage(RContext * context, int depth, unsigned width, unsigned height)
57 {
58         RXImage *rximg;
59         Visual *visual = context->visual;
60
61         rximg = malloc(sizeof(RXImage));
62         if (!rximg) {
63                 RErrorCode = RERR_NOMEMORY;
64                 return NULL;
65         }
66 #ifndef XSHM
67         rximg->image = XCreateImage(context->dpy, visual, depth, ZPixmap, 0, NULL, width, height, 8, 0);
68         if (!rximg->image) {
69                 free(rximg);
70                 RErrorCode = RERR_XERROR;
71                 return NULL;
72         }
73         rximg->image->data = malloc(rximg->image->bytes_per_line * height);
74         if (!rximg->image->data) {
75                 XDestroyImage(rximg->image);
76                 free(rximg);
77                 RErrorCode = RERR_NOMEMORY;
78                 return NULL;
79         }
80 #else                           /* XSHM */
81         if (!context->attribs->use_shared_memory) {
82  retry_without_shm:
83
84                 context->attribs->use_shared_memory = 0;
85                 rximg->is_shared = 0;
86                 rximg->image = XCreateImage(context->dpy, visual, depth, ZPixmap, 0, NULL, width, height, 8, 0);
87                 if (!rximg->image) {
88                         free(rximg);
89                         RErrorCode = RERR_XERROR;
90                         return NULL;
91                 }
92                 rximg->image->data = malloc(rximg->image->bytes_per_line * height);
93                 if (!rximg->image->data) {
94                         XDestroyImage(rximg->image);
95                         free(rximg);
96                         RErrorCode = RERR_NOMEMORY;
97                         return NULL;
98                 }
99         } else {
100                 rximg->is_shared = 1;
101
102                 rximg->info.readOnly = False;
103
104                 rximg->image = XShmCreateImage(context->dpy, visual, depth,
105                                                ZPixmap, NULL, &rximg->info, width, height);
106
107                 rximg->info.shmid = shmget(IPC_PRIVATE, rximg->image->bytes_per_line * height, IPC_CREAT | 0777);
108                 if (rximg->info.shmid < 0) {
109                         context->attribs->use_shared_memory = 0;
110                         perror("wrlib: could not allocate shared memory segment");
111                         XDestroyImage(rximg->image);
112                         goto retry_without_shm;
113                 }
114
115                 rximg->info.shmaddr = shmat(rximg->info.shmid, 0, 0);
116                 if (rximg->info.shmaddr == (void *)-1) {
117                         context->attribs->use_shared_memory = 0;
118                         if (shmctl(rximg->info.shmid, IPC_RMID, 0) < 0)
119                                 perror("wrlib: shmctl");
120                         perror("wrlib: could not allocate shared memory");
121                         XDestroyImage(rximg->image);
122                         goto retry_without_shm;
123                 }
124
125                 shmError = 0;
126                 XSync(context->dpy, False);
127                 oldErrorHandler = XSetErrorHandler(errorHandler);
128                 XShmAttach(context->dpy, &rximg->info);
129                 XSync(context->dpy, False);
130                 XSetErrorHandler(oldErrorHandler);
131
132                 rximg->image->data = rximg->info.shmaddr;
133                 /*      rximg->image->obdata = &(rximg->info); */
134
135                 if (shmError) {
136                         context->attribs->use_shared_memory = 0;
137                         XDestroyImage(rximg->image);
138                         if (shmdt(rximg->info.shmaddr) < 0)
139                                 perror("wrlib: shmdt");
140                         if (shmctl(rximg->info.shmid, IPC_RMID, 0) < 0)
141                                 perror("wrlib: shmctl");
142                         /*      printf("wrlib:error attaching shared memory segment to XImage\n");
143                          */
144                         goto retry_without_shm;
145                 }
146         }
147 #endif                          /* XSHM */
148
149         return rximg;
150 }
151
152 void RDestroyXImage(RContext * context, RXImage * rximage)
153 {
154 #ifndef XSHM
155         XDestroyImage(rximage->image);
156 #else                           /* XSHM */
157         if (rximage->is_shared) {
158                 XSync(context->dpy, False);
159                 XShmDetach(context->dpy, &rximage->info);
160                 XDestroyImage(rximage->image);
161                 if (shmdt(rximage->info.shmaddr) < 0)
162                         perror("wrlib: shmdt");
163                 if (shmctl(rximage->info.shmid, IPC_RMID, 0) < 0)
164                         perror("wrlib: shmctl");
165         } else {
166                 XDestroyImage(rximage->image);
167         }
168 #endif
169         free(rximage);
170 }
171
172 static unsigned getDepth(Display * dpy, Drawable d)
173 {
174         Window w;
175         int foo;
176         unsigned bar;
177         unsigned depth;
178
179         XGetGeometry(dpy, d, &w, &foo, &foo, &bar, &bar, &bar, &depth);
180
181         return depth;
182 }
183
184 RXImage *RGetXImage(RContext * context, Drawable d, int x, int y, unsigned width, unsigned height)
185 {
186         RXImage *ximg = NULL;
187
188 #ifdef XSHM
189         if (context->attribs->use_shared_memory && 0) {
190                 ximg = RCreateXImage(context, getDepth(context->dpy, d), width, height);
191
192                 if (ximg && !ximg->is_shared) {
193                         RDestroyXImage(context, ximg);
194                         ximg = NULL;
195                 }
196                 if (ximg) {
197                         XShmGetImage(context->dpy, d, ximg->image, x, y, AllPlanes);
198                 }
199         }
200         if (!ximg) {
201                 ximg = malloc(sizeof(RXImage));
202                 if (!ximg) {
203                         RErrorCode = RERR_NOMEMORY;
204                         return NULL;
205                 }
206                 ximg->is_shared = 0;
207                 ximg->image = XGetImage(context->dpy, d, x, y, width, height, AllPlanes, ZPixmap);
208         }
209         return ximg;
210 #else                           /* !XSHM */
211         ximg = malloc(sizeof(RXImage));
212         if (!ximg) {
213                 RErrorCode = RERR_NOMEMORY;
214                 return NULL;
215         }
216
217         ximg->image = XGetImage(context->dpy, d, x, y, width, height, AllPlanes, ZPixmap);
218
219         return ximg;
220 #endif                          /* !XSHM */
221 }
222
223 void
224 RPutXImage(RContext * context, Drawable d, GC gc, RXImage * ximage, int src_x,
225            int src_y, int dest_x, int dest_y, unsigned int width, unsigned int height)
226 {
227 #ifndef XSHM
228         XPutImage(context->dpy, d, gc, ximage->image, src_x, src_y, dest_x, dest_y, width, height);
229 #else
230         if (ximage->is_shared) {
231                 XShmPutImage(context->dpy, d, gc, ximage->image, src_x, src_y,
232                              dest_x, dest_y, width, height, False);
233         } else {
234                 XPutImage(context->dpy, d, gc, ximage->image, src_x, src_y, dest_x, dest_y, width, height);
235         }
236         XFlush(context->dpy);
237 #endif                          /* XSHM */
238 }
239
240 #ifdef XSHM
241 Pixmap R_CreateXImageMappedPixmap(RContext * context, RXImage * rximage)
242 {
243         Pixmap pix;
244
245         pix = XShmCreatePixmap(context->dpy, context->drawable,
246                                rximage->image->data, &rximage->info,
247                                rximage->image->width, rximage->image->height, rximage->image->depth);
248
249         return pix;
250 }
251
252 #endif                          /* XSHM */