wdvi

network DVI viewer
Log | Files | Refs

dvi-init.c (20200B)


      1 /*========================================================================*\
      2 
      3 Copyright (c) 1990-2013  Paul Vojta
      4 
      5 Permission is hereby granted, free of charge, to any person obtaining a copy
      6 of this software and associated documentation files (the "Software"), to
      7 deal in the Software without restriction, including without limitation the
      8 rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
      9 sell copies of the Software, and to permit persons to whom the Software is
     10 furnished to do so, subject to the following conditions:
     11 
     12 The above copyright notice and this permission notice shall be included in
     13 all copies or substantial portions of the Software.
     14 
     15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     16 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     17 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     18 IN NO EVENT SHALL PAUL VOJTA OR ANY OTHER AUTHOR OF OR CONTRIBUTOR TO
     19 THIS SOFTWARE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
     20 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
     22 IN THE SOFTWARE.
     23 
     24 NOTE:
     25 	xdvi is based on prior work, as noted in the modification history
     26 	in xdvi.c.
     27 
     28 \*========================================================================*/
     29 
     30 #include <err.h>
     31 
     32 #include <X11/Shell.h>	/* defines XtNtitle and XtNiconName */
     33 
     34 #include "dvi-init.h"
     35 #include "dvi-draw.h"	/* spell_conv() */
     36 #include "events.h"	/* mane */
     37 #include "font.h"	/* struct font, struct glyph */
     38 #include "special.h"	/* init_prescan() */
     39 #include "xdvi.h"
     40 #include "dvi.h"
     41 #include "util.h"	/* xmalloc() */
     42 
     43 
     44 #define	PK_PRE		247
     45 #define	PK_ID		89
     46 #define	PK_MAGIC	((PK_PRE << 8) | PK_ID)
     47 #define	GF_PRE		247
     48 #define	GF_ID		131
     49 #define	GF_MAGIC	((GF_PRE << 8) | GF_ID)
     50 #define	VF_PRE		247
     51 #define	VF_ID_BYTE	202
     52 #define	VF_MAGIC	((VF_PRE << 8) | VF_ID_BYTE)
     53 
     54 
     55 /*
     56  * DVI preamble and postamble information.
     57  */
     58 static	unsigned int	dvi_unshrunk_page_w, dvi_unshrunk_page_h;
     59 
     60 /*
     61  *	free_vf_chain frees the vf_chain structure.
     62  */
     63 
     64 static	void
     65 free_vf_chain(struct tn *tnp)
     66 {
     67 	while (tnp != NULL) {
     68 	    struct tn *tnp1 = tnp->next;
     69 	    free((char *) tnp);
     70 	    tnp = tnp1;
     71 	}
     72 }
     73 
     74 
     75 /*
     76  *	Release all shrunken bitmaps for all fonts.
     77  */
     78 
     79 void
     80 reset_fonts(void)
     81 {
     82 	struct font *f;
     83 	struct glyph *g;
     84 
     85 	for (f = font_head; f != NULL; f = f->next) {
     86 		if (!(f->flags & FONT_LOADED) || (f->flags & FONT_VIRTUAL))
     87 			continue;
     88 
     89 		for (g = f->glyph; g <= f->glyph + f->maxchar; ++g) {
     90 			if (g->bitmap2.bits) {
     91 				free(g->bitmap2.bits);
     92 				g->bitmap2.bits = NULL;
     93 		    	}
     94 			if (g->pixmap2) {
     95 				XDestroyImage(g->image2);
     96 				g->pixmap2 = NULL;
     97 				if (g->pixmap2_t != NULL) {
     98 					free(g->pixmap2_t);
     99 					g->pixmap2_t = NULL;
    100 				}
    101 			}
    102 			g->fg = NULL;
    103 		}
    104 	}
    105 }
    106 
    107 
    108 
    109 /*
    110  *	Release all allocated pixels, and (in greyscale mode) invalidate
    111  *	all shrunken glyphs.
    112  */
    113 
    114 void
    115 reset_colors(void)
    116 {
    117 	struct font *f;
    118 	struct glyph *g;
    119 
    120 	while (bg_head != NULL) {
    121 	    struct bgrec	*bgp;
    122 	    struct fgrec	*fgp;
    123 
    124 	    for (fgp = bg_head->fg_head; fgp != NULL;) {
    125 		struct fgrec *fgp1 = fgp->next;
    126 		free(fgp);
    127 		fgp = fgp1;
    128 	    }
    129 	    bgp = bg_head->next;
    130 	    free(bg_head);
    131 	    bg_head = bgp;
    132 	}
    133 
    134 	/* use_grey */
    135 	for (f = font_head; f != NULL; f = f->next) {
    136 		if (!(f->flags & FONT_LOADED) || (f->flags & FONT_VIRTUAL))
    137 			continue;
    138 
    139 		for (g = f->glyph; g <= f->glyph + f->maxchar; ++g)
    140 			g->fg = NULL;
    141 	}
    142 
    143 	bg_current = NULL;
    144 	fg_active = NULL;
    145 }
    146 
    147 /*
    148  *	All of the above, plus discard all scanned information.
    149  */
    150 
    151 void
    152 full_reset_colors(void)
    153 {
    154 	if (page_colors != NULL) {
    155 	    int			i;
    156 	    const struct rgb	*last_freed = &fg_initial;
    157 
    158 	    for (i = 0; i < total_pages; ++i) {
    159 		if (page_colors[i].colorstack != last_freed) {
    160 		    last_freed = page_colors[i].colorstack;
    161 		    if (last_freed != NULL)
    162 			free((char *) last_freed);
    163 		}
    164 	    }
    165 	    free((char *) page_colors);
    166 	    page_colors = NULL;
    167 	}
    168 	reset_colors();
    169 }
    170 
    171 
    172 
    173 /*
    174  *	realloc_font allocates the font structure to contain (newsize + 1)
    175  *	characters.
    176  */
    177 
    178 void
    179 realloc_font(struct font *fontp, unsigned char newsize)
    180 {
    181 	struct glyph *glyph;
    182 
    183 	glyph = fontp->glyph = xrealloc(fontp->glyph,
    184 	    (unsigned int) (newsize + 1) * sizeof(struct glyph));
    185 	if (newsize > fontp->maxchar)
    186 	    bzero((char *) (glyph + fontp->maxchar + 1),
    187 		(int) (newsize - fontp->maxchar) * sizeof(struct glyph));
    188 	maxchar = fontp->maxchar = newsize;
    189 }
    190 
    191 
    192 /*
    193  *	realloc_virtual_font does the same thing for virtual fonts.
    194  */
    195 
    196 void
    197 realloc_virtual_font(struct font *fontp, unsigned char newsize)
    198 {
    199 	struct macro *macro;
    200 
    201 	macro = fontp->macro = xrealloc(fontp->macro,
    202 	    (unsigned int) (newsize + 1) * sizeof(struct macro));
    203 	if (newsize > fontp->maxchar)
    204 	    bzero((char *) (macro + fontp->maxchar + 1),
    205 		(int) (newsize - fontp->maxchar) * sizeof(struct macro));
    206 	maxchar = fontp->maxchar = newsize;
    207 }
    208 
    209 
    210 /*
    211  *	load_font locates the raster file and reads the index of characters,
    212  *	plus whatever other preprocessing is done (depending on the format).
    213  *	Returns True if successful; False if not.
    214  */
    215 
    216 Boolean
    217 load_font(struct font *fontp)
    218 {
    219 	double	fsize	= fontp->fsize;
    220 	int	dpi	= fsize + 0.5;
    221 	char	*font_found;
    222 	int	size_found;
    223 	int	magic;
    224 	Boolean	hushcs	= False;
    225 
    226 	if (!font_open(fontp, &font_found, &size_found)) {
    227 	    if (ev_flags & EV_GE_NEWDOC)
    228 		return False;
    229 	    fontp->flags |= FONT_LOADED;	/* as loaded as it'll get */
    230 	    warnx("can't find font '%s'.", fontp->fontname);
    231 	    return False;
    232 	}
    233 	fontp->flags |= FONT_LOADED;
    234 	if (font_found != NULL) {
    235 	    warnx("can't find font '%s'; using '%s' instead at %d dpi.",
    236 		    fontp->fontname, font_found, dpi);
    237 	    free(fontp->fontname);
    238 	    fontp->fontname = font_found;
    239 	    hushcs = True;
    240 	}
    241 	else if (size_found > (int) (1.002 * fsize + 0.5) ||
    242 		size_found < (int) (0.998 * fsize + 0.5))
    243 	    warnx("can't find font %s at %d dpi; using %d dpi instead.",
    244 		fontp->fontname, dpi, size_found);
    245 	fontp->timestamp = ++current_timestamp;
    246 	fontp->maxchar = maxchar = 255;
    247 	fontp->set_char_p = set_char;
    248 	if (fontp->ft != NULL) {	/* if freetype font */
    249 	    fontp->set_char_p = set_ft_char;
    250 	    fontp->glyph = xmalloc(256 * sizeof(struct glyph));
    251 	    bzero((char *) fontp->glyph, 256 * sizeof(struct glyph));
    252 	    return True;
    253 	}
    254 	fontp->fsize = size_found;
    255 	magic = two(fontp->file);
    256 	if (magic == PK_MAGIC) read_PK_index(fontp, hushcs);
    257 	else
    258 	    if (magic == VF_MAGIC) read_VF_index(fontp, hushcs);
    259 	else
    260 	    errx(1, "Cannot recognize format for font file '%s'",
    261 		fontp->filename);
    262 
    263 	if (fontp->flags & FONT_VIRTUAL) {
    264 	    while (maxchar > 0 && fontp->macro[maxchar].pos == NULL) --maxchar;
    265 	    if (maxchar < 255)
    266 		realloc_virtual_font(fontp, maxchar);
    267 	}
    268 	else {
    269 	    while (maxchar > 0 && fontp->glyph[maxchar].addr == 0) --maxchar;
    270 	    if (maxchar < 255)
    271 		realloc_font(fontp, maxchar);
    272 	}
    273 	return True;
    274 }
    275 
    276 
    277 /*
    278  *	MAGSTEPVALUE - If the given magnification is close to a \magstep
    279  *	or a \magstephalf, then return twice the number of \magsteps.
    280  *	Otherwise return NOMAGSTP.
    281  */
    282 
    283 #define	NOMAGSTP (-29999)
    284 #define	NOBUILD	29999
    285 
    286 static	int
    287 magstepvalue(float *mag)
    288 {
    289 	int	m	= 0;
    290 	double	fmag	= *mag;
    291 	double	xmag	= pixels_per_inch;
    292 	float	margin	= fmag * 0.002;
    293 
    294 	if (fmag < pixels_per_inch)
    295 	    for (;;) {
    296 		if (xmag - fmag < margin && -(xmag - fmag) < margin) {
    297 		    *mag = xmag;
    298 		    return m;
    299 		}
    300 		if (xmag < fmag) break;
    301 		xmag *= 0.9128709292;
    302 		--m;
    303 	    }
    304 	else
    305 	    for (;;) {
    306 		if (xmag - fmag < margin && -(xmag - fmag) < margin) {
    307 		    *mag = xmag;
    308 		    return m;
    309 		}
    310 		if (xmag > fmag) break;
    311 		xmag *= 1.095445115;
    312 		++m;
    313 	    }
    314 	return NOMAGSTP;
    315 }
    316 
    317 
    318 /*
    319  *	reuse_font recursively sets the flags for font structures being reused.
    320  */
    321 
    322 static	void
    323 reuse_font(struct font *fontp)
    324 {
    325 	struct font **fp;
    326 	struct tn *tnp;
    327 
    328 	if (fontp->flags & FONT_IN_USE) return;
    329 
    330 	fontp->flags |= FONT_IN_USE;
    331 	if (resource._list_fonts)
    332 	    printf("(reusing) %s at %d dpi\n", fontp->fontname,
    333 		(int) (fontp->fsize + 0.5));
    334 	if (fontp->flags & FONT_VIRTUAL) {
    335 	    for (fp = fontp->vf_table; fp < fontp->vf_table + VFTABLELEN; ++fp)
    336 		if (*fp != NULL) reuse_font(*fp);
    337 	    for (tnp = fontp->vf_chain; tnp != NULL; tnp = tnp->next)
    338 		reuse_font(tnp->fontp);
    339 	}
    340 }
    341 
    342 
    343 /*
    344  *      define_font reads the rest of the fntdef command and then reads in
    345  *      the specified pixel file, adding it to the global linked-list holding
    346  *      all of the fonts used in the job.
    347  *
    348  *	vfparent;		vf parent of this font, or NULL
    349  *	tntable;		table for low TeXnumbers
    350  *	tn_table_len;		length of table for TeXnumbers
    351  *	tn_headpp;		addr of head of list of TeXnumbers
    352  *	m;			magnification
    353  *
    354  *	returns NULL when a font cannot be loaded, non NULL otherwise.
    355  */
    356 struct font *
    357 define_font(FILE *file, unsigned char cmnd, struct font *vfparent,
    358 	struct font **tntable, unsigned int tn_table_len,
    359 	struct tn **tn_headpp, long m)
    360 {
    361 	long	k, c, s, d;
    362 	size_t	a, l;
    363 	struct font *fontp;
    364 	float	fsize;
    365 	double	scale_dimconv;
    366 	int	magstepval;
    367 	char	*n;
    368 	int	size;
    369 
    370 	k = num(file, (int) cmnd - FNTDEF1 + 1);
    371 	c = four(file);		/* checksum */
    372 	s = four(file);		/* scale */
    373 	d = four(file);		/* design */
    374 	a = one(file);		/* area (directory) length */
    375 	l = one(file);		/* font name length */
    376 	n = xmalloc(a + l + 1);
    377 	fread(n, sizeof(*n), a + l, file);
    378 	n[a + l] = '\0';	/* font name */
    379 
    380 	if (debug & DBG_PK)
    381 		printf("Define font '%s' scale=%ld design=%ld\n", n, s, d);
    382 
    383 	if (vfparent == NULL) {
    384 		fsize = 0.001 * s / d * m * pixels_per_inch;
    385 		scale_dimconv = dimconv;
    386 	}
    387 	else {
    388 	    /*
    389 	     *	The scaled size is given in units of vfparent->scale * 2 ** -20
    390 	     *	SPELL units, so we convert it into SPELL units by multiplying by
    391 	     *		vfparent->dimconv.
    392 	     *	The design size is given in units of 2 ** -20 pt, so we convert
    393 	     *	into SPELL units by multiplying by
    394 	     *		(pixels_per_inch * 2**16) / (72.27 * 2**20).
    395 	     */
    396 	    fsize = (72.27 * (1<<4)) * vfparent->dimconv * s / d;
    397 	    scale_dimconv = vfparent->dimconv;
    398 	}
    399 
    400 	magstepval = magstepvalue(&fsize);
    401 	size = fsize + 0.5;
    402 
    403 	/*
    404 	 * reuse font if possible
    405 	 */
    406 	for (fontp = font_head; fontp != NULL; fontp = fontp->next) {
    407 		if (strcmp(n, fontp->fontname) != 0 ||
    408 		    size != (int) (fontp->fsize + 0.5))
    409 			continue;
    410 
    411 		/* font already in use */
    412 		reuse_font(fontp);
    413 		free(n);
    414 		break;
    415 	}
    416 
    417 	if (fontp == NULL) {
    418 		/* font doesn't exist yet */
    419 		if (resource._list_fonts)
    420 			printf("%s at %d dpi\n", n, size);
    421 		fontp = xmalloc(sizeof(struct font));
    422 		fontp->fontname = n;
    423 		fontp->fsize = fsize;
    424 		fontp->magstepval = magstepval;
    425 		fontp->file = NULL; /* needed for virtual/freetype fonts */
    426 		fontp->filename = NULL;	/* needed for freetype fonts */
    427 		fontp->checksum = c;
    428 		fontp->flags = FONT_IN_USE;
    429 		fontp->dimconv = s * scale_dimconv / (1 << 20);
    430 		fontp->set_char_p = load_n_set_char;
    431 		fontp->ft = NULL;
    432 		/* spsize = scaled size of the font in spell units,
    433 		 *	  = scale * [vfparent->]dimconv.
    434 		 */
    435 		fontp->spsize = (vfparent != NULL ? vfparent->dimconv : dimconv) * s;
    436 		if (vfparent == NULL)
    437 			if (!load_font(fontp)) {
    438 				free(n);
    439 				free(fontp);
    440 				return NULL;
    441 			}
    442 		fontp->next = font_head;
    443 		font_head = fontp;
    444 	}
    445 
    446 	if (k < tn_table_len)
    447 		tntable[k] = fontp;
    448 	else {
    449 		struct tn *tnp;
    450 		tnp = xmalloc(sizeof(struct tn));
    451 		tnp->next = *tn_headpp;
    452 		*tn_headpp = tnp;
    453 		tnp->TeXnumber = k;
    454 		tnp->fontp = fontp;
    455 	}
    456 	return fontp;
    457 }
    458 
    459 Boolean
    460 dvi_magic_ok(FILE *dvi)
    461 {
    462 	if (one(dvi) != PRE)
    463 		/* Not a DVI file */
    464 		return False;
    465 	if (one(dvi) != 2)
    466 		/* Wrong version of DVI output for this program */
    467 		return False;
    468 
    469 	return True;
    470 }
    471 
    472 
    473 /*
    474  *      process_preamble reads the information in the preamble and stores
    475  *      it into global variables for later use.
    476  */
    477 static Boolean
    478 process_preamble(long *n, long *d, long *m)
    479 {
    480 	char	 comment[256 + 1];
    481 	size_t   k;
    482 
    483 	if (dvi_magic_ok(dvi_file) == False)
    484 		return False;
    485 	*n = four(dvi_file);		/* numerator */
    486 	*d = four(dvi_file);		/* denominator */
    487 	*m = four(dvi_file);		/* magnification */
    488 	dimconv = (((double) (*n) * (*m)) / ((double) (*d) * 1000.));
    489 	dimconv = dimconv * (((long) pixels_per_inch)<<16) / 254000;
    490 	tpic_conv = pixels_per_inch * (*m) / 1000000.0;
    491 	k = one(dvi_file);
    492 	fread(comment, sizeof(char), k, dvi_file);
    493 	comment[k] = '\0';
    494 
    495 	if (debug & DBG_DVI)
    496 		printf("Preamble comment '%s'\n", comment);
    497 
    498 	return True;
    499 }
    500 
    501 /*
    502  *      find_postamble locates the beginning of the postamble
    503  *	and leaves the file ready to start reading at that location.
    504  */
    505 #define	TMPSIZ	516	/* 4 trailer bytes + 512 junk bytes allowed */
    506 static Boolean
    507 find_postamble(void)
    508 {
    509 	long	pos;
    510 	unsigned char	temp[TMPSIZ];
    511 	unsigned char	*p;
    512 	unsigned char	*p1;
    513 	unsigned char	byte;
    514 
    515 	if (fseek(dvi_file, 0, SEEK_END) != 0)
    516 		err(1, "fseek");
    517 	pos = ftell(dvi_file) - TMPSIZ;
    518 	if (pos < 0) pos = 0;
    519 	if (fseek(dvi_file, pos, SEEK_SET) != 0)
    520 		err(1, "fseek");
    521 	p = temp + fread((char *) temp, sizeof(char), TMPSIZ, dvi_file);
    522 	for (;;) {
    523 	    p1 = p;
    524 	    while (p1 > temp && *(--p1) != TRAILER) ;
    525 	    p = p1;
    526 	    while (p > temp && *(--p) == TRAILER) ;
    527 	    if (p <= p1 - 4) break;	/* found 4 TRAILER bytes */
    528 	    if (p <= temp)
    529 		/* DVI file corrupted */
    530 		return False;
    531 	}
    532 	pos += p - temp;
    533 	byte = *p;
    534 	while (byte == TRAILER) {
    535 	    if (fseek(dvi_file, --pos, SEEK_SET) != 0)
    536 		err(1, "fseek");
    537 	    byte = one(dvi_file);
    538 	}
    539 	if (byte != 2)
    540 	    /* Wrong version of DVI output for this program */
    541 	    return False;
    542 	if (fseek(dvi_file, pos - 4, SEEK_SET) != 0)
    543 		err(1, "fseek");
    544 	if (fseek(dvi_file, sfour(dvi_file), SEEK_SET) != 0)
    545 		err(1, "fseek");
    546 
    547 	return True;
    548 }
    549 
    550 
    551 /*
    552  *      read_postamble reads the information in the postamble,
    553  *	storing it into global variables.
    554  *      It also takes care of reading in all of the pixel files for the fonts
    555  *      used in the job.
    556  */
    557 static	Boolean
    558 read_postamble(long *p, long n, long d, long m)
    559 {
    560 	unsigned char   cmnd;
    561 	Boolean		font_not_found;
    562 	struct font	*fontp;
    563 	struct font	**fontpp;
    564 
    565 	if (one(dvi_file) != POST)
    566 		/* Postamble doesn't begin with POST */
    567 		return False;
    568 	*p = four(dvi_file);		/* pointer to final bop (last page) */
    569 
    570 	/* Check postamble duplicates match preamble. */
    571 	if (n != four(dvi_file))
    572 		return False;
    573 	if (d != four(dvi_file))
    574 		return False;
    575 	if (m != four(dvi_file))
    576 		return False;
    577 
    578 	/* read largest box height and width */
    579 	dvi_unshrunk_page_h = (spell_conv(sfour(dvi_file)) >> 16) + offset_y;
    580 	if (dvi_unshrunk_page_h < unshrunk_paper_h)
    581 	    dvi_unshrunk_page_h = unshrunk_paper_h;
    582 	dvi_unshrunk_page_w = (spell_conv(sfour(dvi_file)) >> 16) + offset_x;
    583 	if (dvi_unshrunk_page_w < unshrunk_paper_w)
    584 	    dvi_unshrunk_page_w = unshrunk_paper_w;
    585 	(void) two(dvi_file);	/* max stack size */
    586 	total_pages = two(dvi_file);
    587 
    588 	/*
    589 	 * Attempt to load all fonts for the file. If one is not found,
    590 	 * keep searching such that we can show all fonts that are missing.
    591 	 */
    592 	font_not_found = False;
    593 	while (1) {
    594 		cmnd = one(dvi_file);
    595 		if (cmnd < FNTDEF1 || cmnd > FNTDEF4)
    596 			break;
    597 		if (define_font(dvi_file, cmnd, NULL, tn_table, TNTABLELEN,
    598 		    &tn_head, m) == NULL)
    599 			font_not_found = True;
    600 	}
    601 	if (font_not_found == True)
    602 		return False;
    603 	if (cmnd != POSTPOST)
    604 		/* Non-fntdef command found in postamble */
    605 		return False;
    606 	/*
    607 	 * free up fonts no longer in use
    608 	 */
    609 	fontpp = &font_head;
    610 	while ((fontp = *fontpp) != NULL) {
    611 		if (fontp->flags & FONT_IN_USE) {
    612 			fontpp = &fontp->next;
    613 			continue;
    614 		}
    615 		if (debug & DBG_PK)
    616 		    printf("Discarding font \"%s\" at %d dpi\n",
    617 			fontp->fontname, (int) (fontp->fsize + 0.5));
    618 		*fontpp = fontp->next;		/* remove from list */
    619 		free(fontp->fontname);
    620 		if (fontp->flags & FONT_LOADED) {
    621 		    if (fontp->ft != NULL) {	/* if FreeType font */
    622 			struct ftfont	*ft;
    623 
    624 			ft = fontp->ft;
    625 			if (fontp->size != NULL)
    626 			    FT_Done_Size(fontp->size);
    627 			if (fontp == ft->first_size) {
    628 			    if (fontp->next_size == NULL) {
    629 				/* if this is the only size of this font face */
    630 				FT_Done_Face(ft->face);
    631 				ft->t1->ft = NULL;
    632 				free(ft);
    633 			    }
    634 			    else {
    635 				struct font	*fp2;
    636 
    637 				ft->first_size = fp2 = fontp->next_size;
    638 				fp2->file = fontp->file;
    639 				fontp->file = NULL;
    640 				fp2->filename = fontp->filename;
    641 				fontp->filename = NULL;
    642 				fp2->timestamp = fontp->timestamp;
    643 			    }
    644 			}
    645 			else {
    646 			    struct font *fp2;
    647 
    648 			    fp2 = ft->first_size;
    649 			    while (fp2->next_size != fontp)
    650 				fp2 = fp2->next_size;
    651 			    fp2->next_size = fontp->next_size;
    652 			}
    653 		    }
    654 		    if (fontp->file != NULL)
    655 			fclose(fontp->file);
    656 		    if (fontp->filename != NULL)
    657 			free((void *) fontp->filename);
    658 
    659 		    if (fontp->flags & FONT_VIRTUAL) {
    660 			struct macro *m;
    661 
    662 			for (m = fontp->macro;
    663 				m <= fontp->macro + fontp->maxchar; ++m)
    664 			    if (m->free_me) free((char *) m->pos);
    665 			free((char *) fontp->macro);
    666 			free((char *) fontp->vf_table);
    667 			free_vf_chain(fontp->vf_chain);
    668 		    }
    669 		    else {
    670 			struct glyph *g;
    671 
    672 			for (g = fontp->glyph;
    673 				g <= fontp->glyph + fontp->maxchar; ++g) {
    674 			    if (g->bitmap.bits != NULL) free(g->bitmap.bits);
    675 			    if (g->bitmap2.bits != NULL) free(g->bitmap2.bits);
    676 			    if (g->pixmap2 != NULL) {
    677 				XDestroyImage(g->image2);
    678 				if (g->pixmap2_t != NULL)
    679 				    free(g->pixmap2_t);
    680 			    }
    681 			}
    682 			free((char *) fontp->glyph);
    683 		    }
    684 		    free((char *) fontp);
    685 		}
    686 	}
    687 	return True;
    688 }
    689 
    690 static	void
    691 prepare_pages(long p)
    692 {
    693 	int i;
    694 
    695 	page_info = xmalloc((unsigned) (total_pages + 1) * sizeof(*page_info));
    696 	page_info->pw = unshrunk_paper_w;
    697 	page_info->ph = unshrunk_paper_h;
    698 	page_info->ww = dvi_unshrunk_page_w;
    699 	page_info->wh = dvi_unshrunk_page_h;
    700 	++page_info;	/* this is indexed starting with -1 */
    701 
    702 	i = total_pages;
    703 	page_info[--i].offset = p;
    704 	if (fseek(dvi_file, p, SEEK_SET) != 0)
    705 		err(1, "fseek");
    706 	/*
    707 	 * Follow back pointers through pages in the DVI file,
    708 	 * storing the offsets in the page_info[].offset table.
    709 	 */
    710 	while (i > 0) {
    711 		if (fseek(dvi_file, (long) (1+4+(9*4)), SEEK_CUR) != 0)
    712 			err(1, "fseek");
    713 		if (fseek(dvi_file, page_info[--i].offset = four(dvi_file),
    714 		    SEEK_SET) != 0)
    715 			err(1, "fseek");
    716 	}
    717 }
    718 
    719 void
    720 init_page(void)
    721 {
    722 	unshrunk_page_w = page_info[current_page].ww;
    723 	page_w = ROUNDUP(unshrunk_page_w, mane.shrinkfactor) + 2;
    724 	unshrunk_page_h = page_info[current_page].wh;
    725 	page_h = ROUNDUP(unshrunk_page_h, mane.shrinkfactor) + 2;
    726 }
    727 
    728 	/* For non-toolkit compiles, this code appears in xdvi.c.  */
    729 
    730 static	void
    731 set_titles(void)
    732 {
    733 	char	*title_name;
    734 	char	*icon_name;
    735 	size_t	baselen;
    736 	Boolean	icon_name_malloced = False;
    737 
    738 	icon_name = rindex(dvi_name, '/');
    739 	if (icon_name != NULL) ++icon_name;
    740 	  else icon_name = dvi_name;
    741 	baselen = strlen(icon_name);
    742 	if (baselen > 4 && memcmp(icon_name + baselen - 4, ".dvi", 4) == 0) {
    743 	    /* remove the .dvi */
    744 	    char *p;
    745 
    746 	    baselen -= 4;
    747 	    p = xmalloc(baselen + 1);
    748 	    memcpy(p, icon_name, baselen);
    749 	    p[baselen] = '\0';
    750 	    icon_name = p;
    751 	    icon_name_malloced = True;
    752 	}
    753 
    754 	title_name = xmalloc(baselen + 8);
    755 	memcpy(title_name, "Xdvi:  ", 7);
    756 	memcpy(title_name + 7, icon_name, baselen + 1);
    757 
    758 	XtVaSetValues(top_level,
    759 	  XtNtitle, title_name,
    760 	  XtNiconName, icon_name,
    761 	  NULL);
    762 
    763 	free(title_name);
    764 	if (icon_name_malloced)
    765 	    free(icon_name);
    766 }
    767 
    768 /*
    769  *	init_dvi_file is the main subroutine for reading the startup
    770  *	information from the dvi file.
    771  */
    772 
    773 Boolean
    774 init_dvi_file(void)
    775 {
    776 	long	n, d, m, p;
    777 
    778 	if (!process_preamble(&n, &d, &m))
    779 		goto err;
    780 	if (!find_postamble())
    781 		goto err;
    782 	if (!read_postamble(&p, n, d, m))
    783 		goto err;
    784 
    785 	prepare_pages(p);
    786 	if (current_page >= total_pages)
    787 		current_page = total_pages - 1;
    788 	init_prescan();
    789 	set_titles();
    790 
    791 	return True;
    792 
    793 err:
    794 	fclose(dvi_file);
    795 	dvi_file = NULL;
    796 	return False;
    797 }
    798 
    799 
    800 /**
    801  **	Reload the dvi file (unconditionally).  Called only from do_pages().
    802  **/
    803 
    804 Boolean
    805 reload_dvi_file(void)
    806 {
    807 	struct font	*fontp;
    808 
    809 	if (page_info != NULL) {
    810 		free(page_info - 1);
    811 		page_info = NULL;
    812 		full_reset_colors();
    813 	}
    814 	bzero(tn_table, sizeof(tn_table));
    815 	free_vf_chain(tn_head);
    816 	tn_head = NULL;
    817 	for (fontp = font_head; fontp != NULL; fontp = fontp->next)
    818 	    fontp->flags &= ~FONT_IN_USE;
    819 
    820 	if (fseek(dvi_file, 0, SEEK_SET) != 0)
    821 		err(1, "fseek");
    822 	if (!init_dvi_file())
    823 		return False;
    824 	if (resource._list_fonts)
    825 		putchar('\n');
    826 
    827 	return True;
    828 }