1 /*
2 Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd.
3 All rights reserved.
4 
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8 
9     - Redistributions of source code must retain the above copyright
10       notice, this list of conditions and the following disclaimer.
11 
12     - Redistributions in binary form must reproduce the above copyright
13       notice, this list of conditions and the following disclaimer in
14       the documentation and/or other materials provided with the
15       distribution.
16 
17     - Neither the name of The Numerical ALgorithms Group Ltd. nor the
18       names of its contributors may be used to endorse or promote products
19       derived from this software without specific prior written permission.
20 
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
22 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
25 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33 
34 
35 #define _GFUN_C
36 
37 #include <stdio.h>
38 #include <unistd.h>
39 #include <stdlib.h>
40 #include <string.h>
41 
42 #include "Gdraws0.h"
43 #include "G.h"
44 #include "hash.h"
45 
46 #include "hash.H1"
47 #include "Gfun.H1"
48 #include "strutil.h"
49 
50 /*
51  * Given 2 file pointers, this function copies file ifp to file ofp
52  */
53 
54 static void
filecopy(FILE * ifp,FILE * ofp)55 filecopy(FILE * ifp, FILE * ofp)
56 {
57 
58   int c;
59 
60   while ((c = getc(ifp)) != EOF)
61     putc(c, ofp);
62 }
63 
64 
65 /*
66  * PSCreateFile generates the output file by using the order of defined
67  * variables; they are used to create the OUTPUT file.  Essentially,
68  * PSCreateFile() loop through the index of 0 to psDrawNo and checks if the
69  * file/procedure is used.      If so, the file is included into the output
70  * file.
71  */
72 
73 int
PSCreateFile(int bWidth,Window vw,Window tw,char * title)74 PSCreateFile(
75              int bWidth,            /* border width of picture frame */
76              Window vw, Window tw,  /* viewWindow, and titleWindow */
77              char *title)           /* title of picture to be drawn in title bar */
78 {
79   FILE *ifp, *ofp, *fp;       /* input, output and temp file pointer */
80   int i;                      /* index */
81 
82   /* last things to add to the script file */
83 
84   fp = fopen(psData[scriptps].filename, "a");
85   fprintf(fp, "\n    grestore\t%% restore graphics state\n\n");
86   fclose(fp);
87 
88 #if 0
89   /* Make frame drawing optional. */
90 
91   Gdraws_drawFrame(bWidth, vw, tw, title);
92 #endif
93 
94   /* put procedures and script together into OUTPUT.ps */
95 
96   if ((ofp = fopen(psData[output].filename, "w")) == NULL) {
97     fprintf(stderr, "Cannot open %s to write.\n", psData[output].filename);
98     return (psError);
99   }
100   else {
101     i = 1;
102     while (i < psDrawNo) {  /* loops through each file/procedure */
103       if (psData[i].flag) { /* if set, procedure/file is used */
104         if ((ifp = fopen(psData[i].filename, "r")) == NULL) {
105           if (i == GCdictps) {  /* GC dictionaries */
106             fprintf(stderr, "Warning: missing GCdictionary.\n");
107           }
108           else {
109             fprintf(stderr, "Cannot open %s to read.\n",
110                     psData[i].filename);
111             fclose(ofp);
112             return (psError);
113           }
114         }
115         else {
116           filecopy(ifp, ofp);
117           fclose(ifp);
118         }
119       }
120       i++;
121     }
122   }
123 
124   /* remove script file in tmp */
125 
126   unlink(psData[scriptps].filename);
127 
128 #if 0
129   /* remove GCdict file in tmp */
130   unlink(psData[GCdictps].filename);
131 #endif
132 
133   return (fclose(ofp));
134 }
135 
136 
137 
138 /*
139  * This function draws the frame of the picture, which corresponds to the
140  * picture frame on the X display.  In addition, it draws the title window as
141  * well as the title of the picture.
142  */
143 
144 int
Gdraws_drawFrame(int borderW,Window viewWindow,Window titleWindow,char * title)145 Gdraws_drawFrame(
146           int borderW,          /* border width */
147           Window viewWindow, Window titleWindow,
148           char *title)          /* title of picture */
149 {
150   FILE *fp;
151   XWindowAttributes vwInfo, twInfo;
152 
153   /* choose 2 and "frameDict" for frame dictionary: can be anything else */
154 
155   PSCreateContext((GC)2, "frameDict", borderW, psButtCap, psMiterJoin,
156                   psWhite, psBlack);
157 
158   fp = fopen(psData[scriptps].filename, "a");
159 
160   XGetWindowAttributes(dsply, viewWindow, &vwInfo);
161 
162   /* draw title window */
163 
164   XGetWindowAttributes(dsply, titleWindow, &twInfo);
165   fprintf(fp, "\t%s\t%d\t%d\t%d\t%d\ttitle\n", "frameDict",
166           twInfo.height - vwInfo.height, twInfo.width, 0, vwInfo.height);
167 
168   /* draw viewport window */
169 
170   fprintf(fp, "\t%s\tdrawFrame\n", "frameDict");      /* using Gdraws_setDimension() */
171 
172   /* draw title text */
173 
174   psData[drawIstrps].flag = yes;
175   fprintf(fp, "\t%s\tloadFont\n\t%d\t(%s) stringwidth pop sub 2 div\n",
176           "frameDict", twInfo.width, title);
177   fprintf(fp, "\t%d\t(%s)\t(%s)\tpsDrawIStr\n", 15, title, "title");
178 
179   return (fclose(fp));
180 }
181 
182 
183 /* setDimension sets the dimension of the picture */
184 
185 int
Gdraws_setDimension(Window viewWindow,Window titleWindow)186 Gdraws_setDimension(
187                     Window viewWindow,
188                     Window titleWindow)
189 {
190   FILE *fp;
191   XWindowAttributes vwInfo, twInfo;
192   float pageWidth, pageHeight, width;
193 
194   fp = fopen(psData[scriptps].filename, "w");
195 
196   XGetWindowAttributes(dsply, titleWindow, &twInfo);
197   XGetWindowAttributes(dsply, viewWindow, &vwInfo);
198   pageWidth = 575.0;
199   pageHeight = 750.0;
200 
201 #if 0
202   pageWidth = (float) (DisplayWidth(dsply, scrn) / DisplayWidthMM(dsply, scrn));
203   pageWidth *= 160.0;
204   pageHeight = (float) (DisplayHeight(dsply, scrn) / DisplayHeightMM(dsply, scrn));
205   pageHeight *= 210.0;
206   fprintf(stderr, "%f, %f\n", pageWidth, pageHeight);
207 #endif
208 
209   fprintf(fp, "\n    gsave\t%% save graphics state for clipping path\n\n");
210   if ((vwInfo.height > pageWidth) || (vwInfo.height > pageHeight)) {
211     width = (float) vwInfo.width;
212     if (vwInfo.height > pageWidth) {
213       width = pageWidth / width;
214       fprintf(fp, "\t%f\t%f", width, width);
215     }
216     else {
217       if (vwInfo.height > pageHeight)
218         fprintf(fp, "\t%f\t%f", width, pageHeight / width);
219     }
220   }
221   else {
222     fprintf(fp, "\t%f\t%f", 1.0, 1.0);
223   }
224   fprintf(fp, "\tscale\n\n");
225 
226   fprintf(fp, "\t%d\t%d\t%d\tsetDim\n", twInfo.height - vwInfo.height,
227           vwInfo.height, vwInfo.width);
228 
229   /* Write a Bounding Box for psfig etc. */
230 
231   fprintf(fp, "%%%%BoundingBox: 0 0 %d %d\n", vwInfo.height, vwInfo.width);
232 
233   fprintf(fp, "\tmaxX maxY\t0 0\trectangle\tclip\t%% set clip path\n\n");
234   return (fclose(fp));
235 }
236 /*
237  * GDrawImageString draws an image text string
238  */
239 
240 int
GDrawImageString(GC gc,Window wid,int x,int y,char * string,int length,int dFlag)241 GDrawImageString(
242                  GC gc,         /* graphics context */
243                  Window wid,    /* window id */
244                  int x, int y,
245                  char *string,
246                  int length, int dFlag)
247 {
248   int s;
249 
250   switch (dFlag) {
251   case Xoption:
252     s = XDrawImageString(dsply, wid, gc, x, y, string, length);
253     break;
254   case PSoption:
255     {
256       FILE *fp;
257 
258       if ((fp = fopen(psData[scriptps].filename, "a")) == NULL) {
259         fprintf(stderr, "GDrawImageString cannot open %s\n",
260                 psData[scriptps].filename);
261         return (psError);
262       }
263 
264       psData[drawIstrps].flag = yes;      /* set procedure flag */
265       fprintf(fp, "\t%s\t%d\t%d\t(%s)\t(%s)\tpsDrawIStr\n",
266               PSfindGC(gc), x, y, string, "window");
267       s = fclose(fp);
268     }
269     break;
270   default:
271     fprintf(stderr, "GdrawImagestring request (%d) not implemented yet.\n", dFlag);
272     return (psError);
273   }
274   return (s);
275 }
276 
277 /* Draws an arc; see XDrawArc */
278 
279 int
GDrawArc(GC gc,Window wid,int x,int y,unsigned int wdth,unsigned int hght,int ang1,int ang2,int dFlag)280 GDrawArc(
281          GC gc,                 /* graphics context */
282          Window wid,            /* window id */
283          int x, int y,
284          unsigned int wdth, unsigned int hght,
285          int ang1, int ang2, int dFlag)
286 {
287   int s = 0;
288 
289   switch (dFlag) {
290   case Xoption:
291     XDrawArc(dsply, wid, gc, x, y, wdth, hght, ang1, ang2);
292     break;
293   case PSoption:
294     {
295       FILE *fp;
296 
297       if ((fp = fopen(psData[scriptps].filename, "a")) == NULL) {
298         fprintf(stderr, "GDrawArc cannot open %s\n",
299                 psData[scriptps].filename);
300         return (psError);
301       }
302 
303       psData[drawarcps].flag = yes;
304       fprintf(fp, "\t%s\t%d\t%d\t%d\t%d\t%d\t%d\tpsDrawArc\n",
305               PSfindGC(gc), x, y, hght, wdth, ang1 / 64, ang2 / 64);
306       s = fclose(fp);
307     }
308     break;
309   default:
310     fprintf(stderr, "Gdrawarc request (%d) not implemented yet.\n",
311             dFlag);
312     return (psError);
313   }
314   return (s);
315 }
316 /*
317  * GDrawLine draws a line, see XDrawLine
318  */
319 
320 int
GDrawLine(GC gc,Window wid,int x0,int y0,int x1,int y1,int dFlag)321 GDrawLine(
322           GC gc,                /* graphics context */
323           Window wid,           /* window id */
324           int x0, int y0, int x1, int y1, int dFlag)
325 {
326   int s = 0;
327 
328   switch (dFlag) {
329   case Xoption:
330     XDrawLine(dsply, wid, gc, x0, y0, x1, y1);
331     break;
332   case PSoption:
333     {
334       FILE *fp;
335 
336       if ((fp = fopen(psData[scriptps].filename, "a")) == NULL) {
337         fprintf(stderr, "GDrawLine cannot open %s\n",
338                 psData[scriptps].filename);
339         return (psError);
340       }
341 
342       psData[drawlineps].flag = yes;      /* sets procedure flag */
343       fprintf(fp, "\t%s\t%d\t%d\t%d\t%d\tpsDrawLine\n",
344               PSfindGC(gc), x1, y1, x0, y0);
345       s = fclose(fp);
346     }
347     break;
348   default:
349     fprintf(stderr, "Gdrawline request (%d) not implemented yet.\n",
350             dFlag);
351     return (psError);
352   }
353   return (s);
354 }
355 
356 
357 
358 
359 
360 /*
361  * GDrawLines draws lines; see XDrawLines
362  */
363 
364 int
GDrawLines(GC gc,Window wid,XPoint * points,int numberOfPoints,int mode,int dFlag)365 GDrawLines(
366            GC gc,               /* graphics context */
367            Window wid,          /* window id */
368            XPoint * points,     /* points */
369            int numberOfPoints, int mode, int dFlag)
370                                 /* number of points, mode and display flag */
371 {
372   int s = 0;
373 
374   switch (dFlag) {
375   case Xoption:
376     XDrawLines(dsply, wid, gc, points, numberOfPoints, mode);
377     break;
378   case PSoption:
379     {
380       FILE *fp;           /* not dealing with modes yet */
381       int i = 0;
382 
383       if ((fp = fopen(psData[scriptps].filename, "a")) == NULL) {
384         fprintf(stderr, "GDrawLines cannot open %s\n",
385                 psData[scriptps].filename);
386         return (psError);
387       }
388 
389       psData[drawlinesps].flag = yes;     /* set procedure flag */
390       fprintf(fp, "\t%s\n", PSfindGC(gc));
391       i = numberOfPoints - 1;
392       while (i > 0)
393       { fprintf(fp, "\t%d\t%d\n", points[i].x, points[i].y);
394         i = i-1;
395       }
396 
397       fprintf(fp, "\t%d\t%d\t%d\tpsDrawLines\n",
398               numberOfPoints, points[i].x, points[i].y);
399       s = fclose(fp);
400     }
401     break;
402   default:
403     fprintf(stderr, "Gdrawlines request (%d) not implemented yet\n",
404             dFlag);
405     return (psError);
406   }
407   return (s);
408 }
409 
410 /*
411  * GDrawPoint draws a point, see XDrawPoint
412  */
413 
414 int
GDrawPoint(Window wid,GC gc,int x0,int y0,int dFlag)415 GDrawPoint(
416            Window wid,          /* window id */
417            GC gc,               /* graphics context */
418            int x0, int y0, int dFlag)
419 {
420   int s = 0;
421 
422   switch (dFlag) {
423   case Xoption:
424     XDrawPoint(dsply, wid, gc, x0, y0);
425     break;
426   case PSoption:
427     {
428       FILE *fp;
429 
430       if ((fp = fopen(psData[scriptps].filename, "a")) == NULL) {
431         fprintf(stderr, "GDrawPoint cannot open %s\n",
432                 psData[scriptps].filename);
433         return (psError);
434       }
435 
436       psData[drawpointps].flag = yes;     /* sets procedure flag */
437       fprintf(fp, "\t%s\t%d\t%d\t%d\t%d\tpsDrawPoint\n",
438               PSfindGC(gc), x0, y0, x0 + 1, y0 + 1);
439       s = fclose(fp);
440     }
441     break;
442   default:
443     fprintf(stderr, "Gdrawpoint request (%d) not implemented yet\n",
444             dFlag);
445     return (psError);
446   }
447   return (s);
448 }
449 
450 /*
451  * GDrawRectangle draws a rectangle; see XDrawRectangle
452  */
453 
454 int
GDrawRectangle(GC gc,Window windowId,short int x,short int y,short int width,short int height,int dFlag)455 GDrawRectangle(
456                GC gc,
457                Window windowId,
458                short int x,short  int y,short  int width,short  int height,
459                int dFlag)
460 {
461   int s = 0;
462 
463   switch (dFlag) {
464   case Xoption:
465     XDrawRectangle(dsply, windowId, gc, x, y, width, height);
466     break;
467   case PSoption:
468     {
469       FILE *fp;
470 
471       if ((fp = fopen(psData[scriptps].filename, "a")) == NULL) {
472         fprintf(stderr, "GDrawRect cannot open %s\n",
473                 psData[scriptps].filename);
474         return (psError);
475       }
476 
477       psData[drawrectps].flag = yes;
478       fprintf(fp, "\t%s\t%d\t%d\t%d\t%d\tpsDrawRect\n",
479               PSfindGC(gc), width, height, x, y);
480       s = fclose(fp);
481     }
482     break;
483   default:
484     fprintf(stderr, "Gdrawrect request (%d) not implemented yet\n",
485             dFlag);
486     return (psError);
487   }
488   return (s);
489 }
490 
491 /*
492  * GDraw3DButtonOut draws a rectangle with 3D shading on rhs and bottom
493  */
494 
495 int
GDraw3DButtonOut(GC gc,Window windowId,short int x,short int y,short int width,short int height,int dFlag)496 GDraw3DButtonOut(
497                  GC gc,
498                  Window windowId,
499                  short int x,short  int y,short  int width,short  int height,
500                  int dFlag)
501 {
502   /* draw regular rectangle */
503 
504   int s = GDrawRectangle(gc, windowId, x, y, width - 1, height - 1, dFlag);
505 
506   /* add extra line down rhs */
507 
508   GDrawLine(gc, windowId,
509             x + width, y + 1, x + width, y + height,
510             dFlag);
511 
512   /* add extra line across bottom */
513 
514   GDrawLine(gc, windowId,
515             x + 1, y + height, x + width, y + height,
516             dFlag);
517 
518   return (s);
519 }
520 
521 /*
522  * GDraw3DButtonIn draws a rectangle with 3D shading on lhs and top
523  */
524 
525 int
GDraw3DButtonIn(GC gc,Window windowId,short int x,short int y,short int width,short int height,int dFlag)526 GDraw3DButtonIn(
527                 GC gc,
528                 Window windowId,
529                 short int x,short  int y,short  int width,short  int height,
530                 int dFlag)
531 {
532   /* draw regular rectangle */
533 
534   int s = GDrawRectangle(gc, windowId, x + 1, y + 1, width - 1, height - 1, dFlag);
535 
536   /* add extra line down lhs */
537 
538   GDrawLine(gc, windowId,
539             x, y, x, y + height - 1,
540             dFlag);
541 
542   /* add extra line across top */
543 
544   GDrawLine(gc, windowId,
545             x, y, x + width - 1, y,
546             dFlag);
547 
548   return (s);
549 }
550 
551 /*
552  * GDrawPushButton draws a push button whose appearance depends on "isOn."
553  */
554 
555 int
GDrawPushButton(Display * display,GC gc1,GC gc2,GC gc3,Window windowId,short int x,short int y,short int width,short int height,int isOn,char * text,unsigned long buttonColor,unsigned long color,int dFlag)556 GDrawPushButton(
557                 Display * display,
558                 GC gc1, GC gc2, GC gc3,
559                 Window windowId,
560                 short int x,short int y,short  int width,short  int height,
561                 int isOn, char *text,
562                 unsigned long buttonColor, unsigned long color,
563                 int dFlag)
564 {
565   int len = strlen(text);
566 
567   if (dFlag == Xoption)
568     XClearArea(display, windowId, x, y, width + 1, height + 1, False);
569 
570   GSetForeground(gc1, (float) buttonColor, dFlag);
571 
572   if (isOn)
573     GDraw3DButtonIn(gc1, windowId, x, y, width, height, dFlag);
574   else
575     GDraw3DButtonOut(gc1, windowId, x, y, width, height, dFlag);
576 
577   GSetForeground(gc2, (float) color, dFlag);
578 
579   return GDrawString(gc2, windowId,
580                      x + (isOn ? 2 : 0) + centerX(gc3, text, len, width),
581                      y + (isOn ? 2 : 0) + centerY(gc3, height),
582                      text, len, dFlag);
583 }
584 
585 
586 
587 /*
588  * Draws a string; see XDrawString
589  */
590 
591 int
GDrawString(GC gc,Window wid,int x,int y,char * string,int length,int dFlag)592 GDrawString(
593             GC gc,              /* graphics context */
594             Window wid,         /* window id */
595             int x, int y,
596             char *string,       /* string to be drawn */
597             int length, int dFlag)
598 {
599   int s;
600 
601   switch (dFlag) {
602   case Xoption:
603     s = XDrawString(dsply, wid, gc, x, y, string, length);
604     break;
605   case PSoption:
606     {
607       FILE *fp;
608 
609       if ((fp = fopen(psData[scriptps].filename, "a")) == NULL) {
610         fprintf(stderr, "GDrawString cannot open %s\n",
611                 psData[scriptps].filename);
612         return (psError);
613       }
614 
615       psData[drawstrps].flag = yes;       /* sets procedure flag */
616       fprintf(fp, "\t%s\t(%s)\t%d\t%d\tpsDrawStr\n",
617               PSfindGC(gc), string, x, y);
618 
619       s = fclose(fp);
620     }
621     break;
622   default:
623     fprintf(stderr, "Gdrawstring request (%d) not implemented yet\n",
624             dFlag);
625     return (psError);
626   }
627   return (s);
628 }
629 
630 /*
631  * Draws and fills an arc with foreground color; see XFillArc
632  */
633 
634 int
GFillArc(GC gc,Window wid,int x,int y,unsigned int wdth,unsigned int hght,int ang1,int ang2,int dFlag)635 GFillArc(
636          GC gc,                 /* graphics context */
637          Window wid,            /* window id */
638          int x, int y,
639          unsigned int wdth, unsigned int hght,
640          int ang1, int ang2, int dFlag)
641 {
642   int s = 0;
643 
644   switch (dFlag) {
645   case Xoption:                   /* angle: times 64 already */
646     XFillArc(dsply, wid, gc, x, y, wdth, hght, ang1, ang2);
647     break;
648   case PSoption:
649     {
650       FILE *fp;
651 
652       if ((fp = fopen(psData[scriptps].filename, "a")) == NULL) {
653         fprintf(stderr, "GFillArc cannot open %s\n",
654                 psData[scriptps].filename);
655         return (psError);
656       }
657 
658       psData[fillarcps].flag = yes;       /* sets procedure flag */
659       fprintf(fp, "\t%s\t%d %d\t%d %d\t%d %d\t%d %d\tpsFillArc\n",
660               PSfindGC(gc), x, y, hght, wdth, ang1 / 64, ang2 / 64,
661               x + wdth / 2, y + hght / 2);
662       s = fclose(fp);
663     }
664     break;
665   default:
666     fprintf(stderr, "GFillArc request (%d) not implemented yet\n",
667             dFlag);
668     return (psError);
669   }
670   return (s);
671 }
672 
673 /*
674  * Initializes the path and files to be used.
675  */
676 
677 int
PSGlobalInit(void)678 PSGlobalInit(void)
679 {                               /* This needs to be called only once each
680                                  * session. */
681   char *tmp;
682 
683   /* path-independent global file name */
684   psData[GCdictps].flag = yes;
685   tmp = tempnam(NULL, "axPS");
686   fricas_sprintf_to_buf1(psData[GCdictps].filename, "%s", tmp);
687   free(tmp);
688   psData[setupps].flag = yes;
689   psData[scriptps].flag = yes;/* new script file name */
690   psData[endps].flag = yes;
691 
692   /* path specific file names */
693 
694   if ((env_fricas = getenv("DEVE")) != NULL) {  /* get env var FRICAS */
695 
696     psData[headerps].flag = yes;
697     fricas_sprintf_to_buf2(psData[headerps].filename, "%s%s", env_fricas, "/Gdraws/PS/header.ps");
698     fricas_sprintf_to_buf2(psData[drawps].filename, "%s%s", env_fricas, "/Gdraws/PS/draw.ps");
699     fricas_sprintf_to_buf2(psData[drawarcps].filename, "%s%s", env_fricas,
700             "/Gdraws/PS/drawarc.ps");
701     fricas_sprintf_to_buf2(psData[drawfilledps].filename, "%s%s", env_fricas,
702             "/Gdraws/PS/drwfilled.ps");
703     fricas_sprintf_to_buf2(psData[drawcolorps].filename, "%s%s", env_fricas,
704             "/Gdraws/PS/drawcolor.ps");
705     fricas_sprintf_to_buf2(psData[fillpolyps].filename, "%s%s", env_fricas,
706             "/Gdraws/PS/fillpoly.ps");
707     fricas_sprintf_to_buf2(psData[colorpolyps].filename, "%s%s", env_fricas,
708             "/Gdraws/PS/colorpoly.ps");
709     fricas_sprintf_to_buf2(psData[fillwolps].filename, "%s%s", env_fricas,
710             "/Gdraws/PS/fillwol.ps");
711     fricas_sprintf_to_buf2(psData[colorwolps].filename, "%s%s", env_fricas,
712             "/Gdraws/PS/colorwol.ps");
713     fricas_sprintf_to_buf2(psData[drawpointps].filename, "%s%s", env_fricas,
714             "/Gdraws/PS/drawpoint.ps");
715     fricas_sprintf_to_buf2(psData[drawlineps].filename, "%s%s", env_fricas,
716             "/Gdraws/PS/drawline.ps");
717     fricas_sprintf_to_buf2(psData[drawlinesps].filename, "%s%s", env_fricas,
718             "/Gdraws/PS/drawlines.ps");
719     fricas_sprintf_to_buf2(psData[drawrectps].filename, "%s%s", env_fricas,
720             "/Gdraws/PS/drawrect.ps");
721     fricas_sprintf_to_buf2(psData[drawstrps].filename, "%s%s", env_fricas,
722             "/Gdraws/PS/drawstr.ps");
723     fricas_sprintf_to_buf2(psData[drawIstrps].filename, "%s%s", env_fricas,
724             "/Gdraws/PS/drawIstr.ps");
725     fricas_sprintf_to_buf2(psData[fillarcps].filename, "%s%s", env_fricas,
726             "/Gdraws/PS/fillarc.ps");
727     fricas_sprintf_to_buf2(psData[setupps].filename, "%s%s", env_fricas, "/Gdraws/PS/setup.ps");
728     fricas_sprintf_to_buf2(psData[endps].filename, "%s%s", env_fricas, "/Gdraws/PS/end.ps");
729   }
730   else if ((env_fricas = getenv("FRICAS")) != NULL) {
731     psData[headerps].flag = yes;
732     fricas_sprintf_to_buf2(psData[headerps].filename, "%s%s", env_fricas,
733             "/lib/graph/header.ps");
734     fricas_sprintf_to_buf2(psData[drawps].filename, "%s%s", env_fricas,
735             "/lib/graph/draw.ps");
736     fricas_sprintf_to_buf2(psData[drawarcps].filename, "%s%s", env_fricas,
737             "/lib/graph/drawarc.ps");
738     fricas_sprintf_to_buf2(psData[drawfilledps].filename, "%s%s", env_fricas,
739             "/lib/graph/drwfilled.ps");
740     fricas_sprintf_to_buf2(psData[drawcolorps].filename, "%s%s", env_fricas,
741             "/lib/graph/drawcolor.ps");
742     fricas_sprintf_to_buf2(psData[fillpolyps].filename, "%s%s", env_fricas,
743             "/lib/graph/fillpoly.ps");
744     fricas_sprintf_to_buf2(psData[colorpolyps].filename, "%s%s", env_fricas,
745             "/lib/graph/colorpoly.ps");
746     fricas_sprintf_to_buf2(psData[fillwolps].filename, "%s%s", env_fricas,
747             "/lib/graph/fillwol.ps");
748     fricas_sprintf_to_buf2(psData[colorwolps].filename, "%s%s", env_fricas,
749             "/lib/graph/colorwol.ps");
750     fricas_sprintf_to_buf2(psData[drawpointps].filename, "%s%s", env_fricas,
751             "/lib/graph/drawpoint.ps");
752     fricas_sprintf_to_buf2(psData[drawlineps].filename, "%s%s", env_fricas,
753             "/lib/graph/drawline.ps");
754     fricas_sprintf_to_buf2(psData[drawlinesps].filename, "%s%s", env_fricas,
755             "/lib/graph/drawlines.ps");
756     fricas_sprintf_to_buf2(psData[drawrectps].filename, "%s%s", env_fricas,
757             "/lib/graph/drawrect.ps");
758     fricas_sprintf_to_buf2(psData[drawstrps].filename, "%s%s", env_fricas,
759             "/lib/graph/drawstr.ps");
760     fricas_sprintf_to_buf2(psData[drawIstrps].filename, "%s%s", env_fricas,
761             "/lib/graph/drawIstr.ps");
762     fricas_sprintf_to_buf2(psData[fillarcps].filename, "%s%s", env_fricas,
763             "/lib/graph/fillarc.ps");
764     fricas_sprintf_to_buf2(psData[setupps].filename, "%s%s", env_fricas,
765             "/lib/graph/setup.ps");
766     fricas_sprintf_to_buf2(psData[endps].filename, "%s%s", env_fricas,
767             "/lib/graph/end.ps");
768   }
769   else {
770     fprintf(stderr, " need environment variable FRICAS or DEVE; process aborted\n");
771     return (psError);
772   }
773 
774   return (psInit = yes);
775 }
776 
777 
778 /*
779  * This needs to be called for every postscript file generated. It
780  * initializes the procedure flags.
781  */
782 
783 int
PSInit(Window vw,Window tw)784 PSInit(Window vw, Window tw)
785 {
786   if (!psInit) {
787     /* must have PSGlobalInit() called before this */
788     fprintf(stderr, "Error: need initialization for ps data files: call PSGlobalInit().\n");
789     return (psError);
790   }
791 
792   fricas_sprintf_to_buf1(psData[output].filename, "%s", PSfilename); /* output file name */
793 
794   psData[drawps].flag = no;   /* ps procedures flags */
795   psData[drawarcps].flag = no;
796   psData[drawfilledps].flag = no;
797   psData[drawcolorps].flag = no;
798   psData[fillpolyps].flag = no;
799   psData[fillwolps].flag = no;
800   psData[colorpolyps].flag = no;
801   psData[colorwolps].flag = no;
802   psData[drawpointps].flag = no;
803   psData[drawlineps].flag = no;
804   psData[drawlinesps].flag = no;
805   psData[drawrectps].flag = no;
806   psData[drawstrps].flag = no;
807   psData[drawIstrps].flag = no;
808   psData[fillarcps].flag = no;
809 
810   fricas_sprintf_to_buf1(psData[scriptps].filename, "%s", tmpnam(NULL));     /* script file */
811   return (Gdraws_setDimension(vw, tw));
812 }
813 
814 /*
815  * This procedure sets the line attributes; notice that lineWidth is not set
816  * for PS, this is because lineWidth of 0, the thinest line on the ps device,
817  * is device-dependent, thus, we'll leave it and use default. Also lineStyle
818  * is solid in ps by default, thus we don't need to set it. We'll leave out
819  * line style here since we really never used anything other than line solid
820  * which is the default line style in postscript.
821  */
822 
823 int
PSCreateContext(GC gc,char * C_gc,int lineWidth,int capStyle,int joinStyle,float bg,float fg)824 PSCreateContext(
825                 GC gc,       /* graphics context */
826                 char *C_gc,     /* GC name to be used as postscript variable */
827                 int lineWidth, int capStyle, int joinStyle,
828                 float bg, float fg)
829 {
830   FILE *fp;
831   GCptr newGC, curGC;
832 
833   /* get memory for new GC cell */
834 
835   if (!(newGC = (GCptr) malloc(sizeof(GCstruct)))) {
836     fprintf(stderr, "Ran out of memory(malloc) trying to create a ps GC.\n");
837     exit(-1);
838   }
839 
840   /* attach newGC to chain */
841 
842   if (GChead == NULL)
843     GChead = newGC;
844   else {                      /* attach newGC to end of linked list */
845     curGC = GChead;
846     while (curGC->next != NULL)
847       curGC = curGC->next;
848     curGC->next = newGC;
849   }
850 
851   /* fill newGC with information */
852 
853   newGC->GCint = gc;
854   fricas_sprintf_to_buf1(newGC->GCchar, "%s", C_gc);
855   newGC->next = NULL;
856 
857   if ((fp = fopen(psData[GCdictps].filename, "a")) == NULL) {
858     fprintf(stderr, "PSCreateContext cannot open %s\n",
859             psData[GCdictps].filename);
860     return (psError);
861   }
862 
863   fprintf(fp, "\t%d\t%d\t%d\n\t%f\t%f\t/%s\tmakeDict\n", joinStyle,
864           capStyle, lineWidth, bg, fg, C_gc);
865 
866   return (fclose(fp));
867 }
868 
869 /*
870  * Looks into GC linked list with gc (unsigned long) as index to find the
871  * character name.
872  */
873 
874 char *
PSfindGC(GC gc)875 PSfindGC(GC gc)
876 {
877   GCptr curGC;
878 
879   curGC = GChead;
880   while ((curGC != NULL) && (curGC->GCint != gc))
881     curGC = curGC->next;
882 
883   if (curGC == NULL) {
884     fprintf(stderr, "PSfindGC cannot find gc: %p.\n",gc);
885     return (NULL);
886   }
887   else
888     return (curGC->GCchar);
889 }
890 
891 /*
892  * Sets foreground color; see XSetForeground
893  */
894 
895 int
GSetForeground(GC gc,float color,int dFlag)896 GSetForeground(
897                GC gc,           /* graphics context */
898                float color,     /* foreground color to be set */
899                int dFlag)       /* display flag: PS, X,... */
900 {
901   int s = 0;
902 
903   switch (dFlag) {
904   case Xoption:
905     XSetForeground(dsply, gc, (unsigned long) color);
906     break;
907   case PSoption:
908     {
909       FILE *fp;
910 
911       if ((fp = fopen(psData[scriptps].filename, "a")) == NULL) {
912         fprintf(stderr, "GSetForeground cannot open %s\n",
913                 psData[scriptps].filename);
914         return (0);
915       }
916       fprintf(fp, "\t%s\t%f\tsetForeground\n", PSfindGC(gc), color);
917       s = fclose(fp);
918       break;
919     }
920   default:
921     fprintf(stderr, "GSetForeground request (%d) not implemented yet\n", dFlag);
922     return (0);
923   }
924   return (s);
925 }
926 
927 /*
928  * Sets background color; see XSetBackground
929  */
930 
931 int
GSetBackground(GC gc,float color,int dFlag)932 GSetBackground(
933                GC gc,           /* graphics context */
934                float color,     /* background color to be set */
935                int dFlag)       /* display flag: PS, X,... */
936 {
937   int s = 0;
938 
939   switch (dFlag) {
940   case Xoption:
941     XSetBackground(dsply, gc, (unsigned long) color);
942     break;
943   case PSoption:
944     {
945       FILE *fp;
946 
947       if ((fp = fopen(psData[scriptps].filename, "a")) == NULL) {
948         fprintf(stderr, "GSetBackground cannot open %s\n",
949                 psData[scriptps].filename);
950         return (0);
951       }
952       fprintf(fp, "\t%s\t%f\tsetBackground\n", PSfindGC(gc), color);
953       s = fclose(fp);
954       break;
955     }
956   default:
957     fprintf(stderr, "GSetBackground request (%d) not implemented yet\n", dFlag);
958     return (0);
959   }
960   return (s);
961 }
962 
963 /*
964  * See XSetLineAttributes.  Notice that we'll not setting line style for
965  * postscript.  This is because solid is the ls in ps and in view3D and 2D,
966  * we really don't use anything else than solid.
967  */
968 
969 int
GSetLineAttributes(GC gc,int lineWidth,int lineStyle,int capStyle,int joinStyle,int dFlag)970 GSetLineAttributes(
971                    GC gc,
972                    int lineWidth, int lineStyle, int capStyle, int joinStyle,
973                    int dFlag)
974 {
975   int s = 0;
976 
977   switch (dFlag) {
978   case Xoption:
979     XSetLineAttributes(dsply, gc, lineWidth, lineStyle,
980                            capStyle, joinStyle);
981     break;
982   case PSoption:
983     {
984       FILE *fp;
985       int psCap, psJoin;
986 
987       switch (capStyle) {
988       case 0:           /* CapNotLast is not implemented in ps */
989       case 1:
990         psCap = psButtCap;
991         break;
992       case 2:
993         psCap = psRoundCap;
994         break;
995       case 3:
996         psCap = psPSqCap;
997         break;
998       default:
999         fprintf(stderr, "cap style: %d unknown, using default.\n", capStyle);
1000         psCap = psButtCap;
1001       }
1002 
1003       switch (joinStyle) {
1004       case 0:
1005         psJoin = psMiterJoin;
1006         break;
1007       case 1:
1008         psJoin = psRoundJoin;
1009         break;
1010       case 2:
1011         psJoin = psBevelJoin;
1012         break;
1013       default:
1014         fprintf(stderr, "join style: %d unknown, using default.\n", joinStyle);
1015         psJoin = psMiterJoin;
1016       }
1017 
1018       /*
1019        * width of zero is machine-dependent and is not recom- mended,
1020        * we'll use 1 as the thinest line available if (lineWidth < 1)
1021        * lineWidth = 1;
1022        */
1023 
1024       if ((fp = fopen(psData[scriptps].filename, "a")) == NULL) {
1025         fprintf(stderr, "GSetLineAttributes cannot open %s\n",
1026                 psData[scriptps].filename);
1027         return (0);
1028       }
1029 
1030       fprintf(fp, "\t%d\t%d\t%d\t%s\tsetLineAttributes\n",
1031               lineWidth, psCap, psJoin, PSfindGC(gc));
1032       s = fclose(fp);
1033     }
1034     break;
1035   default:
1036     fprintf(stderr, "GSetLineAttributes request (%d) not implemented yet\n", dFlag);
1037     return (0);
1038   }
1039   return (s);
1040 }
1041 
1042 /*
1043  * This procedure frees the data structure used for GC information, and also
1044  * unlinks the GC dictionary file.
1045  */
1046 
1047 int
PSClose(void)1048 PSClose(void)
1049 {
1050   if (GChead != NULL) {
1051 
1052     /* free memory used by GC struct */
1053 
1054     GCptr curGC = GChead;
1055 
1056     while (curGC != NULL) {
1057       GCptr freeGC = curGC;
1058 
1059       curGC = curGC->next;
1060       free(freeGC);
1061     }
1062   }
1063 
1064   /* remove GC dictionary file */
1065 
1066   return (unlink(psData[GCdictps].filename));
1067 }
1068 
1069 
1070 
1071 
1072 int
centerX(GC viewGCx,char * theString,int strlength,int windowWidth)1073 centerX (GC viewGCx,char * theString,int strlength,int windowWidth)
1074 {
1075   XFontStruct *fontStruct;
1076   GContext con;
1077   int result;
1078 
1079 
1080   con=XGContextFromGC(viewGCx);
1081   fontStruct = XQueryFont(dsply,con);
1082   if(fontStruct == NULL) return(0);
1083   result = (windowWidth - XTextWidth(fontStruct,theString,strlength))/2 -
1084     fontStruct->min_bounds.lbearing;
1085   XFreeFontInfo(NULL,fontStruct,1);
1086   return(result);
1087 }
1088 
1089 
1090 int
centerY(GC viewGCy,int windowHeight)1091 centerY (GC viewGCy,int windowHeight)
1092 {
1093 
1094   XFontStruct *fontStruct;
1095   GContext con;
1096   int result;
1097 
1098   con=XGContextFromGC(viewGCy);
1099   fontStruct = XQueryFont(dsply,con);
1100   if (fontStruct == NULL) return(0);
1101   result = (windowHeight -
1102             (fontStruct->max_bounds.ascent + fontStruct->max_bounds.descent))/2 +
1103     fontStruct->max_bounds.ascent;
1104   XFreeFontInfo(NULL,fontStruct,1);
1105   return(result);
1106 
1107 }
1108 
1109 
1110 /*
1111  * PSColorPolygon draws and fills a polygon given data in XPoint; see
1112  * XFillPolygon
1113  */
1114 
1115 int
PSColorPolygon(float r,float g,float b,XPoint * points,int numberOfPoints)1116 PSColorPolygon(
1117                float r, float g, float b,       /* red, green and blue color
1118                                                  * components */
1119                XPoint * points,         /* vertices of polygon */
1120                int numberOfPoints)      /* number of points */
1121 {
1122   int i = 0;
1123   FILE *fp;
1124 
1125   if ((fp = fopen(psData[scriptps].filename, "a")) == NULL) {
1126     fprintf(stderr, "PSColorPolygon cannot open %s\n",
1127             psData[scriptps].filename);
1128     return (psError);
1129   }
1130 
1131   psData[colorpolyps].flag = yes;     /* sets procedure flag */
1132 
1133   fprintf(fp, "\t%f\t%f\t%f\tsetrgbcolor\n", r, g, b);
1134 
1135   i = numberOfPoints - 1;
1136   while (i > 0)
1137   { fprintf(fp, "\t%d\t%d\n", points[i].x, points[i].y);
1138     i = i-1;
1139   }
1140 
1141   fprintf(fp, "\t%d\t%d\t%d\tpsColorPoly\n", numberOfPoints, points[i].x, points[i].y);
1142 
1143   return (fclose(fp));
1144 }
1145 
1146 
1147 /*
1148  * PSColorwOutline draws and also outlines the colored polygon.
1149  */
1150 
1151 int
PSColorwOutline(float r,float g,float b,XPoint * points,int numberOfPoints)1152 PSColorwOutline(
1153                 float r, float g, float b,      /* red, green and blue color
1154                                                  * components */
1155                 XPoint * points,        /* vertices of polygon */
1156                 int numberOfPoints)     /* number of points */
1157 {
1158   int i = 0;
1159   FILE *fp;
1160 
1161   if ((fp = fopen(psData[scriptps].filename, "a")) == NULL) {
1162     fprintf(stderr, "PSDrawFOL cannot open %s\n", psData[scriptps].filename);
1163     return (psError);
1164   }
1165 
1166   psData[colorwolps].flag = yes;      /* sets procedure flag */
1167 
1168   fprintf(fp, "\t%f\t%f\t%f\tsetrgbcolor\n", r, g, b);
1169 
1170   i = numberOfPoints - 1;
1171   while (i > 0)
1172   { fprintf(fp, "\t%d\t%d\n", points[i].x, points[i].y);
1173     i = i-1;
1174   }
1175 
1176   fprintf(fp, "\t%d\t%d\t%d\tpsFillwOutline\n",
1177           numberOfPoints, points[i].x, points[i].y);
1178 
1179   return (fclose(fp));
1180 }
1181 /*
1182  * This function does what XDraw would do, notice that only a subset of
1183  * attributes in GC is implemented -- adequate for our purpose now
1184  */
1185 
1186 int
PSDrawColor(float r,float g,float b,XPoint * points,int numberOfPoints)1187 PSDrawColor(
1188             float r, float g, float b,  /* red, green and blue color
1189                                          * components */
1190             XPoint *points,             /* point list */
1191             int numberOfPoints)         /* vertex count and display flag (X, PS,...) */
1192 {
1193   int i = 0;
1194   FILE *fp;
1195 
1196   if ((fp = fopen(psData[scriptps].filename, "a")) == NULL) {
1197     fprintf(stderr, "GDraw cannot open %s\n",
1198             psData[scriptps].filename);
1199     return (psError);
1200   }
1201 
1202   psData[drawcolorps].flag = yes;     /* set procedure flag */
1203 
1204   fprintf(fp, "\t%f\t%f\t%f\tsetrgbcolor\n", r, g, b);
1205 
1206   i = numberOfPoints - 1;
1207   while (i > 0)
1208   { fprintf(fp, "\t%d\t%d\n", points[i].x, points[i].y);
1209     i=i-1;
1210   }
1211 
1212   fprintf(fp, "\t%d\t%d\t%d\tpsDrawColor\n", numberOfPoints, points[i].x, points[i].y);
1213 
1214   return (fclose(fp));
1215 }
1216 /*
1217  * PSFillPolygon draws and fills a polygon given data in XPoint; see
1218  * XFillPolygon.
1219  */
1220 
1221 int
PSFillPolygon(GC gc,XPoint * points,int numberOfPoints)1222 PSFillPolygon(
1223               GC gc,               /* graphics context */
1224               XPoint * points,      /* vertices of polygon */
1225               int numberOfPoints)   /* number of points */
1226 {
1227   int i = 0;
1228   FILE *fp;
1229 
1230   if ((fp = fopen(psData[scriptps].filename, "a")) == NULL) {
1231     fprintf(stderr, "PSFillPolygon cannot open %s\n",
1232             psData[scriptps].filename);
1233     return (psError);
1234   }
1235 
1236   psData[fillpolyps].flag = yes;      /* sets procedure flag */
1237   fprintf(fp, "\t%s\n", PSfindGC(gc));
1238 
1239   i = numberOfPoints - 1;
1240   while (i > 0)
1241   { fprintf(fp, "\t%d\t%d\n", points[i].x, points[i].y);
1242     i = i-1;
1243   }
1244 
1245   fprintf(fp, "\t%d\t%d\t%d\tpsFillPoly\n", numberOfPoints, points[i].x, points[i].y);
1246 
1247   return (fclose(fp));
1248 }
1249 
1250 /*
1251  * PSFillwOutline draws and also outlines the filled polygon.
1252  */
1253 
1254 int
PSFillwOutline(GC gc,XPoint * points,int numberOfPoints)1255 PSFillwOutline(
1256                GC gc,           /* graphics context */
1257                XPoint * points, /* vertices of polygon */
1258                int numberOfPoints)
1259                                /* number of points */
1260 {
1261   int i = 0;
1262   FILE *fp;
1263 
1264   if ((fp = fopen(psData[scriptps].filename, "a")) == NULL) {
1265     fprintf(stderr, "PSDrawFOL cannot open %s\n", psData[scriptps].filename);
1266     return (psError);
1267   }
1268 
1269   psData[fillwolps].flag = yes;       /* sets procedure flag */
1270   fprintf(fp, "\t%s\n", PSfindGC(gc));
1271 
1272   i = numberOfPoints - 1;
1273   while (i > 0)
1274   { fprintf(fp, "\t%d\t%d\n", points[i].x, points[i].y);
1275     i = i-1;
1276   }
1277 
1278   fprintf(fp, "\t%d\t%d\t%d\tpsFillwOutline\n",
1279           numberOfPoints, points[i].x, points[i].y);
1280 
1281   return (fclose(fp));
1282 }
1283 
1284 static int
TrivEqual(Window s1,Window s2)1285 TrivEqual(Window s1,Window s2)
1286 {
1287   return ( s1 == s2);
1288 }
1289 
1290 static int
TrivHash_code(Window s,int size)1291 TrivHash_code(Window s,int size)
1292 {
1293   return (s % size);
1294 }
1295 
1296 
1297 HashTable *
XCreateAssocTable(int size)1298 XCreateAssocTable(int size)
1299 {
1300   HashTable * table;
1301   table = (HashTable *) malloc(sizeof(HashTable));
1302   hash_init(table,size,(EqualFunction)TrivEqual,(HashcodeFunction)TrivHash_code);
1303   return table;
1304 }
1305 
1306 void
XMakeAssoc(Display * dsp,HashTable * table,Window w,int * p)1307 XMakeAssoc(Display * dsp, HashTable *table, Window w, int * p)
1308 {
1309   hash_insert(table,(char *) p, (char *) w);
1310 }
1311 
1312 int *
XLookUpAssoc(Display * dsp,HashTable * table,Window w)1313 XLookUpAssoc(Display * dsp, HashTable *table,Window w)
1314 {
1315   return (int *) hash_find(table,(char *)w);
1316 }
1317 
1318 void
XDeleteAssoc(Display * dsp,HashTable * table,Window w)1319 XDeleteAssoc(Display * dsp,HashTable * table, Window w)
1320 {
1321   hash_delete(table,(char *) w);
1322 }
1323