|
|
BSD 4.3
/*
* Copyright (c) 1984, 1985 Xerox Corp.
* Handle troff here
*
* note that Troff uses "fat points" of which there are exactly 72 per inch.
*
* HISTORY
* Nov, 1985 Lee Moore, Xerox Webster Research Center
* Created.
*/
#include <stdio.h>
#include <math.h>
#include "stack.h"
#include "token.h"
#include "config.h"
#include "ipmetrics.h"
#include "troff.h"
#define TRUE 1
#define FALSE 0
/* the following value should be choosen so that none of the widths
* is greater than 256
*/
#define UNITWIDTH 5 /* was 10 */
#define MAXSPECIALNAMES 221 /* maximum number of special characters.
* this constant is fixed in Troff
*/
#define public
#define private static
public char *malloc();
public char *DeviceName,
*LibraryDirectory;
struct CharElement {
struct CharElement *Next;
char CharName[3]; };
private struct CharElement *CharSet = NULL;
private int SetOfPointSizes[MAXPOINTSIZE],
FontCount = 0;
public
InitTroff() {
}
public
CleanUpTroff(configChain)
struct FontConfig *configChain; {
struct FontConfig *p;
WriteDescFile(configChain);
WriteFontMapFile(configChain);
WriteInstallFile(configChain);
WriteCleanUpFile(configChain);
for( p = configChain; p != NULL; p = p->Next )
if( !p->SeenFlag )
printf("couldn't find: %s/%s/%s\n",
p->FontPt1, p->FontPt2, p->FontPt3);
}
private
WriteDescFile(configChain)
struct FontConfig *configChain; {
int i;
FILE *deviceFile;
struct FontConfig *p;
if( (deviceFile = fopen("DESC", "w")) == NULL ) {
printf("can't open 'DESC' for writing\n");
exit(1); }
/* output boiler plate */
fprintf(deviceFile, "# describe the '%s' interpress device\n", DeviceName);
fprintf(deviceFile, "res %d\n", MICAS_PER_INCH);
fprintf(deviceFile, "hor 1\n");
fprintf(deviceFile, "vert 1\n");
fprintf(deviceFile, "unitwidth %d\n", UNITWIDTH);
fprintf(deviceFile, "paperwidth %d\n", PAGE_WIDTH_IN_MICAS);
fprintf(deviceFile, "paperlength %d\n", PAGE_HEIGHT_IN_MICAS);
/* output sizes */
fprintf(deviceFile, "sizes ");
for( i = 1; i < MAXPOINTSIZE; i++ )
if( SetOfPointSizes[i] )
fprintf(deviceFile," %d", i);
fprintf(deviceFile, " 0\n");
/* output fonts */
fprintf(deviceFile, "fonts %d ", FontCount);
for( p = configChain; p != NULL; p = p->Next )
if( p->SeenFlag )
fprintf(deviceFile, "%s ", p->TroffName);
fprintf(deviceFile, "\n");
PrintCharSet(deviceFile);
fclose(deviceFile); }
private
WriteFontMapFile(configChain)
struct FontConfig *configChain; {
int i;
FILE *fontMapFile;
struct FontConfig *p;
if( (fontMapFile = fopen(FONTMAPFILENAME, "w")) == NULL ) {
fprintf(stderr, "can't open the file '%s' for writing\n", FONTMAPFILENAME);
return; }
for( p = configChain; p != NULL; p = p->Next )
if( p->SeenFlag )
fprintf(fontMapFile, "%s %s/%s/%s\n", p->TroffName,
p->FontPt1, p->FontPt2, p->FontPt3);
fclose(fontMapFile);
chmod(FONTMAPFILENAME, 0755); }
private
WriteInstallFile(configChain)
struct FontConfig *configChain; {
int i;
FILE *installFile;
struct FontConfig *p;
if( (installFile = fopen(INSTALLNAME, "w")) == NULL ) {
fprintf(stderr, "can't open the file 'install' for writing\n");
return; }
fprintf(installFile, "#! /bin/sh\n");
fprintf(installFile, "if test ! -d %s/fonts/%s\n", LibraryDirectory, DeviceName);
fprintf(installFile, " then\n");
fprintf(installFile, " mkdir %s/fonts/%s\n", LibraryDirectory, DeviceName);
fprintf(installFile, " fi\n");
fprintf(installFile, "if test ! -d %s/fonts/%s/devipress\n", LibraryDirectory, DeviceName);
fprintf(installFile, " then\n");
fprintf(installFile, " mkdir %s/fonts/%s/devipress\n", LibraryDirectory, DeviceName);
fprintf(installFile, " fi\n");
for( p = configChain; p != NULL; p = p->Next )
if( p->SeenFlag )
fprintf(installFile, "cp %s %s/fonts/%s/devipress\n",
p->TroffName, LibraryDirectory, DeviceName);
fprintf(installFile, "cp DESC %s/fonts/%s/devipress\n", LibraryDirectory,
DeviceName);
fprintf(installFile, "cp %s %s/fonts/%s/devipress\n", FONTMAPFILENAME,
LibraryDirectory, DeviceName);
fprintf(installFile, "cd %s/fonts/%s/devipress\n", LibraryDirectory,
DeviceName);
fprintf(installFile, "makedev DESC\n");
fprintf(installFile, "makextdev DESC\n");
fclose(installFile);
chmod(INSTALLNAME, 0755); }
/*
* write a file that rm's all the files created by this program
*/
private
WriteCleanUpFile(configChain)
struct FontConfig *configChain; {
int i;
FILE *cleanupFile;
struct FontConfig *p;
if( (cleanupFile = fopen(CLEANUPNAME, "w")) == NULL ) {
fprintf(stderr, "can't open the file 'cleanup' for writing\n");
return; }
fprintf(cleanupFile, "#! /bin/sh\n");
for( p = configChain; p != NULL; p = p->Next )
if( p->SeenFlag )
fprintf(cleanupFile, "rm %s\n", p->TroffName);
fprintf(cleanupFile, "rm DESC\n");
fprintf(cleanupFile, "rm %s\n", INSTALLNAME);
fprintf(cleanupFile, "rm %s\n", FONTMAPFILENAME);
fprintf(cleanupFile, "rm %s\n", CLEANUPNAME);
fclose(cleanupFile);
chmod(CLEANUPNAME, 0755); }
/*
* called once per font on the stack
*/
public
PerTroffFont(configChain, fontDescVec)
struct FontConfig *configChain;
unsigned char *fontDescVec; {
unsigned char *charMetricsProperty,
*metricsProperty,
*width,
*charMetric;
char iSender[MAXTOKENSIZE],
iCharName[MAXTOKENSIZE],
fileType[MAXTOKENSIZE],
*fontName[3],
iCharSet[MAXTOKENSIZE],
iCharCode[MAXTOKENSIZE];
FILE *descFile,
*modelFile;
struct FontConfig *p;
struct TokenState *ts;
int charSet,
charNumber,
charIndex,
xWidth;
if( !GetFontNameProperty(fontDescVec, fontName) ) {
fprintf(stderr, "ipmetrics: can't get font name\n");
return;
}
if( (charMetricsProperty = GetStringProp("characterMetrics", fontDescVec))
== NULL ) {
printf("ipmetrics: can't find 'characterMetrics' property\n");
return; }
for( p = configChain; p != NULL; p = p->Next ) {
if( !(strcmp(p->FontPt1, fontName[0]) == 0 &&
strcmp(p->FontPt2, fontName[1]) == 0 &&
strcmp(p->FontPt3, fontName[2]) == 0) )
continue;
if( (descFile = fopen(p->TroffName , "w")) == NULL ) {
printf("ipmetrics: can't open %s for writing\n", p->TroffName);
return;}
if( (modelFile = fopen(p->MapFile, "r")) == NULL ) {
printf("ipmetrics: can't open %s for reading\n", p->MapFile);
return;}
p->SeenFlag = TRUE;
/* (void) strcpy(malloc((unsigned) 3), p->TroffName); */
FontCount++;
ts = InitTokenStream(modelFile);
fprintf(descFile, "#\n");
fprintf(descFile, "# %s/%s/%s for Interpress device %s\n", p->FontPt1, p->FontPt2, p->FontPt3, DeviceName);
fprintf(descFile, "name %s\n", p->TroffName);
fprintf(descFile, "internalname %d\n", FontCount);
GetToken(ts, fileType, MAXTOKENSIZE);
if( strcmp(fileType, "special") == 0 )
fprintf(descFile, "special\n");
else
ProcessTroffLigatures(charMetricsProperty, descFile);
fprintf(descFile, "charset\n");
while( !EndOfFile(ts) ) {
GetToken(ts, iCharSet, MAXTOKENSIZE);
sscanf(iCharSet, "%o", &charSet);
GetToken(ts, iCharCode, MAXTOKENSIZE);
sscanf(iCharCode, "%o", &charNumber);
GetToken(ts, iSender, MAXTOKENSIZE);
GetToken(ts, iCharName, MAXTOKENSIZE);
charIndex = Make16BitChar(charSet, charNumber);
/* skip the rest of this loop if it's not in this font */
if( (charMetric =
GetIntegerProp(charIndex, charMetricsProperty)) == NULL )
continue;
if( (width = GetStringProp("widthX", charMetric)) == NULL ){
printf("ipmetrics: can't find widthX property of %d\n",
charIndex);
continue;}
if( gettype(width) != type_number ) {
printf("ipmetrics: width not of type number for %d\n",
charIndex);
continue;}
if( getsubtype(width) != subtype_rational ) {
printf("ipmetrics: width not of subtype number for %d\n",
charIndex);
continue;}
xWidth = (getnumerator(width)*UNITWIDTH*MICAS_PER_INCH +
(getdenominator(width) * POINTS_PER_INCH)/2)/
(getdenominator(width) * POINTS_PER_INCH);
if( xWidth >= 256 )
printf("ipmetrics: warning width >= 256\n");
fprintf(descFile, "%s\t%d\t%s\t", iCharName, xWidth,
iSender);
if( charIndex < 0377 )
fprintf(descFile, "%d\n", charIndex);
else
fprintf(descFile, "0377\t0%o\n", charIndex);
CheckForSpecialness(iCharName);
while( !EndOfLine(ts) ) {
GetToken(ts, iCharName, MAXTOKENSIZE);
fprintf(descFile, "%s\t\"\n", iCharName);
CheckForSpecialness(iCharName);}}
CloseTokenStream(ts);
fclose(descFile);
fclose(modelFile);
}
if( (metricsProperty = GetStringProp("metrics", fontDescVec))
!= NULL ) {
unsigned char *easyProperty;
if( (easyProperty = GetStringProp("easy", metricsProperty))
!= NULL )
ProcessEasy(easyProperty);
}
}
/*
* assume that the font is in XC1-1-1 standard and find the ligatures
* that troff wants
*/
private
ProcessTroffLigatures(charMetricsVec, descFile)
unsigned char *charMetricsVec;
FILE *descFile; {
char ligatureNames[21];
(void) strcpy(ligatureNames, "");
if( GetIntegerProp(Make16BitChar(0360, 044), charMetricsVec) != NULL )
(void) strcat(ligatureNames, " fi");
if( GetIntegerProp(Make16BitChar(0360, 045), charMetricsVec) != NULL )
(void) strcat(ligatureNames, " fl");
if( GetIntegerProp(Make16BitChar(0360, 041), charMetricsVec) != NULL )
(void) strcat(ligatureNames, " ff");
if( GetIntegerProp(Make16BitChar(0360, 042), charMetricsVec) != NULL )
(void) strcat(ligatureNames, " ffi");
if( GetIntegerProp(Make16BitChar(0360, 043), charMetricsVec) != NULL )
(void) strcat(ligatureNames, " ffl");
if( strcmp(ligatureNames, "") != 0 )
fprintf(descFile, "ligatures %s 0\n", ligatureNames);}
/*
* Check to see if a character is special and add it to the "charset"
* in the DESC file if it is.
*/
private
CheckForSpecialness(s)
char *s; {
/* right now, if it two characters long, then it must be special */
if( strlen(s) == 2 )
AddToCharSet(s); }
/*
* add a special character to the set of special characters. The set
* is implemented as a linked list.
*/
private
AddToCharSet(s)
char *s; {
struct CharElement **p,
*q;
p = &CharSet;
while( *p != NULL ) {
if( strcmp(s, (*p)->CharName) == 0 )
return;
p = &(*p)->Next; }
q = (struct CharElement *) malloc((unsigned) sizeof(struct CharElement));
(void) strcpy(q->CharName, s);
q->Next = NULL;
*p = q; }
/*
* print out the list of special characters to the DESC file
*/
private
PrintCharSet(file)
FILE *file; {
int itemsPerLine;
struct CharElement *p;
/* test to see if there is a char. set. ditroff requires this!
* you just can't have a null charset! */
if( CharSet == NULL )
return;
fprintf(file, "charset\n");
itemsPerLine = 0;
for( p = CharSet; p != NULL; p = p->Next ) {
fprintf(file, " %s", p->CharName);
if( itemsPerLine++ > 20 ) {
fputc('\n', file);
itemsPerLine = 0; } }
if( itemsPerLine != 0 )
fputc('\n', file); }
/*
* Process the "easy" property of the "metrics" property. This
* will tell us what (viewing) sizes the font is available in.
*/
private
ProcessEasy(easyProperty)
unsigned char *easyProperty; {
int depth,
i;
unsigned char **array;
if( gettype(easyProperty) != type_vector ||
getsubtype(easyProperty) != subtype_general ) {
printf("ipmetrics: wrong vector type in 'easy'\n");
return; }
depth = getdepth(easyProperty);
array = getvector(easyProperty);
for( i = 0; i < depth; i++ ) {
double *transform,
fPointSize;
int iPointSize;
if( gettype(array[i]) != type_transformation ) {
printf("ipmetrics: transforms not found in 'easy'\n");
return; }
transform = gettransformation(array[i]);
if( transform[0] != transform[4] ) {
printf("ipmetrics: only square transforms in 'easy'\n");
return; }
if( transform[1] != 0 || transform[2] != 0 ||
transform[3] != 0 || transform[5] != 0 ) {
printf("ipmetrics: troff doesn't support rotations\n");
return; }
fPointSize = transform[0]*72*100000/2540;
iPointSize = fPointSize + 0.5;
if( fabs(fPointSize - iPointSize) > .25 ) {
printf("ipmetrics: troff doesn't support fractional points: %f6.2\n", fPointSize);
return; }
SetOfPointSizes[iPointSize] = 1;
free((char *) transform);
}
free((char *) array);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.