home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_200 / 286_02 / mprint.c < prev    next >
Text File  |  1989-05-25  |  20KB  |  715 lines

  1. #include <stdio.h>
  2. #include <ctype.h>
  3. #include <setjmp.h>
  4. #include <stdarg.h>
  5. #include <fcntl.h>
  6. #include <sys\types.h>
  7. #include <io.h>
  8. #include <sys\stat.h>
  9.  
  10. #define unreadc(ch) ungetc(ch,infile)
  11.  
  12. #define MAXPARM 9       /* max. number of parameters per function */
  13. #define MAXLPP 88       /* max. number of line per page */
  14. #define TBUFSIZ 16384   /* Text buffer size */
  15.  
  16. #define Boolean int
  17. #define TRUE 1
  18. #define FALSE 0
  19. #define ERROR (-1)
  20.  
  21. enum Ptype {            /* Parameter Type */
  22.     UNDEFINED, INTG, STRG
  23. };
  24.  
  25. struct funcdesc {       /* Function description entry */
  26.     char *name;         /* name in ASCII */
  27.     enum Ptype rettype; /* no return value or expected return type */
  28.     int nuparm;         /* number of paramters for the functions */
  29.     enum Ptype parmstype[MAXPARM];      /* definition parameter type */
  30. };
  31.  
  32. /* The function names must arrange in ascending order */
  33. /* and same as the order in EXECFUNC.ASM              */
  34. struct funcdesc FUNCTIONS[] =
  35.     { { "Arc1",     UNDEFINED, 4, { INTG, INTG, INTG, INTG } } ,
  36.       { "Arc2",     UNDEFINED, 5, { INTG, INTG, INTG, INTG, INTG } },
  37.       { "ArcPoint", UNDEFINED, 4, { INTG, INTG, INTG, INTG } },
  38.       { "BlockCopy",  INTG, 8,
  39.                     { INTG, INTG, INTG, INTG, INTG, INTG, INTG, INTG } },
  40.       { "BlockLoad",  INTG, 3, { INTG, INTG, STRG } },
  41.       { "BlockSave",  UNDEFINED, 5, { INTG, INTG, STRG, INTG, INTG } },
  42.       { "Box",      UNDEFINED, 6, { INTG, INTG, INTG, INTG, INTG, INTG } } ,
  43.       { "Circle",   UNDEFINED, 3, { INTG, INTG, INTG } } ,
  44.       { "CreateFrame", INTG, 2, { INTG, INTG } } ,
  45.       { "Dot",      UNDEFINED, 2, { INTG, INTG } } ,
  46.       { "Draw",     UNDEFINED, 3, { STRG, INTG, INTG } },
  47.       { "Earc1",    UNDEFINED, 5, { INTG, INTG, INTG, INTG, INTG } } ,
  48.       { "Earc2",    UNDEFINED, 6, { INTG, INTG, INTG, INTG, INTG, INTG } },
  49.       { "Ellipse",  UNDEFINED, 4, { INTG, INTG, INTG, INTG } } ,
  50.       { "EnvRsto",  UNDEFINED, 2, { INTG, INTG } },
  51.       { "EnvSave",  INTG, 1, { INTG } },
  52.       { "FillCircle", UNDEFINED, 3, { INTG, INTG, INTG } },
  53.       { "FillEllipse",UNDEFINED, 4, { INTG, INTG, INTG, INTG } },
  54.       { "HorzLine", UNDEFINED, 4, { INTG, INTG, INTG, INTG } } ,
  55.       { "Line",     UNDEFINED, 4, { INTG, INTG, INTG, INTG } } ,
  56.       { "LoadFont", INTG, 1, { STRG } } ,
  57.       { "NextXY",   UNDEFINED, 2, { INTG, INTG } },
  58.       { "PatternFill", UNDEFINED, 4, { INTG, INTG, STRG, INTG } },
  59.       { "PlotType", INTG, 1, { INTG } } ,
  60.       { "PrintFrame", UNDEFINED, 5, { INTG, STRG, INTG, INTG, INTG } } ,
  61.       { "PrintPage",  UNDEFINED, 0 },
  62.       { "ReadStr",    UNDEFINED, 7,
  63.                           { STRG, INTG, INTG, INTG, INTG, INTG, INTG } },
  64.       { "Rectangle",  UNDEFINED, 4, { INTG, INTG, INTG, INTG } } ,
  65.       { "RelOrg",   UNDEFINED, 2, { INTG, INTG } } ,
  66.       { "RemvFont", INTG, 1, { INTG } } ,
  67.       { "RemvFrame", INTG, 1, { INTG } } ,
  68.       { "ResetWin", UNDEFINED, 0 } ,
  69.       { "SelectFont",  INTG, 1, { INTG } },
  70.       { "SelectFrame", INTG, 1, { INTG } } ,
  71.       { "SetOrg",   UNDEFINED, 2, { INTG, INTG } } ,
  72.       { "SetStyle", UNDEFINED, 1, { INTG } } ,
  73.       { "SetWin",   UNDEFINED, 4, { INTG, INTG, INTG, INTG } } ,
  74.       { "SolidFill",   UNDEFINED, 2, { INTG, INTG } },
  75.       { "VertLine", UNDEFINED, 4, { INTG, INTG, INTG, INTG } },
  76.       { "WriteStr", UNDEFINED, 7, { INTG, INTG, INTG, INTG, STRG, INTG, INTG }},
  77.       { "XHLine",   INTG, 5, { INTG, INTG, INTG, INTG, INTG } }
  78.  };
  79.  
  80. /* total number of functions */
  81. #define NFUNC (sizeof(FUNCTIONS) / sizeof(struct funcdesc))
  82.  
  83.  
  84. /* Error message in C format string */
  85. char *ERRMSG[]= {
  86.     "Undefined Error Number\n",
  87.     "Variable/Function name expected\n",
  88.     "Variable name %s not found\n",
  89.     "Function name or expression expected\n",
  90.     "Function name %s not found\n",
  91.     "'(' expected after function name\n",
  92.     "Type if parameter %d is different from definition\n",
  93.     "')' expected after the parameters of a function\n",
  94.     "Less parameter than expected\n",
  95.     "End of string not detected before end of line\n",
  96.     "',' expected after a parameter\n",
  97.     "'C' or 'L' expected after '['\n",
  98.     "']' expected after a line or column specification\n",
  99.     "Idendifier Expected\n"
  100. };
  101.  
  102. /* total number of error messges */
  103. #define NUOFERROR (sizeof(ERRMSG) / sizeof(char *))
  104.  
  105. int PATTERN[]={
  106.     0x5555, 0xaaaa, 0x5555, 0xaaaa,
  107.     0x5555, 0xaaaa, 0x5555, 0xaaaa,
  108.     0x5555, 0xaaaa, 0x5555, 0xaaaa,
  109.     0x5555, 0xaaaa, 0x5555, 0xaaaa,
  110.     0x8888, 0x4444, 0x2222, 0x1111,
  111.     0x8888, 0x4444, 0x2222, 0x1111,
  112.     0x8888, 0x4444, 0x2222, 0x1111,
  113.     0x8888, 0x4444, 0x2222, 0x1111,
  114.     0x1111, 0x2222, 0x4444, 0x8888,
  115.     0x1111, 0x2222, 0x4444, 0x8888,
  116.     0x1111, 0x2222, 0x4444, 0x8888,
  117.     0x1111, 0x2222, 0x4444, 0x8888
  118. };
  119.  
  120. char LINE[160]; /* for variable line */
  121.  
  122. struct pval {   /* parameter record */
  123.     enum Ptype parmtype;
  124.     union {
  125.         int u_int;
  126.         char *u_strg;
  127.     } v;
  128. };
  129.  
  130. struct pval RETVAL, *expr();
  131.  
  132. /* Only first 12 characters of identifier is significant */
  133. /* Maximum number of characters in string(s) per function is 512 */
  134. char IDNAME[12], CHARS[512], *PSPTR;
  135.  
  136. #define NUOFVAR 21
  137.  
  138. int nuofvar=NUOFVAR;
  139. char VARNAME[NUOFVAR][12]={
  140.     "pattern1", "pattern2", "pattern3",
  141.     "line",
  142.     "font1", "font2", "font3", "font4",
  143.     "frame1", "frame2", "frame3",
  144.     "temp1", "temp2", "temp3",
  145.     "x1", "x2", "y1", "y2",
  146.     "env1", "env2", "env3"
  147. };
  148.  
  149. struct pval VARTABLE[NUOFVAR];
  150.  
  151. /* configurable parameters */
  152. int COL_OFFSET=0, ROW_OFFSET=0, LINE_HEIGHT=12, CHAR_WIDTH=12, LINEPERPAGE=66;
  153. int FRAME_WIDTH=960, FRAME_HEIGHT=792, VERT_DEN=0, HORZ_DEN=4; 
  154.  
  155. jmp_buf EOF_JMP, SYNERR_JMP;
  156.  
  157. int EOF_FLAG=0, TEXT_EOF=0, REMAIN=0;
  158. char TBUF[TBUFSIZ+1], *PAGE[MAXLPP], *PAGEPTR;
  159.  
  160. FILE *infile;   /* GRAD command file */
  161. int textfile;   /* text file */
  162.  
  163. main(argc,argv)
  164. int argc;
  165. char *argv[];
  166. {
  167.     char ch;
  168.     int ret, frame1;
  169.     FILE *fopen();
  170.  
  171.     /* Interpret the options if any */
  172.  
  173.     argv++;
  174.     while (argc-- > 1 && *(*argv)++=='-') {
  175.         if (**argv) {
  176.             ch= *(*argv)++;
  177.             ret=atoi(*argv);
  178.         } else {
  179.             ch=0;
  180.         }
  181.         switch(ch) {
  182.         case 'H':
  183.             FRAME_HEIGHT=ret;
  184.             break;
  185.         case 'W':
  186.             FRAME_WIDTH=ret;
  187.             break;
  188.         case 'c':
  189.             COL_OFFSET=ret;
  190.             break;
  191.         case 'd':
  192.             HORZ_DEN=ret & 0x0f; 
  193.             break;
  194.         case 'h':
  195.             LINE_HEIGHT=ret;
  196.             break;
  197.         case 'p':
  198.             if (ret > MAXLPP) {
  199.                 fprintf(stderr,"Max number of line per page is %d\n",MAXLPP);
  200.                 exit(1);
  201.             }
  202.             LINEPERPAGE=ret;
  203.             break;
  204.         case 'r':
  205.             ROW_OFFSET=ret;
  206.             break;
  207.         case 'v':
  208.             VERT_DEN=ret ? 0x10 : 0;
  209.             break;
  210.         case 'w':
  211.             CHAR_WIDTH=ret;
  212.             break;
  213.         default:
  214.             fprintf(stderr,"Unknow option -%c ** IGNORED **\n",ch);
  215.             break;
  216.         }
  217.         argv++;
  218.     }
  219.  
  220.     /* Any command line argument remain ? */
  221.     if ((argc < 1) || (argc > 2)) {
  222.         /* no more or too much */
  223.         fprintf(stderr,"Usage: mprint [options] commandfile [textfile]\n");
  224.         exit(1);
  225.     }
  226.     (*argv)--;
  227.  
  228.     /* open GRAD command file */
  229.     if ((infile=fopen(argv[0], "r")) == (FILE *) NULL) {
  230.         fprintf(stderr,"mprint: Command file not found\n");
  231.         exit(1);
  232.     }
  233.     if (argc==2) {
  234.         /* Open text file */
  235.         if ((textfile=open(argv[1],O_RDONLY | O_BINARY)) == ERROR) {
  236.             fprintf(stderr,"mprint: text file not found\n");
  237.             exit(1);
  238.         }
  239.     } else {
  240.         TEXT_EOF=TRUE;
  241.     }
  242.     GRADinit();         /* Initialize GRAD environemnt */
  243.     initvars();         /* Initialize my varaibles */
  244.     frame1=CreateFrame(FRAME_WIDTH,FRAME_HEIGHT);       /* Create Frame */
  245.     SelectFrame(frame1);        /* use it as default output */
  246.  
  247.     if (setjmp(EOF_JMP) != 0) {
  248.         /* End Of File is reached */
  249.         fclose(infile);
  250.         if (EOF_FLAG) { 
  251.             printf("mprint: Unexpected End Of File !\n");
  252.         } else {
  253.             PrintAll();
  254.         }
  255.         close(textfile);
  256.         cleanup(EOF_FLAG);
  257.         exit(0);
  258.     }
  259.     setjmp(SYNERR_JMP);
  260.     /* Back to here if any syntax error is found */
  261.     for (;;) {
  262.         EOF_FLAG=0;
  263.         stmt();
  264.     }
  265. }
  266.  
  267. readc0()        /* return next character but skip over comments */
  268. {               /* comment is treated as a space.               */
  269.     int ch;     /* comments can be nested                       */
  270.  
  271.     if ((ch=getc(infile)) == EOF) {
  272.         longjmp(EOF_JMP,1);     /* EOF found */
  273.     }
  274.     if (ch != '/') return(ch);
  275.     if ((ch=getc(infile)) == EOF) {
  276.         longjmp(EOF_JMP,1);     /* EOF found */
  277.     }
  278.     if (ch != '*') {
  279.         ungetc(ch,infile);
  280.         return('/');            /* not a comment */
  281.     }
  282.     for (;;) {
  283.         if ((ch=readc0()) == '*') {
  284.             while((ch=readc0()) == '*') ;
  285.             if (ch=='/') return(' ');   /* end of comment, return a space */
  286.         }
  287.     }
  288. }
  289.  
  290. readc1()        /* return a single charater but skip over control characters */
  291. {
  292.     int ch;
  293.  
  294.     do {
  295.         ch=readc0();
  296.         if (isspace(ch)) return(' ');
  297.     } while (ch < 0x20);
  298.     return(ch);
  299. }
  300.  
  301. readc2()        /* return a single character but skip over spaces */
  302. {
  303.     int ch;
  304.  
  305.     do {
  306.         ch=readc1();
  307.     } while (ch==' ');
  308.     EOF_FLAG=1;
  309.     return(ch);
  310. }
  311.  
  312. /* processing of  statement, see also stmt() in interp.c */
  313. stmt()
  314. {
  315.     int ch, varidx,funcidx, nuparmoffunc, nparm;
  316.     struct pval *valptr, parmlist[MAXPARM];
  317.  
  318.     PSPTR=CHARS;
  319.     varidx=-1;
  320.     if (!identifier()) {
  321.         synerr(1);
  322.     }
  323.     ch=readc2();
  324.     if (ch=='=') {
  325.         if ((varidx=findvar(IDNAME))==ERROR) {
  326.             synerr(2,IDNAME);
  327.         }
  328.         if (!identifier()) {
  329.             valptr=expr();
  330.             if (valptr->parmtype == UNDEFINED) {
  331.                 synerr(3);
  332.             } else {
  333.                 VARTABLE[varidx]=*valptr;
  334.                 goto endofstmt;
  335.             }
  336.         }
  337.         ch=readc2();
  338.     }
  339.     if ((funcidx=findfunc(IDNAME))==ERROR) {
  340.         synerr(4,IDNAME);
  341.     }
  342.     if (ch!='(') {
  343.         synerr(5);
  344.     }
  345.     if ((nuparmoffunc=FUNCTIONS[funcidx].nuparm) == 0) {
  346.         ch=readc2();
  347.     } else {
  348.         ch=',';
  349.     }
  350.     for (nparm=0; nparm<nuparmoffunc; nparm++) {
  351.         if (ch != ',') {
  352.             synerr(10);
  353.         }
  354.         valptr=expr();
  355.         if (valptr->parmtype == UNDEFINED) {
  356.             synerr(8);
  357.         }
  358.         if (valptr->parmtype != FUNCTIONS[funcidx].parmstype[nparm]) {
  359.             synerr(6,nparm+1);
  360.         }
  361.         parmlist[nparm]=*valptr;
  362.         ch=readc2();
  363.     }
  364.     if (ch != ')') {
  365.         synerr(7);
  366.     }
  367.     execfunc(funcidx, FUNCTIONS[funcidx].nuparm, parmlist,
  368.              FUNCTIONS[funcidx].rettype, &RETVAL);
  369.     if (varidx>=0) {
  370.         VARTABLE[varidx]=RETVAL;
  371.     }
  372. endofstmt:
  373.     ch=readc2();
  374.     if (ch!=';') {
  375.         printf("Warning: Semicolon ';' expected. Assuming present\n");
  376.         unreadc(ch);
  377.     }
  378. }
  379.  
  380. /* read the identifier on input if any */
  381. Boolean identifier()
  382. {
  383.     int ch, count;
  384.  
  385.     if (!isalpha(ch=readc2())) {
  386.         IDNAME[0]='\0';
  387.         unreadc(ch);
  388.         return(FALSE);
  389.     }
  390.     count=0;
  391.     do {
  392.         IDNAME[count++]=ch;
  393.         ch=readc1();
  394.     } while (isalnum(ch));
  395.     unreadc(ch);
  396.     IDNAME[count]='\0';
  397.     return(TRUE);
  398. }
  399.  
  400. /* find the variable given in name from the variable table */
  401. findvar(name)
  402. char *name;
  403. {
  404.     int loop;
  405.  
  406.     for (loop=0; loop<nuofvar; loop++) {
  407.         if (strcmp(name,VARNAME[loop])==0) return(loop);
  408.     }
  409.     return(ERROR);
  410. }
  411.  
  412. /* find the function given in name from the function table */
  413. findfunc(name)
  414. char *name;
  415. {
  416.     int start, end, current, ret;
  417.  
  418.     for (start=0, end=NFUNC; start != end ; ) {
  419.         current=(start+end)>>1;
  420.         if ((ret=strcmp(name,FUNCTIONS[current].name)) == 0) {
  421.             return(current);
  422.         } else if (ret > 0) {
  423.             start=current+1;
  424.         } else {
  425.             end=current;
  426.         }
  427.     }
  428.     return(ERROR);
  429. }
  430.  
  431. /* processing of expression, see also expr() in interp.c */
  432. struct pval *expr()
  433. {
  434.     int ch, number, sign, varidx, addrflag;
  435.  
  436.     RETVAL.parmtype=UNDEFINED;
  437.     number=sign=addrflag=0;
  438.     ch=readc2();
  439.     if (isdigit(ch)) {
  440. getnum:
  441.         if (ch=='0') {
  442.             ch=readc1();
  443.             if (toupper(ch)=='X') {
  444.                 ch=readc1();
  445.                 while(isxdigit(ch)) {
  446.                     number=(number<<4) | ((ch-(isalpha(ch) ? 7:0)) & 0x0f);
  447.                     ch=readc1();
  448.                 }
  449.             } else {
  450.                 number=getint(&ch);
  451.             }
  452.         } else {
  453.             number=getint(&ch);
  454.         }
  455.         unreadc(ch);
  456.         RETVAL.parmtype=INTG;
  457.         RETVAL.v.u_int=sign ? -number:number;
  458.     } else if (ch=='+') {
  459.         ch=readc1();
  460.         goto getnum;
  461.     } else if (ch=='-') {
  462.         sign=1;
  463.         ch=readc1();
  464.         goto getnum;
  465.     } else if (ch=='"') {
  466.         RETVAL.parmtype=STRG;
  467.         RETVAL.v.u_strg=PSPTR;
  468.         for (;;) {
  469.         if ((ch=getc(infile)) == EOF) {
  470.             longjmp(EOF_JMP,1);
  471.         }
  472.             if (ch=='\n') {
  473.                 synerr(9);
  474.             }
  475.             if (ch=='"') break;
  476.             *PSPTR++ = ch;
  477.         }
  478.         *PSPTR++ = '\0';
  479.     } else if (ch=='&') {
  480.         addrflag=1;
  481.         goto ident;
  482.     } else if (ch=='[') {
  483.         ch=readc2();
  484.         if (ch=='L' || ch=='l') {
  485.             ch=readc2();
  486.             number=getint(&ch);
  487.             if (number) number--;
  488.             number=number*LINE_HEIGHT+ROW_OFFSET;
  489.         } else if (ch=='C' || ch=='c') {
  490.             ch=readc2();
  491.             number=getint(&ch);
  492.             if (number) number--;
  493.             number=number*CHAR_WIDTH+COL_OFFSET;
  494.         } else {
  495.             synerr(11);
  496.         }
  497.         if (ch==',') {
  498.             ch=readc2();
  499.             number+=getint(&ch);
  500.         }
  501.         if (ch!=']') {
  502.             synerr(12);
  503.         }
  504.         RETVAL.parmtype=INTG;
  505.         RETVAL.v.u_int=number;  
  506.     } else if (isalpha(ch)) {
  507.         unreadc(ch);
  508. ident:
  509.         if (!identifier()) synerr(13);
  510.         if ((varidx=findvar(IDNAME)) == ERROR) {
  511.             synerr(2,IDNAME);
  512.         }
  513.         RETVAL=VARTABLE[varidx];
  514.         if (addrflag) {
  515.             VARTABLE[varidx].parmtype=INTG;
  516.             RETVAL.parmtype=INTG;
  517.             RETVAL.v.u_int=(int) &VARTABLE[varidx].v.u_int;
  518.         }
  519.     } else if ((ch==',') || (ch==')')) {
  520.         unreadc(ch);
  521.         RETVAL.parmtype=INTG;
  522.         RETVAL.v.u_int=0;
  523.     }
  524.     return(&RETVAL);
  525. }
  526.  
  527. /* processing of syntax error */
  528. synerr(errno)
  529. int errno;
  530. {
  531.     va_list arg_ptr;
  532.     int ch;
  533.  
  534.     va_start(arg_ptr, errno);
  535.     if ((errno >= NUOFERROR) || (errno<0)) {
  536.         errno=0;
  537.     }
  538.     vprintf(ERRMSG[errno], arg_ptr);
  539.     va_end(arg_ptr);
  540.     for(;;) {
  541.         ch=readc2();
  542.         if (ch=='"') {
  543.             do {
  544.                if ((ch=getc(infile)) == EOF) {
  545.                        longjmp(EOF_JMP,1);
  546.                    }
  547.             } while (ch!='"');
  548.         }
  549.         if (ch==';') {
  550.             longjmp(SYNERR_JMP,1);
  551.         }
  552.     }
  553. }
  554.  
  555. /*get an integer */
  556. getint(ch)
  557. int *ch;
  558. {
  559.     int number;
  560.  
  561.     number=0;
  562.     while (isdigit(*ch)) {
  563.         number=number*10 + (*ch & 0x0f);
  564.         *ch=readc1();
  565.     }
  566.     return(number);
  567. }
  568.  
  569. /*   *** FOR DEBUGGING ***
  570. execfunc(current, nparm, parmlist, retype, ret)
  571. int current, nparm;
  572. struct pval *parmlist, *ret;
  573. {
  574.     int loop;
  575.  
  576.     printf("%s(",FUNCTIONS[current].name);
  577.     for (loop=0; loop<nparm; loop++) {
  578.         switch (parmlist->parmtype) {
  579.         case INTG:
  580.             printf("%d,",parmlist->v.u_int);
  581.             break;
  582.         case STRG:
  583.             printf("\"%s\",",parmlist->v.u_strg);
  584.             break;
  585.         }
  586.         parmlist++;
  587.     }
  588.     printf(")\n");
  589. }
  590. */
  591.  
  592. /* read next page of text data */
  593. readpage()
  594. {
  595.     int temp1, linenu, temp2, inkline;
  596.  
  597.     inkline=0;
  598.     if (!TEXT_EOF) {
  599.         temp1=TBUFSIZ-REMAIN;
  600.         if ((temp2=read(textfile, &TBUF[REMAIN], temp1)) != temp1) {
  601.             TEXT_EOF=TRUE;
  602.         }
  603.         REMAIN+=temp2;
  604.     }
  605.     linenu=0;
  606.     if (REMAIN != 0) {
  607.         PAGEPTR=TBUF;
  608.         for (; (linenu<LINEPERPAGE) && (REMAIN>0); ) {
  609.             PAGE[linenu]=PAGEPTR;
  610.             linenu++;
  611.             for (; REMAIN>0 ;) {
  612.                 while (REMAIN-- > 0) {
  613.                     if (*PAGEPTR==12) {         /* is it a FORM FEED ? */
  614.                         *PAGEPTR++='\0';        /* yes, end of page */
  615.                         return(linenu);
  616.                     }
  617.                     if (*PAGEPTR==0) {
  618.                         *PAGEPTR++ = 0x80; /* change 0 in text file to 0x80 */
  619.                         continue;
  620.                     }
  621.                     if (*PAGEPTR++ == '\r')     /* is it a carriage return ? */
  622.                         break;                  /* yes, end of search */
  623.                     inkline=linenu;
  624.                 }
  625.                 if ((REMAIN>0) && (*PAGEPTR=='\n')) {   /* new line ? */
  626.                     *(PAGEPTR-1)='\0';  /* end of line */
  627.                     *PAGEPTR++;
  628.                     REMAIN--;
  629.                     break;
  630.                 }
  631.             }
  632.         }
  633.         if (REMAIN<=0) {        /* any data remain in the buffer ?*/
  634.             linenu=inkline;     /* No more! */
  635.             REMAIN=0;
  636.             *PAGEPTR='\0';
  637.         }
  638.     }
  639.     return(linenu);
  640. }
  641.  
  642. /* Print text data with graphics */
  643. PrintPage()
  644. {
  645.     int linenu, loop;
  646.     char *ptr;
  647.     
  648.     linenu=readpage();
  649.     PrintFrame(VERT_DEN+HORZ_DEN,PAGE,linenu,LINE_HEIGHT,0); 
  650.     SetOrg(0,0);
  651.     PlotType(1);
  652.     HorzLine(0,0,960,792);
  653.     PlotType(0);
  654.     ptr=TBUF;
  655.     for (loop=REMAIN; loop>0; loop--) {
  656.         *ptr++ = *PAGEPTR++;    /* copy remaining data to begining of buffer */
  657.     }
  658.     PAGEPTR=TBUF;
  659. }
  660.  
  661. /* print all the remaining text data */
  662. PrintAll()
  663. {
  664.     int linenu, loop;
  665.     char **tpage, *ptr;
  666.  
  667.     while ((linenu=readpage()) > 0) {
  668.         loop=LINEPERPAGE-linenu;
  669.         tpage=PAGE;
  670.         while (linenu--) {
  671.             ptext(*tpage++);
  672.             skiplong(12);
  673.         }
  674.         while (loop-- > 0) {
  675.             skiplong(12);
  676.         }
  677.         ptr=TBUF;
  678.         for (loop=REMAIN; loop>0; loop--) {
  679.             *ptr++ = *PAGEPTR++;
  680.         }
  681.         PAGEPTR=TBUF;
  682.     }
  683. }
  684.  
  685. /* Initialize one variable */
  686. int initvar(name,type)
  687. char *name;
  688. enum Ptype type;
  689. {
  690.     int varidx;
  691.  
  692.     if ((varidx=findvar(name)) == ERROR) {
  693.         printf("What happened! I can't find '%s'",name);
  694.         cleanup(1);
  695.     }
  696.     VARTABLE[varidx].parmtype=type;
  697.     return(varidx);
  698. }
  699.  
  700. /* Initialize mprint variables */
  701. initvars()
  702. {
  703.     int varidx;
  704.  
  705.     varidx=initvar("pattern1", STRG);
  706.     VARTABLE[varidx].v.u_strg=(char *) &PATTERN[0];
  707.     varidx=initvar("pattern2", STRG);
  708.     VARTABLE[varidx].v.u_strg=(char *) &PATTERN[16];
  709.     varidx=initvar("pattern3", STRG);
  710.     VARTABLE[varidx].v.u_strg=(char *) &PATTERN[32];
  711.     varidx=initvar("line", STRG);
  712.     VARTABLE[varidx].v.u_strg=LINE;
  713. }
  714.  
  715.