// xgrp.c MR Nov 100 // // Auxiliary functions for X-Windows graphics. // // Uses only a few simple EXISTING primary colors, doesn't // allocate/initialize/use a new, newly allocated, color-map. #include "xgrp.h" // -------------------------------------------------------------------------- // graphics stuff, part 1: COLORS // -------------------------------------------------------------------------- #define IABS( a ) ( (a) >= 0 ? (a) : -(a) ) unsigned long get_colorpixel( Display * pD, int targ_r, int targ_g, int targ_b ) // Get the pixel value to use to produce the color nearest // the specified RGB value. We use the ''default color map'' // of the Display pD in unchanged form. // Values of targ_r/g/b lie inside [ 0, 65535 ]. // E.g.: max intensity white = (65535/65535/65535). { XColor clr; int m = 65535 + 65535 + 65535; unsigned long mycolor = 0; unsigned long i; unsigned long imax = 1L; int depth = DefaultDepth( pD, DefaultScreen(pD) ); imax <<= depth; //DEBUG printf( "getcolor : depth=%d\n", depth ); //DEBUG printf( "getcolor : imax=%lu\n", imax ); for ( i = 0; i < imax; i++ ) { int newm; clr.pixel = i; XQueryColor( pD, DefaultColormap( pD, DefaultScreen(pD) ), &clr ); newm = IABS( targ_r - (int)(clr.red) ) + IABS( targ_g - (int)(clr.green) ) + IABS( targ_b - (int)(clr.blue) ); if ( newm < m ) { mycolor = i; m = newm; } } //DEBUG printf( "getcolor : i_final=%d\n", mycolor ); return mycolor; } // Global color pixel-values array: // (global to ALL files in the program) long GLOB_colorpixel[MAXCOLOR]; void initcolors( Display * pD ) // This function initializes the global array GLOB_colorpixel { int i; unsigned long grey = get_colorpixel( pD, 30000, 30000, 30000 ); for ( i = 0; i < MAXCOLOR; i++ ) { GLOB_colorpixel[i] = grey; } GLOB_colorpixel[CLR_BLACK] = get_colorpixel( pD, 0, 0, 0 ); GLOB_colorpixel[CLR_WHITE] = get_colorpixel( pD, 65535, 65535, 65535 ); GLOB_colorpixel[CLR_LGREY] = get_colorpixel( pD, 50000, 50000, 50000 ); GLOB_colorpixel[CLR_DGREY] = get_colorpixel( pD, 20000, 20000, 20000 ); GLOB_colorpixel[CLR_GREY] = grey; GLOB_colorpixel[CLR_RED ] = get_colorpixel( pD, 65535, 0, 0 ); GLOB_colorpixel[CLR_ORANGE] = get_colorpixel( pD, 65535, 40000, 0 ); GLOB_colorpixel[CLR_YELLOW] = get_colorpixel( pD, 65535, 65535, 0 ); GLOB_colorpixel[CLR_YELGR ] = get_colorpixel( pD, 40000, 65535, 0 ); GLOB_colorpixel[CLR_GREEN ] = get_colorpixel( pD, 0, 65535, 0 ); //GLOB_colorpixel[CLR_CYAN ] = get_colorpixel( pD, 0, 40000, 40000 ); GLOB_colorpixel[CLR_CYAN ] = get_colorpixel( pD, 0, 30000, 65535 ); GLOB_colorpixel[CLR_BLUE ] = get_colorpixel( pD, 0, 0, 65535 ); GLOB_colorpixel[CLR_PURPLE] = get_colorpixel( pD, 40000, 0, 65535 ); } // -------------------------------------------------------------------------- // graphics stuff part 2: drawing lines etc. on the screen // -------------------------------------------------------------------------- // // Funcs & structs for use inside 'drawMyPicture()' : // void grp_makenew( grp_t * pgrp, Display * pD, Drawable d ) //Fill *pgrp struct with values for Display 'pD', Drawable 'd' // and with a newly allocated and initialized ''GC'' with suitable // default settings. //Set origin to (0,0) default, and set scale to 1.0 default. { XGCValues xgcvals; pgrp->pD = pD; pgrp->d = d; //grp.w = bb; //grp.w = w; // Initialize ''gc'' with our ''default'' settings xgcvals.function = GXcopy; //GXset; //GXxor; xgcvals.plane_mask = GLOB_colorpixel[ CLR_WHITE ]; //This 'plane_mask' determines the color xgcvals.foreground = 0xffffffffL; xgcvals.background = 0xffffffffL; xgcvals.line_width = 1; xgcvals.line_style = LineSolid; pgrp->gc = XCreateGC( pD, d, //Drawable GCFunction | GCPlaneMask | GCLineWidth | GCForeground | GCBackground | GCLineStyle /*| GCClipMask | GCGraphicsExposures */, &xgcvals ); } void grp_delete( grp_t * pgrp ) { XFreeGC( pgrp->pD, pgrp->gc ); } void grp_setoperation( grp_t * pgrp, int function ) // One of the GX... defines (e.g. XGset, XGclear) { XGCValues xgcvals; xgcvals.function = function; XChangeGC( pgrp->pD, pgrp->gc, GCFunction, &xgcvals ); } void grp_setcolor( grp_t * pgrp, long pm_color ) //One of the PM_... defines { XGCValues xgcvals; xgcvals.plane_mask = pm_color; //This determines the color XChangeGC( pgrp->pD, pgrp->gc, GCPlaneMask, &xgcvals ); } void grp_setlinewidth( grp_t * pgrp, int linewidth ) { XGCValues xgcvals; xgcvals.line_width = linewidth; XChangeGC( pgrp->pD, pgrp->gc, GCLineWidth, &xgcvals ); } #if 0 void grp_clearscreen( grp_t * pgrp ) { XClearWindow( pgrp->pD, pgrp->w ); } #endif void grp_drawline( grp_t * pgrp, int x0, int y0, int x1, int y1 ) { XDrawLine( pgrp->pD, pgrp->d, pgrp->gc, x0, y0, x1, y1 ); } void grp_paintline( grp_t * pgrp, int x0, int y0, int x1, int y1, long color ) // First clear, then draw { grp_setoperation( pgrp, GXclear ); grp_setcolor( pgrp, 0xffffffff ); XDrawLine( pgrp->pD, pgrp->d, pgrp->gc, x0, y0, x1, y1 ); grp_setoperation( pgrp, GXset ); grp_setcolor( pgrp, color ); XDrawLine( pgrp->pD, pgrp->d, pgrp->gc, x0, y0, x1, y1 ); } void grp_drawcircle( grp_t * pgrp, int x, int y, int radius ) { XDrawArc( pgrp->pD, pgrp->d, pgrp->gc, x - radius, y - radius, 2 * radius, 2 * radius, 0, 64*360 ); } void grp_fillcircle( grp_t * pgrp, int x, int y, int radius ) { XFillArc( pgrp->pD, pgrp->d, pgrp->gc, x - radius, y - radius, 2 * radius, 2 * radius, 0, 64*360 ); } void grp_paintcircle( grp_t * pgrp, int x, int y, int radius, long color ) // First clear, then fill { grp_setoperation( pgrp, GXclear ); grp_setcolor( pgrp, 0xffffffff ); grp_fillcircle( pgrp, x, y, radius ); grp_setoperation( pgrp, GXset ); grp_setcolor( pgrp, color ); grp_fillcircle( pgrp, x, y, radius ); } void grp_fillrect( grp_t * pgrp, int x, int y, int width, int height ) { XFillRectangle( pgrp->pD, pgrp->d, pgrp->gc, x, y, width, height ); } void grp_paintrect( grp_t * pgrp, int x, int y, int width, int height, long color ) // First clear, then fill { grp_setoperation( pgrp, GXclear ); grp_setcolor( pgrp, 0xffffffff ); grp_fillrect( pgrp, x, y, width, height ); grp_setoperation( pgrp, GXset ); grp_setcolor( pgrp, color ); grp_fillrect( pgrp, x, y, width, height ); } void grp_paintbox( grp_t * pgrp, int x, int y, int radius, long color ) //Draw an outlined (not filled) box { int x0 = x-radius; int x1 = x+radius; int y0 = y-radius; int y1 = y+radius; grp_paintline( pgrp, x0, y0, x1, y0, color ); grp_paintline( pgrp, x1, y0, x1, y1, color ); grp_paintline( pgrp, x1, y1, x0, y1, color ); grp_paintline( pgrp, x0, y1, x0, y0, color ); } // -------------------------------------------------------------------------- // graphics stuff part 3: Ascii bitmap font data // -------------------------------------------------------------------------- // ''Global'' with FILE scope static const char GLOB_font5x9[96*9] = { // // 0x20 ... 3f (interpunction and numbers) // /*0x20*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x21*/ 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x20, 0x00, 0x00, /*0x22*/ 0xd8, 0xd8, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x23*/ 0x50, 0x50, 0xf8, 0x50, 0xf8, 0x50, 0x50, 0x00, 0x00, /*0x24*/ 0x20, 0x78, 0xa0, 0x70, 0x28, 0xf0, 0x20, 0x00, 0x00, /*0x25*/ 0xc8, 0xd0, 0x10, 0x20, 0x40, 0x58, 0x98, 0x00, 0x00, /*0x26*/ 0x60, 0x90, 0x60, 0x40, 0xa8, 0x90, 0x68, 0x00, 0x00, /*0x27*/ 0x30, 0x18, 0x30, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x28*/ 0x10, 0x20, 0x40, 0x40, 0x40, 0x20, 0x10, 0x00, 0x00, /*0x29*/ 0x40, 0x20, 0x10, 0x10, 0x10, 0x20, 0x40, 0x00, 0x00, /*0x2a*/ 0x00, 0x20, 0xa8, 0x70, 0xa8, 0x20, 0x00, 0x00, 0x00, /*0x2b*/ 0x00, 0x20, 0x20, 0xf8, 0x20, 0x20, 0x00, 0x00, 0x00, /*0x2c*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18, 0x30, 0x40, /*0x2d*/ 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x2e*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x70, 0x20, 0x00, /*0x2f*/ 0x08, 0x10, 0x10, 0x20, 0x40, 0x40, 0x80, 0x00, 0x00, /*0x30*/ 0x70, 0x88, 0x88, 0xa8, 0x88, 0x88, 0x70, 0x00, 0x00, /*0x31*/ 0x20, 0x60, 0x20, 0x20, 0x20, 0x20, 0x70, 0x00, 0x00, /*0x32*/ 0x70, 0x88, 0x08, 0x10, 0x20, 0x40, 0xf8, 0x00, 0x00, /*0x33*/ 0xf0, 0x08, 0x08, 0x70, 0x08, 0x08, 0xf0, 0x00, 0x00, /*0x34*/ 0x10, 0x30, 0x50, 0x90, 0xf8, 0x10, 0x10, 0x00, 0x00, /*0x35*/ 0xf8, 0x80, 0x80, 0xf0, 0x08, 0x08, 0xf0, 0x00, 0x00, /*0x36*/ 0x30, 0x40, 0x80, 0xf0, 0x88, 0x88, 0x70, 0x00, 0x00, /*0x37*/ 0xf8, 0x08, 0x10, 0x20, 0x20, 0x40, 0x40, 0x00, 0x00, /*0x38*/ 0x70, 0x88, 0x88, 0x70, 0x88, 0x88, 0x70, 0x00, 0x00, /*0x39*/ 0x70, 0x88, 0x88, 0x78, 0x08, 0x10, 0x60, 0x00, 0x00, /*0x3a*/ 0x20, 0x70, 0x20, 0x00, 0x00, 0x20, 0x70, 0x20, 0x00, /*0x3b*/ 0x20, 0x70, 0x20, 0x00, 0x00, 0x30, 0x18, 0x30, 0x40, /*0x3c*/ 0x00, 0x10, 0x20, 0x40, 0x20, 0x10, 0x00, 0x00, 0x00, /*0x3d*/ 0x00, 0x00, 0xf8, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, /*0x3e*/ 0x00, 0x40, 0x20, 0x10, 0x20, 0x40, 0x00, 0x00, 0x00, /*0x3f*/ 0x70, 0x88, 0x10, 0x20, 0x20, 0x00, 0x20, 0x00, 0x00, // // 0x40 ... 0x5f (capitals) // /*0x41*/ 0x70, 0x88, 0xb8, 0xa8, 0xb8, 0x80, 0x78, 0x00, 0x00, /*0x41*/ 0x20, 0x50, 0x88, 0x88, 0xf8, 0x88, 0x88, 0x00, 0x00, /*0x42*/ 0xf0, 0x88, 0x88, 0xf0, 0x88, 0x88, 0xf0, 0x00, 0x00, /*0x43*/ 0x70, 0x88, 0x80, 0x80, 0x80, 0x88, 0x70, 0x00, 0x00, /*0x44*/ 0xf0, 0x88, 0x88, 0x88, 0x88, 0x88, 0xf0, 0x00, 0x00, /*0x45*/ 0xf8, 0x80, 0x80, 0xf0, 0x80, 0x80, 0xf8, 0x00, 0x00, /*0x46*/ 0xf8, 0x80, 0x80, 0xf0, 0x80, 0x80, 0x80, 0x00, 0x00, /*0x47*/ 0x70, 0x88, 0x80, 0x98, 0x88, 0x88, 0x78, 0x00, 0x00, /*0x48*/ 0x88, 0x88, 0x88, 0xf8, 0x88, 0x88, 0x88, 0x00, 0x00, /*0x49*/ 0x70, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x00, 0x00, /*0x4a*/ 0x38, 0x10, 0x10, 0x10, 0x10, 0x90, 0x60, 0x00, 0x00, /*0x4b*/ 0x88, 0x90, 0xa0, 0xc0, 0xa0, 0x90, 0x88, 0x00, 0x00, /*0x4c*/ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xf8, 0x00, 0x00, /*0x4d*/ 0x88, 0xd8, 0xe8, 0xa8, 0xa8, 0x88, 0x88, 0x00, 0x00, /*0x4e*/ 0x88, 0xc8, 0xa8, 0xa8, 0x98, 0x88, 0x88, 0x00, 0x00, /*0x4f*/ 0x70, 0x98, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00, /*0x50*/ 0xf0, 0x88, 0x88, 0xf0, 0x80, 0x80, 0x80, 0x00, 0x00, /*0x51*/ 0x70, 0x88, 0x88, 0x88, 0xa8, 0xa8, 0x70, 0x08, 0x00, /*0x52*/ 0xf0, 0x88, 0x88, 0xf0, 0xa0, 0x90, 0x88, 0x00, 0x00, /*0x53*/ 0x70, 0x88, 0x80, 0x70, 0x08, 0x88, 0x70, 0x00, 0x00, /*0x54*/ 0xf8, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, /*0x55*/ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00, /*0x56*/ 0x88, 0x88, 0x88, 0x88, 0x50, 0x50, 0x20, 0x00, 0x00, /*0x57*/ 0x88, 0x88, 0xa8, 0xa8, 0xa8, 0x50, 0x50, 0x00, 0x00, /*0x58*/ 0x88, 0x88, 0x50, 0x20, 0x50, 0x88, 0x88, 0x00, 0x00, /*0x59*/ 0x88, 0x88, 0x88, 0x50, 0x20, 0x20, 0x20, 0x00, 0x00, /*0x5a*/ 0xf8, 0x08, 0x10, 0x20, 0x40, 0x80, 0xf8, 0x00, 0x00, /*0x5b*/ 0x70, 0x40, 0x40, 0x40, 0x40, 0x40, 0x70, 0x00, 0x00, /*0x5c*/ 0x80, 0x40, 0x40, 0x20, 0x10, 0x10, 0x08, 0x00, 0x00, /*0x5d*/ 0x70, 0x10, 0x10, 0x10, 0x10, 0x10, 0x70, 0x00, 0x00, /*0x5e*/ 0x20, 0x50, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x5f*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, // // 0x60 ... 0x7f (small letters) // /*0x60*/ 0x30, 0x60, 0x30, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x61*/ 0x00, 0x00, 0x70, 0x08, 0x78, 0x88, 0x78, 0x00, 0x00, /*0x62*/ 0x80, 0x80, 0xf0, 0x88, 0x88, 0x88, 0xf0, 0x00, 0x00, /*0x63*/ 0x00, 0x00, 0x78, 0x80, 0x80, 0x80, 0x78, 0x00, 0x00, /*0x64*/ 0x08, 0x08, 0x78, 0x88, 0x88, 0x88, 0x78, 0x00, 0x00, /*0x65*/ 0x00, 0x00, 0x70, 0x88, 0xf8, 0x80, 0x70, 0x00, 0x00, /*0x66*/ 0x38, 0x40, 0x40, 0xf0, 0x40, 0x40, 0x40, 0x00, 0x00, /*0x67*/ 0x00, 0x00, 0x78, 0x88, 0x70, 0x08, 0x78, 0x88, 0xf0, /*0x68*/ 0x80, 0x80, 0xf0, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00, /*0x69*/ 0x20, 0x00, 0x60, 0x20, 0x20, 0x20, 0xf0, 0x00, 0x00, /*0x6a*/ 0x10, 0x00, 0x30, 0x10, 0x10, 0x10, 0x10, 0x90, 0x60, /*0x6b*/ 0x80, 0x80, 0x98, 0xb0, 0xe0, 0x90, 0x88, 0x00, 0x00, /*0x6c*/ 0x30, 0x48, 0x50, 0x60, 0xc0, 0x40, 0x30, 0x00, 0x00, /*0x6d*/ 0x00, 0x00, 0xd0, 0xa8, 0xa8, 0xa8, 0xa8, 0x00, 0x00, /*0x6e*/ 0x00, 0x00, 0xf0, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00, /*0x6f*/ 0x00, 0x00, 0x70, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00, /*0x70*/ 0x00, 0x00, 0xf0, 0x88, 0x88, 0x88, 0xf0, 0x80, 0x80, /*0x71*/ 0x00, 0x00, 0x78, 0x88, 0x88, 0x88, 0x78, 0x08, 0x08, /*0x72*/ 0x00, 0x00, 0xb0, 0xc8, 0x80, 0x80, 0x80, 0x00, 0x00, /*0x73*/ 0x00, 0x00, 0x78, 0x80, 0x70, 0x08, 0xf0, 0x00, 0x00, /*0x74*/ 0x00, 0x40, 0xf8, 0x40, 0x40, 0x40, 0x30, 0x00, 0x00, /*0x76*/ 0x00, 0x00, 0x88, 0x88, 0x88, 0x88, 0x78, 0x00, 0x00, /*0x76*/ 0x00, 0x00, 0x88, 0x88, 0x50, 0x50, 0x20, 0x00, 0x00, /*0x77*/ 0x00, 0x00, 0x88, 0xa8, 0xa8, 0xd0, 0x50, 0x00, 0x00, /*0x78*/ 0x00, 0x00, 0x88, 0x50, 0x20, 0x50, 0x88, 0x00, 0x00, /*0x79*/ 0x00, 0x00, 0x88, 0x88, 0x48, 0x30, 0x20, 0x40, 0x80, /*0x7a*/ 0x00, 0x00, 0xf8, 0x10, 0x20, 0x40, 0xf8, 0x00, 0x00, /*0x7b*/ 0x18, 0x20, 0x20, 0xc0, 0x20, 0x20, 0x18, 0x00, 0x00, /*0x7c*/ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, /*0x7d*/ 0xc0, 0x20, 0x20, 0x18, 0x20, 0x20, 0xc0, 0x00, 0x00, /*0x7e*/ 0x40, 0xa8, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x7f*/ 0xf8, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xf8, };//End of GLOB_font5x9[] // -------------------------------------------------------------------------- // graphics stuff part 4: drawing TEXT on the screen // -------------------------------------------------------------------------- // // Our own fonted-text drawing funcs. // void grp_putpixel( grp_t * pgrp, int x, int y ) { XDrawPoint( pgrp->pD, pgrp->d, pgrp->gc, x, y ); } void grp_putbyteicon( grp_t * pgrp, const char * pdata, // Icon bitmap data. int width, /* # of horizontal pixels (max. 8) used in each font byte*/ int hight, /* # of bytes in array pdata[] */ int x, int y ) { unsigned char m; int ix, iy; for ( iy = 0; iy < hight; iy++ ) { for ( ix = 0, m = 0x80; ix < width; ix++, m >>= 1 ) { if ( m & pdata[iy] ) { grp_putpixel( pgrp, x+ix, y+iy ); } } } } void grp_putchar( grp_t * pgrp, unsigned char c, int x, int y ) //Uses font data in GLOB_font5x9[]. { if ( 0x20 <= c && c < 0x7f ) { grp_putbyteicon( pgrp, GLOB_font5x9 + 9*( c - 0x20 ), 6, 9, x, y ); } } void grp_paintchar( grp_t * pgrp, unsigned char c, int x, int y, long color ) //Uses font data in GLOB_font5x9[]. // First clear, then show character in given color. { grp_setoperation( pgrp, GXclear ); grp_setcolor( pgrp, 0xffffffff ); grp_putchar( pgrp, c, x, y ); grp_setoperation( pgrp, GXset ); grp_setcolor( pgrp, color ); grp_putchar( pgrp, c, x, y ); } // #define CHARWID 7 Defined in 'xgrp.h'. // #define CHARHI 12 #include #include // For 'vsprintf()'. void grp_strvprintf( grp_t * pgrp, int x, int y, long color, const char * pFormat, va_list valist ) // Extra formatting characters: // '$' at begin of line = Center this line horizontally. { char buf[256]; int nText; int i; int xstart = x; nText = vsprintf( buf, pFormat, valist ); assert( nText < sizeof(buf) ); for ( i = 0; i < nText; i++ ) { if ( buf[i] == '$' ) //Center line horizontally { int n = 1; while ( buf[i+n] != '\n' && i+n < nText ) { //if ( buf[i+n] == '\t' ) { n += 8; } //else { n++; } n++; } x = ( pgrp->ourScreenWidth - n*CHARWID ) / 2; } else if ( buf[i] == '\t' ) { x += 8 * CHARWID; } else if ( buf[i] == '\n' ) { y += CHARHI; x = xstart; } else { if ( 0 <= x && x < pgrp->ourScreenWidth && 0 <= y && y < pgrp->ourScreenHeight ) { //grp_putchar( pgrp, buf[i], x, y ); grp_paintchar( pgrp, buf[i], x, y, color ); } x += CHARWID; } if ( y > pgrp->ourScreenHeight ) { break; } } } void grp_strprintf( grp_t * pgrp, int x, int y, long color, const char * pFormat, ... ) // Extra formatting characters: // '$' at begin of line = Center this line horizontally. { va_list valist; va_start( valist, pFormat ); grp_strvprintf( pgrp, x, y, color, pFormat, valist ); va_end( valist ); }