home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS - Coast to Coast
/
simteldosarchivecoasttocoast.iso
/
dv_x
/
dvix.zip
/
GENERIC.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-11-04
|
18KB
|
801 lines
/*
* DVI previewer for X.
*
* Eric Cooper, CMU, September 1985.
*
* Code derived from dvi-imagen.c.
*
* Modified for X.10 by Bob Scheifler, MIT LCS, January 1986.
*
* Modified for X.10.3 (Sun) by Jeff Lee, UWO CSD, February 1987.
* -fixed bitmap manipulation to use (short*) for portability
* -added [G] for grid and [LRUD] for 1/4 screen motion
* -added absolute [LRUD] and relative [lrud] positioning
* in 1/10 inch increments.
*
* Modified (again) by Jeff Lee, UWO CSD, April 1987.
* -added an [i] command to re-init the file
*
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <ctype.h>
#include "dvi.h"
#include "pxl.h"
#include "general.h"
#include "local.h"
#include "bitorder.h"
/* these are the interface routines to the viewer */
extern set_char();
extern set_rule();
extern clear_page();
extern put_border();
extern end_page();
struct frame {
long pxl_h, dvi_h, pxl_v, dvi_v, w, x, y, z;
};
struct frame *stack;
int stackp;
#define PXL_H stack[stackp].pxl_h
#define PXL_V stack[stackp].pxl_v
#define DVI_H stack[stackp].dvi_h
#define DVI_V stack[stackp].dvi_v
#define WW stack[stackp].w
#define XX stack[stackp].x
#define YY stack[stackp].y
#define ZZ stack[stackp].z
/*
* Command line flags.
*/
extern char *prog; /* program name */
int debug = 0;
int list_fonts = 0;
int pixels_per_inch = PIXELS_PER_INCH;
int shrink_factor = SHRINK_FACTOR;
char *dvi_filename; /* name of user's file */
FILE *dvi_file; /* user's file */
time_t best_before; /* stale date for file */
char *tmp_dviname; /* mod for DV/X, MS-DOS (GBP) */
int font_not_found = 0;
struct font *current_font = NULL; /* ptr into circular list of fonts */
/*
* DVI preamble and postamble information.
*/
char job_id[300];
int total_pages, maxstack;
int current_page;
double fraction, conv, specialConv;
long numerator, denominator, magnification;
/*
* Offset in DVI file of last page, set in read_postamble().
*/
long last_page_offset;
/*
* Table of page offsets in DVI file, indexed by page number - 1.
* Initialized in prepare_pages().
*/
long *page_offset;
long win_w, win_h, page_w, page_h;
long min_x, max_x, min_y, max_y;
long smin_x, smax_x, smin_y, smax_y;
int redisplay = 0;
int new_file = 0;
unsigned long num();
long snum();
extern unsigned char reverse_byte[];
char *malloc(), *calloc(), *index();
/*
** (re)open the dvi file and save the name for later use in the
** global variable ``dvi_filename''
*/
open_dvi_file(name)
char *name;
{
struct stat filestat;
dvi_filename = name;
dvi_file_copy(name);
if (dvi_file) {
(void) fclose(dvi_file);
dvi_file = NULL;
clear_page();
}
if ((dvi_file = fopen(tmp_dviname, "rb")) == NULL) {
printf("File open error\n");
exit(1);
}
/* now (re)set the global state */
process_preamble();
find_postamble();
read_postamble();
prepare_pages();
init_page();
redisplay = 0;
new_file = 1;
}
/*
** check to see if a file has been modified
*/
check_if_stale(file_name,date)
char *file_name;
time_t date;
{
FILE *chkd_file;
struct stat filestat;
if ((chkd_file = fopen(file_name,"rb"))==NULL) {
printf("Error opening dvi file\n");
exit(1);
}
if (fstat(fileno(chkd_file), &filestat)) {
perror("fstat");
return (1);
}
fclose(chkd_file);
return (filestat.st_mtime != date);
}
/*
** process_preamble reads the information in the preamble and stores
** it into global variables for later use.
*/
process_preamble()
{
int k;
if (one(dvi_file) != PRE)
error("DVI file doesn't start with preamble");
if (one(dvi_file) != 2)
error("Wrong version of DVI output for this program");
numerator = four(dvi_file);
denominator = four(dvi_file);
magnification = four(dvi_file);
fraction = (((double) numerator * magnification)
/ ((double) denominator * 1000.));
define_conv();
k = one(dvi_file);
(void) fread(job_id, sizeof(char), k, dvi_file);
job_id[k] = '\0';
}
define_conv ()
{
conv = ((fraction * pixels_per_inch) / 100000) / (2.54 * shrink_factor);
specialConv = pixels_per_inch / 1000.0 / shrink_factor;
}
/*
** find_postamble locates the beginning of the postamble
** and leaves the file ready to start reading at that location.
*/
find_postamble()
{
ubyte byte;
long offset = -4; /* At least 4 TRAILERS */
do {
offset -= 1;
(void) fseek(dvi_file, offset, 2);
byte = one(dvi_file);
} while (byte == TRAILER);
if (byte != 2)
error("Wrong version of DVI output for this program");
offset -= 4;
(void) fseek(dvi_file, offset, 2);
(void) 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 PXL files for the fonts
** used in the job.
*/
read_postamble()
{
ubyte cmnd;
int page_width, page_height;
if (one(dvi_file) != POST)
error("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))
error("Postamble doesn't match preamble");
page_height = pixel_round(four(dvi_file));
page_width = pixel_round(four(dvi_file));
maxstack = two(dvi_file);
total_pages = two(dvi_file);
do {
switch(cmnd = one(dvi_file)) {
case FNTDEF1:
case FNTDEF2:
case FNTDEF3:
case FNTDEF4:
define_font(cmnd);
break;
case POSTPOST:
break;
default:
error("Non-fntdef cmnd found in postamble");
}
} while (cmnd != POSTPOST);
if (font_not_found)
error("Not all PXL files were found");
list_fonts = 0;
}
prepare_pages()
{
int i;
stack = (struct frame *) malloc((unsigned) sizeof(struct frame) * (maxstack+1));
if (stack == NULL)
error("Can't allocate stack space (%d frames)", maxstack);
page_offset = (long *) malloc((unsigned) total_pages * sizeof(long));
if (page_offset == NULL)
error("Can't allocate page directory (%d pages)", total_pages);
i = total_pages;
page_offset[--i] = last_page_offset;
(void) 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) {
(void) num(dvi_file, 1+4+(9*4));
(void) fseek(dvi_file, page_offset[--i] = four(dvi_file), 0);
}
}
#define nope(str) error("%s not implemented", str)
#define correct() (PXL_H = pixel_round(DVI_H))
do_pages()
{
register int ch;
#ifdef DEBUG
int setchar_ctr = 0;
int changefont_ctr = 0;
int other_ctr = 0;
#endif /*DEBUG*/
min_x = 0;
min_y = 0;
max_x = win_w;
max_y = win_h;
current_page = 0;
for (;;) {
ch = one(dvi_file);
#ifdef DEBUG
if (debug & DBG_DVI)
print_dvi(ch);
#endif /*DEBUG*/
if (ch <= SETCHAR0 + 127) {
#ifdef DEBUG
setchar_ctr++;
#endif /*DEBUG*/
set_char(ch);
DVI_H += current_font->glyph[ch].dvi_adv;
PXL_H = pixel_round(DVI_H);
} else {
register long a, b;
#ifdef DEBUG
other_ctr++;
#endif /*DEBUG*/
switch (ch) {
case SET1:
ch = one(dvi_file);
if (ch < MAXCHARS) {
set_char(ch);
DVI_H += current_font->glyph[ch].dvi_adv;
PXL_H = pixel_round(DVI_H);
} else {
error("bad SET1 (%d)", ch);
}
break;
case SETRULE:
a = sfour(dvi_file); b = sfour(dvi_file);
if (a > 0 && b > 0) {
correct();
set_rule(pixel_round(a), pixel_round(b));
}
DVI_H += b;
PXL_H = pixel_round(DVI_H);
break;
case PUT1:
nope("PUT1");
break;
case PUTRULE:
a = sfour(dvi_file); b = sfour(dvi_file);
if (a > 0 && b > 0) {
correct();
set_rule(pixel_round(a), pixel_round(b));
}
break;
case NOP:
break;
case BOP:
(void) num(dvi_file, 11*4);
stackp = 0;
DVI_H = dvi_round(X_PAGE_OFFSET);
PXL_H = X_PAGE_OFFSET;
DVI_V = dvi_round(Y_PAGE_OFFSET);
PXL_V = Y_PAGE_OFFSET;
WW = XX = YY = ZZ = 0;
smin_x = min_x;
smax_x = max_x;
smin_y = min_y;
smax_y = max_y;
begin_page();
break;
case EOP:
if (stackp > 0)
error("Stack not empty at EOP (%d)",
stackp);
#ifdef DEBUG
printf("SETCHAR=%d CHANGEFONT=%d OTHER=%d\n",
setchar_ctr, changefont_ctr, other_ctr);
#endif
end_page();
if (ftell(dvi_file) > last_page_offset)
return;
break;
case PUSH:
stackp++;
if (stackp > maxstack)
error("More PUSHes than were promised");
stack[stackp] = stack[stackp - 1];
break;
case POP:
stackp--;
if (stackp < 0)
error("More POPs than PUSHes");
break;
case RIGHT1:
case RIGHT2:
case RIGHT3:
case RIGHT4:
DVI_H += snum(dvi_file, ch - RIGHT1 + 1);
PXL_H = pixel_round(DVI_H);
break;
case X1:
case X2:
case X3:
case X4:
XX = snum(dvi_file, ch - X0);
case X0:
DVI_H += XX;
PXL_H += pixel_round(XX);
correct();
break;
case W1:
case W2:
case W3:
case W4:
WW = snum(dvi_file, ch - W0);
case W0:
DVI_H += WW;
PXL_H = pixel_round(DVI_H);
break;
case Y1:
case Y2:
case Y3:
case Y4:
YY = snum(dvi_file, ch - Y0);
case Y0:
DVI_V += YY;
PXL_V = pixel_round(DVI_V);
break;
case Z1:
case Z2:
case Z3:
case Z4:
ZZ = snum(dvi_file, ch - Z0);
case Z0:
DVI_V += ZZ;
PXL_V = pixel_round(DVI_V);
break;
case DOWN1:
case DOWN2:
case DOWN3:
case DOWN4:
DVI_V += snum(dvi_file, ch - DOWN1 + 1);
PXL_V = pixel_round(DVI_V);
break;
case FNT1:
case FNT2:
case FNT3:
case FNT4:
change_font(num(dvi_file, ch - FNT1 + 1));
break;
case XXX1:
case XXX2:
case XXX3:
case XXX4:
a = num(dvi_file, ch - XXX1 + 1);
if(a > 0)
special((unsigned long) a);
break;
case FNTDEF1:
case FNTDEF2:
case FNTDEF3:
case FNTDEF4:
(void) fseek(dvi_file, (long) (12 + ch - FNTDEF1 + 1), 1);
a = one(dvi_file) + one(dvi_file);
(void) fseek(dvi_file, (long) a, 1);
break;
case PRE:
error("Shouldn't happen: PRE encountered.");
break;
case POST:
error("Shouldn't happen: POST encountered.");
break;
case POSTPOST:
error("Shouldn't happen: POSTPOST encountered.");
break;
default:
if (FNTNUM0 <= ch && ch <= FNTNUM0 + 63) {
#ifdef DEBUG
changefont_ctr++;
other_ctr--;
#endif /*DEBUG*/
change_font((unsigned long) (ch - FNTNUM0));
}
else
error("Unknown op-code %d, offset %d",
ch, ftell(dvi_file));
} /* end switch*/
} /* end else (ch not a SETCHAR or FNTNUM) */
} /* end for */
}
begin_page()
{
if (debug)
return;
clear_page();
put_border(0, 0, page_w, page_h, 1);
}
special(nbytes)
unsigned long nbytes;
{
char *cmd;
int i;
cmd = malloc((unsigned) nbytes+1);
if (cmd == NULL)
error("Can't allocate memory for special (%d bytes)", nbytes);
for (i = 0; i < nbytes; i += 1)
cmd[i] = getc(dvi_file);
cmd[i] = '\0';
applicationDoSpecial(cmd);
free(cmd);
}
/*
**
** Read size bytes from the FILE fp, constructing them into a
** signed/unsigned integer.
**
*/
unsigned long
num(fp, size)
register FILE *fp;
register int size;
{
register int i;
register long x;
x = 0;
for (i = 0; i < size; i += 1)
x = x * 0x100 + (unsigned) (getc(fp) & 0xff);
return (x);
}
long
snum(fp, size)
register FILE *fp;
register int size;
{
register int i;
register long x;
x = getc(fp) & 0xff;
if (x & 0x80)
x -= 0x100;
for (i = 1; i < size; i += 1)
x = x * 0x100 + (unsigned) (getc(fp) & 0xff);
return (x);
}
stop_output(sig)
{
exit(sig);
}
/* VARARGS1 */
error(message, a, b, c, d, e, f)
char *message;
{
(void) fprintf(stderr, "%s: ", prog);
(void) fprintf(stderr, message, a, b, c, d, e, f);
putc('\n', stderr);
exit(1);
}
init_page()
{
page_h = PAPER_HEIGHT;
page_w = PAPER_WIDTH;
}
print_char(ch, g)
ubyte ch;
struct glyph *g;
{
(void) printf("char %d", ch);
if (isprint(ch))
(void) printf(" (%c)", ch);
putchar('\n');
(void) printf("x = %d, y = %d, pxl = %d, dvi = %d\n",
g->x, g->y, g->pxl_adv, g->dvi_adv);
print_bitmap(&g->bitmap);
}
print_bitmap(bitmap)
register struct bitmap *bitmap;
{
register short *ptr; /* bitmaps are shorts not bytes guys */
register int x, y, i;
ptr = (short*) bitmap->bits;
if (ptr == NULL)
return;
(void) printf("w = %d, h = %d, bytes wide = %d\n",
bitmap->w, bitmap->h, bitmap->bytes_wide);
for (y = 0; y < bitmap->h; y += 1) {
for (x = 0; x < bitmap->bytes_wide; x += 2) {
for (i = 0; i < BITS_PER_BYTE*2; i += 1)
if (*ptr & (1 << i))
putchar('@');
else
putchar(' ');
ptr += 1;
}
putchar('\n');
}
}
print_dvi(ch)
int ch;
{
(void) printf("%4d %4d ", PXL_H, PXL_V);
if (ch <= SETCHAR0 + 127) {
(void) printf("SETCHAR%-3d", ch - SETCHAR0);
if (isprint(ch))
(void) printf(" (%c)", ch);
} else if (FNTNUM0 <= ch && ch <= FNTNUM0 + 63) {
(void) printf("FNTNUM%d", ch - FNTNUM0);
} else {
switch (ch) {
case SET1:
(void) printf("SET1");
break;
case SETRULE:
(void) printf("SETRULE");
break;
case PUT1:
(void) printf("PUT1");
break;
case PUTRULE:
(void) printf("PUTRULE");
break;
case NOP:
(void) printf("NOP");
break;
case BOP:
(void) printf("BOP");
break;
case EOP:
(void) printf("EOP");
break;
case PUSH:
(void) printf("PUSH");
break;
case POP:
(void) printf("POP");
break;
case RIGHT1:
case RIGHT2:
case RIGHT3:
case RIGHT4:
(void) printf("RIGHT%d", ch - RIGHT1 + 1);
break;
case X0:
case X1:
case X2:
case X3:
case X4:
(void) printf("X%d", ch - X0);
break;
case W0:
case W1:
case W2:
case W3:
case W4:
(void) printf("W%d", ch - W0);
break;
case Y0:
case Y1:
case Y2:
case Y3:
case Y4:
(void) printf("Y%d", ch - Y0);
break;
case Z0:
case Z1:
case Z2:
case Z3:
case Z4:
(void) printf("Z%d", ch - Z0);
break;
case DOWN1:
case DOWN2:
case DOWN3:
case DOWN4:
(void) printf("DOWN%d", ch - DOWN1 + 1);
break;
case FNT1:
case FNT2:
case FNT3:
case FNT4:
(void) printf("FNT%d", ch - FNT1 + 1);
break;
case XXX1:
case XXX2:
case XXX3:
case XXX4:
(void) printf("XXX%d", ch - XXX1 + 1);
break;
case FNTDEF1:
case FNTDEF2:
case FNTDEF3:
case FNTDEF4:
(void) printf("FNTDEF%d", ch - FNTDEF1 + 1);
break;
case PRE:
(void) printf("PRE");
break;
case POST:
(void) printf("POST");
break;
case POSTPOST:
(void) printf("POSTPOST");
break;
default:
error("Unknown op-code %d, offset %d",
ch, ftell(dvi_file));
} /* end switch*/
} /* end else (ch not a SETCHAR or FNTNUM) */
putchar('\n');
}
/* mod for DV/X, MS-DOS, (GBP) */
/*------------------------- dvi_file_copy ----------------------*/
dvi_file_copy( char *from_name )
{
FILE *from_file, *to_file;
char *from_name_dvi, *tmp_data;
int tmp_c, n_len;
struct stat filestat;
long filesize;
/* if dvi_file is open, close it */
if (dvi_file) fclose(dvi_file);
/* open dvi input file */
if ((from_file = fopen(from_name, "rb")) == NULL) {
n_len = strlen(from_name);
if (strcmp(from_name + n_len - sizeof(".dvi"), ".dvi") == 0) {
perror(from_name);
exit(1);
}
from_name_dvi = malloc((unsigned) n_len + sizeof(".dvi"));
(void) sprintf(from_name_dvi, "%s.dvi", from_name);
if ((from_file = fopen(from_name_dvi, "rb")) == NULL) {
perror(from_name_dvi);
exit(1);
}
else {
dvi_filename = from_name_dvi;
}
}
else {
dvi_filename = from_name;
}
/* create the tmp file */
if ((to_file = fopen(tmp_dviname,"wb+")) == NULL ) {
printf("Temp file create error\n");
exit(1);
}
/* find size of dvi (from) file */
fseek(from_file,0L,2);
filesize = ftell(from_file);
fseek(from_file,0L,0);
/* copy the file, in one shot if possible, or byte by byte */
if(!(tmp_data = (char *) malloc(filesize))) {
while ((tmp_c=getc(from_file))!=EOF)
putc(tmp_c,to_file);
}
else {
if (fread(tmp_data, filesize, 1, from_file)!=1) {
printf("Error on dvi file read\n");
exit(1);
}
if (fwrite(tmp_data, filesize, 1, to_file)!=1) {
printf("Error on tmp file write\n");
exit(1);
}
free(tmp_data);
}
/* record the modification date for later testing */
fstat(fileno(from_file), &filestat);
best_before = filestat.st_mtime;
/* close the files */
fclose(from_file);
fclose(to_file);
}