gfxunix.cc
// Program: initx.c
// Source: Taken from page 8 of X Window Applications Programming
// by Johnson and Reichard
// Purpose: Inistialization code to talk to the X Server
#include
#include
#include
#include
#include
#include
#include
#include "gfx.hh"
//
// Private prototypes
//
Window openWindow (int, int, int, int, int);
void closeWindow (Window);
int createGC (Window, GC *);
void setColor (char *, int);
XFontStruct *initFont (char *);
//
// Private Globals.
//
Display *theDisplay;
Window theWindow;
GC theGC;
Colormap theColormap;
XFontStruct *theFont;
int theScreen;
int theDepth;
int nFgColor, nBgColor;
static char *colors[16] =
{
"Black", "Blue", "Green", "Cyan", "Red", "Magenta", "Brown", "White",
"DarkSlateGrey", "LightBlue", "LimeGreen", "LightBlue", "OrangeRed",
"Magenta", "Yellow", "White"
};
// temporary variables used in GfxMoveTo and GfxLineTo
INT16 _startx, _starty;
//#include "pal_unix.cc"
//
// BOOL GfxInit( void )
// - sets up the connection to the X server and stores information about
// the environment
//
BOOL
GfxInit (void)
{
int event_mask = KeyPressMask | ButtonReleaseMask;
// Establish connection to the X Server
theDisplay = XOpenDisplay (NULL);
// Check the connection
if (theDisplay == NULL)
{
cerr << "GfxInit: Cannot Establish a connection to the X Server\n";
return FALSE;
}
// check for the default screen and color plane depth
theScreen = DefaultScreen (theDisplay);
theDepth = DefaultDepth (theDisplay, theScreen);
theColormap = DefaultColormap (theDisplay, theScreen);
theWindow = openWindow (10, 10, 640, 480, 0);
setColor (colors[_DarkGrey], 2);
if (theWindow == 0)
{
cerr << "GfxInit: Cannot open the window\n";
return FALSE;
}
// Initalise what events we want the window to receive
XSelectInput (theDisplay, theWindow, event_mask);
if ((theFont = initFont ("6x13")) == NULL)
{
cerr << "GfxInit: Cannot open the font\n";
GfxClose ();
return FALSE;
}
XSetFont (theDisplay, theGC, theFont->fid);
XFlush (theDisplay);
return TRUE;
}
//
// void GfxClose( void )
// - close the connection to the X server
//
void
GfxClose (void)
{
closeWindow (theWindow);
XFreeFont (theDisplay, theFont);
XCloseDisplay (theDisplay);
}
//
// GfxFill
// - not yet implemented under X
//
void
GfxFill (INT16 x, INT16 y, UINT16 nBound, UINT16 nColor)
{
return;
}
//
// GfxPattern
// - not yet implemented under X
//
void
GfxPattern (UINT16 nStyle)
{
return;
}
//
// void GfxMoveTo( int, int )
//
void
GfxMoveTo (INT16 x, INT16 y)
{
_startx = x;
_starty = y;
}
//
// void GfxLineTo( INT16, INT16 )
//
void
GfxLineTo ( INT16 x, INT16 y)
{
XDrawLine (theDisplay, theWindow, theGC, _startx, _starty, x, y);
// XFlush( theDisplay );
// make sure the next LineTo starts where this one finished
_startx = x;
_starty = y;
}
//
// void GfxTextColor( int )
// - set foreground (??text only??) color
void
GfxTextColor (UINT16 nColor)
{
nFgColor = nColor;
setColor (colors[nFgColor], 0);
}
//
// void GfxTextColorBg( int )
// - set background (??text only??) color
void
GfxTextColorBg (UINT16 nColor)
{
nBgColor = nColor;
setColor (colors[nBgColor], 1);
}
//
// void GfxText( int x, int y, char *st, int nStyle )
// - draw the passed text string at the passed location in the passed style
// - x, y is the top/left of the text extent
// - PROBLEM with X11, y marks the text base line, SOLN, subtract the
// ascent (height above the base line) from y
// - for now nStyle is ignored
//
void
GfxText (INT16 x, INT16 y, char *st, UINT16 nStyle)
{
setColor (colors[nFgColor], 0);
if (nStyle == GFX_Replace)
{
XDrawImageString (theDisplay, theWindow, theGC, x, y + theFont->ascent,
st, strlen (st));
}
else
{
XDrawString (theDisplay, theWindow, theGC, x, y + theFont->ascent,
st, strlen (st));
}
// XFlush( theDisplay );
}
//
// int GfxTextExtent( char * )
// - return the number of pixels the string argument will occupy
//
UINT16
GfxTextExtent (char *str)
{
return XTextWidth (theFont, str, strlen (str));
}
//
// int GfxTextHeight( void )
// - return the height in pixels of a text character cell
//
UINT16
GfxTextHeight (void)
{
return (theFont->ascent + theFont->descent);
}
//
// PIMBUF GfxGetImage( int x1, int y1, int x2, int y2 )
// - store the bounded screen image bit map in the passed buffer
// - for X must translate a width, height
//
PIMBUF
GfxGetImage (INT16 x1, INT16 y1, INT16 x2, INT16 y2 )
{
PIMBUF p;
p = (pixmap_data *) malloc (sizeof (pixmap_data));
if (p == NULL)
{
cerr << "GfxGetImage: couldn't create pixmap_data\n";
return NULL;
}
p->width = x2 - x1;
p->height = y2 - y1;
p->pix = XCreatePixmap (theDisplay, theWindow, p->width, p->height,
theDepth);
// XFlush( theDisplay );
XCopyArea (theDisplay, theWindow, p->pix, theGC, x1, y1, p->width, p->height,
0, 0);
// XFlush( theDisplay );
return p;
}
//
// BOOL GfxPutImage( int x, int y, PIMBUF p )
// - place image at x, y
//
BOOL
GfxPutImage (INT16 x, INT16 y, PIMBUF p)
{
XCopyArea (theDisplay, p->pix, theWindow, theGC,
0, 0, p->width, p->height,
x, y);
// XFlush( theDisplay );
return TRUE;
}
//
// GfxFreeImage( PIMBUF )
// - free up memory used by image
//
void
GfxFreeImage (PIMBUF p)
{
XFreePixmap (theDisplay, p->pix);
delete p;
// XFlush( theDisplay );
}
//
// void GfxSetClip( int x1, int y1, int x2, int y2 )
// - set the clipping area for graphics
//
void
GfxSetClip (INT16 x1, INT16 y1, INT16 x2, INT16 y2)
{
XRectangle clipRects[1];
clipRects[0].x = x1;
clipRects[0].y = y1;
clipRects[0].width = x2 - x1;
clipRects[0].height = y2 - y1;
XSetClipRectangles (theDisplay, theGC, 0, 0, clipRects, 1, Unsorted);
// XFlush( theDisplay );
}
//
// void GfxClrClip( void )
// - return clip to entire region
//
void
GfxClrClip (void)
{
XSetClipMask (theDisplay, theGC, None);
// XFlush( theDisplay );
}
//
// void GfxRect
// - draw a rectangle
//
void
GfxRect (INT16 x1, INT16 y1, INT16 x2, INT16 y2, UINT16 nStyle, UINT16 nColor)
{
setColor (colors[nColor], 0);
switch (nStyle)
{
case GFX_Fill:
XFillRectangle (theDisplay, theWindow, theGC,
x1, y1, x2 - x1, y2 - y1);
break;
case GFX_Frame:
XDrawRectangle (theDisplay, theWindow, theGC,
x1, y1, x2 - x1, y2 - y1);
}
// XFlush( theDisplay );
setColor (colors[nFgColor], 0);
}
//
// void GfxCircle
// - draw a circle either filled or framed
// - X(Draw)(Fill)Arc draws an arc within a rectangle
// modify input x, y, nRad to get upper left corner and width
//
void
GfxCircle (INT16 x, INT16 y, INT16 nRad, UINT16 nStyle, UINT16 nColor)
{
int lx, ly, nWidth;
lx = x - nRad;
ly = y - nRad;
nWidth = 2 * nRad;
setColor (colors[nColor], 0);
if (nStyle == GFX_Fill)
{
XFillArc (theDisplay, theWindow, theGC, lx, ly, nWidth, nWidth,
0, 360 * 64);
}
else
{
XDrawArc (theDisplay, theWindow, theGC, lx, ly, nWidth, nWidth,
0, 360 * 64);
}
// XFlush( theDisplay );
setColor (colors[nFgColor], 0);
}
//
// void GfxArc
// - draw an arc centred on x,y with radius nRad, beginning at dStart
// degress (0 is straight up), ending at dEnd degrees
//
void
GfxArc (INT16 x, INT16 y, INT16 nRad, double dStart, double dEnd, UINT16 nColor)
{
// XDrawArc starts at 3 o'clock angles are specified in units of
// degrees * 64, see GfxCircle, note 360*64 (and are integers),
// x, y again specify bounding box (see GfxCircle)
int lx, ly, nWidth, nStart, nEnd;
lx = x - nRad;
ly = y - nRad;
nWidth = nRad * 2;
nStart = (int) rint ((dStart) * 64) + 90;
nEnd = (((int) rint ((dEnd))) + 90) * 64;
// cout << "start at " << nStart << " finish at " << nEnd << '\n';
setColor (colors[nColor], 0);
XDrawArc (theDisplay, theWindow, theGC, lx, ly, nWidth, nWidth,
nStart, nEnd);
setColor (colors[nFgColor], 0);
}
//**************************************************************************
// X Windows specific functions
//
// Widow openWindow( int x, int y, int width, int height, int flag )
// - open a window a x,y with width,height
// - if flag > 0 then window is a pop-up
//
Window
openWindow (int x, int y, int width, int height, int flag)
{
XSetWindowAttributes theWindowAttributes;
XSizeHints theSizeHints;
unsigned long theWindowMask;
Window theNewWindow;
// set up some of the window attributes
theWindowAttributes.border_pixel = WhitePixel (theDisplay, theScreen);
theWindowAttributes.background_pixel = BlackPixel (theDisplay, theScreen);
theWindowAttributes.override_redirect = False;
nBgColor = BlackPixel (theDisplay, theScreen);
nFgColor = WhitePixel (theDisplay, theScreen);
theWindowMask = CWBackPixel | CWBorderPixel | CWOverrideRedirect;
// open the window
theNewWindow = XCreateWindow (theDisplay, RootWindow (theDisplay, theScreen),
x, y, width, height, 2, theDepth,
InputOutput, CopyFromParent, theWindowMask,
&theWindowAttributes);
// tell window manager about the size and location of the window
theSizeHints.flags = PPosition | PSize;
theSizeHints.x = x;
theSizeHints.y = y;
theSizeHints.width = width;
theSizeHints.height = height;
XSetNormalHints (theDisplay, theNewWindow, &theSizeHints);
// Create a graphics context
if (createGC (theNewWindow, &theGC) == 0)
{
XDestroyWindow (theDisplay, theNewWindow);
return ((Window) 0);
}
// place the window onto the screen
XMapWindow (theDisplay, theNewWindow);
// Flush out all the queued up X requests
XFlush (theDisplay);
return theNewWindow;
}
// void closeWindow( Window toClose )
// - close the passed in window
//
void
closeWindow (Window toClose)
{
XDestroyWindow (theDisplay, toClose);
}
//
// int createGC( Window, GC *)
// - create the graphics context for the given window
//
int
createGC (Window theNewWindow, GC * theNewGC)
{
XGCValues theGCValues;
*theNewGC = XCreateGC (theDisplay, theNewWindow, (unsigned long) 0,
&theGCValues);
if (*theNewGC == 0)
{
cerr << "createGC: unable to create a GC\n";
return 0;
}
else
{
XSetForeground (theDisplay, *theNewGC, BlackPixel (theDisplay, theScreen));
XSetBackground (theDisplay, *theNewGC, WhitePixel (theDisplay, theScreen));
return 1;
}
}
//
// void setColor( char *, int )
// - accept a name describing the color and set color to it
// - if which = 0 then set foreground
// - if which = 1 then set background
// - if which = 2 then set window background
//
void
setColor (char *theName, int which)
{
XColor theRGBColor, theHardwareColor;
int theStatus;
if (theDepth > 1)
{
theStatus = XLookupColor (theDisplay, theColormap, theName,
&theRGBColor, &theHardwareColor);
if (theStatus != 0)
{
theStatus = XAllocColor (theDisplay, theColormap, &theHardwareColor);
if (theStatus != 0)
{
if (which == 0)
XSetForeground (theDisplay, theGC, theHardwareColor.pixel);
else if (which == 1)
XSetBackground (theDisplay, theGC, theHardwareColor.pixel);
else if (which == 2)
{
XSetWindowBackground (theDisplay, theWindow, theHardwareColor.pixel);
XClearWindow (theDisplay, theWindow);
}
// XFlush( theDisplay );
}
}
}
}
//
// XFontStruct *initFont( GC, char *)
// - initialize a font for use
// - return NULL on an error
//
XFontStruct *
initFont (char *fontName)
{
XFontStruct *fontStruct;
fontStruct = XLoadQueryFont (theDisplay, fontName);
if (fontStruct != 0)
{
XSetFont (theDisplay, theGC, fontStruct->fid);
}
else
{
return (NULL);
}
return fontStruct;
}