/* $Id: xm.c,v 1.2 1993/01/23 05:43:59 mjl Exp $
 * $Log: xm.c,v $
 * Revision 1.2  1993/01/23  05:43:59  mjl
 * Can't remember what was changed here.  The motif driver is currently
 * broken anyway (soon to be remedied).
 *
 * Revision 1.1  1992/11/07  07:59:14  mjl
 * Files for the Plplot Motif device driver.  The menus are still just barely
 * sketched out, and this doesn't currently offer any additional functionality
 * over the Xlib driver (but soon, soon..).
 *
*/

/*	xm.c

	PLPLOT X-windows device driver for OSF/Motif.
*/
static int dummy;
#ifdef MOTIF

#include "plplot.h"

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "dispatch.h"
#include "metadefs.h"
#include "xm.h"
#include "xmIcon.h"

/****************************
  Declare the global widgets. 
  ***************************/

/* Declare general-purpose global variables for Xt argument lists. */

Arg      al[20];	/*  arg list		*/
int      ac;		/*  arg count		*/

/*******************************
  Application-defined resources.
  ******************************/

static XrmOptionDescRec option_list[] =
{
  {  "-session",      "session",      XrmoptionSepArg,  NULL  },
};

typedef struct
{
  char * session;
} ApplicationArgs, *ApplicationArgsPtr;

static ApplicationArgs applicationArgs;

static XtResource resources[] =
{
  {
    "session", "Session", XmRString, sizeof (char *),
    XtOffset (ApplicationArgsPtr, session), XmRImmediate, (XtPointer) NULL,
  },
};

unsigned int	plargc=0;
char 		**plargv;

/* Function prototypes */

static void	WaitForPage	(PLStream *);
static void	HandleXEvents	(PLStream *);

static void	xm_Xinit	(PLStream *);
static void	xmesc_ancol	(PLStream *pls, pleNcol *col);
static void	xmesc_rgb	(PLStream *pls, pleRGB *cols);
static int	AreWeMonochrome (Display *);
static void	color_def 	(PLStream *, int, char *);
static int	alloc_named_color( PLStream *pls, XColor *color, char *name);

/* Event handlers and callbacks */

void	MouseEH ( Widget w, PLStream *pls, XEvent *event );
void	ExposeCB ( Widget w, XtPointer client_data, XtPointer call_data);
void	ResizeCB ( Widget w, XtPointer client_data, XtPointer call_data);

/* top level declarations */

/* Unfortunately this stuff still needs some global variables so it is 
   still not quite multi-stream capable */

Widget		topLevel;
Widget		exitDialog;

/* Stuff to handle reentrancy for multiple streams/devices.
   This is still under development so use caution. Right now there
   is no multiple device capability beyond that of multiple streams. */

#define PL_NDEV_XW 10	/* Max number of X sessions active */
#define PL_NDEVICES 10	/* Max number of devices/stream active */

typedef struct {
    int			advance_page;
    int			monochrome;
    long		init_width;
    long		init_height;
    long		cur_width;
    long		cur_height;
    double		xscale;
    double		yscale;
    double		xscale_dev;
    double		yscale_dev;
    int			ignore_next_expose;
    int			in_main_loop;
    U_LONG		foreground;
    U_LONG		background;

    Widget		topLevel;
    Widget		    mainWindow;
    Widget		       menuBar;
    Widget		       drawingArea;
    Widget		    exitDialog;
    
    XtAppContext	app_context;
    Display		*display;
    Window		window;
    Screen		*screen;
    GC			gc;
    Colormap		colormap;
    XColor		colors[17];
} XwDev;

static XwDev xwdev[PL_NDEV_XW];
static PLDev pldev[PL_NDEV_XW];

static int idev = -1;
static int devtable[PL_NSTREAMS][PL_NDEVICES];

/* Miscellaneous global definitions */

U_CHAR c;
static int swap_background = 0;

#define PIXELS_X	32767		/* Number of virtual pixels in x */
#define PIXELS_Y	32767		/* Number of virtual pixels in y */

static PLFLT lpage_x = 238.0;		/* Page length in x in virtual mm */
static PLFLT lpage_y = 178.0;		/* Page length in y in virtual mm */

/*----------------------------------------------------------------------*\
* xm_init()
*
* Initialize device.
* X-dependent stuff done in xm_Xinit().  You can set the display by
* calling plsfile() with the display name as the (string) argument.
\*----------------------------------------------------------------------*/

void 
xm_init (PLStream *pls)
{
    XwDev *xwd;
    PLDev *pld;
    int id;

    if (++idev == PL_NDEV_XW)
	plexit("Exceeded maximum number of active X sessions.");

    id = idev;
    devtable[pls->ipls][pls->ipld] = id;

    xwd = &(xwdev[id]);
    pld = &(pldev[id]);

    pls->termin = 1;		/* is an interactive terminal */
    pls->color = 1;
    pls->width = 1;
    pls->bytecnt = 0;
    pls->page = 0;
    pls->plbuf_enable++;

    xm_Xinit(pls);		/* All X & Motif initialization */

    pld->xold = UNDEFINED;
    pld->yold = UNDEFINED;
    pld->xmin = 0;
    pld->xmax = PIXELS_X;
    pld->ymin = 0;
    pld->ymax = PIXELS_Y;
    pld->xlen = pld->xmax - pld->xmin;
    pld->ylen = pld->ymax - pld->ymin;

    pld->pxlx = pld->xlen / lpage_x;
    pld->pxly = pld->ylen / lpage_y;

    xwd->xscale_dev = (double) xwd->init_width  / (double) pld->xlen;
    xwd->yscale_dev = (double) xwd->init_height / (double) pld->ylen;

    xwd->xscale = xwd->xscale * xwd->xscale_dev;
    xwd->yscale = xwd->yscale * xwd->yscale_dev;

    setpxl(pld->pxlx, pld->pxly);
    setphy(pld->xmin, pld->xmax, pld->ymin, pld->ymax);
}

/*----------------------------------------------------------------------*\
* xm_line()
*
* Draw a line in the current color from (x1,y1) to (x2,y2).
* Here we do NOT check for pending X events as it slows the plot down
* tremendously.
\*----------------------------------------------------------------------*/

void 
xm_line (PLStream *pls, PLINT x1a, PLINT y1a, PLINT x2a, PLINT y2a)
{
    int x1 = x1a, y1 = y1a, x2 = x2a, y2 = y2a;
    int id = devtable[pls->ipls][pls->ipld];
    XwDev * xwd = &(xwdev[id]);
    PLDev * pld = &(pldev[id]);

    y1 = pld->ylen - y1;
    y2 = pld->ylen - y2;

    x1 = x1 * xwd->xscale;
    x2 = x2 * xwd->xscale;
    y1 = y1 * xwd->yscale;
    y2 = y2 * xwd->yscale;

    XDrawLine( XtDisplay(xwd->topLevel), XtWindow(xwd->drawingArea),
	       xwd->gc, x1, y1, x2, y2 );
}

/*----------------------------------------------------------------------*\
* xm_clear()
*
* Clear page.  User must click left mouse button to continue.
\*----------------------------------------------------------------------*/

void 
xm_clear (PLStream *pls)
{
    int id = devtable[pls->ipls][pls->ipld];
    XwDev * xwd = &(xwdev[id]);

    HandleXEvents(pls);
    WaitForPage(pls);

    XFlush( XtDisplay(xwd->topLevel) );
    xwd->window = XtWindow(xwd->drawingArea);
    if (xwd->window)
      XClearWindow( XtDisplay(xwd->topLevel), xwd->window );
}

/*----------------------------------------------------------------------*\
* xm_page()
*
* Set up for the next page.
\*----------------------------------------------------------------------*/

void 
xm_page (PLStream *pls)
{
    HandleXEvents(pls);
    pls->page++;
}

/*----------------------------------------------------------------------*\
* xm_adv()
*
* Advance to the next page.
\*----------------------------------------------------------------------*/

void 
xm_adv (PLStream *pls)
{
    xm_clear(pls);
    xm_page(pls);
}

/*----------------------------------------------------------------------*\
* xm_tidy()
*
* Close graphics file
\*----------------------------------------------------------------------*/

void 
xm_tidy (PLStream *pls)
{
    xm_clear(pls);
    pls->fileset = 0;
    pls->page = 0;
    pls->plbuf_enable--;
    pls->OutFile = NULL;
    idev--;
}

/*----------------------------------------------------------------------*\
* xm_color()
*
* Set pen color.
\*----------------------------------------------------------------------*/

void 
xm_color (PLStream *pls)
{
    int id = devtable[pls->ipls][pls->ipld];
    XwDev * xwd = &(xwdev[id]);
    XColor curcolor;

    HandleXEvents(pls);

    if (xwd->monochrome) 
	curcolor.pixel = (xwd->colors)[15].pixel;
    else {
	if (pls->color >= 0 && pls->color <= 16)
	    curcolor.pixel = (xwd->colors)[pls->color].pixel;
	else
	    curcolor.pixel = (xwd->colors)[15].pixel;
    }
    XSetForeground( XtDisplay(xwd->topLevel), xwd->gc, curcolor.pixel );
}

/*----------------------------------------------------------------------*\
* xm_text()
*
* Switch to text mode.
\*----------------------------------------------------------------------*/

void 
xm_text (PLStream *pls)
{
    HandleXEvents(pls);
}

/*----------------------------------------------------------------------*\
* xm_graph()
*
* Switch to graphics mode.
\*----------------------------------------------------------------------*/

void 
xm_graph (PLStream *pls)
{
    HandleXEvents(pls);
}

/*----------------------------------------------------------------------*\
* xm_width()
*
* Set pen width.
\*----------------------------------------------------------------------*/

void 
xm_width (PLStream *pls)
{
    HandleXEvents(pls);
}

/*----------------------------------------------------------------------*\
* xm_esc()
*
* Escape function.
\*----------------------------------------------------------------------*/

void 
xm_esc (PLStream *pls, PLINT op, char *ptr)
{
    HandleXEvents(pls);

    switch (op) {
    case PL_SET_RGB:
	xmesc_rgb(pls, (pleRGB *) ptr);
	break;

    case PL_ALLOC_NCOL:
	xmesc_ancol(pls, (pleNcol *) ptr);
	break;
    }
}

/*----------------------------------------------------------------------*\
* X/Motif initialization routine.
\*----------------------------------------------------------------------*/

static void 
xm_Xinit (PLStream *pls)
{
    int id = devtable[pls->ipls][pls->ipld];
    XwDev * xwd = &(xwdev[id]);

    int		fg, bg;
    XGCValues 	xgcv;
    Cursor	xhair_cursor;
    Display	*display;

    Window root;
    int x, y;
    U_INT width, height, border_width, depth, myborder=5;

/*************************************
  Initialize toolkit and open display.
  ************************************/

    topLevel = XtAppInitialize( &xwd->app_context, "Plplot", option_list,
			       1, &plargc, plargv, NULL, al, 0);

    display = XtDisplay( topLevel );

    xwd->topLevel = topLevel;
    xwd->display = display;

/*** Establish the window manager and session manager protocols. ***/

    CreateWindowManagerProtocols( topLevel );
    CreateSessionManagerProtocols( topLevel );

/*** Get application-specific resources. ***/

    XtGetApplicationResources( topLevel, &applicationArgs, resources,
			       1, NULL, 0 );
 
/*** Create the Exit dialog (as a child of the top-level shell). ***/

    exitDialog = CreateExitDialog( topLevel );
    xwd->exitDialog = exitDialog;

/************************
  Create the Main Window.
  ***********************/

/*** Create the Main Window widget. ***/

    ac = 0;
    xwd->mainWindow = XmCreateMainWindow ( topLevel, "mainWindow", al, ac );
    XtManageChild ( xwd->mainWindow );

/* Determine the window size. */

    (void) XGetGeometry( XtDisplay(topLevel),
		         DefaultRootWindow( XtDisplay(topLevel) ),
		         &root, &x, &y, &width, &height,
			 &border_width, &depth );

    if (pls->xlength == 0) pls->xlength = 7 * width / 8;
    if (pls->ylength == 0) pls->ylength = 7 * height / 8;

    if (pls->xlength > width)  pls->xlength = width-myborder*2;
    if (pls->ylength > height) pls->ylength = height-myborder*2;

    if (pls->xoffset == 0) pls->xoffset = width / 20;
    if (pls->yoffset == 0) pls->yoffset = height / 20;

/* Set colors */

    xwd->colormap   = DefaultColormap( display, XDefaultScreen(display) );
    xwd->monochrome = AreWeMonochrome( display );
    if (xwd->monochrome)
	swap_background = 1;

    if (!swap_background) {
	xwd->background	= BlackPixel( display, XDefaultScreen(display) );
	xwd->foreground	= WhitePixel( display, XDefaultScreen(display) );
    }
    else {
	xwd->background	= WhitePixel( display, XDefaultScreen(display) );
	xwd->foreground	= BlackPixel( display, XDefaultScreen(display) );
    }

/* Default color values */

    if (!xwd->monochrome) {
        color_def( pls, 0, "coral" );
        color_def( pls, 1, "red" );
        color_def( pls, 2, "yellow" );
        color_def( pls, 3, "green" );
        color_def( pls, 4, "aquamarine" );
        color_def( pls, 5, "pink" );
        color_def( pls, 6, "wheat" );
        color_def( pls, 7, "grey" );
        color_def( pls, 8, "brown" );
        color_def( pls, 9, "blue" );
        color_def( pls, 10, "BlueViolet" );
        color_def( pls, 11, "cyan" );
        color_def( pls, 12, "turquoise" );
        color_def( pls, 13, "magenta" );
        color_def( pls, 14, "salmon" );
    }

/* Default foreground/background */

    if (!swap_background) {
	color_def( pls, 15, "white" );
	color_def( pls, 16, "black" );
    }
    else {
	color_def( pls, 15, "black" );
	color_def( pls, 16, "white" );
    }

/*** Create the pulldown menu in the main window. ***/

    xwd->menuBar = CreateMenuBar ( xwd->mainWindow );
    XtManageChild ( xwd->menuBar );

/*** Create the drawing area for the main window. ***/

    ac = 0;
    XtSetArg( al[ac], XmNresizePolicy, XmRESIZE_ANY ); 	ac++; 
    XtSetArg( al[ac], XmNbackground, xwd->background );	ac++;
    XtSetArg( al[ac], XmNforeground, xwd->foreground );	ac++;
    xwd->drawingArea = (Widget)
      XmCreateDrawingArea ( xwd->mainWindow, "workArea", al, ac );
    XtManageChild (xwd->drawingArea);

/* Install event handler for button events in drawing area */

    XtAddEventHandler( xwd->drawingArea, ButtonPressMask, False,
		       (XtEventHandler) MouseEH, pls );

/* Install callback for exposure events in drawing area */

    XtAddCallback( xwd->drawingArea, XmNexposeCallback,
		   (XtCallbackProc) ExposeCB, pls );

/* Install callback for window resize events */

    XtAddCallback( xwd->drawingArea, XmNresizeCallback,
		   (XtCallbackProc) ResizeCB, pls );

/* Attach the menu bar and drawing area to the main window. */

    XmMainWindowSetAreas ( xwd->mainWindow, xwd->menuBar,
			   NULL, NULL, NULL, xwd->drawingArea );

/* Set default main window title and icon */

    ac = 0;
    XtSetArg( al[ac], XmNtitle, "Plplot Motif driver"); ac++;
    XtSetArg( al[ac], XmNiconName, "Plplot" );		ac++;
    XtSetArg( al[ac], XmNx, pls->xoffset );		ac++;  
    XtSetArg( al[ac], XmNy, pls->yoffset );		ac++;
    XtSetArg( al[ac], XmNwidth, pls->xlength );		ac++;
    XtSetArg( al[ac], XmNheight, pls->ylength );	ac++;
    XtSetArg( al[ac], XmNallowShellResize, True );	ac++;
    XtSetArg( al[ac], XmNdeleteResponse, XmDO_NOTHING ); ac++;
    XtSetArg( al[ac], XmNiconPixmap, 
	      XCreateBitmapFromData(XtDisplay(topLevel), 
				    RootWindowOfScreen(XtScreen(topLevel)), 
				    Icon_bits, 
				    Icon_width,
				    Icon_height) );  ac++;
    XtSetValues (topLevel, al, ac);

/* Create a cross-hair cursor for the drawing area. */

    xhair_cursor = XCreateFontCursor( XtDisplay(xwd->drawingArea),
				      XC_crosshair );

/* Realize all widgets. */

    XtRealizeWidget(topLevel);

/* Set up things so that the cursor changes to a cross-hair and is confined
   to the xwd->drawingArea while the mouse button is pressed.  This is done
   through what is known as a "grab".
*/

    XGrabButton( XtDisplay(xwd->drawingArea), AnyButton, AnyModifier,
		 XtWindow(xwd->drawingArea), True, ButtonPressMask |
		 ButtonMotionMask | ButtonReleaseMask, GrabModeAsync,
		 GrabModeAsync, XtWindow(xwd->drawingArea), xhair_cursor );

/* Create the GC. */

    xwd->gc = XCreateGC( XtDisplay(xwd->drawingArea),
			 XtWindow(xwd->drawingArea), 0, 0);

/* Get initial drawing area dimensions */

    xwd->init_width = XtWidth(xwd->drawingArea);
    xwd->init_height = XtHeight(xwd->drawingArea);

    xwd->cur_width = xwd->init_width;
    xwd->cur_height = xwd->init_height;

    xwd->xscale = (double) xwd->cur_width / (double) xwd->init_width;
    xwd->yscale = (double) xwd->cur_height / (double) xwd->init_height;

/* Process input */
/* Need to process at least twice -- once for the window and once for the
   menus.  Odd behavior, to be sure. */

    xwd->in_main_loop = TRUE;

    HandleXEvents(pls);
    HandleXEvents(pls);
}

/*----------------------------------------------------------------------*\
* MouseEH()
*
* Event handler routine to handle button presses in drawing area.
* On:
*   Button1: nothing for now
*   Button2: spit out device space coordinates
*   Button3: set page advance flag for later processing
\*----------------------------------------------------------------------*/

void
MouseEH ( Widget w, PLStream *pls, XEvent *event )
{
    int id = devtable[pls->ipls][pls->ipld];
    XwDev * xwd = &(xwdev[id]);

    HandleXEvents(pls);

    switch (event->type)
      {
	case ButtonPress:
	  switch (event->xbutton.button)
	    {
	      case Button1:
		break;

	      case Button2:
		printf("%d\t%d\n", event->xbutton.x, event->xbutton.y);
		break;

	      case Button3:
		xwd->advance_page=TRUE;
		return;
	    }
	  break;
      }
}

/*----------------------------------------------------------------------*\
* ExposeCB()
*
* Event handler routine to exposure of drawing area.
\*----------------------------------------------------------------------*/

void
ExposeCB ( Widget w, XtPointer client_data, XtPointer call_data)
{
    PLStream *pls = client_data;
    XmDrawingAreaCallbackStruct *da = call_data;
    int id = devtable[pls->ipls][pls->ipld];
    XwDev * xwd = &(xwdev[id]);

    if (!xwd->in_main_loop) return;

    if (da->event->xexpose.count == 0) {
	if (!xwd->ignore_next_expose) {
	    XFlush( XtDisplay(xwd->topLevel) );
	    xwd->window = XtWindow(xwd->drawingArea);
	    if (xwd->window) {
		plRemakePlot(pls);
	    }
	}
	else {
	    xwd->ignore_next_expose = FALSE;
	}
    }
}

/*----------------------------------------------------------------------*\
* ResizeCB()
*
* Event handler routine to exposure of drawing area.
*
* Note: a resize to a larger window size also generates an expose event
* (in fact one for each dimension enlarged), resulting in a call to 
* ExposeCB.  Since the window will have already been refreshed by ResizeCB, 
* I set a flag to ignore the expose events.
\*----------------------------------------------------------------------*/

void
ResizeCB ( Widget w, XtPointer client_data, XtPointer call_data)
{
    PLStream *pls = client_data;
    XmDrawingAreaCallbackStruct *da = call_data;
    int id = devtable[pls->ipls][pls->ipld];
    XwDev * xwd = &(xwdev[id]);
    int old_width = xwd->cur_width, old_height = xwd->cur_height;

    if (!xwd->in_main_loop) return;

    xwd->cur_width = XtWidth(xwd->drawingArea);
    xwd->cur_height = XtHeight(xwd->drawingArea);

    xwd->xscale = (double) xwd->cur_width / (double) xwd->init_width;
    xwd->yscale = (double) xwd->cur_height / (double) xwd->init_height;

    xwd->xscale = xwd->xscale * xwd->xscale_dev;
    xwd->yscale = xwd->yscale * xwd->yscale_dev;

    XFlush( XtDisplay(xwd->topLevel) );
    xwd->window = XtWindow(xwd->drawingArea);
    if (xwd->window) {
	XClearWindow( XtDisplay(xwd->topLevel), xwd->window );
	plRemakePlot(pls);
    }

    if (xwd->cur_width > old_width || xwd->cur_height > old_height)
      xwd->ignore_next_expose = TRUE;
}

/*----------------------------------------------------------------------*\
* WaitForPage()
*
* This routine waits for the user to advance the plot, while handling 
* all other events.
\*----------------------------------------------------------------------*/

static void 
WaitForPage(PLStream *pls)
{
    XEvent event;
    int id = devtable[pls->ipls][pls->ipld];
    XwDev * xwd = &(xwdev[id]);

    if (pls->nopause) return;
    while (!xwd->advance_page) {
	XtAppNextEvent(xwd->app_context, &event);
	XtDispatchEvent(&event);
    }
    xwd->advance_page=FALSE;
}

/*----------------------------------------------------------------------*\
* HandleXEvents()
*
* This routine handles all pending events, returning when the queue 
* becomes empty.  Since users may want to select a page advance before the
* page is actually finished, we need to check for this.
\*----------------------------------------------------------------------*/

static void 
HandleXEvents(PLStream *pls)
{
    XEvent event;
    int id = devtable[pls->ipls][pls->ipld];
    XwDev * xwd = &(xwdev[id]);

    if (pls->plbuf_read) return;

    while (XtAppPending(xwd->app_context)) {
	XtAppNextEvent(xwd->app_context, &event);

	switch (event.type)
	  {
	    case ButtonPress:
	      switch (event.xbutton.button)
		{
		  case Button3:
		    xwd->advance_page = TRUE;
		    continue;
		}
	      break;
	  }

	XtDispatchEvent(&event);
    }
}

/*----------------------------------------------------------------------*\
* Escape function: Allocate named color.
\*----------------------------------------------------------------------*/

static void 
xmesc_ancol (PLStream *pls, pleNcol *col)
{
    int id = devtable[pls->ipls][pls->ipld];
    XwDev * xwd = &(xwdev[id]);

    if (xwd->monochrome) {
	if (!strcmp(col->name, "white"))
	    ;
	else if (!strcmp(col->name, "black"))
	    ;
	else
	    return;
    }
    alloc_named_color(pls, xwd->colors+col->icolor, col->name);
}

/*----------------------------------------------------------------------*\
* Escape function: Set rgb color.
\*----------------------------------------------------------------------*/

static void 
xmesc_rgb (PLStream *pls, pleRGB *cols)
{
    XColor color;
    int id = devtable[pls->ipls][pls->ipld];
    XwDev * xwd = &(xwdev[id]);

    if (xwd->monochrome) return;

    color.red   = MIN(65535, MAX(0, (int) (65535. * cols->red)));
    color.green = MIN(65535, MAX(0, (int) (65535. * cols->green)));
    color.blue  = MIN(65535, MAX(0, (int) (65535. * cols->blue)));
    XAllocColor(XtDisplay(xwd->topLevel), xwd->colormap, &color);
    XSetForeground(XtDisplay(xwd->topLevel), xwd->gc, color.pixel);
}

/*----------------------------------------------------------------------*\
* Color allocation routines.
\*----------------------------------------------------------------------*/

static void 
color_def (PLStream *pls, int icolor, char *name)
{
    int id = devtable[pls->ipls][pls->ipld];
    XwDev * xwd = &(xwdev[id]);

    if (alloc_named_color(pls, xwd->colors+icolor, name)) {
	if (icolor == 15 || icolor == 16) {
	    fprintf(stderr, "Can't allocate foreground/background colors\n");
	    exit(1);
	}
    }
}

static int
alloc_named_color( PLStream *pls, XColor *color, char *name)
{
    int id = devtable[pls->ipls][pls->ipld];
    XwDev * xwd = &(xwdev[id]);
    XColor xcolor;

    if (XAllocNamedColor(XtDisplay(xwd->topLevel), xwd->colormap,
			 name, &xcolor, color) == 0)
    {
	fprintf(stderr, "Can't allocate color %s\n", name);
	fprintf(stderr, "Using current foreground color instead\n");
	color = xwd->colors+15;
	return(1);
    }
    return(0);
}

/*----------------------------------------------------------------------*\
* Misc. support routines.
\*----------------------------------------------------------------------*/

/* gmf 11-8-91; Courtesy of Paul Martz of Evans and Sutherland. */

static int AreWeMonochrome ( Display *display )
{
#if defined(__cplusplus) || defined(c_plusplus)
#define THING c_class
#else
#define THING class
#endif

    XVisualInfo *visuals;
    int nitems, i;

    /* get a list of info on the visuals available */
    visuals = XGetVisualInfo (display, 0, NULL, &nitems);

    /* check the list looking for non-monochrome visual classes */
    for (i=0; i<nitems; i++)
        if ((visuals[i].THING != GrayScale) &&
            (visuals[i].THING != StaticGray))
            return (0);

    /* if we got this far, only StaticGray and GrayScale classes available */
    return (1);
}

#endif	/* MOTIF */
