edmoy@violet.Berkeley.EDU (11/30/88)
[macps & prepfix - print Mac files on Unix] Macps is a Unix program that takes a PostScript file created on a Macintosh by typing Command-F to the LaserWriter dialog box and includes an appropriately modified LaserPrep file so that the result can be sent to a PostScript printer from Unix. Unlike most of the other versions of this program, this one includes a second program, prepfix, that converts LaserPrep files to a form compatible with Unix (and can even be electronically mailed). Enjoy, Edward Moy Principal Programmer - Macintosh & Unix Workstation Support Services Workstation Software Support Group University of California Berkeley, CA 94720 edmoy@violet.Berkeley.EDU ucbvax!violet!edmoy --- #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # ReadMe # Makefile # macps.c # macaux.c # ucbwhich.c # prepfix.c # ucbwhich.h # macps.config # macps.1 # prepfix.1 # macps.shar - archive created: Mon Sep 19 17:46:48 PDT 1988 if test -f ReadMe then echo shar: will not overwrite existing file "'ReadMe'" else echo 'x - ReadMe' cat << \RAZZLE!DAZZLE > ReadMe COPYRIGHT NOTICE Copyright (c) 1988, The Trustees of the University of California. Edward Moy, Workstation Software Support Group, Workstation Support Serices, Information Systems and Technology. Permission is granted to any individual or institution to use, copy, or redistribute this software so long as it is not sold for profit, provided that this notice and the original copyright notices are retained. The University of California makes no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. WHAT IS MACPS? Macps is a Unix program that takes a PostScript file created on a Macintosh by typing Command-F to the LaserWriter dialog box (see macps.1 for more details) and includes an appropriately modified LaserPrep file so that the result can be sent to a PostScript printer from Unix. The LaserPrep file contains macros used by the PostScript generator on the Macintosh. WHICH VERSION OF THE LASERPREP WILL BE USED? Macps interprets the %%IncludeProcSet directive found in the PostScript generated by LaserWriter driver 4.0 and greater. It takes the ProcSet id and looks it up in a file "macps.config", to get the pathname of the prep file, and thus macps can convert PostScript generated by different versions of the LaserWriter driver (as well as from applications that have their own ProcSet, such as FullWrite Professional, Aldus PageMaker or Adobe Illustrator. HOW ARE THE PROCSETS GENERATED? Since the Apple LaserPrep files are copyrighted, I've included a program, prepfix, that reads version 4.0 and up LaserPrep files, and edits them so that they are compatible with Unix (and are even electronically mailable). (See prepfix.1 for more details.) Other ProcSets will have to be done manually. WHERE IS THE MACPS.CONFIG FILE LOCATED? Macps has some special code that is able to figure out from which directory it was called from. The macps.config file is expected to be in a "lib" sub-directory. WHAT ABOUT BIT-SMOOTHING ON NON-LASERWRITER PRINTERS? For PostScript printers using Motorola 680x0 processors and Adobe PostScript firmware other than LaserWriters, there are options that will allow these printers to do bit-smoothing, just like LaserWriters. RAZZLE!DAZZLE fi # End ReadMe if test -f Makefile then echo shar: will not overwrite existing file "'Makefile'" else echo 'x - Makefile' cat << \RAZZLE!DAZZLE > Makefile # Copyright (c) 1988, The Trustees of the University of California. # Edward Moy, Workstation Software Support Group, Workstation Support Serices, # Information Systems and Technology. # # Permission is granted to any individual or institution to use, copy, # or redistribute this software so long as it is not sold for profit, # provided that this notice and the original copyright notices are # retained. The University of California makes no representations about the # suitability of this software for any purpose. It is provided "as is" # without express or implied warranty. CFLAGS = -O MACPS = macps.o macaux.o ucbwhich.o PREPFIX = prepfix.o macaux.o all : macps prepfix macps : $(MACPS) cc -o macps -s $(CFLAGS) $(MACPS) prepfix : $(PREPFIX) cc -o prepfix -s $(CFLAGS) $(PREPFIX) RAZZLE!DAZZLE fi # End Makefile if test -f macps.c then echo shar: will not overwrite existing file "'macps.c'" else echo 'x - macps.c' cat << \RAZZLE!DAZZLE > macps.c /* * Copyright (c) 1988, The Trustees of the University of California. * Edward Moy, Workstation Software Support Group, Workstation Support Serices, * Information Systems and Technology. * * Permission is granted to any individual or institution to use, copy, * or redistribute this software so long as it is not sold for profit, * provided that this notice and the original copyright notices are * retained. The University of California makes no representations about the * suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. */ #ifndef lint static char *SCCSid = "@(#)macps.c 1.1 9/19/88"; #endif lint #include <ctype.h> #include <stdio.h> #include <strings.h> #include "ucbwhich.h" #define CONFIG "macps.config" #define LINELEN 256 char *Fgets(); char *myname; int ucbalternate; char ucbpath[UCBMAXPATHLEN]; char ucblib[UCBMAXPATHLEN]; main(argc, argv) int argc; char **argv; { register char *cp, *pp; register FILE *fp, *lp; register int i, libend; char buf[BUFSIZ], line[LINELEN]; ucbwhich(*argv); if(myname = rindex(*argv, '/')) myname++; else myname = *argv; if(argc > 2) { fprintf(stderr, "Usage: %s [file]\n", myname); exit(1); } if(argc == 2 && freopen(*++argv, "r", stdin) == NULL) { fprintf(stderr, "%s: can't open %s\n", myname, *argv); exit(1); } if(Fgets(buf, BUFSIZ, stdin) == NULL) { fprintf(stderr, "%s: Null input\n", myname); exit(1); } strcat(ucblib, "/"); libend = strlen(ucblib); strcat(ucblib, CONFIG); if((fp = fopen(ucblib, "r")) == NULL) { fprintf(stderr, "%s: Can't open %s\n", myname, ucblib); exit(1); } fputs("%!\n", stdout); do { Fputs(buf, stdout); if(strncmp(buf, "%%IncludeProcSet:", 17) == 0) { for(cp = &buf[17] ; ; cp++) { if(!*cp) { fprintf(stderr, "%s: Syntax error on IncludeProcSet line\n", myname); exit(1); } if(!isspace(*cp)) break; } pp = cp + strlen(cp); for( ; ; ) { --pp; if(!isspace(*pp)) break; *pp = 0; } fseek(fp, 0L, 0); for( ; ; ) { if(!fgets(line, LINELEN, fp)) { fprintf(stderr, "%s: Unknown IncludeProcSet (%s)\n", myname, cp); exit(1); } if(*line == '#') continue; if(pp = index(line, '\n')) { if(pp == line) continue; *pp = 0; } if(!(pp = index(line, '\t'))) { fprintf(stderr, "%s: Syntax error in %s\n", myname, ucblib); exit(1); } *pp++ = 0; if(strcmp(line, cp) == 0) break; } if(*pp == '/') strcpy(ucblib, pp); else { ucblib[libend] = 0; strcat(ucblib, pp); } if((lp = fopen(ucblib, "r")) == NULL) { fprintf(stderr, "%s: Can't open %s\n", myname, ucblib); exit(1); } while((i = fread(buf, 1, BUFSIZ, lp)) > 0) fwrite(buf, 1, i, stdout); fclose(lp); } } while(Fgets(buf, BUFSIZ, stdin)); exit(0); } RAZZLE!DAZZLE fi # End macps.c if test -f macaux.c then echo shar: will not overwrite existing file "'macaux.c'" else echo 'x - macaux.c' cat << \RAZZLE!DAZZLE > macaux.c /* * Copyright (c) 1988, The Trustees of the University of California. * Edward Moy, Workstation Software Support Group, Workstation Support Serices, * Information Systems and Technology. * * Permission is granted to any individual or institution to use, copy, * or redistribute this software so long as it is not sold for profit, * provided that this notice and the original copyright notices are * retained. The University of California makes no representations about the * suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. */ #ifndef lint static char *SCCSid = "@(#)macaux.c 1.1 9/19/88"; #endif lint #include <ctype.h> #include <stdio.h> char *Fgets(b, n, fp) char *b; register int n; register FILE *fp; { register int c; register char *cp = b; while(--n > 0) { if((c = getc(fp)) == EOF) { if(cp > b) break; else return(NULL); } if(isascii(c) && !isprint(c)) { if(c == '\n' || c == '\r') { *cp++ = '\n'; *cp = 0; return(b); } else if(c == 0) c = 0200; } *cp++ = c; } *cp = 0; return(b); } Fputs(b, fp) register char *b; register FILE *fp; { while(*b) { if(*b & 0200) { if((*b & 0177) == 0) *b = 0; fprintf(fp, "\\%03o", *b); } else if(!isprint(*b) && *b != '\n' && *b != '\t') fprintf(fp, "\\%03o", *b); else putc(*b, fp); b++; } } RAZZLE!DAZZLE fi # End macaux.c if test -f ucbwhich.c then echo shar: will not overwrite existing file "'ucbwhich.c'" else echo 'x - ucbwhich.c' cat << \RAZZLE!DAZZLE > ucbwhich.c /* * Copyright (c) 1988, The Trustees of the University of California. * Edward Moy, Workstation Software Support Group, Workstation Support Serices, * Information Systems and Technology. * * Permission is granted to any individual or institution to use, copy, * or redistribute this software so long as it is not sold for profit, * provided that this notice and the original copyright notices are * retained. The University of California makes no representations about the * suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. */ #ifndef lint static char *SCCSid = "@(#)ucbwhich.c 1.1 9/19/88"; #endif lint #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include "ucbwhich.h" #define F_OK 0 /* does file exist */ #define X_OK 1 /* is it executable by caller */ #define W_OK 2 /* writable by caller */ #define R_OK 4 /* readable by caller */ #define LIBLEN 4 static char lib[] = "/lib"; char ucblib[UCBMAXPATHLEN]; int ucbalternate = 0; char ucbpath[UCBMAXPATHLEN]; ucbwhich(str) char *str; { register char *dir, *name, *cp, *tp; register int len; char dirbuf[UCBMAXPATHLEN], namebuf[UCBMAXPATHLEN]; struct stat sbuf; char *index(), *rindex(), *getwd(), *getenv(); strcpy(name = namebuf, str); if(*name == '/') /* absolute pathname */ *(rindex(dir = name, '/')) = 0 ; /* remove tail */ else { if(cp = index(name, '/')) { /* relative pathname */ if((dir = getwd(dirbuf)) == NULL) return(0); /* if any errors occurs assume standard version */ *cp++ = 0; for( ; ; ) { if(*name != 0) { /* multiple slashes */ if(strcmp(name, "..") == 0) { /* parent directory */ if((tp = rindex(dir, '/')) == NULL) return(0); if(tp == dir) tp++; /* root directory */ *tp = 0; /* remove last component */ } else if(strcmp(name, ".") != 0) { /* subdirectory */ strcat(dir, "/"); strcat(dir, name); } } name = cp; if((cp = index(name, '/')) == NULL) break; /* ignore last component */ *cp++ = 0; } } else { /* look through $PATH variable */ if((tp = getenv("PATH")) == NULL) return(0); for(name = namebuf ; ; ) { if(*tp == 0) return(0); else if(*tp == ':') tp++; if((cp = index(tp, ':')) == NULL) cp = tp + strlen(tp); /* positioned on null */ for(dir = dirbuf ; tp < cp ; ) *dir++ = *tp++; *dir = 0; strcpy(name, dir = dirbuf); strcat(name, "/"); strcat(name, str); if(stat(name, &sbuf) < 0 || (sbuf.st_mode & S_IFMT) != S_IFREG) continue; if(access(name, X_OK) == 0) { if(strcmp(dir, ".") == 0 && (dir = getwd(dirbuf)) == NULL) return(0); break; } } } } strcpy(ucbpath, dir); strcpy(ucblib, dir); if((len = strlen(dir)) < LIBLEN || strcmp(&dir[len - LIBLEN], lib) != 0) strcat(ucblib, lib); else ucbpath[len - LIBLEN] = 0; ucbalternate = (strcmp(ucbpath, UCBSTANDARD) != 0); #ifdef EBUG fprintf(stderr, "ucbwhich: alt=%d path=%s lib=%s\n", ucbalternate, ucbpath, ucblib); #endif EBUG return(ucbalternate); } RAZZLE!DAZZLE fi # End ucbwhich.c if test -f prepfix.c then echo shar: will not overwrite existing file "'prepfix.c'" else echo 'x - prepfix.c' cat << \RAZZLE!DAZZLE > prepfix.c /* * Copyright (c) 1988, The Trustees of the University of California. * Edward Moy, Workstation Software Support Group, Workstation Support Serices, * Information Systems and Technology. * * Permission is granted to any individual or institution to use, copy, * or redistribute this software so long as it is not sold for profit, * provided that this notice and the original copyright notices are * retained. The University of California makes no representations about the * suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. */ #ifndef lint static char *SCCSid = "@(#)prepfix.c 1.1 9/19/88"; #endif lint #include <ctype.h> #include <stdio.h> #include <strings.h> #define BIGBUFSIZE 10240 #define CLEARTOMARK 12 #define EEXECLEN 80 #define EXTRA (NZEROLINE * ZEROLINE + CLEARTOMARK) #define LINELEN 256 #define NPRODUCT 16 #define NZEROLINE 7 #define PRODUCTLEN 64 #define ZEROLINE 65 char *Fgets(); char *match(); char *myname; char lproduct[PRODUCTLEN][NPRODUCT]; char pproduct[PRODUCTLEN][NPRODUCT]; char tempname[] = "/tmp/prepfixXXXXXX"; main(argc, argv) int argc; char **argv; { register FILE *tp; register int i, nl, np; register char *lp, *pp; char buf[BIGBUFSIZE]; if(myname = rindex(*argv, '/')) myname++; else myname = *argv; nl = np = 0; for(argc--, argv++ ; argc > 0 && **argv == '-' ; argc--, argv++) { switch((*argv)[1]) { case 'h': usage(); case 'l': if(nl >= NPRODUCT - 1) { fprintf(stderr, "%s: Too many LW-like product names\n", myname); exit(1); } if((*argv)[2]) lp = &(*argv)[2]; else { if(argc < 2) { fprintf(stderr, "%s: No argument for -l\n", myname); exit(1); } argc--; argv++; lp = *argv; } strncpy(lproduct[nl], lp, PRODUCTLEN - 1); lproduct[nl++][PRODUCTLEN - 1] = 0; break; case 'p': if(np >= NPRODUCT - 1) { fprintf(stderr, "%s: Too many LW+-like product names\n", myname); exit(1); } if((*argv)[2]) pp = &(*argv)[2]; else { if(argc < 2) { fprintf(stderr, "%s: No argument for -p\n", myname); exit(1); } argc--; argv++; pp = *argv; } strncpy(pproduct[np], pp, PRODUCTLEN - 1); pproduct[np++][PRODUCTLEN - 1] = 0; break; } } if(argc > 1) usage(); if(argc > 0 && freopen(*argv, "r", stdin) == NULL) { fprintf(stderr, "%s: can't open %s\n", myname, *argv); exit(1); } mktemp(tempname); if((tp = fopen(tempname, "w+")) == NULL) { fprintf(stderr, "%s: can't create temp file %s\n", myname, tempname); exit(1); } unlink(tempname); if(Fgets(buf, BIGBUFSIZE, stdin) == NULL) { fprintf(stderr, "%s: Null input\n", myname); exit(1); } for( ; ; ) { if(strncmp(buf, "% \251", 3) == 0) { fputs("% ", tp); buf[0] = '('; buf[1] = 'C'; buf[2] = ')'; } else if(strncmp(buf, "%%BeginProcSet:", 15) == 0) { Fputs(buf, stdout); fseek(tp, 0L, 0); while((i = fread(buf, 1, BIGBUFSIZE, tp)) > 0) fwrite(buf, 1, i, stdout); fclose(tp); break; } Fputs(buf, tp); if(Fgets(buf, BIGBUFSIZE, stdin) == NULL) { fprintf(stderr, "%s: No BeginProcSet\n", myname); exit(1); } } while(Fgets(buf, BIGBUFSIZE, stdin)) { if((nl || np) && strncmp(buf, "/LW{", 4) == 0) { Fputs(buf, stdout); if(!Fgets(buf, BIGBUFSIZE, stdin)) { fprintf(stderr, "%s: Unexpected EOF while adding product names\n", myname); exit(1); } Fputs(buf, stdout); for(i = 0 ; i < nl ; i++) printf("LW 0 eq {/LW{save statusdict/product get(%s)anchorsearch exch pop {pop 1}{0}ifelse exch restore}bind def}if\n", lproduct[i]); for(i = 0 ; i < np ; i++) printf("LW 0 eq {/LW{save statusdict/product get(%s)anchorsearch exch pop {pop 2}{0}ifelse exch restore}bind def}if\n", pproduct[i]); continue; } else if(match(buf, "setdefaulttimeouts") || match(buf, "setsccinteractive")) putchar('%'); else if(match(buf, "eexec")) { if(match(buf, "/stretch")) { eexec("stretch", buf); continue; } else if(match(buf, "/smooth4")) { eexec("smooth4", buf); continue; } } else if(strncmp(buf, "%%EndProcSet", 12) == 0) { Fputs(buf, stdout); break; } Fputs(buf, stdout); } exit(0); } char *match(str1, str2) register char *str1, *str2; { register int firstchar = *str2; register int len = strlen(str2); while(*str1) { if(*str1 == firstchar && strncmp(str1, str2, len) == 0) return(str1); str1++; } return(NULL); } eexec(name, buf) char *name; register char *buf; { register int len; register char *bp; if(!Fgets(buf, BIGBUFSIZE, stdin)) { fprintf(stderr, "%s: EOF during reading eexec\n", myname); exit(1); } len = strlen(bp = buf) - 1; printf("ok userdict/%s known not and{currentfile eexec}{%d{currentfile read pop pop}repeat}ifelse\n", name, len + (len / EEXECLEN) + (len % EEXECLEN ? 1 : 0) + EXTRA); while(len >= 80) { fwrite(bp, 80, 1, stdout); putchar('\n'); bp += 80; len -= 80; } if(len > 0) { fwrite(bp, len, 1, stdout); putchar('\n'); } for( ; ; ) { if(Fgets(buf, BIGBUFSIZE, stdin) == NULL) { fprintf(stderr, "%s: EOF reached before cleartomark\n", myname); exit(1); } if(strncmp(buf, "cleartomark", 11) == 0) { Fputs(buf, stdout); return; } Fputs(buf, stdout); } } usage() { fprintf(stderr, "Usage: %s [-l LW_name] [-p LW+_name] [file]\n", myname); fprintf(stderr, " %s -help\n", myname); exit(1); } RAZZLE!DAZZLE fi # End prepfix.c if test -f ucbwhich.h then echo shar: will not overwrite existing file "'ucbwhich.h'" else echo 'x - ucbwhich.h' cat << \RAZZLE!DAZZLE > ucbwhich.h /* * Copyright (c) 1988, The Trustees of the University of California. * Edward Moy, Workstation Software Support Group, Workstation Support Serices, * Information Systems and Technology. * * Permission is granted to any individual or institution to use, copy, * or redistribute this software so long as it is not sold for profit, * provided that this notice and the original copyright notices are * retained. The University of California makes no representations about the * suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. */ /* * SCCSid = "@(#)ucbwhich.h 1.1 9/19/88" */ #define UCBMAXPATHLEN 128 #define UCBSTANDARD "/usr/ucb" extern char ucblib[]; extern int ucbalternate; extern char ucbpath[]; RAZZLE!DAZZLE fi # End ucbwhich.h if test -f macps.config then echo shar: will not overwrite existing file "'macps.config'" else echo 'x - macps.config' cat << \RAZZLE!DAZZLE > macps.config # This is the config file read by macps. # # Each line is composed of the %%IncludeProcSet id, a tab and the file # containing the ProcSet. If the file doesn't begin with a slash, the # the name is taken to be relative to the directory in which this config file # resides. AldusDict2 209 1 ProcSets/AldusPrep2.0 Adobe_Illustrator_1.1 0 0 ProcSets/Illustrator1.1 (FullWriteProcSet) 1.0 1 ProcSets/FullWrite1.0 "(AppleDict md)" 65 0 ProcSets/LaserPrep4.0 "(AppleDict md)" 66 ProcSets/LaserPrep5.0 "(AppleDict md)" 67 0 ProcSets/LaserPrep5.1 "(AppleDict md)" 68 0 ProcSets/LaserPrep5.2 RAZZLE!DAZZLE fi # End macps.config if test -f macps.1 then echo shar: will not overwrite existing file "'macps.1'" else echo 'x - macps.1' cat << \RAZZLE!DAZZLE > macps.1 .TH MACPS 1 "19 Sept 1988" .UC 4 .SH NAME macps \- print Macintosh-created PostScript file on Unix .SH SYNOPSIS .B macps [ file ] .SH DESCRIPTION .I Macps takes the command-line file (or the standard input if no filename is given), and prepends the appropriate Macintosh LaserPrep file (e.g., those generated by .IR prepfix (1)). The standard output can then be directed to a PostScript printer, via .IR lpr (1), for example. .PP The input PostScript file is generated on a Macintosh by typing (and holding) command-F immediately after clicking the OK button of the LaserWriter printer dialog box. Another dialog will appear, confirming that a file named ``PostScript'' is being created (the command-F keys can be released now). This file can then be uploaded via some file transfer program, such as MacTerminal/VersaTerm and .IR macget (1) or MacKermit/Red Ryder and .IR kermit (1). .SH FILES .TP "\w'lib/macps.config 'u" lib/macps.config Maps ProcSet ids to ProcSet filenames .SH "SEE ALSO" lpr(1), macget(1), kermit(1), prepfix(1) .SH BUGS .I Macps only works with version 4.0 and up of the Macintosh LaserPrep files, as well as Aldus PageMaker, Adobe Illustrator and FullWrite Professional LaserPrep files. Because of the way bit smoothing is implimented by the LaserWriter driver, many PostScript printers other than the Apple LaserWriters will not be able to bit smooth. RAZZLE!DAZZLE fi # End macps.1 if test -f prepfix.1 then echo shar: will not overwrite existing file "'prepfix.1'" else echo 'x - prepfix.1' cat << \RAZZLE!DAZZLE > prepfix.1 .TH PREPFIX 1 "19 Sept 1988" .UC 4 .SH NAME prepfix \- converts Apple LaserPrep files to form useable on Unix .SH SYNOPSIS .B prepfix [ .B \-l lw_name ] [ .B \-p lw+_name ] [ file ] .SH DESCRIPTION .I Prepfix takes the command-line LaserPrep file (or the standard input if no filename is given), and converts it into a form that is useable on Unix with the .IR macps (1), and is even electronically mailable. .PP To use .IR prepfix , create the input LaserPrep file on a Macintosh by opening an empty document in some application, selecting .B Print from the .B File menu and then typing (and holding) command-K immediately after clicking the .B OK button of the LaserWriter printer dialog box. Another dialog will appear, confirming that a file named ``PostScript'' is being created (the command-K keys can be released now). This file can then be uploaded via some file transfer program, such as MacTerminal/VersaTerm and .IR macget (1) or MacKermit/Red Ryder and .IR kermit (1). .PP Normally, only Apple LaserWriters can take advantage of the bit smoothing feature of the LaserPrep file. However, other PostScript laser printer using the Motorola 680x0 processor and the Adobe PostScript firmware can be made to do bit smoothing by specifying for each printer either the .B \-l or .B \-p options for LaserWriter and LaserWriter Plus class machines, respectively. The option argument is the first 63 characters of the printer's name (as returned by the .B product command in .BR serverdict ). The resulting LaserPrep file will be modified so that for LaserWriters and for printers specified in the .B \-l and .B \-p options, bit smoothing will be allowed (smoothing must still be selected in the Print Dialog box when saving the PostScript to disk). .SH "SEE ALSO" macps(1), macget(1), kermit(1) .SH BUGS .I Prepfix only works with version 4.0 and up of the Macintosh LaserPrep files. Only 16 of each of the .B \-l and .B \-p printer names is currently supported. RAZZLE!DAZZLE fi # End prepfix.1 echo '***** End of' macps.shar '*****' exit ---