Received: by ATHENA-PO-3.MIT.EDU (5.45/4.7) id AA17279; Sun, 21 Apr 91 11:33:18 EST
Received: from munnari.OZ.AU by ATHENA.MIT.EDU with SMTP
	id AA07419; Sun, 21 Apr 91 12:32:09 EDT
Received: from melba.bby.oz (via ditmela) by munnari.oz.au with SunIII (5.64+1.3.1+0.50)
	id AA28437; Mon, 22 Apr 1991 02:31:59 +1000 (from gnb%bby.oz.au@melba.bby.oz.au)
Received: from baby.bby.oz.au by melba.bby.oz.au (4.0/SMI-4.0/BBY)
	id AA16677; Tue, 16 Apr 91 16:18:39 EST
       (from gnb@bby.oz.au for bug-at%athena.mit.edu@munnari.oz)
Received: by baby.bby.oz.au (4.1/SMI-4.1)
	id AA10536; Tue, 16 Apr 91 16:18:22 EST
Message-Id: <9104160618.AA10536@baby.bby.oz.au>
To: bug-at@ATHENA.MIT.EDU
Subject: AtPlotter bugs/enhancements
Date: Tue, 16 Apr 91 16:18:17 +1000
From: Gregory Bond <gnb@bby.oz.au>

Guys,

As promised last week, here is a set of quite significant patches to
the plotter widget.  They add significantly more flexible axis
processing, and fix a number of bugs.

Changes:
--------

The main change is that all three main axes are now optional (although
the results of not displaying at least one Y axis is "interesting".)
The default behaviour is as the old version (X & Y displayed, Y2 not
displayed).  However, there has been a change in the specification:
the showY2Axis resource has been removed, and the three axis are
displayed using the displayed constraint resource.

I have added a y2frameaxis for the case where framedAxis is true and
Y2axis is displayed but not Yaxis.

Bug Fixes:
----------
The plotter widget now knows about its private children, and doesn't
attempt to treat axis objects the same as plot objects.

No mention in the man pages about what the private children are, when
they are used, etc.  Added a section on the private children in the
AtPlotter man page.

No mention in the man page about the fact that the plot and axis
children cannot be managed (as they are not subclasses of RectObj) and
that doing so will corrupt the instance record (in particular, the
lineWidth resource gets clobbered by the assignment to the
core.managed field in XtManageChildren).

Mixed in with this is a whole lotta code that makes mirrored axes,
framed axes, Y hidden, Y2 hidden, numbersOutside, every combination
that I can think of work and do what you expect, for screen and
PostScript output.

Compatability Problems
----------------------
1) The size of the AtPlotter instance record has changed.
2) The showY2Axis resource has gone; use y2axis.displayed instead.
3) The resources for fetching the axes have gone; use 
   AtPlotterGetXAxis() and similar routines instead.  They can also
   get access to the frame axis objects.
----------------------------------------------------------------

The diffs attatched require the patch I posted a few weeks ago to make
the displayed constraint resource work, and the patch I posted last
week to make the axis processing work better.

Next on the list:
1) Making the legend auto-scale for width (or make it legendWidth if
   non zero) 
2) There is, in some wierd circumstances, a bug in the redrawing of
   the title so that it redraws in a slightly different place.  Also,
   the continual redrawing and flashing of the title and legend is
   annoying on exposes etc, so I will probably do the redraw in a clip
   region. 
3) Major work on the redisplay hierarchy (see the following posting).

Greg.
-- 
Gregory Bond, Burdett Buckeridge & Young Ltd, Melbourne, Australia
Internet: gnb@melba.bby.oz.au    non-MX: gnb%melba.bby.oz@uunet.uu.net
Uucp: {uunet,pyramid,ubc-cs,ukc,mcvax,prlb2,nttlab...}!munnari!melba.bby.oz!gnb

*** /tmp/,RCSt1a22231	Tue Apr 16 16:12:39 1991
--- Plotter.c	Tue Apr 16 16:00:21 1991
***************
*** 146,153 ****
       sizeof(Boolean), offset(plotter.floatingY), XtRImmediate, (caddr_t)False},
      {XtNframedAxes, XtCFramedAxes, XtRBoolean,
       sizeof(Boolean), offset(plotter.framedAxes), XtRImmediate,(caddr_t)False},
-     {XtNshowY2Axis, XtCShowY2Axis, XtRBoolean,
-      sizeof(Boolean), offset(plotter.showY2Axis), XtRImmediate,(caddr_t)False},
      {XtNshowLegend, XtCShowLegend, XtRBoolean,
       sizeof(Boolean), offset(plotter.showLegend), XtRImmediate, (caddr_t)True},
      {XtNlegendWidth, XtCLegendWidth, XtRShort,
--- 146,151 ----
***************
*** 173,185 ****
      {XtNdoubleSelectCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
       offset(plotter.doubleSelectCallback), XtRCallback, NULL},
      {XtNerrorCallback, XtCCallback, XtRCallback,sizeof(XtCallbackList),
!      offset(plotter.errorCallback), XtRCallback, NULL},
!     {XtNxaxis, XtCAxis, XtRPlotterAxis, sizeof(AtAxisObject),
!      offset(plotter.xaxis), XtRPlotterAxis, NULL},
!     {XtNyaxis, XtCAxis, XtRPlotterAxis, sizeof(AtAxisObject),
!      offset(plotter.yaxis), XtRPlotterAxis, NULL},
!     {XtNy2axis, XtCAxis, XtRPlotterAxis, sizeof(AtAxisObject),
!      offset(plotter.y2axis), XtRPlotterAxis, NULL},    
  };
  #undef offset
  
--- 171,177 ----
      {XtNdoubleSelectCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
       offset(plotter.doubleSelectCallback), XtRCallback, NULL},
      {XtNerrorCallback, XtCCallback, XtRCallback,sizeof(XtCallbackList),
!      offset(plotter.errorCallback), XtRCallback, NULL}
  };
  #undef offset
  
***************
*** 386,411 ****
    gcv.function = GXxor;
    new->plotter.dragGC = XtGetGC(new, GCForeground | GCFunction, &gcv);
  
-   ac = 0;
-   XtSetArg(al[ac], XtNvertical, False); ac++;
    new->plotter.xaxis = (AtAxisObject)
!     XtCreateWidget("xaxis", atAxisObjectClass, new, al, ac);
  
    new->plotter.yaxis = (AtAxisObject)
      XtCreateWidget("yaxis", atAxisObjectClass, new, NULL, 0);
  
    new->plotter.y2axis = (AtAxisObject)
!     XtCreateWidget("y2axis", atAxisObjectClass, new, NULL, 0);
  
    ac = 0;
    XtSetArg(al[ac], XtNmirror, True); ac++;
    XtSetArg(al[ac], XtNautoNumber, False); ac++;
-   new->plotter.yframeAxis = (AtAxisObject)
-     XtCreateWidget("yframeAxis", atAxisObjectClass, new, al, ac);
    XtSetArg(al[ac], XtNvertical, False); ac++;
    new->plotter.xframeAxis = (AtAxisObject)
!     XtCreateWidget("xframeAxis", atAxisObjectClass, new, al, ac);
  
    XtAddCallback(new->plotter.xaxis, XtNaxisNeedsRedraw, AxisNeedsRedraw, new);
    XtAddCallback(new->plotter.yaxis, XtNaxisNeedsRedraw, AxisNeedsRedraw, new);
    XtAddCallback(new->plotter.y2axis, XtNaxisNeedsRedraw, AxisNeedsRedraw, new);
--- 378,438 ----
    gcv.function = GXxor;
    new->plotter.dragGC = XtGetGC(new, GCForeground | GCFunction, &gcv);
  
    new->plotter.xaxis = (AtAxisObject)
!     XtVaCreateWidget("xaxis", atAxisObjectClass, (Widget)new,
! 			    XtNvertical, False, NULL);
  
    new->plotter.yaxis = (AtAxisObject)
      XtCreateWidget("yaxis", atAxisObjectClass, new, NULL, 0);
  
+   ac = 0;
+   XtSetArg(al[ac], XtNmirror, True); ac++;
+ 
+   /*
+    * Check the "sub" resources for y2 axis and see if it is displayed...
+    * (This is needed so we can emulate the old default behaviour of X
+    * and Y axes displayed, Y2 not displayed.  We check the resource
+    * file before we create y2axis so we can override the default True
+    * if we need to!)
+    */
+   {
+     static Boolean disp;
+     static XtResource disp_res = {
+       XtNdisplayed, XtCDisplayed, XtRBoolean, sizeof(Boolean), 0,
+       XtRImmediate, (caddr_t)False }; /* NB - default = FALSE!!! */
+ 
+     XtGetSubresources(new, &disp, "y2axis", "AtAxis", &disp_res, 1,
+ 		      NULL, 0);
+     if (!disp) {
+       XtSetArg(al[ac], XtNdisplayed, False);
+       ac++;
+     }
+   }
    new->plotter.y2axis = (AtAxisObject)
!     XtCreateWidget("y2axis", atAxisObjectClass, new, al, ac); 
  
    ac = 0;
    XtSetArg(al[ac], XtNmirror, True); ac++;
    XtSetArg(al[ac], XtNautoNumber, False); ac++;
    XtSetArg(al[ac], XtNvertical, False); ac++;
    new->plotter.xframeAxis = (AtAxisObject)
!     XtCreateManagedWidget("xframeAxis", atAxisObjectClass, new, al, ac);
  
+   ac--;				/* y axes are not vertical! */
+   new->plotter.yframeAxis = (AtAxisObject)
+     XtCreateManagedWidget("yframeAxis", atAxisObjectClass, new, al, ac);
+ 
+   /* Y2 frame is neither mirrored nor vertical! */
+   new->plotter.y2frameAxis = (AtAxisObject)
+     XtVaCreateManagedWidget("y2frameAxis", atAxisObjectClass, (Widget)new,
+ 			    XtNautoNumber, False, NULL);
+ 
+   if (NUMCHILDREN(new) != FIRST_PUBLIC_CHILD || 
+       new->plotter.y2frameAxis != (AtAxisObject)CHILD(new, CHILD_Y2FRAMEAXIS)) {
+     PlotterError(new, 
+ 		 "AtPlotter Initialize: Private children in public spaces!");
+   }
+   
    XtAddCallback(new->plotter.xaxis, XtNaxisNeedsRedraw, AxisNeedsRedraw, new);
    XtAddCallback(new->plotter.yaxis, XtNaxisNeedsRedraw, AxisNeedsRedraw, new);
    XtAddCallback(new->plotter.y2axis, XtNaxisNeedsRedraw, AxisNeedsRedraw, new);
***************
*** 454,475 ****
    }
      
    /* Draw the Axes, rescaling if necessary */
!   AtAxisDraw(XtDisplay(pw), XtWindow(pw), pw->plotter.xaxis, 
! 	     pw->core.background_pixel);
!   AtAxisDraw(XtDisplay(pw), XtWindow(pw), pw->plotter.yaxis,
! 	     pw->core.background_pixel);
!   if (pw->plotter.showY2Axis)
      AtAxisDraw(XtDisplay(pw), XtWindow(pw), pw->plotter.y2axis,
  	       pw->core.background_pixel);
    if (pw->plotter.framedAxes) {
      AtAxisDraw(XtDisplay(pw), XtWindow(pw), pw->plotter.xframeAxis,
  	       pw->core.background_pixel);
!     AtAxisDraw(XtDisplay(pw), XtWindow(pw), pw->plotter.yframeAxis,
! 	       pw->core.background_pixel);
    }
      
    /* Draw the axis grids */
!   if (pw->plotter.xaxis->axis.drawGrid)  {
      if (region == NULL)
        AtAxisDrawGrid(XtDisplay(pw), XtWindow(pw), pw->plotter.xaxis,
  		     pw->plotter.layout.y1, pw->plotter.layout.y2);
--- 481,509 ----
    }
      
    /* Draw the Axes, rescaling if necessary */
!   if (NTHCHILDISDISPLAYED(pw, CHILD_XAXIS))
!     AtAxisDraw(XtDisplay(pw), XtWindow(pw), pw->plotter.xaxis, 
! 	       pw->core.background_pixel);
!   if (NTHCHILDISDISPLAYED(pw, CHILD_YAXIS))
!     AtAxisDraw(XtDisplay(pw), XtWindow(pw), pw->plotter.yaxis,
! 	       pw->core.background_pixel);
!   if (NTHCHILDISDISPLAYED(pw, CHILD_Y2AXIS))
      AtAxisDraw(XtDisplay(pw), XtWindow(pw), pw->plotter.y2axis,
  	       pw->core.background_pixel);
    if (pw->plotter.framedAxes) {
      AtAxisDraw(XtDisplay(pw), XtWindow(pw), pw->plotter.xframeAxis,
  	       pw->core.background_pixel);
!     if (!NTHCHILDISDISPLAYED(pw, CHILD_Y2AXIS))
!       AtAxisDraw(XtDisplay(pw), XtWindow(pw), pw->plotter.yframeAxis,
! 		 pw->core.background_pixel);
!     if (!NTHCHILDISDISPLAYED(pw, CHILD_YAXIS))
!       AtAxisDraw(XtDisplay(pw), XtWindow(pw), pw->plotter.y2frameAxis,
! 		 pw->core.background_pixel);
    }
      
    /* Draw the axis grids */
!   if (NTHCHILDISDISPLAYED(pw, CHILD_XAXIS) && 
!       pw->plotter.xaxis->axis.drawGrid)  {
      if (region == NULL)
        AtAxisDrawGrid(XtDisplay(pw), XtWindow(pw), pw->plotter.xaxis,
  		     pw->plotter.layout.y1, pw->plotter.layout.y2);
***************
*** 478,484 ****
  			   pw->plotter.layout.y1, pw->plotter.layout.y2,
  			   region);
    }
!   if (pw->plotter.yaxis->axis.drawGrid)  {
      if (region == NULL)
        AtAxisDrawGrid(XtDisplay(pw), XtWindow(pw), pw->plotter.yaxis,
  		     pw->plotter.layout.x1, pw->plotter.layout.x2);
--- 512,519 ----
  			   pw->plotter.layout.y1, pw->plotter.layout.y2,
  			   region);
    }
!   if (NTHCHILDISDISPLAYED(pw, CHILD_YAXIS) && 
!       pw->plotter.yaxis->axis.drawGrid)  {
      if (region == NULL)
        AtAxisDrawGrid(XtDisplay(pw), XtWindow(pw), pw->plotter.yaxis,
  		     pw->plotter.layout.x1, pw->plotter.layout.x2);
***************
*** 487,493 ****
  			   pw->plotter.layout.x1, pw->plotter.layout.x2,
  			   region);
    }
!   if (pw->plotter.showY2Axis && pw->plotter.y2axis->axis.drawGrid)  {
      if (region == NULL)
        AtAxisDrawGrid(XtDisplay(pw), XtWindow(pw), pw->plotter.y2axis,
  		     pw->plotter.layout.x2, pw->plotter.layout.x1);
--- 522,528 ----
  			   pw->plotter.layout.x1, pw->plotter.layout.x2,
  			   region);
    }
!   if (NTHCHILDISDISPLAYED(pw, CHILD_Y2AXIS) && pw->plotter.y2axis->axis.drawGrid)  {
      if (region == NULL)
        AtAxisDrawGrid(XtDisplay(pw), XtWindow(pw), pw->plotter.y2axis,
  		     pw->plotter.layout.x2, pw->plotter.layout.x1);
***************
*** 508,514 ****
      }
    }
    else /* draw children according to birth */
!     for(i=0; i<pw->composite.num_children; i++)
        if (NTHCHILDISDISPLAYED(pw, i)) 
  	REDRAWCHILD(pw, i, region);
      
--- 543,549 ----
      }
    }
    else /* draw children according to birth */
!     for (i = FIRST_PUBLIC_CHILD; i < NUMCHILDREN(pw); i++)
        if (NTHCHILDISDISPLAYED(pw, i)) 
  	REDRAWCHILD(pw, i, region);
      
***************
*** 579,585 ****
      ResizeLegend(pw);
  	
      /* Resize the plots */
!     for(i=0; i<pw->composite.num_children; i++)
        if (NTHCHILDISDISPLAYED(pw, i))
  	RESIZECHILD(pw,i);
    }
--- 614,620 ----
      ResizeLegend(pw);
  	
      /* Resize the plots */
!     for (i = FIRST_PUBLIC_CHILD; i < NUMCHILDREN(pw); i++)
        if (NTHCHILDISDISPLAYED(pw, i))
  	RESIZECHILD(pw,i);
    }
***************
*** 615,624 ****
    if (Changed(rankChildren))
      redraw = True;
    
-   if (Changed(showY2Axis) || Changed(showLegend)) {
-     layout = True;
-     redraw = True;
-   }
    if (Changed(autoScale) && new->plotter.autoScale) {
      Autoscale(new);
      redraw = True;
--- 650,655 ----
***************
*** 677,700 ****
      AtWarning(w, "Attempt to add child that is not a subclass of AtPlot");
      
    /* call the superclass's insert_child proc to actually add the child */
!   /* but don't let the axes get into the list.  They'd just clutter it up */
!   if (XtIsSubclass(w, atPlotWidgetClass))  {
!     (*superclass->composite_class.insert_child)(w);
      RecalcLegend(p);
!     RankOrderChildren(w); /* maintain this list even if no rank order
! 			     is requested, so if rank order is wanted
! 			     later the list is ready. This will also
! 			     create the nonbar_children list which is 
! 			     used to draw the none barchart children.
! 			     After incremental update to barcharts,
! 			     the objects in this list (e.g. XYPlots)
! 			     are drawn, so that they will always be
! 			     on top of barcharts and therefore visible. 
! 			     */
!   
      if (p->plotter.autoScale) Autoscale(p);
    }
-   if (XtIsRealized(p)) Redraw(p, (Region) NULL);
  }
  
  static void DeleteChild(Widget w)
--- 708,725 ----
      AtWarning(w, "Attempt to add child that is not a subclass of AtPlot");
      
    /* call the superclass's insert_child proc to actually add the child */
!   (*superclass->composite_class.insert_child)(w);
!   if (XtIsSubclass(w, atPlotWidgetClass)) {
      RecalcLegend(p);
!     RankOrderChildren(w);
!     /*
!      * maintain this list even if no rank order is requested, so if
!      * rank order is wanted later the list is ready.
!      */
!     
      if (p->plotter.autoScale) Autoscale(p);
+     if (XtIsRealized(p)) Redraw(p, (Region) NULL);
    }
  }
  
  static void DeleteChild(Widget w)
***************
*** 705,712 ****
    /* if a plot is selected, figure out which child is being deleted */
    /* and adjust the selected plot as necessary */
      
!   if (p->plotter.legendItem != -1) {
!     for(i=0; i<NUMCHILDREN(p); i++) 
        if (CHILD(p, i) == w) break;
      if (i == p->plotter.legendItem)
        p->plotter.legendItem = -1;
--- 730,737 ----
    /* if a plot is selected, figure out which child is being deleted */
    /* and adjust the selected plot as necessary */
      
!   if (XtIsSubclass(w, atPlotWidgetClass) && p->plotter.legendItem != -1) {
!     for(i=FIRST_PUBLIC_CHILD; i<NUMCHILDREN(p); i++) 
        if (CHILD(p, i) == w) break;
      if (i == p->plotter.legendItem)
        p->plotter.legendItem = -1;
***************
*** 714,731 ****
        p->plotter.legendItem -= 1;
    }
  
-   RankOrderRemove(w);
- 
    /* call the superclass's delete_child proc to actually delete the child */
!   if (XtIsSubclass(w, atPlotWidgetClass))  {
!     (*superclass->composite_class.delete_child)(w);
      RecalcLegend(p);
      if (p->plotter.autoScale) Autoscale(p);
    }
-   if (XtIsRealized(p)) Redraw(p, (Region) NULL);
  }
  
  
  void AtPlotterLayout(AtPlotterWidget w)
  {
    int approxheight, approxwidth;
--- 739,756 ----
        p->plotter.legendItem -= 1;
    }
  
    /* call the superclass's delete_child proc to actually delete the child */
!   (*superclass->composite_class.delete_child)(w);
!   if (XtIsSubclass(w, atPlotWidgetClass)) {
      RecalcLegend(p);
+     RankOrderRemove(w);
      if (p->plotter.autoScale) Autoscale(p);
+     if (XtIsRealized(p)) Redraw(p, (Region) NULL);
    }
  }
  
  
+ 
  void AtPlotterLayout(AtPlotterWidget w)
  {
    int approxheight, approxwidth;
***************
*** 735,741 ****
    AtAxisObject y2axis = w->plotter.y2axis;
    Boolean floatx, floaty;
    int originx, originy;
!   double xmin, xmax, ymin, ymax;
    int i;
      
    w->plotter.layout.x1 = w->plotter.marginWidth;
--- 760,766 ----
    AtAxisObject y2axis = w->plotter.y2axis;
    Boolean floatx, floaty;
    int originx, originy;
!   double xmin, xmax, ymin, ymax, y2min, y2max;
    int i;
      
    w->plotter.layout.x1 = w->plotter.marginWidth;
***************
*** 777,793 ****
    else
      floaty = False;
  
!   AtAxisComputeTicSpacing(w->plotter.xaxis, approxwidth);
!   AtAxisComputeTicSpacing(w->plotter.yaxis, approxheight);
!   if (w->plotter.showY2Axis)
      AtAxisComputeTicSpacing(w->plotter.y2axis, approxheight);
  
    AtAxisGetBounds(w->plotter.xaxis, &xmin, &xmax);
    AtAxisGetBounds(w->plotter.yaxis, &ymin, &ymax);
  
    if (w->plotter.framedAxes) {
      AtAxisChangeBounds(w->plotter.xframeAxis, xmin, xmax);
      AtAxisChangeBounds(w->plotter.yframeAxis, ymin, ymax);
      /* mildly illegal... */
      AtAxisChangeNumbering(w->plotter.xframeAxis,
  			  w->plotter.xaxis->axis.ticInterval,
--- 802,822 ----
    else
      floaty = False;
  
!   if (NTHCHILDISDISPLAYED(w, CHILD_XAXIS))
!     AtAxisComputeTicSpacing(w->plotter.xaxis, approxwidth);
!   if (NTHCHILDISDISPLAYED(w, CHILD_YAXIS))
!     AtAxisComputeTicSpacing(w->plotter.yaxis, approxheight);
!   if (NTHCHILDISDISPLAYED(w, CHILD_Y2AXIS))
      AtAxisComputeTicSpacing(w->plotter.y2axis, approxheight);
  
    AtAxisGetBounds(w->plotter.xaxis, &xmin, &xmax);
    AtAxisGetBounds(w->plotter.yaxis, &ymin, &ymax);
+   AtAxisGetBounds(w->plotter.y2axis, &y2min, &y2max);
  
    if (w->plotter.framedAxes) {
      AtAxisChangeBounds(w->plotter.xframeAxis, xmin, xmax);
      AtAxisChangeBounds(w->plotter.yframeAxis, ymin, ymax);
+     AtAxisChangeBounds(w->plotter.y2frameAxis, y2min, y2max);
      /* mildly illegal... */
      AtAxisChangeNumbering(w->plotter.xframeAxis,
  			  w->plotter.xaxis->axis.ticInterval,
***************
*** 795,813 ****
      AtAxisChangeNumbering(w->plotter.yframeAxis,
  			  w->plotter.yaxis->axis.ticInterval,
  			  w->plotter.yaxis->axis.subtics);
    }
  
!   xaxiswidth = AtAxisWidth(w->plotter.xaxis);
!   yaxiswidth = AtAxisWidth(w->plotter.yaxis);
!   if (w->plotter.showY2Axis)
      y2axiswidth = AtAxisWidth(w->plotter.y2axis);
  
    if (!floaty) w->plotter.layout.x1 += yaxiswidth;
    if (!floatx) w->plotter.layout.y2 -= xaxiswidth;
!   if (w->plotter.showY2Axis)
!     w->plotter.layout.x2 -= y2axiswidth;
    if (w->plotter.framedAxes) {
!     w->plotter.layout.x2 -= AtAxisWidth(w->plotter.yframeAxis);
      w->plotter.layout.y1 += AtAxisWidth(w->plotter.xframeAxis);
    }
  
--- 824,854 ----
      AtAxisChangeNumbering(w->plotter.yframeAxis,
  			  w->plotter.yaxis->axis.ticInterval,
  			  w->plotter.yaxis->axis.subtics);
+     AtAxisChangeNumbering(w->plotter.y2frameAxis,
+ 			  w->plotter.y2axis->axis.ticInterval,
+ 			  w->plotter.y2axis->axis.subtics);
    }
  
!   xaxiswidth = yaxiswidth = y2axiswidth = 0;
!   
!   if (NTHCHILDISDISPLAYED(w, CHILD_XAXIS))
!     xaxiswidth = AtAxisWidth(w->plotter.xaxis);
!   if (NTHCHILDISDISPLAYED(w, CHILD_YAXIS))
!     yaxiswidth = AtAxisWidth(w->plotter.yaxis);
!   if (NTHCHILDISDISPLAYED(w, CHILD_Y2AXIS))
      y2axiswidth = AtAxisWidth(w->plotter.y2axis);
  
    if (!floaty) w->plotter.layout.x1 += yaxiswidth;
    if (!floatx) w->plotter.layout.y2 -= xaxiswidth;
!   w->plotter.layout.x2 -= y2axiswidth;
    if (w->plotter.framedAxes) {
!     int ydisp = NTHCHILDISDISPLAYED(w, CHILD_YAXIS);
!     int y2disp = NTHCHILDISDISPLAYED(w, CHILD_Y2AXIS);
!     
!     if (ydisp && !y2disp)
!       w->plotter.layout.x2 -= AtAxisWidth(w->plotter.yframeAxis);
!     if (y2disp && !ydisp)
!       w->plotter.layout.x1 += AtAxisWidth(w->plotter.y2frameAxis);
      w->plotter.layout.y1 += AtAxisWidth(w->plotter.xframeAxis);
    }
  
***************
*** 820,832 ****
  
    if (w->plotter.showLegend) ResizeLegend(w);
  
!   AtAxisSetLocation(w->plotter.xaxis, w->plotter.layout.x1,
! 		    w->plotter.layout.y2, w->plotter.layout.x2,
! 		    w->plotter.layout.y2);
!   AtAxisSetLocation(w->plotter.yaxis, w->plotter.layout.x1,
! 		    w->plotter.layout.y1, w->plotter.layout.x1,
! 		    w->plotter.layout.y2);
!   if (w->plotter.showY2Axis)
      AtAxisSetLocation(w->plotter.y2axis,
  		      w->plotter.layout.x2, w->plotter.layout.y1,
  		      w->plotter.layout.x2, w->plotter.layout.y2);
--- 861,875 ----
  
    if (w->plotter.showLegend) ResizeLegend(w);
  
!   if (NTHCHILDISDISPLAYED(w, CHILD_XAXIS))
!     AtAxisSetLocation(w->plotter.xaxis, w->plotter.layout.x1,
! 		      w->plotter.layout.y2, w->plotter.layout.x2,
! 		      w->plotter.layout.y2);
!   if (NTHCHILDISDISPLAYED(w, CHILD_YAXIS))
!     AtAxisSetLocation(w->plotter.yaxis, w->plotter.layout.x1,
! 		      w->plotter.layout.y1, w->plotter.layout.x1,
! 		      w->plotter.layout.y2);
!   if (NTHCHILDISDISPLAYED(w, CHILD_Y2AXIS))
      AtAxisSetLocation(w->plotter.y2axis,
  		      w->plotter.layout.x2, w->plotter.layout.y1,
  		      w->plotter.layout.x2, w->plotter.layout.y2);
***************
*** 837,842 ****
--- 880,888 ----
      AtAxisSetLocation(w->plotter.yframeAxis,
  		      w->plotter.layout.x2, w->plotter.layout.y1,
  		      w->plotter.layout.x2, w->plotter.layout.y2);
+     AtAxisSetLocation(w->plotter.y2frameAxis,
+ 		      w->plotter.layout.x1, w->plotter.layout.y1,
+ 		      w->plotter.layout.x1, w->plotter.layout.y2);
    }
  
    /* The axes are the right length now, but the location may be wrong. */
***************
*** 915,920 ****
--- 961,972 ----
  	AtAxisChangeNumbering(w->plotter.yframeAxis,
  			      w->plotter.yaxis->axis.ticInterval,
  			      w->plotter.yaxis->axis.subtics);
+ 	AtAxisSetLocation(w->plotter.y2frameAxis, 
+ 			  w->plotter.layout.x1,w->plotter.layout.y1,
+ 			  w->plotter.layout.x1,w->plotter.layout.y2);
+ 	AtAxisChangeNumbering(w->plotter.y2frameAxis,
+ 			      w->plotter.y2axis->axis.ticInterval,
+ 			      w->plotter.y2axis->axis.subtics);
  	AtAxisSetLocation(w->plotter.xframeAxis,
  			  w->plotter.layout.x1,w->plotter.layout.y1,
  			  w->plotter.layout.x2,w->plotter.layout.y1);
***************
*** 948,953 ****
--- 1000,1008 ----
  	AtAxisSetLocation(w->plotter.xframeAxis, 
  			  w->plotter.layout.x1,w->plotter.layout.y1,
  			  w->plotter.layout.x2,w->plotter.layout.y1);
+ 	AtAxisSetLocation(w->plotter.y2frameAxis, 
+ 			  w->plotter.layout.x1,w->plotter.layout.y1,
+ 			  w->plotter.layout.x1,w->plotter.layout.y2);
  	AtAxisChangeNumbering(w->plotter.xframeAxis,
  			      w->plotter.xaxis->axis.ticInterval,
  			      w->plotter.xaxis->axis.subtics);
***************
*** 960,968 ****
      AtAxisChangeNumbering(w->plotter.yframeAxis,
  			  w->plotter.yaxis->axis.ticInterval,
  			  w->plotter.yaxis->axis.subtics);
    }
      
!   for(i=0; i<NUMCHILDREN(w); i++)
      if (NTHCHILDISDISPLAYED(w, i))
        RESIZECHILD(w, i);
  }
--- 1015,1027 ----
      AtAxisChangeNumbering(w->plotter.yframeAxis,
  			  w->plotter.yaxis->axis.ticInterval,
  			  w->plotter.yaxis->axis.subtics);
+     AtAxisChangeBounds(w->plotter.y2frameAxis, y2min, y2max);
+     AtAxisChangeNumbering(w->plotter.y2frameAxis,
+ 			  w->plotter.y2axis->axis.ticInterval,
+ 			  w->plotter.y2axis->axis.subtics);
    }
      
!   for(i=FIRST_PUBLIC_CHILD; i<NUMCHILDREN(w); i++)
      if (NTHCHILDISDISPLAYED(w, i))
        RESIZECHILD(w, i);
  }
***************
*** 1016,1024 ****
  
    if (Changed(boundingBox.xmin) || Changed(boundingBox.xmax) ||
        Changed(boundingBox.ymin) || Changed(boundingBox.ymax) ||
!       Changed(useY2Axis)) { 
      parent->plotter.newBoundingBox = True;
    }
  
    if (!XtWindow(parent)) { return False;  }
    
--- 1075,1088 ----
  
    if (Changed(boundingBox.xmin) || Changed(boundingBox.xmax) ||
        Changed(boundingBox.ymin) || Changed(boundingBox.ymax) ||
!       Changed(useY2Axis)) {
      parent->plotter.newBoundingBox = True;
    }
+   
+   if (Changed(displayed) && XtIsSubclass(current, atAxisObjectClass)) { 
+     newc->plotter.needsRedraw = True;
+     parent->plotter.newBoundingBox = True;
+   }
  
    if (!XtWindow(parent)) { return False;  }
    
***************
*** 1064,1070 ****
  	    }
  	  }
  	  else   /* draw children according to birthorder */
! 	    for (j = 0; j < parent->composite.num_children; j++)
  	      if (NTHCHILDISDISPLAYED(parent, j))
  		BARREDRAW(parent, parent->composite.children[j], &rlist[i]);
  	}
--- 1128,1134 ----
  	    }
  	  }
  	  else   /* draw children according to birthorder */
! 	    for (j = FIRST_PUBLIC_CHILD; j < NUMCHILDREN(parent); j++)
  	      if (NTHCHILDISDISPLAYED(parent, j))
  		BARREDRAW(parent, parent->composite.children[j], &rlist[i]);
  	}
***************
*** 1089,1095 ****
  	  }
  	}
  	else   /* draw children according to birthorder */
! 	  for (i = 0; i < parent->composite.num_children; i++)
  	    if (NTHCHILDISDISPLAYED(parent, i))
  	      BARDRAWINC(parent, parent->composite.children[i], 
  			 parent->plotter.clip_region);
--- 1153,1159 ----
  	  }
  	}
  	else   /* draw children according to birthorder */
! 	  for (i = FIRST_PUBLIC_CHILD; i < NUMCHILDREN(parent); i++)
  	    if (NTHCHILDISDISPLAYED(parent, i))
  	      BARDRAWINC(parent, parent->composite.children[i], 
  			 parent->plotter.clip_region);
***************
*** 1113,1127 ****
  {
    int i;
      
!   AtAxisChangeBounds(pw->plotter.xaxis, xmin, xmax);
!   AtAxisChangeBounds(pw->plotter.yaxis, ymin, ymax);
!   if (pw->plotter.showY2Axis)
      AtAxisChangeBounds(pw->plotter.y2axis, y2min, y2max);
  
    if(XtIsRealized(pw))
      AtPlotterLayout(pw);
      
!   for(i=0; i<NUMCHILDREN(pw); i++)
      if (NTHCHILDISDISPLAYED(pw, i))
        RESCALECHILD(pw, i);
  }
--- 1177,1193 ----
  {
    int i;
      
!   if (NTHCHILDISDISPLAYED(pw, CHILD_XAXIS))
!     AtAxisChangeBounds(pw->plotter.xaxis, xmin, xmax);
!   if (NTHCHILDISDISPLAYED(pw, CHILD_YAXIS))
!     AtAxisChangeBounds(pw->plotter.yaxis, ymin, ymax);
!   if (NTHCHILDISDISPLAYED(pw, CHILD_Y2AXIS))
      AtAxisChangeBounds(pw->plotter.y2axis, y2min, y2max);
  
    if(XtIsRealized(pw))
      AtPlotterLayout(pw);
      
!   for(i=FIRST_PUBLIC_CHILD; i<NUMCHILDREN(pw); i++)
      if (NTHCHILDISDISPLAYED(pw, i))
        RESCALECHILD(pw, i);
  }
***************
*** 1135,1141 ****
    Boolean firstx = True, firsty = True, firsty2 = True;
    double tmp;
  
!   for(i = 0; i < NUMCHILDREN(pw); i++) {
      if (!NTHCHILDISDISPLAYED(pw, i)) continue; /* Don't scale on undisplayed */
      /* if bounding box doesn't make sense, ignore it! */
      /* by default, text plots have non-sensical boxes */
--- 1201,1207 ----
    Boolean firstx = True, firsty = True, firsty2 = True;
    double tmp;
  
!   for(i = FIRST_PUBLIC_CHILD; i < NUMCHILDREN(pw); i++) {
      if (!NTHCHILDISDISPLAYED(pw, i)) continue; /* Don't scale on undisplayed */
      /* if bounding box doesn't make sense, ignore it! */
      /* by default, text plots have non-sensical boxes */
***************
*** 1260,1266 ****
    h = AtTextHeight(w->plotter.legendTitleText);
    h += w->plotter.marginHeight;
      
!   for(i = 0; i < NUMCHILDREN(w); i++) {
      if (!NTHCHILDISDISPLAYED(w, i)) continue; 
      c = CONSTRAINT(w,i);
      if (i == w->plotter.legendItem)
--- 1326,1332 ----
    h = AtTextHeight(w->plotter.legendTitleText);
    h += w->plotter.marginHeight;
      
!   for(i = FIRST_PUBLIC_CHILD; i < NUMCHILDREN(w); i++) {
      if (!NTHCHILDISDISPLAYED(w, i)) continue; 
      c = CONSTRAINT(w,i);
      if (i == w->plotter.legendItem)
***************
*** 1319,1325 ****
  		      AtTextHeight(w->plotter.legendTitleText));
  
    y += AtTextHeight(w->plotter.legendTitleText) + w->plotter.marginWidth;
!   for(i = 0; i < NUMCHILDREN(w); i++ ) {
      if (!NTHCHILDISDISPLAYED(w, i)) continue; 
      t = CONSTRAINT(w,i)->plotter.legendText;
      if (t != NULL) {
--- 1385,1391 ----
  		      AtTextHeight(w->plotter.legendTitleText));
  
    y += AtTextHeight(w->plotter.legendTitleText) + w->plotter.marginWidth;
!   for(i = FIRST_PUBLIC_CHILD; i < NUMCHILDREN(w); i++ ) {
      if (!NTHCHILDISDISPLAYED(w, i)) continue; 
      t = CONSTRAINT(w,i)->plotter.legendText;
      if (t != NULL) {
***************
*** 1440,1446 ****
      return;
    }
      
!   for(i=0; i < NUMCHILDREN(pw); i++) {
      if (!NTHCHILDISDISPLAYED(pw, i)) continue; 
      t = CONSTRAINT(pw,i)->plotter.legendText;
      if (t != NULL) {
--- 1506,1512 ----
      return;
    }
      
!   for(i=FIRST_PUBLIC_CHILD; i < NUMCHILDREN(pw); i++) {
      if (!NTHCHILDISDISPLAYED(pw, i)) continue; 
      t = CONSTRAINT(pw,i)->plotter.legendText;
      if (t != NULL) {
***************
*** 1575,1590 ****
  	  (pw->plotter.dragwidth*pw->plotter.dragwidth +
  	   pw->plotter.dragheight*pw->plotter.dragheight > 16)) {
  	RectangleStruct r;
! 	r[0].pixelx = pw->plotter.clickx;
! 	r[0].pixely = pw->plotter.clicky;
! 	r[0].x = xscale(pw,pw->plotter.clickx);
! 	r[0].y = yscale(pw, pw->plotter.clicky);
! 	if (pw->plotter.showY2Axis) 
  	  r[0].y2= y2scale(pw, pw->plotter.clicky);
- 	r[1].x = xscale(pw,pw->plotter.clickx+pw->plotter.dragwidth);
- 	r[1].y = yscale(pw,pw->plotter.clicky+pw->plotter.dragheight);
- 	if (pw->plotter.showY2Axis)
  	  r[1].y2=y2scale(pw, pw->plotter.clicky+pw->plotter.dragheight);
  	r[0].pixelx = pw->plotter.clickx;
  	r[0].pixely = pw->plotter.clicky;
  	r[1].pixelx = event->x;
--- 1641,1659 ----
  	  (pw->plotter.dragwidth*pw->plotter.dragwidth +
  	   pw->plotter.dragheight*pw->plotter.dragheight > 16)) {
  	RectangleStruct r;
! 	bzero(&r, sizeof r); 
! 	if (NTHCHILDISDISPLAYED(pw, CHILD_XAXIS)) {
! 	  r[0].x = xscale(pw, pw->plotter.clickx);
! 	  r[1].x = xscale(pw, pw->plotter.clickx+pw->plotter.dragwidth);
! 	}
! 	if (NTHCHILDISDISPLAYED(pw, CHILD_YAXIS)) {
! 	  r[0].y = yscale(pw, pw->plotter.clicky);
! 	  r[1].y = yscale(pw, pw->plotter.clicky+pw->plotter.dragheight);
! 	}
! 	if (NTHCHILDISDISPLAYED(pw, CHILD_Y2AXIS)) {
  	  r[0].y2= y2scale(pw, pw->plotter.clicky);
  	  r[1].y2=y2scale(pw, pw->plotter.clicky+pw->plotter.dragheight);
+ 	}
  	r[0].pixelx = pw->plotter.clickx;
  	r[0].pixely = pw->plotter.clicky;
  	r[1].pixelx = event->x;
***************
*** 1593,1603 ****
        }
        else {
  	PointStruct point;
  	point.pixelx = event->x;
  	point.pixely = event->y;
! 	point.x = xscale(pw, event->x);
! 	point.y = yscale(pw, event->y);
! 	if (pw->plotter.showY2Axis) point.y2 = y2scale(pw, event->y);
  	XtCallCallbacks(pw, XtNclickCallback, (caddr_t)&point);
        }
      }
--- 1662,1673 ----
        }
        else {
  	PointStruct point;
+ 	bzero(&point, sizeof point);
  	point.pixelx = event->x;
  	point.pixely = event->y;
! 	if (NTHCHILDISDISPLAYED(pw, CHILD_XAXIS)) point.x = xscale(pw, event->x);
! 	if (NTHCHILDISDISPLAYED(pw, CHILD_YAXIS)) point.y = yscale(pw, event->y);
! 	if (NTHCHILDISDISPLAYED(pw, CHILD_Y2AXIS)) point.y2 = y2scale(pw, event->y);
  	XtCallCallbacks(pw, XtNclickCallback, (caddr_t)&point);
        }
      }
***************
*** 1641,1651 ****
    PointStruct point;
      
    if (InPlottingRegion(pw,event)) {
      point.pixelx = event->x;
      point.pixely = event->y;
!     point.x = xscale(pw,event->x);
!     point.y = yscale(pw, event->y);
!     if (pw->plotter.showY2Axis) point.y2 = y2scale(pw,event->y);
      XtCallCallbacks((Widget)pw, XtNmotionCallback, (caddr_t)&point);
    }
  }
--- 1711,1722 ----
    PointStruct point;
      
    if (InPlottingRegion(pw,event)) {
+     bzero(&point, sizeof point); 
      point.pixelx = event->x;
      point.pixely = event->y;
!     if (NTHCHILDISDISPLAYED(pw, CHILD_XAXIS)) point.x = xscale(pw,event->x);
!     if (NTHCHILDISDISPLAYED(pw, CHILD_YAXIS)) point.y = yscale(pw, event->y);
!     if (NTHCHILDISDISPLAYED(pw, CHILD_Y2AXIS)) point.y2 = y2scale(pw,event->y);
      XtCallCallbacks((Widget)pw, XtNmotionCallback, (caddr_t)&point);
    }
  }
***************
*** 1675,1683 ****
  
  AtPlotWidget AtPlotterGetLastPlot(AtPlotterWidget w)
  {
!   if (w->composite.num_children > 0)
!     return (AtPlotWidget) 
!       w->composite.children[w->composite.num_children - 1];
    else
      return NULL;
  }
--- 1746,1753 ----
  
  AtPlotWidget AtPlotterGetLastPlot(AtPlotterWidget w)
  {
!   if (NUMCHILDREN(w) > FIRST_PUBLIC_CHILD)
!     return (AtPlotWidget)CHILD(w, NUMCHILDREN(w) - 1);
    else
      return NULL;
  }
***************
*** 1707,1712 ****
--- 1777,1787 ----
    return w->plotter.yframeAxis;
  }
  
+ AtAxisObject AtPlotterGetY2FrameAxis(AtPlotterWidget w)
+ {
+   return w->plotter.y2frameAxis;
+ }
+ 
  void AtPlotterGetPlotExtents(AtPlotterWidget w, int *xmin, int *xmax,
  			     int *ymin, int *ymax)
  {
***************
*** 1751,1757 ****
    if(XtIsRealized(w))
      AtPlotterLayout(w);
      
!   for(i=0; i<NUMCHILDREN(w); i++)
      if (NTHCHILDISDISPLAYED(w, i)) 
        RESCALECHILD(w, i);
  
--- 1826,1832 ----
    if(XtIsRealized(w))
      AtPlotterLayout(w);
      
!   for(i=FIRST_PUBLIC_CHILD; i<NUMCHILDREN(w); i++)
      if (NTHCHILDISDISPLAYED(w, i)) 
        RESCALECHILD(w, i);
  
***************
*** 1771,1777 ****
  
    if(XtIsRealized(w))  {
      AtPlotterLayout(w);
!     for(i=0; i<NUMCHILDREN(w); i++)
        if (NTHCHILDISDISPLAYED(w, i)) 
  	RESCALECHILD(w, i);
      Redraw(w, (Region) NULL);
--- 1846,1852 ----
  
    if(XtIsRealized(w))  {
      AtPlotterLayout(w);
!     for(i=FIRST_PUBLIC_CHILD; i<NUMCHILDREN(w); i++)
        if (NTHCHILDISDISPLAYED(w, i)) 
  	RESCALECHILD(w, i);
      Redraw(w, (Region) NULL);
***************
*** 1782,1788 ****
  {
    int i;
  
!   for(i = 0; i < NUMCHILDREN(pw); i++)
      XtDestroyWidget(CHILD(pw,i));
  }
  
--- 1857,1863 ----
  {
    int i;
  
!   for(i = FIRST_PUBLIC_CHILD; i < NUMCHILDREN(pw); i++)
      XtDestroyWidget(CHILD(pw,i));
  }
  
***************
*** 1791,1797 ****
  {
    int i;
  
!   for(i = 0; i < NUMCHILDREN(pw); i++)
      if (NTHCHILDISDISPLAYED(pw, i)) 
        if (CHECKHIT(pw,i,x,y)) return (AtPlotWidget)CHILD(pw,i);
    
--- 1866,1872 ----
  {
    int i;
  
!   for(i = FIRST_PUBLIC_CHILD; i < NUMCHILDREN(pw); i++)
      if (NTHCHILDISDISPLAYED(pw, i)) 
        if (CHECKHIT(pw,i,x,y)) return (AtPlotWidget)CHILD(pw,i);
    
***************
*** 1828,1833 ****
--- 1903,1910 ----
    Rank *getnode(void);
    Boolean found = False;
  
+   if (!XtIsSubclass(w, atPlotWidgetClass)) return; /* Don't rank axes */
+   
    if (ORDLIST == NULL) {
      ORDLIST = getnode();
      ORDLIST->prev = NULL;
***************
*** 1890,1895 ****
--- 1967,1974 ----
    Rank *locate;
    int i, position;
  
+   if (!XtIsSubclass(w, atPlotWidgetClass)) return; /* Don't rank axes */
+   
    for (locate = ORDLIST; locate != NULL; locate = locate->next)  {
      if (locate->child == w) { 
        if (locate->next)
***************
*** 1910,1912 ****
--- 1989,2000 ----
  {
    return ((Rank*) XtMalloc(sizeof(Rank)));
  }
+ 
+ /*
+  * Need to use eval rather than just c-style as hack-local-variables
+  * is called after the c-mode-hook. 
+  *
+  * Local Variables:
+  * eval: (set-c-style 'GNU)
+  * End:
+  */
*** /tmp/,RCSt1a22231	Tue Apr 16 16:12:41 1991
--- Plotter.h	Tue Apr 16 15:26:54 1991
***************
*** 47,53 ****
  #define XtNfloatingX "floatingX"
  #define XtNfloatingY "floatingY"    
  #define XtNframedAxes "framedAxes"
- #define XtNshowY2Axis "showY2Axis"    
  #define XtNshowLegend "showLegend"    
  #define XtNlegendWidth "legendWidth"
  #define XtNlegendSpacing "legendSpacing"
--- 47,52 ----
***************
*** 61,69 ****
  #define XtNselectCallback "selectCallback"
  #define XtNdoubleSelectCallback "doubleSelectCallback"    
  #define XtNerrorCallback "errorCallback"
- #define XtNxaxis "xaxis"
- #define XtNyaxis "yaxis"
- #define XtNy2axis "y2axis"
      
  #define XtCTitle "Title"
  #define XtCLegendTitle "LegendTitle"    
--- 60,65 ----
***************
*** 74,86 ****
  #define XtCForceAspect "ForceAspect"
  #define XtCFloatingAxes "FloatingAxes"
  #define XtCFramedAxes "FramedAxes"
- #define XtCShowY2Axis "ShowY2Axis"    
  #define XtCShowLegend "ShowLegend"    
  #define XtCLegendWidth "LegendWidth"
  #define XtCMargin "Margin"
  #define XtCRankChildren "RankChildren"
  #define XtCDoubleClickInterval "DoubleClickInterval"    
- #define XtCAxis "Axis"
  
  /* constraint resource names and classes */
  #define XtNdisplayed "displayed"
--- 70,80 ----
***************
*** 99,107 ****
  #define XtCBoundingBox "BoundingBox"
  #define XtCRankOrder "RankOrder"
  
- #define XtRPlotterAxis "PlotterAxis"    
- 
- 
  /* Class record constants */
  
  extern WidgetClass atPlotterWidgetClass;
--- 93,98 ----
***************
*** 137,142 ****
--- 128,134 ----
  extern AtAxisObject AtPlotterGetY2Axis(AtPlotterWidget);
  extern AtAxisObject AtPlotterGetXFrameAxis(AtPlotterWidget);
  extern AtAxisObject AtPlotterGetYFrameAxis(AtPlotterWidget);
+ extern AtAxisObject AtPlotterGetY2FrameAxis(AtPlotterWidget);
  void AtPlotterGetPlotExtents(AtPlotterWidget, int *, int *, int *, int *);
  extern void AtPlotterGetAxisBounds(AtPlotterWidget, double*, double*,
  				   double*, double*);
*** /tmp/,RCSt1a22231	Tue Apr 16 16:12:41 1991
--- PlotterP.h	Fri Apr 12 19:01:20 1991
***************
*** 60,66 ****
      Boolean floatingX;
      Boolean floatingY;
      Boolean framedAxes;
-     Boolean showY2Axis;
      Boolean showLegend;
      short legendWidth;
      short legendSpacing;
--- 60,65 ----
***************
*** 74,84 ****
--- 73,90 ----
      XtCallbackList selectCallback;
      XtCallbackList doubleSelectCallback;
      XtCallbackList errorCallback;
+ 
+     /* 
+      * Private widgets.  They are also managed children, numbered
+      *  (in order) 0-5 
+      */ 
+ 
      AtAxisObject xaxis;
      AtAxisObject yaxis;
      AtAxisObject y2axis;
      AtAxisObject xframeAxis;
      AtAxisObject yframeAxis;
+     AtAxisObject y2frameAxis;
  
      /* private state */
  
***************
*** 153,157 ****
--- 159,173 ----
  
  
  #define XtRBoundingBox "BoundingBox"
+ 
+ /* This is the number of children that are "private" children - we
+    manage them so XtNameToWidget can process them! */
+ #define FIRST_PUBLIC_CHILD 6
+ #define CHILD_XAXIS 0
+ #define CHILD_YAXIS 1
+ #define CHILD_Y2AXIS 2
+ #define CHILD_XFRAMEAXIS 3
+ #define CHILD_YFRAMEAXIS 4
+ #define CHILD_Y2FRAMEAXIS 5
  
  #endif
*** /tmp/,RCSt1a22231	Tue Apr 16 16:12:42 1991
--- PlotterPS.c	Mon Apr 15 12:42:46 1991
***************
*** 39,45 ****
--- 39,49 ----
  #define NUMCHILDREN(w) (w->composite.num_children)
  #define CHILD(w,i) (w->composite.children[i])
  #define CONSTRAINT(w,i) ((AtPlotterConstraints)(CHILD(w,i)->core.constraints))
+ #define CHILDCONSTRAINTS(cw) ((AtPlotterConstraints)(cw)->core.constraints)
+ #define NTHCHILDISDISPLAYED(w, i) (CONSTRAINT(w, i)->plotter.displayed)
+ #define ISDISPLAYED(cw) (CHILDCONSTRAINTS(cw)->plotter.displayed)
  #define DRAWPS(w,i) (*((AtPlotWidgetClass)CHILD(w,i)->core.widget_class)->plot_class.drawPS)
+ #define DRAWPSCHILD(cw) (*((AtPlotWidgetClass)(cw)->core.widget_class)->plot_class.drawPS)
  #define LEGENDICON(f,w,i,x,y,width,height) (*((AtPlotWidgetClass)CHILD(w,i)->core.widget_class)->plot_class.drawIconPS)(f, (AtPlotWidget)CHILD(w,i),x,y,width,height)
  
  #define height(x) AtTextPSAscent(x) + AtTextPSDescent(x)
***************
*** 54,64 ****
      fprintf(f, "%%%%BeginObject: AtPlotter legend\ngsave\n");
      
      h = height(w->plotter.legendTitleText) + w->plotter.marginWidth;
!     for(i=0; i < NUMCHILDREN(w); i++) {
  	t = CONSTRAINT(w,i)->plotter.legendText;
  	if (t != NULL) h += height(t) + w->plotter.legendSpacing;
      }
! 	
      y = y2 - ((y2 - y1) - h)/2;
      x = x1 + ((x2 - x1) - AtTextPSWidth(w->plotter.legendTitleText))/2;
      AtTextPSDraw(f, w->plotter.legendTitleText, x,
--- 58,70 ----
      fprintf(f, "%%%%BeginObject: AtPlotter legend\ngsave\n");
      
      h = height(w->plotter.legendTitleText) + w->plotter.marginWidth;
!     for(i=FIRST_PUBLIC_CHILD; i < NUMCHILDREN(w); i++) {
!       if (NTHCHILDISDISPLAYED(w, i)) {
  	t = CONSTRAINT(w,i)->plotter.legendText;
  	if (t != NULL) h += height(t) + w->plotter.legendSpacing;
+       }
      }
!     
      y = y2 - ((y2 - y1) - h)/2;
      x = x1 + ((x2 - x1) - AtTextPSWidth(w->plotter.legendTitleText))/2;
      AtTextPSDraw(f, w->plotter.legendTitleText, x,
***************
*** 65,73 ****
  		 y - AtTextPSAscent(w->plotter.legendTitleText));
      y -= height(w->plotter.legendTitleText) + w->plotter.marginWidth;
  
!     for(i = 0; i < NUMCHILDREN(w); i++ ) {
  	t = CONSTRAINT(w,i)->plotter.legendText;
! 	if (t != NULL) {
  	    h = height(t);
  	    LEGENDICON(f,w,i, x1, y, 16, h);
  	    AtTextPSDraw(f, t, x1+16+w->plotter.marginWidth,
--- 71,79 ----
  		 y - AtTextPSAscent(w->plotter.legendTitleText));
      y -= height(w->plotter.legendTitleText) + w->plotter.marginWidth;
  
!     for(i = FIRST_PUBLIC_CHILD; i < NUMCHILDREN(w); i++ ) {
  	t = CONSTRAINT(w,i)->plotter.legendText;
! 	if (NTHCHILDISDISPLAYED(w, i) && t != NULL) {
  	    h = height(t);
  	    LEGENDICON(f,w,i, x1, y, 16, h);
  	    AtTextPSDraw(f, t, x1+16+w->plotter.marginWidth,
***************
*** 127,144 ****
      else
          floaty = False;
  
!     xaxiswidth = AtAxisWidthPS(w->plotter.xaxis);
!     yaxiswidth = AtAxisWidthPS(w->plotter.yaxis);
!     if (w->plotter.showY2Axis)
! 	y2axiswidth = AtAxisWidthPS(w->plotter.y2axis);
  
      if (!floaty) x1 += yaxiswidth;
      if (!floatx) y1 += xaxiswidth;
!     if (w->plotter.showY2Axis)
! 	x2 -= y2axiswidth;
      if (w->plotter.framedAxes) {
! 	x2 -= AtAxisWidthPS(w->plotter.yframeAxis);
! 	y2 -= AtAxisWidthPS(w->plotter.xframeAxis);
      }
  
      width = x2 - x1;
--- 133,159 ----
      else
          floaty = False;
  
!     xaxiswidth = yaxiswidth = y2axiswidth = 0;
!     
!     if (NTHCHILDISDISPLAYED(w, CHILD_XAXIS))
!       xaxiswidth = AtAxisWidthPS(w->plotter.xaxis);
!     if (NTHCHILDISDISPLAYED(w, CHILD_YAXIS))
!       yaxiswidth = AtAxisWidthPS(w->plotter.yaxis);
!     if (NTHCHILDISDISPLAYED(w, CHILD_Y2AXIS))
!       y2axiswidth = AtAxisWidthPS(w->plotter.y2axis);
  
      if (!floaty) x1 += yaxiswidth;
      if (!floatx) y1 += xaxiswidth;
!     x2 -= y2axiswidth;
      if (w->plotter.framedAxes) {
!       int ydisp = NTHCHILDISDISPLAYED(w, CHILD_YAXIS);
!       int y2disp = NTHCHILDISDISPLAYED(w, CHILD_Y2AXIS);
!       
!       if (ydisp && !y2disp)
! 	x2 -= AtAxisWidth(w->plotter.yframeAxis);
!       if (y2disp && !ydisp)
! 	x1 += AtAxisWidth(w->plotter.y2frameAxis);
!       y1 += AtAxisWidth(w->plotter.xframeAxis);
      }
  
      width = x2 - x1;
***************
*** 189,214 ****
  			   w->plotter.y2axis->axis.transform);
  
      /* draw the axes */
!     if (floatx) {
  	originy = AtScaleUserToPixel(yscale, 0.0);
  	AtAxisDrawPS(f, w->plotter.xaxis, x1, originy, x2, originy, y1, y2);
!     }
!     else
  	AtAxisDrawPS(f, w->plotter.xaxis, x1, y1, x2, y1, y1, y2);
! 
!     if (floaty) {
  	originx = AtScaleUserToPixel(xscale, 0.0);
  	AtAxisDrawPS(f, w->plotter.yaxis, originx, y1, originx, y2, x1, x2);
!     }
!     else 
  	AtAxisDrawPS(f, w->plotter.yaxis, x1, y1, x1, y2, x1, x2);
! 
!     if (w->plotter.showY2Axis)
  	AtAxisDrawPS(f, w->plotter.y2axis, x2, y1, x2, y2, x1, x2);
  
      if (w->plotter.framedAxes) {
  	AtAxisDrawPS(f, w->plotter.xframeAxis, x1, y2, x2, y2, 0, 0);
! 	AtAxisDrawPS(f, w->plotter.yframeAxis, x2, y1, x2, y2, 0, 0);
      }
  
      /* set up clipping */
--- 204,236 ----
  			   w->plotter.y2axis->axis.transform);
  
      /* draw the axes */
!     if (NTHCHILDISDISPLAYED(w, CHILD_XAXIS)) {
!       if (floatx) {
  	originy = AtScaleUserToPixel(yscale, 0.0);
  	AtAxisDrawPS(f, w->plotter.xaxis, x1, originy, x2, originy, y1, y2);
!       }
!       else
  	AtAxisDrawPS(f, w->plotter.xaxis, x1, y1, x2, y1, y1, y2);
!     }
!     
!     if (NTHCHILDISDISPLAYED(w, CHILD_YAXIS)) {
!       if (floaty) {
  	originx = AtScaleUserToPixel(xscale, 0.0);
  	AtAxisDrawPS(f, w->plotter.yaxis, originx, y1, originx, y2, x1, x2);
!       }
!       else 
  	AtAxisDrawPS(f, w->plotter.yaxis, x1, y1, x1, y2, x1, x2);
!     }
!     
!     if (NTHCHILDISDISPLAYED(w, CHILD_Y2AXIS))
  	AtAxisDrawPS(f, w->plotter.y2axis, x2, y1, x2, y2, x1, x2);
  
      if (w->plotter.framedAxes) {
  	AtAxisDrawPS(f, w->plotter.xframeAxis, x1, y2, x2, y2, 0, 0);
! 	if (!NTHCHILDISDISPLAYED(w, CHILD_Y2AXIS))
! 	  AtAxisDrawPS(f, w->plotter.yframeAxis, x2, y1, x2, y2, 0, 0);
! 	if (!NTHCHILDISDISPLAYED(w, CHILD_YAXIS))
! 	  AtAxisDrawPS(f, w->plotter.y2frameAxis, x1, y1, x1, y2, 0, 0);
      }
  
      /* set up clipping */
***************
*** 217,227 ****
  	    x1, y1, x1, y2, x2,y2, x2, y1);
  
      /* draw each of the plots */
!     for(i=0; i<NUMCHILDREN(w); i++) {
! 	if (CONSTRAINT(w,i)->plotter.useY2Axis)
  	    DRAWPS(w,i)(f, (AtPlotWidget)CHILD(w,i), xscale, y2scale);
! 	else
  	    DRAWPS(w,i)(f, (AtPlotWidget)CHILD(w,i), xscale, yscale);
      }
      
      /* finish up */
--- 239,264 ----
  	    x1, y1, x1, y2, x2,y2, x2, y1);
  
      /* draw each of the plots */
!     if (w->plotter.rankChildren) {
!       Rank *tmp = w->plotter.ordered_children;
!       while (tmp) {
! 	if (ISDISPLAYED(tmp->child))
! 	  if (CHILDCONSTRAINTS(tmp->child)->plotter.useY2Axis)
! 	    DRAWPSCHILD(tmp->child)(f, (AtPlotWidget)tmp->child, 
! 				    xscale, y2scale);
! 	  else
! 	    DRAWPSCHILD(tmp->child)(f, (AtPlotWidget)tmp->child, 
! 				    xscale, yscale);
! 	tmp = tmp->next;
!       }
!     } else {
!       for(i=FIRST_PUBLIC_CHILD; i<NUMCHILDREN(w); i++) {
! 	if (NTHCHILDISDISPLAYED(w, i))
! 	  if (CONSTRAINT(w,i)->plotter.useY2Axis)
  	    DRAWPS(w,i)(f, (AtPlotWidget)CHILD(w,i), xscale, y2scale);
! 	  else
  	    DRAWPS(w,i)(f, (AtPlotWidget)CHILD(w,i), xscale, yscale);
+       }
      }
      
      /* finish up */
***************
*** 308,310 ****
--- 345,353 ----
  
      fclose(f);
  }
+ 
+ /*
+  * Local Variables:
+  * eval: (set-c-style 'GNU)
+  * End:
+  */
*** /tmp/,RCSt1a22231	Tue Apr 16 16:12:43 1991
--- AtPlotter.man	Tue Apr 16 15:47:11 1991
***************
*** 28,39 ****
  
  The axes and plots are treated as sub-objects of the widget and each has
  its own set of resources.  New plots types can be displayed by
! subclassing an existing plot type.
  
  .SH CLASSES
  The Plotter widget is a subclass of Constraint.  The class pointer
  is atPlotterWidgetClass, and the class name is AtPlotter.
  
  .SH RESOURCES
  The Plotter widget inherits all the resources of the Core, Composite,
  and Constraint widget classes. 
--- 28,96 ----
  
  The axes and plots are treated as sub-objects of the widget and each has
  its own set of resources.  New plots types can be displayed by
! subclassing an existing plot type.  The axes and plots are subclasses
! of Object and are not Widgets. They should 
! .I not
! be managed or created with the 
! .B XtCreateManagedWidget()
! call, as corruption of the plot data will occur.  (As a hint, if the
! linewidth in the generated PostScript is 256 (hence filling up the
! graph area with black), then you have probably attempted to manage the
! plot object.)
  
  .SH CLASSES
  The Plotter widget is a subclass of Constraint.  The class pointer
  is atPlotterWidgetClass, and the class name is AtPlotter.
  
+ .SH PRIVATE CHILD OBJECTS
+ There are six private children of the Plotter widget:
+ .BR xaxis ", " yaxis ", " y2axis ", "
+ .BR xframeaxis ", " yframeaxis ", and " y2frameaxis .
+ They are all created at widget creation time and are AtAxis objects.
+ (Programs can get the object pointer using the
+ .BI AtPlotterGet object ()
+ routines.)  Resources for each of these axes can be set in the usual
+ way.  There are three main axis objects and three frame axis objects.
+ The X axis is along the bottom of the graph, and all plots use the
+ same X scale.  There are two Y axes that are completely equivalent,
+ called the Y and Y2 axes.  The Y axis is on the left of the main graph
+ area, the Y2 axis is on the right.  A given graph may use either or
+ both Y axes.  (The
+ .B useY2Axis
+ constraint variable for each plot determines which Y axis it is
+ associated with.)
+ 
+ In addition to being used for scaling, each of the three main axes can
+ be independently displayed or not displayed by setting the 
+ .B displayed
+ constraint resource for the axis object.  (Previous versions insisted
+ on displaying the X and Y axes, and had an AtPlotter resource to
+ control the display of the Y2 axis.)  The results of setting the
+ .B displayed
+ resource to 
+ .B false
+ for both 
+ .B yaxis 
+ and
+ .B y2axis
+ is undefined.
+ 
+ The three frame axes are used when the 
+ .B framedAxis
+ resource is set to
+ .BR True .
+ In this case, the xframeaxis is always drawn, the yframe axis is drawn if
+ the y2 axis is not being displayed, and the y2frameaxis is drawn if the
+ yaxis is not being displayed.  The 
+ .B displayed
+ constraint resource is ignored for frame axes.
+ The 
+ .B autoNumber
+ resource of frame axes is forced to
+ .BR False ,
+ and the numbering of frame axes is forces to be the same as for the
+ corresponding main axis by the AtPlotter widget code.
+ 
  .SH RESOURCES
  The Plotter widget inherits all the resources of the Core, Composite,
  and Constraint widget classes. 
***************
*** 66,72 ****
  XtNfloatingX	Boolean	False
  XtNfloatingY	Boolean	False
  XtNframedAxes	Boolean	False
- XtNshowY2Axis	Boolean False
  XtNshowLegend	Boolean	True
  XtNlegendWidth	short	100
  XtNlegendSpacing	short	3
--- 123,128 ----
***************
*** 80,88 ****
  XtNselectCallback	XtCallbackList	NULL
  XtNdoubleSelectCallback	XtCallbackList	NULL
  XtNerrorCallback	XtCallbackList	NULL
- XtNxaxis	AtAxisObject	dynamic
- XtNyaxis	AtAxisObject	dynamic
- XtNy2axis	AtAxisObject	NULL
  .TE
  
  .IP XtNfontFamily
--- 136,141 ----
***************
*** 150,159 ****
  resource and XtNfloatingAxes are both set to True, the results are
  un-specified.  
  
- .IP XtNshowY2Axis
- Specifies whether the second Y2 axis should be displayed at the right of
- the plotting area
- 
  .IP XtNshowLegend
  Specifies whether the legend should be drawn.
  
--- 203,208 ----
***************
*** 216,230 ****
  If no procedures are specified, the widget will output any warnings to
  standard error using \fBXtWarning()\fP.
  
- .IP XtNxaxis
- The AtAxisObject corresponding to the plotter widget's x-axis.
- 
- .IP XtNyaxis
- The AtAxisObject corresponding to the plotter widget's y-axis.
- 
- .IP XtNy2axis
- The AtAxisObject corresponding to the plotter widget's y2-axis.
- 
  .SH "PLOTTER CONSTRAINT RESOURCES"
  The AtPlotter widget is a constraint widget, which means that it
  provides resources that each of its children (the individual plots that
--- 265,270 ----
***************
*** 281,287 ****
  	AtPlotterWidget \fIplotter\fP;
  AtAxisObject AtPlotterGetXFrameAxis(\fIplotter\fP)
  	AtPlotterWidget \fIplotter\fP;
! AtAxisObject AtPlotterGetYFrameAxis(\fIplotter\fP)
  	AtPlotterWidget \fIplotter\fP;
  void AtPlotterGetPlotExtents(\fIplotter\fP, *\fIxmin\fP, *\fIxmax\fP, *\fIymin\fP, *\fIymax\fP)
  	AtPlotterWidget \fIplotter\fP;
--- 321,327 ----
  	AtPlotterWidget \fIplotter\fP;
  AtAxisObject AtPlotterGetXFrameAxis(\fIplotter\fP)
  	AtPlotterWidget \fIplotter\fP;
! AtAxisObject AtPlotterGetY2FrameAxis(\fIplotter\fP)
  	AtPlotterWidget \fIplotter\fP;
  void AtPlotterGetPlotExtents(\fIplotter\fP, *\fIxmin\fP, *\fIxmax\fP, *\fIymin\fP, *\fIymax\fP)
  	AtPlotterWidget \fIplotter\fP;
***************
*** 342,347 ****
--- 382,392 ----
  
  .IP AtPlotterGetYFrameAxis()
  Returns the y-frame-axis AtAxisObject of \fIplotter\fP.  If
+ \fIplotter\fP's XtNframedAxes resource is False, the returned value is
+ undefined.
+ 
+ .IP AtPlotterGetY2FrameAxis()
+ Returns the y2-frame-axis AtAxisObject of \fIplotter\fP.  If
  \fIplotter\fP's XtNframedAxes resource is False, the returned value is
  undefined.
  
