1 /*
2  * $Id: style.c,v 1.2 2007-12-26 04:25:46 dhmunro Exp $
3  * Set/get details of graphics style for style.i functions.
4  */
5 /* Copyright (c) 2005, The Regents of the University of California.
6  * All rights reserved.
7  * This file is part of yorick (http://yorick.sourceforge.net).
8  * Read the accompanying LICENSE file for details.
9  */
10 
11 #include "gist.h"
12 #include "hlevel.h"
13 #include "draw.h"
14 
15 /* various X headers included by xfancy.h define True and False */
16 #undef True
17 #undef False
18 
19 #include "ydata.h"
20 #include "pstdlib.h"
21 
22 typedef struct GfakeSystem GfakeSystem;
23 struct GfakeSystem {
24   double viewport[4];    /* [xmin,xmax,ymin,ymax] in NDC coordinates */
25   GaTickStyle ticks;     /* tick style for this coordinate system */
26   char *legend;          /* e.g.- "System 0" or "System 1", p_malloc */
27 };
28 
29 /* If nsys==0, this is a query operation which fills in the input
30                data arrays (if the pointers are non-zero)
31    otherwise, systems is systems[nsys], and the operation is to
32                set the values specified in the data arrays
33    the return value is always the number of coordinate systems;
34    for queries the routine must be called twice, first with systems==0
35    to retrieve the number of systems, then with a large enough systems
36    to hold the returned values */
37 extern int raw_style(long nsys, int *landscape,
38                      GfakeSystem *systems, GeLegendBox *legends);
39 
40 extern BuiltIn Y_viewport;
41 
42 /* write wrapper routine by hand -- someday should let codger do it */
43 extern BuiltIn Y_raw_style;
Y_raw_style(int nArgs)44 void Y_raw_style(int nArgs)
45 {
46   if (nArgs!=4) YError("raw_style takes exactly 4 arguments");
47   PushIntValue(raw_style(yarg_si(3),yarg_i(2,0),*yarg_p(1,0),*yarg_p(0,0)));
48 }
49 
raw_style(long nsys,int * landscape,GfakeSystem * systems,GeLegendBox * legends)50 int raw_style(long nsys, int *landscape,
51               GfakeSystem *systems, GeLegendBox *legends)
52 {
53   extern int YCurrentPlotter(void); /* defined in graph.c */
54   int nsy= YCurrentPlotter();
55   Drauing *drawing= (nsy>=0 && nsy<GH_NDEVS)? ghDevices[nsy].drawing : 0;
56   GeSystem *sys= drawing? drawing->systems : 0;
57 
58   if (!nsys) {
59     /* query operation */
60     if (!drawing) return 0;
61     if (landscape) *landscape= drawing->landscape;
62     nsy= drawing->nSystems;
63     if (systems && nsy>0) {
64       int i;
65       for (i=0 ; i<nsy ; i++,sys=(GeSystem *)sys->el.next) {
66         if (systems[i].legend) {
67           char *legend= systems[i].legend;
68           systems[i].legend= 0;
69           p_free(legend);
70         }
71         systems[i].legend= p_strcpy(sys->el.legend);
72         systems[i].viewport[0]= sys->trans.viewport.xmin;
73         systems[i].viewport[1]= sys->trans.viewport.xmax;
74         systems[i].viewport[2]= sys->trans.viewport.ymin;
75         systems[i].viewport[3]= sys->trans.viewport.ymax;
76         /* lazy today -- use ANSI struct assignment */
77         systems[i].ticks= sys->ticks;
78       }
79     }
80     if (legends) {
81       /* lazy today -- use ANSI struct assignment */
82       legends[0]= drawing->legends[0];
83       legends[1]= drawing->legends[1];
84     }
85     return nsy;
86 
87   } else {
88     /* set new style operation */
89     int i;
90     extern void GdKillSystems(void);  /* defined in draw.c */
91     GpBox vp;
92 
93     if (!landscape || !systems || !legends)
94       YError("missing data in Y_raw_style call");
95 
96     /* don't clobber the current display list(s) unless the
97        number of coordinate systems has changed */
98     nsy= drawing? drawing->nSystems : 0;
99     if (nsy != nsys) GdKillSystems();
100 
101     for (i=0 ; i<nsys ; i++) {
102       gistD.hidden= 0;
103       gistD.legend= systems[i].legend;
104       vp.xmin= systems[i].viewport[0];
105       vp.xmax= systems[i].viewport[1];
106       vp.ymin= systems[i].viewport[2];
107       vp.ymax= systems[i].viewport[3];
108       if (nsy==nsys) {
109         GdSetSystem(i+1);
110         /* don't bother with the legend */
111         gistD.trans.viewport.xmin= vp.xmin;
112         gistD.trans.viewport.xmax= vp.xmax;
113         gistD.trans.viewport.ymin= vp.ymin;
114         gistD.trans.viewport.ymax= vp.ymax;
115         /* lazy today -- use ANSI struct assignment */
116         gistD.ticks= systems[i].ticks;
117         GdSetPort();
118       } else if (GdNewSystem(&vp, &systems[i].ticks)<0) {
119         gistD.legend= 0;
120         YError("GdNewSystem failed in Y_raw_style");
121       }
122       gistD.legend= 0;
123     }
124     if (nsys && nsy==nsys) GdSetSystem(1);
125 
126     for (i=0 ; i<2 ; i++)
127       GdLegendBox(i, legends[i].x, legends[i].y,
128                   legends[i].dx, legends[i].dy,
129                   &legends[i].textStyle, legends[i].nchars,
130                   legends[i].nlines, legends[i].nwrap);
131 
132     GdLandscape(*landscape);
133 
134     return (int)nsys;
135   }
136 }
137 
Y_viewport(int nArgs)138 void Y_viewport(int nArgs)
139 {
140   Array *array=
141     PushDataBlock(NewArray(&doubleStruct,
142                            NewDimension(4L, 1L, (Dimension *)0)));
143   double *port= array->value.d;
144   array->type.dims->references--;
145   port[0]= gistD.trans.viewport.xmin;
146   port[1]= gistD.trans.viewport.xmax;
147   port[2]= gistD.trans.viewport.ymin;
148   port[3]= gistD.trans.viewport.ymax;
149 }
150