jonnyg@umd5.umd.edu (Jon Greenblatt) (02/13/88)
Here is the epson to postscript program I promised earlier. It works very well now but it's still a baby. I am distributing it in hopes to get other postscript hackers interested in giving input. This program is implemented using a finite state machine in readable format. I am not much of a believer in comments but I strongly believe in readable code. If you read the source carefully, you should know what's going on. # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # # Wrapped by rover!jonnyg on Fri Feb 12 12:33:06 EST 1988 # Contents: epson.c set.h set.c crlf.c makefile echo x - epson.c sed 's/^@//' > "epson.c" <<'@//E*O*F epson.c//' /* * Version 0.5 {Supports about half of the more reasonable escapes} * * IBM Graphics printer to postscript translator. * * Copyright (c) 1988, Jonathan Greenblatt, * <jonnyg@rover.umd.edu> (128.8.2.73) * <jonnyg@umd5.umd.edu> (128.8.10.5) * <pcproj@gymble.umd.edu> (128.8.128.16) * This program may be redistributed in source form, * provided no fee is charged and this copyright notice is preserved. * * DESCRIPTION: * This program uses standard input and output to convert epson printer * codes to Postcript. This program is an execlent ASCII listing printer. * The crlf program is include to add PC crlf to end of lines for * printing UNIX listings. This program was written on an IBM RT running * 4.3. The RT does not do crlf conversions by default so some changes * may have to be made on other systems. This is a working subset of * what I plan to complete. I am distributing this in hopes someone else * will take interest in this code. * * SUPPORTS: * 1: ASCII text. * 2: Underlining. * 3: Overstrike. * 4: Double width. * 5: Highlighting <Esc>G * 6: Super/Subscript * 7: 80x66 character on a page. * * NEEDED: * 1: Compressed mode. * 2: Variable line spacing. * 3: Option for hadling CRLF * 4: Non ASCII characters. * 5: Graphics escapes. * 6: I make an assumption that the font has a 6/10 ration, there are * better ways of doing this. * * BUGS: * 1: Seems to timeout the apple laserwriter when I send large prinouts * through the tty line using no specail line controll. * * PORTABILITY: * I have not tried this anywhere else but it should be easily portable * to the IBM PC with turbo or Microsoft C. * * FILES: * crlf.c: Convert UNIX file to pc Carriage return linefeed format. * epson.c: Main program. * set.c: ASCII set functions, like pascal, will be used more as I write * more. * set.h: Include file for set handling code. * makefile: Unix makefile. * */ #include <stdio.h> #include "set.h" /* Set functions for characters */ #define MAXX 480 #define MAXY 396 #define XSTART 0 #define YSTART point_sizey #define YSTOP MAXY #define XSTOP MAXX #define BNDX (cx >= (XSTOP - point_sizex - 1)) #define BNDY (cy >= (YSTOP - 1)) #define NUM_TABS 28 int tabs[NUM_TABS+1] = {8,16,32,40,48,56,64,72,80,88,96,104,112,124, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}; char *printables = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890`,./\\[]=-!@#$%^&*()_+|{}:\"<>?~;'"; char *needesc = "()\\"; typedef enum {normal,bold,doublenorm,doublebold} _font_type; char *font_descr[] = {"Courier","Courier-Bold","Courier","Courier-Bold"}; char *font_name[] = {"normalfont","boldfont","doublefont","doublebold"}; int font_size[][2] = {{10,10},{10,10},{5,10},{5,10}}; char_set printable_set; char_set needesc_set; _font_type font_type; int cx, cy; int point_sizex, point_sizey; int underline = 0; int subscript = 0; int doublewidth = 0; int highlight = 0; char *start_doc[] = { "/saveobj1 save def", "/mt {moveto} def", "/s {show} def", "clippath pathbbox", "/ymax exch def /xmax exch def /ymin exch def /xmin exch def", "xmin ymax translate", "xmax xmin sub 480 div", "ymin ymax sub 396 div", "scale", "newpath", ".5 setlinewidth", NULL}; char *start_page[] = { "/saveobj2 save def", NULL}; char *end_page[] = { "showpage", "saveobj2 restore", NULL}; char *end_doc[] = { "saveobj1 restore", "\004", NULL}; define_font(name,font,sizex,sizey) char *name, *font; { printf("/%s {/%s findfont [%d 10 6 div mul 0 0 -%d 0 0] makefont setfont} def\n",name,font,sizex,sizey); } new_page() { cx = XSTART; cy = YSTART; plist(start_page); set_font(); } set_font() { font_type = (doublewidth) ? (highlight) ? doublebold : doublenorm : (highlight) ? bold: normal; point_sizex = get_pointx(font_size[(int)font_type][0]); point_sizey = get_pointy(font_size[(int)font_type][1]); printf("%s\n",font_name[(int)font_type]); } eject_page() { plist(end_page); new_page(); } init_sets() { clear_set(printable_set); clear_set(needesc_set); str_add_set(printable_set,printables); str_add_set(needesc_set,needesc); } get_pointx(char_per_inch) { return(60/char_per_inch); } get_pointy(char_per_inch) { return(60/char_per_inch); } init_printer() { point_sizex = get_pointx(font_size[(int)normal][0]); point_sizey = get_pointy(font_size[(int)normal][1]); plist(start_doc); define_font(font_name[(int)normal],font_descr[(int)normal],point_sizex,point_sizey); define_font(font_name[(int)bold],font_descr[(int)bold],point_sizex,point_sizey); point_sizex = get_pointx(font_size[(int)doublenorm][0]); point_sizey = get_pointy(font_size[(int)doublenorm][1]); define_font(font_name[(int)doublenorm],font_descr[(int)doublenorm],point_sizex,point_sizey); define_font(font_name[(int)doublebold],font_descr[(int)doublebold],point_sizex,point_sizey); font_type = normal; new_page(); } plist(l) char **l; { while (*l != NULL) printf("%s\n",*l++); } #define LINE_SIZE 256 char pline[256]; int ptr = 0; char outline[258]; putline() { char *s = pline; int p; int lx; if (BNDY) eject_page(); while (*s == ' ' && ptr > 0) { s++; ptr--; if (BNDX) {cx = XSTART; newline();} cx += point_sizex; } while (ptr>0) { p = 0; if (BNDY) eject_page(); if (BNDX) {cx = XSTART; newline();} lx = cx; while ((lx+point_sizex-1) < XSTOP && ptr > 0) { if (in_set(needesc_set,*s)) outline[p++] = '\\'; outline[p++] = *s++; ptr--; lx += point_sizex; } outline[p] = 0; if (p > 0) { int i = strlen(outline); /* Forward slash won't work at the end of a string */ if (outline[i-1] == '/') { outline[i] = ' '; outline[i+1] = '\0'; } if (subscript) if (subscript == 1) /* Subscript */ printf("%d %d mt gsave 1 .5 scale (%s) s grestore\n",cx,cy,outline); else /* Superscript */ printf("%d %d mt gsave 1 .5 scale (%s) s grestore\n",cx,cy-(point_sizey>>1),outline); else /* Normal printing */ printf("%d %d mt (%s) s\n",cx,cy,outline); if (underline) printf("%d %d mt %d %d lineto stroke\n",cx,cy+1,lx-1,cy+1); } cx = lx; } } newline() { cy += point_sizey; if (BNDY) eject_page(); } typedef enum {S_BASE,S_ESC,S_UNDERLINE,S_SUBSCRIPT,S_DOUBLE} states; states state = S_BASE; dochar(c) { if (ptr >= LINE_SIZE) putline(); switch (state) { case S_UNDERLINE: state = S_BASE; if (c == '\0') underline = 0; else if (c == '\1') underline = 1; break; case S_DOUBLE: state = S_BASE; if (c == '\0') doublewidth = 0; else if (c == '\1') doublewidth = 1; set_font(); break; case S_SUBSCRIPT: state = S_BASE; if (c == '\0') subscript = 2; else if (c == '\1') subscript = 1; break; case S_ESC: state = S_BASE; switch (c) { case 'G': highlight = 1; set_font(); break; case 'H': highlight = 0; set_font(); break; case '-': state = S_UNDERLINE; break; case 'T': subscript = 0; break; case 'S': state = S_SUBSCRIPT; break; case 'W': state = S_DOUBLE; break; } break; case S_BASE: switch(c) { case '\011': { int i,l; l = cx / point_sizex + ptr; for (i = 0; i < NUM_TABS && tabs[i] <= l; i++); if (tabs[i] == -1) break; i = tabs[i] - l; while (i-- > 0) dochar(' '); } break; case '\033': putline(); state = S_ESC; break; case '\014': putline(); eject_page(); break; case '\n': putline(); newline(); break; case '\r': putline(); cx = XSTART; break; case 26: /* CTRL-Z */ break; default: if (in_set(printable_set,c)) pline[ptr++] = c; else pline[ptr++] = ' '; break; } break; } } char istr[128]; main() { int n; char *p; init_sets(); init_printer(); while ((n = read(0,p = istr,128)) > 0) while (n--) dochar(*p++); if (cx > XSTART || cy > YSTART) plist(end_page); else printf("saveobj2 restore\n"); plist(end_doc); } @//E*O*F epson.c// chmod u=rw,g=r,o=r epson.c echo x - set.h sed 's/^@//' > "set.h" <<'@//E*O*F set.h//' #define INTS_IN_SET 16 typedef unsigned int char_set[INTS_IN_SET]; @//E*O*F set.h// chmod u=rw,g=r,o=r set.h echo x - set.c sed 's/^@//' > "set.c" <<'@//E*O*F set.c//' #include "set.h" clear_set(set) char_set set; { int i; for (i = 0; i < INTS_IN_SET; i++) set[i] = 0; } fill_set(set) char_set set; { int i; for (i = 0; i < INTS_IN_SET; i++) set[i] = 0xffff; } not_set(set) char_set set; { int i; for (i = 0; i < INTS_IN_SET; i++) set[i] ^= 0xffff; } and_set(set,set1) char_set set, set1; { int i; for (i = 0; i < INTS_IN_SET; i++) set[i] &= set1[i]; } or_set(set,set1) char_set set,set1; { int i; for (i = 0; i < INTS_IN_SET; i++) set[i] |= set1[i]; } add_set(set,c) char_set set; unsigned int c; { c &= 0xff; set[c >> 4] |= 1 << (c & 15); } del_set(set,c) char_set set; unsigned int c; { c &= 0xff; set[c >> 4] &= ~(1 << (c & 15)); } in_set(set,c) char_set set; unsigned int c; { c &= 0xff; return ((set[c >> 4] & (1 << (c & 15))) != 0); } str_add_set(set,s) char_set set; char *s; { unsigned int c; while (*s) { c = *s++; c &= 0xff; set[c >> 4] |= 1 << (c & 15); } } str_del_set(set,s) char_set set; char *s; { unsigned int c; while (*s) { c = *s++; c &= 0xff; set[c >> 4] &= ~(1 << (c & 15)); } } @//E*O*F set.c// chmod u=rw,g=r,o=r set.c echo x - crlf.c sed 's/^@//' > "crlf.c" <<'@//E*O*F crlf.c//' main() { char ibuff[512], *ip; char obuff[1024]; int ic, oc; while ((ic = read(0,ip = ibuff,512)) > 0) { oc = 0; while (ic--) if (*ip == '\n') { ip++; obuff[oc++] = '\r'; obuff[oc++] = '\n'; } else obuff[oc++] = *ip++; write(1,obuff,oc); } } @//E*O*F crlf.c// chmod u=rw,g=r,o=r crlf.c echo x - makefile sed 's/^@//' > "makefile" <<'@//E*O*F makefile//' CC=cc all: epson crlf epson: epson.o set.o $(CC) epson.o set.o -o epson epson.o: epson.c set.h $(CC) -O -c epson.c set.o: set.c set.h $(CC) -O -c set.c crlf: crlf.c $(CC) -O crlf.c -o crlf @//E*O*F makefile// chmod u=rw,g=r,o=r makefile exit 0