open-axiom repository from github
/*1Copyright (C) 1991-2002, The Numerical ALgorithms Group Ltd.2All rights reserved.3Copyright (C) 2007-2008, Gabriel Dos Reis.4All rights reserved.56Redistribution and use in source and binary forms, with or without7modification, are permitted provided that the following conditions are8met:910- Redistributions of source code must retain the above copyright11notice, this list of conditions and the following disclaimer.1213- Redistributions in binary form must reproduce the above copyright14notice, this list of conditions and the following disclaimer in15the documentation and/or other materials provided with the16distribution.1718- Neither the name of The Numerical ALgorithms Group Ltd. nor the19names of its contributors may be used to endorse or promote products20derived from this software without specific prior written permission.2122THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS23IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED24TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A25PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER26OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,27EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,28PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR29PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF30LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING31NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS32SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.33*/343536#define _GFUN_C3738#include <stdio.h>39#include <unistd.h>40#include <stdlib.h>41#include <string.h>4243#include "Gdraws0.h"44#include "G.h"45#include "hash.h"4647#include "Gfun.H1"48#include "cfuns.h"4950using namespace OpenAxiom;515253/*54* Given 2 file pointers, this function copies file ifp to file ofp55*/5657static void58filecopy(FILE * ifp, FILE * ofp)59{6061int c;6263while ((c = getc(ifp)) != EOF)64putc(c, ofp);65}666768/*69* PSCreateFile generates the output file by using the order of defined70* variables; they are used to create the OUTPUT file. Essentially,71* PSCreateFile() loop through the index of 0 to psDrawNo and checks if the72* file/procedure is used. If so, the file is included into the output73* file.74*/7576int77PSCreateFile(78int bWidth, /* border width of picture frame */79Window vw, Window tw, /* viewWindow, and titleWindow */80char *title) /* title of picture to be drawn in title bar */81{82FILE *ifp, *ofp, *fp; /* input, output and temp file pointer */83int i; /* index */8485/* last things to add to the script file */8687fp = fopen(psData[scriptps].filename, "a");88fprintf(fp, "\n grestore\t%% restore graphics state\n\n");89fclose(fp);9091#if 092/* Make frame drawing optional. */9394Gdraws_drawFrame(bWidth, vw, tw, title);95#endif9697/* put procedures and script together into OUTPUT.ps */9899if ((ofp = fopen(psData[output].filename, "w")) == NULL) {100fprintf(stderr, "Cannot open %s to write.\n", psData[output].filename);101return (psError);102}103else {104i = 1;105while (i < psDrawNo) { /* loops through each file/procedure */106if (psData[i].flag) { /* if set, procedure/file is used */107if ((ifp = fopen(psData[i].filename, "r")) == NULL) {108if (i == GCdictps) { /* GC dictionaries */109fprintf(stderr, "Warning: missing GCdictionary.\n");110}111else {112fprintf(stderr, "Cannot open %s to read.\n",113psData[i].filename);114fclose(ofp);115return (psError);116}117}118else {119filecopy(ifp, ofp);120fclose(ifp);121}122}123i++;124}125}126127/* remove script file in tmp */128129unlink(psData[scriptps].filename);130131#if 0132/* remove GCdict file in tmp */133unlink(psData[GCdictps].filename);134#endif135136return (fclose(ofp));137}138139140141/*142* This function draws the frame of the picture, which corresponds to the143* picture frame on the X display. In addition, it draws the title window as144* well as the title of the picture.145*/146147int148Gdraws_drawFrame(149int borderW, /* border width */150Window viewWindow, Window titleWindow,151char *title) /* title of picture */152{153FILE *fp;154XWindowAttributes vwInfo, twInfo;155156/* choose 2 and "frameDict" for frame dictionary: can be anything else */157158PSCreateContext((GC)2, "frameDict", borderW, psButtCap, psMiterJoin,159psWhite, psBlack);160161fp = fopen(psData[scriptps].filename, "a");162163XGetWindowAttributes(dsply, viewWindow, &vwInfo);164165/* draw title window */166167XGetWindowAttributes(dsply, titleWindow, &twInfo);168fprintf(fp, "\t%s\t%d\t%d\t%d\t%d\ttitle\n", "frameDict",169twInfo.height - vwInfo.height, twInfo.width, 0, vwInfo.height);170171/* draw viewport window */172173fprintf(fp, "\t%s\tdrawFrame\n", "frameDict"); /* using Gdraws_setDimension() */174175/* draw title text */176177psData[drawIstrps].flag = yes;178fprintf(fp, "\t%s\tloadFont\n\t%d\t(%s) stringwidth pop sub 2 div\n",179"frameDict", twInfo.width, title);180fprintf(fp, "\t%d\t(%s)\t(%s)\tpsDrawIStr\n", 15, title, "title");181182return (fclose(fp));183}184185186/* setDimension sets the dimension of the picture */187188int189Gdraws_setDimension(190Window viewWindow,191Window titleWindow)192{193FILE *fp;194XWindowAttributes vwInfo, twInfo;195float pageWidth, pageHeight, width;196197fp = fopen(psData[scriptps].filename, "w");198199XGetWindowAttributes(dsply, titleWindow, &twInfo);200XGetWindowAttributes(dsply, viewWindow, &vwInfo);201pageWidth = 575.0;202pageHeight = 750.0;203204#if 0205pageWidth = (float) (DisplayWidth(dsply, scrn) / DisplayWidthMM(dsply, scrn));206pageWidth *= 160.0;207pageHeight = (float) (DisplayHeight(dsply, scrn) / DisplayHeightMM(dsply, scrn));208pageHeight *= 210.0;209fprintf(stderr, "%f, %f\n", pageWidth, pageHeight);210#endif211212fprintf(fp, "\n gsave\t%% save graphics state for clipping path\n\n");213if ((vwInfo.height > pageWidth) || (vwInfo.height > pageHeight)) {214width = (float) vwInfo.width;215if (vwInfo.height > pageWidth) {216width = pageWidth / width;217fprintf(fp, "\t%f\t%f", width, width);218}219else {220if (vwInfo.height > pageHeight)221fprintf(fp, "\t%f\t%f", width, pageHeight / width);222}223}224else {225fprintf(fp, "\t%f\t%f", 1.0, 1.0);226}227fprintf(fp, "\tscale\n\n");228229fprintf(fp, "\t%d\t%d\t%d\tsetDim\n", twInfo.height - vwInfo.height,230vwInfo.height, vwInfo.width);231232/* Write a Bounding Box for psfig etc. */233234fprintf(fp, "%%%%BoundingBox: 0 0 %d %d\n", vwInfo.height, vwInfo.width);235236fprintf(fp, "\tmaxX maxY\t0 0\trectangle\tclip\t%% set clip path\n\n");237return (fclose(fp));238}239/*240* GDrawImageString draws an image text string241*/242243int244GDrawImageString(245GC gc, /* graphics context */246Window wid, /* window id */247int x, int y,248const char* string,249int length, int dFlag)250{251int s;252253switch (dFlag) {254case Xoption:255s = XDrawImageString(dsply, wid, gc, x, y, string, length);256break;257case PSoption:258{259FILE *fp;260261if ((fp = fopen(psData[scriptps].filename, "a")) == NULL) {262fprintf(stderr, "GDrawImageString cannot open %s\n",263psData[scriptps].filename);264return (psError);265}266267psData[drawIstrps].flag = yes; /* set procedure flag */268fprintf(fp, "\t%s\t%d\t%d\t(%s)\t(%s)\tpsDrawIStr\n",269PSfindGC(gc), x, y, string, "window");270s = fclose(fp);271}272break;273default:274fprintf(stderr, "GdrawImagestring request (%d) not implemented yet.\n", dFlag);275return (psError);276}277return (s);278}279280/* Draws an arc; see XDrawArc */281282int283GDrawArc(284GC gc, /* graphics context */285Window wid, /* window id */286int x, int y,287unsigned int wdth, unsigned int hght,288int ang1, int ang2, int dFlag)289{290int s = 0;291292switch (dFlag) {293case Xoption:294XDrawArc(dsply, wid, gc, x, y, wdth, hght, ang1, ang2);295break;296case PSoption:297{298FILE *fp;299300if ((fp = fopen(psData[scriptps].filename, "a")) == NULL) {301fprintf(stderr, "GDrawArc cannot open %s\n",302psData[scriptps].filename);303return (psError);304}305306psData[drawarcps].flag = yes;307fprintf(fp, "\t%s\t%d\t%d\t%d\t%d\t%d\t%d\tpsDrawArc\n",308PSfindGC(gc), x, y, hght, wdth, ang1 / 64, ang2 / 64);309s = fclose(fp);310}311break;312default:313fprintf(stderr, "Gdrawarc request (%d) not implemented yet.\n",314dFlag);315return (psError);316}317return (s);318}319/*320* GDrawLine draws a line, see XDrawLine321*/322323int324GDrawLine(325GC gc, /* graphics context */326Window wid, /* window id */327int x0, int y0, int x1, int y1, int dFlag)328{329int s = 0;330331switch (dFlag) {332case Xoption:333XDrawLine(dsply, wid, gc, x0, y0, x1, y1);334break;335case PSoption:336{337FILE *fp;338339if ((fp = fopen(psData[scriptps].filename, "a")) == NULL) {340fprintf(stderr, "GDrawLine cannot open %s\n",341psData[scriptps].filename);342return (psError);343}344345psData[drawlineps].flag = yes; /* sets procedure flag */346fprintf(fp, "\t%s\t%d\t%d\t%d\t%d\tpsDrawLine\n",347PSfindGC(gc), x1, y1, x0, y0);348s = fclose(fp);349}350break;351default:352fprintf(stderr, "Gdrawline request (%d) not implemented yet.\n",353dFlag);354return (psError);355}356return (s);357}358359360361362363/*364* GDrawLines draws lines; see XDrawLines365*/366367int368GDrawLines(369GC gc, /* graphics context */370Window wid, /* window id */371XPoint * points, /* points */372int numberOfPoints, int mode, int dFlag)373/* number of points, mode and display flag */374{375int s = 0;376377switch (dFlag) {378case Xoption:379XDrawLines(dsply, wid, gc, points, numberOfPoints, mode);380break;381case PSoption:382{383FILE *fp; /* not dealing with modes yet */384int i = 0;385386if ((fp = fopen(psData[scriptps].filename, "a")) == NULL) {387fprintf(stderr, "GDrawLines cannot open %s\n",388psData[scriptps].filename);389return (psError);390}391392psData[drawlinesps].flag = yes; /* set procedure flag */393fprintf(fp, "\t%s\n", PSfindGC(gc));394i = numberOfPoints - 1;395while (i > 0)396{ fprintf(fp, "\t%d\t%d\n", points[i].x, points[i].y);397i = i-1;398}399400fprintf(fp, "\t%d\t%d\t%d\tpsDrawLines\n",401numberOfPoints, points[i].x, points[i].y);402s = fclose(fp);403}404break;405default:406fprintf(stderr, "Gdrawlines request (%d) not implemented yet\n",407dFlag);408return (psError);409}410return (s);411}412413/*414* GDrawPoint draws a point, see XDrawPoint415*/416417int418GDrawPoint(419Window wid, /* window id */420GC gc, /* graphics context */421int x0, int y0, int dFlag)422{423int s = 0;424425switch (dFlag) {426case Xoption:427XDrawPoint(dsply, wid, gc, x0, y0);428break;429case PSoption:430{431FILE *fp;432433if ((fp = fopen(psData[scriptps].filename, "a")) == NULL) {434fprintf(stderr, "GDrawPoint cannot open %s\n",435psData[scriptps].filename);436return (psError);437}438439psData[drawpointps].flag = yes; /* sets procedure flag */440fprintf(fp, "\t%s\t%d\t%d\t%d\t%d\tpsDrawPoint\n",441PSfindGC(gc), x0, y0, x0 + 1, y0 + 1);442s = fclose(fp);443}444break;445default:446fprintf(stderr, "Gdrawpoint request (%d) not implemented yet\n",447dFlag);448return (psError);449}450return (s);451}452453/*454* GDrawRectangle draws a rectangle; see XDrawRectangle455*/456457int458GDrawRectangle(459GC gc,460Window windowId,461short int x,short int y,short int width,short int height,462int dFlag)463{464int s = 0;465466switch (dFlag) {467case Xoption:468XDrawRectangle(dsply, windowId, gc, x, y, width, height);469break;470case PSoption:471{472FILE *fp;473474if ((fp = fopen(psData[scriptps].filename, "a")) == NULL) {475fprintf(stderr, "GDrawRect cannot open %s\n",476psData[scriptps].filename);477return (psError);478}479480psData[drawrectps].flag = yes;481fprintf(fp, "\t%s\t%d\t%d\t%d\t%d\tpsDrawRect\n",482PSfindGC(gc), width, height, x, y);483s = fclose(fp);484}485break;486default:487fprintf(stderr, "Gdrawrect request (%d) not implemented yet\n",488dFlag);489return (psError);490}491return (s);492}493494/*495* GDraw3DButtonOut draws a rectangle with 3D shading on rhs and bottom496*/497498int499GDraw3DButtonOut(500GC gc,501Window windowId,502short int x,short int y,short int width,short int height,503int dFlag)504{505/* draw regular rectangle */506507int s = GDrawRectangle(gc, windowId, x, y, width - 1, height - 1, dFlag);508509/* add extra line down rhs */510511GDrawLine(gc, windowId,512x + width, y + 1, x + width, y + height,513dFlag);514515/* add extra line across bottom */516517GDrawLine(gc, windowId,518x + 1, y + height, x + width, y + height,519dFlag);520521return (s);522}523524/*525* GDraw3DButtonIn draws a rectangle with 3D shading on lhs and top526*/527528int529GDraw3DButtonIn(530GC gc,531Window windowId,532short int x,short int y,short int width,short int height,533int dFlag)534{535/* draw regular rectangle */536537int s = GDrawRectangle(gc, windowId, x + 1, y + 1, width - 1, height - 1, dFlag);538539/* add extra line down lhs */540541GDrawLine(gc, windowId,542x, y, x, y + height - 1,543dFlag);544545/* add extra line across top */546547GDrawLine(gc, windowId,548x, y, x + width - 1, y,549dFlag);550551return (s);552}553554/*555* GDrawPushButton draws a push button whose appearance depends on "isOn."556*/557558int559GDrawPushButton(560Display * display,561GC gc1, GC gc2, GC gc3,562Window windowId,563short int x,short int y,short int width,short int height,564int isOn, const char *text,565unsigned long buttonColor, unsigned long color,566int dFlag)567{568int len = strlen(text);569570if (dFlag == Xoption)571XClearArea(display, windowId, x, y, width + 1, height + 1, False);572573GSetForeground(gc1, (float) buttonColor, dFlag);574575if (isOn)576GDraw3DButtonIn(gc1, windowId, x, y, width, height, dFlag);577else578GDraw3DButtonOut(gc1, windowId, x, y, width, height, dFlag);579580GSetForeground(gc2, (float) color, dFlag);581582return GDrawString(gc2, windowId,583x + (isOn ? 2 : 0) + centerX(gc3, text, len, width),584y + (isOn ? 2 : 0) + centerY(gc3, height),585text, len, dFlag);586}587588589590/*591* Draws a string; see XDrawString592*/593594int595GDrawString(596GC gc, /* graphics context */597Window wid, /* window id */598int x, int y,599const char* string, /* string to be drawn */600int length, int dFlag)601{602int s;603604switch (dFlag) {605case Xoption:606s = XDrawString(dsply, wid, gc, x, y, string, length);607break;608case PSoption:609{610FILE *fp;611612if ((fp = fopen(psData[scriptps].filename, "a")) == NULL) {613fprintf(stderr, "GDrawString cannot open %s\n",614psData[scriptps].filename);615return (psError);616}617618psData[drawstrps].flag = yes; /* sets procedure flag */619fprintf(fp, "\t%s\t(%s)\t%d\t%d\tpsDrawStr\n",620PSfindGC(gc), string, x, y);621622s = fclose(fp);623}624break;625default:626fprintf(stderr, "Gdrawstring request (%d) not implemented yet\n",627dFlag);628return (psError);629}630return (s);631}632633/*634* Draws and fills an arc with foreground color; see XFillArc635*/636637int638GFillArc(639GC gc, /* graphics context */640Window wid, /* window id */641int x, int y,642unsigned int wdth, unsigned int hght,643int ang1, int ang2, int dFlag)644{645int s = 0;646647switch (dFlag) {648case Xoption: /* angle: times 64 already */649XFillArc(dsply, wid, gc, x, y, wdth, hght, ang1, ang2);650break;651case PSoption:652{653FILE *fp;654655if ((fp = fopen(psData[scriptps].filename, "a")) == NULL) {656fprintf(stderr, "GFillArc cannot open %s\n",657psData[scriptps].filename);658return (psError);659}660661psData[fillarcps].flag = yes; /* sets procedure flag */662fprintf(fp, "\t%s\t%d %d\t%d %d\t%d %d\t%d %d\tpsFillArc\n",663PSfindGC(gc), x, y, hght, wdth, ang1 / 64, ang2 / 64,664x + wdth / 2, y + hght / 2);665s = fclose(fp);666}667break;668default:669fprintf(stderr, "GFillArc request (%d) not implemented yet\n",670dFlag);671return (psError);672}673return (s);674}675676/*677* Initializes the path and files to be used.678*/679680int681PSGlobalInit(void)682{ /* This needs to be called only once each683* session. */684char *tmp;685686/* path-independent global file name */687psData[GCdictps].flag = yes;688tmp = tempnam(NULL, "axPS");689sprintf(psData[GCdictps].filename, "%s", tmp);690free(tmp);691psData[setupps].flag = yes;692psData[scriptps].flag = yes;/* new script file name */693psData[endps].flag = yes;694695/* path specific file names */696697if ((envAXIOM = oa_getenv("DEVE")) != NULL) { /* get env var AXIOM */698699psData[headerps].flag = yes;700sprintf(psData[headerps].filename, "%s%s", envAXIOM, "/Gdraws/PS/header.ps");701sprintf(psData[drawps].filename, "%s%s", envAXIOM, "/Gdraws/PS/draw.ps");702sprintf(psData[drawarcps].filename, "%s%s", envAXIOM,703"/Gdraws/PS/drawarc.ps");704sprintf(psData[drawfilledps].filename, "%s%s", envAXIOM,705"/Gdraws/PS/drwfilled.ps");706sprintf(psData[drawcolorps].filename, "%s%s", envAXIOM,707"/Gdraws/PS/drawcolor.ps");708sprintf(psData[fillpolyps].filename, "%s%s", envAXIOM,709"/Gdraws/PS/fillpoly.ps");710sprintf(psData[colorpolyps].filename, "%s%s", envAXIOM,711"/Gdraws/PS/colorpoly.ps");712sprintf(psData[fillwolps].filename, "%s%s", envAXIOM,713"/Gdraws/PS/fillwol.ps");714sprintf(psData[colorwolps].filename, "%s%s", envAXIOM,715"/Gdraws/PS/colorwol.ps");716sprintf(psData[drawpointps].filename, "%s%s", envAXIOM,717"/Gdraws/PS/drawpoint.ps");718sprintf(psData[drawlineps].filename, "%s%s", envAXIOM,719"/Gdraws/PS/drawline.ps");720sprintf(psData[drawlinesps].filename, "%s%s", envAXIOM,721"/Gdraws/PS/drawlines.ps");722sprintf(psData[drawrectps].filename, "%s%s", envAXIOM,723"/Gdraws/PS/drawrect.ps");724sprintf(psData[drawstrps].filename, "%s%s", envAXIOM,725"/Gdraws/PS/drawstr.ps");726sprintf(psData[drawIstrps].filename, "%s%s", envAXIOM,727"/Gdraws/PS/drawIstr.ps");728sprintf(psData[fillarcps].filename, "%s%s", envAXIOM,729"/Gdraws/PS/fillarc.ps");730sprintf(psData[setupps].filename, "%s%s", envAXIOM, "/Gdraws/PS/setup.ps");731sprintf(psData[endps].filename, "%s%s", envAXIOM, "/Gdraws/PS/end.ps");732}733else if ((envAXIOM = oa_getenv("AXIOM")) != NULL) {734psData[headerps].flag = yes;735sprintf(psData[headerps].filename, "%s%s", envAXIOM,736"/lib/graph/header.ps");737sprintf(psData[drawps].filename, "%s%s", envAXIOM,738"/lib/graph/draw.ps");739sprintf(psData[drawarcps].filename, "%s%s", envAXIOM,740"/lib/graph/drawarc.ps");741sprintf(psData[drawfilledps].filename, "%s%s", envAXIOM,742"/lib/graph/drwfilled.ps");743sprintf(psData[drawcolorps].filename, "%s%s", envAXIOM,744"/lib/graph/drawcolor.ps");745sprintf(psData[fillpolyps].filename, "%s%s", envAXIOM,746"/lib/graph/fillpoly.ps");747sprintf(psData[colorpolyps].filename, "%s%s", envAXIOM,748"/lib/graph/colorpoly.ps");749sprintf(psData[fillwolps].filename, "%s%s", envAXIOM,750"/lib/graph/fillwol.ps");751sprintf(psData[colorwolps].filename, "%s%s", envAXIOM,752"/lib/graph/colorwol.ps");753sprintf(psData[drawpointps].filename, "%s%s", envAXIOM,754"/lib/graph/drawpoint.ps");755sprintf(psData[drawlineps].filename, "%s%s", envAXIOM,756"/lib/graph/drawline.ps");757sprintf(psData[drawlinesps].filename, "%s%s", envAXIOM,758"/lib/graph/drawlines.ps");759sprintf(psData[drawrectps].filename, "%s%s", envAXIOM,760"/lib/graph/drawrect.ps");761sprintf(psData[drawstrps].filename, "%s%s", envAXIOM,762"/lib/graph/drawstr.ps");763sprintf(psData[drawIstrps].filename, "%s%s", envAXIOM,764"/lib/graph/drawIstr.ps");765sprintf(psData[fillarcps].filename, "%s%s", envAXIOM,766"/lib/graph/fillarc.ps");767sprintf(psData[setupps].filename, "%s%s", envAXIOM,768"/lib/graph/setup.ps");769sprintf(psData[endps].filename, "%s%s", envAXIOM,770"/lib/graph/end.ps");771}772else {773fprintf(stderr, " need environment variable AXIOM or DEVE; process aborted\n");774return (psError);775}776777return (psInit = yes);778}779780781/*782* This needs to be called for every postscript file generated. It783* initializes the procedure flags.784*/785786int787PSInit(Window vw, Window tw)788{789if (!psInit) {790/* must have PSGlobalInit() called before this */791fprintf(stderr, "Error: need initialization for ps data files: call PSGlobalInit().\n");792return (psError);793}794795sprintf(psData[output].filename, "%s", PSfilename); /* output file name */796797psData[drawps].flag = no; /* ps procedures flags */798psData[drawarcps].flag = no;799psData[drawfilledps].flag = no;800psData[drawcolorps].flag = no;801psData[fillpolyps].flag = no;802psData[fillwolps].flag = no;803psData[colorpolyps].flag = no;804psData[colorwolps].flag = no;805psData[drawpointps].flag = no;806psData[drawlineps].flag = no;807psData[drawlinesps].flag = no;808psData[drawrectps].flag = no;809psData[drawstrps].flag = no;810psData[drawIstrps].flag = no;811psData[fillarcps].flag = no;812813sprintf(psData[scriptps].filename, "%s", tmpnam(NULL)); /* script file */814return (Gdraws_setDimension(vw, tw));815}816817/*818* This procedure sets the line attributes; notice that lineWidth is not set819* for PS, this is because lineWidth of 0, the thinest line on the ps device,820* is device-dependent, thus, we'll leave it and use default. Also lineStyle821* is solid in ps by default, thus we don't need to set it. We'll leave out822* line style here since we really never used anything other than line solid823* which is the default line style in postscript.824*/825826int827PSCreateContext(828GC gc, /* graphics context */829const char *C_gc, /* GC name to be used as postscript variable */830int lineWidth, int capStyle, int joinStyle,831float bg, float fg)832{833FILE *fp;834GCptr newGC, curGC;835836/* get memory for new GC cell */837838if (!(newGC = (GCptr) malloc(sizeof(GCstruct)))) {839fprintf(stderr, "Ran out of memory(malloc) trying to create a ps GC.\n");840exit(-1);841}842843/* attach newGC to chain */844845if (GChead == NULL)846GChead = newGC;847else { /* attach newGC to end of linked list */848curGC = GChead;849while (curGC->next != NULL)850curGC = curGC->next;851curGC->next = newGC;852}853854/* fill newGC with information */855856newGC->GCint = gc;857sprintf(newGC->GCchar, "%s", C_gc);858newGC->next = NULL;859860if ((fp = fopen(psData[GCdictps].filename, "a")) == NULL) {861fprintf(stderr, "PSCreateContext cannot open %s\n",862psData[GCdictps].filename);863return (psError);864}865866fprintf(fp, "\t%d\t%d\t%d\n\t%f\t%f\t/%s\tmakeDict\n", joinStyle,867capStyle, lineWidth, bg, fg, C_gc);868869return (fclose(fp));870}871872/*873* Looks into GC linked list with gc (unsigned long) as index to find the874* character name.875*/876877char *878PSfindGC(GC gc)879{880GCptr curGC;881882curGC = GChead;883while ((curGC != NULL) && (curGC->GCint != gc))884curGC = curGC->next;885886if (curGC == NULL) {887fprintf(stderr, "PSfindGC cannot find gc: %p.\n",gc);888return (NULL);889}890else891return (curGC->GCchar);892}893894/*895* Sets foreground color; see XSetForeground896*/897898int899GSetForeground(900GC gc, /* graphics context */901float color, /* foreground color to be set */902int dFlag) /* display flag: PS, X,... */903{904int s = 0;905906switch (dFlag) {907case Xoption:908XSetForeground(dsply, gc, (unsigned long) color);909break;910case PSoption:911{912FILE *fp;913914if ((fp = fopen(psData[scriptps].filename, "a")) == NULL) {915fprintf(stderr, "GSetForeground cannot open %s\n",916psData[scriptps].filename);917return (0);918}919fprintf(fp, "\t%s\t%f\tsetForeground\n", PSfindGC(gc), color);920s = fclose(fp);921break;922}923default:924fprintf(stderr, "GSetForeground request (%d) not implemented yet\n", dFlag);925return (0);926}927return (s);928}929930/*931* Sets background color; see XSetBackground932*/933934int935GSetBackground(936GC gc, /* graphics context */937float color, /* background color to be set */938int dFlag) /* display flag: PS, X,... */939{940int s = 0;941942switch (dFlag) {943case Xoption:944XSetBackground(dsply, gc, (unsigned long) color);945break;946case PSoption:947{948FILE *fp;949950if ((fp = fopen(psData[scriptps].filename, "a")) == NULL) {951fprintf(stderr, "GSetBackground cannot open %s\n",952psData[scriptps].filename);953return (0);954}955fprintf(fp, "\t%s\t%f\tsetBackground\n", PSfindGC(gc), color);956s = fclose(fp);957break;958}959default:960fprintf(stderr, "GSetBackground request (%d) not implemented yet\n", dFlag);961return (0);962}963return (s);964}965966/*967* See XSetLineAttributes. Notice that we'll not setting line style for968* postscript. This is because solid is the ls in ps and in view3D and 2D,969* we really don't use anything else than solid.970*/971972int973GSetLineAttributes(974GC gc,975int lineWidth, int lineStyle, int capStyle, int joinStyle,976int dFlag)977{978int s = 0;979980switch (dFlag) {981case Xoption:982XSetLineAttributes(dsply, gc, lineWidth, lineStyle,983capStyle, joinStyle);984break;985case PSoption:986{987FILE *fp;988int psCap, psJoin;989990switch (capStyle) {991case 0: /* CapNotLast is not implemented in ps */992case 1:993psCap = psButtCap;994break;995case 2:996psCap = psRoundCap;997break;998case 3:999psCap = psPSqCap;1000break;1001default:1002fprintf(stderr, "cap style: %d unknown, using default.\n", capStyle);1003psCap = psButtCap;1004}10051006switch (joinStyle) {1007case 0:1008psJoin = psMiterJoin;1009break;1010case 1:1011psJoin = psRoundJoin;1012break;1013case 2:1014psJoin = psBevelJoin;1015break;1016default:1017fprintf(stderr, "join style: %d unknown, using default.\n", joinStyle);1018psJoin = psMiterJoin;1019}10201021/*1022* width of zero is machine-dependent and is not recom- mended,1023* we'll use 1 as the thinest line available if (lineWidth < 1)1024* lineWidth = 1;1025*/10261027if ((fp = fopen(psData[scriptps].filename, "a")) == NULL) {1028fprintf(stderr, "GSetLineAttributes cannot open %s\n",1029psData[scriptps].filename);1030return (0);1031}10321033fprintf(fp, "\t%d\t%d\t%d\t%s\tsetLineAttributes\n",1034lineWidth, psCap, psJoin, PSfindGC(gc));1035s = fclose(fp);1036}1037break;1038default:1039fprintf(stderr, "GSetLineAttributes request (%d) not implemented yet\n", dFlag);1040return (0);1041}1042return (s);1043}10441045/*1046* This procedure frees the data structure used for GC information, and also1047* unlinks the GC dictionary file.1048*/10491050int1051PSClose(void)1052{1053if (GChead != NULL) {10541055/* free memory used by GC struct */10561057GCptr curGC = GChead;10581059while (curGC != NULL) {1060GCptr freeGC = curGC;10611062curGC = curGC->next;1063free(freeGC);1064}1065}10661067/* remove GC dictionary file */10681069return (unlink(psData[GCdictps].filename));1070}10711072107310741075int1076centerX (GC viewGCx, const char* theString,int strlength,int windowWidth)1077{1078XFontStruct *fontStruct;1079GContext con;1080int result;108110821083con=XGContextFromGC(viewGCx);1084fontStruct = XQueryFont(dsply,con);1085if(fontStruct == NULL) return(0);1086result = (windowWidth - XTextWidth(fontStruct,theString,strlength))/2 -1087fontStruct->min_bounds.lbearing;1088XFreeFontInfo(NULL,fontStruct,1);1089return(result);1090}109110921093int1094centerY (GC viewGCy,int windowHeight)1095{10961097XFontStruct *fontStruct;1098GContext con;1099int result;11001101con=XGContextFromGC(viewGCy);1102fontStruct = XQueryFont(dsply,con);1103if (fontStruct == NULL) return(0);1104result = (windowHeight -1105(fontStruct->max_bounds.ascent + fontStruct->max_bounds.descent))/2 +1106fontStruct->max_bounds.ascent;1107XFreeFontInfo(NULL,fontStruct,1);1108return(result);11091110}111111121113/*1114* PSColorPolygon draws and fills a polygon given data in XPoint; see1115* XFillPolygon1116*/11171118int1119PSColorPolygon(1120float r, float g, float b, /* red, green and blue color1121* components */1122XPoint * points, /* vertices of polygon */1123int numberOfPoints) /* number of points */1124{1125int i = 0;1126FILE *fp;11271128if ((fp = fopen(psData[scriptps].filename, "a")) == NULL) {1129fprintf(stderr, "PSColorPolygon cannot open %s\n",1130psData[scriptps].filename);1131return (psError);1132}11331134psData[colorpolyps].flag = yes; /* sets procedure flag */11351136fprintf(fp, "\t%f\t%f\t%f\tsetrgbcolor\n", r, g, b);11371138i = numberOfPoints - 1;1139while (i > 0)1140{ fprintf(fp, "\t%d\t%d\n", points[i].x, points[i].y);1141i = i-1;1142}11431144fprintf(fp, "\t%d\t%d\t%d\tpsColorPoly\n", numberOfPoints, points[i].x, points[i].y);11451146return (fclose(fp));1147}114811491150/*1151* PSColorwOutline draws and also outlines the colored polygon.1152*/11531154int1155PSColorwOutline(1156float r, float g, float b, /* red, green and blue color1157* components */1158XPoint * points, /* vertices of polygon */1159int numberOfPoints) /* number of points */1160{1161int i = 0;1162FILE *fp;11631164if ((fp = fopen(psData[scriptps].filename, "a")) == NULL) {1165fprintf(stderr, "PSDrawFOL cannot open %s\n", psData[scriptps].filename);1166return (psError);1167}11681169psData[colorwolps].flag = yes; /* sets procedure flag */11701171fprintf(fp, "\t%f\t%f\t%f\tsetrgbcolor\n", r, g, b);11721173i = numberOfPoints - 1;1174while (i > 0)1175{ fprintf(fp, "\t%d\t%d\n", points[i].x, points[i].y);1176i = i-1;1177}11781179fprintf(fp, "\t%d\t%d\t%d\tpsFillwOutline\n",1180numberOfPoints, points[i].x, points[i].y);11811182return (fclose(fp));1183}1184/*1185* This function does what XDraw would do, notice that only a subset of1186* attributes in GC is implemented -- adequate for our purpose now1187*/11881189int1190PSDrawColor(1191float r, float g, float b, /* red, green and blue color1192* components */1193XPoint *points, /* point list */1194int numberOfPoints) /* vertex count and display flag (X, PS,...) */1195{1196int i = 0;1197FILE *fp;11981199if ((fp = fopen(psData[scriptps].filename, "a")) == NULL) {1200fprintf(stderr, "GDraw cannot open %s\n",1201psData[scriptps].filename);1202return (psError);1203}12041205psData[drawcolorps].flag = yes; /* set procedure flag */12061207fprintf(fp, "\t%f\t%f\t%f\tsetrgbcolor\n", r, g, b);12081209i = numberOfPoints - 1;1210while (i > 0)1211{ fprintf(fp, "\t%d\t%d\n", points[i].x, points[i].y);1212i=i-1;1213}12141215fprintf(fp, "\t%d\t%d\t%d\tpsDrawColor\n", numberOfPoints, points[i].x, points[i].y);12161217return (fclose(fp));1218}1219/*1220* PSFillPolygon draws and fills a polygon given data in XPoint; see1221* XFillPolygon.1222*/12231224int1225PSFillPolygon(1226GC gc, /* graphics context */1227XPoint * points, /* vertices of polygon */1228int numberOfPoints) /* number of points */1229{1230int i = 0;1231FILE *fp;12321233if ((fp = fopen(psData[scriptps].filename, "a")) == NULL) {1234fprintf(stderr, "PSFillPolygon cannot open %s\n",1235psData[scriptps].filename);1236return (psError);1237}12381239psData[fillpolyps].flag = yes; /* sets procedure flag */1240fprintf(fp, "\t%s\n", PSfindGC(gc));12411242i = numberOfPoints - 1;1243while (i > 0)1244{ fprintf(fp, "\t%d\t%d\n", points[i].x, points[i].y);1245i = i-1;1246}12471248fprintf(fp, "\t%d\t%d\t%d\tpsFillPoly\n", numberOfPoints, points[i].x, points[i].y);12491250return (fclose(fp));1251}12521253/*1254* PSFillwOutline draws and also outlines the filled polygon.1255*/12561257int1258PSFillwOutline(1259GC gc, /* graphics context */1260XPoint * points, /* vertices of polygon */1261int numberOfPoints)1262/* number of points */1263{1264int i = 0;1265FILE *fp;12661267if ((fp = fopen(psData[scriptps].filename, "a")) == NULL) {1268fprintf(stderr, "PSDrawFOL cannot open %s\n", psData[scriptps].filename);1269return (psError);1270}12711272psData[fillwolps].flag = yes; /* sets procedure flag */1273fprintf(fp, "\t%s\n", PSfindGC(gc));12741275i = numberOfPoints - 1;1276while (i > 0)1277{ fprintf(fp, "\t%d\t%d\n", points[i].x, points[i].y);1278i = i-1;1279}12801281fprintf(fp, "\t%d\t%d\t%d\tpsFillwOutline\n",1282numberOfPoints, points[i].x, points[i].y);12831284return (fclose(fp));1285}12861287static int1288TrivEqual(Window s1,Window s2)1289{1290return ( s1 == s2);1291}12921293static int1294TrivHash_code(Window s,int size)1295{1296return (s % size);1297}129812991300HashTable *1301XCreateAssocTable(int size)1302{1303HashTable * table;1304table = (HashTable *) malloc(sizeof(HashTable));1305hash_init(table,size,(EqualFunction)TrivEqual,(HashcodeFunction)TrivHash_code);1306return table;1307}13081309void1310XMakeAssoc(Display * dsp, HashTable *table, Window w, int * p)1311{1312hash_insert(table,(char *) p, (char *) w);1313}13141315int *1316XLookUpAssoc(Display * dsp, HashTable *table,Window w)1317{1318return (int *) hash_find(table,(char *)w);1319}13201321void1322XDeleteAssoc(Display * dsp,HashTable * table, Window w)1323{1324hash_delete(table,(char *) w);1325}13261327132813291330133113321333