/*
 *	(c) Copyright 1991 Sun Microsystems, Inc.  All rights reserved.
 *	See LEGAL_NOTICE file for terms and restrictions.
 */


#ifndef lint
static  char sccsid[] = "@(#)SSM2 display_list.c 1.12 91/05/06 ";
#endif

/***********************************************************************
 *
 *	routines to implement display lists for Drawarea object
 *
 ***********************************************************************/


#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <xview/rect.h>
#include <xview/xv_xrect.h>
#include <xview/win_input.h>
#include <sspkg/drawobj.h>
#include "r_impl.h"
#include "do_impl.h"
#include "drawarea.h"
#include <sspkg/canshell.h>



/***********************************************************************
  
  
  exported display list routines
  
  
  ***********************************************************************/

traverse_display_list(drawarea_public, 
		      dpy, 
		      win, 
		      xrects, 
		      partial_flag)
     Drawarea drawarea_public;  
     Display * dpy;
     XID win;
     Xv_xrectlist *xrects;	/* additional clip rects to use 	      */
     int partial_flag; 		/* set if user wants to do just the new stuff */
{
  Drawarea_info *	dinfo 		= DRAWAREA_PRIVATE(drawarea_public);
  Rectobj_info *	rinfo 		= RECTOBJ_PRIVATE(drawarea_public);
  Shared_info *		shared_info 	= rinfo->shared_info;
  Dl_Cmds *		dl_cmds		= & dinfo->dl_cmds;
  Dl_Cmd  *		cmds		= dl_cmds->cmds;
  Dl_Transform *	dl_transform	= & dinfo->dl_transform;
  Dl_Interp		interp_instance;
  Dl_Interp *		dl_interp	= & interp_instance;
  Rect *		rect		= & rinfo->rect;
  GC			gc 		= dinfo->gc;
  Dl_Drawargs	       	drawargs_space;
  Dl_Drawargs *		dl_drawargs	= & drawargs_space;
  Region		region;
  Region		RectobjRegion();
  int 			i,n;
  
  if(gc == NULL)
    {
      gc = dinfo->gc = XCreateGC(dpy, xv_get(shared_info->canvas_shell,XV_XID), 0, 0);
      
      dinfo->font_info = XQueryFont(dpy, gc);
      
      XSetForeground(shared_info->dpy, 
		     dinfo->gc, 
		     rinfo->shared_info->pixels[rinfo->fg_color]);
      XSetBackground(shared_info->dpy, 
		     dinfo->gc, 
		     rinfo->shared_info->pixels[rinfo->bg_color]);
    }
  
  if(!partial_flag)
    {
      XSetForeground(shared_info->dpy, 
		     dinfo->gc, 
		     rinfo->shared_info->pixels[rinfo->fg_color]);
      XSetBackground(shared_info->dpy, 
		     dinfo->gc, 
		     rinfo->shared_info->pixels[rinfo->bg_color]);
    }
  
  region = RectobjRegion(drawarea_public, xrects);
  
  if(XEmptyRegion(region))
    return;
  
  XSetRegion(dpy, gc, region);
  
  XDestroyRegion(region);
  
  dl_interp->x_m = (double) rect->r_width/
    (dl_transform->right_x - dl_transform->left_x);
  
  dl_interp->x_b = (double) rect->r_left - 
    dl_interp->x_m * dl_transform->left_x;
  
  dl_interp->y_m = (double) rect->r_height/
    (dl_transform->lower_y - dl_transform->upper_y);
  
  dl_interp->y_b = (double) rect->r_top - 
    dl_interp->y_m * dl_transform->upper_y;
  
  dl_drawargs->dpy 	 = dpy;
  dl_drawargs->win_xid 	 = win;
  dl_drawargs->gc 	 = gc;
  dl_drawargs->rect 	 = rect;
  dl_drawargs->dl_interp = dl_interp;
  dl_drawargs->dl_limits = & dinfo->dl_limits;
    
  if((!partial_flag) || (dl_cmds->displayed == 0))
    {
      dl_drawargs->dl_limits->min_x = 
/*	dl_drawargs->dl_limits->min_y = max_normal(); */
	dl_drawargs->dl_limits->min_y = 0;
      dl_drawargs->dl_limits->max_x = 
/*	dl_drawargs->dl_limits->max_y = -max_normal(); */
	dl_drawargs->dl_limits->max_y = 0;
      dl_drawargs->dl_limits->checked = 0;
    }

  for(i=(partial_flag?dl_cmds->displayed:0); i<dl_cmds->used;i++)
    {
      dl_drawargs->data = cmds[i].data_ptr;
      (*(cmds[i].func))(dl_drawargs);
    }

  dl_cmds->displayed = dl_cmds->used;

  return(0);
}

Dl_Cmd * add_dl_cmd(dl_cmds)
     Dl_Cmds * dl_cmds;
{
  if(dl_cmds->used == dl_cmds->allocated)
    dl_cmds->cmds = ((dl_cmds->cmds)?
		     ((Dl_Cmd *) realloc(dl_cmds->cmds, 
					 sizeof(Dl_Cmd) * 
					 (dl_cmds->allocated+=30))):
		     ((Dl_Cmd *) malloc(sizeof(Dl_Cmd) * 
					(dl_cmds->allocated+=30))));
  return(dl_cmds->cmds + dl_cmds->used++);
}

clear_dl_cmds(dl_cmds)
     Dl_Cmds * dl_cmds;
{
  int i;
  caddr_t ptr;
  
  for(i=0;i<dl_cmds->used;i++)
    {
      free(dl_cmds->cmds[i].data_ptr);
      dl_cmds->cmds[i].data_ptr = NULL;
      dl_cmds->cmds[i].func = NULL;
    }
  
  dl_cmds->allocated = 0;
  dl_cmds->displayed = 0;
  dl_cmds->used = 0;
  if(dl_cmds->cmds)
    free(dl_cmds->cmds);
  dl_cmds->cmds = NULL;
}


/***********************************************************************
  
  
  internal display list routines
  
  
  ***********************************************************************/

static rd2X(out, dl_interp,x,y,w,h)
     Rect * out;
     Dl_Interp * dl_interp;
     double x, y, w, h;
{
  short x0 = xd2X(dl_interp, x);
  short y0 = xd2X(dl_interp, y);
  short x1 = xd2X(dl_interp, x + w);
  short y1 = xd2X(dl_interp, y + h);
  
  out->r_top = MIN(y0,y1);
  out->r_left = MIN(x0,x1);
  out->r_width = abs(x1-x0);
  out->r_height = abs(y1-y0);
}

static dl_limits_check(x,y,dl_limits)
double x, y;
Dl_Limits * dl_limits;
{
  dl_limits->max_x = 
    MAX(dl_limits->max_x,x);

  dl_limits->min_x = 
    MIN(dl_limits->min_x,x);

  dl_limits->max_y = 
    MAX(dl_limits->max_y,y);

  dl_limits->min_y = 
    MIN(dl_limits->min_y,y);

  dl_limits->checked = 1;
}

static int Ddrawline(dl_drawargs)
     Dl_Drawargs * dl_drawargs;
{
  int i;
  
  Dd_Line_Data * data =
    (Dd_Line_Data *) dl_drawargs->data;

  Dl_Interp * dl_interp = 
    dl_drawargs->dl_interp;

  Dl_Limits * dl_limits = 
    dl_drawargs->dl_limits;


  short x1 = xd2X(dl_interp, data->x1);
  short y1 = yd2X(dl_interp, data->y1);
  short x2 = xd2X(dl_interp, data->x2);
  short y2 = yd2X(dl_interp, data->y2);

  dl_limits_check(data->x1, data->y1, dl_limits);
  dl_limits_check(data->x2, data->y2, dl_limits);

  XDrawLine(dl_drawargs->dpy,
	    dl_drawargs->win_xid,
	    dl_drawargs->gc,
	    x1,
	    y1,
	    x2,
	    y2);
  return(0);
}

static int Ddrawrect(dl_drawargs)
     Dl_Drawargs * dl_drawargs;
{
  int i;
  
  Rect  a;
  
  Dd_Rect_Data * data =
    (Dd_Rect_Data *) dl_drawargs->data;
  
  Dl_Limits * dl_limits = 
    dl_drawargs->dl_limits;

  dl_limits_check(data->x, data->y, dl_limits);
  dl_limits_check(data->x + data->width, data->y + data->height, dl_limits);

  rd2X(&a, 
       dl_drawargs->dl_interp, 
       data->x,
       data->y,
       data->width,
       data->height);
  
  
  XDrawRectangle(dl_drawargs->dpy,
		 dl_drawargs->win_xid,
		 dl_drawargs->gc,
		 a.r_left,
		 a.r_top,
		 a.r_width,
		 a.r_height);
  return(0);
}

static int Dfillrect(dl_drawargs)
     Dl_Drawargs * dl_drawargs;
{
  int i;
  
  Rect  a;
  
  Dd_Rect_Data * data =
    (Dd_Rect_Data *) dl_drawargs->data;
  
  Dl_Limits * dl_limits = 
    dl_drawargs->dl_limits;

  dl_limits_check(data->x, data->y, dl_limits);
  dl_limits_check(data->x + data->width, data->y + data->height, dl_limits);

  rd2X(&a, 
       dl_drawargs->dl_interp, 
       data->x,
       data->y,
       data->width,
       data->height);
  
  
  XFillRectangle(dl_drawargs->dpy,
		 dl_drawargs->win_xid,
		 dl_drawargs->gc,
		 a.r_left,
		 a.r_top,
		 a.r_width,
		 a.r_height);
  return(0);
}

static int Ddrawarc(dl_drawargs)
     Dl_Drawargs * dl_drawargs;
{
  int i;
  
  Rect  a;
  
  Dd_Arc_Data * data =
    (Dd_Arc_Data *) dl_drawargs->data;
  
  Dl_Limits * dl_limits = 
    dl_drawargs->dl_limits;

  dl_limits_check(data->x, data->y, dl_limits);
  dl_limits_check(data->x + data->width, data->y + data->height, dl_limits);
  
  rd2X(&a, 
       dl_drawargs->dl_interp, 
       data->x,
       data->y,
       data->width,
       data->height);
  
  
  XDrawArc(dl_drawargs->dpy,
	   dl_drawargs->win_xid,
	   dl_drawargs->gc,
	   a.r_left,
	   a.r_top,
	   a.r_width,
	   a.r_height,
	   data->start,
	   data->stop);
  return(0);
}

static int Dfillarc(dl_drawargs)
     Dl_Drawargs * dl_drawargs;
{
  int i;
  
  Rect  a;
  
  Dd_Arc_Data * data =
    (Dd_Arc_Data *) dl_drawargs->data;
  
  Dl_Limits * dl_limits = 
    dl_drawargs->dl_limits;

  dl_limits_check(data->x, data->y, dl_limits);
  dl_limits_check(data->x + data->width, data->y + data->height, dl_limits);

  rd2X(&a, 
       dl_drawargs->dl_interp, 
       data->x,
       data->y,
       data->width,
       data->height);
  
  
  
  XFillArc(dl_drawargs->dpy,
	   dl_drawargs->win_xid,
	   dl_drawargs->gc,
	   a.r_left,
	   a.r_top,
	   a.r_width,
	   a.r_height,
	   (int)data->start,
	   (int)data->stop);
  return(0);
}

static int Ddrawstring(dl_drawargs)
     Dl_Drawargs * dl_drawargs;
{
  int i;
  
  Dd_String_Data * data =
    (Dd_String_Data *) dl_drawargs->data;

  Dl_Interp * dl_interp = 
    dl_drawargs->dl_interp;
  
  Dl_Limits * dl_limits = 
    dl_drawargs->dl_limits;


  short x = xd2X(dl_interp, data->x);
  short y = yd2X(dl_interp, data->y);
  
  dl_limits_check(data->x, data->y, dl_limits);
  
  XDrawString(dl_drawargs->dpy,
	      dl_drawargs->win_xid,
	      dl_drawargs->gc,
	      x,
	      y,
	      data->chars,
	      data->length);
  return(0);
}



static int Ddrawlines(dl_drawargs)
     Dl_Drawargs * dl_drawargs;
{
  int i,j,k;
  static int size;
  
  Dd_Poly_Data * data =
    (Dd_Poly_Data *) dl_drawargs->data;

  Dl_Interp * dl_interp = 
    dl_drawargs->dl_interp;
  
  Dl_Limits * dl_limits = 
    dl_drawargs->dl_limits;

  XPoint * points = (XPoint *) malloc(sizeof(XPoint) * data->npoints);
  
  if(size == 0)
    size = (XMaxRequestSize(dl_drawargs->dpy)-3)/2; /* should depend on display */
  
  for(i = 0 ; i < data->npoints; i++)
    {
      dl_limits_check(data->points[i].x,
		      data->points[i].y,		      
		      dl_limits);
      points[i].x = (short) xd2X(dl_interp, data->points[i].x);
      points[i].y = (short) yd2X(dl_interp, data->points[i].y);
    }
  
  for(j=0, k = data->npoints;j < data->npoints;j+=size, k-=size)
    XDrawLines(dl_drawargs->dpy,
	       dl_drawargs->win_xid,
	       dl_drawargs->gc,
	       points+j,
	       (k < size)?k:size,
	       data->mode);

  free((char *)points);
  return(0);
}

static int Dfillpoly(dl_drawargs)
     Dl_Drawargs * dl_drawargs;
{
  int i;
  
  Dd_Poly_Data * data =
    (Dd_Poly_Data *) dl_drawargs->data;

  Dl_Interp * dl_interp = 
    dl_drawargs->dl_interp;

  Dl_Limits * dl_limits = 
    dl_drawargs->dl_limits;

  XPoint * points = (XPoint *) malloc(sizeof(XPoint) * data->npoints);
  
  for(i = 0 ; i < data->npoints; i++)
    {
      dl_limits_check(data->points[i].x,
		      data->points[i].y,		      
		      dl_limits);
      points[i].x = (short) xd2X(dl_interp, data->points[i].x);
      points[i].y = (short) yd2X(dl_interp, data->points[i].y);
    }
  
  
  XFillPolygon(dl_drawargs->dpy,
	       dl_drawargs->win_xid,
	       dl_drawargs->gc,
	       points,
	       data->npoints,
	       data->shape,
	       data->mode);
  free((char *)points);
  return(0);
}


/*
  routines that use fixed transform
  */



static int Sdrawline(dl_drawargs)
     Dl_Drawargs * dl_drawargs;
{
  int i;
  
  Ds_Line_Data * data = 
    (Ds_Line_Data *) dl_drawargs->data;

  Rect * rect = dl_drawargs->rect;

  short x1 = xv2X(rect, data->x1);
  short y1 = yv2X(rect, data->y1);
  short x2 = xv2X(rect, data->x2);
  short y2 = yv2X(rect, data->y2);
  
  
  XDrawLine(dl_drawargs->dpy,
	    dl_drawargs->win_xid,
	    dl_drawargs->gc,
	    x1,
	    y1,
	    x2,
	    y2);
  return(0);
}

static int Sdrawrect(dl_drawargs)
     Dl_Drawargs * dl_drawargs;
{
  int i;
  
  Ds_Rect_Data * data = 
    (Ds_Rect_Data *) dl_drawargs->data;

  Rect * rect = dl_drawargs->rect;
  
  short x = xv2X(rect, data->x);
  short y = yv2X(rect, data->y);
  short height = hv2X(rect, data->height);
  short width = wv2X(rect, data->width);
  
  
  XDrawRectangle(dl_drawargs->dpy,
		 dl_drawargs->win_xid,
		 dl_drawargs->gc,
		 x,
		 y,
		 width,
		 height);
  return(0);
}

static int Sfillrect(dl_drawargs)
     Dl_Drawargs * dl_drawargs;
{
  int i;
  
  Ds_Rect_Data * data = 
    (Ds_Rect_Data *) dl_drawargs->data;
  
  Rect * rect = dl_drawargs->rect;

  short x = xv2X(rect, data->x);
  short y = yv2X(rect, data->y);
  short height = hv2X(rect, data->height);
  short width = wv2X(rect, data->width);
  
  
  XFillRectangle(dl_drawargs->dpy,
		 dl_drawargs->win_xid,
		 dl_drawargs->gc,
		 x,
		 y,
		 width,
		 height);
  return(0);
}

static int Sdrawarc(dl_drawargs)
     Dl_Drawargs * dl_drawargs;
{
  int i;
  
  Ds_Arc_Data * data = 
    (Ds_Arc_Data *) dl_drawargs->data;

  Rect * rect = dl_drawargs->rect;

  
  short x = xv2X(rect, data->x);
  short y = yv2X(rect, data->y);
  short height = hv2X(rect, data->height);
  short width = wv2X(rect, data->width);
  
  
  XDrawArc(dl_drawargs->dpy,
	   dl_drawargs->win_xid,
	   dl_drawargs->gc,
	   x,
	   y,
	   width,
	   height,
	   data->start,
	   data->stop);
  return(0);
}

static int Sfillarc(dl_drawargs)
     Dl_Drawargs * dl_drawargs;
{
  int i;
  
  Ds_Arc_Data * data = 
    (Ds_Arc_Data *) dl_drawargs->data;
  
  Rect * rect = dl_drawargs->rect;

  short x = xv2X(rect, data->x);
  short y = yv2X(rect, data->y);
  short height = hv2X(rect, data->height);
  short width = wv2X(rect, data->width);
  
  
  XFillArc(dl_drawargs->dpy,
	   dl_drawargs->win_xid,
	   dl_drawargs->gc,
	   x,
	   y,
	   width,
	   height,
	   data->start,
	   data->stop);
  return(0);
}

static int Sdrawstring(dl_drawargs)
     Dl_Drawargs * dl_drawargs;
{
  int i;
  
  Ds_String_Data * data = 
    (Ds_String_Data *) dl_drawargs->data;
  
  Rect * rect = dl_drawargs->rect;

  short x = xv2X(rect, data->x);
  short y = yv2X(rect, data->y);
  
  
  XDrawString(dl_drawargs->dpy,
	      dl_drawargs->win_xid,
	      dl_drawargs->gc,
	      x,
	      y,
	      data->chars,
	      data->length);
  return(0);
}



static int Sdrawlines(dl_drawargs)
     Dl_Drawargs * dl_drawargs;
{
  int i,j,k;
  static int size;
  
  Rect * rect = dl_drawargs->rect;

  Ds_Poly_Data * data = 
    (Ds_Poly_Data *) dl_drawargs->data;
  
  XPoint * points = (XPoint *) malloc(sizeof(XPoint) * data->npoints);
  
  if(size == 0)
    size = (XMaxRequestSize(dl_drawargs->dpy)-3)/2; /* should depend on display */
  
  for(i = 0 ; i < data->npoints; i++)
    {
      points[i].x = (short) xv2X(rect, (int) data->points[i].x);
      points[i].y = (short) yv2X(rect, (int) data->points[i].y);
    }
  
  for(j=0, k = data->npoints;j < data->npoints;j+=size, k-=size)
    XDrawLines(dl_drawargs->dpy,
	       dl_drawargs->win_xid,
	       dl_drawargs->gc,
	       points+j,
	       (k < size)?k:size,
	       data->mode);
  free((char *)points);
  return(0);
}

static int Sfillpoly(dl_drawargs)
     Dl_Drawargs * dl_drawargs;
{
  int i;
  
  Ds_Poly_Data * data = 
    (Ds_Poly_Data *) dl_drawargs->data;

  Rect * rect = dl_drawargs->rect;

  
  XPoint * points = (XPoint *) malloc(sizeof(XPoint) * data->npoints);
  
  for(i = 0 ; i < data->npoints; i++)
    {
      points[i].x = (short) xv2X(rect, (int) data->points[i].x);
      points[i].y = (short) yv2X(rect, (int) data->points[i].y);
    }
  
  
  XFillPolygon(dl_drawargs->dpy,
	       dl_drawargs->win_xid,
	       dl_drawargs->gc,
	       points,
	       data->npoints,
	       data->shape,
	       data->mode);
  free((char *)points);
  return(0);
}

/***********************************
  
  gc routine
  
  **********************************/






static int update_gc(dl_drawargs)
     Dl_Drawargs * dl_drawargs;
{

  Dl_Gc_Data * data = 
    (Dl_Gc_Data *) dl_drawargs->data;

  Rect * rect = dl_drawargs->rect;

  switch(data->type)
    {
    case Gc_LineStyle:
    case Gc_LineWidth:
      XSetLineAttributes(dl_drawargs->dpy, dl_drawargs->gc, 
			 wv2X(rect, data->data.linestylewidth[1]),
			 data->data.linestylewidth[0],
			 CapButt,
			 JoinMiter);
      break;
      
    case Gc_Color:
      XSetForeground(dl_drawargs->dpy,dl_drawargs->gc,data->data.color);
      break;
      
    case Gc_FillStyle:
      XSetFillStyle(dl_drawargs->dpy, dl_drawargs->gc,data->data.fillstyle);
      break;
      
    case Gc_Font:
      XSetFont(dl_drawargs->dpy, dl_drawargs->gc,  data->data.font_xid);
      break;
      
    case Gc_Stipple:
      XSetStipple(dl_drawargs->dpy, dl_drawargs->gc, data->data.pixmap);
      break;
      
    case Gc_Tile:
      XSetTile(dl_drawargs->dpy, dl_drawargs->gc, data->data.pixmap);
      break;
    }
  return(0);
}

/***********************************************************************
  
  public interface
  
  **********************************************************************/

VDrawLine(drawarea_public,x1,y1,x2,y2)
     Drawarea drawarea_public;
     SCoord x1,y1,x2,y2;
{
  Drawarea_info *	dinfo 		= DRAWAREA_PRIVATE(drawarea_public);
  Ds_Line_Data * ptr;
  Dl_Cmd * cmd;
  
  ptr = (Ds_Line_Data *) malloc(sizeof(*ptr));
  cmd = add_dl_cmd(&dinfo->dl_cmds);
  ptr->x1 = x1;
  ptr->y1 = y1;
  ptr->x2 = x2;
  ptr->y2 = y2;
  cmd->data_ptr = (caddr_t) ptr;
  cmd->func = Sdrawline;
  return(0);
}

VDrawRectangle(drawarea_public,x,y,width, height)
     Drawarea drawarea_public;
     SCoord x,y, width, height;
{
  Drawarea_info *	dinfo 		= DRAWAREA_PRIVATE(drawarea_public);
  Ds_Rect_Data * ptr;
  Dl_Cmd * cmd;
  
  ptr = (Ds_Rect_Data *) malloc(sizeof(*ptr));
  cmd = add_dl_cmd(&dinfo->dl_cmds);
  ptr->x = x;
  ptr->y = y;
  ptr->width = width;
  ptr->height = height;
  cmd->data_ptr = (caddr_t) ptr;
  cmd->func = Sdrawrect;
  return(0);
}

VFillRectangle(drawarea_public,x,y,width, height)
     Drawarea drawarea_public;
     SCoord x,y, width, height;
{
  Drawarea_info *	dinfo 		= DRAWAREA_PRIVATE(drawarea_public);
  Ds_Rect_Data * ptr;
  Dl_Cmd * cmd;
  
  ptr = (Ds_Rect_Data *) malloc(sizeof(*ptr));
  cmd = add_dl_cmd(&dinfo->dl_cmds);
  ptr->x = x;
  ptr->y = y;
  ptr->width = width;
  ptr->height = height;
  cmd->data_ptr = (caddr_t) ptr;
  cmd->func = Sfillrect;
  return(0);
}

VDrawArc(drawarea_public,x,y,width, height, start,stop)
     Drawarea drawarea_public;
     SCoord x,y, width, height, start, stop;
{
  Drawarea_info *	dinfo 		= DRAWAREA_PRIVATE(drawarea_public);
  Ds_Arc_Data * ptr;
  Dl_Cmd * cmd;
  
  ptr = (Ds_Arc_Data *) malloc(sizeof(*ptr));
  cmd = add_dl_cmd(&dinfo->dl_cmds);
  ptr->x = x;
  ptr->y = y;
  ptr->width = width;
  ptr->height = height;
  ptr->start = start;
  ptr->stop = stop;
  cmd->data_ptr = (caddr_t) ptr;
  cmd->func = Sdrawarc;
  return(0);
}

VFillArc(drawarea_public,x,y,width, height, start,stop)
     Drawarea drawarea_public;
     SCoord x,y, width, height, start, stop;
{
  Drawarea_info *	dinfo 		= DRAWAREA_PRIVATE(drawarea_public);
  Ds_Arc_Data * ptr;
  Dl_Cmd * cmd;
  
  ptr = (Ds_Arc_Data *) malloc(sizeof(*ptr));
  cmd = add_dl_cmd(&dinfo->dl_cmds);
  ptr->x = x;
  ptr->y = y;
  ptr->width = width;
  ptr->height = height;
  ptr->start = start;
  ptr->stop = stop;
  cmd->data_ptr = (caddr_t) ptr;
  cmd->func = Sfillarc;
  return(0);
}

VDrawString(drawarea_public,x,y,string, length)
     Drawarea drawarea_public;
     SCoord x,y;
     int length;
     char * string;
{
  Drawarea_info *	dinfo 		= DRAWAREA_PRIVATE(drawarea_public);
  Ds_String_Data * ptr;
  Dl_Cmd * cmd;
  
  ptr = (Ds_String_Data *) malloc(sizeof(*ptr)+length);
  cmd = add_dl_cmd(&dinfo->dl_cmds);
  ptr->x = x;
  ptr->y = y;
  ptr->length = length;
  strncpy(ptr->chars, string, length);
  cmd->data_ptr = (caddr_t) ptr;
  cmd->func = Sdrawstring;
  return(0);
}

VFillPoly(drawarea_public, points, npoints, shape, mode)
     Drawarea drawarea_public;
     SCoord points[];
     int npoints, shape, mode;
{
  Drawarea_info *	dinfo 		= DRAWAREA_PRIVATE(drawarea_public);
  Ds_Poly_Data * ptr;
  Dl_Cmd * cmd;
  int i;
  
  ptr = (Ds_Poly_Data *) malloc(sizeof(*ptr) + sizeof(XPoint) * npoints);
  
  cmd = add_dl_cmd(&dinfo->dl_cmds);
  
  for( i = 0; i < npoints;i++)
    {
      ptr->points[i].x = points[i*2];
      ptr->points[i].y = points[i*2+1];
    }
  
  ptr->npoints = npoints;
  ptr->shape = /* shape; */ 	Complex;
  ptr->mode = /* mode; */	CoordModeOrigin;
  cmd->data_ptr = (caddr_t) ptr;
  cmd->func = Sfillpoly;
  return(0);
}

VDrawPoly(drawarea_public, points, npoints, mode)
     Drawarea drawarea_public;
     SCoord points[];
     int npoints, mode;
{
  Drawarea_info *	dinfo 		= DRAWAREA_PRIVATE(drawarea_public);
  Ds_Poly_Data * ptr;
  Dl_Cmd * cmd;
  int i;
  
  ptr = (Ds_Poly_Data *) malloc(sizeof(*ptr) + sizeof(XPoint) * (npoints+1));
  
  cmd = add_dl_cmd(&dinfo->dl_cmds);
  
  for( i = 0; i < npoints;i++)
    {
      ptr->points[i].x = points[i*2];
      ptr->points[i].y = points[i*2+1];
    }
  
  ptr->points[npoints] = ptr->points[0];
  
  ptr->npoints = npoints + 1;
  ptr->mode = /* mode; */	CoordModeOrigin;
  cmd->data_ptr = (caddr_t) ptr;
  cmd->func = Sdrawlines;
  return(0);
}

VDrawLines(drawarea_public, points, npoints, mode)
     Drawarea drawarea_public;
     SCoord points[];
     int npoints, mode;
{
  Drawarea_info *	dinfo 		= DRAWAREA_PRIVATE(drawarea_public);
  Ds_Poly_Data * ptr;
  Dl_Cmd * cmd;
  int i;
  
  ptr = (Ds_Poly_Data *) malloc(sizeof(*ptr) + sizeof(XPoint) * (npoints));
  
  cmd = add_dl_cmd(&dinfo->dl_cmds);
  
  for( i = 0; i < npoints;i++)
    {
      ptr->points[i].x = points[i*2];
      ptr->points[i].y = points[i*2+1];
    }
  
  ptr->npoints = npoints;
  ptr->mode = /* mode; */	CoordModeOrigin;
  cmd->data_ptr = (caddr_t) ptr;
  cmd->func = Sdrawlines;
  return(0);
}
/* double versions */

DDrawLine(drawarea_public,x1,y1,x2,y2)
     Drawarea drawarea_public;
     DCoord x1,y1,x2,y2;
{
  Drawarea_info *	dinfo 		= DRAWAREA_PRIVATE(drawarea_public);
  Dd_Line_Data * ptr;
  Dl_Cmd * cmd;
  
  ptr = (Dd_Line_Data *) malloc(sizeof(*ptr));
  cmd = add_dl_cmd(&dinfo->dl_cmds);
  ptr->x1 = x1;
  ptr->y1 = y1;
  ptr->x2 = x2;
  ptr->y2 = y2;
  cmd->data_ptr = (caddr_t) ptr;
  cmd->func = Ddrawline;

  return(0);
}

DDrawRectangle(drawarea_public,x,y,width, height)
     Drawarea drawarea_public;
     DCoord x,y, width, height;
{
  Drawarea_info *	dinfo 		= DRAWAREA_PRIVATE(drawarea_public);
  Dd_Rect_Data * ptr;
  Dl_Cmd * cmd;
  
  ptr = (Dd_Rect_Data *) malloc(sizeof(*ptr));
  cmd = add_dl_cmd(&dinfo->dl_cmds);
  ptr->x = x;
  ptr->y = y;
  ptr->width = width;
  ptr->height = height;
  cmd->data_ptr = (caddr_t) ptr;
  cmd->func = Ddrawrect;
  return(0);
}

DFillRectangle(drawarea_public,x,y,width, height)
     Drawarea drawarea_public;
     DCoord x,y, width, height;
{
  Drawarea_info *	dinfo 		= DRAWAREA_PRIVATE(drawarea_public);
  Dd_Rect_Data * ptr;
  Dl_Cmd * cmd;
  
  ptr = (Dd_Rect_Data *) malloc(sizeof(*ptr));
  cmd = add_dl_cmd(&dinfo->dl_cmds);
  ptr->x = x;
  ptr->y = y;
  ptr->width = width;
  ptr->height = height;
  cmd->data_ptr = (caddr_t) ptr;
  cmd->func = Dfillrect;
  return(0);
}

DDrawArc(drawarea_public,x,y,width, height, start,stop)
     Drawarea drawarea_public;
     DCoord x,y, width, height, start, stop;
{
  Drawarea_info *	dinfo 		= DRAWAREA_PRIVATE(drawarea_public);
  Dd_Arc_Data * ptr;
  Dl_Cmd * cmd;
  
  ptr = (Dd_Arc_Data *) malloc(sizeof(*ptr));
  cmd = add_dl_cmd(&dinfo->dl_cmds);
  ptr->x = x;
  ptr->y = y;
  ptr->width = width;
  ptr->height = height;
  ptr->start = start;
  ptr->stop = stop;
  cmd->data_ptr = (caddr_t) ptr;
  cmd->func = Ddrawarc;
  return(0);
}

DFillArc(drawarea_public,x,y,width, height, start,stop)
     Drawarea drawarea_public;
     DCoord x,y, width, height, start, stop;
{
  Drawarea_info *	dinfo 		= DRAWAREA_PRIVATE(drawarea_public);
  Dd_Arc_Data * ptr;
  Dl_Cmd * cmd;
  
  ptr = (Dd_Arc_Data *) malloc(sizeof(*ptr));
  cmd = add_dl_cmd(&dinfo->dl_cmds);
  ptr->x = x;
  ptr->y = y;
  ptr->width = width;
  ptr->height = height;
  ptr->start = start;
  ptr->stop = stop;
  cmd->data_ptr = (caddr_t) ptr;
  cmd->func = Dfillarc;
  return(0);
}

DDrawString(drawarea_public,x,y,string, length)
     Drawarea drawarea_public;
     DCoord x,y;
     int length;
     char * string;
{
  Drawarea_info *	dinfo 		= DRAWAREA_PRIVATE(drawarea_public);
  Dd_String_Data * ptr;
  Dl_Cmd * cmd;
  
  ptr = (Dd_String_Data *) malloc(sizeof(*ptr)+length);
  cmd = add_dl_cmd(&dinfo->dl_cmds);
  ptr->x = x;
  ptr->y = y;
  ptr->length = length;
  strncpy(ptr->chars, string, length);
  cmd->data_ptr = (caddr_t) ptr;
  cmd->func = Ddrawstring;
  return(0);
}

DFillPoly(drawarea_public, points, npoints, shape, mode)
     Drawarea drawarea_public;
     DCoord points[];
     int npoints, shape, mode;
{
  Drawarea_info *	dinfo 		= DRAWAREA_PRIVATE(drawarea_public);
  Dd_Poly_Data * ptr;
  Dl_Cmd * cmd;
  int i;
  
  ptr = (Dd_Poly_Data *) malloc(sizeof(*ptr) + sizeof(DPoint) * npoints);
  
  cmd = add_dl_cmd(&dinfo->dl_cmds);
  
  for( i = 0; i < npoints;i++)
    {
      ptr->points[i].x = points[i*2];
      ptr->points[i].y = points[i*2+1];
    }
  
  ptr->npoints = npoints;
  ptr->shape = /* shape; */ 	Complex;
  ptr->mode = /* mode; */	CoordModeOrigin;
  cmd->data_ptr = (caddr_t) ptr;
  cmd->func = Dfillpoly;
  return(0);
}

DDrawPoly(drawarea_public, points, npoints, mode)
     Drawarea drawarea_public;
     DCoord points[];
     int npoints, mode;
{
  Drawarea_info *	dinfo 		= DRAWAREA_PRIVATE(drawarea_public);
  Dd_Poly_Data * ptr;
  Dl_Cmd * cmd;
  int i;
  
  ptr = (Dd_Poly_Data *) malloc(sizeof(*ptr) + sizeof(DPoint) * (npoints+1));
  
  cmd = add_dl_cmd(&dinfo->dl_cmds);
  
  for( i = 0; i < npoints;i++)
    {
      ptr->points[i].x = points[i*2];
      ptr->points[i].y = points[i*2+1];
    }
  
  ptr->points[npoints] = ptr->points[0];
  
  ptr->npoints = npoints+1;
  ptr->mode = /* mode; */	CoordModeOrigin;
  cmd->data_ptr = (caddr_t) ptr;
  cmd->func = Ddrawlines;
  return(0);
}

DDrawLines(drawarea_public, points, npoints, mode)
     Drawarea drawarea_public;
     DCoord points[];
     int npoints, mode;
{
  Drawarea_info *	dinfo 		= DRAWAREA_PRIVATE(drawarea_public);
  Dd_Poly_Data * ptr;
  Dl_Cmd * cmd;
  int i;
  
  ptr = (Dd_Poly_Data *) malloc(sizeof(*ptr) + sizeof(DPoint) * (npoints));
  
  cmd = add_dl_cmd(&dinfo->dl_cmds);
  
  for( i = 0; i < npoints;i++)
    {
      ptr->points[i].x = points[i*2];
      ptr->points[i].y = points[i*2+1];
    }
  
  
  ptr->npoints = npoints;
  ptr->mode = /* mode; */	CoordModeOrigin;
  cmd->data_ptr = (caddr_t) ptr;
  cmd->func = Ddrawlines;
  return(0);
}


VSetFont(drawarea_public, font)
     Xv_font font;
     Drawarea drawarea_public;
{
  Drawarea_info *	dinfo 		= DRAWAREA_PRIVATE(drawarea_public);
  Dl_Gc_Data * ptr;
  Dl_Cmd * cmd;
  
  ptr = (Dl_Gc_Data *) malloc(sizeof(*ptr));
  cmd = add_dl_cmd(&dinfo->dl_cmds);
  
  ptr->type = Gc_Font;
  ptr->data.font_xid = (XID) xv_get(font, XV_XID);
  
  cmd->data_ptr = (caddr_t) ptr;
  cmd->func = update_gc;
  return(0);
}

VSetTile(drawarea_public, server_image)
     Server_image server_image;
     Drawarea drawarea_public;
{
  Drawarea_info *	dinfo 		= DRAWAREA_PRIVATE(drawarea_public);
  Dl_Gc_Data * ptr;
  Dl_Cmd * cmd;
  
  ptr = (Dl_Gc_Data *) malloc(sizeof(*ptr));
  cmd = add_dl_cmd(&dinfo->dl_cmds);
  
  ptr->type = Gc_Tile;
  ptr->data.pixmap = (Pixmap) xv_get(server_image, SERVER_IMAGE_PIXMAP);
  
  cmd->data_ptr = (caddr_t) ptr;
  cmd->func = update_gc;
  return(0);
}

VSetStipple(drawarea_public, server_image)
     Server_image server_image;
     Drawarea drawarea_public;
{
  Drawarea_info *	dinfo 		= DRAWAREA_PRIVATE(drawarea_public);
  Dl_Gc_Data * ptr;
  Dl_Cmd * cmd;
  
  ptr = (Dl_Gc_Data *) malloc(sizeof(*ptr));
  cmd = add_dl_cmd(&dinfo->dl_cmds);
  
  ptr->type = Gc_Stipple;
  ptr->data.pixmap = (Pixmap) xv_get(server_image, SERVER_IMAGE_PIXMAP);
  
  cmd->data_ptr = (caddr_t) ptr;
  cmd->func = update_gc;
  return(0);
}

VSetFillStyle(drawarea_public, fillstyle)
     Drawarea drawarea_public;
     int fillstyle;
{
  Drawarea_info *	dinfo 		= DRAWAREA_PRIVATE(drawarea_public);
  Dl_Gc_Data * ptr;
  Dl_Cmd * cmd;
  
  ptr = (Dl_Gc_Data *) malloc(sizeof(*ptr));
  cmd = add_dl_cmd(&dinfo->dl_cmds);
  
  ptr->type = Gc_FillStyle;
  ptr->data.fillstyle = fillstyle;
  
  cmd->data_ptr = (caddr_t) ptr;
  cmd->func = update_gc;
  return(0);
}

VSetLineWidth(drawarea_public, linewidth)
     Drawarea drawarea_public;
{
  Drawarea_info *	dinfo 		= DRAWAREA_PRIVATE(drawarea_public);
  Dl_Gc_Data * ptr;
  Dl_Cmd * cmd;
  
  ptr = (Dl_Gc_Data *) malloc(sizeof(*ptr));
  cmd = add_dl_cmd(&dinfo->dl_cmds);
  
  ptr->type = Gc_LineWidth;
  
  dinfo->linewidth = ptr->data.linestylewidth[1] = linewidth;
  ptr->data.linestylewidth[0] = dinfo->linestyle;
  
  cmd->data_ptr = (caddr_t) ptr;
  cmd->func = update_gc;
  return(0);
  
}

VSetLineStyle(drawarea_public, linestyle)
     Drawarea drawarea_public;
{
  Drawarea_info *	dinfo 		= DRAWAREA_PRIVATE(drawarea_public);
  Dl_Gc_Data * ptr;
  Dl_Cmd * cmd;
  
  ptr = (Dl_Gc_Data *) malloc(sizeof(*ptr));
  cmd = add_dl_cmd(&dinfo->dl_cmds);
  
  ptr->type = Gc_LineStyle;
  dinfo->linestyle = ptr->data.linestylewidth[0] = linestyle;
  ptr->data.linestylewidth[1] = dinfo->linewidth;
  cmd->data_ptr = (caddr_t) ptr;
  cmd->func = update_gc;
  return(0);
}

VSetColor(drawarea_public, color)
     Drawarea drawarea_public;
{
  Drawarea_info *	dinfo 		= DRAWAREA_PRIVATE(drawarea_public);
  Rectobj_info    *rinfo 		= RECTOBJ_PRIVATE(drawarea_public);
  
  
  Dl_Gc_Data * ptr;
  Dl_Cmd * cmd;
  
  if(rinfo->shared_info) 
    if((color >= rinfo->shared_info->num_colors) || ( color < 0))
      return(-1);
  
  
  ptr = (Dl_Gc_Data *) malloc(sizeof(*ptr));
  cmd = add_dl_cmd(&dinfo->dl_cmds);
  
  ptr->type = Gc_Color;
  
  if(rinfo->shared_info) 
    ptr->data.color = rinfo->shared_info->pixels[color];
  else
    ptr->data.color = rinfo->fg_color;
  
  cmd->data_ptr = (caddr_t) ptr;
  cmd->func = update_gc;
  return(0);
  
}

VFlush(drawarea_public)
     Drawarea drawarea_public;
{
  Rectobj_info		*rinfo = RECTOBJ_PRIVATE(drawarea_public);
  Xv_window		xv_win;
  Xv_xrectlist		xrects;
  
  if(!rinfo->shared_info)
    return;
  
  
  xrects.count = 1;
  xrects.rect_array[0] = *(XRectangle*) & rinfo->rect;
  
  CANVAS_EACH_PAINT_WINDOW(rinfo->shared_info->canvas_shell, xv_win)
    
    traverse_display_list(drawarea_public,
			  rinfo->shared_info->dpy, 
			  xv_get(xv_win, XV_XID), 
			  &xrects,
			  1);
  
  CANVAS_END_EACH
  }



VClear(drawarea_public)
     Drawarea drawarea_public;
{
  Drawarea_info *	dinfo 		= DRAWAREA_PRIVATE(drawarea_public);
  Rectobj_info *	rinfo 		= RECTOBJ_PRIVATE(drawarea_public);
  Shared_info *		shared_info 	= rinfo->shared_info;
  
  clear_dl_cmds(& dinfo->dl_cmds);
  
  if(!shared_info)
    return;
  
  rectobj_repaint_rect(drawarea_public, NULL, TRUE);
  rectobj_flush_repaint();
  
}

