BSD 4_4_Lite2 development
authorCSRG <csrg@ucbvax.Berkeley.EDU>
Tue, 2 Sep 1986 10:44:11 +0000 (02:44 -0800)
committerCSRG <csrg@ucbvax.Berkeley.EDU>
Tue, 2 Sep 1986 10:44:11 +0000 (02:44 -0800)
Work on file usr/src/contrib/dipress/src/bin/dipress/ipress.c

Synthesized-from: CSRG/cd3/4.4BSD-Lite2

usr/src/contrib/dipress/src/bin/dipress/ipress.c [new file with mode: 0644]

diff --git a/usr/src/contrib/dipress/src/bin/dipress/ipress.c b/usr/src/contrib/dipress/src/bin/dipress/ipress.c
new file mode 100644 (file)
index 0000000..75a6752
--- /dev/null
@@ -0,0 +1,1030 @@
+
+/*-----------------------------------------------------------------------------
+ * Copyright (c) 1984, 1985, 1986 Xerox Corp.
+ *
+ *  ipress - most of the code directly dependent on interpress used by dipress
+ *          to produce an interpress file from device independent troff
+ *          intermediate code.  
+ *
+ *  William LeFebvre
+ *
+ *
+ * HISTORY
+ * 12-Aug-86  Lee Moore (lee) at Xerox Webster Research Center
+ *     Added positioning option to the RES command.
+ *     
+ *
+ * 07-Jul-86  Lee Moore (lee) at Xerox Webster Research Center
+ *     Updated IPDeviceType for services 10.0 .
+ *
+ * 24-Feb-86  Lee Moore (lee) at Xerox Webster Research Center
+ *     Added a subroutine to emit the SequenceInsertFile command.
+ *
+ * John Mellor-Crummey 28-aug-1985
+ *     restructuring and minor modifications
+ *
+ * ed flint 10-may-1985
+ *     coerce device.num_char_wid to unsigned char, change
+ *     ch argument in outputChar to unsigned int 
+ *     since we now have > 128 special characters
+ *---------------------------------------------------------------------------*/
+
+
+#include <stdio.h>
+#include <ctype.h>
+#include <signal.h>
+#include <math.h>
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+
+#include "deviceinfo.h"        /* typesetter characteristics */
+
+#include "iptokens.h"  /* \                                    */
+#include "literal.h"   /*  > interface levels for interpress   */
+#include "operator.h"  /* /                                    */
+
+#include "defs.h"      /* constant and macro definitions */
+#include "externs.h"   /* declarations for global variables */
+
+
+
+/* initialize device */
+initDevice()           
+{
+       int  lines = 0;
+       int  timapf;
+       int  ret;
+       register char *ptr;
+       register char **ipp;
+       register char **trp;
+       char temp[60];
+       struct stat stbuf;
+
+       if (dbg) printf("initDevice called\n");
+
+       /* start the preamble */
+       ip_select(outputfile);
+       /* special master instructions go here... */
+       AppendOp(OP_beginBlock);
+       AppendOp(OP_beginBody);
+
+       /* save scaling transform that uses a mica co-ordinate system */
+       AppendRational(1L, 100000);
+       AppendOp(OP_scale);
+       AppendInteger((long) F_transform);
+       AppendOp(OP_fset);
+
+       /* select file that holds page bodies */
+       ip_select(pagebodyfile);
+
+       /* open file that maps troff names to interpress names */
+       (void) sprintf(temp, "%s/dev%s/interpress-fonts", fontdirectory, devicename);
+       if ((timapf = open(temp, O_RDONLY,0)) == -1)
+               reportError(QUIT, "can't open %s (%s)", temp, sys_errlist[errno]);
+
+       /* read in the whole thing */
+       ret = fstat(timapf, &stbuf);
+       if (dbg) printf("stat returned %d, errno %d\n", ret, errno);
+       timap = malloc((unsigned)(stbuf.st_size + 1));
+       if (dbg) printf("reading %d bytes from timapf\n", stbuf.st_size);
+       ret = read(timapf, timap, (int)stbuf.st_size);
+       if (dbg) printf("read returned %d, errno %d, timapf %d\n", ret, errno, timapf);
+       timap[(int)stbuf.st_size] = '\0';
+       (void) close(timapf);
+
+       /* count the newlines */
+       if (dbg) printf("pointer starts at %08x ... ", timap);
+
+       for (ptr = timap; *ptr != '\0'; ptr++)
+               if (*ptr == '\n') lines++;
+
+       if (dbg) printf("ends at %08x\n", ptr);
+       if (dbg) printf("found %d lines\n", lines);
+
+       /* allocate the mapping arrays */
+       trp = trname = (char **)malloc((unsigned)(lines * 2 * sizeof(char *)));
+       ipp = ipname = trname + lines;
+
+       /* break out the strings and store pointers in the arrays */
+       ptr = timap;
+       mapcnt = 0;
+       while (*ptr)
+       {
+               if (dbg) printf("loop: ptr = %08x, *ptr = %c\n", ptr, *ptr);
+               *trp++ = ptr;
+               while (!white(*ptr)) ptr++;
+               *ptr++ = '\0';
+               while (white(*ptr)) ptr++;
+               *ipp++ = ptr;
+               while (*++ptr != '\n') /* nothing */;
+               *ptr++ = '\0';
+               mapcnt++;
+       }
+
+       if (dbg)
+       {
+               int i;
+
+               for (i = 0; i < lines; i++)
+                       printf("%s\t%s\n", trname[i], ipname[i]);
+       }
+
+       /* reset vertical and horizontal positions */
+       hor_pos = ver_pos = old_hor = old_ver = 0;
+
+       /* reset the font information */
+       bzero((char *) currfonts, sizeof(currfonts));
+}
+
+setScale(spi)          /* set resolution */
+
+int spi;
+
+{
+       /* set the scaling variable used in all x and y calculations */
+       scale = floor(2540.0 / (double)spi + 0.5);
+       if (dbg) printf("setScale(%d) sets scale to %e\n", spi, scale);
+
+       /*
+            *  Set the drawing scale based on the scale.  This factor is applied to
+            *  all points drawn in the bitmap for graphical objects.  It is scaled
+            *  down from micas to 508 dpi so that the bitmaps aren't of unwieldy
+            *  size, but still retain enough information to look decent on a good
+            *  device.  508/2540 == 0.2
+            */
+       drawscale = scale * .2;
+       if (dbg) printf("setScale(%d) sets drawscale to %e\n", spi, drawscale);
+}
+
+pushCurrentEnv()       /* begin a new block */
+{
+       statep->ssize = size;
+       statep->sfont = font;
+       statep->shorig = hor_orig;
+       statep->svorig = ver_orig;
+       statep->shpos = hor_pos;
+       statep->svpos = ver_pos;
+       hor_orig = hor_pos;
+       ver_orig = ver_pos;
+       hor_pos = ver_pos = 0;
+       if (statep++ >= state + MAXSTATE)
+       {
+               reportError(QUIT, "{ nested too deep");
+       }
+       hor_pos = ver_pos = 0;
+}
+
+popSavedEnv()  /* pop to previous state */
+{
+       if (--statep < state)
+       {
+               reportError(QUIT, "extra }");
+       }
+       size = statep->ssize;
+       font = statep->sfont;
+       hor_pos = statep->shpos;
+       ver_pos = statep->svpos;
+       hor_orig = statep->shorig;
+       ver_orig = statep->svorig;
+}
+
+newpage(n)             /* new page */
+int n;
+{
+       int i;
+       char buff[15];
+
+       /* print any pending bitmap */
+
+       /* terminate previous page if outputting */
+       if (outputflag)
+       {
+               print_bitmap();
+               AppendOp(OP_endBody);
+       }
+       else flush_bitmap();
+
+       /* reset vertical positions */
+       ver_pos = old_ver = 0;
+
+       /* check new page number against those found in the nPageRanges */
+       if (nPageRanges == 0)
+       {
+               /* no -o specified -- do all pages */
+               outputflag = 1;
+       }
+       else
+       {
+               /* see if new page has been selected for output */
+               outputflag = 0;
+               for (i = 0; i < nPageRanges; i++)
+               {
+                       if ((n >= pagerange[i][0]) && (n <= pagerange[i][1]))
+                       {
+                               outputflag = 1;
+                               break;
+                       }
+               }
+       }
+
+       /* start new page */
+       if (outputflag)
+       {
+               AppendOp(OP_beginBody);
+               (void) sprintf(buff, "Page %d", n);
+               AppendComment(buff);
+               Fget(F_transform);
+               AppendOp(OP_concatt);
+               AppendInteger(2L);
+               AppendInteger((long) I_strokeEnd);
+               AppendOp(OP_iset);
+       }
+
+       /* font/size no longer valid -- force a new assignment */
+       oldftsz = -1;
+}
+
+newLine()              /* new line (no vertical motion implied) */
+{
+       if (dbg == 3)
+               putchar('\n');
+       flushbuff();
+       endcorrect();
+       hor_pos = 0;
+       virgin_line = 1;
+}
+
+internalSize(number)           /* convert integer to internal size number */
+int number;
+{
+       int index;
+
+       if (number >= pointsizeTab[device.num_sizes - 1])
+       {
+               /* larger than largest -- use largest */
+               return(device.num_sizes-1);
+       }
+       else if (number <= pointsizeTab[0])
+       {
+               /* smaller than smallest -- use smallest */
+               return(0);
+       }
+
+       /* else find the size in pointsizeTab and return index */
+       for (index = 0; number > pointsizeTab[index]; index++);
+       return(index);
+}
+
+
+
+
+
+/* handle device stop command */
+resetDevice()          
+{
+       int amt;
+       static int is_reset = 0;
+       char bigbuff[1024];
+
+       if (is_reset) return; /* ignore multiple resets */
+
+       print_bitmap();
+
+       /* this is the absolute last thing that we do */
+       /* wrap up the preamble and the body */
+       ip_select(outputfile);
+       AppendOp(OP_endBody);
+       ip_select(pagebodyfile);                
+       AppendOp(OP_endBody);
+       AppendOp(OP_endBlock);
+       ip_close();                     /* close the body */
+
+       /*
+            *  Reopen the body and copy it onto the end of the real file (which is
+            *  where we have been building the preamble).  We don't need to ip_flush
+            *  the preamble since that is done everytime we ip_select the body.
+            *  Conveniently enough, "tempfilename" still holds the name of the body
+            *  temporary.
+            */
+       pagebodyfile = open(tempfilename, O_RDONLY,0);
+       while ((amt = read(pagebodyfile, bigbuff, sizeof(bigbuff))) != 0)
+       {
+               (void) write(outputfile, bigbuff, amt);
+       }
+
+       /* close and unlink the body temporary file */
+       (void) close(pagebodyfile);
+       (void) unlink(tempfilename);
+
+       /* send the file off to the printer */
+       tempfilename[strlen(tempfilename) - 1] = '\0';
+       if (outputfile != 1)
+       {
+               IPprint(tempfilename);
+       }
+
+       /* we are now reset */
+       is_reset = 1;
+}
+
+outputString(character)                /* print a "funny" character */
+char *character;
+{
+       int i;
+
+       if (!outputflag)
+               return;
+       if (dbg > 2) printf("\\(%s", character);
+       if (dbg > 3) putchar(' ');
+       for (i = 0; i < device.spec_char_num; i++)
+               if (strcmp(&specCharStrTab[specCharTab[i]], character) == 0)
+                       break;
+       if (i < device.spec_char_num) {
+               /*      printf(" i = %d so i+128 = %d\n", i, i+128);    */
+               outputChar((unsigned int) i + 128);
+       }
+       else {
+               if (dbg > 3)
+                       printf("-- character not found");
+       }
+
+       if (dbg > 2)
+               putchar('\n');
+}
+
+outputChar(character)          /* put a character */
+unsigned int character;
+{
+       unsigned char *widp;    /* pointer to appropriate width table */
+       register char *codep;   /* pointer to appropriate table of codes */
+       register int i, old_font, fnt_index;
+       int j, value;
+
+       if (!outputflag)
+               return;
+
+       if (character <= 32)
+       {
+               if (dbg) printf("non-existent character 0%o\n", character);
+               charw = charWidthTab[font][0] * pointsizeTab[size-1] / device.width_units;
+               return;
+       }
+       character -= 32;
+
+       old_font= font;
+       i = fontIndexTab[font][character] & 255;
+       if (i != 0)                             /* it's on this font */
+       {
+               codep = charCodeTab[font];
+               widp = charWidthTab[font];
+       }
+       else if (specFontPos > 0)                       /* on special (we hope) */
+       {
+               /* assertion:  i == 0 */
+               fnt_index= specFontPos;
+               for (j=0; j <= device.num_fonts; j++)
+               {
+                       struct font_entry *fb;
+
+                       fnt_index= (fnt_index+1) % (device.num_fonts+1);
+
+                       if ((fb = fontPtr[fnt_index]) != NULL)
+                       {
+                               if (fb->special_flag && (i = fontIndexTab[fnt_index][character] & 255) != 0)
+                               {
+                                       codep = charCodeTab[fnt_index];
+                                       widp = charWidthTab[fnt_index];
+                                       setFont(fnt_index);
+                                       break;
+                               }
+                       }
+               }
+               /* assertion:  if j > device.num_fonts then i == 0 and character was not found */
+       }
+
+       value= codep[i] & 255;
+
+       if (i == 0 || value == 0)
+       {
+               if (dbg) printf("character not found 0%o\n", character+32);
+               return;
+       }
+
+       /* remember this character's width */
+       /* This MUST be done before calling showchar */
+       charw = (widp[i] * pointsizeTab[size-1] + device.width_units/2) / device.width_units;
+       if (dbg == 3)
+       {
+               if (isprint(character+32))
+                       putchar(character+32);
+       }
+       if (dbg > 3)
+       {
+               if (isprint(character+32))
+                       printf("character %c %d\n", character+32, value);
+               else
+                       printf("character %03o %d\n", character+32, value);
+       }
+
+       if (value == 0377)
+       {
+               /* special escape to an extended code */
+               value = getexcode(i);
+       }
+
+       if (dbg < 6)
+               showchar(value);
+
+       if (font != old_font)
+       {
+               setFont(old_font);
+       }
+}
+
+
+/*
+ * set point size to n
+ */
+setPointSize(n)
+
+int n;                 /* internal value:  index into pointsizeTab */
+
+{
+       size = n;
+       ftsz = ((long)font << 16) | ((long)size);
+}
+
+
+/*
+ * set the current font to number
+ */
+setFont(n)
+
+int n;                 /* internal index */
+
+{
+       font = n;
+       ftsz = ((long)font << 16) | ((long)size);
+}
+
+
+/*
+ *     reportError     an error reporting hack that uses dummy parameters 
+ *                     as place holders for arguments that may or may not 
+ *                     exist, fprintf will sort out how many should be there
+ */
+/*VARARGS 2*/
+reportError(f, s, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) 
+char *s, *arg1, *arg2, *arg3, *arg4, *arg5, *arg6, *arg7, *arg8;
+{
+       fprintf(stderr, "dipress: ");
+       fprintf(stderr, s, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
+       fprintf(stderr, "\nerror encountered near line %d\n", linenumber);
+       if (f == QUIT) goodbye();
+}
+
+
+
+
+/*
+ *  Graphics drawing primitives.  These use the vector drawing capabilities of
+ *  interpress to draw straight lines.  All other primitive objects (circle,
+ *  ellipse, etc.) are built in a bitmap and printed with a pixel vector.
+ */
+
+drawline(dh, dv)
+int dh,dv;
+{
+
+       if(!outputflag) return;
+       AppendInteger((long) curr_strokewidth);
+       AppendInteger((long) I_strokeWidth);
+       AppendOp(OP_iset);
+       Moveto(xloc(hor_pos), yloc(ver_pos));
+       hor_pos += dh;
+       ver_pos += dv;
+       Lineto(xloc(hor_pos), yloc(ver_pos));
+       AppendOp(OP_maskstroke);
+}
+
+/* routines used by interpress dependent routines */
+
+char showbuff[Showbuff_size + 1];
+char *showp = showbuff;
+int  showcnt = 0;
+
+showchar(ch)           /* buffer "ch" for use in a "show" command */
+int ch;
+{
+       char *framep;
+       register int hdiff, vdiff;
+
+       /* set correct position */
+       vdiff = ver_pos - old_ver;
+       hdiff = hor_pos - old_hor;
+       if (dbg > 4)
+       {
+               printf("old_hor %d, hor_pos %d, hdiff %d;  old_ver %d, ver_pos %d, vdiff %d %s\n",
+               old_hor, hor_pos, hdiff, old_ver, ver_pos, vdiff,
+               virgin_line ? "(virgin)" : "");
+       }
+
+       /* NOTE:  this expression depends on boolean true being 1! */
+       /* See K&R, Appendix A, section 7.7, page 190 */
+       switch (((vdiff != 0) << 1) | (hdiff != 0))
+       {
+       case 0:         /* no change */
+               break;
+       default:
+               flushbuff();
+               Setxy(xloc(hor_pos), yloc(ver_pos));
+               break;
+       }
+
+       /*
+            *  Update old_hor and old_ver.  Account for character width in old_hor but not in
+            *  hor_pos.  If the next hInc call is for the width of the character, the
+            *  next time showchar gets called, old_hor will equal hor_pos.
+            */
+       old_ver = ver_pos;
+       old_hor = hor_pos + charw;
+
+       /* line is no longer virgin */
+       virgin_line = 0;
+
+       /* font and point still the same? */
+       if (ftsz != oldftsz)
+       {
+               flushbuff();
+               if ((framep = currfonts[font]->frames) == NULL)
+               {
+                       /* previously unused -- give it a frame table */
+                       framep = currfonts[font]->frames = malloc((unsigned)(device.num_sizes * sizeof(char)));
+                       bzero(framep, device.num_sizes * sizeof(char));
+               }
+
+               if (framep[size] == 0)
+               {
+                       /* make a new font */
+                       ip_select(outputfile);
+                       SetupFont(currfonts[font]->uname,
+                       floor(pointsizeTab[size-1] * 35.28 + .5),
+                       frameindex);
+                       ip_select(pagebodyfile);
+                       framep[size] = frameindex++;
+               }
+
+               /* switch to new font/size combo */
+               Setfont(framep[size]);
+               oldftsz = ftsz;
+       }
+
+       /* adjust for character codes > 0377 */
+       if (ch > 0377)
+       {
+               if (dbg > 4)
+               {
+                       printf("processing large code: 0%o (%d)\n", ch, ch);
+               }
+
+               if (showcnt + 5 > Showbuff_size)
+               {
+                       flushbuff();
+               }
+               *showp++ = '\377';
+               *showp++ = (ch & 0177400) >> 8;
+               *showp++ = ch & 255;
+               *showp++ = '\377';
+               *showp++ = '\0';
+               showcnt += 5;
+       }
+       else
+       {
+               *showp++ = ch;
+               if (++showcnt > Showbuff_size)
+               {
+                       flushbuff();
+               }
+       }
+}
+
+/*
+ *  getexcode(findex) - get the extended code for the character "findex"
+ */
+
+getexcode(findex)
+int findex;
+{
+       register int extfd;
+       register int i;
+       register unsigned short *tab;
+       char temp[132];
+
+       if (dbg > 4)
+       {
+               printf("getexcode(%d)\n", findex);
+       }
+
+       if ((tab = currfonts[font]->extab) == NULL)
+       {
+               /* load in the extended code table */
+
+               (void) sprintf(temp, "%s/dev%s/%s.out.ext",
+               fontdirectory, devicename, currfonts[font]->name);
+               if (dbg > 4)
+               {
+                       printf("opening and reading %s\n", temp);
+               }
+               if ((extfd = open(temp, O_RDONLY,0)) == -1)
+               {
+                       reportError(CONTINUE, "can't open %s (%s)", temp, sys_errlist[errno]);
+                       return(0);
+               }
+               currfonts[font]->extab = tab = (unsigned short *)
+                       malloc( (unsigned)(i = (device.spec_char_num + 128-32) * sizeof(short)) );
+               (void) read(extfd, (char *)tab, i); /* should test result! */
+               (void) close(extfd);
+       }
+
+       if (dbg > 4)
+       {
+               printf("getexcode returning %.7o\n", tab[findex]);
+       }
+       return(tab[findex]);
+}
+
+flushbuff()            /* flush and reset "showbuff" */
+{
+       if (showcnt == 0)
+               return;
+
+       if (!in_correct)
+       {
+               startcorrect();
+       }
+
+       /* we must do the append_Sequence explicitly, */
+       /* because showbuff might have nulls in it.   */
+       append_Sequence(sequenceString, showcnt, (unsigned char *)showbuff);
+       AppendOp(OP_show);
+       showp = showbuff;
+       showcnt = 0;
+}
+
+int hstart;
+
+startcorrect()
+{
+#ifdef CORRECT_BLOCKS
+       AppendOp(OP_correct);
+       AppendOp(OP_beginBody);
+#endif
+       in_correct = 1;
+       hstart = hor_pos;
+}
+
+endcorrect()
+{
+       /* append a Setcorrectmeasure operation */
+       /* "hor_pos" or "old_hor"???  Make it "old_hor" for now */
+#ifdef CORRECT_BLOCKS
+       Setcorrectmeasure(xloc(old_hor), 0.0);
+       AppendOp(OP_endBody);
+#endif
+       in_correct = 0;
+}
+
+/*
+ *  IPprint(filename) - send the file "filename" to the interpress printer.
+ *                      This routine is *very* dependent on local
+ *                      environments.
+ */
+
+IPprint(filename)
+char *filename;
+{
+       if (dbg)
+       {
+               printf("interpress file saved in %s.\n", filename);
+               return;
+       }
+
+       if (vfork() == 0)
+       {
+               /* is child */
+               execl("/usr/local/bin/qip", "qip", "-nc", "-nk", filename, 0);
+               exit(1);
+       }
+}
+
+/* bitmap graphics object sizing functions */
+
+g_sizearc(x1, y1, xc, yc, x2, y2)
+int x1, y1, xc, yc, x2, y2;
+{
+       int minx;
+       int miny;
+       int maxx;
+       int maxy;
+       int quad1;
+       int quad2;
+       int radius;
+       int axc;
+       int ayc;
+       int i;
+
+       /* the center and the second point are offsets from the first */
+       /* calculate actual center and radius */
+       axc = x1 + xc;
+       ayc = y1 + yc;
+       radius = (int)(hypot((double)xc, (double)yc) + .5);
+       if (dbg > 1)
+       {
+               printf("g_sizearc(%d, %d, %d, %d, %d, %d): radius is %d\n",
+               x1, y1, xc, yc, x2, y2, radius);
+       }
+
+       /* preset the minmal and maximal points -- this is our first guess */
+       if ((minx = x1 + xc + x2) > x1)
+       {
+               maxx = minx;
+               minx = x1;
+       }
+       else
+       {
+               maxx = x1;
+       }
+       if ((miny = y1 + yc + y2) > y1)
+       {
+               maxy = miny;
+               miny = y1;
+       }
+       else
+       {
+               maxy = y1;
+       }
+
+       /* calculate the offset from the center to the first point */
+       x1 = -xc;
+       y1 = -yc;               /* now all three arguments are offsets */
+
+       /* calculate the quadrant of each endpoint */
+       quad1 = quadrant(x1, y1);
+       quad2 = quadrant(x2, y2);
+       if (dbg > 1)
+       {
+               printf("(%d, %d) in quadrant %d ... ", x1, y1, quad1);
+               printf("(%d, %d) in quadrant %d\n", x2, y2, quad2);
+       }
+
+       /* insure that quad1 < quad2 */
+       if (quad2 < quad1)
+       {
+               quad2 += 4;
+       }
+
+       /* compensate for arc at each quadrant boundary */
+       for (i = quad1 + 1; i <= quad2; i++)
+       {
+               switch (i & 3)
+               {
+               case 0:         /* 1st quadrant */
+                       maxx = axc + radius;
+                       break;
+
+               case 1:         /* 2nd quadrant */
+                       miny = ayc - radius;
+                       break;
+
+               case 2:         /* 3rd quadrant */
+                       minx = axc - radius;
+                       break;
+
+               case 3:         /* 4th quadrant */
+                       maxy = ayc + radius;
+                       break;
+               }
+       }
+
+       /* now set the extremes */
+       if (dbg > 1)
+       {
+               printf("extremes are %d, %d, %d, %d\n", minx, miny, maxx, maxy);
+       }
+       gobj_size(minx, miny, maxx, maxy);
+}
+
+quadrant(dx, dy)
+int dx,dy;
+{
+       register int yplus;
+
+       yplus = dy > 0;
+       if (dx > 0)
+       {
+               return(yplus ? 3 : 0);
+       }
+       else
+       {
+               return(yplus ? 2 : 1);
+       }
+}
+
+
+g_sizeWigglyLine(str)
+char *str;
+{
+       int minx;
+       int miny;
+       int maxx;
+       int maxy;
+       int currx;
+       int curry;
+       int incx;
+       int incy;
+
+       currx = minx = maxx = hor_pos;
+       curry = miny = maxy = ver_pos;
+
+       while(white(*str)) str++; /* trim leading white space */
+
+       while (*str)
+       {
+
+               (void) readNumber(&str,&incx);
+               (void) readNumber(&str,&incy);
+               currx += incx;
+               curry += incy;
+               if (currx > maxx)
+                       maxx = currx;
+               else if (currx < minx)
+                       minx = currx;
+               if (curry > maxy)
+                       maxy = curry;
+               else if (curry < miny)
+                       miny = curry;
+       }
+       gobj_size(minx, miny, maxx, maxy);
+}
+
+
+/*
+ * Request the insertion of an Interpress master
+ */
+
+doSequenceInsertIP(fileName)
+char *fileName; {
+       AppendOp(OP_dosavesimplebody);
+       AppendOp(OP_beginBody);
+       /* set the IP position at the current troff position */
+       Setxy(xloc(hor_pos), yloc(ver_pos));
+
+       /* undo the Troff scaling */
+       AppendRational(spotsPerInch*10000L, 254L);
+       AppendOp(OP_scale);
+       AppendOp(OP_concatt);
+       AppendOp(OP_trans);
+
+       AppendInsertFile(fileName);
+       AppendOp(OP_endBody);
+}
+
+
+#define SAME   0
+
+/*
+ * define frame variables for the RES image
+ */
+#define IMAGE_EDIT     47L
+#define IMAGE_COLOR_OP 46L
+#define IMAGE_COLOR    45L
+#define IMAGE_MASK     44L
+#define IMAGE_Y                43L
+#define IMAGE_X                42L
+#define IMAGE_SCALE    41L
+
+/*
+ * Request the insertion of an RES file
+ */
+
+doSequenceInsertRES(anchor, resolutionString, fileName) 
+char *anchor,
+     *resolutionString,
+     *fileName; {
+       int resolution;
+
+       resolution = atoi(resolutionString);
+
+       AppendOp(OP_dosavesimplebody);
+       AppendOp(OP_beginBody);
+       /* set the IP position at the current troff position */
+       Setxy(xloc(hor_pos), yloc(ver_pos));
+
+       AppendInsertFile(fileName);
+
+       /* pop and store */
+       AppendOp(OP_pop);               /* for now, don't check the signature */
+       AppendInteger(IMAGE_EDIT);
+       AppendOp(OP_fset);
+       AppendInteger(IMAGE_COLOR_OP);
+       AppendOp(OP_fset);
+       AppendInteger(IMAGE_COLOR);
+       AppendOp(OP_fset);
+       AppendOp(OP_pop);                       /* discard mask image */
+       AppendInteger(IMAGE_Y);
+       AppendOp(OP_fset);
+       AppendInteger(IMAGE_X);
+       AppendOp(OP_fset);
+       AppendInteger(IMAGE_SCALE);
+       AppendOp(OP_fset);
+
+       /* undo the Troff scaling */
+       AppendRational(spotsPerInch*10000L, 254L);
+       AppendOp(OP_scale);
+
+       /* set the resolution */
+       if( resolution != 0 ) {
+               /* display the RES file at the specified resolution */
+               AppendRational(254L, resolution*10000L);
+               AppendOp(OP_scale); }
+       else 
+               /* get the default scale from the RES file */
+               /* can the device do a "get" operator? */
+               if( IPDeviceType == Xerox8044_Services8  ||
+                   IPDeviceType == Xerox8044_Services9  ||
+                   IPDeviceType == Xerox8044_Services10 )
+                       reportError(CONTINUE, "requested device can't read resolution from an RES file");
+               else {
+                       /* Yes!  Use the imageScale suggested by the image */
+                       Fget(IMAGE_SCALE);
+                       Get(1L);
+                       Fget(IMAGE_SCALE);
+                       Get(2L);
+                       AppendOp(OP_scale2); }
+
+       AppendOp(OP_concat);            /* concat undo-scale with image scale */
+
+       if( strcmp(anchor, "bl") == SAME )              /* bottom left */
+               ;
+       else if( strcmp(anchor, "tl") == SAME ) {       /* top left */
+               AppendInteger(-1L);             /* invert scale */
+               AppendOp(OP_scale);
+               AppendOp(OP_concat);
+               AppendOp(OP_concatt);
+
+               FGet(IMAGE_Y);
+               AppendOp(OP_setyrel);
+
+               AppendInteger(-1L);
+               AppendOp(OP_scale);
+       }
+       else if( strcmp(anchor, "c") == SAME ) {        /* center */
+               AppendRational(-1L, 2L);
+               AppendOp(OP_scale);
+               AppendOp(OP_concat);
+               AppendOp(OP_concatt);   /* half normal scale for centering */
+
+               FGet(IMAGE_X);
+               FGet(IMAGE_Y);
+               AppendOp(OP_setxyrel);
+
+               AppendRational(-2L, 1L);
+               AppendOp(OP_scale);
+       }
+       else if( strcmp(anchor, "br") == SAME ) {       /* bottom right */
+               AppendInteger(-1L);             /* invert scale */
+               AppendOp(OP_scale);
+               AppendOp(OP_concat);
+               AppendOp(OP_concatt);
+
+               FGet(IMAGE_X);
+               AppendOp(OP_setxrel);
+
+               AppendInteger(-1L);             /* invert scale */
+               AppendOp(OP_scale);
+       }
+       else if( strcmp(anchor, "tr") == SAME ) {       /* top right */
+               AppendInteger(-1L);             /* invert scale */
+               AppendOp(OP_scale);
+               AppendOp(OP_concat);
+               AppendOp(OP_concatt);
+
+               FGet(IMAGE_X);
+               FGet(IMAGE_Y);
+               AppendOp(OP_setxyrel);
+
+               AppendInteger(-1L);             /* invert scale */
+               AppendOp(OP_scale);
+       }
+       else
+               reportError(CONTINUE, "unknown position in RES command: %s", anchor );
+
+       AppendOp(OP_concatt);
+
+       AppendOp(OP_trans);
+
+       FGet(IMAGE_COLOR);
+       AppendOp(OP_maskpixel);
+       AppendOp(OP_endBody);
+}