/* m2ps Ver.2.2 -- Convert multilingual text to PostScript Copyright (C) 1992 Free Software Foundation, Inc. */ /* This file is part of Mule (MULtilingual Enhancement of GNU Emacs). Mule is free software distributed in the form of patches to GNU Emacs. You can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. Mule is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Emacs; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* 92.10.8 written by K.Handa */ /* 92.11.3 modified for Mule Ver.0.9.7 by T.Matsuzawa Support NONSPACING characters and send smaller bitmap. */ /* 92.11.6 modified for Mule Ver.0.9.7 by K.Shibata Modified for ANSI-C. */ /* 92.11.10 modified for Mule Ver.0.9.7 by K.Sakaeda Modified for SystemV. */ /* 92.11.24 modified for Mule Ver.0.9.7 by K.Handa Modified to reduce memory. */ /* 92.12.14 modified for Mule Ver.0.9.7 by K.Handa Support composite character. */ /* 93.5.7 modified for Mule Ver.0.9.8 by K.Handa Bug in handling missing font fixed. Support Big5. */ /* 93.5.29 modified for Mule Ver.0.9.8 by Y.Niibe Include config.h in src directory */ /* 93.6.4 modified for Mule Ver.0.9.8 by K.Shibata Modified for ANSI-C. */ /* 93.12.25 modified for Mule Ver.1.0 by K.Handa In textmode(), bug of right-to-left handling fixed */ /* 94.3.8 modified for Mule Ver.1.1 by K.Handa Bug in find_encoding() fixed. */ /* See `mule/ChangeLog.Mule' for the recent change log */ #include #include #include #include #include "mulelib.h" static char *m2ps_version = "2.2"; #ifndef PSHeader #define PSHeader "m2ps.ps" #endif #ifndef DPI #define DPI 300 #endif #ifndef FontScale #define FontScale 10 #endif #ifndef LinePitch #define LinePitch 14 #endif /* Parameters for A4 paper */ #define A4_MaxLine 56 #define A4_TopMargin 800 /* Parameters for US-LETTER paper */ #define US_MaxLine 50 #define US_TopMargin 746 #ifndef USLETTER #ifndef MaxLine #define MaxLine A4_MaxLine #endif #ifndef TopMargin #define TopMargin A4_TopMargin #endif #else /* US-LETTER */ #ifndef MaxLine #define MaxLine US_MaxLine #endif #ifndef TopMargin #define TopMargin US_TopMargin #endif #endif /* US-LETTER */ #ifndef LeftMargin #define LeftMargin 30 /* To widen left margin, specify larger value. */ #endif #ifndef ShortMemory #define ShortMemory 0 #endif char *psheader = PSHeader; int dpi = DPI; int fontscale = FontScale; int linepitch = LinePitch; int maxline = MaxLine; int topmargin = TopMargin; int leftmargin = LeftMargin; int shortmemory = ShortMemory; /***************/ /* Main staffs */ /***************/ /* GLOBAL VARIABLES */ int clm, row, current_lc; set_font(lc) int lc; { /* 93.5.7, 94.11.29 by K.Handa -- Big change */ if (FONT_LOADED (lc) == 0) { if (bdf_load_font(lc)) ps_newfont(lc); else lc = 0; } else if (FONT_LOADED (lc) < 0) lc = 0; if (lc != current_lc) { ps_setfont(lc); current_lc = lc; } } renew_font(lc) int lc; { bzero(((font_extra *)font[lc & 0x7F].extra)->new, 256 * (sizeof (char))); } /* Load specified glyph, then return the index to glyph. Note the index is within the range of [0,255]. Return -1 if error. */ set_glyph1(lc, c) int lc, c; { if (!DEFINED1(lc, c)) { if (bdf_load_glyph(lc, c, &glyph)) { ps_newglyph(c, &glyph); DEFINE1(lc, c); } else return -1; } return c; } find_encoding(fontp, lc, c) font_struct *fontp; int lc, c; { font_extra *ext = (font_extra *)fontp->extra; int i, min_count = ext->count[0], j = 0; if (min_count > 0) { min_count = 0x7FFF; /* 94.3.8 by K.Handa */ for (i = 0; i < 256; i++) { if (ext->count[i] <= min_count && !ext->new[i]) { min_count = ext->count[i], j = i; if (min_count == 0) break; } } } if (min_count > 0) UNDEFINE2(lc, ext->code[j]); ext->count[j] = ext->new[j] = 1; ext->code[j] = c; DEFINE2(lc, ext->code[j]); return j; } /* Load specified glyph, replacing previously loaded glyph if necessary, then return the index to glyph. Note the index is within the range of [0,255]. Return -1 if error. */ set_glyph2(lc, c) int lc, c; { int code; font_struct *fontp = &font[lc & 0x7F]; font_extra *ext = (font_extra *)fontp->extra; if (!DEFINED2(lc, c)) { if (bdf_load_glyph(lc, c, &glyph)) { code = find_encoding(fontp, lc, c); ps_newglyph(code, &glyph); } else return -1; } else { for (code = 0; code < 256; code++) { if (ext->code[code] == c) break; } ext->new[code] = 1; ext->count[code]++; } return code; } swap_buf(buf, from, to) unsigned char *buf; int from, to; { int i, j; unsigned char buf2[1024], *p = buf2; i = j = to; while (--i >= from) { if (NONASCII_P(buf[i])) continue; bcopy(buf + i, p, j - i); p += j - i; j = i; } bcopy(buf2, buf + from, to - from); } textmode() { register int i, j, k, c, lc; char buf[1024]; /* 92.11.6 by K.Shibata */ unsigned char line[1024], *p; int cmp_flag = 0, len, r2l_chars; ps_bot(); ps_bop(); clm = row = 0; current_lc = -1; /* set_font(0); */ while ((len = get_line(line, 1024, stdin)) >= 0) { /* 93.6.4 by K.Shibata */ /* We should process line by line to handle r2l direction. */ j = 0; r2l_chars = 0; /* At first, re-order characters of r2l direction. */ while (j < len) { p = line + j; if (*p <= 0x7F) { lc = 0; p++; } else { lc = *p++; if (lc == LCCMP) lc = *p++ - 0x20; if (lc >= LCPRV11) lc = *p++; } while (NONASCII_P(*p)) p++; if (char_direction[lc]) { if (!r2l_chars) k = j; r2l_chars++; } else { if (r2l_chars > 1) swap_buf(line, k, j); r2l_chars = 0; } j = p - line; } if (r2l_chars > 1) swap_buf(line, k, j); /* 93.12.25 by K.Handa */ /* Then output characters. */ for (j = 0; j < len;) { c = line[j]; if (c == LCCMP) { /* start of composite characters */ cmp_flag = 1; j++; continue; } if (cmp_flag) { /* composed characters have special encoding */ if (c == 0xA0) c = line[++j] & 0x7F; else if (c > 0xA0) c -= 0x20; else cmp_flag = 0; } if (c < 0x20 || c == 0x7F) { /* Control code */ switch (c) { case '\t': i = 8 - (clm % 8); clm += i; set_font(0); if (set_glyph1(0, ' ') >= 0) { putchar('('); while (i--) putchar(' '); printf(") s "); } break; case '\f': ps_eop(), ps_bop(); break; default: if (c < ' ') control_char(c); else invalid_char(c); } j++; } else if (c < 0x7F) { /* ASCII */ set_font(0); i = 0; do { if ((c = set_glyph1(0, c)) >= 0) { if (c == '\\' || c == '(' || c == ')') buf[i++] = '\\', buf[i++] = c; else buf[i++] = c; clm++; } c = line[++j]; } while (!cmp_flag /* process composite character one by one */ && 0x20 <= c && c < 0x7F); buf[i] = 0; switch (cmp_flag) { case 0: /* not composite character */ printf("(%s) s ", buf); break; case 1: /* first of composite character */ printf("(%s) cs1 ", buf); cmp_flag = 2; break; default: /* case 2: rest of composite character*/ if (font[0].relative_compose) printf("(%s) cs2 ", buf); else printf("(%s) cs3 ", buf); } } else if (c < LCINV) { /* Multilingual character */ int cur_lc = c < LCPRV11 ? c : line[j + 1]; CCL_PROGRAM *ccl = x_ccl_programs[cur_lc & 0x7F]; unsigned char c1, c2; set_font(cur_lc); i = 0, lc = cur_lc; while (1) { if (lc >= LCPRV11) lc = line[j + 1]; if (lc != cur_lc) break; if (lc < LCJPOLD) c1 = 0, c2 = line[j + 1], j += 2; else if (lc < LCPRV11) c1 = line[j + 1], c2 = line[j + 2], j += 3; else if (lc < LCPRV21EXT) c1 = 0, c2 = line[j + 2], j += 3; else c1 = line[j + 2], c2 = line[j + 3], j += 4; if (!ccl) { c = c1 * 256 + c2; } else { ccl->reg[0] = c1; ccl->reg[1] = c2; ccl_driver (ccl, NULL, NULL, 0, 0); c = ccl->reg[0] * 256 + ccl->reg[1]; } if (current_lc != lc) { /* Font is not found. Use ASCII to write the code. */ c &= 0x7F; if (c >= ' ' && c <= 126) c = set_glyph1(0, c & 0x7F); else c = set_glyph1(0, ' '); } else if (char_type[lc] < TYPE94N) c = set_glyph1(lc, c); else c = set_glyph2(lc, c); if (c >= 0) { if (c == '\\' || c == '(' || c == ')') buf[i++] = '\\', buf[i++] = c; else if (c >= ' ' && c < 127) buf[i++] = c; else sprintf(buf + i, "\\%03o", c), i += 4; clm += lc < 0x90 || (lc >= LCPRV11EXT && lc < LCPRV21EXT) ? 1 : 2; } if (cmp_flag) break; lc = line[j]; } buf[i] = 0; switch (cmp_flag) { case 0: printf("(%s) s ", buf); break; case 1: printf("(%s) cs1 ", buf); cmp_flag = 2; break; case 2: default: if (font[lc & 0x7F].relative_compose) printf("(%s) cs2 ", buf); else printf("(%s) cs3 ", buf); } renew_font(cur_lc); } else { invalid_char(c); } } printf("n\n"); row++, clm = 0; if (row >= maxline) ps_eop(), ps_bop(); } ps_eop(); ps_eot(); } control_char(c) int c; { c += '@'; set_font(0); if ((set_glyph1(0, '^') >= 0) && (set_glyph1(0, c) >= 0)) { printf("(^%c) s ", c); clm += 2; } } invalid_char(c) int c; { int i; set_font(0); if (set_glyph1(0, '\\') >= 0) { for (i = '0'; i <= '9'; i++) { if (set_glyph1(0, i) < 0) break; } if (i > '9') { printf("(\\\\%03o) s ", c); clm += 4; } } } main(argc, argv) int argc; char *argv[]; { register int i = 1; char *bdf_path = NULL, *charsets = NULL; while (i < argc) { if (!strcmp(argv[i], "-ps") && (i + 1) < argc) { psheader = argv[i + 1]; i += 2; } else if (!strcmp(argv[i], "-fp") && (i + 1) < argc) { bdf_path = argv[i + 1]; i += 2; } else if (!strcmp(argv[i], "-cs") && (i + 1) < argc) { charsets = argv[i + 1]; i += 2; } else if (!strcmp(argv[i], "-dpi") && (i + 1) < argc) { dpi = atoi(argv[i + 1]); i += 2; } else if (!strcmp(argv[i], "-fs") && (i + 1) < argc) { fontscale = atoi(argv[i + 1]); i += 2; } else if (!strcmp(argv[i], "-lp") && (i + 1) < argc) { linepitch = atoi(argv[i + 1]); i += 2; } else if (!strcmp(argv[i], "-ml") && (i + 1) < argc) { maxline = atoi(argv[i + 1]); i += 2; } else if (!strcmp(argv[i], "-tm") && (i + 1) < argc) { topmargin = atoi(argv[i + 1]); i += 2; } else if (!strcmp(argv[i], "-lm") && (i + 1) < argc) { leftmargin = atoi(argv[i + 1]); i += 2; } else if (!strcmp(argv[i], "-sm")) { shortmemory = 1; i++; } else if (!strcmp(argv[i], "-bm")) { shortmemory = 0; i++; } else if (!strcmp(argv[i], "-a4") || !strcmp(argv[i], "-A4")) { maxline = A4_MaxLine; topmargin = A4_TopMargin; i++; } else if (!strcmp(argv[i], "-us") || !strcmp(argv[i], "-US")) { maxline = US_MaxLine; topmargin = US_TopMargin; i++; } else if (!strncmp(argv[i], "-ver", 4)) { printf("m2ps Ver.%s\n", m2ps_version); exit(0); } else { fprintf(stderr, "%s: Invalid argument: %s\n", argv[0], argv[i]); exit(1); } } mulelib_initialize(argc, argv, charsets, NULL); bdf_initialize(bdf_path, 0); textmode(); exit(0); } /*********************/ /* PostScript staffs */ /*********************/ ps_bot() { int c; FILE *fp; if ((fp = open_file(PATH_DATA, psheader)) == NULL) fatal1("PostScript header file not found."); while ((c = getc(fp)) != EOF) putchar(c); fclose(fp); printf("Mydict begin\n"); printf("/DPI %d def\n", dpi); printf("/FontScale %d def\n", fontscale); printf("/LinePitch %d def\n", linepitch); printf("/TopMargin %d def\n", topmargin); printf("/LeftMargin %d def\n", leftmargin); printf("/ShortMemory %s def\n", (shortmemory ? "true" : "false")); } ps_eot() { printf("end\n"); } /* Define new PS font for a leading char LC. No_cache flag is for the fonts be modified (replacing the glyphs, etc.) at execution time. */ ps_newfont(lc) int lc; { font_struct *fontp = &font[lc & 0x7F]; printf("/F%02x /FF%02x %d [%d %d %d %d] %d %s nf\n", lc, lc, ((font_extra *)fontp->extra)->fs, fontp->llx, fontp->lly - fontp->yoffset, fontp->urx, fontp->ury - fontp->yoffset, fontp->relative_compose, (fontp->bytes == 1 ? "true" : "false")); } ps_setfont(lc) int lc; { printf("F%02x f\n", lc); } ps_newglyph(encoding, glyph) int encoding; glyph_struct *glyph; { char *bitmap = glyph->bitmap; if (*bitmap == '\0') bitmap = "00"; printf("/C%d%s[ %d %d %d %d %d %d %d %d %d <%s> ] g\n", encoding, (encoding < 10 ? "XX " : encoding < 100 ? "X " : " "), glyph->dwidth, glyph->bbox, glyph->bboy, glyph->bbw + glyph->bbox, glyph->bbh + glyph->bboy, glyph->bbw, glyph->bbh, glyph->bbox, glyph->bbh + glyph->bboy, bitmap); } ps_bop() { int lc; row = clm = 0; printf("bp\n"); if (shortmemory) { current_lc = -1; for (lc = 0; lc < 256; lc++) { /* 93.5.7 by K.Handa */ if (FONT_LOADED (lc) == 1) FONT_LOADED (lc) = 0; } } } ps_eop() { printf("ep\n"); }