define FOGR,0  rem  section dealing with graph as a whole
define FSGR,1
define FAGR,2
define TCGR,3
define LCGR,4
define LWGR,5
define PDGR,6
define PSGR,7
define BGGR,8
define PWGR,9
define PHGR,10
define BWGR,11
define DCOLGR,12
define GRGR,17
define ROWS,18
define COLUMNS,19
define TDGR,20
define GRAPHTYPE,21
define XLABEL,22
define YLABELS,23
define THICKNESSGR,29
define FRGR,30
define OLGR,31
define OTGR,32
define ORGR,33
define OBGR,34
define ILGR,35
define ITGR,36
define IRGR,37
define IBGR,38
define MTGR,39
define MSGR,40
define PIGR,41
define MAGR,42
define PSIZE,43
define FOA,0   rem  Section dealing with axis
define FSA,1
define FAA,2
define TCA,3
define LCA,4
define LWA,5
define STA,6
define LGA,7
define INA,8
define UPA,9
define LOA,10
define NSA,11
define AA,12
define BA,13
define WIDTHA,14
define HEIGHTA,15
define HOTXA,16
define HOTYA,17
define FORMATA,18
define LENGTHA,19
define PAXIS,20
define FOD,0    rem Section dealing with data set
define FSD,1
define FAD,2
define TCD,3
define LWD,4
define LCD,5
define PDD,6
define PSD,7
define FCD,8
define MTD,9
define MSD,10
define MCD,11
define FRD,12
define TDD,13
define PDATA, 14
define FOM,0    rem Section dealing with marker keys - text properties
define FSM,1
define FAM,2
define TCM,3
define LWM,4    rem line properties
define LCM,5
define PDM,6
define PSM,7
define MTM,8    rem marker properties- repeated 5 times
define MSM,9
define MCM,10
define XSM,28
define YSM,29
define XEM,30
define YEM,31
define NSM,32
define MDATA,33
define FOC,0    rem Section dealing with colour keys - text properties
define FSC,1
define FAC,2
define TCC,3
define LWC,4    rem line properties
define LCC,5
define PDC,6
define PSC,7
define FCC,8    rem colour (repeated 16 times)
define XSC,20
define YSC,21
define XEC,22
define YEC,23
define CDATA,24
define LINES_ONLY,0   rem types of 2D graph
define POINTS_ONLY,1
define LINES_AND_POINTS,2
define VERTICAL_HISTOGRAM,3
define HORIZONTAL_HISTOGRAM,4
define STACKED_VERTICAL_HISTOGRAM,5
define STACKED_HORIZONTAL_HISTOGRAM,6
define PICTOGRAM,7
define PIE_CHART,8
define TWO_LINES,9
define BOX_AND_TAILS,10
define DISTRIBUTION,11
define GENERAL,12
define LINE_HISTO,13
define DRAG_ALLOWED, 0x1
define SELECT_ALLOWED, 0x2
define TEXT_EFFECTS, 0x4
define FILL_EFFECTS, 0x8
define LINE_EFFECTS, 0x10
define GRAPH_COLOUR_ALLOWED, 0x20
define THREE_DEE_ALLOWED, 0x40
define GRID_ALLOWED, 0x80
define EXPLODE_ALLOWED, 0x100
define COLOURS_ALLOWED, 0x200
define BAR_WIDTH_ALLOWED, 0x400
define POINT_DETAILS_ALLOWED, 0x800
define TICKS_ALLOWED, 0x1000
define DIMENSIONS_ALLOWED, 0x2000
define TOP_ALLOWED, 0x4000
define DELETE_ALLOWED, 0x8000
define ALL_SELECTED, 0x10000
define NONE_SELECTED, 0x20000
define REDRAW_NEEDED, 0x40000

rem : ********************************************************************
rem : macro CRM_plot_point_set plots a data set in a line plot or
rem : scatter diagram. w is the window, data the normalised data block,
rem : p, xaxis, yaxis and di are the inherited parameters, dsc is the
rem : data set number.
macro CRM_plot_point_set (w,data(),p(),xaxis(),yaxis(),di(),dsc)
   local k,res,color,kk,xc,yc,zc
   local z(1,p(ROWS))
   local c(1,4)
   kk=0
           rem : first assemble data set from array data and scale
   for k=0 to p(ROWS)-1
     if (type(data(k,0)) < 3 and type(data(k,dsc)) < 3) then 
        if xaxis(LGA) = 0 then 
            z(0,kk) = data(k,0) * xaxis(AA) + xaxis(BA)
        else 
            z(0,kk) = log(data(k,0)) * xaxis(AA) + xaxis(BA)
        endif
        if yaxis(LGA) = 0 then
             z(1,kk) = data(k,dsc) * yaxis(AA) + yaxis(BA)
        else
             z(1,kk) = log(data(k,dsc)) * yaxis(AA) + yaxis(BA)
        endif
        kk=kk+1
     endif
   next k
   if p(THICKNESSGR) <> 0 then
      zc = p(THICKNESSGR)/(p(COLUMNS)-1)
      xc = (p(COLUMNS)-1-dsc) * 0.33*zc
      yc = (p(COLUMNS)-1-dsc) * 0.55*zc
      for k = 0 to p(ROWS)-1
         z(0,k) = z(0,k)+xc
         z(1,k)=z(1,k)+yc
      next k
   endif
   if (kk < 2) then = "Too few points to plot"
   res = lineattributes(w,1,p(LWGR),di(LCD),0)
   if ( (p(GRAPHTYPE) <> POINTS_ONLY) and (p(THICKNESSGR) <> 0)) then
       res = group(w)
       for k = 0 to p(ROWS)-2
          c(0,0) = z(0,k)
          c(1,0) = z(1,k)
          c(0,1) = z(0,k+1)
          c(1,1) = z(1,k+1)
          c(0,2) = c(0,1)+ 0.33*zc
          c(1,2) = c(1,1)+0.55*zc
          c(0,3) = c(0,0) + 0.33*zc
          c(1,3) = c(1,0)+0.55*zc
          res = poly(w,c,4,di(LCD))
       next k
       res = lineattributes(w,1,p(LWGR),0,0)         
       res = openpoly(w,z,kk)
       res = endgroup(w)
       =res  
   endif   

   res = group(w)
   if p(GRAPHTYPE) <> POINTS_ONLY then res = openpoly(w,z,kk)
   if p(GRAPHTYPE) <> LINES_ONLY then
   res = polymarker(w,z,kk,di(MTD),di(MSD),di(MCD))
   endif
   res = endgroup(w)
   =res
endmacro



rem : this macro is called when the data for the point-plot
rem : has been arranged in a regular way in array data. 

macro CRM_point_plot_x(data(),s,p(),v)

   local xaxis(PAXIS),yaxis(PAXIS),di(PDATA),kk(MDATA)
   local minx,maxx,miny,maxy,flag
   local x_axis_height,y_axis_width
   local x_tag,y_tag,gr_tag,le_tag
   local j,k,res,w,hor_label_dims,ver_label_dims
   local data_up,data_right,data_height,data_width
   local dsc,dsp,sss,ttt
   local has_legend
   local has_top_label
   local bitmap 
               rem find max and min values in both axes
   p(THICKNESSGR) = p(THICKNESSGR) * (p(COLUMNS)-1)
   has_top_label = ((len(p(YLABELS)) > 0) and (p(COLUMNS) = 2))
   gr_tag = psexsub(v)
   has_legend = 0
   bitmap = LINE_EFFECTS+TEXT_EFFECTS+GRAPH_COLOUR_ALLOWED+GRID_ALLOWED+COLOURS_ALLOWED+TICKS_ALLOWED+DIMENSIONS_ALLOWED 
   if p(GRAPHTYPE) = LINES_AND_POINTS  then 
           bitmap = bitmap + POINT_DETAILS_ALLOWED
   endif
   if p(GRAPHTYPE) = POINTS_ONLY then
           bitmap=bitmap+POINT_DETAILS_ALLOWED
   endif
   bitmap=bitmap + 0x40
   res = settag(gr_tag,bitmap)
   w = gstart(p(PWGR),p(PHGR))
                                       rem find data minima and maxim
   minx=data(0,0)
   maxx=data(0,0)
   miny = data(0,1)
   maxy = data(0,1)
   for j = 0 to p(ROWS)-1
      if data(j,0) > maxx then maxx = data(j,0)
      if data(j,0) < minx then minx = data(j,0)
      for k = 1 to p(COLUMNS)-1
         if type(data(j,k)) = 3 then = "Bad data"
         if data(j,k) > maxy then maxy = data(j,k)
         if data(j,k) < miny then miny = data(j,k)
      next k
   next j
   sss = minx
   if minx = maxx then
       if sss > 0 then maxx = 2*minx : minx = 0
       if sss < 0 then minx = 2 * minx:maxx = 0
       if sss = 0 then  minx = -1 : maxx = 1
   endif
   sss = miny
   if miny = maxy then
       if sss > 0 then maxy = 2*miny : miny = 0
       if sss < 0 then miny = 2*miny : maxy = 0
       if sss = 0 then miny = -1 : maxy = 1
   endif
   if (p(COLUMNS) >= 3) and (len(p(YLABELS)) > 0 )then  
                 rem look for a legend substring
      has_legend = 1
      res = CRM_close_string(v)
      v = CRM_find_substring(s,"F")
      if (res = -1) then 
                  rem legend not found
          le_tag = CRM_get_legend_default_params(p,kk)
      else
          le_tag = psexsub(v)
          res = CRM_get_legend_params(p,kk,v)
          res = CRM_close_string(v)
      endif
      v = psregister(s)
      res = psstep(v)
   endif   
                             rem   Now extract x-axis data
   res = psstep(v)
   if iserror(res) then = res
   if res<> CRM_code("B") then = "Missing B() Parameter"
   x_tag = psexsub(v)
   res = CRM_get_ax_params(p,xaxis,v)                                     rem   Now extract y-axis data
   res = psstep(v)
   if iserror(res) then = res
   if res<> CRM_code("C") then = "Missing C() Parameter"
   y_tag = psexsub(v)
   res = CRM_get_ax_params(p,yaxis,v)
                                                     rem set limits
   if xaxis(LOA) = (-1) or xaxis(LOA) > minx then xaxis(LOA) = minx
   if xaxis(UPA) = (-1) or xaxis(UPA) < maxx then xaxis(UPA) = maxx
   if yaxis(LOA) = (-1) or yaxis(LOA) > miny then yaxis(LOA) = miny
   if yaxis(UPA) = (-1) or yaxis(UPA) < maxy then yaxis(UPA) = maxy

                rem now plan layout using dummy width for x-axis and
                rem dummy height for y-axis

   xaxis(WIDTHA) = 500
   yaxis(HEIGHTA) = 500
   res = CRM_plan_horizontal_axis(w,xaxis,p)
   if type(res) = 3 then =res
   res = CRM_plan_vertical_axis(w,yaxis,p) 
   if type(res) = 3 then =res
   if (has_legend) then 
       res = CRM_size_of_legend(w,p,kk,p(GRAPHTYPE))
       if kk(XSM) = 0 then
             kk(XSM) = p(PWGR) - p(ORGR)-p(IRGR)+20 - kk(XEM)
             kk(YSM) = p(PHGR)/2 - kk(YEM)/2
       endif
   else
       kk(XEM) = 0
       kk(YEM) = 0
   endif

                           rem now compute sheet geography correctly

   data_right = yaxis(WIDTHA)+p(OLGR)+p(ILGR)+xaxis(HOTXA)
   data_up = xaxis(HEIGHTA)+p(OBGR)+p(IBGR)+yaxis(HOTYA)
   data_width = p(PWGR) - p(ORGR)-p(IRGR) - data_right -0.33*p(THICKNESSGR)
   if kk(XEM) > 0 then data_width = data_width -40 -kk(XEM)
   data_height = p(PHGR) - p(OTGR)-p(ITGR)-p(OBGR)-p(IBGR) - data_up-0.55*p(THICKNESSGR)
                            rem fill sheet with white
   yaxis(HEIGHTA) = p(PHGR)- p(OTGR)-p(ITGR)-p(OBGR)-p(IBGR)- xaxis(HEIGHTA)
   xaxis(WIDTHA) = p(PWGR) - p(OLGR)-p(ILGR)-p(ORGR)-p(IRGR) - kk(XEM)-yaxis(WIDTHA)
   res = box(w,0,0,p(PWGR),p(PHGR),p(MAGR))
                            rem draw background if not white
   if p(BGGR) <> p(MAGR) then
       res = box(w,p(OLGR),p(OBGR),p(PWGR)-p(OLGR)-p(ORGR),p(PHGR)-p(OTGR)-p(OBGR),p(BGGR))
   endif
                  rem do it again to dispose of residual errors 
   res = CRM_plan_horizontal_axis(w,xaxis,p)
   res = CRM_plan_vertical_axis(w,yaxis,p)
   sss=0
   if maxy * miny < 0 then sss = yaxis(BA)
   ttt=0
   if maxx*minx < 0 then ttt = xaxis(BA)
   if xaxis(LGA) then
       res = CRM_draw_horlog_axis(w,data_right,data_up,sss,xaxis,p,yaxis(LENGTHA),x_tag)
   else
       res = CRM_draw_horizontal_axis(w,data_right,data_up,sss,xaxis,p,yaxis(LENGTHA),x_tag,xaxis(BA))
   endif
   if type(res) = 3 then =res
   if yaxis(LGA) then
        res = CRM_draw_verlog_axis(w,data_right,ttt,data_up,yaxis,p,xaxis(LENGTHA),y_tag,has_top_label)
   else
        res = CRM_draw_vertical_axis(w,data_right,ttt,data_up,yaxis,p,xaxis(LENGTHA),y_tag,has_top_label)
   endif  
   if type(res) = 3 then =res

   dsc = 1
   while dsc < p(COLUMNS) 
      res = CRM_get_di_default_params(p,di,dsc)
      if has_legend then
           kk(MTM+ 3*(dsc-1))= di(MTD)
           kk(MSM+3*(dsc-1)) = di(MSD)
           kk(MCM+3*(dsc-1)) = di(MCD)
       endif
       res = CRM_plot_point_set(w,data,p,xaxis,yaxis,di,dsc)
       if (type(res))=3 then =res
       dsc = dsc+1
   endwhile
   if has_legend then res = CRM_draw_legend(w,p,kk,le_tag,p(GRAPHTYPE))
   res=CRM_close_string(v)
   res = CRM_tail_end(w,s,p)
      if res then =res     
=w                 
endmacro


rem : *****************************************************************
rem : This is the high-level macro called to plot a line graph.
rem : In the absence of any DI substrings it plots all the datasets
rem : lines, with undecorated points.
rem : The graph may of course be post-edited to mark the points.
macro line_plot(a(),s)
graphmacro "Line plot",0x19FF,""
   local v,q,n,res,h,w,j
   local p(PSIZE)
   v = psregister(s)
   q = psstep(v)
   if iserror(q) then = q
   if q<> CRM_code("A") then = "Missing parameter substring"
   res = CRM_get_gr_params(p,v)
   p(GRAPHTYPE) = LINES_ONLY
   h = first(a)
   w = second(a)
   n = CRM_datasets(v,w,h)
   if n <= 1 then = "Graph can't be plotted"
   if pscontains(v,"u") then 
      res = CRM_point_plot_row_data(a,s,v,p,w,n,0)
   else
      res = CRM_point_plot_col_data(a,s,v,p,h,n,0)
   endif
   q= CRM_close_string(v)
   = res
endmacro


rem : *****************************************************************
rem : This is the high-level macro called to plot a scatter diagram.
rem : In the absence of any DI substrings it plots all the datasets
rem : as unconnected points.
rem : The graph may of course be post-edited to modify the points.
macro scatter_diagram(a(),s)
graphmacro "Scatter diagram",0x18FF,""
   local v,q,n,res,h,w,j
   local p(PSIZE)

   v = psregister(s)
   q = psstep(v)
   if iserror(q) then = q
   if q<> CRM_code("A") then = "Missing parameter substring"

   res = CRM_get_gr_params(p,v)
   p(GRAPHTYPE) = POINTS_ONLY
   h = first(a)
   w = second(a)
   n = CRM_datasets(v,w,h)
   if pscontains(v,"u") then 
      res = CRM_point_plot_row_data(a,s,v,p,w,n,0)
   else
      res = CRM_point_plot_col_data(a,s,v,p,h,n,0)
   endif
   q= CRM_close_string(v)
   = res
endmacro


rem : *****************************************************************
rem : This is the high-level macro called to plot a line graph marked
rem : with points.
rem : The graph may of course be post-edited to mark the points.
macro marked_lines(a(),s)
graphmacro "Marked lines",0x18FF,""
   local v,q,n,res,h,w,j
   local p(PSIZE)

   v = psregister(s)
   q = psstep(v)
   if iserror(q) then = q
   if q<> CRM_code("A") then = "Missing parameter substring"

   res = CRM_get_gr_params(p,v)
   p(GRAPHTYPE) = LINES_AND_POINTS
   h = first(a)
   w = second(a)
   n = CRM_datasets(v,w,h)
  if pscontains(v,"u") then 
      res = CRM_point_plot_row_data(a,s,v,p,w,n,0)
   else
      res = CRM_point_plot_col_data(a,s,v,p,h,n,0)
   endif
   q= CRM_close_string(v)
   = res
endmacro
