+#define copy_to(from, xoff, yoff, to, op) \
+ bitblt (st, st->from, st->to, op, 0, 0, \
+ st->size-(xoff), st->size-(yoff), (xoff), (yoff))
+
+#define copy_from(to, xoff, yoff, from, op) \
+ bitblt (st, st->from, st->to, op, (xoff), (yoff), \
+ st->size-(xoff), st->size-(yoff), 0, 0)
+
+
+#ifdef USE_XCOPYAREA
+# define bitblt(st, from, to, op, src_x, src_y, w, h, dst_x, dst_y) \
+ XCopyArea((st)->dpy, (from), (to), (st)->gc_##op, \
+ (src_x), (src_y), (w), (h), (dst_x), (dst_y))
+#else /* !USE_XCOPYAREA */
+
+# define bitblt(st, from, to, op, src_x, src_y, w, h, dst_x, dst_y) \
+ do_bitblt((st)->dpy, (from), (to), st->gc, GX##op, \
+ (src_x), (src_y), (w), (h), (dst_x), (dst_y))
+
+static void
+do_bitblt (Display *dpy, Drawable src, Drawable dst, GC gc, int op,
+ int src_x, int src_y,
+ unsigned int width, unsigned int height,
+ int dst_x, int dst_y)
+{
+ if (op == GXclear)
+ {
+ XSetForeground (dpy, gc, 0xFF000000); /* ARGB black for Cocoa */
+ XFillRectangle (dpy, dst, gc, dst_x, dst_y, width, height);
+ }
+ else if (op == GXset)
+ {
+ XSetForeground (dpy, gc, ~0L);
+ XFillRectangle (dpy, dst, gc, dst_x, dst_y, width, height);
+ }
+ else if (op == GXcopy)
+ {
+ XCopyArea (dpy, src, dst, gc, src_x, src_y, width, height, dst_x, dst_y);
+ }
+ else
+ {
+ XImage *srci = XGetImage (dpy, src, src_x, src_y, width, height,
+ ~0L, ZPixmap);
+ XImage *dsti = XGetImage (dpy, dst, dst_x, dst_y, width, height,
+ ~0L, ZPixmap);
+ unsigned long *out = (unsigned long *) dsti->data;
+ unsigned long *in = (unsigned long *) srci->data;
+ unsigned long *end = (in + (height * srci->bytes_per_line
+ / sizeof(unsigned long)));
+ switch (op)
+ {
+ case GXor: while (in < end) { *out++ |= *in++; } break;
+ case GXand: while (in < end) { *out++ &= *in++; } break;
+ case GXxor: while (in < end) { *out++ ^= *in++; } break;
+ default: abort();
+ }
+ XPutImage (dpy, dst, gc, dsti, 0, 0, dst_x, dst_y, width, height);
+ XDestroyImage (srci);
+ XDestroyImage (dsti);
+ }
+}
+
+#endif /* !USE_XCOPYAREA */
+