/***************************************************************************** ** Copyright (C) 1998-2001 Ljubomir Milanovic & Horst Wagner ** This file is part of the g2 library ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ** Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public ** License along with this library; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ******************************************************************************/ #include #include #include #include #include #include #include #include #include "g2.h" #include "g2_device.h" #include "g2_util.h" #include "g2_X11_P.h" #include "g2_X11.h" #include "g2_X11_funix.h" #include "g2_config.h" static int N_X11=0; static g2_X11_device *g2_X11_dev=NULL; /** * \ingroup physdev * \defgroup X11 X11 */ /** * * Open a simple X11 window (physical device device). * * \param width window width * \param height window height * \return physical device id * * \ingroup X11 */ int g2_open_X11(int width, int height) { return g2_open_X11X(width, height, 10, 10, NULL, NULL, NULL, -1, -1); } /** * * Open a X11 window (physical device device). If \a icon_width or \a * icon_height is smaller than 0, the \a icon_data is interpreted as a * file name. * * \param width window width * \param height window height * \param x x position on screen * \param y y position on screen * \param window_name hint for window manager * \param icon_name hint for window manager * \param icon_data icon bitmap (\a icon_width * \a icon_height bits) or file name containing bitmap * (if \a icon_width <= 0 or \a icon_height <= 0) * \param icon_width icon width * \param icon_height icon height * \return physical device id * * \ingroup X11 */ int g2_open_X11X(int width, int height, int x, int y, char *window_name, char *icon_name, char *icon_data, int icon_width, int icon_height) { g2_X11_device *xout=NULL; int pid=-1, i; char name[32]; int vid; if(g2_X11_dev==NULL) { g2_X11_dev=g2_malloc(sizeof(g2_X11_device)); N_X11=1; /* first X11 device */ xout=&g2_X11_dev[N_X11-1]; pid=0; } else { for(i=0;iwidth=width; /* set window size */ xout->height=height; xout->NofInks=0; /* reset inks */ xout->inks=NULL; vid = g2_register_physical_device(pid, NULL, g2_IntCoor, g2_X11_funix, 1.0, -1.0, 0.0, height-1); sprintf(name, "g2: %d", vid); /* set window and icon names */ if(window_name==NULL) window_name=name; if(icon_name==NULL) icon_name=name; g2_X11_init_X11X(pid, width, height, x, y, window_name, icon_name, icon_data, icon_width, icon_height); /* g2 calls */ g2_allocate_basic_colors(vid); g2_set_background(vid, 0); g2_pen(vid, 1); return vid; } /* * * Extended version of the InitX11 * */ int g2_X11_init_X11X(int pid, int width, int height, int xposition, int yposition, char *window_name, char *icon_name, char *icon_data, unsigned int icon_width, unsigned int icon_height) { g2_X11_device *xout=&g2_X11_dev[pid]; Window root; XSetWindowAttributes wattr; XEvent event; Pixmap iconPixmap; XSizeHints sizehints; int xhot, yhot, rv; XColor w_scr, w_exa, r_scr, r_exa; XClassHint class_hint; if((xout->display=XOpenDisplay(NULL))==NULL) { g2_log(Error, "g2: can't open display\n"); exit(-1); } xout->root=RootWindow(xout->display, DefaultScreen(xout->display)); root=xout->root; wattr.event_mask=ExposureMask; xout->window=XCreateWindow(xout->display, root, xposition, yposition, width, height, 0, CopyFromParent, InputOutput, CopyFromParent, CWEventMask, &wattr); xout->gc=XCreateGC(xout->display, xout->window, 0lu, NULL); xout->colormap=DefaultColormap(xout->display, DefaultScreen(xout->display)); XAllocNamedColor(xout->display, xout->colormap, "red", &r_scr, &r_exa); XAllocNamedColor(xout->display, xout->colormap, "white", &w_scr, &w_exa); if(icon_data!=NULL) { if(icon_width<=0 || icon_height<=0) { /* read icon from file */ rv=XReadBitmapFile(xout->display, xout->window, icon_data, &icon_width, &icon_height, &iconPixmap, &xhot, &yhot); } else { /* icon is bitmap */ iconPixmap=XCreatePixmapFromBitmapData(xout->display, xout->window, icon_data, icon_width, icon_height, 1ul, 0ul, 1); rv=BitmapSuccess; } switch(rv) { case BitmapOpenFailed: fputs("g2(OpenXX): bitmap file open failed\n",stderr); break; case BitmapFileInvalid: fputs("g2(OpenXX): bitmap file invalid\n",stderr); break; case BitmapNoMemory: fputs("g2(OpenXX): no enough memeory for bitmap\n",stderr); break; } } else { /* no icon data avail. */ unsigned char bitmapData[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x80,0x03,0x00,0x00,0x00,0xe0, 0x0d,0x00,0x00,0x00,0x60,0x0c,0x00,0x00,0x00,0x20,0x18, 0x00,0x00,0x00,0x00,0x10,0x00,0xf8,0xe3,0x07,0x08,0x00, 0xfe,0xfa,0x07,0x0c,0x00,0xbf,0x6e,0x07,0x06,0x80,0x0f, 0xf5,0x00,0x01,0x80,0x05,0x34,0x80,0x09,0xc0,0x03,0x78, 0xe0,0x18,0x80,0x00,0x70,0xe0,0x1e,0xc0,0x01,0x70,0x70, 0x1b,0xc0,0x01,0x50,0x00,0x00,0xc0,0x01,0x70,0x00,0x00, 0xc0,0x00,0x70,0x00,0x00,0x40,0x03,0x38,0x00,0x00,0x80, 0x05,0x50,0x00,0x00,0x80,0x0a,0x6e,0x00,0x00,0x00,0xfe, 0x37,0x00,0x00,0x00,0x6a,0x59,0x00,0x00,0x00,0xbc,0x57, 0x00,0x00,0x00,0xe0,0x50,0x00,0x00,0x00,0x00,0x60,0x00, 0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x7e,0x00,0x00, 0x00,0x7c,0x2b,0x00,0x00,0x00,0xa4,0x1d,0x00,0x00,0x00, 0xb8,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00}; iconPixmap=XCreatePixmapFromBitmapData(xout->display, xout->window, (char*)bitmapData, 40u, 40u, w_scr.pixel, r_scr.pixel, 1ul); } sizehints.x = xposition; sizehints.y = yposition; sizehints.min_width = width; sizehints.max_width = width; sizehints.min_height = height; sizehints.max_height = height; sizehints.flags = PPosition | PMinSize | PMaxSize; XSetStandardProperties(xout->display, xout->window, window_name, icon_name, iconPixmap, (char **)NULL, 0, &sizehints); class_hint.res_name = "g2"; class_hint.res_class = "G2"; XSetClassHint(xout->display, xout->window, &class_hint); XMapRaised(xout->display, xout->window); /* XSetWindowBackground(xout->display, xout->window, w_scr.pixel); */ XClearWindow(xout->display,xout->window); g2_X11_paper(pid, NULL, 0); g2_X11_set_font_size(pid, NULL, 12); /* wait expose event */ /* (no back. store) */ while(!XCheckWindowEvent(xout->display,xout->window, ExposureMask,&event)) ; wattr.event_mask=NoEventMask; /* set NoEventMask */ wattr.backing_store=Always; /* set backing store */ XChangeWindowAttributes(xout->display, xout->window, CWEventMask|CWBackingStore, &wattr); xout->dest = xout->window; xout->backing_pixmap = None; if(XDoesBackingStore(XDefaultScreenOfDisplay(xout->display))!=Always) { if(g2_EmulateBackingStore) { g2_log(Warning, "g2: Warning! Backing store is not available. Allocating pixmap instead.\n"); xout->backing_pixmap = XCreatePixmap(xout->display, xout->window, xout->width, xout->height, DefaultDepth(xout->display, DefaultScreen(xout->display))); XSetWindowBackgroundPixmap(xout->display, xout->window, xout->backing_pixmap); XSetForeground (xout->display, xout->gc, w_scr.pixel); XFillRectangle(xout->display, xout->backing_pixmap, xout->gc, 0, 0, xout->width, xout->height); xout->dest = xout->backing_pixmap; } else { g2_log(Warning, "g2: Warning! Backing store is not available.\n"); } } XFlush(xout->display); return 0; } int g2_X11_delete(int pid, void *pdp) { g2_X11_device *xout=&g2_X11_dev[pid]; XUnmapWindow(xout->display, xout->window); if (xout->backing_pixmap != None) XFreePixmap(xout->display,xout->backing_pixmap); XDestroyWindow(xout->display, xout->window); XDestroyWindow(xout->display, xout->root); XFreeGC(xout->display, xout->gc); XFreeColormap(xout->display, xout->colormap); XCloseDisplay(xout->display); if(xout->inks!=NULL) g2_free(xout->inks); xout->width=xout->height=0; xout->display=NULL; return 0; } int g2_X11_clear(int pid, void *pdp) { g2_X11_device *xout=&g2_X11_dev[pid]; if (xout->backing_pixmap == None) { XClearWindow(xout->display,xout->window); } else { XSetForeground (xout->display, xout->gc, xout->background); XFillRectangle(xout->display, xout->dest, xout->gc, 0, 0, xout->width, xout->height); } g2_X11_flush(pid, pdp); return 0; } int g2_X11_flush(int pid, void *pdp) { g2_X11_device *xout=&g2_X11_dev[pid]; if( xout->backing_pixmap != None ) { XCopyArea(xout->display, xout->dest, xout->window, xout->gc, 0, 0, xout->width, xout->height, 0, 0); } XFlush(xout->display); return 0; } int g2_X11_ink(int pid, void *pdp, double red, double green, double blue) { g2_X11_device *xout=&g2_X11_dev[pid]; XColor color; color.flags=DoRed|DoGreen|DoBlue; color.red = (int)(red * USHRT_MAX); color.green = (int)(green * USHRT_MAX); color.blue = (int)(blue * USHRT_MAX); if(XAllocColor(xout->display,xout->colormap,&color)) { xout->NofInks++; if(xout->inks==NULL) xout->inks= (unsigned long *)g2_malloc(xout->NofInks*sizeof(unsigned long)); else xout->inks= (unsigned long *)g2_realloc((void *)xout->inks, xout->NofInks*sizeof(unsigned long)); if(xout->inks==NULL) { fputs("g2: not enough memory\n",stderr); return -1; } xout->inks[xout->NofInks-1]=color.pixel; return xout->NofInks-1; } else { fputs("g2: color is not available\n",stderr); return -1; } } int g2_X11_clear_palette(int pid, void *pdp) { g2_X11_device *xout=&g2_X11_dev[pid]; XFreeColors(xout->display,xout->colormap, xout->inks,xout->NofInks,0x0ul); xout->NofInks=0; if(xout->inks!=NULL) free(xout->inks); xout->inks=NULL; return 0; } int g2_X11_set_background(int pid, void *pdp, int color) { g2_X11_device *xout=&g2_X11_dev[pid]; if(color>=xout->NofInks || color<0) return -1; if (xout->backing_pixmap == None) { XSetWindowBackground(xout->display,xout->dest, xout->inks[color]); } else { xout->background = xout->inks[color]; } g2_X11_clear(pid,pdp); return 0; } int g2_X11_pen(int pid, void *pdp, int color) { g2_X11_device *xout=&g2_X11_dev[pid]; if(color>=xout->NofInks || color<0) return -1; XSetForeground(xout->display, xout->gc, xout->inks[color]); return 0; } int g2_X11_paper(int pid, void *pdp, int color) { g2_X11_device *xout=&g2_X11_dev[pid]; if(color>=xout->NofInks || color<0) return -1; XSetBackground(xout->display, xout->gc, xout->inks[color]); return 0; } int g2_X11_set_line_width(int pid, void *pdp, int w) { g2_X11_device *xout=&g2_X11_dev[pid]; XGCValues val; val.line_width=w; XChangeGC(xout->display, xout->gc, GCLineWidth, &val); return 0; } int g2_X11_set_dash(int pid, void *pdp, int n, int *data) { g2_X11_device *xout=&g2_X11_dev[pid]; XGCValues val; int i; if(n<=0 || data==NULL) { val.line_style=LineSolid; XChangeGC(xout->display, xout->gc, GCLineStyle,&val); } else { char *ch_data; ch_data=g2_malloc(n*sizeof(char)); val.line_style=LineOnOffDash; for(i=0;i0) ch_data[i]=(char)data[i]; else ch_data[i]=1; XChangeGC(xout->display, xout->gc, GCLineStyle, &val); XSetDashes(xout->display, xout->gc, 0, ch_data, n); g2_free(ch_data); } return 0; } int g2_X11_set_font_size(int pid, void *pdp, int size) { g2_X11_device *xout=&g2_X11_dev[pid]; XFontStruct *fnt_str; char font_name[256]; int sizei, d, n; sizei=dtoi(size); if(sizei<=0) sizei=1; /* set to smallest size */ for(n=1;n<32;n++) { d=((n&0x01)? -1:1)*(n>>1); sprintf(font_name, g2_X11Font, sizei+d); fnt_str=XLoadQueryFont(xout->display, font_name); if(fnt_str==NULL) { if(!d) fprintf(stderr,"g2: can not load font: '%s'\n",font_name); } else { XSetFont(xout->display,xout->gc,fnt_str->fid); if(d) fprintf(stderr,"g2: using '%s' instead\n",font_name); return 0; } } fprintf(stderr, "g2: are you sure about %d point size\n", size); return -1; } int g2_X11_plot(int pid, void *pdp, int x, int y) { g2_X11_device *xout=&g2_X11_dev[pid]; XDrawPoint(xout->display, xout->dest, xout->gc, x, y); return 0; } int g2_X11_line(int pid, void *pdp, int x1, int y1, int x2, int y2) { g2_X11_device *xout=&g2_X11_dev[pid]; XDrawLine(xout->display,xout->dest,xout->gc, x1, y1, x2, y2); return 0; } int g2_X11_poly_line(int pid, void *pdp, int N, int *p) { g2_X11_device *xout=&g2_X11_dev[pid]; XPoint *points; int i; points=g2_malloc(N*sizeof(XPoint)); for(i=0;idisplay,xout->dest,xout->gc, points, N, CoordModeOrigin); g2_free(points); return 0; } int g2_X11_polygon(int pid, void *pdp, int N, int *p) { g2_X11_device *xout=&g2_X11_dev[pid]; XPoint *points; int i; points=g2_malloc((N+1)*sizeof(XPoint)); for(i=0;idisplay,xout->dest,xout->gc, points, N+1, CoordModeOrigin); g2_free(points); return 0; } int g2_X11_filled_polygon(int pid, void *pdp, int N, int *p) { g2_X11_device *xout=&g2_X11_dev[pid]; XPoint *points; int i; points=g2_malloc((N+1)*sizeof(XPoint)); for(i=0;idisplay,xout->dest,xout->gc, points, N+1, Complex, CoordModeOrigin); g2_free(points); return 0; } int g2_X11_triangle(int pid, void *pdp, int x1, int y1, int x2, int y2, int x3, int y3) { g2_X11_device *xout=&g2_X11_dev[pid]; XPoint points[4]; points[0].x=x1; points[0].y=y1; points[1].x=x2; points[1].y=y2; points[2].x=x3; points[2].y=y3; points[3].x=x1; points[3].y=y1; XDrawLines(xout->display,xout->dest,xout->gc, points, 4, CoordModeOrigin); return 0; } int g2_X11_filled_triangle(int pid, void *pdp, int x1, int y1, int x2, int y2, int x3, int y3) { g2_X11_device *xout=&g2_X11_dev[pid]; XPoint points[4]; points[0].x=x1; points[0].y=y1; points[1].x=x2; points[1].y=y2; points[2].x=x3; points[2].y=y3; points[3].x=x1; points[3].y=y1; XFillPolygon(xout->display,xout->dest,xout->gc, points, 4, Convex, CoordModeOrigin); return 0; } int g2_X11_rectangle(int pid, void *pdp, int x1, int y1, int x2, int y2) { g2_X11_device *xout=&g2_X11_dev[pid]; XDrawRectangle(xout->display,xout->dest,xout->gc, x1, y1, x2-x1, y2-y1); return 0; } int g2_X11_filled_rectangle(int pid, void *pdp, int x1, int y1, int x2, int y2) { g2_X11_device *xout=&g2_X11_dev[pid]; XDrawRectangle(xout->display,xout->dest,xout->gc, x1, y1, x2-x1, y2-y1); XFillRectangle(xout->display,xout->dest,xout->gc, x1, y1, x2-x1, y2-y1); return 0; } int g2_X11_arc(int pid, void *pdp, int x, int y, int r1, int r2, double a1, double a2) { g2_X11_device *xout=&g2_X11_dev[pid]; double a0, d; a0=fmod(a1, 360.) + (a1<0? 360:0); /* map a1 to [0, 360) */ d=a2>a1? a2-a1:a2-a1+360; XDrawArc(xout->display,xout->dest,xout->gc, x-r1, y-r2, r1*2, r2*2, (int)(a0*64.), (int)(d*64.)); return 0; } int g2_X11_filled_arc(int pid, void *pdp, int x, int y, int r1, int r2, double a1, double a2) { g2_X11_device *xout=&g2_X11_dev[pid]; double a0, d; a0=fmod(a1, 360.) + (a1<0? 360:0); /* map a1 to [0, 360) */ d=a2>a1? a2-a1:a2-a1+360; XDrawArc(xout->display,xout->dest,xout->gc, x-r1, y-r2, r1*2, r2*2, (int)(a0*64.), (int)(d*64.)); XFillArc(xout->display,xout->dest,xout->gc, x-r1, y-r2, r1*2, r2*2, (int)(a0*64.), (int)(d*64.)); return 0; } int g2_X11_ellipse(int pid, void *pdp, int x, int y, int r1, int r2) { g2_X11_device *xout=&g2_X11_dev[pid]; XDrawArc(xout->display,xout->dest,xout->gc, x-r1, y-r2, r1*2, r2*2, 0,360*64); return 0; } int g2_X11_filled_ellipse(int pid, void *pdp, int x, int y, int r1, int r2) { g2_X11_device *xout=&g2_X11_dev[pid]; XDrawArc(xout->display,xout->dest,xout->gc, x-r1, y-r2, r1*2, r2*2, 0,360*64); XFillArc(xout->display,xout->dest,xout->gc, x-r1, y-r2, r1*2, r2*2, 0,360*64); XFlush(xout->display); return 0; } int g2_X11_draw_string(int pid, void *pdp, int x, int y, const char *text) { g2_X11_device *xout=&g2_X11_dev[pid]; XDrawString(xout->display,xout->dest,xout->gc, x, y, text, strlen(text)); return 0; } int g2_X11_image(int pid, void *pdp, int x, int y, int width, int height, int *pen_array) { g2_X11_device *xout=&g2_X11_dev[pid]; XImage *image=NULL; Screen *screen; unsigned long *ink_array; int i; ink_array=malloc(sizeof(unsigned long)*width*height); for(i=0;iinks[pen_array[i]]; screen=DefaultScreenOfDisplay(xout->display); image=XCreateImage(xout->display, DefaultVisualOfScreen(screen), DefaultDepthOfScreen(screen), ZPixmap, 0, /* offset */ (char *)ink_array, width, height, sizeof(unsigned long)*8, /* bitmap pad */ 0); /* bytes per line */ /* XInitImage(image); problems with AIX ?!! */ XPutImage(xout->display, xout->dest, xout->gc, image, 0, 0, x, y, width, height); XDestroyImage(image); free(ink_array); return 0; } int g2_X11_query_pointer(int pid, void *pdp, int *x, int *y, unsigned int *button) { Bool rv; g2_X11_device *xout=&g2_X11_dev[pid]; Window root, child; int rx, ry; rv = XQueryPointer(xout->display, xout->window, &root, &child, &rx, &ry, x, y, button); if(rv) return 0; else return 1; } int g2_X11_get_pd_handles(int pid, void *pdp, void *handles[G2_PD_HANDLES_SIZE]) { g2_X11_device *xout=&g2_X11_dev[pid]; handles[0]=xout->display; handles[1]=&xout->window; handles[2]=&xout->root; handles[3]=&xout->colormap; handles[4]=&xout->gc; handles[5]=&xout->dest; return 0; }