This is ScrollParse.c in view mode; [Download] [Up]
/* * $RCSfile: ScrollParse.c,v $ * * Copyright (C) 1992 by Adobe Systems Incorporated. * All rights reserved. * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notices appear in all copies and that * both those copyright notices and this permission notice appear in * supporting documentation and that the name of Adobe Systems * Incorporated not be used in advertising or publicity pertaining to * distribution of the software without specific, written prior * permission. If any portion of this software is changed, it cannot be * marketed under Adobe's trademarks and/or copyrights unless Adobe, in * its sole discretion, approves by a prior writing the quality of the * resulting implementation. * * ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR * ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. * ADOBE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY FITNESS FOR A PARTICULAR PURPOSE AND * NON-INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE * TO YOU OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE, STRICT LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT * PROVIDE ANY TRAINING OR OTHER SUPPORT FOR THE SOFTWARE. * * PostScript, Display PostScript, and Adobe are trademarks of Adobe Systems * Incorporated registered in the U.S.A. and other countries. * * Author: Adobe Systems Incorporated */ #include "Scroll.h" #include <DPS/dpsexcept.h> #include <X11/Xos.h> #include <stdlib.h> /*************************************************************** ** ** LOCAL DATA DECLARATIONS ** ***************************************************************/ #define STACKSIZE 256 /* Maximum stack size. */ #define ERR_MSG_LEN 80 /* Size of the error msg buffer */ static UserPath CurrentPath; static Page CurrentPage; static char *dp; /* input data pointer */ static int stackdepth; /* number of elements */ static Any *stacktop; /* ptr to top of stack */ static Any *stack; /* ptr to bottom of stack */ static Point currentpoint; static Point startpoint; static Boolean nocurrentpoint; static BBox pathbbox; static GraphicParams gparms; static char *errmsg; static Boolean error; /* Parsing routines */ static void i_int(), i_real(), i_string(), i_literal(), i_name(), i_array(), i_f(), i_s(), i_clip(), i_T(), i_A(), i_W(), i_AW(), i_m(), i_lineto(), i_L(), i_r(), i_R(), i_l(), i_x(), i_y(), i_X(), i_Y(), i_c(), i_cp(), i_w(), i_g(), i_j(), i_d(), i_miter(), i_cap(), i_RGB(), i_F(), i_FF(), i_DF(), i_MF(), i_IMASK(), i_IMAGE(), i_BPAGE(), i_EPAGE(), i_REMAP(), i_RECODE(), i_initclip(); #define NUM_PROCS 43 /* Size of the procs [] function array */ typedef void (*VoidProc) (); static VoidProc procs[128] = { /* 00 */ i_int, i_real, i_string, i_literal, i_name, i_array, i_f, i_s, /* 08 */ i_clip, i_T, i_A, i_W, i_AW, i_m, i_lineto, i_L, /* 16 */ i_r, i_R, i_l, i_x, i_y, i_X, i_Y, i_c, /* 24 */ i_cp, i_w, i_g, i_j, i_d, i_miter, i_cap, i_RGB, /* 32 */ i_F, i_FF, i_DF, i_MF, i_IMASK, i_IMAGE, i_BPAGE, i_EPAGE, /* 40 */ i_REMAP, i_RECODE, i_initclip }; extern char yytext[]; extern int yyleng; /* Concatenate the string to the generic parser error message and display */ static void showerror(string) String string; { XmString err, msg; msg = XmStringCreateSimple(string); err = XmStringConcat(AppData.parserErrorMessage, msg); XmStringFree(msg); putUpInfoDialog(err); XmStringFree(err); } /* end showerror() */ /* Set error flag and show error message */ static void errorlog(pMsg, pFlag) char *pMsg; Boolean *pFlag; { *pFlag = TRUE; errmsg = pMsg; showerror(errmsg); } /* end errorlog() */ /* Construct error message and show it */ static void errordisplay(token) int token; { static char errbuff[ERR_MSG_LEN]; sprintf(errbuff, "Token=%d, ", token); strcat(errbuff, errmsg); showerror(errbuff); } /* end errordisplay() */ /* Malloc routine that puts up error message if malloc fails */ char *mymalloc(size) unsigned int size; { char *ch = (char *) malloc(size); if (ch == NULL) putUpInfoDialog(AppData.noMemoryMessage); return ch; } /* end mymalloc() */ /* Reads the entire contents of the file into memory */ unsigned long readFileIntoBuffer(f, buff) FILE *f; char **buff; { char *cp; unsigned long fsize, count; struct stat fdata; /* Init the buff pointer to NULL */ *buff = NULL; /* Get the file length and allocate a (maybe huge) buffer */ fstat (fileno(f), &fdata); fsize = (unsigned long) fdata.st_size; /* Don't use XtMalloc since we want to let this fail */ cp = (char *) mymalloc(fsize + 2); if (cp == NULL) count = 0; else { count = fread(cp, 1, fsize, f); if (count != fsize) { putUpInfoDialog(AppData.badReadMessage); free(cp); return 0; } /* Null-terminate the buffer and save control information */ *(cp + count) = '\n'; *(cp + count + 1) = '\0'; *buff = cp; } return count; } /* end of readFileIntoBuffer() */ /* Returns the first character of the next line after cp */ static char *skipToLineEnd(cp) char *cp; { cp = index(cp,'\n'); cp++; return cp; } /* end of skipToLineEnd () */ /* Returns the first nonspace character after a colon */ static char *skipToField (cp) char *cp; { cp = index(cp,':'); cp++; if (*cp == ' ') { rindex(cp, ' '); cp++; } return cp; } /* end of skipToField () */ /* Checks for the valid PostScript header */ static Boolean checkForPS(data) char **data; { Boolean valid = FALSE; if (!strncmp(*data, "%!PS-Adobe-", 11)) valid = TRUE; *data = skipToLineEnd(*data); return valid; } /* end of checkForPS () */ /* Checks if the file was created by the distillery */ static int checkFileType(s0, s1, s2, s3) char *s0, *s1, *s2, *s3; { int type = PS_NOT_KNOWN; if (s0 && *s0 && s1 && *s1 && s2 && *s2 && s3 && *s3) { if (!strncmp(s3, "still.ps", 8)) type = PS_DISTILLERY; } return type; } /* end of checkFileType () */ /* Checks header comments for creator */ static void checkHeader(dataptr, creator) char **dataptr; int *creator; { Boolean done = FALSE; char *cp; char str0[40], str1[40], str2[40], str3[40]; *creator = PS_NOT_KNOWN; cp = *dataptr; while (*cp && !done) { /* Skip any lines that aren't comments */ if (strncmp(cp, "%%", 2) == 0) { cp += 2; /* Look for end-of-comments comments */ if (strncmp(cp, "EndComments", 11) == 0) done = TRUE; /* Look for the Creator field */ else if (strncmp(cp, "Creator:", 8) == 0) { cp = skipToField (cp); sscanf(cp, "%s%s%s%s", str0, str1, str2, str3); *creator = checkFileType(str0, str1, str2, str3); } } cp = skipToLineEnd(cp); } *dataptr = cp; return; } /* end of checkHeader () */ /* Return next character in the buffer */ char igetc () { return *dp++; } /* Initialize the graphics parameters */ void initGraphicParms(ptr) GraphicParams *ptr; { if (ptr) { ptr->path_type = PATH_TYPE_STROKE; ptr->color_type = COLOR_MODEL_GRAY; ptr->gray = 0.0; ptr->red = ptr->green = ptr->blue = 0.0; ptr->linewidth = 1; ptr->miterlimit = 10; ptr->linejoin = ptr->linecap = 0; } } /* end of initGraphicParms () */ /* Reset stored path structure */ static void resetPathStruct() { CurrentPath.num_pts = 0; CurrentPath.num_ops = 0; } /* end resetPathStruct() */ /* One-time parser initialization */ static void parseInitialize() { unsigned int size = STACKSIZE * sizeof(Any); if (CurrentPath.pts == NULL) { CurrentPath.pts = (float *) XtCalloc(PTS_UPATH_BUFFER, sizeof(float)); CurrentPath.ops = (char *) XtCalloc(OPS_UPATH_BUFFER, sizeof(char)); } resetPathStruct(); CurrentPage.qHead = CurrentPage.qTail = NULL; CurrentPage.objNum = 0; CurrentPage.bounds.ll.x = CurrentPage.bounds.ll.y = 9999; CurrentPage.bounds.ur.x = CurrentPage.bounds.ur.y = -9999; initGraphicParms(&gparms); if (stack == NULL) stack = (Any *) XtMalloc((Cardinal) size); nocurrentpoint = TRUE; stackdepth = 0; stacktop = stack; error = FALSE; } /* Parse the buffer */ Page *doParse(buffer) char **buffer; { Boolean parse_err = FALSE; Boolean skip = TRUE; Boolean done = FALSE; int token; dp = *buffer; parseInitialize(); /* Initially we're skipping lines. %%EndPageSetup signals to stop doing that and start parsing them. %%Trailer says we're done */ while (*dp != 0 && !done) { if (*dp == '\n') dp++; else if (!strncmp(dp, "%%", 2)) { dp += 2; if (!strncmp(dp, "Trailer", 7)) done = TRUE; else if (!strncmp(dp, "EndPageSetup", 12)) skip = FALSE; else if (!strncmp(dp, "PageTrailer", 11)) skip = TRUE; dp = index(dp,'\n'); dp++; } else if (skip) { dp = index(dp,'\n'); dp++; } else { /* Get and parse a token */ token = yylex(); while (token && !parse_err) { if (token <= NUM_PROCS) { (*procs[token-1])(); parse_err = error; } else errorlog("unrecognized token", &parse_err); if (!parse_err) token = yylex (); else errordisplay(token); } } } *buffer = dp; return &CurrentPage; } /* end doParse() */ /* Parse the data buffer */ static Page *parseDataBuffer(buffer) char *buffer; { int creator; Page *p; /* Check the buffer for PS-identifying DSC or EPSF comments */ if (!checkForPS (&buffer)) { putUpInfoDialog(AppData.badFileMessage); return NULL; } /* Check the prologue for Creator comments */ checkHeader(&buffer, &creator); /* If Creator isn't a magic name, the input isn't distilled */ if (creator == PS_NOT_KNOWN) { putUpInfoDialog(AppData.badFileMessage); return NULL; } /* ** Having finished with prologue, parse the actual PS program; ** this will also fill the bounding box with the actual ** image dimensions, derived from the bounds of each user path. */ p = doParse(&buffer); if (p == NULL) return NULL; return p; } /* end of parseDataBuffer () */ /* Free all objects in a page */ static void freeObjects(p) Page *p; { Graphic *g, *nextg; for (g = p->qHead; g != NULL; g = nextg) { if (g->parms.path_type != PATH_TYPE_INITCLIP) { XtFree((XtPointer) g->path.pts); XtFree((XtPointer) g->path.ops); } nextg = g->next; XtFree((XtPointer) g); } } /* end freeObjects() */ /* Parse a file by reading it into a buffer and calling parse */ Boolean parseFile(f) FILE *f; { unsigned long bufferSize; char *buffer; Page *p; bufferSize = readFileIntoBuffer(f, &buffer); if (bufferSize != 0) { p = parseDataBuffer(buffer); free(buffer); if (p != NULL) { freeObjects(&AppData.picture); AppData.picture = *p; return True; } } return False; } /* end of parseFile() */ /*************************************************************** ** ** TOKEN PARSING SUBROUTINES ** ***************************************************************/ /* Pop and discard stack */ static void pop() { if (!error) { if (stackdepth > 0) { stackdepth--; stacktop--; } else errorlog("stack underflow", &error); } } /* Clear stack */ static void clear() { while (stackdepth > 0) pop(); } /* Pop and return integer */ static void popint(aval) int *aval; { if (!error) { if (stackdepth > 0) { if (stacktop->type == INTEGER) { *aval = stacktop->element.integer; stackdepth--; stacktop--; } else errorlog("typecheck", &error); } else errorlog("stack underflow", &error); } } /* Pop and return real */ static void popreal(aval) float *aval; { if (!error) { if (stackdepth > 0) { if (stacktop->type == REAL || stacktop->type == INTEGER) { if (stacktop->type == REAL) { *aval = stacktop->element.real; } else *aval = (float) stacktop->element.integer; stackdepth--; stacktop--; } else errorlog("typecheck", &error); } else errorlog("stack underflow", &error); } } /* Push an integer on the stack */ static void pushint(aval) int aval; { if (!error) { if (stackdepth < STACKSIZE) { stackdepth++; stacktop++; stacktop->type = INTEGER; stacktop->element.integer = aval; } else errorlog("stack overflow", &error); } } /* Push a real on the stack */ static void pushreal(aval) float aval; { if (!error) { if (stackdepth < STACKSIZE) { stackdepth++; stacktop++; stacktop->type = REAL; stacktop->element.real = aval; } else errorlog("stack overflow", &error); } } /* Roll stack, like PS roll operator */ static void roll(n, j) int n; int j; { int a, b; Any temp; if (!error) { if (stackdepth - n >= 0) { for (a = j; a > 0; a--) { temp = *stacktop; for (b = 1; b < n; b++) { stack [stackdepth - (b-1)] = stack [stackdepth - b]; } stack[stackdepth - (n - 1)] = temp; } } else errorlog("stack underflow", &error); } } /* Check points against path bounding box and expand if necessary */ static void checkBounds(pts, num_pts, relative) Point *pts; int num_pts; Boolean relative; { int i; Point pt; if (nocurrentpoint && num_pts > 0) { pathbbox.ll.x = pathbbox.ur.x = pts->x; pathbbox.ll.y = pathbbox.ur.y = pts->y; } for (i = 0; i < num_pts; i++) { pt = pts[i]; if (relative) { pt.x += currentpoint.x; pt.y += currentpoint.y; } if (pt.x < pathbbox.ll.x ) pathbbox.ll.x = pt.x; else if (pt.x > pathbbox.ur.x) pathbbox.ur.x = pt.x; if (pt.y < pathbbox.ll.y) pathbbox.ll.y = pt.y; else if (pt.y > pathbbox.ur.y) pathbbox.ur.y = pt.y; } } /* Add an object to the page */ void addObjToPage(pPage, pObj) Page *pPage; Graphic *pObj; { Graphic *pTmp; /* Handle special case of null queue pointers */ if (pPage->qTail == NULL) { /* first obj */ pPage->qHead = pPage->qTail = pObj; pObj->next = NULL; pPage->objNum = 1; } else { /* just add it to the end of the list */ pTmp = pPage->qTail; pObj->next = NULL; pTmp->next = pPage->qTail = pObj; pPage->objNum += 1; } } /* Inset bounding box by deltas */ void insetBox(pBox, deltaX, deltaY) BBox *pBox; float deltaX; float deltaY; { pBox->ll.x += deltaX; pBox->ll.y += deltaY; pBox->ur.x -= deltaX; pBox->ur.y -= deltaY; } /* Copy user path to the object */ void installUPathAndBounds(pObj, pPath, pBBox) Graphic *pObj; UserPath *pPath; BBox *pBBox; { int i; /* Allocate space for the operator and operand arrays */ pObj->path.pts = (float *) XtMalloc(pPath->num_pts * sizeof(float)); pObj->path.ops = (char *) XtMalloc(pPath->num_ops + 1); /* Insert the bounding box and copy in the other operands */ pObj->path.bbox[0] = pBBox->ll.x; pObj->path.bbox[1] = pBBox->ll.y; pObj->path.bbox[2] = pBBox->ur.x; pObj->path.bbox[3] = pBBox->ur.y; for (i = 0; i < pPath->num_pts; i++) pObj->path.pts[i] = pPath->pts[i]; pObj->path.num_pts = pPath->num_pts; /* Insert dps_ucache cmd and copy in the other operators */ pObj->path.ops[0] = dps_ucache; bcopy(pPath->ops, pObj->path.ops+1, pPath->num_ops); pObj->path.num_ops = pPath->num_ops + 1; } /* end of installUPathAndBounds () */ /* Update the page's bounding box */ void updatePageBBox(pPage, pBBox) Page *pPage; BBox *pBBox; { /* Test for extension leftwards */ if (pBBox->ll.x < pPage->bounds.ll.x) pPage->bounds.ll.x = pBBox->ll.x; /* Test for extension downwards */ if (pBBox->ll.y < pPage->bounds.ll.y) pPage->bounds.ll.y = pBBox->ll.y; /* Test for extension rightwards */ if (pBBox->ur.x > pPage->bounds.ur.x) pPage->bounds.ur.x = pBBox->ur.x; /* Test for extension upwards */ if (pBBox->ur.y > pPage->bounds.ur.y) pPage->bounds.ur.y = pBBox->ur.y; } /* Add a path to the page */ static void insertPath(path_type) int path_type; { Graphic *pObj; BBox bbox; if (!error) { if (CurrentPath.num_ops > 0 || path_type == PATH_TYPE_INITCLIP) { bbox = pathbbox; /* If stroking, increase bounding box by half the stroke width */ if (path_type == PATH_TYPE_STROKE) { insetBox (&bbox, -gparms.linewidth/2, -gparms.linewidth/2); } pObj = (Graphic *) XtMalloc(sizeof (Graphic)); gparms.path_type = (unsigned char) path_type; pObj->parms = gparms; if (path_type != PATH_TYPE_INITCLIP) { installUPathAndBounds(pObj, &CurrentPath, &bbox); updatePageBBox(&CurrentPage, &bbox); } addObjToPage(&CurrentPage, pObj); } resetPathStruct(); nocurrentpoint = TRUE; } } /* Reset graphics state at end of page */ static void insertPage() { if (!error) { resetPathStruct(); nocurrentpoint = TRUE; } } /* Add coordinates and an operator to the current path */ static void insertPathCoord(ptr_pts, num_pts, dps_op) Point *ptr_pts; int num_pts; char dps_op; { int i; for (i = 0; i < num_pts; i++, ptr_pts++) { CurrentPath.pts[CurrentPath.num_pts++] = ptr_pts->x; CurrentPath.pts[CurrentPath.num_pts++] = ptr_pts->y; } CurrentPath.ops[CurrentPath.num_ops++] = dps_op; } /* Pop operands from the stack and add an operator to the path */ static void insertPathOp(dps_op, num_args) int dps_op; int num_args; { Boolean relative_op = TRUE; Boolean start_path = FALSE; /* Whether op starts a path segment */ int i, num_pts; Point pts[3]; if (!error) { switch (dps_op) { case dps_rmoveto: start_path = TRUE; break; case dps_moveto: start_path = TRUE; relative_op = FALSE; break; case dps_lineto: case dps_curveto: case dps_closepath: relative_op = FALSE; break; } if ((relative_op || dps_op == dps_closepath) && nocurrentpoint) { errorlog("no currentpoint", &error); } else { /* Take pts off stack and put (back to front) into pts array */ num_pts = num_args/2; for (i = num_pts - 1; i >= 0; i--) { popreal(&pts[i].y); popreal(&pts[i].x); } if (!error) { /* Path from end to start and check bounds. */ checkBounds(pts, num_pts, relative_op); insertPathCoord(pts, num_pts, dps_op); if (relative_op) { currentpoint.x += pts[num_pts-1].x; currentpoint.y += pts[num_pts-1].y; } else if (dps_op == dps_closepath) currentpoint = startpoint; else currentpoint = pts[num_pts-1]; if (start_path) startpoint = currentpoint; nocurrentpoint = FALSE; } } } } /* Utilities to set graphics state parameters */ static void setgray(fval) float fval; { gparms.gray = fval; gparms.color_type = COLOR_MODEL_GRAY; } static void setlinewidth(fval) float fval; { gparms.linewidth = fval; } static void setlinejoin(ival) int ival; { gparms.linejoin = (unsigned char) ival; } static void setmiterlimit(fval) float fval; { gparms.miterlimit = fval; } static void setlinecap (ival) int ival; { gparms.linecap = (unsigned char) ival; } static void setrgbcolor(r, g, b) float r, g, b; { gparms.red = r; gparms.green = g; gparms.blue = b; gparms.color_type = COLOR_MODEL_RGB; } /*************************************************************** ** ** FIRST-LEVEL TOKEN PARSING FUNCTIONS ** ***************************************************************/ /* integer */ static void i_int() { int avalue; sscanf(yytext,"%d", &avalue); pushint(avalue); } /* real number */ static void i_real() { float avalue; sscanf(yytext,"%f", &avalue); pushreal(avalue); } /* literal -- skip it */ static void i_literal() { } /* name -- skip it */ static void i_name() { } /* array -- skip it */ static void i_array() { } /* string -- skip it */ static void i_string() { } /* f (fill) operator */ static void i_f() { insertPath(PATH_TYPE_FILL); } /* s (stroke) operator */ static void i_s() { insertPath(PATH_TYPE_STROKE); } /* clip operator */ static void i_clip() { insertPath(PATH_TYPE_CLIP); } /* T (text) operator -- unimplemented */ static void i_T() { clear(); } /* A (ashow) operator -- unimplemented */ static void i_A() { clear(); } /* W (widthshow) operator -- unimplemented */ static void i_W() { clear(); } /* AW (awidthshow) operator -- unimplemented */ static void i_AW() { clear(); } /* m (moveto) operator */ static void i_m() { insertPathOp(dps_moveto, 2); } /* lineto operator */ static void i_lineto() { insertPathOp (dps_lineto, 2); } /* L (multiple lineto) operator */ static void i_L() { int i, index; popint(&index); /* number of lines */ for (i = index; i > 0; i--) insertPathOp(dps_lineto,2); } /* r (rlineto) operator */ static void i_r() { insertPathOp(dps_rlineto, 2); } /* R (multiple rlineto) operator */ static void i_R() { int i, index; popint (&index); for (i = index; i > 0; i--) insertPathOp(dps_rlineto, 2); } /* l (moveto-lineto) operator */ static void i_l() { insertPathOp(dps_moveto, 2); insertPathOp(dps_lineto, 2); insertPath(PATH_TYPE_STROKE); } /* x (horizontal rlineto) operator */ static void i_x() { pushreal(0.0); insertPathOp(dps_rlineto, 2); } /* y (vertical rlineto) operator */ static void i_y() { pushreal(0.0); roll(2, 1); insertPathOp(dps_rlineto, 2); } /* X (moveto-horizontal rlineto) operator */ static void i_X() { insertPathOp(dps_moveto, 2); pushreal(0.0); insertPathOp(dps_rlineto, 2); insertPath(PATH_TYPE_STROKE); } /* Y (moveto-vertical rlineto) operator */ static void i_Y() { insertPathOp(dps_moveto, 2); pushreal(0.0); roll(2, 1); insertPathOp(dps_rlineto, 2); insertPath(PATH_TYPE_STROKE); } /* c (curveto) operator */ static void i_c() { insertPathOp (dps_curveto, 6); } /* cp (closepath) operator */ static void i_cp() { insertPathOp (dps_closepath, 0); } /* w (setlinewidth) operator */ static void i_w() { float avalue; popreal(&avalue); setlinewidth(avalue); } /* g (setgray) operator */ static void i_g() { float avalue; popreal(&avalue); setgray(avalue); } /* j (setlinejoin) operator */ static void i_j() { int avalue; popint(&avalue); setlinejoin(avalue); } /* d (setdash) operator -- unimplemented */ static void i_d() { clear(); } /* setmiterlimit operator */ static void i_miter() { float avalue; popreal(&avalue); setmiterlimit(avalue); } /* setlinecap operator */ static void i_cap() { float data; unsigned parm; popreal(&data); parm = (unsigned) floor(data); setlinecap(parm); } /* RGB (setrgbcolor) operator */ static void i_RGB() { float r, g, b; popreal(&b); popreal(&g); popreal(&r); setrgbcolor (r, g, b); } /* F (setfont) operator -- unimplemented */ static void i_F() { /* setfont not implemented */ clear(); } /* MF (makefont) operator -- unimplemented */ static void i_MF() { clear(); } /* FF (setfont) operator -- unimplemented */ static void i_FF() { clear(); } /* DF (definefont) operator -- unimplemented */ static void i_DF() { clear(); } /* IMASK (imagemask) operator -- unimplemented */ static void i_IMASK() { clear(); } /* IMAGE (image) operator -- unimplemented */ static void i_IMAGE() { clear(); } /* BPAGE (begin page) operator -- unimplemented */ static void i_BPAGE() { pop(); } /* EPAGE (end page) operator -- unimplemented */ static void i_EPAGE() { pop(); insertPage(); } /* REMAP (font remapping) operator -- unimplemented */ static void i_REMAP() { clear(); } /* RECODE (font reencoding) operator -- unimplemented */ static void i_RECODE() { clear(); } /* initclip operator */ static void i_initclip() { insertPath(PATH_TYPE_INITCLIP); } /*************************************************************** ** ** DISTILLERY FUNCTIONS ** ***************************************************************/ /* Special DPS text handler procedure that saves the output of the DPSContext to a file. */ static FILE *outfile; static Boolean writeErr; void saveTextProc (ctxt, buff, count) DPSContext ctxt; char *buff; unsigned long count; { unsigned long wrote; if (writeErr || buff == NULL || count <= 0) return; wrote = fwrite(buff, 1, count, outfile); if (wrote != count) { putUpInfoDialog(AppData.badWriteMessage); writeErr = True; } } /* end of saveTextProc () */ /* Special DPS text handler procedure that throws away the text output of the DPSContext. */ void tossTextProc(ctxt, buff, count) DPSContext ctxt; char *buff; long count; { } /* end of tossTextProc () */ /* Convert a file into its distilled form */ void distillFile(f, name) FILE *f; String name; { #ifndef FILENAME_MAX #define FILENAME_MAX 1024 #endif FILE *dfile; int len; char *cp; char *dname; char nbuff [FILENAME_MAX]; Boolean errflag; static DPSContext ctxt; static char startCmd[] = "resyncstart clear cleardictstack\n"; /* Create a context for the distiller. Don't user our main one to protect from possible distillery bugs */ if (ctxt == NULL) { ctxt = XDPSCreateSimpleContext(XtDisplay(AppData.time), NULL, AppData.gc, 0, 0, DPSDefaultTextBackstop, DPSDefaultErrorProc, NULL); if (ctxt == NULL) { putUpInfoDialog(AppData.noDistillContextMessage); return; } /* resync and init the context */ DPSWritePostScript(ctxt, startCmd, strlen(startCmd)); } DPSSetTextProc(ctxt, tossTextProc); /* Read the distillery program into a buffer */ dname = getenv("POSTSCRIPT_DISTILLERY"); if (dname == NULL) dname = "still.ps"; dfile = fopen(dname, "r"); if (dfile == NULL) { putUpInfoDialog(AppData.noDistillFileMessage); return; } if ((len = readFileIntoBuffer (dfile, &cp)) == 0) { fclose(dfile); putUpInfoDialog(AppData.noMemoryMessage); return; } fclose(dfile); /* Load the distiller program into the context */ errflag = FALSE; DURING DPSWritePostScript(ctxt, cp, len + 1); HANDLER DPSResetContext(ctxt); errflag = TRUE; END_HANDLER free(cp); if (errflag) { putUpInfoDialog(AppData.distillErrorMessage); return; } /* Change the source filename into the target filename */ strcpy(nbuff, name); cp = rindex(nbuff, '.'); *cp = '\0'; strcat(nbuff, ".dst"); /* Load the input file into a buffer */ if ((len = readFileIntoBuffer(f, &cp)) == 0) { putUpInfoDialog(AppData.noMemoryMessage); return; } /* Open the output file for writing */ if ((outfile = fopen(nbuff, "w")) == NULL) { putUpInfoDialog(AppData.noOutputFileMessage); return; } /* Blast the input file at the context */ DPSPrintf(ctxt, "distill\n"); writeErr = False; DPSSetTextProc(ctxt, saveTextProc); DPSWaitContext(ctxt); DURING DPSWritePostScript (ctxt, cp, len + 1); HANDLER DPSResetContext(ctxt); errflag = TRUE; END_HANDLER free(cp); DPSWaitContext(ctxt); DPSSetTextProc(ctxt, tossTextProc); fclose(outfile); if (errflag) putUpInfoDialog(AppData.distillErrorMessage); else putUpInfoDialog(AppData.distillCompleteMessage); } /* end of distillFile() */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.