home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Meeting Pearls 3
/
Meeting_Pearls_III.iso
/
Pearls
/
texmf
/
source
/
driver
/
util
/
dvihand.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-11-12
|
40KB
|
1,636 lines
/*
** This file generated by localize 2.9 (AmigaDOS 2.1) from util/dvihand.c
*/
/** dvihand.c **/
#include "defines.h"
#include <stdio.h>
#include <ctype.h>
#include "globals.h"
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "bitmap.h"
#include "commands.h"
#include "dvihand.h"
#include "flmt.h"
#include "new_font.h"
#include "dvihand.i"
#include "globals.i"
#include "new_font.i"
#include "bitmap.i"
#ifndef AZTEC_C
# define fgetc(fp) getc(fp) /* Effizienz ? */
#endif
#ifdef AMIGA
# include <exec/types.h>
# include <exec/exec.h>
# include <exec/ports.h>
# include <dos/dos.h>
extern struct ExecBase * SysBase;
extern struct DosLibrary * DOSBase;
# include <clib/dos_protos.h>
# include <pragmas/dos_pragmas.h>
# include <clib/exec_protos.h>
# include <pragmas/exec_pragmas.h>
# include "fast_cp.i"
#endif
#ifdef ATARI
extern int access(char *, int);
# include "atscreen.h"
#endif
#ifndef ANSI
char *strcpy();
#endif
/** char *logname(); **/
/*
* Fuer die locale-Library:
*
* Hier duerfen *nur* die MSG_#? Nummern eingebunden werden!
* Achtung:
* Es muss/sollte 'multiple-include' erlaubt sein!
*/
#include "local.i"
#undef CATCOMP_ARRAY
#undef CATCOMP_BLOCK
#undef CATCOMP_STRINGS
#define CATCOMP_NUMBERS
#include "localstr.h"
extern long hconv, vconv; /* converts DVI units to pixels */
extern long den; /* denominator specified in preamble */
extern DVIFILE *dvifp; /* DVI file pointer */
extern long h; /* current horizontal position */
extern long hh; /* current h on device */
extern long v; /* current vertical position */
extern long vv; /* current v on device */
extern long mag; /* magnification specified in preamble*/
extern long num; /* numerator specified in preamble */
extern long postambleptr; /* Pointer to the postamble */
extern long ppagep; /* previous page pointer */
extern long paper_height, paper_width; /* real height and width of page */
extern int pheight_pt; /* real height in pt */
extern int pwidth_pt; /* real width in pt */
extern int hmaxdrift; /* max pixels away from true rounded position */
extern int vmaxdrift; /* max pixels away from true rounded position */
extern int thinspace; /* needet in dvihand.c for rounding */
extern int backspace;
extern int vertsmallspace; /* also ^^ */
extern double alpha; /* conversion ratio, DVI unit per TFM unit */
extern struct bitmap map;
extern long upper_limit;
extern long lower_limit;
#define EVPATH
#ifdef EVPATH
#include "EVPaths.h"
static struct EnvVarPath * evpath_config = NULL;
void _STD_5555_FreeEVpath(void)
{
if (evpath_config) {
Free_EnvVarPath(evpath_config);
evpath_config = NULL;
}
}
#endif
#ifdef AMIGA
FILE *OpenConfigFile(char *name, int modus)
{
register char *ptr;
char path[120], env[120];
FILE *fp;
ptr = getenv(ENV_DEFAULT_PATH);
if (ptr == NULL) ptr = DEFAULT_PATH;
strcpy(env, ptr);
#ifdef EVPATH
if (!evpath_config) {
evpath_config = Alloc_EnvVarPath(ENV_DEFAULT_PATH, 1024);
Init_EnvVarPath(evpath_config, DEFAULT_PATH, ENVPATH_DEFSTR);
#undef EVPATH_DEBUG
#ifdef EVPATH_DEBUG
{ int i = 0;
printf("The environment variable `%s' has length %ld\n", ENV_DEFAULT_PATH, GetVarLength(ENV_DEFAULT_PATH));
while (evpath_config->storage.strings[i])
printf("%ld -> `%s'\n", i, evpath_config->storage.strings[i++]);
}
#endif
}
if (!evpath_config) return NULL;
switch(modus) {
case MODE_READ: ptr = "r"; break;
case MODE_WRITE: ptr = "w"; break;
default: ptr = "a"; break;
}
if (EVP_FileSearch(name, evpath_config, path, sizeof(path)-1)) {
fp = fopen(path, ptr);
}
#else
ptr = strtok(env, ",;");
do {
strcpy(path, ptr);
mk_correct_path(path);
if (strcmp(path, "./") == 0) path[0] = '\0'; /* ./ is actual directory */
strcat(path, name);
fp = fopen(path, "r");
} while (fp == NULL && (ptr = strtok(NULL, ",;")) != NULL);
/* bei WRITE/APPEND ueberschreibe existierendes File */
if (fp != NULL && modus != MODE_READ) {
fclose(fp);
if (modus == MODE_WRITE) {
fp = fopen(path, "w");
}
else {
fp = fopen(path, "a");
}
}
#endif
/* falls noch kein existierendes File gefunden wurde dann nun ein neues oeffnen */
if (fp == NULL && modus != MODE_READ) {
ptr = strtok(env, ",;");
do {
strcpy(path, ptr);
mk_correct_path(path);
if (strcmp(path, "./") == 0) path[0] = '\0'; /* ./ is actual directory */
strcat(path, name);
fp = fopen(path, (modus == MODE_WRITE) ? "w" : "a");
} while (fp == NULL && (ptr = strtok(NULL, ",;")) != NULL);
}
return fp;
}
#endif
/*
* Oeffne ein DVI-File und kopiere ins RAM, wenns denn sein muss
*/
DVIFILE * OpenDVI(char * name, int maxbuf)
{
DVIFILE * df;
FILE * fp;
__aligned struct FileInfoBlock fib;
BPTR lck;
dvidatestamp.ds_Days = 0;
dvidatestamp.ds_Minute = 0;
dvidatestamp.ds_Tick = 0;
df = xmalloc(sizeof(DVIFILE));
fp = fopen(name, "r");
if (fp) {
lck = Lock(name, ACCESS_READ);
if (lck) {
strncpy(df->name, name, sizeof(df->name));
df->pointer = 0;
if (Examine(lck, &fib)) {
df->size = fib.fib_Size;
dvidatestamp = fib.fib_Date;
if (df->size <= maxbuf) {
// soll es kopiert werden? Ja.
df->rambuf = malloc(df->size);
if (df->rambuf) {
fseek(fp, 0, SEEK_SET); // an den Anfang
if (fread(df->rambuf, 1, df->size, fp) != df->size) {
free(df->rambuf);
df->rambuf = NULL;
}
fseek(fp, 0, SEEK_SET); // und wieder an den Anfang
if (df->rambuf) df->flags |= InRam;
}
}
}
UnLock(lck);
}
// und wie ist das File nun angelegt?
if (df->flags & InRam) {
// ist in RAM, fp wird also nicht mehr gebraucht
fclose(fp);
if (df->size == 0) df->flags |= Eof;
}
else {
df->fp = fp;
}
}
if (!(df->flags & InRam) && !df->fp) {
// dann sind wir gescheitert
free(df);
df = NULL;
}
return df;
}
/*
* CloseDVI: schliesse ein DVI-File
*/
void CloseDVI(DVIFILE * dvifp)
{
if (dvifp) {
if (dvifp->fp) fclose(dvifp->fp);
if (dvifp->rambuf) free(dvifp->rambuf);
free(dvifp);
}
}
/*
* TempCloseDVI: schliesse bei einem DVI-File nur temporaer das fp
* damit virtex darauf schreiben kann
*/
void TempCloseDVI(DVIFILE * dvifp)
{
if (dvifp) {
if (!(dvifp->flags & InRam) && dvifp->fp) {
dvifp->tmpftell = ftell(dvifp->fp);
fclose(dvifp->fp);
dvifp->fp = NULL;
dvifp->flags |= TmpClosed;
}
}
}
/*
* TempOpenDVI: Oeffne ein DVI-File, das vorher Temp geschlossen wurde
*/
void TempOpenDVI(DVIFILE ** dvifp)
{
DVIFILE * fp = *dvifp;
if (fp && (fp->flags & TmpClosed) && !fp->fp) {
fp->flags &= ~TmpClosed;
fp->fp = fopen(fp->name, "r");
if (fp->fp) {
fseek(fp->fp, fp->tmpftell, SEEK_SET);
}
else {
CloseDVI(fp);
*dvifp = NULL;
}
}
}
/*
* DVIftell: Wie ftell
*/
long DVIftell(DVIFILE * dvifp)
{
if (dvifp->flags & InRam) {
return dvifp->pointer;
}
else {
return ftell(dvifp->fp);
}
}
/*
* DVIfseekSet: Wie fseek mit SEEK_SET
*/
int DVIfseekSet(DVIFILE * dvifp, long pos)
{
if (dvifp) {
if (dvifp->flags & InRam) {
if (pos > dvifp->size || pos < 0) {
return -1;
}
else {
dvifp->pointer = pos;
return 0;
}
}
else {
return fseek(dvifp->fp, pos, SEEK_SET);
}
}
}
/*
* DVIrewind: wie rewind
*/
void DVIrewind(DVIFILE * dvifp)
{
if (dvifp) {
if (dvifp->flags & InRam) {
dvifp->pointer = 0;
}
else {
rewind(dvifp->fp);
}
}
}
/*
* DVIseekEnd: setze Filepointer auf das Ende des Files
*/
void DVIseekEnd(DVIFILE * dvifp)
{
if (dvifp) {
if (dvifp->flags & InRam) {
dvifp->pointer = dvifp->size;
}
else {
fseek(dvifp->fp, 0, SEEK_END);
#ifdef SEEK_FUNKT_NICHT
if (ftell(dvifp->fp) == 0) {
WarningStr("ACHTUNG: fseek(fp, 0, SEEK_END) funktioniert nicht!");
while (!feof(dvifp->fp)) (void)fgetc(dvifp->fp);
}
#endif
}
}
}
/*
* DVIfread: Wie fread
*/
int DVIfread(char * buf, int bsize, int nr, DVIFILE * dvifp)
{
if (dvifp->flags & InRam) {
int cnr = bsize*nr;
if (dvifp->pointer+cnr < dvifp->size) {
/* CopyMem(dvifp->rambuf+dvifp->pointer, buf, cnr); */
memcpy(buf, dvifp->rambuf+dvifp->pointer, cnr); // das ist builtin
dvifp->pointer += cnr;
}
else {
Fatal(5,MSG_DVI_FILE_ERROR);
}
}
else {
if (fread(buf, bsize, nr, dvifp->fp) != nr) Fatal(5,MSG_DVI_FILE_ERROR);
}
return nr;
}
/*
* DVIfeof: wie feof
*/
int DVIfeof(DVIFILE * dvifp)
{
if (dvifp) {
if (dvifp->flags & InRam) {
return dvifp->size == dvifp->pointer;
}
else {
return feof(dvifp->fp);
}
}
}
/*
* Code to scale dimensions. Takes two thirty-two bit integers, multiplies
* them, divides them by 2^20, and returns the thirty-two bit result.
* The first integer, the width in FIXes, can lie between -2^24 and 2^24-1.
* The second integer, the scale factor, can lie between 0 and 2^27-1. The
* arithmetic must be exact. The answer is truncated to an integer.
*
*/
long scalewidth(long a, long b)
{
register long al, bl ;
al = a & 32767 ;
bl = b & 32767 ;
a >>= 15 ;
b >>= 15 ;
return ( ((al*bl/32768) + a*bl+al*b)/32 + a*b*1024) ;
}
/*-->ActualFactor*/
/**********************************************************************/
/************************** ActualFactor ****************************/
/**********************************************************************/
double /* compute the actual size factor given the approximation */
ActualFactor(long unmodsize) /* actually factor * 1000 */
{
double realsize; /* the actual magnification factor */
realsize = (double)unmodsize / 1000.0;
/* a real hack to correct for rounding in some cases--rkf */
if(unmodsize==1095) realsize = 1.095445; /*stephalf*/
else if(unmodsize==1315) realsize=1.314534; /*stepihalf*/
else if(unmodsize==1577) realsize=1.577441; /*stepiihalf*/
else if(unmodsize==1893) realsize=1.892929; /*stepiiihalf*/
else if(unmodsize==2074) realsize=2.0736; /*stepiv*/
else if(unmodsize==2488) realsize=2.48832; /*stepv*/
else if(unmodsize==2986) realsize=2.985984; /*stepvi*/
/* the remaining magnification steps are represented with sufficient
accuracy already */
return(realsize);
}
/*-->DoConv*/
/*********************************************************************/
/******************************** DoConv ***************************/
/*********************************************************************/
long DoConv(long num, long den, int convResolution)
{
double conv;
conv = ((double)num/(double)den) *
((double) mag/(double)1000.0) *
((double)convResolution/(double)254000.0);
return (long)floor((double)1.0 / conv + 0.5);
}
/*-->FindPostAmblePtr*/
/**********************************************************************/
/************************ FindPostAmblePtr **************************/
/**********************************************************************/
int FindPostAmblePtr(long *postambleptr)
/* this routine will move to the end of the file and find the start
of the postamble */
{
int i;
DVIseekEnd(dvifp); /* goto end of file */
*postambleptr = DVIftell(dvifp) - 4;
DVIfseekSet(dvifp, (long) *postambleptr);
while (TRUE)
{
DVIfseekSet(dvifp,(long) --(*postambleptr));
if (((i = Read1Byte(dvifp)) != 223) && (i != DVIFORMAT))
{
/*
Fatal (5, "Bad end of DVI file");
*/
Warning(MSG_BAD_DVI_FILE_END);
return(1);
}
if (i == DVIFORMAT)
break;
}
DVIfseekSet(dvifp, (long) ((*postambleptr) - 4));
(*postambleptr) = Read4Byte(dvifp);
DVIfseekSet(dvifp,(long) *postambleptr);
return(0);
}
/*-->GetBytes*/
/**********************************************************************/
/***************************** GetBytes *****************************/
/**********************************************************************/
void GetBytes(DVIFILE *fp, char *cp, long n) /* get n bytes from file fp */
/* fp file pointer */
/* cp character pointer */
/* n number of bytes */
{
(void)DVIfread(cp, 1, n, fp);
}
/*-->GetFontDef*/
/**********************************************************************/
/**************************** GetFontDef *****************************/
/**********************************************************************/
void GetFontDef(int load)
/***********************************************************************
Read the font definitions as they are in the postamble of the DVI
file.
***********************************************************************/
{
unsigned char byte;
while (((byte = (unsigned char) Read1Byte(dvifp)) >= FNT_DEF1) &&
(byte <= FNT_DEF4))
{
switch (byte)
{
case FNT_DEF1:
ReadFontDef (Read1Byte(dvifp),load);
break;
case FNT_DEF2:
ReadFontDef (Read2Byte(dvifp),load);
break;
case FNT_DEF3:
ReadFontDef (Read3Byte(dvifp),load);
break;
case FNT_DEF4:
ReadFontDef (Read4Byte(dvifp),load);
break;
default:
Fatal (5, MSG_BAD_FONT_DEFS);
break;
}
}
if (byte != POST_POST)
{
Fatal (5, MSG_MISS_POST_POST);
}
}
/*-->MoveDown*/
/**********************************************************************/
/**************************** MoveDown ******************************/
/**********************************************************************/
void MoveDown(long p)
{
long roundpos;
/*
* The calculations here are crucial to the appearance of the document.
* If the motion is small, we round the amount of relative motion; otherwise,
* we update the position and round the new position. Then we check to
* insure that the rounded position didn't accumulate an error that was
* greater than maxdrift.
*/
/* naechste Zeile nur fuer virtuelle Fonts */
/* if (curpos) p = scalewidth(p, (frp-1)->curf->scaledsize) ; */
v += p;
if (p >= vertsmallspace || p <= -vertsmallspace) {
vv = PixRound(v, vconv); /* hier ist schon alles exact */
}
else {
vv += PixRound(p, vconv);
roundpos = PixRound(v, vconv);
if (roundpos - vv > vmaxdrift) {
vv = roundpos - vmaxdrift;
}
else if (vv - roundpos > vmaxdrift) {
vv = roundpos + vmaxdrift;
}
}
}
/*-->MoveOver*/
/**********************************************************************/
/**************************** MoveOver ******************************/
/**********************************************************************/
void MoveOver(long p)
{
/*
* Horizontal motion is analogous. We know the exact width of each
* character in pixels. Kerning is distinguished from space between
* words if it's less than a thinspace and not more negative than would
* occur when an accent is being positioned by backspacing.
*/
long roundpos;
/* naechste Zeile nur fuer virtuelle Fonts */
/* if (curpos) p = scalewidth(p, (frp-1)->curf->scaledsize); */
h += p;
if (p >= thinspace || p <= backspace) {
hh = PixRound(h, hconv);
}
else {
hh += PixRound(p, hconv);
#if 1 /* bringt etwas Geschwindigkeit.... (hoff) (hes) */
roundpos = PixRound(h, hconv);
if (roundpos - hh > hmaxdrift) {
hh = roundpos - hmaxdrift;
}
else if (hh - roundpos > hmaxdrift) {
hh = roundpos + hmaxdrift;
}
#else
setmotion(); /** das oben ist setmotion() (hes) **/
#endif
}
}
#if 0 /* wird in SetChar/SetRule gebraucht (??!) */
// ist nach fast_cp ausgelagert!! (hes) 10.07.94
/*-->setmotion*/
/**********************************************************************/
/*************************** setmotion ******************************/
/**********************************************************************/
void setmotion(void)
{
long roundpos;
roundpos = PixRound(h, hconv);
if (roundpos - hh > hmaxdrift) {
hh = roundpos - hmaxdrift;
}
else if (hh - roundpos > hmaxdrift) {
hh = roundpos + hmaxdrift;
}
}
#endif
/*-->NoSignExtend*/
/**********************************************************************/
/*************************** NoSignExtend ***************************/
/**********************************************************************/
#ifdef oldie
long OldNoSignExtend(FILE *fp, int n) /* return n byte quantity from file fd */
/* fp file pointer */
/* n number of bytes */
{
register long x = 0L; /* number being constructed */
int n1;
x = fgetc(fp); /* get first (high-order) byte */
n1 = n--;
while (n--)
{
x <<= 8;
x |= fgetc(fp);
}
return(x);
}
#endif
long NoSignExtend(DVIFILE *fp, int n) /* return n byte quantity from file fd */
/* fp file pointer */
/* n number of bytes */
{
if (n==1) return Read1Byte(fp);
else if (n==2) return Read2Byte(fp);
else if (n==3) return Read3Byte(fp);
else return Read4Byte(fp);
}
#if 0 // die 4 Funktionen sind nach dvihand.h ausgelagert worden (INLINE!!)
long __inline Read1Byte(DVIFILE *fp) /* return n byte quantity from file fd */
{
unsigned char buf[2];
DVIfread(buf, 1, 1, fp);
return (long)buf[0];
}
long __inline Read2Byte(DVIFILE *fp)
{
unsigned short x;
DVIfread((char *)&x,2,1,fp);
return (long)((unsigned long)x);
}
long __inline Read3Byte(DVIFILE *fp)
{
unsigned char x[4];
DVIfread(&(x[0]),3,1,fp);
return (long)((*(unsigned long *)(&(x[0]))) >> 8);
}
long __inline Read4Byte(DVIFILE *fp)
{
long x;
DVIfread((char *)&x,1,4,fp);
return x;
}
#endif
/*-->PixRound*/
/**********************************************************************/
/***************************** PixRound *****************************/
/**********************************************************************/
/*
#define PixRound(x,conv) (long)(((x) + ((conv) >> 1)) / (conv))
long
PixRound(x, conv) / * return rounded number of pixels * /
register long x; / * in DVI units * /
long conv; / * conversion factor * /
{
return((long)((x + (conv >> 1)) / conv));
}
*/
/*-->ReadFontDef*/
/**********************************************************************/
/**************************** ReadFontDef ***************************/
/**********************************************************************/
void ReadFontDef(long k, int load)
{
char nname[STRSIZE];
long font_mag, font_mag_5, c, s, d;
int a, l;
double z;
c = Read4Byte(dvifp); /* checksum */
s = Read4Byte(dvifp); /* space size */
d = Read4Byte(dvifp); /* design size */
a = Read1Byte(dvifp); /* area length for font name */
l = Read1Byte(dvifp); /* device length */
GetBytes(dvifp, nname, (long) (a+l));
nname[a+l] = '\0';
#ifdef AMIGA
z = ActualFactor((long)floor( ((double)s/(double)d) * (double)1000.0 +0.5)) *
ActualFactor(mag) * (double)resolution;
font_mag = (long)floor(z+0.5);
font_mag_5 = (long)floor(z*(double)5.0+0.5);
#else
{
register long par;
z = ((double) s/(double) d)*1000.0 + 0.5;
par = (long)floor(z);
z = ActualFactor(par) * ActualFactor(mag) * (double)resolution;
font_mag_5 = floor((z * (double)5.0) + (double)0.5);
font_mag = (long)floor(z + (double)0.5);
}
#endif
LoadFont ((load)? 2 : 0, k, nname, c, d, s, font_mag, font_mag_5 );
}
/*-->ReadPostAmble*/
/**********************************************************************/
/************************** ReadPostAmble ***************************/
/**********************************************************************/
int ReadPostAmble(int load)
/***********************************************************************
This routine is used to read in the postamble values. It
initializes the magnification and checks the stack height prior to
starting printing the document.
***********************************************************************/
{ long ph, pw;
int pages;
NumOfPages = 0;
if (FindPostAmblePtr (&postambleptr))
{
ppagep = -1L;
return(1);
}
if (Read1Byte(dvifp) != POST)
{
Warning (MSG_MISS_POST);
ppagep = -1L;
if (hconv == 0) {
hconv = 50000;
}
if (vconv == 0) {
vconv = 50000;
}
return (1);
}
#ifdef DEBUG
if (DeBug) {
Message("got POST command");
}
#endif
ppagep = Read4Byte(dvifp);
num = Read4Byte(dvifp);
den = Read4Byte(dvifp);
mag = Read4Byte(dvifp);
/* man muss beim h-v offset die Magnification beruecksichtigen! */
if (hoffset_is_true) {
hoffset_in = hoffset_in_fix;
}
else {
hoffset_in = (hoffset_in_fix * mag) / 1000.0;
}
if (voffset_is_true) {
voffset_in = voffset_in_fix;
}
else {
voffset_in = (voffset_in_fix * mag) / 1000.0;
}
if (moffset_is_true) {
moffset_in = moffset_in_fix;
}
else {
moffset_in = (moffset_in_fix * mag) / 1000.0;
}
hoffset = (int)((float)hconvresolution * hoffset_in);
voffset = (int)((float)vconvresolution * voffset_in);
moffset = (int)((float)hconvresolution * moffset_in);
hconv = DoConv(num, den, hconvresolution);
vconv = DoConv(num, den, vconvresolution);
alpha = (((double)den / 7227.0) / 0x100000) * (25400000.0 / (double) num) ;
/** fsizetol = 1 + (long)(resolution/(72270.0 * hconv)) ; **/
ph = Read4Byte (dvifp);
pw = Read4Byte (dvifp);
if (abs(user_paper_height_in+13.13) > 0.01) {
// hier kommt kein Offset dazu oder weg. Die Höhe ist inklusive Offset!
pheight_pt = (int)(user_paper_height_in * 72.27 + 0.5);
paper_height = (int)(user_paper_height_in * vconvresolution);
ph = pheight_pt << 16;
}
else {
pheight_pt = (int)((unsigned long)((ph+voffset*vconv)>>16));
paper_height = (int) (PixRound(ph,vconv) + (long)voffset); /* height-plus-depth of tallest page */
}
if (abs(user_paper_width_in+13.13) > 0.01) {
// hier kommt kein Offset dazu oder weg. Die Breite ist inklusive Offset!
pwidth_pt = (int)(user_paper_width_in * 72.27 + 0.5);
paper_width = (int)(user_paper_width_in * hconvresolution);
pw = pwidth_pt << 16;
}
else {
pwidth_pt = (int)((unsigned long)((pw+hoffset*hconv)>>16));
paper_width = (int) (PixRound(pw,hconv) + (long)hoffset); /* width of widest page */
}
/** pheight_inch = (pheight_inch * 1000) / mag; **/
/** pwidth_inch = (pwidth_inch * 1000) /mag; **/
/* pheight_inch = ((pheight_inch + 50) / 100 ) * 100; */ /* eine Kommastelle reicht */
/* pwidth_inch = ((pwidth_inch + 50) / 100 ) * 100; */
if (Stats) {
Logging(MSG_LOG_PAGE_DIM);
Logging(MSG_LOG_HORIZ, (float)(((unsigned long)pw)>>16) / 72.27, paper_width - hoffset,
((unsigned long)pw)>>16, pw);
Logging(MSG_LOG_VERT, (float)(((unsigned long)ph)>>16) / 72.27, paper_height - voffset,
((unsigned long)ph)>>16, ph);
Logging(MSG_LOG_MAG,mag, hconv);
Logging(MSG_LOG_OFFSET);
Logging(MSG_LOG_HOFF, hoffset_in, hoffset_in_fix, hoffset);
Logging(MSG_LOG_VOFF, voffset_in, voffset_in_fix, voffset);
Logging(MSG_LOG_RESO,hconvresolution, vconvresolution);
}
if (Read2Byte(dvifp) >= STACKSIZE) {
Fatal (10, MSG_DVI_STACK_TOO_SMALL,STACKSIZE);
}
pages=Read2Byte(dvifp); /* this reads the number of pages in */
NumOfPages = pages; /* the DVI file */
if (Stats)
{
Logging(MSG_LOG_NUM_PAGES, pages);
}
#ifdef oldie
if (load) {
GetFontDef (1); /* (hes) */
}
#endif
return(0); /* DVI file is complete */
}
#if 0
#ifdef SLOW
/*-->SetChar*/
/**********************************************************************/
/***************************** SetChar ******************************/
/**********************************************************************/
void SetChar(long c, int command)
{
long shift;
hh = PixRound(h, hconv);
vv = PixRound(v, vconv);
shift = PrintChar(hh,vv,c);
if (command <= SET4) h += shift;
}
#endif
#endif
#if 0
#ifdef SLOW
/*-->SetRule*/
/**********************************************************************/
/***************************** SetRule ******************************/
/**********************************************************************/
void SetRule(long a, long b, BOOLEAN Set)
{ /* this routine will draw a rule */
long ehh, evv;
hh = PixRound(h, hconv);
vv = PixRound(v-a, vconv);
ehh = PixRound(h + b, hconv);
evv = PixRound(v, vconv);
if (hh == ehh)
{
ehh++;
}
if (vv == evv)
{
vv--;
}
if ((a > 0) && (b > 0))
{
CopyBitArray ((long)hh, (long)vv, (long)(ehh-hh), (long)(evv-vv),
(long *)NULL);
}
if (Set)
{
h += b;
}
}
#endif
#endif
/*-->SignExtend*/
/**********************************************************************/
/**************************** SignExtend ****************************/
/**********************************************************************/
#ifdef oldie
long OldSignExtend(FILE *fp, int n) /* return n byte quantity from file fd */
{
int n1; /* number of bytes */
register long x=0; /* number being constructed */
x = fgetc(fp); /* get first (high-order) byte */
n1 = n--;
while (n--)
{
x <<= 8;
x |= fgetc(fp);
}
/* NOTE: This code assumes that the right-shift is an arithmetic, rather
than logical, shift which will propagate the sign bit right. According
to Kernighan and Ritchie, this is compiler dependent! */
x<<=32-8*n1;
x>>=32-8*n1; /* sign extend */
return(x);
}
#endif
long SignExtend(DVIFILE *fp, int n) /* return n byte quantity from file fd */
{
if (n==1) return SRead1Byte(fp);
else if (n==2) return SRead2Byte(fp);
else if (n==3) return SRead3Byte(fp);
else return SRead4Byte(fp);
}
long SRead1Byte(DVIFILE *fp) /* return n byte quantity from file fd */
{
signed char x;
DVIfread((char *)&x,1,1,fp);
return (long)x;
}
long SRead2Byte(DVIFILE *fp)
{
short x;
DVIfread((char *)&x,2,1,fp);
return (long)x;
}
long SRead3Byte(DVIFILE *fp)
{
char x[4];
DVIfread(&(x[0]),3,1,fp);
return (long)((*(long *)(&(x[0]))) >> 8);
}
long SRead4Byte(DVIFILE *fp)
{
long x;
DVIfread((char *)&x,1,4,fp);
return x;
}
/*-->SkipFontDef*/
/**********************************************************************/
/**************************** SkipFontDef ***************************/
/**********************************************************************/
void SkipFontDef(void)
{
int a, l;
char n[STRSIZE];
Read4Byte(dvifp);
Read4Byte(dvifp);
Read4Byte(dvifp);
a = Read1Byte(dvifp);
l = Read1Byte(dvifp);
GetBytes(dvifp, n,(long)(a+l));
}
/*-->DoSpecial*/
/*********************************************************************/
/***************************** DoSpecial ***************************/
/*********************************************************************/
#ifdef KEIN_DOSPECIAL_FILE
/* die Funktionen sind nun nach dospecia verlagert worden. */
#ifdef ATARI
typedef enum {None, String, Integer, Number, Dimension} ValTyp;
typedef struct
{
char *Key; /* the keyword string */
char *Val; /* the value string */
ValTyp vt; /* the value type */
union /* the decoded value */
{
int i;
float n;
} v;
} KeyWord;
typedef struct
{
char *Entry;
ValTyp Type;
} KeyDesc;
# define IMGFILE 0
# define MAXIMGWIDTH 1
# define MAXIMGHEIGHT 2
KeyDesc KeyTab[] =
{{"imgfile", String},
{"hsize", Dimension},
{"vsize", Dimension},
{"hoffset", Dimension},
{"voffset", Dimension},
{"hscale", Number},
{"vscale", Number}};
# define NKEYS (sizeof(KeyTab)/sizeof(KeyTab[0]))
/*-->GetKeyStr*/
/**********************************************************************/
/***************************** GetKeyStr ****************************/
/**********************************************************************/
/* extract first keyword-value pair from string (value part may be null)
* return pointer to remainder of string
* return NULL if none found
*/
char KeyStr[STRSIZE];
char ValStr[STRSIZE];
char *GetKeyStr( char *str, KeyWord *kw )
{
char *s, *k, *v, t;
if( str== NULL )
{
return( NULL );
}
for( s=str; *s == ' '; s++ )
; /* skip over blanks */
if ( *s == '\0' )
{
return( NULL );
}
for( k=KeyStr; /* extract keyword portion */
(*s != ' ') && (*s != '\0') && (*s != '=');
*k++ = *s++ )
;
*k = '\0';
kw->Key = KeyStr;
kw->Val = v = NULL;
kw->vt = None;
for( ; *s == ' '; s++ )
; /* skip over blanks */
if( *s != '=' ) /* look for "=" */
{
return( s );
}
for( s++ ; *s == ' '; s++ )
; /* skip over blanks */
if( *s == '\'' || *s == '\"' ) /* get string delimiter */
{
t = *s++;
}
else
{
t = ' ';
}
for( v=ValStr; /* copy value portion up to delim */
*s != t && *s != '\0';
*v++ = *s++ )
;
if ( t != ' ' && *s == t )
{
s++;
}
*v = '\0';
kw->Val = ValStr;
kw->vt = String;
return( s );
}
/*-->GetKeyVal*/
/**********************************************************************/
/***************************** GetKeyVal ****************************/
/**********************************************************************/
/* get next keyword-value pair
* decode value according to table entry
*/
int GetKeyVal( KeyWord *kw, KeyDesc tab[], int nt, int *tno)
{
int i;
*tno = -1;
for(i=0; i<nt; i++)
{
if ( !strcmp(kw->Key, tab[i].Entry) )
{
*tno = i;
switch ( tab[i].Type )
{
case None:
if ( kw->vt != None )
{
return( FALSE );
}
break;
case String:
if ( kw->vt != String )
{
return( FALSE );
}
break;
case Integer:
if ( kw->vt != String )
{
return( FALSE );
}
# if 0
if ( sscanf(kw->Val,"%d%c", &(kw->v.i), &c) != 1
|| c != '\0' )
# endif
if ( sscanf(kw->Val,"%d", &(kw->v.i)) != 1)
{
return( FALSE );
}
break;
case Number:
case Dimension:
if ( kw->vt != String )
{
return( FALSE );
}
# if 0
if( sscanf(kw->Val,"%f%c", &(kw->v.n), &c) != 2
/* || c != '\0' */)
# endif
if( sscanf(kw->Val,"%f", &(kw->v.n)) != 1)
{
return( FALSE );
}
break;
}
kw->vt = tab[i].Type;
return( TRUE );
}
}
return( TRUE );
}
void DoSpecial( char *str, long n )
/* interpret a \special command, made up of keyword=value pairs */
{
char spbuf[STRSIZE];
char *sf = NULL;
KeyWord k;
int i;
int maxwidth, maxheight;
double hsz, vsz;
long ihh, ivv;
str[n] = '\0';
spbuf[0] = '\0';
while( (str=GetKeyStr(str,&k)) != NULL ) /* get all keyword-value pairs */
{
/* for compatibility, single words are taken as file names */
if( k.vt == None /* && access(k.Key,0) == 0 */)
{
if (sf != NULL)
{
Warning("More than one \\special file name given. %s ignored", sf );
}
strcpy(spbuf, k.Key);
sf = spbuf;
}
else if( GetKeyVal( &k, KeyTab, NKEYS, &i ) && i != -1 )
{
switch (i)
{
case IMGFILE:
if (sf != NULL)
{
Warning("More than one \\special file name given. %s ignored", sf );
}
strcpy(spbuf, k.Val);
sf = spbuf;
break;
case MAXIMGWIDTH:
hsz = k.v.n;
break;
case MAXIMGHEIGHT:
vsz = k.v.n;
break;
default:
Logging( "%f @%s\n", k.v.n, KeyTab[i].Entry);
break;
}
}
else
{
Warning("Invalid keyword or value in \\special - \"%s\" ignored", k.Key );
}
}
if (sf != NULL)
{
ihh = (long)PixRound(h, hconv) + (long)hoffset;
ivv = (long)PixRound(v, vconv) + (long)voffset;
maxwidth = (int)((hsz * hconvresolution)/2.54);
maxwidth = (maxwidth+7)/8;
maxheight = (int)((vsz * vconvresolution)/2.54);
# ifdef ATARI
PaintImage (sf, ihh, ivv, maxwidth, maxheight);
# endif
}
else
{
Warning("No special file name provided.");
}
}
#endif /* ATARI */
#ifdef AMIGA
static void draw_border(struct special_map *bmap);
static void draw_border(struct special_map *bmap)
{
long width,height;
long svv = vv, shh = hh;
width = bmap->width; /* width in Bits */
height = bmap->height;
width = ((long)(((double)width/(double)hconvresolution)*72.27+0.5))<<16;
height = ((long)(((double)height/(double)vconvresolution)*72.27+0.5))<<16;
vv += bmap->voffset;
hh += bmap->hoffset;
SetRule(height, 1<<15, FALSE); /* 1<<15 == 0.5 pt */
SetRule(1<<15, width, FALSE);
vv -= bmap->height /*-vthickness*/;
SetRule(1<<15, width, FALSE);
vv += bmap->height /*-vthickness*/;
hh += bmap->width /*-hthickness*/;
SetRule(height, 1<<15, FALSE);
vv = svv;
hh = shh;
}
void DoSpecial( char *str, long n )
{
struct special_map *bmap;
long x,y,width,height, xpos, ypos, pagewidth, xoff, shift, ystart;
long xstart, xend;
unsigned short *page, *image, it;
unsigned long copy, *insert;
FILE *iffile;
long buffer;
unsigned short *line;
long width_bit;
str[n] = '\0';
bmap = send_special(str);
xstart = 0;
xend = 0;
if (bmap != NULL) {
#ifdef OLD_VERSION
x = PixRound(h, hconv) + (long)hoffset + bmap->hoffset;
y = PixRound(v, vconv) + (long)voffset + bmap->voffset;
#endif
if (landscape) {
// wird spaeter noch gedreht, also jetzt etwas seltsame Offsets
x = hh + hconvresolution + bmap->hoffset; // plus 1 inch
y = vv + hoffset + bmap->voffset;
}
else {
x = hh + hoffset + bmap->hoffset;
y = vv + voffset + bmap->voffset;
}
// die rechte Seite wird direkt neben die linke gesetzt.
// Dazu wird der hoffset der rechten abgezogen, da dort kein Offset mehr benoetigt wird.
// hoffset gibt es wirklich nur am linken Rand. Ansonsten hat man ja den moffset.
if (twopage && !leftpage) x += paper_width + moffset - hoffset;
if (x < 0) {
Warning("Picture out of left border! (x=%ld)",x);
xstart = (15-x)/16; /* weglassen von Vielfachen von 16Bit (Word) */
x += xstart*16;
}
switch (bmap->where_is) {
case LOC_BITMAP:
case LOC_BITMAP_BORDER:
copy = 0;
width = (bmap->width + 15) / 16; /* width in Words */
height = bmap->height;
y -= height;
xend = width;
if (x+width*16 > map.width) {
Warning("Picture out of right border!");
xend = width - (((x+width*16-map.width)+15)/16);
}
xoff = x >> 4;
shift = x - (xoff << 4);
pagewidth = map.width >> 4;
/* Test ob Bild im sichtbaren Bereich */
if (y >= lower_limit || y + height < upper_limit) {
break;
}
/* Test oberer Rand */
if (y < upper_limit) {
ystart = upper_limit - y;
page = ((unsigned short *)map.pixptr) + xoff;
image = (unsigned short *)bmap->loc.map + xstart + (width*ystart);
}
else {
ystart = 0;
page = ((unsigned short *)map.pixptr) + (y-upper_limit) * pagewidth + xoff;
image = (unsigned short *)bmap->loc.map + xstart;
}
/* Test unterer Rand */
if (y + height >= lower_limit) {
height = lower_limit - y - 1;
/* height -= (lower_limit - y); that's a bug !! */
}
for (ypos = ystart; ypos < height; ypos++) {
for (xpos = xstart; xpos < xend; xpos++) {
it = *((unsigned short *)image+xpos);
copy = ((unsigned long)it) << 16;
insert = (unsigned long *)(page + xpos);
*insert |= (copy >> shift);
}
image += width;
page += pagewidth;
}
if (bmap->where_is == LOC_BITMAP_BORDER) {
draw_border(bmap);
}
break;
case LOC_FILE:
case LOC_FILE_BORDER:
if ((iffile = fopen(bmap->loc.filename,"r")) != NULL) {
if (fread((char *)&buffer,4,1,iffile) == 1 && buffer == MAGIC_WORD) {
(void)fread((char *)&buffer,4,1,iffile);
if (fread((char *)&buffer,4,1,iffile) == 1) {
width = (buffer+15) / 16; /* in words */
width_bit = buffer;
xend = width;
if (x+width*16 > map.width) {
Warning("Picture out of right border!");
xend = width - (((x+width*16-map.width)+15)/16);
}
if (fread((char *)&buffer,4,1,iffile) == 1) {
height = buffer;
y -= height;
if ((line = xmalloc(width*2)) == NULL) {
Warning("No memory for special-bitmap copy!");
}
else {
xoff = x >> 4;
shift = x - (xoff << 4);
pagewidth = map.width >> 4;
/* Test on Bild im sichtbaren Bereich */
if (y > lower_limit || y + height < upper_limit) {
fclose(iffile);
break;
}
/* Test oberer Rand */
if (y < upper_limit) {
ystart = upper_limit - y;
page = ((unsigned short *)map.pixptr) + xoff;
fseek(iffile,width * 2 * ystart, 1); /* seek from actuall pos */
}
else {
page = ((unsigned short *)map.pixptr) + (y-upper_limit) * pagewidth + xoff;
ystart = 0;
}
/* Test unterer Rand */
if (y + height > lower_limit) {
height = lower_limit - y;
}
for (ypos = ystart; ypos < height; ypos++) {
if (fread((char *)line,2,width,iffile) == width) {
image = (unsigned short *)line+xstart;
for (xpos = xstart; xpos < xend; xpos++) {
it = *((unsigned short *)image+xpos);
copy = ((unsigned long)it) << 16;
insert = (unsigned long *)(page + xpos);
*insert |= (copy >> shift);
}
page += pagewidth;
}
}
xfree(line);
}
if (bmap->where_is == LOC_FILE_BORDER) {
bmap->width = width_bit;
bmap->height = height;
draw_border(bmap);
}
}
}
}
fclose(iffile);
}
break;
case LOC_BORDER:
draw_border(bmap);
break;
case LOC_RECTANGLE:
width = bmap->width; /* width in Bits */
height = bmap->height;
width = ((long)(((double)width/(double)hconvresolution)*72.27+0.5))<<16;
height = ((long)(((double)height/(double)vconvresolution)*72.27+0.5))<<16;
vv += bmap->voffset;
hh += bmap->hoffset;
SetRule(height, width, FALSE);
vv -= bmap->voffset;
hh -= bmap->hoffset;
break;
case LOC_NONE:
break;
default:
Warning("Unknown picture locating!?");
break;
}
}
special_ok();
}
#endif
#endif /* KEIN_DOSPECIAL_FILE */