/* $Log: dospecial.c,v $ * Revision 0.8 92/11/23 19:46:42 19:46:42 bt (Bo Thide') * Fixed resolution bug. Portable downloading. Added/changed options. PJXL color support * * Revision 0.7 92/11/13 02:41:26 02:41:26 bt (Bo Thide') * More bug fixes and improvements. Support for PaintJet XL * * Revision 0.6 92/11/10 21:47:42 21:47:42 bt (Bo Thide') * Bug fixes. Added -R option. Better font handling. * * Revision 0.5 92/11/09 16:25:29 16:25:29 bt (Bo Thide') * Rewrite of dospecial.c. Extended \special support * * Revision 0.4 92/11/08 02:45:45 02:45:45 bt (Bo Thide') * Changed to portable bit manipulations. Replaced strrstr for non-POSIX compliant C. Fixed numerous bugs. Added support for more \special's. * * Revision 0.3 92/08/24 12:45:37 12:45:37 bt (Bo Thide') * Fixed 8 bit (dc font) support. * * Revision 0.2 92/08/23 17:28:56 17:28:56 bt (Bo Thide') * Source cleaned up. Changed certain function calls. Removed globals. * * Revision 0.1 92/08/22 23:58:47 23:58:47 bt (Bo Thide') * First Release. * */ /* * This procedure will handle any special commands that might appear. * The following variants are handled: * * \special{command} * \special{command(parameters)} * \special{command=parameters} * \special{command parameters} * \special{command:parameters} * * The string contained in the special command is in the name array starting at * 'nextnamesfree' and ending with a '\0'. Also, the 'prescan' boolean should * be checked to see if this is the first or second time that this string was * encountered. * * Copyright 1992 Bo Thide', Uppsala, Sweden . */ #define S_LANDSCAPE 0 /* Original \special "landscape" */ #define S_INCLUDE 1 /* Original \special "include()" */ #define S_GRAFIX 2 /* Original \special "grafix()" */ #define S_MOVE 3 /* Original \special "move()" */ #define S_ESCAPESEQ 4 /* dvi \special "escapeseq ..." */ #define S_RASTERFILE 5 /* dvi \special "rasterfile ..." */ #define S_RAWSTRING 6 /* dvi \special "rawstring ..." */ #define S_ORIENTATION 7 /* Gustaf Neumann's \special "orientation" */ #define S_FILE 8 /* Gustaf Neumann's \special "file" */ #define S_PS 9 /* PostScript \special's "ps:" */ #define S_EM 10 /* 'emtex' \special's "em:" */ #define S_PCL 11 /* PCL \special's "pcl:" */ #define S_HPGL 12 /* PCL5 \special's "hpgl:" */ #define S_PJXL 13 /* PaintJet XL \special "rawstring ..." */ #define SPECIALS 14 /* Number of \special's supported */ #define GRAFLIST 7 /* Number of graphics resolutions supported */ #define COLORLIST 8 /* Number of PaintJet XL text colors */ #include #include #include "globals.h" #include "pcl.h" static char rcsid[] = "$Header: dospecial.c,v 0.8 92/11/23 19:46:42 bt Exp $"; void dospecial(bitfile, prescan, pcllevel, hh, vv, resolution) FILE *bitfile; bool prescan; short pcllevel; long hh, vv; short resolution; { /* The \special arguemnt keywords and their assocated delimiters */ static char *spclargv[SPECIALS][2] = { "landscape", "", "include", "(", "grafix", "(", "move", "(", "escapeseq", " ", "rasterfile", " ", "rawstring", " ", "orientation", "=", "file", "=", "ps", ":", "em", ":", "pcl", ":", "hpgl", ":", "pjxl", ":" }; static char *graflist[] = {"600","300","180","150","100","90","75"}; static char *colorlist[] = {"black","red","green","yellow","blue", "magenta","cyan","white"}; char *bufptr; char *delimptr; /* Pointer to the argument delimiter */ char *iptr, *jptr; /* Generic pointers */ char c; char drawrow[8]; char curname[NAMELENGTH]; /* Current name of generic file */ bool relative; short angle=0; short planes=1; int i, j, k, l; int pxl_rows, row_bytes; int gflag; int ic; long hoffset, voffset; FILE *genfile; /* Generic file pointer */ bufptr = nextnamesfree; #ifdef DEBUG fprintf(stderr,"\ndospecial: nextnamesfree = '%s'\n", nextnamesfree); fprintf(stderr,"dospecial: prescan = '%d'\n", prescan); fprintf(stderr,"dospecial: pcllevel = '%d'\n", pcllevel); #endif /* DEBUG */ /* Process as long as the 'nextnamesfree' is not empty */ while(*bufptr){ while(isspace(*bufptr)) /* Skip over all leading white space */ bufptr++; if(*bufptr){ /* Process only if it was not all white space */ iptr = jptr = bufptr; while(isalpha(*jptr)) /* Move to the end of the first alpha string */ jptr++; /* See if the first alpha string is an OK keyword */ k = 0; while(strncmp(bufptr,spclargv[k][0],strlen(spclargv[k][0]))) k++; /* If the keyword is correct k points to it */ /* Locate the correct delimiter associated with the keyword */ while(*jptr && (*jptr != *spclargv[k][1])) jptr++; delimptr = jptr; /* * Bail out if no correct keyword (k >= SPECIALS) * or no correct delimiter (*jptr == NULL) was found */ if(prescan && ((k >= SPECIALS) || !*jptr)) { fprintf(stderr,"\ndospecial: \\special command not understood: %s\n", nextnamesfree); return; } /* * Here we know that the keyword is OK and that delimptr points to * the correct delimiter associated with that keyword. */ #ifdef DEBUG fprintf(stderr,"\ndospecial: delimptr = '%s'\n", delimptr); #endif /* DEBUG */ /* Move bufptr to point to the delimiter, after the first alpha string */ bufptr = delimptr; /* Make sure the delimiter '(' has a matching ')' */ if(*delimptr == '(') { bufptr++; while((*bufptr != ')') && *bufptr) bufptr++; if(*bufptr == '\0') fprintf(stderr,"\ndospecial: Expected ) after parameter in \\special{%s}.\n", nextnamesfree); else bufptr++; } else { /* Handle the other delimiters */ bufptr++; while(*bufptr) bufptr++; } /* Now bufptr points to the end of the nextnamesfree string */ /* Move jptr to point to after the (one byte) delimiter */ jptr = delimptr + 1; /* Parse the rest of the string for keyword entry spclargv[k][0] */ switch (k) { case S_LANDSCAPE: /* Landscape mode */ if(prescan) landscape = TRUE; break; case S_INCLUDE: /* include(filename) */ if(!prescan) { iptr = curname; while((*jptr != ' ') && (*jptr != ')') && *jptr) *iptr++ = *jptr++; *iptr = '\0'; #ifdef DEBUG fprintf(stderr,"\ndospecial: S_INCLUDE curname = %s\n", curname); #endif /* DEBUG */ if((genfile = fopen(curname,"r")) == NULL) { fprintf(stderr,"Cannot open the \\special{include()} file %s for input.\n", curname); exit(-1); } /* Make the cursor position current and push it */ /* fprintf(bitfile, PCL4_MOVE_POSITION, hh+h_offset, vv+v_offset); fputs(PCL4_PUSH, bitfile); */ while((ic = getc(genfile)) != EOF) putc(ic, bitfile); fclose(genfile); /* fputs(PCL4_POP, bitfile); */ } break; case S_MOVE: /* move(h=..dim v=..dim) */ if(!prescan) { hoffset = voffset = 0L; relative = TRUE; while(*jptr != ')'){ while(*jptr == ' ') jptr++; if(!(c = *jptr++)); if(*jptr == '=') jptr++; switch(c) { case 'h': hoffset = dim_to_dots(jptr, resolution); break; case 'v': voffset = dim_to_dots(jptr, resolution); break; case 'a': relative = FALSE; break; case 'r': relative = TRUE; break; default: fprintf(stderr,"\ndospecial: Invalid parameter in \\special{move}\n"); break; } while((*jptr != ' ') && (*jptr != ')') && *jptr) jptr++; } #ifdef DEBUG fprintf(stderr,"\ndospecial: S_MOVE relative = %d, hoffset = %ld, voffset = %ld\n", relative, hoffset, voffset); #endif /* DEBUG */ if(relative) { if(hoffset) fprintf(bitfile, PCL4_MOVE_HREL, hoffset); if(voffset) fprintf(bitfile, PCL4_MOVE_VREL, voffset); } else { if(hoffset) fprintf(bitfile, PCL4_MOVE_H_POSITION, hoffset); if(voffset) fprintf(bitfile, PCL4_MOVE_V_POSITION, voffset); } } break; case S_GRAFIX: /* grafix(filename [resolution]) */ if(!prescan) { iptr = curname; while((*jptr != ' ') && (*jptr != ')') && *jptr) *iptr++ = *jptr++; *iptr = '\0'; if((genfile = fopen(curname,"r")) == NULL) { fprintf(stderr,"Cannot open the \\special{grafix()} input file %s for input.\n", curname); exit(-1); } while(*jptr == ' ') jptr++; delimptr = jptr; while((*jptr != ' ') && (*jptr != ')') && *jptr) jptr++; if(jptr != delimptr) { *jptr = '\0'; l = 0; while(l < GRAFLIST) if(!strcmp(delimptr, graflist[l])) break; else l++; } else l = 2; if(l == GRAFLIST) { fprintf(stderr,"\ndospecial: Invalid resolution in \\special{grafix}: %s.\n", delimptr); l = 2; } if(l) fprintf(bitfile, PCL4_GRAPHRES, graflist[l]); /* Make the cursor position current and push it */ fprintf(bitfile, PCL4_MOVE_POSITION, hh+h_offset, vv+v_offset); fputs(PCL4_PUSH, bitfile); fputs(PCL4_START_RASTER, bitfile); pxl_rows = (getc(genfile) << 8); pxl_rows = pxl_rows + getc(genfile); gflag = getc(genfile); if(!gflag) sprintf(drawrow, PCL4_DRAWROW, row_bytes = getc(genfile)); for(i = 0 ; i < pxl_rows ; i++) { if(gflag) fprintf(bitfile, PCL4_DRAWROW, row_bytes = getc(genfile)); else fputs(drawrow, bitfile); for(j = 0 ; j < row_bytes ; j++) putc(getc(genfile), bitfile); } fclose(genfile); fputs(PCL4_END_RASTER, bitfile); if(l) fprintf(bitfile, PCL4_GRAPHRES, graflist[0]); fputs(PCL4_POP, bitfile); } break; case S_ORIENTATION: /* PCL5 print orientation/direction */ if(!prescan) { if(pcllevel < 5) fprintf(stderr,"\ndospecial: Changing print direction via \\special not supported at PCL level %d.\n Only at PCL level 5 (option -5).", pcllevel); else { angle = (short)atoi(jptr); if(angle==1) angle=90; else if(angle==2) angle=180; else if(angle==3) angle=270; #ifdef DEBUG fprintf(stderr,"\ndospecial: S_ORIENTATION angle = %d\n", angle); #endif /* DEBUG */ /* Make the cursor position current */ /* fprintf(bitfile, PCL4_MOVE_POSITION, hh+h_offset, vv+v_offset); */ fprintf(bitfile, PCL5_PRINT_DIRECTION, angle); } } break; case S_FILE: /* Input file */ if(!prescan) { iptr = curname; while((*jptr != ' ') && *jptr) *iptr++ = *jptr++; *iptr = '\0'; if((genfile = fopen(curname,"r")) == NULL) { fprintf(stderr,"Cannot open the \\special{input=} file %s for input.\n", curname); exit(-1); } /* Make the cursor position current and push it */ fprintf(bitfile, PCL4_MOVE_POSITION, hh+h_offset, vv+v_offset); fputs(PCL4_PUSH, bitfile); while((ic = getc(genfile)) != EOF) putc(ic, bitfile); fclose(genfile); fputs(PCL4_POP, bitfile); } break; case S_PCL: /* PCL code */ case S_PS: /* PostScript code */ if(!prescan) { /* Make the cursor position current and push it */ fprintf(bitfile, PCL4_MOVE_POSITION, hh+h_offset, vv+v_offset); fputs(PCL4_PUSH, bitfile); while(*jptr) putc(*jptr++, bitfile); fputs(PCL4_POP, bitfile); } break; case S_HPGL: /* PCL5 HP-GL/2 code */ if(!prescan) { if(pcllevel < 5) fprintf(stderr,"\ndospecial: Using HP-GL/2 commands in \\special not supported at PCL level %d.\n Only at PCL level 5 or higher (option -5).", pcllevel); else { /* Make the cursor position current and push it */ fprintf(bitfile, PCL4_MOVE_POSITION, hh+h_offset, vv+v_offset); fputs(PCL4_PUSH, bitfile); /* Enter HP-GL/2 mode. Pen to previous PCL pen position */ fputs(PCL5_HPGLMODE_PCLPEN, bitfile); while(*jptr) putc(*jptr++, bitfile); /* Enter PCL mode. Pen to previous PCL pen position */ fputs(PCL5_PCLMODE_PCLPEN, bitfile); fputs(PCL4_POP, bitfile); } } break; case S_RASTERFILE: /* rasterfile ...*/ if(!prescan) { iptr = curname; while((*jptr != ' ') && *jptr) *iptr++ = *jptr++; *iptr = '\0'; #ifdef DEBUG fprintf(stderr,"\ndospecial: S_RASTERFILE curname = %s\n", curname); #endif /* DEBUG */ if((genfile = fopen(curname,"r")) == NULL){ fprintf(stderr,"Cannot open the \\special{rasterfile} file %s for input.\n", curname); exit(-1); } /* Make the cursor position current and push it */ fprintf(bitfile, PCL4_MOVE_POSITION, hh+h_offset, vv+v_offset); fputs(PCL4_PUSH, bitfile); while((ic = getc(genfile)) != EOF) putc(ic, bitfile); fclose(genfile); fputs(PCL4_POP, bitfile); } break; case S_PJXL: if(!prescan) { #ifdef DEBUG fprintf(stderr,"\ndospecial: S_PJXL jptr = %s\n", jptr); #endif /* DEBUG */ l = 0; while(l < GRAFLIST) { if(!strcmp(jptr, colorlist[l])) break; else l++; } if(l == GRAFLIST) { fprintf(stderr,"\ndospecial: Invalid color in \\special{pjxl:}: %s.\n", jptr); l = 0; } fprintf(bitfile, PJXL_TEXT_COLOR, l); } break; case S_ESCAPESEQ: case S_RAWSTRING: case S_EM: if(prescan) { fprintf(stderr,"\ndospecial: \\special command not implemented: %s\n", nextnamesfree); } break; } } } }