home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Geek Gadgets 1
/
ADE-1.bin
/
ade-dist
/
unixtex-6.1b-src.tgz
/
tar.out
/
contrib
/
unixtex
/
dvipsk
/
resident.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-09-28
|
20KB
|
713 lines
/* For use with emTeX set FONTPATH to "TEXTFM"
*/
#ifndef FONTPATH
#define FONTPATH "TEXFONTS"
#endif
/*
* This code reads in and handles the defaults for the program from the
* file config.sw. This entire file is a bit kludgy, sorry.
*/
#include "dvips.h" /* The copyright notice in that file is included too! */
#include "paths.h"
#include <kpathsea/c-pathch.h>
#include <kpathsea/pathsearch.h>
#include <kpathsea/tex-file.h>
/*
* This is the structure definition for resident fonts. We use
* a small and simple hash table to handle these. We don't need
* a big hash table.
*/
struct resfont *reshash[RESHASHPRIME] ;
/*
* These are the external routines we use.
*/
extern void error() ;
extern integer scalewidth() ;
extern int tfmload() ;
extern FILE *search() ;
extern shalfword pkbyte() ;
extern integer pkquad() ;
extern integer pktrio() ;
extern Boolean pkopen() ;
extern char *getenv() ;
extern char *newstring() ;
extern int add_header() ;
extern int add_name() ;
extern char *get_name() ;
extern int system() ;
extern void handlepapersize() ;
extern void checkstrings() ;
void getpsinfo() ;
extern void *revlist() ;
/*
* These are the external variables we use.
*/
#ifdef DEBUG
extern integer debug_flag;
#endif /* DEBUG */
extern integer pagecopies ;
extern int overridemag ;
extern long bytesleft ;
extern quarterword *raster ;
extern FILE *pkfile ;
extern char *oname ;
extern Boolean downloadpspk ;
extern integer swmem, fontmem ;
extern Boolean noenv ;
#ifdef FONTLIB
extern char *flipath, *fliname ;
#endif
extern char *paperfmt ;
extern char *nextstring ;
extern char *maxstring ;
extern char *warningmsg ;
extern Boolean disablecomments ;
extern Boolean compressed ;
extern int quiet ;
extern int filter ;
extern Boolean reverse ;
extern Boolean usesPSfonts ;
extern Boolean nosmallchars ;
extern Boolean removecomments ;
extern Boolean safetyenclose ;
extern Boolean dopprescan ;
extern integer maxsecsize ;
extern integer mag ;
extern Boolean sepfiles ;
extern int actualdpi ;
extern int vactualdpi ;
extern int maxdrift ;
extern int vmaxdrift ;
extern char *printer ;
extern char *mfmode ;
extern int mfmode_option;
extern int oname_option;
extern Boolean sendcontrolD ;
extern unsigned lastresortsizes[] ;
extern integer hoff, voff ;
extern struct papsiz *papsizes ;
extern Boolean secure ;
extern integer hpapersize, vpapersize ;
extern int landscape ;
/*
* To maintain a list of document fonts, we use the following
* pointer.
*/
struct header_list *ps_fonts_used ;
/*
* Our hash routine.
*/
int
hash(s)
char *s ;
{
int h = 12 ;
while (*s != 0)
h = (h + h + *s++) % RESHASHPRIME ;
return(h) ;
}
/*
* Reverse the hash chains.
*/
void
revpslists() {
register int i ;
for (i=0; i<RESHASHPRIME; i++)
reshash[i] = (struct resfont *)revlist(reshash[i]) ;
}
/*
* cleanres() marks all resident fonts as not being yet sent.
*/
void
cleanres() {
register int i ;
register struct resfont *p ;
for (i=0; i<RESHASHPRIME; i++)
for (p=reshash[i]; p; p=p->next)
p->sent = 0 ;
}
/*
* The routine that looks up a font name.
*/
struct resfont *
lookup(name)
char *name ;
{
struct resfont *p ;
for (p=reshash[hash(name)]; p!=NULL; p=p->next)
if (strcmp(p->Keyname, name)==0)
return(p) ;
return(NULL) ;
}
/*
* This routine adds an entry.
*/
void
add_entry(TeXname, PSname, specinfo, downloadinfo)
char *TeXname, *PSname, *specinfo, *downloadinfo ;
{
struct resfont *p ;
int h ;
if (PSname == NULL)
PSname = TeXname ;
p = (struct resfont *)mymalloc((integer)sizeof(struct resfont)) ;
p->Keyname = TeXname ;
p->PSname = PSname ;
p->TeXname = TeXname ;
p->specialinstructions = specinfo ;
if (downloadinfo && *downloadinfo)
p->downloadheader = downloadinfo ;
else
p->downloadheader = 0 ;
h = hash(TeXname) ;
p->next = reshash[h] ;
p->sent = 0 ;
reshash[h] = p ;
}
/*
* Now our residentfont routine. Returns the number of characters in
* this font, based on the TFM file.
*/
extern char *infont ;
int
residentfont(curfnt)
register fontdesctype *curfnt ;
{
register shalfword i ;
struct resfont *p ;
/*
* First we determine if we can find this font in the resident list.
*/
if (*curfnt->area)
return 0 ; /* resident fonts never have a nonstandard font area */
if ((p=lookup(curfnt->name))==NULL)
return 0 ;
/*
* This is not yet the correct way to do things, but it is useful as it
* is so we leave it in. The problem: if resident Times-Roman is
* re-encoded, then it will be downloaded as bitmaps; this is not
* right. The solution will be to introduce two types of `<'
* directives, one that downloads fonts and one that downloads
* short headers that are innocuous.
*/
if (p->downloadheader && downloadpspk) {
#ifdef DEBUG
if (dd(D_FONTS))
(void)fprintf(stderr,"Using PK font %s for <%s>.\n",
curfnt->name, p->PSname) ;
#endif /* DEBUG */
return 0 ;
}
/*
* We clear out some pointers:
*/
#ifdef DEBUG
if (dd(D_FONTS))
(void)fprintf(stderr,"Font %s <%s> is resident.\n",
curfnt->name, p->PSname) ;
#endif /* DEBUG */
curfnt->resfont = p ;
curfnt->name = p->TeXname ;
for (i=0; i<256; i++) {
curfnt->chardesc[i].TFMwidth = 0 ;
curfnt->chardesc[i].packptr = NULL ;
curfnt->chardesc[i].pixelwidth = 0 ;
curfnt->chardesc[i].flags = 0 ;
}
add_name(p->PSname, &ps_fonts_used) ;
/*
* We include the font here. But we only should need to include the
* font if we have a stupid spooler; smart spoolers should be able
* to supply it automatically.
*/
if (p->downloadheader) {
char *cp = p->downloadheader ;
char *q ;
infont = p->PSname ;
while (1) {
q = cp ;
while (*cp && *cp != ' ')
cp++ ;
if (*cp) {
*cp = 0 ;
add_header(q) ;
*cp++ = ' ' ;
} else {
add_header(q) ;
break ;
}
infont = 0 ;
}
infont = 0 ;
}
i = tfmload(curfnt) ;
if (i < 0)
i = 1 ;
usesPSfonts = 1 ;
return(i) ;
}
#define INLINE_SIZE (500)
static char was_inline[INLINE_SIZE] ;
void
bad_config() {
error("Error in config file:") ;
(void)fprintf(stderr, "%s\n", was_inline) ;
exit(1) ;
}
/*
* We use this function so we can support strings delimited by
* double quotes with spaces in them. We also accept strings
* with spaces in them, but kill off any spaces at the end.
*/
char *configstring(s, nullok)
char *s ;
int nullok ;
{
char tstr[300] ;
char *p = tstr ;
while (*s && *s <= ' ')
s++ ;
if (*s == '"') {
s++ ;
while (*s != 10 && *s != 0 && *s != '"' && p < tstr+290)
*p++ = *s++ ;
} else {
while (*s && p < tstr+290)
*p++ = *s++ ;
while (*(p-1) <= ' ' && p > tstr)
p-- ;
}
*p = 0 ;
if (p == tstr && ! nullok)
bad_config() ;
return newstring(tstr) ;
}
/* We use this in `getdefaults' to modify the kpathsea structure for the
paths we read. See kpathsea/tex-file.[ch]. */
#define SET_CLIENT_PATH(filefmt, val) \
kpse_format_info[filefmt].client_path = xstrdup (val)
/*
* Now we have the getdefaults routine.
*/
static char *psmapfile = PSMAPFILE ;
void
getdefaults(s)
char *s ;
{
FILE *deffile ;
char PSname[300] ;
register char *p ;
int i, j ;
integer hsiz, vsiz ;
int canaddtopaper = 0 ;
if (printer == NULL) {
if (s) {
strcpy(PSname, s) ;
} else {
strcpy(PSname, DVIPSRC) ;
}
} else {
#if defined(MSDOS) || defined(OS2)
strcpy(PSname, printer) ;
strcat(PSname, ".cfg") ;
#else
strcpy(PSname, "config.") ;
strcat(PSname, printer) ;
#endif
}
if ((deffile=search(configpath,PSname,READ))!=NULL) {
while (fgets(was_inline, INLINE_SIZE, deffile)!=NULL) {
/*
* We need to get rid of the newline.
*/
for (p=was_inline; *p; p++) ;
if (p > was_inline) *(p-1) = 0 ;
if (was_inline[0] != '@')
canaddtopaper = 0 ;
switch (was_inline[0]) {
/*
* Handling paper size information:
*
* If line is empty, then we clear out the paper size information
* we have so far.
*
* If it is `@+', then we add to the current paper size info.
*
* If it is `name hsize vsize', then we start a new definition.
*/
case '@' :
p = was_inline + 1 ;
while (*p && *p <= ' ') p++ ;
if (*p == 0) {
papsizes = 0 ; /* throw away memory */
} else if (*p == '+') {
if (canaddtopaper == 0)
error(
" @+ in config files must immediately following a @ lines") ;
else {
*(nextstring-1) = '\n' ;/* IBM: VM/CMS - changed 10 to "\n" */
p++ ;
while (*p && *p == ' ') p++ ;
strcpy(nextstring, p) ;
nextstring += strlen(p) + 1 ;
}
} else {
struct papsiz *ps ;
ps = (struct papsiz *)mymalloc((integer)sizeof(struct papsiz)) ;
ps->next = papsizes ;
papsizes = ps ;
ps->name = p ;
while (*p && *p > ' ')
p++ ;
*p++ = 0 ;
ps->name = newstring(ps->name) ;
while (*p && *p <= ' ') p++ ;
handlepapersize(p, &hsiz, &vsiz) ;
ps->xsize = hsiz ;
ps->ysize = vsiz ;
ps->specdat = nextstring++ ;
canaddtopaper = 1 ;
}
break ;
case 'a' :
dopprescan = (was_inline[1] != '0') ;
break ;
case 'b':
#ifdef SHORTINT
if (sscanf(was_inline+1, "%ld", &pagecopies) != 1) bad_config() ;
#else
if (sscanf(was_inline+1, "%d", &pagecopies) != 1) bad_config() ;
#endif
if (pagecopies < 1 || pagecopies > 1000)
bad_config() ;
break ;
case 'm' :
#ifdef SHORTINT
if (sscanf(was_inline+1, "%ld", &swmem) != 1) bad_config() ;
#else /* ~SHORTINT */
if (sscanf(was_inline+1, "%d", &swmem) != 1) bad_config() ;
#endif /* ~SHORTINT */
swmem += fontmem ; /* grab headers we've seen already */
break ;
case 'M' :
/* If the user specified a -mode, don't replace it. */
if (!mfmode_option)
mfmode = configstring(was_inline+1, 0) ;
break ;
case 'o' :
if (!oname_option) {
oname = configstring(was_inline+1, 1) ;
if (*oname && oname[strlen(oname)-1] == ':')
sendcontrolD = 1 ; /* if we send to a device, *we* are spooler */
}
break ;
case 'O' :
p = was_inline + 1 ;
handlepapersize(p, &hoff, &voff) ;
break ;
#ifdef FONTLIB
case 'L' :
{
char tempname[300] ;
extern char *fliparse() ;
if (sscanf(was_inline+1, "%s", PSname) != 1) bad_config() ;
else {
flipath = getpath(fliparse(PSname,tempname), flipath);
fliname = newstring(tempname) ;
}
}
break ;
#endif
case 'T' :
if (sscanf(was_inline+1, "%s", PSname) != 1) bad_config() ;
else SET_CLIENT_PATH (kpse_tfm_format, PSname);
break ;
case 'P' :
if (sscanf(was_inline+1, "%s", PSname) != 1) bad_config() ;
else SET_CLIENT_PATH (kpse_pk_format, PSname);
break ;
case 'p' :
p = was_inline + 1 ;
while (*p && *p <= ' ')
p++ ;
if (*p == '+') {
if (sscanf(p+1, "%s", PSname) != 1) bad_config() ;
getpsinfo(PSname) ;
} else {
psmapfile = configstring(was_inline+1, 0) ;
}
break ;
case 'v' : case 'V' :
if (sscanf(was_inline+1, "%s", PSname) != 1) bad_config() ;
else SET_CLIENT_PATH (kpse_vf_format, PSname);
break ;
case 'S' :
if (sscanf(was_inline+1, "%s", PSname) != 1) bad_config() ;
else SET_CLIENT_PATH (kpse_pict_format, PSname);
break ;
case 's':
safetyenclose = 1 ;
break ;
case 'H' :
if (sscanf(was_inline+1, "%s", PSname) != 1) bad_config() ;
else SET_CLIENT_PATH (kpse_dvips_header_format, PSname);
break ;
case '%': case ' ' : case '*' : case '#' : case ';' :
case '=' : case 0 : case '\n' :
break ;
case 'r' :
reverse = (was_inline[1] != '0') ;
break ;
/*
* This case is for last resort font scaling; I hate this, but enough
* people have in no uncertain terms demanded it that I'll go ahead and
* add it.
*
* This line must have numbers on it, resolutions, to search for the
* font as a last resort, and then the font will be scaled. These
* resolutions should be in increasing order.
*
* For most machines, just `300' is sufficient here; on the NeXT,
* `300 400' may be more appropriate.
*/
case 'R':
i = 0 ;
p = was_inline + 1 ;
while (*p) {
while (*p && *p <= ' ')
p++ ;
if ('0' <= *p && *p <= '9') {
j = 0 ;
while ('0' <= *p && *p <= '9')
j = 10 * j + (*p++ - '0') ;
if (i > 0)
if (lastresortsizes[i-1] > j) {
error("last resort sizes (R) must be sorted") ;
bad_config() ;
}
lastresortsizes[i++] = j ;
} else {
if (*p == 0)
break ;
error("! only numbers expected on `R' line in config!") ;
}
}
lastresortsizes[i] = 0 ;
break ;
case 'D' :
if (sscanf(was_inline+1, "%d", &actualdpi) != 1) bad_config() ;
if (actualdpi < 10 || actualdpi > 10000) bad_config() ;
vactualdpi = actualdpi;
break ;
/*
* Execute a command. This can be dangerous, but can also be very useful.
*/
case 'E' :
#ifdef SECURE
error("dvips was compiled with SECURE, which disables E in config") ;
#else
if (secure) {
error("dvips -R option used, which disables E in config") ;
break ;
}
(void)system(was_inline+1) ;
#endif
break ;
case 'K':
removecomments = (was_inline[1] != '0') ;
break ;
case 'U':
nosmallchars = (was_inline[1] != '0') ;
break ;
case 'W':
for (p=was_inline+1; *p && *p <= ' '; p++) ;
if (*p)
warningmsg = newstring(p) ;
else
warningmsg = 0 ;
break ;
case 'X' :
if (sscanf(was_inline+1, "%d", &actualdpi) != 1) bad_config() ;
if (actualdpi < 10 || actualdpi > 10000) bad_config() ;
break ;
case 'Y' :
if (sscanf(was_inline+1, "%d", &vactualdpi) != 1) bad_config() ;
if (vactualdpi < 10 || vactualdpi > 10000) bad_config() ;
break ;
case 'x': case 'y':
if (sscanf(was_inline+1, "%d", &mag) != 1) bad_config() ;
overridemag = (was_inline[0] == 'x') ? 1 : -1 ;
break ;
case 'e' :
if (sscanf(was_inline+1, "%d", &maxdrift) != 1) bad_config() ;
if (maxdrift < 0) bad_config() ;
vmaxdrift = maxdrift;
break ;
case 'q' : case 'Q' :
quiet = (was_inline[1] != '0') ;
break ;
case 'f' : case 'F' :
filter = (was_inline[1] != '0') ;
break ;
case 'h' :
if (sscanf(was_inline+1, "%s", PSname) != 1) bad_config() ;
else (void)add_header(PSname) ;
break ;
case 'i' :
if (sscanf(was_inline+1, "%d", &maxsecsize) != 1)
maxsecsize = 0 ;
sepfiles = 1 ;
break ;
case 'I':
noenv = (was_inline[1] != '0') ;
break ;
case 'N' :
disablecomments = (was_inline[1] != '0') ;
break ;
case 'Z' :
compressed = (was_inline[1] != '0') ;
break ;
case 't' :
if (sscanf(was_inline+1, "%s", PSname) != 1) bad_config() ;
else {
if (strcmp(PSname, "landscape") == 0) {
if (hpapersize || vpapersize)
error(
"both landscape and papersize specified; ignoring landscape") ;
else
landscape = 1 ;
} else
paperfmt = newstring(PSname) ;
}
break ;
default:
bad_config() ;
}
}
(void)fclose(deffile) ;
} else {
if (printer)
{
char msg[1000];
sprintf (msg, "! no config file for printer `%s'", printer);
error(msg);
}
}
}
/*
* If a character pointer is passed in, use that name; else, use the
* default (possibly set) name.
*/
void getpsinfo(name)
char *name ;
{
FILE *deffile ;
register char *p ;
char *specinfo, *downloadinfo ;
char downbuf[500] ;
char specbuf[500] ;
if (name == 0)
name = psmapfile ;
if ((deffile=search(configpath, name, READ))!=NULL) {
while (fgets(was_inline, INLINE_SIZE, deffile)!=NULL) {
p = was_inline ;
if (*p > ' ' && *p != '*' && *p != '#' && *p != ';' && *p != '%') {
char *TeXname = NULL ;
char *PSname = NULL ;
specinfo = NULL ;
downloadinfo = NULL ;
downbuf[0] = 0 ;
specbuf[0] = 0 ;
while (*p) {
while (*p && *p <= ' ')
p++ ;
if (*p) {
if (*p == '"') {
if (specinfo) {
strcat(specbuf, specinfo) ;
strcat(specbuf, " ") ;
}
specinfo = p + 1 ;
}
else if (*p == '<') {
if (downloadinfo) {
strcat(downbuf, downloadinfo) ;
strcat(downbuf, " ") ;
}
while (p[1] == ' ' || p[1] == '\t')
p++;
downloadinfo = p + 1 ;
} else if (TeXname)
PSname = p ;
else
TeXname = p ;
if (*p == '"') {
p++ ;
while (*p != '"' && *p)
p++ ;
} else
while (*p > ' ')
p++ ;
if (*p)
*p++ = 0 ;
}
}
if (specinfo)
strcat(specbuf, specinfo) ;
if (downloadinfo)
strcat(downbuf, downloadinfo) ;
if (TeXname) {
TeXname = newstring(TeXname) ;
specinfo = newstring(specbuf) ;
PSname = newstring(PSname) ;
downloadinfo = newstring(downbuf) ;
add_entry(TeXname, PSname, specinfo, downloadinfo) ;
}
}
}
(void)fclose(deffile) ;
}
checkstrings() ;
}
#if 0
/* Print the path P with label TITLE. */
static void
print_path (title, p)
string title;
string p;
{
fprintf (stderr, "%s path: \t", title);
if (p == NULL)
fprintf (stderr, "(null)\n");
else if (p == NULL)
fprintf (stderr, "(empty)\n");
else
fprintf (stderr, "%s", p);
putc ('\n', stderr);
}
#endif
void
checkenv(which)
int which ;
{
/* Now irrelevant; kpathsea does all the initializations. */
}