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 */