#include "dvitops.h" static char rcsid[] = "$Header: /usr/jjc/dvitops/RCS/code.c,v 1.5 90/08/14 13:07:42 jjc Rel $"; static struct { char *name; int width; int height; } paper_table[] = { "letter", 612, 792, "lettersmall", 612, 792, "a4", 595, 842, "A4", 595, 842, "a4small", 595, 842, "legal", 612, 1008, "b5", 516, 729, "b4", 729, 1032, "tabloid", 792, 1224, "ledger", 1224, 792, "statement", 396, 612, "executive", 540, 720, "a3", 842, 1190, "a5", 420, 595, "folio", 612, 936, "quarto", 610, 780, "10x17", 720, 1224, NULL }; #define MAXCOLS 70 static FILE *psfp; static int cols = 0; /* the number of characters on the current line */ #define NS 200 typedef struct string { size_t i; /* index into pool */ int n; /* number of characters */ int region; integer h; integer v; struct string *next; } STRING; struct rule { int region; integer a,b,h,v; struct rule *next; } *rule_list = NULL; static unsigned char *pool = NULL; static size_t pool_size = 0, pool_used = 0; STRING *string_list[MAXFONTS]; /* one list of strings for each font */ STRING *free_string_list; #ifdef PROTO void ps_string(unsigned char *s, int n); void print_string_list(STRING *s); static void print_rule_list(void); #else void ps_string(); void print_string_list(); static void print_rule_list(); #endif static int page_number = 0; int landscape = FALSE; int magnification = 0; void print_string_list(s) STRING *s; { int cc; integer v; integer ox = 0, oy = 0; /* current origin */ int r = NO_REGION; /* the current region */ if (s == NULL) return; v = s->v + 1; /* use the 'Z' command not the 'X' command */ while (s != NULL) { if (s->region != r) { fprintf(psfp, "%% region %d\n", s->region); if (r != NO_REGION) fputs("grestore\n", psfp); if (s->region != NO_REGION) { fputs("gsave\n", psfp); do_transform(s->region, &ox, &oy, psfp); } else ox = oy = 0; r = s->region; v = s->v + 1; /* use the 'Z' command not the 'X' command */ } if (s->v == v) { cols = put_dim((long)(s->h - ox), psfp); cc = 'X'; } else { cols = put_dim((long)(s->h - ox), psfp); putc(' ', psfp); cols++; cols += put_dim((long)(s->v - oy), psfp); cc = 'Z'; } v = s->v; ps_string(pool + s->i, s->n); putc(cc, psfp); putc('\n', psfp); s = s->next; } if (r != NO_REGION) fputs("grestore\n", psfp); } void set_string(p, n, f, h, v) char *p; int n, f; integer h, v; { STRING *s; if (!free_string_list) { int i; free_string_list = (STRING *)malloc(sizeof(STRING)*NS); if (free_string_list == NULL) out_of_memory(); for (i = 0; i < NS - 1; ++i) free_string_list[i].next = free_string_list + i + 1; free_string_list[NS - 1].next = NULL; } s = free_string_list; free_string_list = free_string_list->next; if (pool == NULL || pool_size - pool_used < n) { if (pool == NULL) { pool_size = 5000; pool = (unsigned char *)malloc(pool_size); pool_used = 0; } else { if (pool_used > SIZE_MAX - n) message(FATAL_ERROR, "too many characters on the page"); pool_size = pool_used + n; if (pool_size > SIZE_MAX/2) pool_size = SIZE_MAX; else pool_size <<= 1; pool = (unsigned char *)realloc((char *)pool, pool_size); } if (pool == NULL) out_of_memory(); } s->i = pool_used; memcpy((char *)(pool + pool_used), p, n); pool_used += n; s->h = h; s->v = v; s->n = n; s->next = string_list[f]; s->region = current_region; string_list[f] = s; } void set_rule(a, b, h, v) integer a, b, h, v; { struct rule *p; if (a <= 0 || b <= 0) return; p = (struct rule *)malloc(sizeof(struct rule)); if (p == NULL) out_of_memory(); p->a = a; p->b = b; p->h = h; p->v = v; p->region = current_region; p->next = rule_list; rule_list = p; } static void print_rule_list() { int r = NO_REGION; integer ox = 0, oy = 0; struct rule *p = rule_list; while (p != NULL) { struct rule *q = p; if (p->region != r) { fprintf(psfp, "%% region %d\n", p->region); if (r != NO_REGION) fputs("grestore\n", psfp); if (p->region != NO_REGION) { fputs("gsave\n", psfp); do_transform(p->region, &ox, &oy, psfp); } else ox = oy = 0; r = p->region; } put_dim((long)(p->a), psfp); putc(' ', psfp); put_dim((long)(p->b), psfp); putc(' ', psfp); put_dim((long)(p->h - ox), psfp); putc(' ', psfp); put_dim((long)(p->v - oy), psfp); fputs(" R\n", psfp); p = p->next; free((char *)q); } rule_list = NULL; if (r != NO_REGION) fputs("grestore\n", psfp); } void eop(page) struct page_info *page; { char page_label[100]; int i, j; char *ptr; int page_height, page_width; for (i = 0; paper_table[i].name != NULL; i++) if (strcmp(paper_table[i].name, page->paper) == 0) break; if (paper_table[i].name == NULL) { page_height = paper_table[0].height; page_width = paper_table[0].width; message(ERROR, "unrecognised page type %s", optarg); } else { page_height = paper_table[i].height; page_width = paper_table[i].width; } ptr = page_label; for (i = 9; page->count[i] == 0 && i > 0; --i) ; for (j = 0; j < i; ++j) { sprintf(ptr, "%ld.", (long)(page->count[j])); ptr += strlen(ptr); } sprintf(ptr, "%ld", (long)page->count[i]); if (!quiet) fprintf(stderr, "[%s", page_label); ++page_number; fprintf(psfp, "\n%%%%Page: %s %d\n", page_label, page_number); fputs("dvitops begin\n", psfp); fprintf(psfp, "/#copies %d def BP\n", page->copies); p_form_list(psfp); if (landscape) { int n; fprintf(psfp, "%d landscape\n", page_width); n = page_height; page_height = page_width; page_width = n; landscape = FALSE; } if (magnification > 0) { page->mag = magnification; magnification = 0; } fprintf(psfp, "%ld ", (long)(page->num)); put_dim((long)(page->den), psfp); fprintf(psfp, " %d %g %g %d SC\n", page->mag, page->hoffset, page->voffset, page_height); p_inline_list(psfp); p_import_list(psfp, page); #ifdef TPIC_SUPPORT p_tpic_list(psfp, page); #endif print_rule_list(); for (j = 0; j < MAXFONTS; ++j) { int emitted = FALSE; for (i = j; i != EOF; i = same_font(i)) { STRING *p = NULL; STRING *q = string_list[i]; STRING *last = q; if (string_list[i] == NULL) continue; /* reverse the string list */ while (q != NULL) { STRING *temp = q; q = q->next; temp->next = p; p = temp; } if (!f_is_blank(i)) { if (!emitted) { fputs("BO\n", psfp); f_emit(i, psfp); emitted = TRUE; } f_set(i, psfp); print_string_list(p); } last->next = free_string_list; free_string_list = p; string_list[i] = NULL; } if (emitted) fputs("EO\n", psfp); } pool_used = 0; fputs("\nEP end", psfp); if (ferror(psfp)) message(FATAL_ERROR, "write error: disk full?"); if (!quiet) fputs("] ", stderr); pool_used = 0; current_region = NO_REGION; nregions = 0; } void trailer() { fputs("\n%%Trailer\n", psfp); if (!quiet) fputc('\n', stderr); } void prologue(fp, npages, is_reverse, paper) FILE *fp; int npages, is_reverse; char *paper; { time_t t; psfp = fp; (void)time(&t); fputs("%!PS-Adobe-2.0\n", psfp); fputs("%%Creator: dvitops\n", psfp); f_comment(psfp); fprintf(psfp, "%%%%CreationDate: %s", ctime(&t)); fprintf(psfp, "%%%%DocumentPaperSizes: %s\n", paper); fprintf(psfp, "%%%%Pages: %d %d\n", npages, (is_reverse ? -1 : 1)); fputs("%%EndComments\n", psfp); p_special_prologues(psfp); if (include_file("dvitops.pro", psfp) == EOF) message(FATAL_ERROR, "can't open dvitops.pro"); fputs("dvitops begin\n", psfp); f_prologue(psfp); fputs("end\n", psfp); fputs("%%EndProlog\n", psfp); fprintf(psfp, "%%%%BeginSetup\n"); fprintf(psfp, "%%%%PaperSize: %s\n", paper); fprintf(psfp, "%%%%EndSetup\n"); } /* we asssume all seven-bit printable ascii characters are representable in the host character set */ #define ASCII_LEFT_PARENTHESIS 050 #define ASCII_RIGHT_PARENTHESIS 051 #define ASCII_BACKSLASH 0134 void ps_string(s, n) unsigned char *s; int n; { cols++; putc('(', psfp); while (n--) { unsigned char c = *s++; if (c == ASCII_LEFT_PARENTHESIS || c == ASCII_RIGHT_PARENTHESIS || c == ASCII_BACKSLASH) { if (cols + 2 > MAXCOLS) cols = 0, fputs("\\\n", psfp); fputc('\\', psfp); fputc(XCHAR(c), psfp); cols += 2; } else if (c >= 040 && c < 0177) { if (cols + 1 > MAXCOLS) cols = 0, fputs("\\\n", psfp); putc(XCHAR(c), psfp); cols++; } else { if (cols + 4 > MAXCOLS) cols = 0, fputs("\\\n", psfp); fprintf(psfp, "\\%03o", c); cols += 4; } } putc(')', psfp); } static int fixed_point = 4; #define LONG_DIGITS 10 int put_dim(n, fp) long n; FILE *fp; { int len; /* room for a -, LONG_DIGITS digits, a decimal point, and a terminating '\0' */ char buf[LONG_DIGITS + 3]; char *p = buf + LONG_DIGITS + 2; int point = 0; buf[LONG_DIGITS + 2] = '\0'; if (n >= 0) { do { *--p = '0' + (n % 10); n /= 10; if (++point == fixed_point) *--p = '.'; } while (n != 0 || point < fixed_point); } else { /* n < 0 */ do { *--p = '0' - (n % 10); n /= 10; if (++point == fixed_point) *--p = '.'; } while (n != 0 || point < fixed_point); *--p = '-'; } if (fixed_point > 0) { char *q; /* there must be a dot, so this will terminate */ for (q = buf + LONG_DIGITS + 2; q[-1] == '0'; --q) ; if (q[-1] == '.') { if (q - 1 == p) { q[-1] = '0'; q[0] = '\0'; } else q[-1] = '\0'; } else *q = '\0'; } len = strlen(p); fputs(p, fp); return len; } /* Local Variables: tab-width: 4 c-indent-level: 4 c-continued-statement-offset: 4 c-brace-offset: -4 c-argdecl-indent: 0 c-label-offset: -4 End: */