/* Program ep437.c */

/* Print IBM PC Code Page 437 Files on an Epson FX-80 or RX-80 Printer */
/* Converts PC character set into Epson character set. */
/* When the Epson does not have an equivalent to a PC character, this */
/* Program attempts to approximate it by overstriking (like a-ring, */
/* i-acute, less-than-or-equal, etc). If an overstruck version can't be */
/* made, this program prints a round blob.  Most Greek characters are */
/* written with Roman equivalents (alpha = a, sigma = s, etc). */

/* Users are encouraged to improve this program and to adapt it for use */
/* with other code pages (like CP850) and with other kinds of printers */
/* (like Postscript). */ 

/* Usage: On PC, "ep437 filename > prn" or "program | ep437 > prn"

/* F. da Cruz, Columbia University, December 1989 */

#include <stdio.h>

/* Add "\33O" to reset if you want to defeat "skip-over-perforation". */

char *reset = "\33@";			/* Escape sequence to reset printer */
char *ascii = "\33R0";			/* Sequence to switch character set */
					/* to US ASCII. */

/* 7-bit characters are plain ASCII, untranslated. */
/* The following translation table is for 8-bit characters. */
/* Constants are in octal, since that's how C likes them. */
/* First, the "national" language-related characters... */

char *t[] = {
"\33R\1\134",				/* 128 C-cedilla */ 
"\33R\2\175",				/* 129 u-umlaut */
"\33R\1\173",				/* 130 e-acute */ 
"\33R0a\10\136",			/* 131 a-circumflex */ 
"\33R\2\173",				/* 132 a-umlaut */ 
"\33R\1\100",				/* 133 a-grave */ 
"\33R\6\133\10\141",			/* 134 a-ring (overstrike) */ 
"\33R\1\134",				/* 135 c-cedilla (use uppercase) */ 
"\33R0e\10^",				/* 136 e-circumflex */ 
"\33R0e\10\33R\1\176",			/* 137 e-umlaut (overstrike) */ 
"\33R0\33R\1\175",			/* 138 e-grave (overstrike) */ 
"\33R0i\10\33R\1\176",			/* 139 i-umlaut (overstrike) */ 
"\33R0i\10^",				/* 140 i-circumflex (overstrike) */ 
"\33R\6\176",				/* 141 i-grave */ 
"\33R\2\133",				/* 142 A-umlaut */ 
"\33R\4\135",				/* 143 A-ring */ 
"\33R\5\100",				/* 144 E-acute */ 
"\33R\4\173",				/* 145 ae digraph */ 
"\33R\4\133",				/* 146 AE digraph */ 
"\33R0o\10^",				/* 147 o-circumflex (overstrike) */ 
"\33R\2\174",				/* 148 o-umlaut */ 
"\33R\6\174",				/* 149 o-grave */ 
"\33R\2\175\10^",			/* 150 u-circumflex (overstrike) */ 
"\33R\1\174",				/* 151 u-grave */ 
"\33R0y\10\33R\1\176",			/* 152 y-umlaut (overstrike) */ 
"\33R\2\134",				/* 153 O-umlaut */ 
"\33R\2\135",				/* 154 U-umlaut */ 
"\33R0c\10\033R0/",			/* 155 cent (overstrike) */ 
"\33R\3\43",				/* 156 pound */ 
"\33R\10\134",				/* 157 yen */ 
"\33R\7\43",				/* 158 Pt */ 
"\33R0f",				/* 159 florin */ 
"\33R0a\10'",				/* 160 a-acute (overstrike) */ 
"\33R0i\10'",				/* 161 i-acute (overstrike) */ 
"\33R0o\10'",				/* 162 o-acute (overstrike) */ 
"\33R0u\10'",				/* 163 u-acute (overstrike) */ 
"\33R\7\174",				/* 164 n-tilde */ 
"\33R\7\134",				/* 165 N-tilde */ 
"\33S0a\33T",				/* 166 fem. ordinal (superscript) */ 
"\33S0o\33T",				/* 167 masc. ordinal (superscript) */
"\33R\7\135",				/* 168 ?-inverted */ 

/* The following are approximations of IBM box & line drawing characters */

"\33m\4\207",				/* 169 u.l.corner */ 
"\33m\4\210",				/* 170 u.r.corner */ 
"\33m\4\217",				/* 171 1/2 unk */ 
"\33m\4\217",				/* 172 1/4 unk */ 
"\33R\7\133",				/* 173 !-inv */ 
"\33R0<",				/* 174 << */ 
"\33R0>",				/* 175 >> */ 
"\33m\4\213",				/* 176 light box */ 
"\33m\4\213",				/* 177 med box */ 
"\33m\4\214",				/* 178 dark box */ 
"\33m\4\206",				/* 179 vert line */ 
"\33m\4\203",				/* 180 -| */ 
"\33m\4\203",				/* 181 =| */ 
"\33m\4\203",				/* 182 -|| */ 
"\33m\4\210",				/* 183 overline || (u.r.corner) */ 
"\33m\4\210",				/* 184 double overline | (u.r.c) */ 
"\33m\4\203",				/* 185 double -| */ 
"\33m\4\206",				/* 186 || */ 
"\33m\4\210",				/* 187 double u.r.corner */ 
"\33m\4\212",				/* 188 double l.r.corner */ 
"\33m\4\212",				/* 189 _|| */ 
"\33m\4\212",				/* 190 double underline | */ 
"\33m\4\210",				/* 191 u.r.corner */ 
"\33m\4\211",				/* 192 l.l.corner */ 
"\33m\4\201",				/* 193 inv-T.corner */ 
"\33m\4\202",				/* 194 T.corner */ 
"\33m\4\204",				/* 195 |- */ 
"\33m\4\205",				/* 196 center line */ 
"\33m\4\200",				/* 197 big plus */ 
"\33m\4\204",				/* 198 |= */ 
"\33m\4\204",				/* 199 ||- */ 
"\33m\4\211",				/* 200 double l.l.corner */ 
"\33m\4\207",				/* 201 double u.l.corner */ 
"\33m\4\201",				/* 202 double inv.T.corner */ 
"\33m\4\202",				/* 203 double T.corner */ 
"\33m\4\204",				/* 204 double |- */ 
"\33m\4\205",				/* 205 double center line */ 
"\33m\4\200",				/* 206 double big plus */ 
"\33m\4\201",				/* 207 double center line, | over */ 
"\33m\4\201",				/* 208 double | w/center line under */
"\33m\4\202",				/* 209 double center line, | under */ 
"\33m\4\202",				/* 210 || with overline (T) */ 
"\33m\4\211",				/* 211 ||_ */ 
"\33m\4\211",				/* 212 | with = l.l.corner */ 
"\33m\4\207",				/* 213 | with = u.l.corner */ 
"\33m\4\207",				/* 214 || with overline u.l.corner */ 
"\33m\4\200",				/* 215 || with -- thru center */ 
"\33m\4\200",				/* 216 == with | thru center */ 
"\33m\4\212",				/* 217 l.r.corner */ 
"\33m\4\207",				/* 218 u.l.corner */ 
"\33m\4\214",				/* 219 big black square */ 
"\33m\4\215",				/* 220 low center black rectangle */ 
"\33m\4\216",				/* 221 left black rectangle */ 
"\33m\4\216",				/* 222 right black rectangle */ 
"\33m\4\215",				/* 223 high black rectangle */ 
"\33R0a",				/* 224 Greek alpha (use a) */ 
"\33R\2\176",				/* 225 Greek beta */
"\33m\4\207",				/* 226 Greek Gamma (use u.l.corner */ 
"\33R0n",				/* 227 Greek pi (use l.c. n) */ 
"\33R0S",				/* 228 Greek Sigma (overstrike) */
"\33R0s",				/* 229 Greek sigma (use l.c. s) */ 
"\33R0u",				/* 230 Greek mu (use u) */ 
"\33R0t",				/* 231 Greek tau (use t) */ 
"\33R00\10\033R0I",			/* 232 Greek Fi (overstrike) */ 
"\33R00\10-",				/* 233 Greek Theta (overstrike) */ 
"\33R0O",				/* 234 Greek Omega (use O) */ 
"\33R0d",				/* 235 Greek delta (use d) */ 
"\33m\4\217",				/* 236 infinity (unk) */
"\33R0o\10/",				/* 237 Greek fi */ 
"\33R0e",				/* 238 Greek epsilon (use e) */ 
"\33m\4\217",				/* 239 set thing (unk) */ 
"\33R0=",				/* 240 = with 3 lines (use =) */ 
"\33m\4\237",				/* 241 plus/minus */ 
"\33R0>\10=",				/* 242 greater-equal (overstrike) */ 
"\33R0<\10=",				/* 243 less-equal (overstrike) */ 
"\33m\4\217",				/* 244 integral top (unk) */ 
"\33m\4\217",				/* 245 integral bottom (unk) */ 
"\33m\4\236",				/* 246 division */ 
"\33R0\176\10\33S1\176\33T",		/* 247 approx equal (overstrike) */ 
"\33R\1\133",				/* 248 degree */ 
"\33S0.\33T",				/* 249 center dot (superscript) */ 
"\33S0.\33T",				/* 250 big center dot (superscript) */ 
"\33m\4\217",				/* 251 radical */ 
"\33S0n\33T",				/* 252 n superscript */ 
"\33S02\33T",				/* 253 2 superscript */ 
"\33m\4\217",				/* 254 small center box */ 
"\33R0 \10"				/* 255 nothing */
};

FILE *fp, *fopen();

main(argc,argv) int argc; char *argv[]; { /* Main function. */
    int i, j, n;

    if ((argc == 2) && (!strcmp(argv[1],"-t"))) {
	table();			/* -t means to print tables */
	exit(0);
    }
    if (argc == 1) {			/* If no files given, use stdin */
	fp = stdin;
	xlate();
	exit(0);
    }
    n = 0;				/* File counter */
    while (++n < argc) {		/* Filenames given on command line */
        fprintf(stderr,"%s...\n",argv[n]);
	if ((fp = fopen(argv[n],"r")) == NULL) { /* Open the file */
	  fprintf(stderr,"Can't open %s, skipping.\n",argv[n]);
          continue;
        }
	xlate();			/* Translate the file */
	fclose(fp);			/* Close the file */
	printf("%s","\014");		/* Print a formfeed */
    }
    exit(0);				/* Done */
}

xlate() {				/* Translation function. */
    int mode, y;
    unsigned char x;

    printf("%s",reset);			/* Reset the printer */
    mode = 1;				/* 0 = Regular ASCII, 1 = special */
    while (1) {
	x = y = getc(fp);		/* Get a character */
	if (y == EOF) {			/* EOF, done */
	    printf("%s",reset);
	    return(0);
	} else if (x < 128) {		/* If regular ASCII character */
	    if (mode) {			/* If necessary, */
		printf("%s",ascii);	/* go back to ASCII */
		mode = 0;		/* and remember mode. */
	    }
	    putchar(x);			/* then print the character. */
	} else {			/* If special character */
	    printf("%s",t[x-128]);	/* print its translation */
	    mode = 1;			/* and remember mode. */
	}
    }
}

/* Special positions in 7-bit national replacement character sets */

char c[] = { 35, 36, 64, 91, 92, 93, 94, 96, 123, 124, 125, 126 } ;

/* Function to print character tables... */

table() {
    int i, j, k;

/* Print the Epson national character set table. */

    printf("%s","Epson FX/RX Built-in National Characters:\n\n");
    printf("Dec / Oct   %s",
      "\33-1USA  FR   GE   UK   DK   SW   IT   SP   JP   NO\33-0\n\n");
    for (i = 0; i < 12; i++) {		/* Loop for each line */
	printf("%s",reset);		/* Reset printer */
	printf("%3d / %3o:  0/%c  ",c[i], c[i], c[i]);
	for (j = 1; j < 10; j++) {	/* Loop for each character set */
	    printf("%d/",j);
	    putchar('\33');		/* ESC */
	    putchar('R');		/* R */
	    putchar((char) j);		/* Country character set number */
	    putchar(c[i]);		/* Character to print */
	    putchar(' ');		/* Spaces */
	    putchar(' ');
	}
	putchar('\n');			/* End of line */
    }

/* Print the CP437 character table. */
/* Compare this with the real CP437 table in the back of the DOS manual. */

    printf("%s%s",reset,ascii);		/* Reset printer, select ASCII */
    printf("\n\nIBM Code Page 437:\n\n"); /* Print heading */
    printf("   %s%c","\33-",'1');	/* Underline on */
    for (j = 2; j < 16; j++)            /* Column headings */    
	printf("%3d",j);
    printf("%s%c\n\n","\033-",'0');	/* Underline off */

    for	(i = 0; i < 16; i++) {		/* Loop for each row */
	printf("%s%2d:  ",reset,i);	/* Reset printer */
	for (j = 2; j < 16; j++) {	/* Loop for each character in row */
	    k = i + (j * 16);			/* Code for this character */
	    if (k < 0177) 			/* 7-bit ASCII character */
		printf("%s%c  ", ascii, k); 	/* Print it in ASCII mode */
	    else if (k == 0177)                 /* DEL */
		printf("   "); 		        /* Just print a space */
	    else                                /* 8-bit character */
		printf("%s  ",t[k - 0200]);     /* Use table */
	}
	printf("\n");			/* End of row. */
    }					/* Loop till done. */
    printf("%s",reset);			/* Reset printer. */
}
