1 /*  aqua.c
2  *
3  *  Initial Implementation: 10/2007
4  *  UPDATED  - March      2008.  Add AQSEC2 routine to support "imaging" routine
5  *  UPDATED  - May        2009.  When using the "-DDOUBLE" option, need
6  *                               to make a distinction between real
7  *                               numbers and integers since the default
8  *                               byte size can be set independently
9  *                               for these.  Add the option "-DINTEGER8"
10  *                               to handle the case where integers set
11  *                               to 8 bytes on a 32-bit machine.
12  *  UPDATED  - June       2014.  With the new versions of the Mac OSX and
13  *                               Aquaterm, need to modify how real numbers
14  *                               are passed between the Fortran,
15  *                               aqua.c, and the Aquaterm library.
16  *
17  *  The purpose of this library is to provide easy access from
18  *  a Fortran 77 program to the AquaTerm library on MacOSX.
19  *
20  *  Aquaterm provides a native Mac OSX terminal.  This can be
21  *  used as an alternative to using X11 under Mac OSX.  The
22  *  advantage of Aquaterm is that is does not require the user
23  *  to have X11 installed (X11 installation is optional under
24  *  Mac OSX).  The Aquaterm terminal also has the "look" of the
25  *  Mac OSX window system (the X11 windows do not).
26  *
27  *  A few commets:
28  *
29  *     1) It is assumed that the Mac user has installed the
30  *        underlying Aquaterm software (in particular, the
31  *        Aquaterm library is a shared library that is expected
32  *        to be in /usr/local/lib.
33  *
34  *     2) Although Aquaterm provides a Fortran-based "adapter",
35  *        I am unable to take advantage of this.  The Fortran
36  *        adapter requires that the Fortran code be compiled to
37  *        preserve case in names.  This causes problems with
38  *        Dataplot since I do not want to do this for some other
39  *        routines that I am calling.
40  *
41  *     3) Aquaterm is a dynamic library.  With Dataplot, I try
42  *        to link libraries statically whenever possible.
43  *
44  *        This seems to cause a conflict with the zlib compression
45  *        library.  Dataplot uses the GD library for PNG and JPEG
46  *        graphics.  GD in turn uses the jpeg, png, and zlib
47  *        libraries.  For the Mac OSX, I have built static versions
48  *        of these libraries.  However, Aquaterm seems to need
49  *        a dynamic version of zlib.
50  *
51  *  For these reasons, I have choosen to use the C-based version
52  *  of Aquaterm.  I have provided this subroutine as an intermediate
53  *  wrapper between the Dataplot Fortran and the Aquaterm C-based
54  *  library.
55  *
56  *  Given my problem, I have not supported the full Aquaterm library.
57  *  Instead, I have supported a basic set of calls to support a
58  *  device driver for Aquaterm.  This set of routines provides
59  *  a wrapper layer between Fortran and the C based GD libraries.
60  *  That is, these routines use only integer and real arguments with
61  *  no C specific structures.  This makes the calling sequence from
62  *  Fortran easy.
63  *
64  *  Although I wrote this wrapper with a specific application in
65  *  mind, I believe it may well be useful for other Fortran
66  *  codes.  This code may be used and modified by anyone without
67  *  restriction.
68  *
69  *  A dummy version of this routine is maintained for non-Mac OSX
70  *  systems.  Since the dummy library is coded in Fortran, routine
71  *  names will be limited to six characters.
72  *
73  *  Note that calling C from Fortran is not standard.  I have
74  *  provided the following compiler defintions to enhance portability.
75  *
76  *  1) The default is to assume that the Fortran compiler appends an
77  *     underscore to the routine name.  Use -DNOUNDERSCORE if your
78  *     compiler does not append the underscore.
79  *  2) The default is to assume that the Fortran compiler converts
80  *     routine names to lower case.  Use -DUPPERCASE if your
81  *     Fortran compiler does not do this (e.g., the Cray).
82  *  3) Dataplot is compiled with options to make both single precision
83  *     and double precision 64-bit.  So real numbers will be passed
84  *     as "double" but need to be converted to "float" when calling
85  *     the Aquaterm routines.
86  *  4) Character strings are the most troublesome issue for
87  *     portability.  Passing character strings from Fortran to C
88  *     is very compiler dependent.  I have addressed this issue
89  *     by passing character strings as arrays of ASCII Decimal
90  *     Equivalents (ADE's).  That is, the Fortran converts a
91  *     character string to an array of the integer values where
92  *     the integer is the ASCII collating sequence (i.e., A = 65,
93  *     B = 66, etc.).  The end of the string is denoted by setting
94  *     the value to 0.  This is easily accomplished on the Fortran
95  *     side by using the ICHAR function.  The C code here then
96  *     calls an internal routine to covnert the integer array to
97  *     a C string.   Although a bit convoluted, this avoids a lot
98  *     of messy portability issues.
99  *
100  *
101  *  The following routines are included:
102  *
103  *  aqinit      - initialize Aquaterm
104  *  aqend       - close Aquaterm
105  *  aqrend      - render the current plot
106  *  aqeras      - start a new graph (close currently open one as well)
107  *  aqdraw      - draw a polyline
108  *  aqmove      - move to a point
109  *  aqseco      - set foreground color (based on color-map table)
110  *  aqsec2      - set foreground color (based on RGB triplet)
111  *  aqsepa      - set line pattern
112  *  aqpoin      - draw a point (i.e., a pixel)
113  *  aqcirc      - draw a circle
114  *  aqrgfl      - solid fill of a region
115  *  aqtxth      - draw a horizontal character string
116  *  aqtxtv      - draw a vertical character string
117  *  aqrelo      - read mouse position
118  *  i_to_s_4    - utility routine to convert array of ADE's to string
119  *                array
120  *
121  */
122 
123 /*  Site dependent definitions (see comments above) */
124 /*  Default is an underscore and lower case.  The compiler specified
125  *  definitions -DNOUNDERSCORE and -DUPPERCASE can be specified to
126  *  override these defaults. */
127 
128 #ifdef NOUNDERSCORE
129 #define APPEND_UNDERSCORE 0
130 #else
131 #define APPEND_UNDERSCORE 1
132 #endif
133 #ifdef UPPERCASE
134 #define SUBROUTINE_CASE 0
135 #else
136 #define SUBROUTINE_CASE 1
137 #endif
138 
139 /*  include files */
140 
141 #include <stdio.h>
142 #include <stdlib.h>
143 #include <math.h>
144 #include <strings.h>
145 #include <aquaterm/aquaterm.h>
146 
147 /* global definitions */
148 
149 int decodeEvent(char *event, int *x, int *y);
150 
151 /* flags for current attribute settings */
152 static int    OPEN_FLAG_AQUA = 0;          /* 0 - closed, 1 - open */
153 
154 #if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1
155 void  aqend_(), aqdraw_(), aqpoin_(), aqcirc_(), aqrgfl_();
156 void  aqinit_(), aqeras_(), aqtxth_(), aqtxtv_();
157 void  aqseco_(), aqsec2(), aqsepa_(), aqrend_(), aaqrelo_();
158 #elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0
159 void  AQEND_(), AQINIT_(), AQDRAW_(), AQPOIN_(), AQCIRC_(), AQRGFL_();
160 void  AQINIT_(), AQERAS_(), AQTXTH_(), AQTXTV_();
161 void  AQSECO_(), AQSEC2(), AQSEPA_(), AQREND_(), AQRELO_(),;
162 #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1
163 void  aqend(), aqdraw(), aqpoin(), aqcirc(), aqrgfl();
164 void  aqinit(), aqeras(), aqtxth(), aqtxtv(),gdtatt();
165 void  aqseco(), aqsec2(), aqsepa(), aqrend(), aqrelo();
166 #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0
167 void  AQEND(),  AQDRAW(), AQPOIN(), AQCIRC(), AQRGFL();
168 void  AQINIT(), AQERAS(), AQTXTH(), AQTXTV();
169 void  AQSECO(), AQSEC2(), AQSEPA(), AQRELO();
170 #endif
171 void  i_to_s_4();
172 
173 /* AQINIT  - routine to initialize Aquaterm.
174  *
175  */
176 #if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1
aqinit_(nplot,anumhp,anumvp,ired,igreen,iblue,maxclr)177 void aqinit_(nplot,anumhp,anumvp,ired,igreen,iblue,maxclr)
178 #elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0
179 void AQINIT_(nplot,anumhp,anumvp,ired,igreen,iblue,maxclr)
180 #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1
181 void aqinit(nplot,anumhp,anumvp,ired,igreen,iblue,maxclr)
182 #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0
183 void AQINIT(nplot,anumhp,anumvp,ired,igreen,iblue,maxclr)
184 #endif
185 int  ired[];
186 int  igreen[];
187 int  iblue[];
188 int  *maxclr;
189 int  *nplot, *anumhp, *anumvp;
190 
191 {
192 int    nplot_temp, anumhp_temp, anumvp_temp;
193 int    maxclr_temp;
194 int    ival1, ival2, ival3;
195 int    i;
196 float  val1, val2, val3;
197 
198     maxclr_temp = *maxclr;
199     nplot_temp  = *nplot;
200     anumhp_temp = *anumhp;
201     anumvp_temp = *anumvp;
202 
203     if (OPEN_FLAG_AQUA == 0) {           /*  Device currently closed */
204        OPEN_FLAG_AQUA = 1;
205        aqtInit();
206        aqtOpenPlot(nplot_temp);
207        aqtSetPlotSize(anumhp_temp,anumvp_temp);
208        aqtSetPlotTitle("Dataplot Graphics Window");
209        for (i = 0; i < maxclr_temp; i++) {
210            ival1 = ired[i];
211            ival2 = igreen[i];
212            ival3 = iblue[i];
213            val1 = (float)(ival1)/255.0;
214            val2 = (float)(ival2)/255.0;
215            val3 = (float)(ival3)/255.0;
216            aqtSetColormapEntry(i,val1,val2,val3);
217        }
218     }
219 }
220 
221 /* AQERAS  - routine to clear the screen.
222  *
223  *           1) Check if a plot is currently open.  If yes, write
224  *              it to a file and destroy the current image.
225  *           2) Create a new image with the specified size specified
226  *              in pixels.  Note that orientation (landscape, portrait,
227  *              is implicit in the pixel dimensions).  Note that
228  *              this routine does not modify the values.
229  *           3) Set all colors to be undefined and then set
230  *              background and foreground colors.
231  *
232  *  xpixels   - width (in pixels) for graphics window
233  *  ypixels   - height (in pixels) for graphics window
234  *  back_col  - background color
235  *  file name - file name (in integer ascii decimal equivalents)
236  *
237  */
238 
239 #if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1
aqeras_(nplot,anumhp,anumvp,iback)240 void aqeras_(nplot, anumhp, anumvp, iback)
241 #elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0
242 void AQERAS_(nplot, anumhp, anumvp, iback)
243 #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1
244 void aqeras(nplot, anumhp, anumvp, iback)
245 #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0
246 void AQERAS(nplot, anumhp, anumvp, iback)
247 #endif
248 int  *nplot, *anumhp, *anumvp, *iback;
249 {
250 
251    int   nplot_temp, anumhp_temp, anumvp_temp, iback_temp;
252 
253    nplot_temp  = *nplot;
254    anumhp_temp = *anumhp;
255    anumvp_temp = *anumvp;
256    iback_temp  = *iback;
257 
258    /* Use "erase rectangle" method to clear screen  */
259    if (OPEN_FLAG_AQUA > 0) {
260       /* aqtTakeBackgroundColorFromColormapEntry(iback_temp); */
261       /* aqtOpenPlot(nplot_temp); */
262       /* aqtSetPlotSize(anumhp_temp,anumvp_temp); */
263       /* aqtClearPlot(); */
264       /* aqtSetPlotTitle("Dataplot Graphics Window"); */
265 
266       aqtTakeColorFromColormapEntry(iback_temp-1);
267       aqtEraseRect(0,0,anumhp_temp,anumvp_temp);
268       aqtAddFilledRect(0,0,anumhp_temp,anumvp_temp);
269 
270       aqtSetFontname("Helvetica");
271       aqtSetFontsize(12.0);
272    }
273 }
274 
275 /* AQEND   - routine to end Aquaterm display and close the display
276  *
277  */
278 #if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1
aqend_()279 void aqend_()
280 #elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0
281 void AQEND_()
282 #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1
283 void aqend()
284 #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0
285 void AQEND()
286 #endif
287 
288 {
289    if (OPEN_FLAG_AQUA > 0) {
290       aqtClosePlot();
291       aqtTerminate();
292       OPEN_FLAG_AQUA = 0;
293    }
294 }
295 
296 /* AQREND   - routine to render current plot
297  *
298  */
299 #if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1
aqrend_()300 void aqrend_()
301 #elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0
302 void AQREND_()
303 #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1
304 void aqrend()
305 #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0
306 void AQREND()
307 #endif
308 
309 {
310    if (OPEN_FLAG_AQUA > 0) {
311       aqtRenderPlot();
312    }
313 }
314 
315 /* AQDRAW  - draw a polyline.  The line attributes are set in
316  *           other routines.
317  *
318  * xpts   - contains the x coordinates
319  * ypts   - contains the y coordinates
320  * npts   - the number of points to plot
321  * icap   - cap style: 1 = Butt
322  *                     2 = Round
323  *                     3 = Square
324  *
325  *          Calling routine should send points in increments of
326  *          1,000.
327  */
328 #if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1
aqdraw_(xpts,ypts,npts,icap)329 void aqdraw_(xpts, ypts, npts, icap)
330 #elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0
331 void AQDRAW_(xpts, ypts, npts, icap)
332 #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1
333 void aqdraw(xpts, ypts, npts)
334 #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0
335 void AQDRAW(xpts, ypts, npts)
336 #endif
337 double   xpts[], ypts[];
338 int   *npts;
339 int   *icap;
340 {
341    int     i;
342    int     iindx;
343    int     npts_temp;
344    int     icap_temp;
345    int     nlast;
346    float   xpts_temp[1000];
347    float   ypts_temp[1000];
348 
349    npts_temp = *npts;
350    icap_temp = *icap;
351 
352    if (OPEN_FLAG_AQUA > 0) {
353       if (icap_temp == 2) {
354         aqtSetLineCapStyle(AQTRoundLineCapStyle);
355       } else if (icap_temp == 3) {
356         aqtSetLineCapStyle(AQTSquareLineCapStyle);
357       } else {
358         aqtSetLineCapStyle(AQTButtLineCapStyle);
359       }
360 
361       nlast = npts_temp;
362       if (nlast > 1000) nlast = 1000;
363       for (i = 0; i < nlast; i++) {
364           /* iindx=2*i; */
365           iindx=i;
366           xpts_temp[i] = xpts[iindx];
367           ypts_temp[i] = ypts[iindx];
368       }
369 
370       if (npts_temp > 0) {
371          aqtAddPolyline(xpts_temp, ypts_temp, npts_temp);
372       }
373    }
374 
375 }
376 
377 /* AQMOVE  - move to a point
378  *
379  * ax1    - contains the x coordinate
380  * ay1    - contains the y coordinate
381  *
382  */
383 #if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1
aqmove_(ax1,ay1)384 void aqmove_(ax1, ay1)
385 #elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0
386 void AQMOVE_(ax1,a1)
387 #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1
388 void aqmove(ax1,ay1)
389 #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0
390 void AQMOVE(ax1,ay1)
391 #endif
392 double   *ax1, *ay1;
393 {
394    float   ax1_temp;
395    float   ay1_temp;
396 
397    ax1_temp = *ax1;
398    ay1_temp = *ay1;
399 
400   aqtMoveTo(ax1_temp,ay1_temp);
401 
402 }
403 
404 /* AQSECO  - set the color
405  *
406  * jcol   - index for desired color
407  *
408  */
409 #if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1
aqseco_(jcol)410 void aqseco_(jcol)
411 #elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0
412 void AQSECO_(jcol)
413 #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1
414 void aqseco(jcol)
415 #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0
416 void AQSECO(jcol)
417 #endif
418 int   *jcol;
419 {
420    int    jcol_temp;
421    float  avalue;
422 
423    jcol_temp = *jcol;
424 
425    if (OPEN_FLAG_AQUA > 0) {
426       if (jcol_temp > 0) {
427          aqtTakeColorFromColormapEntry(jcol_temp-1);
428       } else {
429          avalue = -(float)jcol_temp/100.;
430          aqtSetColor(avalue,avalue,avalue);
431       }
432    }
433 
434 }
435 
436 /* AQSEC2  - set the color using RGB specification
437  *
438  * jred   - index for red component
439  * jgreen - index for green component
440  * jblue  - index for blue component
441  *
442  */
443 #if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1
aqsec2_(jred,jgreen,jblue)444 void aqsec2_(jred,jgreen,jblue)
445 #elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0
446 void AQSEC2_(jred,jgreen,jblue)
447 #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1
448 void aqsec2(jred,jgreen,jblue)
449 #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0
450 void AQSEC2(jred,jgreen,jblue)
451 #endif
452 float   *jred;
453 float   *jgreen;
454 float   *jblue;
455 {
456    float    avalue1;
457    float    avalue2;
458    float    avalue3;
459 
460    avalue1 = *jred;
461    avalue2 = *jgreen;
462    avalue3 = *jblue;
463 
464    if (avalue1 < 0) {
465       avalue1 = 0.0;
466    }
467    if (avalue1 > 1) {
468       avalue1=1.0;
469    }
470    if (avalue2 < 0) {
471       avalue2 = 0.0;
472    }
473    if (avalue2 > 1) {
474       avalue2=1.0;
475    }
476    if (avalue3 < 0) {
477       avalue3 = 0.0;
478    }
479    if (avalue3 > 1) {
480       avalue3=1.0;
481    }
482 
483    if (OPEN_FLAG_AQUA > 0) {
484       aqtSetColor(avalue1,avalue2,avalue3);
485    }
486 
487 }
488 
489 /* AQSEPA  - set line attribute (color set in AQSECO):
490  *
491  * jpatt   - the line pattern
492  * pthick  - the line thickness (in points)
493  *
494  */
495 #if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1
aqsepa_(xpatt,npatt,pthick,iopt)496 void aqsepa_(xpatt,npatt,pthick,iopt)
497 #elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0
498 void AQSEPA_(xpatt,npatt,pthick,iopt)
499 #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1
500 void aqsepa(xpatt,npatt,pthick,iopt)
501 #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0
502 void AQSEPA(xpatt,npatt,pthick,iopt)
503 #endif
504 double  xpatt[];
505 double *pthick;
506 int    *npatt;
507 int    *iopt;
508 {
509    int     npatt_temp;
510    int     iopt_temp;
511    int     iindx;
512    int     i;
513    int     nlast;
514    float   pthick_temp;
515    float   xpatt_temp[8];
516 
517    pthick_temp = *pthick;
518    npatt_temp  = *npatt;
519    iopt_temp   = *iopt;
520 
521    nlast = npatt_temp;
522    if (nlast > 7) nlast = 7;
523    for (i = 0; i < nlast; i++) {
524        /* iindx=2*i; */
525        iindx=i;
526        xpatt_temp[i] = xpatt[iindx];
527    }
528 
529    if (OPEN_FLAG_AQUA > 0) {
530       if (iopt_temp == 1) {
531          if (npatt_temp <= 1) {
532             aqtSetLinestyleSolid();
533          } else {
534             aqtSetLinestylePattern(xpatt_temp,npatt_temp,0.0);
535          }
536       }
537       if (iopt_temp == 2) {
538          aqtSetLinewidth(pthick_temp);
539       }
540    }
541 
542 }
543 
544 /* AQSESI  - set character size
545  *
546  * pheigh   - the desired point size
547  *
548  */
549 #if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1
aqsesi_(pheigh)550 void aqsesi_(pheigh)
551 #elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0
552 void AQSESI_(pheigh)
553 #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1
554 void aqsesi(pheigh)
555 #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0
556 void AQSESI(pheigh)
557 #endif
558 double *pheigh;
559 {
560    float   pheigh_temp;
561 
562    pheigh_temp = *pheigh;
563 
564    if (OPEN_FLAG_AQUA > 0) {
565       aqtSetFontsize(pheigh_temp);
566    }
567 
568 }
569 
570 /* AQPOIN - draw a point.
571  *
572  * ix     - contains the x coordinate
573  * iy     - contains the y coordinate
574  * jcol   - color to use in drawing the point
575  *
576  */
577 #if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1
aqpoin_(ix,iy,ired,igreen,iblue)578 void aqpoin_(ix, iy, ired, igreen, iblue)
579 #elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0
580 void AQPOIN_(ix, iy, ired, igreen, iblue)
581 #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1
582 void aqpoin(ix, iy, ired, igreen, iblue)
583 #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0
584 void AQPOIN(ix, iy, ired, igreen, iblue)
585 #endif
586 int   *ix, *iy;
587 int   *ired, *igreen, *iblue;
588 {
589 
590    unsigned char rgbImage[3] = {255, 255, 255};
591    int    ixtemp;
592    int    iytemp;
593    int    ired_temp;
594    int    igreen_temp;
595    int    iblue_temp;
596 
597    ixtemp = *ix;
598    iytemp = *iy;
599    ired_temp   = *ired;
600    igreen_temp = *igreen;
601    iblue_temp  = *iblue;
602 
603    rgbImage[0] = ired_temp;
604    rgbImage[1] = igreen_temp;
605    rgbImage[2] = iblue_temp;
606 
607    aqtAddImageWithBitmap(rgbImage,1,1,ixtemp,iytemp,4,4);
608 
609 }
610 
611 /* AQRECT - fill a rectangle.
612  *
613  * ix1    - start x position
614  * iy1    - start y position
615  * ix2    - length of x
616  * iy2    - length of y
617  *          otherwise, a convex polygon)
618  *
619  */
620 #if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1
aqrect_(ix1,iy1,ix2,iy2)621 void aqrect_(ix1, iy1, ix2, iy2)
622 #elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0
623 void AQRECT_(ix1, iy1, ix2, iy2)
624 #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1
625 void aqrect(ix1, iy1, ix2, iy2)
626 #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0
627 void AQRECT(ix1, iy1, ix2, iy2)
628 #endif
629 int   *ix1;
630 int   *iy1;
631 int   *ix2;
632 int   *iy2;
633 {
634    int     ix1_temp;
635    int     iy1_temp;
636    int     ix2_temp;
637    int     iy2_temp;
638 
639    ix1_temp = *ix1;
640    iy1_temp = *iy1;
641    ix2_temp = *ix2;
642    iy2_temp = *iy2;
643 
644    if (OPEN_FLAG_AQUA > 0) {
645       aqtAddFilledRect(ix1_temp, iy1_temp, ix2_temp, iy2_temp);
646    }
647 
648 }
649 
650 /* AQRGFL - fill a region.  Rectangular regions will be filled differently
651  *          non-rectangular regions.  Dataplot only handles convex polygons,
652  *          so set this (for faster performance).  This routine only does
653  *          solid fills.  Hatch patterns must be drawn
654  *          by the calling program (i.e., send the individual lines to
655  *          the AQDRAW routine).
656  *
657  * xpts   - contains the x coordinates
658  * ypts   - contains the y coordinates
659  * npts   - the number of points in the polygon (if 2, assume a rectangle,
660  *          otherwise, a convex polygon)
661  *
662  */
663 #define MAX_REG_POINTS  100
664 #if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1
aqrgfl_(xpts,ypts,npts)665 void aqrgfl_(xpts, ypts, npts)
666 #elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0
667 void AQRGFL_(xpts, ypts, npts)
668 #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1
669 void aqrgfl(xpts, ypts, npts)
670 #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0
671 void AQRGFL(xpts, ypts, npts)
672 #endif
673 double   xpts[], ypts[];
674 int   *npts;
675 {
676    int     i;
677    int     iindx;
678    int     npts_temp;
679    int     nlast;
680    float   xpts_temp[MAX_REG_POINTS];
681    float   ypts_temp[MAX_REG_POINTS];
682 
683    npts_temp = *npts;
684    nlast = MAX_REG_POINTS;
685    if (nlast > MAX_REG_POINTS) nlast = MAX_REG_POINTS;
686    for (i = 0; i < nlast; i++) {
687        /* iindx=2*i; */
688        iindx=i;
689        xpts_temp[i] = xpts[iindx];
690        ypts_temp[i] = ypts[iindx];
691    }
692 
693    if (OPEN_FLAG_AQUA > 0) {
694       aqtAddPolygon(xpts_temp, ypts_temp, npts_temp);
695    }
696 
697 }
698 
699 /* AQTXTH - draw a horizontal text string.
700  *
701  * string - text string to draw
702  * ixpos  - x position
703  * iypos  - y position
704  * ijusth - justification (horizontal)
705  *          0 - left justified
706  *          1 - center justified
707  *          2 - right justified
708  * ijustv - justiciation (vertical)
709  *          0 - center justified
710  *          1 - bottom justified
711  *          2 - top justified
712  * font   - font name
713  * error  - error flag
714  *
715  */
716 #if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1
aqtxth_(string,ixpos,iypos,ijusth,ijustv,font,error)717 void aqtxth_(string, ixpos, iypos, ijusth, ijustv, font, error)
718 #elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0
719 void AQTXTH_(string, ixpos, iypos, ijusth, ijustv, font, error)
720 #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1
721 void aqtxth(string, ixpos, iypos, ijusth, ijustv, font, error)
722 #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0
723 void AQTXTH(string, ixpos, iypos, ijusth, ijustv, font, error)
724 #endif
725 int    string[];
726 int    font[];
727 int    *ixpos;
728 int    *iypos;
729 int    *ijusth;
730 int    *ijustv;
731 int    *error;
732 {
733 
734    int    len;                     /* number of characters in string */
735    int    len2;                    /* number of characters in string */
736    int    string_width;            /* width of string in pixels */
737    char   string2[130];            /* converted string */
738    char   font2[130];              /* font name */
739    int    i;
740    int    ixpos_temp;
741    int    iypos_temp;
742    int    ijusth_temp;
743    int    ijustv_temp;
744    int    error_temp;
745    float  xpos;
746    float  ypos;
747 
748    ixpos_temp = *ixpos;
749    iypos_temp = *iypos;
750    ijusth_temp = *ijusth;
751    ijustv_temp = *ijustv;
752 
753    i_to_s_4(string, string2, 130, &len);
754    i_to_s_4(font, font2, 130, &len2);
755 
756    if (len2 > 1) {
757       aqtSetFontname(font2);
758    }
759 
760    xpos = (float)ixpos_temp;
761    ypos = (float)iypos_temp;
762    if (ijusth_temp == 0 && ijustv_temp == 0) {   /* Left-bottom */
763       aqtAddLabel(string2,xpos,ypos,0.0,(AQTAlignLeft | AQTAlignBottom));
764    } else if (ijusth_temp == 0 && ijustv_temp == 1) {   /* Left-center */
765       aqtAddLabel(string2,xpos,ypos,0.0,(AQTAlignLeft | AQTAlignMiddle));
766    } else if (ijusth_temp == 0 && ijustv_temp == 2) {   /* Left-Top */
767       aqtAddLabel(string2,xpos,ypos,0.0,(AQTAlignLeft | AQTAlignTop));
768    } else if (ijusth_temp == 1 && ijustv_temp == 0) {   /* Center-bottom */
769       aqtAddLabel(string2,xpos,ypos,0.0,(AQTAlignCenter | AQTAlignBottom));
770    } else if (ijusth_temp == 1 && ijustv_temp == 1) {   /* Center-Center */
771       aqtAddLabel(string2,xpos,ypos,0.0,(AQTAlignCenter | AQTAlignMiddle));
772    } else if (ijusth_temp == 1 && ijustv_temp == 2) {   /* Center-Top */
773       aqtAddLabel(string2,xpos,ypos,0.0,(AQTAlignCenter | AQTAlignTop));
774    } else if (ijusth_temp == 2 && ijustv_temp == 0) {   /* Right-bottom */
775       aqtAddLabel(string2,xpos,ypos,0.0,(AQTAlignRight | AQTAlignBottom));
776    } else if (ijusth_temp == 2 && ijustv_temp == 1) {   /* Right-Center */
777       aqtAddLabel(string2,xpos,ypos,0.0,(AQTAlignRight | AQTAlignMiddle));
778    } else if (ijusth_temp == 2 && ijustv_temp == 2) {   /* Right-Top */
779       aqtAddLabel(string2,xpos,ypos,0.0,(AQTAlignRight | AQTAlignTop));
780    } else {
781       aqtAddLabel(string2,xpos,ypos,0.0,(AQTAlignLeft | AQTAlignBottom));
782    }
783 
784 }
785 
786 /* AQTXTV - draw a vertical text string.
787  *
788  * string - text string to draw
789  * ixpos  - x position
790  * iypos  - y position
791  * ijusth - justification (horizontal)
792  *          0 - left justified
793  *          1 - center justified
794  *          2 - right justified
795  * ijustv - justiciation (vertical)
796  *          0 - center justified
797  *          1 - bottom justified
798  *          2 - top justified
799  * font   - font name
800  * error  - error flag
801  *
802  */
803 #if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1
aqtxtv_(string,ixpos,iypos,ijusth,ijustv,font,error)804 void aqtxtv_(string, ixpos, iypos, ijusth, ijustv, font, error)
805 #elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0
806 void AQTXTV_(string, ixpos, iypos, ijusth, ijustv, font, error)
807 #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1
808 void aqtxtv(string, ixpos, iypos, ijusth, ijustv, font, error)
809 #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0
810 void AQTXTV(string, ixpos, iypos, ijusth, ijustv, font, error)
811 #endif
812 int    string[];
813 int    font[];
814 int    *ixpos;
815 int    *iypos;
816 int    *ijusth;
817 int    *ijustv;
818 int    *error;
819 {
820 
821    int    len;                     /* number of characters in string */
822    int    string_width;            /* width of string in pixels */
823    char   string2[130];            /* converted string */
824    char   font2[130];              /* font name */
825    int    i;
826    int    ixpos_temp;
827    int    iypos_temp;
828    int    ijusth_temp;
829    int    ijustv_temp;
830    int    error_temp;
831    float  xpos;
832    float  ypos;
833 
834    ixpos_temp = *ixpos;
835    iypos_temp = *iypos;
836    ijusth_temp = *ijusth;
837    ijustv_temp = *ijustv;
838 
839    i_to_s_4(string, string2, 130, &len);
840    i_to_s_4(font, font2, 130, &len);
841 
842    xpos = (float)ixpos_temp;
843    ypos = (float)iypos_temp;
844    if (ijusth_temp == 0 && ijustv_temp == 0) {   /* Left-bottom */
845       aqtAddLabel(string2,xpos,ypos,90.0,(AQTAlignLeft | AQTAlignBottom));
846    } else if (ijusth_temp == 0 && ijustv_temp == 1) {   /* Left-center */
847       aqtAddLabel(string2,xpos,ypos,90.0,(AQTAlignLeft | AQTAlignMiddle));
848    } else if (ijusth_temp == 0 && ijustv_temp == 2) {   /* Left-Top */
849       aqtAddLabel(string2,xpos,ypos,90.0,(AQTAlignLeft | AQTAlignTop));
850    } else if (ijusth_temp == 1 && ijustv_temp == 0) {   /* Center-bottom */
851       aqtAddLabel(string2,xpos,ypos,90.0,(AQTAlignCenter | AQTAlignBottom));
852    } else if (ijusth_temp == 1 && ijustv_temp == 1) {   /* Center-Center */
853       aqtAddLabel(string2,xpos,ypos,90.0,(AQTAlignCenter | AQTAlignMiddle));
854    } else if (ijusth_temp == 1 && ijustv_temp == 2) {   /* Center-Top */
855       aqtAddLabel(string2,xpos,ypos,90.0,(AQTAlignCenter | AQTAlignTop));
856    } else if (ijusth_temp == 2 && ijustv_temp == 0) {   /* Right-bottom */
857       aqtAddLabel(string2,xpos,ypos,90.0,(AQTAlignRight | AQTAlignBottom));
858    } else if (ijusth_temp == 2 && ijustv_temp == 1) {   /* Right-Center */
859       aqtAddLabel(string2,xpos,ypos,90.0,(AQTAlignRight | AQTAlignMiddle));
860    } else if (ijusth_temp == 2 && ijustv_temp == 2) {   /* Right-Top */
861       aqtAddLabel(string2,xpos,ypos,90.0,(AQTAlignRight | AQTAlignTop));
862    } else {
863       aqtAddLabel(string2,xpos,ypos,90.0,(AQTAlignLeft | AQTAlignBottom));
864    }
865 
866 }
867 
868 /* AQRDLO  - routine to read a position from the graphics window (used
869  *           by the Dataplot cross-hair command).  The mouse position at
870  *           the next mouse click will be determined.
871  *
872  *           This routine will wait until a mouse button is pressed.
873  *
874  * ixret   - x coordinate of mouse position when button pressed
875  * iyret   - y coordinate of mouse position when button pressed
876  * error   - error flag
877  *
878  */
879 #if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1
aqrdlo_(ixret,iyret,error)880 void aqrdlo_(ixret, iyret, error)
881 #elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0
882 void AQRDLO_(ixret, iyret, error)
883 #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1
884 void aqrdlo(ixret, iyret, error)
885 #elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0
886 void AQRDLO(ixret, iyret, error)
887 #endif
888 int  *ixret, *iyret, *error;
889 {
890      int running = 0;
891      char buffer[AQT_EVENTBUF_SIZE];
892      int      x, y;
893 
894 
895        *ixret = -1;
896        *iyret = -1;
897        *error = 0;
898 
899        running = 0;
900        while (running == 0) {         /* loop until mouse click */
901 
902           aqtSelectPlot(1);
903           aqtWaitNextEvent(buffer);
904           switch (decodeEvent(buffer, &x, &y)) {
905 
906           case 0:            /* Null Event */
907               *error = 1;
908               running = 1;
909               break;
910 
911           case -1:            /* Error */
912               *error = 1;
913               running = 1;
914               break;
915 
916           case 1:            /* Mouse Click */
917               *ixret = x;
918               *iyret = y;
919               running = 1;
920               break;
921 
922           default:
923               *error = 1;
924               running = 1;
925               break;
926           }       /* end switch */
927        }          /* end while */
928 
929 }
930 
931 /* i_to_s_4  - utitlity routine to convert an integer array containing
932  *           Ascii Decimal Equivalents to a character string array.  The
933  *           Fortran routines pass character type data as an array of
934  *           ADE's, which this routine then converts to C's character
935  *           type.  Note that the input array is assumed to be correct
936  *           (i.e., a value between 0 and 127) and no error checking is
937  *           done on it.
938  *
939  * string1 - input array containing ADE's.
940  * string2 - output array in C character format.
941  * maxlen  - maximum length for string2
942  * ilen    - length of character string
943  *
944  */
i_to_s_4(string1,string2,maxlen,ilen)945 void i_to_s_4(string1, string2, maxlen, ilen)
946 int   string1[], maxlen, *ilen;
947 char  string2[];
948 
949 {
950      int  i;
951      int  itemp;
952      i = 0;
953      while (string1[i] != 0 && i < (maxlen - 1) ) {
954          itemp = string1[i];
955          string2[i] = string1[i];
956          i++;
957      }
958      *ilen = i;
959      string2[i]='\0';
960 }
961 
decodeEvent(char * event,int * x,int * y)962 int decodeEvent(char *event, int *x, int *y)
963 {
964    /* int x, y; */
965    char **ap, *argv[10];
966 
967    /* Split arguments separated by a ':'  */
968    for (ap = argv; (*ap = strsep(&event, ":")) != NULL;)
969       if (**ap != '\0')
970          if (++ap >= &argv[10])
971             break;
972 
973    if (strcmp(argv[0], "42") >= 0)        /* Check for server error */
974       return -1;
975 
976    if (argv[0][0] != '1')                 /* Only check for mouse clicks */
977       return 0;
978 
979    /* sscanf(argv[1], "{%d ,%d}", &x, &y);  */  /* Decode Position */
980    return 1;
981 }
982 
983