 /*
  * Khoros: $Id: X11.c,v 1.3 1991/12/18 09:08:51 dkhoros Exp $
  */

#if !defined(lint) && !defined(SABER)
static char rcsid[] = "Khoros: $Id: X11.c,v 1.3 1991/12/18 09:08:51 dkhoros Exp $";
#endif

 /*
  * $Log: X11.c,v $
 * Revision 1.3  1991/12/18  09:08:51  dkhoros
 * HellPatch3
 *
  */ 


/*
 *----------------------------------------------------------------------
 *
 * Copyright 1990, University of New Mexico.  All rights reserved.
 * 
 * Permission to copy and modify this software and its documen-
 * tation only for internal use in your organization is hereby
 * granted, provided that this notice is retained thereon and
 * on all copies.  UNM makes no representations as too the sui-
 * tability and operability of this software for any purpose.
 * It is provided "as is" without express or implied warranty.
 * 
 * UNM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
 * NESS.  IN NO EVENT SHALL UNM BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY OTHER DAMAGES WHAT-
 * SOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PER-
 * FORMANCE OF THIS SOFTWARE.
 * 
 * No other rights, including for example, the right to redis-
 * tribute this software and its documentation or the right to
 * prepare derivative works, are granted unless specifically
 * provided in a separate license agreement.
 *----------------------------------------------------------------------
 */

#include "unmcopyright.h"	 /* Copyright 1990 by UNM */
#include "X3D.h"

/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
   >>>>                                                       <<<<
   >>>>	    	    file name: X11.c                          <<<<
   >>>>                                                       <<<<
   >>>>                 X11 Utilities			      <<<<
   >>>>                                                       <<<<
   >>>>			X3D_set_X11()			      <<<<
   >>>>			X11_DrawLine()			      <<<<
   >>>>			X11_DrawLines()			      <<<<
   >>>>			X11_DrawSegments()		      <<<<
   >>>>			X11_DrawRectangle()		      <<<<
   >>>>			X11_DrawArc()			      <<<<
   >>>>			X11_FillPolygon()		      <<<<
   >>>>			X11_close_device()		      <<<<
   >>>>			X11_set_line_width()		      <<<<
   >>>>			X11_set_line_type()		      <<<<
   >>>>			X11_set_draw()			      <<<<
   >>>>			X11_set_fill()			      <<<<
   >>>>			X11_DrawPolygon()		      <<<<
   >>>>			X11_DrawText()			      <<<<
   >>>>			X11_FillArc()			      <<<<
   >>>>			X11_FillRectangle()		      <<<<
   >>>>                                                       <<<<
   >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */


/************************************************************
*
*  MODULE NAME:  X3D_set_X11
*
*      PURPOSE:  This routine sets the display, the window, and
*		 the graphics contexts for future calls to the
*		 xvgraphics library using this id
*
*        INPUT:  id - xvgraphics id
*		 display - the display to which all graphics will go
*		 window  - the window that all graphics will appear in
*		 gc_draw - graphics context for drawing
*		 gc_fill - graphics context for filling
*
*    CALLED BY:  application program
*
*   WRITTEN BY:  Mike Lang & Mark Young
*
*
*************************************************************/

int X3D_set_X11(id, display, window, widget)

int     id;
Display *display;
Window  window;
Widget  widget;
{
	Window		root;
	int		x, y;
        unsigned	int width, height, border_width, depth;
	X3DGraphics     *graphics;

	if (!(graphics = _X3D_get_graphics(id)))
	{
	   fprintf (stderr,"X3D_set_X11:");
	   fprintf (stderr,"\t unknown graphics id %d\n",id);
	   return(FALSE);
	}

	graphics->device    = X11;

	if (widget == NULL)
	{
	   graphics->widget    = NULL;
	   graphics->display   = display;
	   graphics->workspace = window;
	}
	else
	{
	   graphics->widget    = widget;
	   graphics->display   = XtDisplay(widget);
	   graphics->workspace = XtWindow(widget);
	}

	if ( !XGetGeometry(graphics->display, graphics->workspace, &root, &x,
			&y, &width, &height, &border_width, &depth))
        {
           fprintf (stderr,"\nX3D_set_X11: Window does not exist.\n");
           return(FALSE);
        }
	X3D_set_window(id, 0, 0, width, height);
	return(TRUE);
}



/************************************************************
*
*  MODULE NAME:  X11_DrawLine
*
*      PURPOSE: Draw a single line for an X11 device
*
*        INPUT:  graphics - graphics structure
*
*       OUTPUT: displays a line to an X11 workstation
*
*    CALLED BY: graphics routines
*
*   WRITTEN BY: Mike Lang & Mark Young
*
*************************************************************/

void X11_DrawLine (graphics, p1x, p1y, p2x, p2y)

X3DGraphics *graphics;
short   p1x, p1y, p2x, p2y;
{
        XDrawLine(graphics->display, graphics->workspace, graphics->gc_draw,
		  p1x, p1y, p2x, p2y);
}



/************************************************************
*
*  MODULE NAME:  X11_DrawLines
*
*      PURPOSE:  Draw a series of lines for an X11 device
*
*        INPUT:  graphics - graphics structure
*
*       OUTPUT: displays a a set of lines to an X11 workstation
*
*    CALLED BY: graphics routines
*
*   WRITTEN BY: Mike Lang & Mark Young
*
*************************************************************/

void X11_DrawLines (graphics, points, size, coordmode)

X3DGraphics *graphics;
int         coordmode, size;
XPoint      *points;
{
	int		i, num;

	i = 0;
	while (i < size)
	{
	   num = MIN(size - i, 10000);
	   XDrawLines(graphics->display, graphics->workspace, graphics->gc_draw,
		   &points[i], num, coordmode);
	   i += num;
	}
}



/************************************************************
*
*  MODULE NAME:  X11_DrawSegments
*
*      PURPOSE:  Draw a series of disjoint segments for an X11 device
*
*        INPUT:  graphics - graphics structure
*
*       OUTPUT: displays a a set of segments to an X11 workstation
*
*    CALLED BY: graphics routines
*
*   WRITTEN BY: Mike Lang & Mark Young
*
*************************************************************/

void X11_DrawSegments (graphics, segments, seg_num)

X3DGraphics *graphics;
int	 seg_num;
XSegment *segments;
{
	XDrawSegments(graphics->display, graphics->workspace, graphics->gc_draw,
		      segments, seg_num);
}



/************************************************************
*
*  MODULE NAME:  X11_DrawRectangle
*
*      PURPOSE:  Draw a rectangle to an X11 device
*
*        INPUT:  graphics - graphics structure
*
*       OUTPUT: displays a rectangle to an X11 workstation
*
*    CALLED BY: graphics routines
*
*   WRITTEN BY: Mike Lang & Mark Young
*
*************************************************************/

void X11_DrawRectangle (graphics, x, y, w, h)

X3DGraphics *graphics;
int      x, y;
unsigned int w, h;
{
	XDrawRectangle(graphics->display, graphics->workspace,graphics->gc_draw,
		       x, y, w, h);
}



/************************************************************
*
*  MODULE NAME:  X11_DrawArc
*
*      PURPOSE:  Draw an arc (circle) for an X11 device x,y are
*		 the upper left corner of the bounding box of the
*		 circle ang1 & ang2 are the start and finish angles
*		 specified in 64's of a degree
*
*        INPUT:  graphics - graphics structure
*
*    CALLED BY: graphics routines
*
*   WRITTEN BY: Mike Lang & Mark Young
*
*************************************************************/

void X11_DrawArc (graphics, x, y, w, h, ang1, ang2) 

X3DGraphics *graphics;
int      x, y, ang1, ang2;
unsigned int     w, h;
{
	ang1 *= 64;
	ang2 *= 64;
	x = x - ((float) w)/2.0 + 0.5;
	y = y - ((float) h)/2.0 + 0.5;

	XDrawArc(graphics->display, graphics->workspace, graphics->gc_draw,
		 x, y, w, h, ang1, ang2);
}



/************************************************************
*
*  MODULE NAME:  X11_FillPolygon
*
*      PURPOSE: Fill a polygon for an X11 device
*
*        INPUT:  graphics - graphics structure
*
*       OUTPUT: displays a filled polygon to an X11 workstation
*
*    CALLED BY: graphics routines
*
*   WRITTEN BY: Mike Lang & Mark Young
*
*************************************************************/

void X11_FillPolygon (graphics, points, size, shape, coordmode) 

X3DGraphics *graphics;
int     size, shape, coordmode;
XPoint	*points;
{
	XFillPolygon(graphics->display, graphics->workspace, graphics->gc_fill,
		     points, size, shape, coordmode);
}



/************************************************************
*
*  MODULE NAME:  X11_close_device
*
*      PURPOSE:  
*
*        INPUT:  graphics - graphics structure
*
*    CALLED BY:  application program
*
*   WRITTEN BY:  Mike Lang & Mark Young
*
*
*************************************************************/


void X11_close_device(graphics)

X3DGraphics *graphics;
{
	/* just return */
}

/************************************************************
*
*  MODULE NAME:  X11_set_line_width
*
*      PURPOSE: Set the linr width before drawing.
*
*        INPUT:  graphics context
*	         line_width as specified in xvgraphics.h
*
*    CALLED BY:  application program
*
*   WRITTEN BY:  Mike Lang & Tom Sauer
*
*
*************************************************************/


void X11_set_line_width(graphics, line_width)

X3DGraphics  *graphics;
int	     line_width;
{
	graphics->line_width = line_width;
	X11_set_draw(graphics, NULL, FALSE);
}



/************************************************************
*
*  MODULE NAME:  X11_set_line_type
*
*      PURPOSE:  sets the line type before drawing
*
*        INPUT:  graphics context
*	         line_type as specified in xvgraphics.h
*
*    CALLED BY:  application program
*
*   WRITTEN BY:  Tom Sauer
*
*
*************************************************************/


void X11_set_line_type(graphics, line_type)

X3DGraphics *graphics;
int	    line_type;
{
	graphics->line_type = line_type;
	X11_set_draw(graphics, NULL, FALSE);
}



/************************************************************
*
*  MODULE NAME:  X11_set_draw
*
*      PURPOSE:  Set the foreground draw color.
*
*        INPUT:  graphics - graphics context
*	         fg	  - foreground color
*		 override - whether the foreground color can
*			    be overriden.
*
*    CALLED BY:  application program
*
*   WRITTEN BY:  Mark Young
*
*
*************************************************************/

void X11_set_draw(graphics, fg, override)

X3DGraphics     *graphics;
XColor		*fg;
int		override;
{
	XGCValues  _values;
	Pixel	   pixel;


	if (fg == NULL)
	   pixel = graphics->fg;
	else if (fg->pixel == graphics->fg)
	   return;
	else
	   pixel = fg->pixel;

	_values.foreground = pixel;
	_values.line_width =line_widths[graphics->line_width][graphics->device];

	if (graphics->line_type == Solid)
	   _values.line_style = LineSolid;
	else
	   _values.line_style = LineOnOffDash;

	graphics->gc_draw = XtGetGC(graphics->widget, GCForeground |
				GCLineWidth | GCLineStyle, &_values);

	if (graphics->line_type != Solid)
           XSetDashes(graphics->display, graphics->gc_draw, 0,
				dash_type[graphics->line_type],
				dash_len[graphics->line_type]);

	graphics->fg = pixel;
}



/************************************************************
*
*  MODULE NAME:  X11_set_fill
*
*      PURPOSE:  Set the background fill color.
*
*        INPUT:  graphics - graphics context
*	         bg	  - background color
*		 override - whether the background color can
*			    be overriden.
*
*    CALLED BY:  application program
*
*   WRITTEN BY:  Mark Young
*
*
*************************************************************/

void X11_set_fill(graphics, bg, override)

X3DGraphics     *graphics;
XColor		*bg;
int		override;
{
	XGCValues  _values;


	if (graphics->bg != bg->pixel)
	{
	   _values.foreground = bg->pixel;
	   graphics->gc_fill = XtGetGC(graphics->widget, GCForeground,
				&_values);
	   graphics->bg = bg->pixel;
	}
}



/************************************************************
*
*  MODULE NAME:  X11_DrawPolygon
*
*      PURPOSE:  Draw a polygon.
*
*        INPUT:  graphics - graphics structure
*	         points   - points to be drawn
*	         size     - number of points
*
*   WRITTEN BY:
*
*
*************************************************************/

void X11_DrawPolygon(graphics, points, size)

X3DGraphics     *graphics;
XPoint		*points;
int		size;
{
	X11_DrawLines(graphics, points, size, CoordModeOrigin);
        XDrawLine(graphics->display, graphics->workspace, graphics->gc_draw,
		  points[size-1].x, points[size-1].y, points[0].x, points[0].y);
}



/************************************************************
*
*  MODULE NAME:  X11_DrawText
*
*      PURPOSE:  Draw text at the given position.
*
*        INPUT:  graphics - graphics structure
*	         x	  - x position
*	         y	  - y position
*		 font	  - font to be used
*	         text	  - text to be printed
*	         size	  - size of text array
*
*   WRITTEN BY:
*
*
*************************************************************/

void X11_DrawText(graphics, x, y, font, text, size)

X3DGraphics     *graphics;
char		*font, *text;
int		x, y, size;
{
	XDrawString(graphics->display, graphics->workspace, graphics->gc_draw, 
		    x,y,text,size);
}



/************************************************************
*
*  MODULE NAME:  X11_FillArc
*
*      PURPOSE: Draw a filled arc.  x,y are the upper left corner
*		of the bounding box of the circle ang1 & ang2 are
*		the start and finish angles specified in 64's of a degree
*
*
*        INPUT:  graphics - graphics structure
*	         x	  - of upper left corner
*	         y	  - of upper left corner
*	         w	  - width of Arc
*	         h	  - height of Arc
*	         arc1	  - start angle
*	         arc2	  - end angle
*
*   WRITTEN BY:  Mark Young & Mike Lang
*
*
*************************************************************/

void X11_FillArc(graphics, x, y, w, h, ang1, ang2)

X3DGraphics	*graphics;
int		x, y, ang1, ang2;
unsigned int	w, h;
{
	ang1 *= 64;
	ang2 *= 64;
	x = x - ((float) w)/2.0 + 0.5;
	y = y - ((float) h)/2.0 + 0.5;

	XFillArc(graphics->display, graphics->workspace, graphics->gc_fill,
		 x, y, w, h, ang1, ang2);
}



/************************************************************
*
*  MODULE NAME:  X11_FillRectangle
*
*      PURPOSE:  Draw a filled rectangle.
*
*        INPUT:  graphics - graphics structure
*	         x	  - of upper left corner
*	         y	  - of upper left corner
*	         w	  - width of rectangle
*	         h	  - height of rectangle
*
*   WRITTEN BY:  Mark Young & Mike Lang
*
*
*************************************************************/

void X11_FillRectangle(graphics, x, y, w, h)

X3DGraphics     *graphics;
int		x, y, w, h;
{
	XFillRectangle(graphics->display, graphics->workspace,
		       graphics->gc_fill, x, y, w, h);
}
