diff options
Diffstat (limited to 'w3mimg/x11/x11_w3mimg.c')
-rw-r--r-- | w3mimg/x11/x11_w3mimg.c | 330 |
1 files changed, 330 insertions, 0 deletions
diff --git a/w3mimg/x11/x11_w3mimg.c b/w3mimg/x11/x11_w3mimg.c new file mode 100644 index 0000000..685f038 --- /dev/null +++ b/w3mimg/x11/x11_w3mimg.c @@ -0,0 +1,330 @@ +/* $Id: x11_w3mimg.c,v 1.1 2002/07/17 20:58:48 ukai Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> + +#include <Imlib.h> + +#include "w3mimg/w3mimg.h" + +#define OFFSET_X 2 +#define OFFSET_Y 2 + +struct x11_info { + Display *display; + Window window, parent; + unsigned long background_pixel; + GC imageGC; + ImlibData *id; +}; + +static int +x11_init(w3mimg_op *self) +{ + struct x11_info *xi; + if (self == NULL) + return 0; + xi = (struct x11_info *)self->priv; + if (xi == NULL) + return 0; + if (! xi->id) { + xi->id = Imlib_init(xi->display); + if (! xi->id) + return 0; + } + if (! xi->imageGC) { + xi->imageGC = XCreateGC(xi->display, xi->parent, 0, NULL); + if (! xi->imageGC) + return 0; + } + return 1; +} + +static int +x11_finish(w3mimg_op *self) +{ + struct x11_info *xi; + if (self == NULL) + return 0; + xi = (struct x11_info *)self->priv; + if (xi == NULL) + return 0; + if (xi->imageGC) { + XFreeGC(xi->display, xi->imageGC); + xi->imageGC = NULL; + } + return 1; +} + +static int +x11_active(w3mimg_op *self) +{ + struct x11_info *xi; + if (self == NULL) + return 0; + xi = (struct x11_info *)self->priv; + if (xi == NULL) + return 0; + if (! xi->imageGC) + return 0; + return 1; +} + +static void +x11_set_background(w3mimg_op *self, char *background) +{ + XColor screen_def, exact_def; + struct x11_info *xi; + if (self == NULL) + return; + xi = (struct x11_info *)self->priv; + if (xi == NULL) + return; + + if (background && + XAllocNamedColor(xi->display, DefaultColormap(xi->display, 0), + background, &screen_def, &exact_def)) + xi->background_pixel = screen_def.pixel; + else { + Pixmap p; + GC gc; + XImage *i; + + p = XCreatePixmap(xi->display, xi->window, 1, 1, + DefaultDepth(xi->display, 0)); + gc = XCreateGC(xi->display, xi->window, 0, NULL); + if (!p || !gc) + exit(1); /* XXX */ + XCopyArea(xi->display, xi->window, p, gc, + (self->offset_x >= 1) ? (self->offset_x - 1) : 0, + (self->offset_y >= 1) ? (self->offset_y - 1) : 0, + 1, 1, 0, 0); + i = XGetImage(xi->display, p, 0, 0, 1, 1, -1, ZPixmap); + if (!i) + exit(1); + xi->background_pixel = XGetPixel(i, 0, 0); + XDestroyImage(i); + XFreeGC(xi->display, gc); + XFreePixmap(xi->display, p); + } +} + +static void +x11_sync(w3mimg_op *self) +{ + struct x11_info *xi; + if (self == NULL) + return; + xi = (struct x11_info *)self->priv; + if (xi == NULL) + return; + XSync(xi->display, False); +} + +static void +x11_close(w3mimg_op *self) +{ + /* XCloseDisplay(xi->display); */ +} + +static int +x11_load_image(w3mimg_op *self, W3MImage *img, char *fname, int w, int h) +{ + struct x11_info *xi; + ImlibImage *im; + + if (self == NULL) + return 0; + xi = (struct x11_info *)self->priv; + if (xi == NULL) + return 0; + + im = Imlib_load_image(xi->id, fname); + if (!im) + return 0; + if (w <= 0) + w = im->rgb_width; + if (h <= 0) + h = im->rgb_height; + img->pixmap = (void *)XCreatePixmap(xi->display, xi->parent, w, h, + DefaultDepth(xi->display, 0)); + if (! img->pixmap) + return 0; + XSetForeground(xi->display, xi->imageGC, xi->background_pixel); + XFillRectangle(xi->display, (Pixmap)img->pixmap, xi->imageGC, 0, 0, w, h); + Imlib_paste_image(xi->id, im, (Pixmap)img->pixmap, 0, 0, w, h); + Imlib_kill_image(xi->id, im); + img->width = w; + img->height = h; + return 1; +} + +static int +x11_show_image(w3mimg_op *self, W3MImage *img, int sx, int sy, int sw, int sh, + int x, int y) +{ + struct x11_info *xi; + if (self == NULL) + return 0; + xi = (struct x11_info *)self->priv; + if (xi == NULL) + return 0; + + XCopyArea(xi->display, (Pixmap)img->pixmap, xi->window, xi->imageGC, + sx, sy, + (sw ? sw : img->width), + (sh ? sh : img->height), + x + self->offset_x, y + self->offset_y); + return 1; +} + +static void +x11_free_image(w3mimg_op *self, W3MImage *img) +{ + struct x11_info *xi; + if (self == NULL) + return; + xi = (struct x11_info *)self->priv; + if (xi == NULL) + return; + if (img && img->pixmap) { + XFreePixmap(xi->display, (Pixmap)img->pixmap); + img->pixmap = NULL; + img->width = 0; + img->height = 0; + } +} + + +/* *INDENT-OFF* */ +/* + xterm/kterm/hanterm/cxterm + top window (WINDOWID) + +- text window + +- scrollbar + rxvt/aterm/Eterm/wterm + top window (WINDOWID) + +- text window + +- scrollbar + +- menubar (etc.) + gnome-terminal + top window + +- text window (WINDOWID) + +- scrollbar + +- menubar + mlterm (-s) + top window + +- text window (WINDOWID) + +- scrollbar + mlterm + top window = text window (WINDOWID) + + powershell + top window + +- window + | +- text window + | +- scrollbar + +- menubar (etc.) + dtterm + top window + +- window + +- window + | +- window + | +- text window + | +- scrollbar + +- menubar + hpterm + top window + +- window + +- text window + +- scrollbar + +- (etc.) +*/ +/* *INDENT-ON* */ + +w3mimg_op * +w3mimg_x11open() +{ + w3mimg_op *wop = NULL; + struct x11_info *xi = NULL; + char *id; + int revert, i, nchildren; + XWindowAttributes attr; + Window root, *children; + + wop = (w3mimg_op *)malloc(sizeof(w3mimg_op)); + if (wop == NULL) + return NULL; + memset(wop, 0, sizeof(w3mimg_op)); + + xi = (struct x11_info *)malloc(sizeof(struct x11_info)); + if (xi == NULL) + goto error; + memset(xi, 0, sizeof(struct x11_info)); + + xi->display = XOpenDisplay(NULL); + if (xi->display == NULL) { + goto error; + } + if ((id = getenv("WINDOWID")) != NULL) + xi->window = (Window)atoi(id); + else + XGetInputFocus(xi->display, &xi->window, &revert); + if (! xi->window) + exit(1); + + XGetWindowAttributes(xi->display, xi->window, &attr); + wop->width = attr.width; + wop->height = attr.height; + + while (1) { + Window p_window; + + XQueryTree(xi->display, xi->window, &root, &xi->parent, + &children, &nchildren); + p_window = xi->window; + for (i = 0; i < nchildren; i++) { + XGetWindowAttributes(xi->display, children[i], &attr); + if (attr.width > wop->width * 0.7 && + attr.height > wop->height * 0.7) { + /* maybe text window */ + wop->width = attr.width; + wop->height = attr.height; + xi->window = children[i]; + } + } + if (p_window == xi->window) + break; + } + wop->offset_x = OFFSET_X; + for (i = 0; i < nchildren; i++) { + XGetWindowAttributes(xi->display, children[i], &attr); + if (attr.x <= 0 && attr.width < 30 && + attr.height > wop->height * 0.7) { + /* scrollbar of xterm/kterm ? */ + wop->offset_x += attr.x + attr.width + attr.border_width * 2; + break; + } + } + wop->offset_y = OFFSET_Y; + + wop->priv = xi; + + wop->init = x11_init; + wop->finish = x11_finish; + wop->active = x11_active; + wop->set_background = x11_set_background; + wop->sync = x11_sync; + wop->close = x11_close; + + wop->load_image = x11_load_image; + wop->show_image = x11_show_image; + wop->free_image = x11_free_image; + + return wop; +error: + if (xi) + free(xi); + free(wop); + return NULL; +} |