WRaster: add functions to save image on disk
[wmaker-crm.git] / wrlib / xutil.c
blob2ca872aedb94e089a69537625da1d274c3456c2b
1 /* xutil.c - utility functions for X
3 * Raster graphics library
5 * Copyright (c) 1997-2003 Alfredo K. Kojima
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.
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.
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., 51 Franklin St, Fifth Floor, Boston,
20 * MA 02110-1301, USA.
23 #include <config.h>
25 #include <X11/Xlib.h>
26 #include <X11/Xutil.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <errno.h>
32 #include <assert.h>
34 #ifdef USE_XSHM
35 #include <sys/ipc.h>
36 #include <sys/shm.h>
37 #endif /* USE_XSHM */
39 #include "wraster.h"
40 #include "xutil.h"
41 #include "wr_i18n.h"
44 #ifdef USE_XSHM
46 static int shmError;
48 static int (*oldErrorHandler)(Display *dpy, XErrorEvent *err);
50 static int errorHandler(Display * dpy, XErrorEvent * err)
52 shmError = 1;
53 if (err->error_code != BadAccess)
54 (*oldErrorHandler) (dpy, err);
56 return 0;
59 #endif
61 RXImage *RCreateXImage(RContext * context, int depth, unsigned width, unsigned height)
63 RXImage *rximg;
64 Visual *visual = context->visual;
66 rximg = malloc(sizeof(RXImage));
67 if (!rximg) {
68 RErrorCode = RERR_NOMEMORY;
69 return NULL;
71 #ifndef USE_XSHM
72 rximg->image = XCreateImage(context->dpy, visual, depth, ZPixmap, 0, NULL, width, height, 8, 0);
73 if (!rximg->image) {
74 free(rximg);
75 RErrorCode = RERR_XERROR;
76 return NULL;
78 rximg->image->data = malloc(rximg->image->bytes_per_line * height);
79 if (!rximg->image->data) {
80 XDestroyImage(rximg->image);
81 free(rximg);
82 RErrorCode = RERR_NOMEMORY;
83 return NULL;
85 #else /* USE_XSHM */
86 if (!context->attribs->use_shared_memory) {
87 retry_without_shm:
89 context->attribs->use_shared_memory = 0;
90 rximg->is_shared = 0;
91 rximg->image = XCreateImage(context->dpy, visual, depth, ZPixmap, 0, NULL, width, height, 8, 0);
92 if (!rximg->image) {
93 free(rximg);
94 RErrorCode = RERR_XERROR;
95 return NULL;
97 rximg->image->data = malloc(rximg->image->bytes_per_line * height);
98 if (!rximg->image->data) {
99 XDestroyImage(rximg->image);
100 free(rximg);
101 RErrorCode = RERR_NOMEMORY;
102 return NULL;
104 } else {
105 rximg->is_shared = 1;
107 rximg->info.readOnly = False;
109 rximg->image = XShmCreateImage(context->dpy, visual, depth,
110 ZPixmap, NULL, &rximg->info, width, height);
112 rximg->info.shmid = shmget(IPC_PRIVATE, rximg->image->bytes_per_line * height, IPC_CREAT | 0777);
113 if (rximg->info.shmid < 0) {
114 context->attribs->use_shared_memory = 0;
115 fprintf(stderr, _("wrlib: could not allocate shared memory segment, %s: %s\n"), "shmget", strerror(errno));
116 XDestroyImage(rximg->image);
117 goto retry_without_shm;
120 rximg->info.shmaddr = shmat(rximg->info.shmid, 0, 0);
121 if (rximg->info.shmaddr == (void *)-1) {
122 fprintf(stderr, _("wrlib: could not allocate shared memory segment, %s: %s\n"), "shmat", strerror(errno));
123 context->attribs->use_shared_memory = 0;
124 if (shmctl(rximg->info.shmid, IPC_RMID, 0) < 0)
125 fprintf(stderr, _("wrlib: error occured while aborting %s, %s\n"), "shmctl", strerror(errno));
126 XDestroyImage(rximg->image);
127 goto retry_without_shm;
130 shmError = 0;
131 XSync(context->dpy, False);
132 oldErrorHandler = XSetErrorHandler(errorHandler);
133 XShmAttach(context->dpy, &rximg->info);
134 XSync(context->dpy, False);
135 XSetErrorHandler(oldErrorHandler);
137 rximg->image->data = rximg->info.shmaddr;
138 /* rximg->image->obdata = &(rximg->info); */
140 if (shmError) {
141 fprintf(stderr, _("wrlib: could not attach shared memory segment to XImage\n"));
142 context->attribs->use_shared_memory = 0;
143 XDestroyImage(rximg->image);
144 if (shmdt(rximg->info.shmaddr) < 0)
145 fprintf(stderr, _("wrlib: error occured while aborting %s, %s\n"), "shmdt", strerror(errno));
146 if (shmctl(rximg->info.shmid, IPC_RMID, 0) < 0)
147 fprintf(stderr, _("wrlib: error occured while aborting %s, %s\n"), "shmctl", strerror(errno));
148 goto retry_without_shm;
151 #endif /* USE_XSHM */
153 return rximg;
156 void RDestroyXImage(RContext * context, RXImage * rximage)
158 #ifndef USE_XSHM
159 /* Argument is not used in this case, tell the compiler it is ok */
160 (void) context;
162 XDestroyImage(rximage->image);
163 #else /* USE_XSHM */
164 if (rximage->is_shared) {
165 XSync(context->dpy, False);
166 XShmDetach(context->dpy, &rximage->info);
167 XDestroyImage(rximage->image);
168 if (shmdt(rximage->info.shmaddr) < 0)
169 fprintf(stderr, _("wrlib: error occured while releasing XImage, %s: %s\n"), "shmdt", strerror(errno));
170 if (shmctl(rximage->info.shmid, IPC_RMID, 0) < 0)
171 fprintf(stderr, _("wrlib: error occured while releasing XImage, %s: %s\n"), "shmctl", strerror(errno));
172 } else {
173 XDestroyImage(rximage->image);
175 #endif
176 free(rximage);
179 static unsigned getDepth(Display * dpy, Drawable d)
181 Window w;
182 int foo;
183 unsigned bar;
184 unsigned depth;
186 XGetGeometry(dpy, d, &w, &foo, &foo, &bar, &bar, &bar, &depth);
188 return depth;
191 RXImage *RGetXImage(RContext * context, Drawable d, int x, int y, unsigned width, unsigned height)
193 RXImage *ximg = NULL;
195 #ifdef USE_XSHM
196 if (context->attribs->use_shared_memory && 0) {
197 ximg = RCreateXImage(context, getDepth(context->dpy, d), width, height);
199 if (ximg && !ximg->is_shared) {
200 RDestroyXImage(context, ximg);
201 ximg = NULL;
203 if (ximg) {
204 XShmGetImage(context->dpy, d, ximg->image, x, y, AllPlanes);
207 if (!ximg) {
208 ximg = malloc(sizeof(RXImage));
209 if (!ximg) {
210 RErrorCode = RERR_NOMEMORY;
211 return NULL;
213 ximg->is_shared = 0;
214 ximg->image = XGetImage(context->dpy, d, x, y, width, height, AllPlanes, ZPixmap);
216 #else /* !USE_XSHM */
217 ximg = malloc(sizeof(RXImage));
218 if (!ximg) {
219 RErrorCode = RERR_NOMEMORY;
220 return NULL;
223 ximg->image = XGetImage(context->dpy, d, x, y, width, height, AllPlanes, ZPixmap);
224 #endif /* !USE_XSHM */
226 if (ximg->image == NULL) {
227 free(ximg);
228 return NULL;
231 return ximg;
234 void
235 RPutXImage(RContext * context, Drawable d, GC gc, RXImage * ximage, int src_x,
236 int src_y, int dest_x, int dest_y, unsigned int width, unsigned int height)
238 #ifndef USE_XSHM
239 XPutImage(context->dpy, d, gc, ximage->image, src_x, src_y, dest_x, dest_y, width, height);
240 #else
241 if (ximage->is_shared) {
242 XShmPutImage(context->dpy, d, gc, ximage->image, src_x, src_y,
243 dest_x, dest_y, width, height, False);
244 } else {
245 XPutImage(context->dpy, d, gc, ximage->image, src_x, src_y, dest_x, dest_y, width, height);
247 XFlush(context->dpy);
248 #endif /* USE_XSHM */
251 #ifdef USE_XSHM
252 Pixmap R_CreateXImageMappedPixmap(RContext * context, RXImage * rximage)
254 Pixmap pix;
256 pix = XShmCreatePixmap(context->dpy, context->drawable,
257 rximage->image->data, &rximage->info,
258 rximage->image->width, rximage->image->height, rximage->image->depth);
260 return pix;
263 #endif /* USE_XSHM */