summaryrefslogtreecommitdiff
path: root/systems/msdos/dviware/xdvi-dos/src/dvi_init.c
diff options
context:
space:
mode:
Diffstat (limited to 'systems/msdos/dviware/xdvi-dos/src/dvi_init.c')
-rw-r--r--systems/msdos/dviware/xdvi-dos/src/dvi_init.c639
1 files changed, 639 insertions, 0 deletions
diff --git a/systems/msdos/dviware/xdvi-dos/src/dvi_init.c b/systems/msdos/dviware/xdvi-dos/src/dvi_init.c
new file mode 100644
index 0000000000..f257cd579f
--- /dev/null
+++ b/systems/msdos/dviware/xdvi-dos/src/dvi_init.c
@@ -0,0 +1,639 @@
+/*
+ * DVI previewer for X.
+ *
+ * Eric Cooper, CMU, September 1985.
+ *
+ * Code derived from dvi-imagen.c.
+ *
+ * Modification history:
+ * 1/1986 Modified for X.10 --Bob Scheifler, MIT LCS.
+ * 7/1988 Modified for X.11 --Mark Eichin, MIT
+ * 12/1988 Added 'R' option, toolkit, magnifying glass
+ * --Paul Vojta, UC Berkeley.
+ * 2/1989 Added tpic support --Jeffrey Lee, U of Toronto
+ * 4/1989 Modified for System V --Donald Richardson, Clarkson Univ.
+ * 3/1990 Added VMS support --Scott Allendorf, U of Iowa
+ * 7/1990 Added reflection mode --Michael Pak, Hebrew U of Jerusalem
+ * 1/1992 Added greyscale code --Till Brychcy, Techn. Univ. Muenchen
+ * and Lee Hetherington, MIT
+ *
+ * Compilation options:
+ * SYSV compile for System V
+ * VMS compile for VMS
+ * X10 compile for X10
+ * NOTOOL compile without toolkit (X11 only)
+ * BUTTONS compile with buttons on the side of the window (needs toolkit)
+ * MSBITFIRST store bitmaps internally with most significant bit first
+ * BMSHORT store bitmaps in shorts instead of bytes
+ * BMLONG store bitmaps in longs instead of bytes
+ * ALTFONT default for -altfont option
+ * A4 use European size paper
+ * TEXXET support reflection dvi codes (right-to-left typesetting)
+ * GREY use grey levels to shrink fonts
+ */
+
+#include "xdvi.h"
+#include "dvi.h"
+#include <sys/stat.h>
+
+#ifdef sun
+extern char *sprintf();
+#endif
+
+#ifndef X_NOT_STDC_ENV
+#include <stdlib.h>
+#else
+char *realloc();
+#endif
+#if defined(macII) && !defined(__STDC__) /* stdlib.h doesn't define these */
+char *realloc();
+#endif /* macII */
+
+#define PK_PRE 247
+#define PK_ID 89
+#define PK_MAGIC (PK_PRE << 8) + PK_ID
+#define GF_PRE 247
+#define GF_ID 131
+#define GF_MAGIC (GF_PRE << 8) + GF_ID
+#define VF_PRE 247
+#define VF_ID_BYTE 202
+#define VF_MAGIC (VF_PRE << 8) + VF_ID_BYTE
+#define PXL_MAGIC1 0
+#define PXL_MAGIC2 1001
+
+#define dvi_oops(str) longjmp(dvi_env, (int) str);
+
+static struct stat fstatbuf;
+
+static Boolean font_not_found;
+
+/*
+ * DVI preamble and postamble information.
+ */
+static char job_id[300];
+static long numerator, denominator, magnification;
+
+/*
+ * Offset in DVI file of last page, set in read_postamble().
+ */
+static long last_page_offset;
+
+
+/*
+ * free_vf_chain frees the vf_chain structure.
+ */
+
+static void
+free_vf_chain(tnp)
+ struct tn *tnp;
+{
+ while (tnp != NULL) {
+ register struct tn *tnp1 = tnp->next;
+ free((char *) tnp);
+ tnp = tnp1;
+ }
+}
+
+
+/*
+ * Release all shrunken bitmaps for all fonts.
+ */
+
+void
+reset_fonts()
+{
+ register struct font *f;
+ register struct glyph *g;
+
+ for (f = font_head; f != NULL; f = f->next)
+ if ((f->flags & FONT_LOADED) && !(f->flags & FONT_VIRTUAL))
+ for (g = f->glyph; g <= f->glyph + f->maxchar; ++g) {
+ if (g->bitmap2.bits) {
+ free(g->bitmap2.bits);
+ g->bitmap2.bits = NULL;
+ }
+#ifdef GREY
+ if (g->pixmap2) {
+ XDestroyImage(g->image2);
+ g->pixmap2 = NULL;
+ }
+#endif
+ }
+}
+
+/*
+ * realloc_font allocates the font structure to contain (newsize + 1)
+ * characters.
+ */
+
+void
+realloc_font(fontp, newsize)
+ struct font *fontp;
+ WIDEARG(ubyte, int) newsize;
+{
+ struct glyph *glyph;
+
+ glyph = fontp->glyph = (struct glyph *) realloc((char *) fontp->glyph,
+ ((unsigned int) newsize + 1) * sizeof(struct glyph));
+ if (glyph == NULL) oops("! Cannot reallocate space for glyph array.");
+ if (newsize > fontp->maxchar)
+ bzero((char *) (glyph + fontp->maxchar + 1),
+ (int) (newsize - fontp->maxchar) * sizeof(struct glyph));
+ maxchar = fontp->maxchar = newsize;
+}
+
+
+/*
+ * realloc_virtual_font does the same thing for virtual fonts.
+ */
+
+void
+realloc_virtual_font(fontp, newsize)
+ struct font *fontp;
+ WIDEARG(ubyte, int) newsize;
+{
+ struct macro *macro;
+
+ macro = fontp->macro = (struct macro *) realloc((char *) fontp->macro,
+ ((unsigned int) newsize + 1) * sizeof(struct macro));
+ if (macro == NULL) oops("! Cannot reallocate space for macro array.");
+ if (newsize > fontp->maxchar)
+ bzero((char *) (macro + fontp->maxchar + 1),
+ (int) (newsize - fontp->maxchar) * sizeof(struct macro));
+ maxchar = fontp->maxchar = newsize;
+}
+
+
+/*
+ * load_font locates the raster file and reads the index of characters,
+ * plus whatever other preprocessing is done (depending on the format).
+ */
+
+void
+load_font(fontp)
+ struct font *fontp;
+{
+ float fsize = fontp->fsize;
+ int dpi = fsize + 0.5;
+ char *font_found;
+ int size_found;
+ int magic;
+
+ fontp->flags |= FONT_LOADED;
+ fontp->file = font_open(fontp->fontname, &font_found,
+ (WIDEARG(float, double)) fsize, &size_found, fontp->magstepval,
+ &fontp->filename);
+ if (fontp->file == NULL) {
+ Fprintf(stderr, "Can't find font %s.\n", fontp->fontname);
+ font_not_found = True;
+ return;
+ }
+ --n_files_left;
+ if (font_found != NULL) {
+ Fprintf(stderr,
+ "Can't find font %s; using %s instead at %d dpi\n",
+ fontp->fontname, font_found, dpi);
+ free(fontp->fontname);
+ fontp->fontname = font_found;
+ }
+ else if (size_found > (int) (5 * 1.002 * fsize + 0.5) ||
+ size_found < (int) (5 * 0.998 * fsize + 0.5))
+ Fprintf(stderr,
+ "Can't find font %s at %d dpi; using %d dpi instead.\n",
+ fontp->fontname, dpi, (size_found + 2) / 5);
+ fontp->fsize = (float) size_found / 5;
+ fontp->timestamp = ++current_timestamp;
+ fontp->maxchar = maxchar = 255;
+ fontp->set_char_p = set_char;
+ magic = two(fontp->file);
+#ifdef USE_PK
+ if (magic == PK_MAGIC) read_PK_index(fontp);
+ else
+#endif
+#ifdef USE_GF
+ if (magic == GF_MAGIC) read_GF_index(fontp);
+ else
+#endif
+ if (magic == VF_MAGIC) read_VF_index(fontp);
+ else
+#ifdef USE_PXL
+ if (magic == PXL_MAGIC1 && two(fontp->file) == PXL_MAGIC2)
+ read_PXL_index(fontp);
+ else
+#endif
+ oops("Cannot recognize format for font file %s", fontp->filename);
+
+ if (fontp->flags & FONT_VIRTUAL) {
+ while (maxchar > 0 && fontp->macro[maxchar].pos == NULL) --maxchar;
+ if (maxchar < 255)
+ realloc_virtual_font(fontp, WIDEARG(,(int)) maxchar);
+ }
+ else {
+ while (maxchar > 0 && fontp->glyph[maxchar].addr == 0) --maxchar;
+ if (maxchar < 255)
+ realloc_font(fontp, WIDEARG(,(int)) maxchar);
+ }
+}
+
+
+/*
+ * MAGSTEPVALUE - If the given magnification is close to a \magstep
+ * or a \magstephalf, then return twice the number of \magsteps.
+ * Otherwise return NOMAGSTP.
+ */
+
+#define NOMAGSTP (-29999)
+#define NOBUILD 29999
+
+static int
+magstepvalue(mag)
+ float *mag;
+{
+ int m = 0;
+ double fmag = *mag;
+ double xmag = pixels_per_inch;
+ float margin = fmag * 0.002;
+
+ if (fmag < pixels_per_inch)
+ for (;;) {
+ if (xmag - fmag < margin && -(xmag - fmag) < margin) {
+ *mag = xmag;
+ return m;
+ }
+ if (xmag < fmag) break;
+ xmag *= 0.9128709292;
+ --m;
+ }
+ else
+ for (;;) {
+ if (xmag - fmag < margin && -(xmag - fmag) < margin) {
+ *mag = xmag;
+ return m;
+ }
+ if (xmag > fmag) break;
+ xmag *= 1.095445115;
+ ++m;
+ }
+ return NOMAGSTP;
+}
+
+
+/*
+ * reuse_font recursively sets the flags for font structures being reused.
+ */
+
+static void
+reuse_font(fontp)
+ struct font *fontp;
+{
+ struct tn *tnp;
+
+ if (fontp->flags & FONT_IN_USE) return;
+
+ fontp->flags |= FONT_IN_USE;
+ if (list_fonts)
+ Printf("(reusing) %s at %d dpi\n", fontp->fontname,
+ (int) (fontp->fsize + 0.5));
+ if (fontp->flags & FONT_VIRTUAL)
+ for (tnp = fontp->vf_chain; tnp != NULL; tnp = tnp->next)
+ reuse_font(tnp->fontp);
+}
+
+
+/*
+ * define_font reads the rest of the fntdef command and then reads in
+ * the specified pixel file, adding it to the global linked-list holding
+ * all of the fonts used in the job.
+ */
+void
+define_font(file, cmnd, vfparent, tn_headpp)
+ FILE *file;
+ WIDEARG(ubyte, unsigned int) cmnd;
+ struct font *vfparent; /* vf parent of this font, or NULL */
+ struct tn **tn_headpp; /* addr of head of list of TeXnumbers */
+{
+ register struct tn *tnp;
+ struct font *fontp;
+ float fsize;
+ double scale_dimconv;
+ int scale;
+ int design;
+ int magstepval;
+ int len;
+ char *fontname;
+ int size;
+
+ tnp = (struct tn *) xmalloc((unsigned) sizeof(struct tn),
+ "TeXnumber structure");
+ tnp->next = *tn_headpp;
+ *tn_headpp = tnp;
+ tnp->TeXnumber = num(file, (int) cmnd - FNTDEF1 + 1);
+ (void) four(file); /* checksum */
+ scale = four(file);
+ design = four(file);
+ len = one(file) + one(file);
+ fontname = xmalloc((unsigned) len + 1, "font name");
+ Fread(fontname, sizeof(char), len, file);
+ fontname[len] = '\0';
+ if(debug & DBG_PK)
+ Printf("Define font \"%s\" scale=%d design=%d\n",
+ fontname, scale, design);
+ if (vfparent == NULL) {
+ fsize = 0.001 * scale / design * magnification * pixels_per_inch;
+ scale_dimconv = dimconv;
+ }
+ else {
+ /*
+ * The scaled size is given in units of vfparent->scale * 2 ** -20
+ * SPELL units, so we convert it into SPELL units by multiplying by
+ * vfparent->dimconv.
+ * The design size is given in units of 2 ** -20 pt, so we convert
+ * into SPELL units by multiplying by
+ * (pixels_per_inch * 2**16) / (72.27 * 2**20).
+ */
+ fsize = (72.27 * (1<<4)) * vfparent->dimconv * scale / design;
+ scale_dimconv = vfparent->dimconv;
+ }
+ magstepval = magstepvalue(&fsize);
+ size = 5 * fsize + 0.5;
+ /*
+ * reuse font if possible
+ */
+ for (fontp = font_head;; fontp = fontp->next) {
+ if (fontp == NULL) { /* if font doesn't exist yet */
+ if (list_fonts)
+ Printf("%s at %d dpi\n", fontname, (int) (fsize + 0.5));
+ fontp = (struct font *) xmalloc((unsigned) sizeof(struct font),
+ "font structure");
+ fontp->dimconv = scale * scale_dimconv / (1<<20);
+ fontp->fontname = fontname;
+ fontp->fsize = fsize;
+ fontp->magstepval = magstepval;
+ fontp->flags = FONT_IN_USE;
+ if (vfparent == NULL) load_font(fontp);
+ fontp->next = font_head;
+ font_head = fontp;
+ break;
+ }
+ if (strcmp(fontname, fontp->fontname) == 0
+ && size == (int) (5 * fontp->fsize + 0.5)) {
+ /* if font already in use */
+ reuse_font(fontp);
+ free(fontname);
+ break;
+ }
+ }
+ tnp->fontp = fontp;
+}
+
+
+/*
+ * process_preamble reads the information in the preamble and stores
+ * it into global variables for later use.
+ */
+static void
+process_preamble()
+{
+ ubyte k;
+
+ if (one(dvi_file) != PRE)
+ dvi_oops("DVI file doesn't start with preamble");
+ if (one(dvi_file) != 2)
+ dvi_oops("Wrong version of DVI output for this program");
+ numerator = four(dvi_file);
+ denominator = four(dvi_file);
+ magnification = four(dvi_file);
+ dimconv = (((double) numerator * magnification)
+ / ((double) denominator * 1000.));
+ dimconv = dimconv * (((long) pixels_per_inch)<<16) / 254000;
+ specialConv = pixels_per_inch * magnification / 1000000.0;
+ k = one(dvi_file);
+ Fread(job_id, sizeof(char), (int) k, dvi_file);
+ job_id[k] = '\0';
+}
+
+/*
+ * find_postamble locates the beginning of the postamble
+ * and leaves the file ready to start reading at that location.
+ */
+#define TMPSIZ 516 /* 4 trailer bytes + 512 junk bytes allowed */
+static void
+find_postamble()
+{
+ long pos;
+ ubyte temp[TMPSIZ];
+ ubyte *p;
+ ubyte *p1;
+ ubyte byte;
+
+ Fseek(dvi_file, (long) 0, 2);
+ pos = ftell(dvi_file) - TMPSIZ;
+ if (pos < 0) pos = 0;
+ Fseek(dvi_file, pos, 0);
+ p = temp + fread((char *) temp, sizeof(char), TMPSIZ, dvi_file);
+ for (;;) {
+ p1 = p;
+ while (p1 > temp && *(--p1) != TRAILER) ;
+ p = p1;
+ while (p > temp && *(--p) == TRAILER) ;
+ if (p <= p1 - 4) break; /* found 4 TRAILER bytes */
+ if (p <= temp) dvi_oops("DVI file corrupted");
+ }
+ pos += p - temp;
+ byte = *p;
+ while (byte == TRAILER) {
+ Fseek(dvi_file, --pos, 0);
+ byte = one(dvi_file);
+ }
+ if (byte != 2)
+ dvi_oops("Wrong version of DVI output for this program");
+ Fseek(dvi_file, pos - 4, 0);
+ Fseek(dvi_file, sfour(dvi_file), 0);
+}
+
+
+/*
+ * read_postamble reads the information in the postamble,
+ * storing it into global variables.
+ * It also takes care of reading in all of the pixel files for the fonts
+ * used in the job.
+ */
+static void
+read_postamble()
+{
+ ubyte cmnd;
+ struct font *fontp;
+ struct font **fontpp;
+
+ if (one(dvi_file) != POST)
+ dvi_oops("Postamble doesn't begin with POST");
+ last_page_offset = four(dvi_file);
+ if (numerator != four(dvi_file)
+ || denominator != four(dvi_file)
+ || magnification != four(dvi_file))
+ dvi_oops("Postamble doesn't match preamble");
+ /* read largest box height and width */
+ unshrunk_page_h = (spell_conv(sfour(dvi_file)) >> 16) + offset_y;
+ if (unshrunk_page_h < unshrunk_paper_h)
+ unshrunk_page_h = unshrunk_paper_h;
+ unshrunk_page_w = (spell_conv(sfour(dvi_file)) >> 16) + offset_x;
+ if (unshrunk_page_w < unshrunk_paper_w)
+ unshrunk_page_w = unshrunk_paper_w;
+ (void) two(dvi_file); /* max stack size */
+ total_pages = two(dvi_file);
+ font_not_found = False;
+ while ((cmnd = one(dvi_file)) >= FNTDEF1 && cmnd <= FNTDEF4)
+ define_font(dvi_file, cmnd, (struct font *) NULL, &tn_head);
+ if (cmnd != POSTPOST)
+ dvi_oops("Non-fntdef command found in postamble");
+ if (font_not_found)
+ dvi_oops("Not all pixel files were found");
+ /*
+ * free up fonts no longer in use
+ */
+ fontpp = &font_head;
+ while ((fontp = *fontpp) != NULL)
+ if (fontp->flags & FONT_IN_USE)
+ fontpp = &fontp->next;
+ else {
+ if (debug & DBG_PK)
+ Printf("Discarding font \"%s\" at %d dpi\n",
+ fontp->fontname, (int) (fontp->fsize + 0.5));
+ *fontpp = fontp->next; /* remove from list */
+ free(fontp->fontname);
+ if (fontp->flags & FONT_LOADED) {
+ if (fontp->file != NULL) {
+ Fclose(fontp->file);
+ ++n_files_left;
+ }
+ free(fontp->filename);
+ if (fontp->flags & FONT_VIRTUAL) {
+ register struct macro *m;
+
+ for (m = fontp->macro;
+ m <= fontp->macro + fontp->maxchar; ++m)
+ if (m->free_me) free((char *) m->pos);
+ free((char *) fontp->macro);
+ free_vf_chain(fontp->vf_chain);
+ }
+ else {
+ register struct glyph *g;
+
+ for (g = fontp->glyph;
+ g <= fontp->glyph + fontp->maxchar; ++g) {
+ if (g->bitmap.bits != NULL) free(g->bitmap.bits);
+ if (g->bitmap2.bits != NULL) free(g->bitmap2.bits);
+#ifdef GREY
+ if (g->pixmap2 != NULL) XDestroyImage(g->image2);
+#endif
+ }
+ free((char *) fontp->glyph);
+ }
+ free((char *) fontp);
+ }
+ }
+}
+
+static void
+prepare_pages()
+{
+ int i;
+
+ page_offset = (long *) xmalloc((unsigned) total_pages * sizeof(long),
+ "page directory");
+ i = total_pages;
+ page_offset[--i] = last_page_offset;
+ Fseek(dvi_file, last_page_offset, 0);
+ /*
+ * Follow back pointers through pages in the DVI file,
+ * storing the offsets in the page_offset table.
+ */
+ while (i > 0) {
+ Fseek(dvi_file, (long) (1+4+(9*4)), 1);
+ Fseek(dvi_file, page_offset[--i] = four(dvi_file), 0);
+ }
+}
+
+void
+init_page()
+{
+ page_w = ROUNDUP(unshrunk_page_w, mane.shrinkfactor) + 2;
+ page_h = ROUNDUP(unshrunk_page_h, mane.shrinkfactor) + 2;
+}
+
+/*
+ * init_dvi_file is the main subroutine for reading the startup information
+ * from the dvi file.
+ */
+
+static void
+init_dvi_file()
+{
+ (void) fstat(fileno(dvi_file), &fstatbuf);
+ dvi_time = fstatbuf.st_mtime;
+ process_preamble();
+ find_postamble();
+ read_postamble();
+ prepare_pages();
+ init_page();
+ if (current_page >= total_pages) current_page = total_pages - 1;
+ hush_spec_now = hush_spec;
+}
+
+/**
+ ** open_dvi_file opens the dvi file and calls init_dvi_file() to
+ ** initialize it.
+ **/
+
+void
+open_dvi_file()
+{
+ char *errmsg;
+
+ if ((dvi_file = fopen(dvi_name, OPEN_MODE)) == NULL) {
+ int n = strlen(dvi_name);
+ char *file = dvi_name;
+
+ if (strcmp(dvi_name + n - sizeof(".dvi") + 1, ".dvi") == 0) {
+ perror(dvi_name);
+ exit(1);
+ }
+ dvi_name = xmalloc((unsigned) n + sizeof(".dvi"), "dvi file name");
+ Sprintf(dvi_name, "%s.dvi", file);
+ if ((dvi_file = fopen(dvi_name, OPEN_MODE)) == NULL) {
+ perror(dvi_name);
+ exit(1);
+ }
+ }
+
+ if (errmsg = (char *) setjmp(dvi_env)) oops(errmsg);
+ init_dvi_file();
+}
+
+/**
+ ** Check for changes in dvi file.
+ **/
+
+Boolean
+check_dvi_file()
+{
+ struct font *fontp;
+
+ if (dvi_file == NULL || fstat(fileno(dvi_file), &fstatbuf) != 0
+ || fstatbuf.st_mtime != dvi_time) {
+ if (dvi_file) Fclose(dvi_file);
+ free((char *) page_offset);
+ dvi_file = fopen(dvi_name, OPEN_MODE);
+ if (dvi_file == NULL)
+ dvi_oops("Cannot reopen dvi file.");
+ if (list_fonts) Putchar('\n');
+ free_vf_chain(tn_head);
+ tn_head = NULL;
+ for (fontp = font_head; fontp != NULL; fontp = fontp->next)
+ fontp->flags &= ~FONT_IN_USE;
+ init_dvi_file();
+ redraw_page();
+ return False;
+ }
+ return True;
+}