summaryrefslogtreecommitdiff
path: root/Build/source/texk/xdvik/dvisel.c
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2006-01-17 21:41:51 +0000
committerKarl Berry <karl@freefriends.org>2006-01-17 21:41:51 +0000
commit487ca4806cc046076293cf6cc5fbba0db282bac7 (patch)
tree847b412ab5158dd7bdd7ed7e5a4cc3fbca94be32 /Build/source/texk/xdvik/dvisel.c
parenta3d3111bfe26b8e5f5bc6049dfb2a4ca2edc7881 (diff)
texk 1
git-svn-id: svn://tug.org/texlive/trunk@1485 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/xdvik/dvisel.c')
-rw-r--r--Build/source/texk/xdvik/dvisel.c759
1 files changed, 759 insertions, 0 deletions
diff --git a/Build/source/texk/xdvik/dvisel.c b/Build/source/texk/xdvik/dvisel.c
new file mode 100644
index 00000000000..d6b6b7f6793
--- /dev/null
+++ b/Build/source/texk/xdvik/dvisel.c
@@ -0,0 +1,759 @@
+/*
+ * select pages from a DVI file.
+ *
+ * Copyright (c) 1999
+ * WATANABE Takeshi watanabe@komadori.planet.sci.kobe-u.ac.jp
+ * Copyright (c) 2002-2004 the xdvik development team
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL ANY AUTHO OF THIS SOFTWARE BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <string.h>
+#include <ctype.h>
+
+#include "dvi.h"
+#include "pagesel.h"
+#include "dvisel.h"
+#include "util.h"
+#include "dvi-init.h"
+#include "events.h"
+#include "dvi-draw.h"
+#include "message-window.h"
+#include "statusline.h"
+#include "print-dialog.h"
+
+/* stack for HTEX / Color stack */
+typedef enum { IS_A_HREF, IS_A_COLOR } stackElemT;
+
+/*
+ * Length of BOP command, without p[4] (previous BOP pointer):
+ * bop c_0[4] ... c_9[4]
+ */
+static const int BOP_PART_LEN = 1 + 10 * 4;
+/*
+ * Like above but with p[4]:
+ */
+static const int BOP_LEN = 1 + 10 * 4 + 4;
+/*
+ * Lenght of postamble:
+ * post p[4] num[4] den[4] mag[4] l[4] u[4] s[2] t[2]
+ */
+static const int POSTAMBLE_LEN = 1 + 4 * 6 + 2 + 2;
+/*
+ * Postamble without p[4] (final bop offset) and t[2] (total page number):
+ * num[4] den[4] mag[4] l[4] u[4] s[2]
+ */
+static const int POSTAMBLE_PART_LEN = 4 * 5 + 2;
+
+static char *dvips_papersize_special = NULL;
+
+/*
+ * Struct to save specials that need to be copied verbatim into the output file
+ * (things like `draftcopy'; see dvips manual, `Literal headers')
+ */
+struct literal_headers {
+ size_t size;
+ char **headers;
+};
+static struct literal_headers literal_headers = { 0, NULL };
+
+static struct specials_stack color_stack = { 0, NULL};
+static struct specials_stack href_stack = { 0, NULL};
+
+/*
+ stacks saved from the previous page (i.e. active at the
+ beginning of the page)
+ */
+static struct specials_stack color_save_stack = { 0, NULL };
+static struct specials_stack href_save_stack = { 0, NULL };
+
+static void
+push_stack(struct specials_stack *stack, const char *content)
+{
+ stack->items = xrealloc(stack->items, (stack->stack_len + 1) * sizeof *(stack->items));
+ stack->items[stack->stack_len].content = xstrdup(content);
+ stack->stack_len++;
+}
+
+static Boolean
+stack_contains_item(struct specials_stack *stack, const char *str)
+{
+ size_t i;
+ for (i = 0; i < stack->stack_len; i++) {
+ if (strcmp(str, stack->items[i].content) == 0) {
+ return True;
+ }
+ }
+ return False;
+}
+
+static void
+pop_stack(struct specials_stack *stack)
+{
+ ASSERT(stack->stack_len >= 1, "Attempt to pop empty stack");
+ free(stack->items[stack->stack_len - 1].content);
+ stack->stack_len--;
+}
+
+static void
+empty_stack(struct specials_stack *stack)
+{
+ while(stack->stack_len > 0) {
+ pop_stack(stack);
+ }
+}
+
+/*
+ This is used instead of struct tn, and struct font* from dvi-init.h,
+ since it appears that we don't need all the information from there.
+*/
+static struct fontinfo {
+ long TeXnumber;
+ unsigned char info[14];
+ char *fontname;
+ struct fontinfo *next;
+ Boolean used;
+} *fontinfo_head;
+
+#define PutFour(num, fp) { \
+ putc(((num) >> 24) & 0xff, (fp)); \
+ putc(((num) >> 16) & 0xff, (fp)); \
+ putc(((num) >> 8) & 0xff, (fp)); \
+ putc( (num) & 0xff, (fp)); \
+}
+
+#define CopyNum(fin, fout, num) { \
+ int m = num; \
+ while (--m >= 0) putc(getc(fin), fout); \
+}
+
+static void
+FontWrite(FILE *fout, struct fontinfo *fontp, long *fout_pos)
+{
+ if (fontp->TeXnumber > 0xff) {
+ if (fontp->TeXnumber > 0xffff) {
+ if (fontp->TeXnumber > 0xffffff) {
+ putc(FNTDEF4, fout);
+ putc((fontp->TeXnumber >> 24) & 0xff, fout);
+ (*fout_pos)++;
+ }
+ else {
+ putc(FNTDEF3, fout);
+ }
+ putc((fontp->TeXnumber >> 16) & 0xff, fout);
+ (*fout_pos)++;
+ }
+ else {
+ putc(FNTDEF2, fout);
+ }
+ putc((fontp->TeXnumber >> 8) & 0xff, fout);
+ (*fout_pos)++;
+ }
+ else {
+ putc(FNTDEF1, fout);
+ }
+ putc(fontp->TeXnumber & 0xff, fout);
+ fwrite(fontp->info, sizeof(char), 14, fout);
+ fwrite(fontp->fontname, sizeof(char), fontp->info[12] + fontp->info[13], fout);
+ (*fout_pos) += 2 + 14 + fontp->info[12] + fontp->info[13];
+}
+
+/*
+ Invoked by spcl_scan; saves file names referenced by special commands
+ into the `warn_files' field of `info'.
+*/
+static Boolean
+scan_for_included_files(char *special, int str_len, void *my_info)
+{
+ struct select_pages_info *info = (struct select_pages_info *)my_info;
+ UNUSED(str_len);
+ if (info->warn_files.items == NULL) /* no info needed, e.g. when printing */
+ return True;
+
+ while (*special == ' ' || *special == '\t')
+ ++special;
+
+ if (memicmp(special, "psfile=", strlen("psfile=")) == 0) {
+ char *b_ptr = special + strlen("psfile=");
+ char *e_ptr;
+
+ while (*b_ptr == '"')
+ b_ptr++;
+
+ if ((e_ptr = strchr(b_ptr, '"')) != NULL) {
+ size_t len = e_ptr - b_ptr;
+ char *tmp = xmalloc(len + 1);
+ memcpy(tmp, b_ptr, len);
+ tmp[len] = '\0';
+ if (!stack_contains_item(&(info->warn_files), tmp)) {
+ push_stack(&(info->warn_files), tmp);
+ }
+ free(tmp);
+ }
+ }
+
+ return True; /* dummy */
+}
+
+/*
+ Invoked by spcl_scan; saves hyperref and color commands
+ into the global stacks `color_stack' and `hyperref_stack'.
+ FIXME: In reality char *special is treated as const, but the declaration
+ of spcl_scan doesn't allow for this.
+*/
+static Boolean
+stack_save(char *special, int str_len, void *data)
+{
+ char *ptr;
+ size_t len;
+
+ UNUSED(data);
+ UNUSED(str_len);
+
+ while (isspace((int)*special))
+ ++special;
+
+ ptr = special;
+
+ if (memicmp(special, "color ", len = strlen("color ")) == 0) {
+ special += len;
+ while (*special == ' ' || *special == '\t')
+ ++special;
+ if (memicmp(special, "push ", 5) == 0) {
+ push_stack(&color_stack, ptr);
+ }
+ else if (memicmp(special, "pop", 3) == 0) {
+ pop_stack(&color_stack);
+ }
+ }
+ else if (memicmp(special, "html:", len = strlen("html:")) == 0) {
+ /* fprintf(stderr, "++++ special: %s; fd: %ld\n", special + 5, ftell(globals.dvi_file.bak_fp)); */
+ special += len;
+ if (memicmp(special, "<a href=", 8) == 0
+ || memicmp(special, "<a name=", 8) == 0) {
+ push_stack(&href_stack, ptr);
+ }
+ else if (memicmp(special, "</a>", 4) == 0) {
+ pop_stack(&href_stack);
+ }
+ }
+ else if (memicmp(special, "papersize", len = strlen("papersize")) == 0) {
+ free(dvips_papersize_special);
+ dvips_papersize_special = xstrdup(special);
+ }
+ else if (*special == '!'
+ || memcmp(special, "header", strlen("header")) == 0) {
+ size_t idx = literal_headers.size++;
+ if (globals.debug & DBG_GUI)
+ fprintf(stderr, "(literal) header %lu: |%s|\n", (unsigned long)idx, special);
+ literal_headers.headers = xrealloc(literal_headers.headers,
+ literal_headers.size * sizeof *(literal_headers.headers));
+ literal_headers.headers[idx] = xstrdup(special);
+ }
+ return True; /* dummy */
+}
+
+/* write a special to the FILE *fp, updating offset as appropriate. */
+static void
+write_special(const char *str, FILE *fp, long *offset)
+{
+ unsigned int len = strlen(str);
+ if (len < 256) {
+ unsigned char c = len;
+ putc(XXX1, fp);
+ putc(c, fp);
+ *offset += 2;
+ }
+ else { /* how about xxx2, xxx3? It seems that TeX doesn't use them either? */
+ putc(XXX4, fp);
+ PutFour(len, fp);
+ *offset += 5;
+ }
+ fputs(str, fp);
+ *offset += len;
+}
+
+/*
+ * Dump the headers in the global list `literal_headers',
+ * and free up resources
+ */
+static void
+dump_literal_headers(FILE *fp, long *pos)
+{
+ size_t i;
+ for (i = 0; i < literal_headers.size; i++) {
+ write_special(literal_headers.headers[i], fp, pos);
+ free(literal_headers.headers[i]);
+ }
+ free(literal_headers.headers);
+ literal_headers.headers = NULL;
+ literal_headers.size = 0;
+}
+
+
+static void
+scan_page_for_specials(FILE *fp, int page, Boolean save_stack,
+ Boolean (*special_proc)(char *str, int str_len, void *data),
+ struct select_pages_info *info)
+{
+ off_t pos_save;
+ static ubyte my_scan_buffer[DVI_BUFFER_LEN];
+
+ struct drawinf currinf_save;
+ ubyte maxchar_save;
+ size_t i;
+ TRACE_GUI((stderr, "parsing page: %d", page));
+ if (save_stack) {
+ /*
+ first, copy the current stacks (which reflect the state on the
+ preceding page) to color_save_stack and href_save_stack:
+ */
+ empty_stack(&color_save_stack);
+ empty_stack(&href_save_stack);
+ for (i = 0; i < color_stack.stack_len; i++) {
+ TRACE_GUI((stderr, "saving stack: |%s|", color_stack.items[i].content));
+ push_stack(&color_save_stack, color_stack.items[i].content);
+ }
+ for (i = 0; i < href_stack.stack_len; i++) {
+ TRACE_GUI((stderr, "saving stack: |%s|", href_stack.items[i].content));
+ push_stack(&href_save_stack, href_stack.items[i].content);
+ }
+ }
+
+ /* (void)fseek(fp, pageinfo_get_offset(page), SEEK_SET); */
+ /*
+ The datastructures in dvi-draw are rather weird in requiring
+ us to provide a buffer, and point the global currinf.pos and end
+ pointers to that buffer, for spcl_scan to be able to scan the file.
+ First save the contents of the exising currinf, pointing to the main file:
+ */
+ pos_save = save_file_status(fp, &currinf_save, &maxchar_save);
+
+ lseek(fileno(fp), pageinfo_get_offset(page), SEEK_SET);
+ memset((char *)&currinf.data, 0, sizeof currinf.data);
+ currinf.tn_table_len = TNTABLELEN;
+ currinf.tn_table = tn_table;
+ currinf.tn_head = tn_head;
+
+ /* then point currinf to our own buffer: */
+ G_dvi_buf_ptr = my_scan_buffer;
+ currinf.pos = currinf.end = G_dvi_buf_ptr;
+ lseek(fileno(fp), pageinfo_get_offset(page), SEEK_SET);
+ /*
+ finally we may invoke spcl_scan(). I hope we can do without
+ the
+ (!setjmp(some_env))
+ black magic since there shouldn't be any interruptions ...
+ */
+#if 1
+ spcl_scan(special_proc, info, False, fp);
+#else
+ /* this is an attempt at using setjmp(), but it's just too ugly ... */
+ for (;;) {
+ int page_bak;
+ if (read_events(EV_NOWAIT) & EV_GE_NEWPAGE)
+ break;
+ page_bak = page;
+ if (!setjmp(globals.ev.canit)) {
+ fprintf(stderr, "current position: %lu; seeking to: %lu\n",
+ (unsigned long)pos_save,
+ (unsigned long)pageinfo_get_offset(page));
+ (void) fprintf(stderr, "seeking to offset %ld, page %d of file %d\n",
+ pageinfo_get_offset(page),
+ page, fileno(globals.dvi_file.bak_fp));
+ fseek(fp, pageinfo_get_offset(page), SEEK_SET);
+ spcl_scan(special_proc, info, False);
+ }
+ else { /* if interrupted */
+ fprintf(stderr, "========= interrupted!\n");
+ if (page >= page_bak)
+ page = page_bak;
+ break;
+ }
+ if (page >= current_page)
+ break;
+ page++;
+ }
+#endif
+ /* now we restore those pesky globals, hoping that nobody
+ has stamped upon them in the meantime. */
+ restore_file_status(fp, currinf_save, maxchar_save, pos_save);
+
+ /* reposition file pointer */
+ (void)fseek(fp, pageinfo_get_offset(page), SEEK_SET);
+}
+
+
+/* dump the `open' commands on the current stack to the FILE *fp */
+static void
+stack_dump_open_commands(FILE *fp, long *pos)
+{
+ size_t i;
+ TRACE_GUI((stderr, "length of stacks: %lu, %lu",
+ (unsigned long)color_save_stack.stack_len,
+ (unsigned long)href_save_stack.stack_len));
+ for (i = 0; i < color_save_stack.stack_len; i++) {
+ TRACE_GUI((stderr, "dumping: |%s|", color_save_stack.items[i].content));
+ write_special(color_save_stack.items[i].content, fp, pos);
+ }
+ for (i = 0; i < href_save_stack.stack_len; i++) {
+ TRACE_GUI((stderr, "dumping: |%s|", href_save_stack.items[i].content));
+ write_special(href_save_stack.items[i].content, fp, pos);
+ }
+ if (dvips_papersize_special != NULL)
+ write_special(dvips_papersize_special, fp, pos);
+ TRACE_GUI((stderr, "end of dumping open\n"));
+}
+
+/* dump `close' commands for all the `open' commands on the
+ current stack (not the saved one, but the one active at the end of the page)
+ to the FILE *fp (closing tags for hyperref anchors,
+ `pop' commands for color specials).
+*/
+static void
+stack_dump_close_commands(FILE *fp, long *pos)
+{
+ size_t i;
+
+ for (i = color_stack.stack_len; i > 0; i--) {
+ TRACE_GUI((stderr, "===== color pop"));
+ write_special("color pop", fp, pos);
+ }
+ for (i = href_stack.stack_len; i > 0; i--) {
+ TRACE_GUI((stderr, "===== html:</a>"));
+ write_special("html:</a>", fp, pos);
+ }
+}
+
+
+static void
+WriteDVI(FILE *fin, FILE *fout, long *fout_pos, int c)
+{
+ int i, n;
+ struct fontinfo *fontp;
+
+ if (c >= FNTNUM0 && c <= FNT4) {
+ if (c >= FNT1)
+ n = get_bytes(fin, c - FNT1 + 1);
+ else
+ n = c - FNTNUM0;
+ for (fontp = fontinfo_head; fontp; fontp = fontp->next)
+ if (n == fontp->TeXnumber)
+ break;
+ if (fontp && fontp->used == False) {
+ fontp->used = True;
+ FontWrite(fout, fontp, fout_pos);
+ }
+ putc(c, fout);
+ (*fout_pos)++;
+ switch (c) {
+ case FNT4:
+ putc((n >> 24) & 0xff, fout);
+ (*fout_pos)++;
+ case FNT3:
+ putc((n >> 16) & 0xff, fout);
+ (*fout_pos)++;
+ case FNT2:
+ putc((n >> 8) & 0xff, fout);
+ (*fout_pos)++;
+ case FNT1:
+ putc(n & 0xff, fout);
+ (*fout_pos)++;
+ default:
+ break;
+ }
+ }
+ else if (c >= FNTDEF1 && c <= FNTDEF4) {
+ n = get_bytes(fin, c - FNTDEF1 + 1);
+ for (fontp = fontinfo_head; fontp; fontp = fontp->next)
+ if (n == fontp->TeXnumber)
+ break;
+ if (fontp && fontp->used == False) {
+ fontp->used = True;
+ FontWrite(fout, fontp, fout_pos);
+ }
+ (void) get_bytes(fin, 12);
+ (void) get_bytes(fin, (int)(get_byte(fin) + get_byte(fin)));
+ }
+ else {
+ putc(c, fout);
+ (*fout_pos)++;
+ n = 0;
+ if (c <= XXX4) {
+ for (i = 0; i < c - XXX1 + 1; i++) {
+ int x = get_byte(fin);
+ putc(x, fout);
+ (*fout_pos)++;
+ n = (n << 8) | x;
+ }
+ }
+ switch (c) {
+ case SETRULE:
+ case PUTRULE:
+ n += 4;
+ /* fall through */
+
+ case RIGHT4:
+ case W4:
+ case X4:
+ case DOWN4:
+ case Y4:
+ case Z4:
+ n++;
+ /* fall through */
+
+ case RIGHT3:
+ case W3:
+ case X3:
+ case DOWN3:
+ case Y3:
+ case Z3:
+ n++;
+ /* fall through */
+
+ case SET2:
+ case PUT2:
+ if (!resource.omega) {
+ dvi_fmt_error("%s:%d: WriteDVI: op-code %d only works with the \"-omega\" option",
+ __FILE__, __LINE__, c);
+ }
+ case RIGHT2:
+ case W2:
+ case X2:
+ case DOWN2:
+ case Y2:
+ case Z2:
+ n++;
+ /* fall through */
+
+ case SET1:
+ case PUT1:
+ case RIGHT1:
+ case W1:
+ case X1:
+ case DOWN1:
+ case Y1:
+ case Z1:
+#ifdef PTEX
+ case TDIR:
+#endif
+ n++;
+ /* fall through */
+
+ case XXX1:
+ case XXX2:
+ case XXX3:
+ case XXX4:
+ CopyNum(fin, fout, n);
+ (*fout_pos) += n;
+ /* fall through */
+
+ default:
+ break;
+ }
+ }
+}
+
+/* public functions */
+
+
+/* callback functions for selecting pages */
+Boolean
+check_pagerange(struct select_pages_info *info, int page)
+{
+ return (page >= info->from && page <= info->to);
+}
+
+Boolean
+check_marked(struct select_pages_info *info, int page)
+{
+ UNUSED(info);
+ return pageinfo_is_marked(page);
+}
+
+void
+select_pages(struct select_pages_info *pinfo)
+{
+ int c, n, page, pagecnt;
+ long fout_pos = 0L;
+ unsigned long curr_page_offset = 0xffffffff; /* pattern to be overwritten later */
+ unsigned long post_cmd_offset = 0xffffffff; /* pattern to be overwritten later */
+ struct fontinfo *fontp;
+ FILE *in_fp = pinfo->finfo->dvi_in.fp;
+ FILE *out_fp = pinfo->finfo->dvi_tmp.fp;
+
+ Boolean headers_dumped = False;
+ free(dvips_papersize_special); /* re-initialize */
+ dvips_papersize_special = NULL;
+
+ ASSERT(in_fp != NULL, "input file mustn't be NULL in select_pages()!");
+ ASSERT(out_fp != NULL, "output file mustn't be NULL in select_pages()!");
+
+ pinfo->errflag = NO_ERROR; /* reset errflag, in case we're recovering from a previous error */
+
+ /* get font list from postamble; in_fp already has been positioned
+ at correct position (start of postamble) in caller. */
+ (void)fseek(in_fp, ftell(in_fp), SEEK_SET); /* paranoia */
+ (void)get_bytes(in_fp, POSTAMBLE_LEN);
+ fontinfo_head = NULL;
+ for (;;) {
+ if ((c = get_byte(in_fp)) < FNTDEF1 || c > FNTDEF4) /* maybe POSTPOST */
+ break;
+ fontp = (struct fontinfo *) xmalloc(sizeof(struct fontinfo));
+ fontp->TeXnumber = get_bytes(in_fp, c - FNTDEF1 + 1);
+ fread(fontp->info, sizeof(char), 14, in_fp);
+ n = fontp->info[12] + fontp->info[13];
+ fontp->fontname = xmalloc(n);
+ fread(fontp->fontname, sizeof(char), n, in_fp);
+ fontp->next = fontinfo_head;
+ fontinfo_head = fontp;
+ fontp->used = False;
+ }
+
+ /* preamble */
+ fseek(in_fp, 0L, SEEK_SET);
+ fout_pos = pageinfo_get_offset(0);
+ CopyNum(in_fp, out_fp, fout_pos);
+
+ /* each page */
+ pagecnt = 0;
+ for (page = 0; page < total_pages; page++) {
+ scan_page_for_specials(in_fp, page, True, stack_save, NULL);
+
+ /* should the current page be selected? */
+ if (pinfo->callback == NULL || pinfo->callback(pinfo, page)) {
+ scan_page_for_specials(in_fp, page, False, scan_for_included_files, pinfo);
+
+ /* read BOP except for p[4] */
+ CopyNum(in_fp, out_fp, BOP_PART_LEN);
+ /* read p[4] (previous bop pointer */
+ (void)get_bytes(in_fp, 4);
+ /* write actual value of p[4] */
+ PutFour(curr_page_offset, out_fp);
+ /* remember offset of current page, for postamble */
+ curr_page_offset = fout_pos;
+ /* update fout_pos to current position */
+ fout_pos += BOP_LEN;
+
+ if (!headers_dumped) {
+ headers_dumped = True;
+ dump_literal_headers(out_fp, &fout_pos);
+ }
+
+ /* if (!written_pre_cmds) { */
+ stack_dump_open_commands(out_fp, &fout_pos);
+/* written_pre_cmds = True; */
+/* } */
+
+ while ((c = getc(in_fp)) != EOF) {
+ if ((c & 0x80) == 0) { /* ordinary character */
+ putc(c, out_fp);
+ fout_pos++;
+ }
+ else if (c == EOP) { /* End Of Page */
+/* fprintf(stderr, "EOP at %ld\n", ftell(fin)); */
+
+/* if (page == to) { */ /* print close stack for last page */
+ stack_dump_close_commands(out_fp, &fout_pos);
+/* } */
+
+ putc(c, out_fp);
+ fout_pos++;
+ break;
+ }
+ else {
+/* fprintf(stderr, "WRITE_DVI before: %ld, in_fp before: %ld\n", fout_pos, ftell(in_fp)); */
+ WriteDVI(in_fp, out_fp, &fout_pos, c);
+/* fprintf(stderr, "WRITE_DVI after: %ld; in_fp after: %ld\n", fout_pos, ftell(in_fp)); */
+ }
+ /* HACK alert: force synchronization - why is this neccessary?
+ Seems to have something do with the fact that two FILE *'s on the same
+ file are open. POSIX.1,
+ `Interaction of File Descriptors and Standard I/O Streams' seems to
+ say the seek()s on one of them also affect the other, but I'm not sure
+ about this.
+ */
+ fseek(in_fp, 0L, SEEK_CUR);
+ }
+ pagecnt++;
+ }
+ }
+
+ /* postamble */
+ if (!find_postamble(in_fp, &(pinfo->errflag))) {
+ return;
+ }
+
+ /* read/write POST command */
+ putc(get_byte(in_fp), out_fp);
+ /* read over last page offset */
+ get_bytes(in_fp, 4);
+ /* write last page offset */
+ PutFour(curr_page_offset, out_fp);
+ /* remember start of POST */
+ post_cmd_offset = fout_pos;
+ /* copy part of postamble */
+ CopyNum(in_fp, out_fp, POSTAMBLE_PART_LEN);
+ /* read t[2], total number of pages */
+ get_bytes(in_fp, 2);
+ /* write t[2] (two calls) */
+ putc((pagecnt >> 8) & 0xff, out_fp);
+ putc(pagecnt & 0xff, out_fp);
+ /* update fout_pos to current pos */
+ fout_pos += POSTAMBLE_LEN;
+
+ /* output font list */
+ for (;;) {
+ if ((c = get_byte(in_fp)) < FNTDEF1 || c > FNTDEF4) /* maybe POSTPOST */
+ break;
+ n = get_bytes(in_fp, c - FNTDEF1 + 1);
+ for (fontp = fontinfo_head; fontp; fontp = fontp->next)
+ if (n == fontp->TeXnumber)
+ break;
+ if (fontp && fontp->used == True)
+ FontWrite(out_fp, fontp, &fout_pos);
+ (void) get_bytes(in_fp, 12);
+ (void) get_bytes(in_fp, (int)(get_byte(in_fp) + get_byte(in_fp)));
+ }
+
+ /* free list */
+ for (fontp = fontinfo_head; fontp;) {
+ struct fontinfo *nextp;
+ free(fontp->fontname);
+ nextp = fontp->next;
+ free(fontp);
+ fontp = nextp;
+ }
+
+ /* POSTPOST */
+ putc(c, out_fp);
+ get_bytes(in_fp, 4);
+ PutFour(post_cmd_offset, out_fp);
+ CopyNum(in_fp, out_fp, 1 + 4);
+ for (fout_pos += 1 + 4 + 1 + 4;
+ fout_pos & 3;
+ fout_pos++) {
+ putc(TRAILER, out_fp);
+ }
+
+/* fclose(in_fp); */
+ fflush(out_fp);
+}
+