/* Changed for truecolor 24bit support by * Roberto Flor/ITC-Irst, Trento, Italy * August 1999 * * Heavily modified by Glynn Clements, May 2001 */ #include /* This driver extensively updated by P. Thompson * (phils@athena.mit.edu) on 9/13/90 Driver modified to work with * Decstation X11r3 by David B. Satnik on 8/90 */ #include #include #include #include "includes.h" #include #include #include #include "icon.bit" #include #include #include "XDRIVER.h" /* This program is a rewrite of the original Grah_Set from the GRASS * 3.0 version. All suncore and sunview related stuff (which was the * bulk of the original code) has been replaced by X11 library calls. * All non-suncore code has been retained. */ /* declare global variables */ const char *monitor_name; Display *dpy; Window grwin; Visual *use_visual; int use_bit_depth; int scrn; Screen *use_screen; GC gc; Colormap floatcmap, fixedcmap; Cursor cur_xh, cur_clock; u_long gemask = StructureNotifyMask; Pixmap bkupmap; int truecolor; int external_window; unsigned long *xpixels; /* lookup table for FIXED color mode */ #ifdef X11R3 /* compatibility functions for X11R3 */ static Status XSetWMProtocols(Display *dpy, Window w, Atom *protocols, int count) { Atom wmProtocols; wmProtocols = XInternAtom (dpy, "WM_PROTOCOLS", False); if (!wmProtocols) return 0; XChangeProperty(dpy, w, wmProtocols, XA_ATOM, 32, PropModeReplace, (unsigned char *) protocols, count); return 1; } XSizeHints * XAllocSizeHints(void) { return (XSizeHints *) G_malloc(sizeof(XSizeHints)); } XWMHints * XAllocWMHints(void) { return (XWMHints *) G_malloc(sizeof(XWMHints)); } XClassHint * XAllocClassHint(void) { return (XClassHint *) G_malloc(sizeof(XClassHint)); } #endif static RETSIGTYPE sigint(int sig) { COM_Graph_close(); exit(1); } static void find_truecolor_visual(void) { static int search_mask = VisualClassMask | VisualScreenMask; XVisualInfo search_template; XVisualInfo *mvisual_info; int num_visuals; int vis_num; int highest_bit_depth = 0; search_template.class = TrueColor; search_template.screen = scrn; mvisual_info = XGetVisualInfo(dpy, search_mask, &search_template, &num_visuals); fprintf (stderr,_("found %d visuals of type TrueColor\n"), num_visuals); fprintf(stderr,_("searching for highest bit depth\n")); for (vis_num = 0; vis_num < num_visuals; vis_num++) { if (mvisual_info[vis_num].depth <= highest_bit_depth) continue; use_visual = mvisual_info[vis_num].visual; use_bit_depth = mvisual_info[vis_num].depth; highest_bit_depth = use_bit_depth; } XFree(mvisual_info); if (highest_bit_depth == 0) G_warning("unable to find a TrueColor visual\n"); else fprintf(stderr, _("selected %d bit depth\n"), use_bit_depth); } static void use_window(int win_id) { XWindowAttributes xwa; external_window = 1; grwin = (Window) win_id; XSelectInput(dpy, grwin, gemask); if (!XGetWindowAttributes(dpy, grwin, &xwa)) G_fatal_error("Graph_Set: cannot get window attributes\n"); use_screen = xwa.screen; scrn = XScreenNumberOfScreen(xwa.screen); use_visual = xwa.visual; use_bit_depth = xwa.depth; } static void create_window(int argc, char **argv) { static const char * const classname[6] = { "StaticGray", "GrayScale", "StaticColor", "PseudoColor", "TrueColor", "DirectColor" }; XSetWindowAttributes xswa; /* Set Window Attribute struct */ Atom closedownAtom; #ifndef X11R3 XTextProperty windowName, iconName; #endif /* X11R3 */ XSizeHints *szhints; XClassHint *clshints; XWMHints *wmhints; char title[1024]; char *p; external_window = 0; /* scrn is the screen number */ scrn = DefaultScreen(dpy); /* use_screen is a pointer to that screen structure */ use_screen = ScreenOfDisplay(dpy, scrn); use_visual = NULL; /* special flag to indicate a search for a True Color Display */ p = getenv("XDRIVER_TRUECOLOR"); if (p && strcmp(p, "TRUE") == 0) find_truecolor_visual(); /* If we can't find a TrueColor visual then use the default visual */ if (!use_visual) { use_visual = DefaultVisual(dpy, scrn); use_bit_depth = DefaultDepth(dpy, scrn); fprintf(stderr, _("using default visual which is %s\n"), classname[use_visual->class]); } /* Deal with providing the window with an initial size. * Window is resizable */ szhints = XAllocSizeHints(); szhints->flags = USSize; szhints->height = screen_bottom - screen_top; szhints->width = screen_right - screen_left; /* Create the Window with the information in the XSizeHints */ xswa.event_mask = gemask; xswa.backing_store = NotUseful; grwin = XCreateWindow(dpy, RootWindow(dpy, scrn), 0, 0, (unsigned)szhints->width, (unsigned)szhints->height, 0, use_bit_depth, InputOutput, use_visual, (CWEventMask | CWBackingStore), &xswa); /* properties for window manager */ wmhints = XAllocWMHints(); wmhints->icon_pixmap = XCreateBitmapFromData(dpy, grwin, icon_bits, icon_width, icon_height); wmhints->flags |= IconPixmapHint; clshints = XAllocClassHint(); clshints->res_name = NULL; clshints->res_class = WIN_NAME; #ifndef X11R3 sprintf (title, "GRASS %s - Monitor: %s - Location: %s", WIN_NAME, monitor_name, G_location()); iconName.encoding = XA_STRING; iconName.format = 8; iconName.value = (u_char *) title; iconName.nitems = strlen((char *) iconName.value); windowName.encoding = iconName.encoding = XA_STRING; windowName.format = iconName.format = 8; windowName.value = (u_char *) title; windowName.nitems = strlen((char *) windowName.value); XSetWMProperties(dpy, grwin, &windowName, &iconName, argv, argc, szhints, wmhints, clshints); #endif closedownAtom = XInternAtom(dpy, "WM_DELETE_WINDOW", False); XSetWMProtocols(dpy, grwin, &closedownAtom, 1); /* Map the window to make it visible. This causes an expose event */ XMapWindow(dpy, grwin); } static Cursor create_cross_cursor(void) { static int width = 16; static int height = 16; static int x0 = 7; static int y0 = 7; /* Old cursor */ /* static const unsigned char pix_data[] = { 0x00, 0x00, 0xa0, 0x02, 0xa0, 0x02, 0xa0, 0x02, 0xa0, 0x02, 0xbe, 0x3e, 0x80, 0x00, 0x7e, 0x3f, 0x80, 0x00, 0xbe, 0x3e, 0xa0, 0x02, 0xa0, 0x02, 0xa0, 0x02, 0xa0, 0x02, 0x00, 0x00, 0x00, 0x00 }; static const unsigned char mask_data[] = { 0x00, 0x00, 0xe0, 0x03, 0xe0, 0x03, 0xe0, 0x03, 0xe0, 0x03, 0xfe, 0x3f, 0xfe, 0x3f, 0x7e, 0x3f, 0xfe, 0x3f, 0xfe, 0x3f, 0xe0, 0x03, 0xe0, 0x03, 0xe0, 0x03, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00 }; */ static const unsigned char pix_data[] = { 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00 }; static const unsigned char mask_data[] = { 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0x00, 0x00, 0x1f, 0x7c, 0x1f, 0x7c, 0x1f, 0x7c, 0x00, 0x00, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0x00, 0x00, }; Pixmap pix, mask; XColor fg, bg; fg.pixel = BlackPixel(dpy, scrn); XQueryColor(dpy, fixedcmap, &fg); bg.pixel = WhitePixel(dpy, scrn); XQueryColor(dpy, fixedcmap, &bg); pix = XCreateBitmapFromData(dpy, grwin, pix_data, width, height); mask = XCreateBitmapFromData(dpy, grwin, mask_data, width, height); return XCreatePixmapCursor(dpy, pix, mask, &fg, &bg, x0, y0); } int XD_Graph_set(int argc, char **argv) { XWindowAttributes xwa; /* Get Window Attribute struct */ const char *privcmap; char *p; int win_id; int i; monitor_name = argv[1]; /* Open the display using the $DISPLAY environment variable to * locate the X server. Return 0 if cannot open. */ if (!(dpy = XOpenDisplay(NULL))) G_fatal_error("Graph_Set: can't open Display %s\n", XDisplayName(NULL)); privcmap = getenv("XDRIVER_PRIVATE_CMAP"); if ((p = getenv("XDRIVER_WINDOW")) && sscanf (p, "%i", &win_id) == 1) use_window(win_id); else create_window(argc, argv); /* this next bit forces the use of a private colormap */ /* a must have for read only visuals */ /* since we could allow any type to be selected above assume that */ /* if this is not the default visual we must use a private colormap */ if (use_visual != DefaultVisual(dpy,scrn) || (privcmap && privcmap[0])) fixedcmap = XCreateColormap(dpy, DefaultRootWindow(dpy), use_visual, AllocNone); else fixedcmap = DefaultColormap(dpy, scrn); fixedcmap = init_color_table(fixedcmap); fprintf(stderr,"ncolors: %d\n", NCOLORS); XSetWindowColormap(dpy, grwin, fixedcmap); if (COM_Can_do_float()) { /* Allocate floating colormap */ XColor *xcolors = (XColor *) G_malloc(NCOLORS * sizeof(XColor)); floatcmap = XCreateColormap(dpy, use_screen->root, use_visual, AllocAll); for (i = 0; i < NCOLORS; i++) xcolors[i].pixel = i; XQueryColors(dpy, fixedcmap, xcolors, NCOLORS); XStoreColors(dpy, floatcmap, xcolors, NCOLORS); G_free(xcolors); } /* Create the cursors to be used later */ cur_xh = create_cross_cursor(); cur_clock = XCreateFontCursor(dpy, XC_watch); /* Create the GC. */ gc = XCreateGC(dpy, grwin, 0UL, NULL); /* Find out how big the window really is (in case window manager * overrides our request) and set the SCREEN values. */ screen_left = screen_top = 0; if (!XGetWindowAttributes(dpy, grwin, &xwa)) G_fatal_error("Graph_Set: cannot get window attributes\n"); screen_right = xwa.width; screen_bottom = xwa.height; /* Now create a pixmap that will contain same contents as the * window. It will be used to redraw from after expose events */ bkupmap = XCreatePixmap(dpy, grwin, xwa.width, xwa.height, xwa.depth); XSetWindowBackgroundPixmap(dpy, grwin, bkupmap); XSetForeground(dpy, gc, WhitePixel(dpy, scrn)); XFillRectangle(dpy, bkupmap, gc, 0, 0, xwa.width, xwa.height); XSetBackground(dpy, gc, BlackPixel(dpy, scrn)); XSetForeground(dpy, gc, WhitePixel(dpy, scrn)); XClearWindow(dpy, grwin); /* prepare to catch signals */ signal(SIGHUP, sigint); signal(SIGINT, sigint); signal(SIGQUIT, sigint); signal(SIGILL, sigint); signal(SIGTSTP, SIG_IGN); XFlush(dpy); return 0; }