home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
gondwana.ecr.mu.oz.au/pub/
/
Graphics.tar
/
Graphics
/
fermiVogle.tar.Z
/
fermiVogle.tar
/
devel
/
drivers
/
decX11.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-02-07
|
13KB
|
615 lines
/*
* VOGLE driver for X11 under the DEC window manager.
*
* ok so we admit that we don't know heaps about X11, but come
* on guys, this shouldn't be neccessary (wild comment from DEC about
* why our standard X11 driver won't work is welcome.)
*/
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include "vogle.h"
#define LARGEX11R2 "courier12f.snf"
#define SMALLX11R2 "courier10f.snf"
#define LARGEX11R3 "-adobe-courier-medium-r-normal--24-240-75-75-m-150-iso8859-1"
#define SMALLX11R3 "-adobe-courier-medium-r-normal--10-100-75-75-m-60-iso8859-1"
#define MIN(x,y) ((x) < (y) ? (x) : (y))
#define CMAPSIZE 256
#define EV_MASK KeyPressMask|ButtonReleaseMask|ExposureMask|ButtonPressMask
static Window winder;
static Display *display;
static int screen;
static unsigned long carray[CMAPSIZE];
static Colormap colormap;
static Drawable theDrawable;
static GC theGC;
static Pixmap bbuf; /* Back buffer pixmap */
static int back_used; /* Have we backbuffered ? */
static XFontStruct *font_id;
XEvent event;
static int size;
static unsigned long colour;
static unsigned int h, w;
static int DECX11_init(void);
static int DECX11_exit(void);
static void DECX11_draw(int x, int y);
static int DECX11_getkey(void);
static int DECX11_checkkey(void);
static int DECX11_locator(int *wx, int *wy);
static void DECX11_clear(void);
static void DECX11_color(int ind);
static int DECX11_mapcolor(int i, int r, int g, int b);
static int DECX11_font(char *fontfile);
static void DECX11_char(char c);
static void DECX11_string(char s[]);
static void DECX11_fill(int n, int x[], int y[]);
static int DECX11_backbuf(void);
static void DECX11_swapbuf(void);
static void DECX11_frontbuf(void);
static void DECX11_noop(void);
/*
* DECX11_init
*
* initialises X11 display.
*/
static int
DECX11_init(void)
{
int i;
int x, y, prefx, prefy, prefxs, prefys;
unsigned int bw, depth, mask;
Window rootw, childw, topwinder, *kiddies;
char *av[2], name[50];
XSetWindowAttributes theWindowAttributes;
XSizeHints theSizeHints;
unsigned long theWindowMask;
XWMHints theWMHints;
av[0] = "vogle.X11";
av[1] = (char *)NULL;
if ((display = XOpenDisplay((char *)NULL)) == (Display *)NULL) {
fprintf(stderr,"vogle: DECX11_init: can't connect to X server\n");
exit(1);
}
winder = DefaultRootWindow(display);
screen = DefaultScreen(display);
vdevice.depth = DefaultDepth(display, screen);
colormap = DefaultColormap(display, screen);
/*
* Set our standard colors...
*/
if (vdevice.depth == 1) {
/*
* Black and white - anything that's not black is white.
*/
carray[0] = BlackPixel(display, screen);
for (i = 1; i < CMAPSIZE; i++)
carray[i] = WhitePixel(display, screen);
} else {
/*
* Color, try to get our colors close to what's in the
* default colormap.
*/
DECX11_mapcolor(0, 0, 0, 0);
DECX11_mapcolor(1, 255, 0, 0);
DECX11_mapcolor(2, 0, 255, 0);
DECX11_mapcolor(3, 255, 255, 0);
DECX11_mapcolor(4, 0, 0, 255);
DECX11_mapcolor(5, 255, 0, 255);
DECX11_mapcolor(6, 0, 255, 255);
DECX11_mapcolor(7, 255, 255, 255);
}
getprefposandsize(&prefx, &prefy, &prefxs, &prefys);
XQueryPointer(display, winder, &rootw, &childw, &x, &y, &x, &y, &mask);
if (childw == None)
childw = rootw;
/*
* there is something very weird about dec's window manager
* as expressed on a dec station, to get the details for the window
* we are actually in we have to get the root window of the childw
* which gives us the root window of the real window stack, and then
* we use XQueryPointer to find the real child window.
*/
XQueryTree(display, childw, &rootw, &rootw, &kiddies, &i);
topwinder = winder;
winder = kiddies[0];
XQueryPointer(display, winder, &rootw, &childw, &x, &y, &x, &y, &mask);
XGetGeometry(display, childw, &rootw, &x, &y, &w, &h, &bw, &depth);
if (prefx > -1) {
x = prefx;
y = prefy;
}
if (prefxs > -1) {
w = prefxs;
h = prefys;
}
x += bw;
y += bw;
w -= 2 * bw;
h -= 2 * bw;
theWindowAttributes.override_redirect = False;
/*theWindowMask = CWBackPixel|CWBorderPixel|CWOverrideRedirect;*/
theWindowMask = CWOverrideRedirect;
winder = XCreateWindow(display,
topwinder,
x, y,
w, h,
bw,
(int)depth,
InputOutput,
CopyFromParent,
theWindowMask,
&theWindowAttributes
);
theWMHints.initial_state = NormalState;
theWMHints.flags = StateHint;
XSetWMHints(display, winder, &theWMHints);
theSizeHints.flags = PPosition|PSize;
theSizeHints.x = x;
theSizeHints.y = y;
theSizeHints.width = w;
theSizeHints.height = h;
XSetNormalHints(display, winder, &theSizeHints);
sprintf(name, "vogle %d", getpid());
XSetStandardProperties(display,
winder,
name,
name,
None,
av,
1,
&theSizeHints
);
XSelectInput(display, winder, EV_MASK);
theDrawable = (Drawable)winder;
/*
* Let VOGLE know about the window size.
*/
vdevice.sizeX = vdevice.sizeY = MIN(h, w) - 1;
vdevice.sizeSx = w - 1;
vdevice.sizeSy = h - 1;
/*
* Create Graphics Context and Drawable
*/
theGC = XDefaultGC(display, screen);
theDrawable = (Drawable)winder;
DECX11_color(0);
XMapRaised(display, winder);
XFlush(display);
/*
* Wait for Exposure event.
*/
do {
XNextEvent(display, &event);
} while (event.type != Expose);
if (prefx == -1 && prefxs == -1)
XSetInputFocus(display, winder, RevertToParent, CurrentTime);
back_used = 0;
return(1);
}
/*
* DECX11_exit
*
* cleans up before returning the window to normal.
*/
static int
DECX11_exit(void)
{
XFreeGC(display, theGC);
if (back_used)
XFreePixmap(display, bbuf);
XUnmapWindow(display, winder);
XDestroyWindow(display, winder);
return(1);
}
/*
* DECX11_draw
*
* draws a line from the current graphics position to (x, y).
*
* Note: (0, 0) is defined as the top left of the window in X (easy
* to forget).
*/
static void
DECX11_draw(int x, int y)
{
XDrawLine(display,
theDrawable,
theGC,
vdevice.cpVx, vdevice.sizeSy - vdevice.cpVy,
x, vdevice.sizeSy - y
);
XFlush(display);
}
/*
* DECX11_getkey
*
* grab a character from the keyboard - blocks until one is there.
*/
static int
DECX11_getkey(void)
{
char c;
do {
XNextEvent(display, &event);
if (event.type == KeyPress) {
if (XLookupString(&event, &c, 1, NULL, NULL) > 0)
return((int)c);
else
return(0);
}
} while (event.type != KeyPress);
}
/*
* DECX11_checkkey
*
* Check if there has been a keyboard key pressed.
* and return it if there is.
*/
static int
DECX11_checkkey(void)
{
char c;
int i;
if (!XCheckWindowEvent(display, winder, KeyPressMask, &event))
return(0);
if (event.type == KeyPress)
if (XLookupString(&event, &c, 1, NULL, NULL) > 0)
return((int)c);
return(0);
}
/*
* DECX11_locator
*
* return the window location of the cursor, plus which mouse button,
* if any, is been pressed.
*/
static int
DECX11_locator(int *wx, int *wy)
{
Window rootw, childw;
int x, y, mask;
XQueryPointer(display, winder, &rootw, &childw, &x, &y, wx, wy, &mask);
*wy = (int)vdevice.sizeSy - *wy;
return(mask >> 8);
}
/*
* DECX11_clear
*
* Clear the screen (or current buffer )to current colour
*/
static void
DECX11_clear(void)
{
XSetBackground(display, theGC, colour);
XFillRectangle(display,
theDrawable,
theGC,
0,
0,
(unsigned int)vdevice.sizeSx + 1,
(unsigned int)vdevice.sizeSy + 1
);
}
/*
* DECX11_color
*
* set the current drawing color index.
*/
static void
DECX11_color(int ind)
{
colour = carray[ind];
XSetForeground(display, theGC, colour);
}
/*
* DECX11_mapcolor
*
* change index i in the color map to the appropriate r, g, b, value.
*/
static int
DECX11_mapcolor(int i, int r, int g, int b)
{
int stat;
XColor tmp;
if (i >= CMAPSIZE)
return(-1);
/*
* For Black and White.
* If the index is 0 and r,g,b != 0 then we are remapping black.
* If the index != 0 and r,g,b == 0 then we make it black.
*/
if (vdevice.depth == 1) {
if (i == 0 && (r != 0 || g != 0 || b != 0))
carray[i] = WhitePixel(display, screen);
else if (i != 0 && r == 0 && g == 0 && b == 0)
carray[i] = BlackPixel(display, screen);
} else {
tmp.red = (unsigned short)(r / 255.0 * 65535);
tmp.green = (unsigned short)(g / 255.0 * 65535);
tmp.blue = (unsigned short)(b / 255.0 * 65535);
tmp.flags = 0;
tmp.pixel = (unsigned long)i;
if ((stat = XAllocColor(display, colormap, &tmp)) == 0) {
fprintf(stderr, "XAllocColor failed (status = %d)\n", stat);
exit(1);
}
carray[i] = tmp.pixel;
}
XFlush(display);
return(0);
}
/*
* DECX11_font
*
* Set up a hardware font. Return 1 on success 0 otherwise.
*
*/
static int
DECX11_font(char *fontfile)
{
XGCValues xgcvals;
if (font_id != (XFontStruct *)NULL)
XFreeFont(display, font_id);
if (strcmp(fontfile, "small") == 0) {
if ((font_id = XLoadQueryFont(display, SMALLX11R2)) == (XFontStruct *)NULL) { /* X11 R2 */
if ((font_id = XLoadQueryFont(display, SMALLX11R3)) == (XFontStruct *)NULL) /* X11 R3 */
return(0);
else
fontfile = SMALLX11R3;
} else
fontfile = SMALLX11R2;
} else if (strcmp(fontfile, "large") == 0) {
if ((font_id = XLoadQueryFont(display, LARGEX11R2)) == (XFontStruct *)NULL) { /* X11 R2 */
if ((font_id = XLoadQueryFont(display, LARGEX11R3)) == (XFontStruct *)NULL) /* X11 R3 */
return(0);
else
fontfile = LARGEX11R3;
} else
fontfile = LARGEX11R2;
} else if ((font_id = XLoadQueryFont(display, fontfile)) == (XFontStruct *)NULL)
return(0);
vdevice.hheight = font_id->max_bounds.ascent + font_id->max_bounds.descent;
vdevice.hwidth = font_id->max_bounds.width;
xgcvals.font = XLoadFont(display, fontfile);
XChangeGC(display, theGC, GCFont, &xgcvals);
return(1);
}
/*
* DECX11_char
*
* outputs one char - is more complicated for other devices
*/
static void
DECX11_char(char c)
{
char *s = " ";
s[0] = c;
XDrawString(display, theDrawable, theGC, vdevice.cpVx, (int)(vdevice.sizeSy - vdevice.cpVy), s, 1);
XFlush(display);
}
/*
* DECX11_string
*
* Display a string at the current drawing position.
*/
static void
DECX11_string(char s[])
{
XDrawString(display, theDrawable, theGC, vdevice.cpVx, (int)(vdevice.sizeSy - vdevice.cpVy), s, strlen(s));
XSync(display, 0);
}
/*
* DECX11_fill
*
* fill a polygon
*/
static void
DECX11_fill(int n, int x[], int y[])
{
XPoint plist[128];
int i;
if (n > 128)
verror("vogle: more than 128 points in a polygon");
for (i = 0; i < n; i++) {
plist[i].x = x[i];
plist[i].y = vdevice.sizeSy - y[i];
}
XFillPolygon(display, theDrawable, theGC, plist, n, Nonconvex, CoordModeOrigin);
vdevice.cpVx = x[n-1];
vdevice.cpVy = y[n-1];
XFlush(display);
}
#define GC_COPY_MASK ~0
/*
* DECX11_backbuf
*
* Set up double buffering by allocating the back buffer and
* setting drawing into it.
*/
static int
DECX11_backbuf(void)
{
if (!back_used)
bbuf = XCreatePixmap(display,
(Drawable)winder,
(unsigned int)vdevice.sizeSx + 1,
(unsigned int)vdevice.sizeSy + 1,
(unsigned int)vdevice.depth
);
theDrawable = (Drawable)bbuf;
back_used = 1;
return(1);
}
/*
* DECX11_swapbuf
*
* Swap the back and from buffers. (Really, just copy the
* back buffer to the screen).
*/
static void
DECX11_swapbuf(void)
{
XCopyArea(display,
theDrawable,
winder,
theGC,
0, 0,
(unsigned int)vdevice.sizeSx + 1,
(unsigned int)vdevice.sizeSy + 1,
0, 0
);
XSync(display, 0); /* Not XFlush */
}
/*
* DECX11_frontbuf
*
* Make sure we draw to the screen.
*/
static void
DECX11_frontbuf(void)
{
theDrawable = (Drawable)winder;
}
/*
* DECX11_noop
*
* noop for the dec X11 driver.
*/
static void
DECX11_noop(void)
{
}
/*
* the device entry
*/
static DevEntry DECX11dev = {
"decX11",
"large",
"small",
DECX11_backbuf,
DECX11_char,
DECX11_checkkey,
DECX11_clear,
DECX11_color,
DECX11_draw,
DECX11_exit,
DECX11_fill,
DECX11_font,
DECX11_frontbuf,
DECX11_getkey,
DECX11_init,
DECX11_locator,
DECX11_mapcolor,
noop,
DECX11_string,
DECX11_swapbuf,
DECX11_noop
};
/*
* _DECX11_devcpy
*
* copy the decX11 device into vdevice.dev.
*/
void
_DECX11_devcpy(void)
{
vdevice.dev = DECX11dev;
}