v04i060: xtroff -- troff previewer for X11, Part15/18

Dan Heller argv at island.uu.net
Wed Jul 19 19:13:17 AEST 1989


Submitted-by: Mark Moraes <moraes at ai.toronto.edu>
Posting-number: Volume 4, Issue 60
Archive-name: xtroff/part15



#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 15 (of 18)."
# Contents:  xtroff/font.c
# Wrapped by moraes at neat.ai on Thu Jul 13 20:55:22 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'xtroff/font.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xtroff/font.c'\"
else
echo shar: Extracting \"'xtroff/font.c'\" \(29184 characters\)
sed "s/^X//" >'xtroff/font.c' <<'END_OF_FILE'
X/*
X *	SunTroff -  A program to display the output of Device Independent
X *		Troff as a window on a Sun Workstation.
X *
X *	font.c - All the stuff you will ever need to deal with
X *		troff fonts, versatec fonts for the screen and picking
X *		the best font to use when nothing else is available.  
X *		Tries to be intelligent about the best font to use and
X *		to cache all the information it figures out.
X *
X *	Authors - The original version of this program was written by
X *			Richard L. Hyde (Purdue)
X *			David Slattengren (Berkeley)
X *		It was nearly all rewritten, cleaned up and a more elegant
X *		user interface installed by
X *			Malcolm Slaney (Schlumberger Palo Alto Research)
X *
X *	Legalese -  This command was developed as an independent project
X *		to satisfy a need of the author.  This program may contain
X *		bugs and the user is cautioned to independently verify that
X *		the program is suitable for the user's intended purpose.
X *		The program is made available on an ``as is'' basis with
X *		all faults and without any implied or expressed warranties
X *		or support from either the author, Malcolm Slaney, or
X *		Schlumberger Palo Alto Research Laboratory.
X *
X *		I am putting this program in the public domain.  You are
X *		free to use it as you wish.  In return I ask two things.
X *		First, that you do not remove the names of the authors
X *		from this work.  Secondly, if you make changes or
X *		improvements to this program that you pass these back to
X *		the author so that everybody can benefit from the
X *		improvements.
X *
X *					Malcolm Slaney  (December 1986)
X *					Schlumberger Palo Alto Research
X *					3340 Hillview Avenue
X *					Palo Alto, CA 94304
X *					(415) 496-4669
X *					spar!malcolm at decwrl.dec.com
X *					malcolm at ecn.purdue.edu
X *					malcolm at spar.slb.com (Someday)
X */
X
X#include	"suntroff.h"
X#include	<sys/dir.h>
X
X#ifndef SUNTOOLS
Xextern Display *dpy;
Xextern GC gc;
Xextern int SUNRES;
X/*
X *  Maximum number of fonts to list - make it too big and XListFonts
X *  will fail. Make it large enough to list all fonts you have - 1k
X *  should be enough for most installations
X */
X#define MAX_XFONTS	1024
X#endif
X
X#ifdef SUNTOOLS
X/* emalloc - call fatal() if it can't get memory */
Xchar *
Xemalloc(n)
Xint n;
X{
X	char *cp = malloc((unsigned int) n);
X	if (cp == NULL)
X		fatal("Can't allocate memory\n");
X	return(cp);
X}
X#else
Xextern char *XtMalloc();
X#define emalloc(n)	XtMalloc((unsigned int) (n))
X#endif
Xextern char *malloc();
X
X/* rfont () - allocate space and read section of font description
X *
X *	fp - font file
X * 	n - number of bytes to read
X *	file - file name
X *	exit - pointer to table section
X */
Xchar *
Xrfont(fp, n, file)
Xint	fp;
Xint	n;
Xchar	*file;
X{
X	char	*p;
X	extern char *malloc();
X
X	if((p = (char *) malloc((unsigned) n)) == NULL)
X		fatal("Can't allocate space for reading %d bytes of typesetter information.\n", n);
X	if (read(fp, p, n) != n)
X		fatal("Can't read font information from %s.\n", file);
X	return(p);
X}
X		     
X/*
X	Each typesetter has a DESC.out file that contains information about
X	the capabilities of the device.  The InitFonts function reads this
X	file and puts 	the information in a useable format for this program.
X
X	The following information is present in the file:
X	Device			A binary image of the Device structure
X				(see dev.h)
X	
X	PointSizeTable		An array of shorts that map a point size
X				number (used in the output file format) into
X				a real paper point size.
X
X	SpecialCharacterNumber	An array of indexes that can be used to map
X				a special character number (- 128) into the
X				special character name array that follows.
X
X	SpecialCharacterName	Many null terminated strings representing
X				the names of the special characters that are
X				recognized by this device.
X
X	Then for each of the Device.nfonts fonts the following information
X	is present (index by i, the font number).
X	FontInformation[i]:	Lots of miscellaneous information about the
X				font.
X	WidthTable[i]		A pointer to a table of characters indicating
X				the width of each character in the font.  The
X				width listed is that of point size 'unitwidth'
X				(see the Device structure.)
X	Kerning[i]		A pointer to a table of ascender/descender
X				information
X	CodeTable[i]		A pointer to a table giving the code sent to
X				the typesetter to actually produce this
X				character.
X	AsciiTable[i]		A pointer to a table giving the mapping
X				between the ASCII code for a character and
X			        the character number in the device width
X				tables. Note: The first 128-32 entries of this
X				table give the mapping to the printable ascii
X				characters.  Those indices above 128-32 are
X				used for the special characters defined in the
X				SpecialCharacterName[SpecialCharacterNumber]
X				array.
X
XTo look up a character do the following....
XIf the character is a printable ascii simply subtract 32 from its character
Xcode, and look up this number in the AsciiTable.  The number retuned by
Xthe AsciiTable can be used to index into the WidthTable, Kerning and
XCodeTables.
X
XIf the character is a special character then it is necessary to search
Xthrough the names listed in the SpecialCharacterName array until a match
Xis found.  Then add 128-32 to this number and then do the above procedure.
X				
X*/
X
Xstruct Typesetter TypesetterList = {
X	"*********", };
X
Xstruct Typesetter *UserTypesetter = NULL, *OutputTypesetter = NULL,
X		  *DefaultTypesetter = NULL;
X
X#ifndef	SUNTOOLS
X#define DEFAULTFONT "r"
X#else	SUNTOOLS
X#define DEFAULTFONT "R"
X#endif	SUNTOOLS
X
Xstatic char *FontName = NULL;
X	
X						/* The table below is used
X						 * to keep the mapping between
X						 * font positions as used by
X						 * the user and the actual
X						 * font name.
X						 */
Xstatic char FontPosition[NFONTS][MaxFontName+1];
X
X/* LoadDevice - This routine is called by the routine that parses device
X *	control requests in the user's input file.  At this point the
X *	user has specified the desired typesetter.....we first check
X *	check to see if we already know about this one.  If not then we
X *	call the InitFonts() routine to load the description file.
X *
X *	This routine is simply called with the name of the typesetter.
X *	All typesetters are stored in a linked list so we just skip down
X *	the list until we find a match.
X */
Xstruct Typesetter *
XLoadDevice(Device)
Xchar	*Device;
X{
X	struct Typesetter *CurrentTypesetter, *LastTypesetter;
X	extern char *malloc();
X
X	for (CurrentTypesetter = &TypesetterList;
X	     CurrentTypesetter;
X	     CurrentTypesetter = CurrentTypesetter->NextTypesetter){
X		     if (STREQ(Device,CurrentTypesetter->Name)){
X			     return(CurrentTypesetter);
X		     }
X		     LastTypesetter = CurrentTypesetter;
X	     }
X	CurrentTypesetter = (struct Typesetter *)
X	  			malloc(sizeof(*CurrentTypesetter));
X	if (!CurrentTypesetter) {
X		fatal("Can't get space for typesetter description.\n");
X	}
X
X	LastTypesetter->NextTypesetter = CurrentTypesetter;
X	CurrentTypesetter->NextTypesetter = NULL;
X	strncpy(CurrentTypesetter->Name,Device,MAXNAME);
X
X	InitFonts(CurrentTypesetter);
X	return(CurrentTypesetter);
X}
X		     
X/*
X * InitFonts - Given a typesetter structure (that is empty except for the
X * 	name) go out and read the description file (DESC.out) and fill in
X *	all the entries.
X *
X *	This is called by the LoadDevice() routine when a typesetter,
X *	previously unknown to this program, is requested.
X */
XInitFonts(Typesetter)
Xstruct Typesetter *Typesetter;
X{
X	char	temp[BUFSIZ];
X	int	i;
X	int	fp;
X
X	sprintf(temp,"%s/dev%s/DESC.out",FONTDIR,Typesetter->Name);
X	if ((fp = open(temp, O_RDONLY)) == NULL)
X		fatal("Can't open typesetter description %s.\n",temp);
X	
X	if (read(fp, (char *) &Typesetter->Device, sizeof(Typesetter->Device)) 
X						!= sizeof(Typesetter->Device)) {
X		fatal("Can't read header of %s.\n",temp);
X	}
X	
X	Typesetter->PointSizeTable = (short *) rfont(fp,
X		sizeof(short) * (Typesetter->Device.nsizes + 1), temp);
X
X	Typesetter->SpecialCharacterNumber = (short *) rfont(fp,
X		sizeof(short) * Typesetter->Device.nchtab, temp);
X	
X	Typesetter->SpecialCharacterName = (char *) rfont(fp,
X		Typesetter->Device.lchname, temp);
X	
X	Typesetter->WidthTable = (char **)emalloc(NFONTS*sizeof(char *));
X	Typesetter->CodeTable = (char **)emalloc(NFONTS*sizeof(char *));
X	Typesetter->AsciiTable = (char **)emalloc(NFONTS*sizeof(char *));
X
X 	for (i=1;i<=Typesetter->Device.nfonts;i++){
X		int	NumberWidths;
X		
X		Typesetter->FontInformation[i] = (struct Font *) rfont(fp,
X			sizeof(struct Font), temp);
X		NumberWidths = Typesetter->FontInformation[i]->nwfont & 0377;
X
X		Typesetter->WidthTable[i] = rfont(fp, 3 * NumberWidths +
X			Typesetter->Device.nchtab + 128 - 32, temp);
X						/* Skip Kerning Table */
X
X		Typesetter->CodeTable[i] = Typesetter->WidthTable[i] +
X			2 * NumberWidths;
X
X		Typesetter->AsciiTable[i] = Typesetter->WidthTable[i] +
X			3 * NumberWidths;
X
X		SetFontPositionBuffer(i,Typesetter->FontInformation[i]->namefont,
X				Typesetter->FontInformation[i]->intname);
X	}
X
X	close(fp);
X
X						/* Clear out the rest of the
X						   font table. */
X	for (i=Typesetter->Device.nfonts+1;i<NFONTS;i++){
X		Typesetter->FontInformation[i] = (struct Font *) 0;
X	}
X
X						/* Set up the default font
X						   position (0) */
X	Typesetter->FontInformation[0] =
X	    (struct Font *)emalloc(sizeof (struct Font));
X	Typesetter->WidthTable[0] = (char *)emalloc(3 * 255 +
X	    Typesetter->Device.nchtab + 128 - 32);
X	Typesetter->FontInformation[0]->nwfont = 255;
X	Typesetter->CodeTable[0] = Typesetter->WidthTable[0] + 2 * 255;
X	Typesetter->AsciiTable[0] = Typesetter->WidthTable[0] + 3 * 255;
X	Typesetter->FontBitHead.NextFont = NULL;
X	Typesetter->FontBitHead.NextSize = NULL;
X	*(Typesetter->FontBitHead.Name) = NULL;
X
X#ifdef	FONTDEBUG
X	PrintDevice(Typesetter);
X#endif	FONTDEBUG
X}
X
X/* InitTypesetter () - This routine is called in response to the "x i"
X *	device control request in the user's input file.  This routine 
X *	needs to do only two things.  Both of these things could be done
X *	in the LoadDevice routine but we do them here just so we have
X *	something to do in this routine.
X *
X *	First, we use ReadFontDirectory() to figure out which fonts we 
X *	have bits we can use on the screen.
X *
X *	Second, we load the FontPosition table with the default font 
X *	position mapping information.
X */
XInitTypesetter()
X{
X	int	i;
X
X	if (!ReadFontDirectory(UserTypesetter)){
X#ifdef	TYPEDEBUG	
X		printf("Loading the %s DESC.out file\n",DEFAULT_TYPESETTER);
X#endif	TYPEDEBUG		
X		if (!DefaultTypesetter){
X			DefaultTypesetter = LoadDevice(DEFAULT_TYPESETTER);
X			if (!DefaultTypesetter){
X				fatal("Can't read default typesetter DESC\n");
X			}
X		}
X		OutputTypesetter = DefaultTypesetter;
X#ifdef	TYPEDEBUG		
X		printf("Attempting to load bits for %s.\n",
X		       OutputTypesetter->Name);
X#endif	TYPEDEBUG		
X		if (!ReadFontDirectory(DefaultTypesetter)){
X			fatal("Can't get font bits for default typesetter.\n");
X		}
X	} else {
X		OutputTypesetter = UserTypesetter;
X	}
X	
X	for (i=0;i<UserTypesetter->Device.nfonts;i++){
X	        strncpy(FontPosition[i],
X			UserTypesetter->FontInformation[i]->namefont,
X			MaxFontName);
X	}
X	for (i; i<NFONTS; i++){
X		FontPosition[i][0] = 0;
X	}
X		
X#ifdef	FONTDEBUG
X	PrintFontDirectory(OutputTypesetter);
X#endif	FONTDEBUG
X}	
X
X/* SetFontPosition - Given a font number and a font name (from the "x f"
X *	device request) if the font is not already loaded (in that position)
X *      get the font info and store the name in the FontPostion buffer
X */
XSetFontPosition(FontNumber,FontName,InternalFontName)
Xint	FontNumber;
Xchar	*FontName, *InternalFontName;
X{
X	char	temp[BUFSIZ];
X	int	NumberWidths;
X	FILE	*fp;
X	struct	Typesetter	*Typesetter = OutputTypesetter;
X	int	norig;
X	
X
X	if (FontNumber < 0 || FontNumber > NFONTS)
X		fatal("illegal x font command %d %s", FontNumber, FontName);
X#ifdef FONTDEBUG
X	printf("x font %d %s - FontPosition[%d]= %s\n", FontNumber, FontName,
X	    FontNumber, FontPosition[FontNumber]);
X#endif /* FONTDEBUG */
X	if (strncmp(FontPosition[FontNumber], FontName, MaxFontName) == 0)
X		return;
X	if (Typesetter->FontInformation[FontNumber] == 0) {
X#ifdef FONTDEBUG
X		printf("allocating space for %s/dev%s/%s.out\n", FONTDIR,
X		    Typesetter->Name, FontName);
X#endif /* FONTDEBUG */
X		Typesetter->FontInformation[FontNumber] =
X		    (struct Font *)emalloc(sizeof (struct Font));
X		Typesetter->WidthTable[FontNumber] = (char *)emalloc(3 * 255 +
X		    Typesetter->Device.nchtab + 128 - 32);
X		Typesetter->FontInformation[FontNumber]->nwfont = 255;
X		Typesetter->CodeTable[FontNumber] =
X		    Typesetter->WidthTable[FontNumber] + 2 * 255;
X		Typesetter->AsciiTable[FontNumber] =
X		    Typesetter->WidthTable[FontNumber] + 3 * 255;
X	}
X	SetFontPositionBuffer(FontNumber,FontName,InternalFontName);
X
X	/* open the font file */
X	sprintf(temp,"%s/dev%s/%s.out",FONTDIR,Typesetter->Name,
X		FontName);
X	fp = fopen(temp,"r");
X	if (!fp){
X		warning("Can't open typesetter description %s.\n",temp);
X#ifdef FONTDEBUG
X		printf("Can't open typesetter description %s.\n",temp);
X#endif /* FONTDEBUG */
X		return;
X	}
X	norig = Typesetter->FontInformation[FontNumber]->nwfont & 0xff;
X
X	fread((char *) Typesetter->FontInformation[FontNumber],
X	      sizeof(struct Font), 1, fp);
X	NumberWidths = Typesetter->FontInformation[FontNumber]->nwfont & 0377;
X	if (NumberWidths > norig) {
X#ifdef FONTDEBUG
X		printf("allocating space for %s/dev%s/%s.out\n", FONTDIR,
X		    Typesetter->Name, FontName);
X#endif /* FONTDEBUG */
X		Typesetter->WidthTable[FontNumber] = (char *)emalloc(3 * 255 +
X		    Typesetter->Device.nchtab + 128 - 32);
X		norig = 255;
X	}
X	fread(Typesetter->WidthTable[FontNumber], NumberWidths * 3 +
X	    Typesetter->Device.nchtab + 128 - 32, 1, fp);
X	fclose(fp);
X
X	Typesetter->CodeTable[FontNumber] =
X	    Typesetter->WidthTable[FontNumber] + 2 * NumberWidths;
X	Typesetter->AsciiTable[FontNumber] =
X	    Typesetter->WidthTable[FontNumber] + 3 * NumberWidths;
X	Typesetter->FontInformation[FontNumber]->nwfont = norig;
X}
X
X/* SetFontPositionBuffer - Given a font number and a font name, store the
X * name in the font position table
X */
X/*ARGSUSED*/
XSetFontPositionBuffer(FontNumber,FontName,InternalFontName)
Xint	FontNumber;
Xchar	*FontName, *InternalFontName;
X{
X	int	i;
X	char *cp;
X
X	if (FontNumber >= 0 && FontNumber <= NFONTS){
X	        strncpy(FontPosition[FontNumber], FontName, MaxFontName);
X#ifndef SUNTOOLS
X		for(i = 0, cp = FontPosition[FontNumber]; *cp && 
X		 i < MaxFontName; i++, cp++)
X		 	if (isascii(*cp) && islower(*cp))
X				*cp = tolower(*cp);
X#endif
X	}
X}
X
X/* SetFontSize - Given a point size change the current font to this new
X *	font.  Most of the work needed is done by VirtualLoadFont.  But
X *	then VirtualLoadFont doesn't really do any work....it just caches
X *	the information until it is needed later.
X */
XSetFontSize(n)
Xint	n;					/* Actual Point Size */
X{
X	size = n;
X	ditsiz = (float)(SUNRES * n)/75.;
X#ifdef	FONTDEBUG
X	printf("SetFontSize(%d)\n",n);
X	printf("ditsiz=%g\n",ditsiz);
X#endif	/* FONTDEBUG */
X
X	if (FontName == NULL) {
X		if ((FontName = (char *) malloc(sizeof(DEFAULTFONT))) == NULL)
X			fatal("Can't allocate font name space\n");
X		strcpy(FontName, DEFAULTFONT);
X	}
X	VirtualLoadFont(FontName,size);
X}
X
X/* SetFont - Given a font number this routine looks it up in the FontPosition
X *	mapping table.  All the real work is done by the VirtualLoadFont()
X *	routine.
X */
XSetFont(n)
Xint	n;					/* Internal Font Number */
X{
X	if (n >= 0 &&
X	    n < NFONTS){
X		font = n;
X		FontName = FontPosition[n];
X		VirtualLoadFont(FontName,size);
X	}
X}
X
X#ifdef	FONTDEBUG
X
X/* PrintDevice - Print out an ASCII representation of the DESC.out file
X *	so that the correct operation of the InitFonts routine can be
X *	verified.  This also will verify that the DESC.out file and the
X *	dev.h file used to compile this program are compatible.
X */
XPrintDevice(Typesetter)
Xstruct Typesetter *Typesetter;
X{
X	int	i;
X	struct dev	*Device;
X	short	*SpecialCharacterNumber;
X	char	*SpecialCharacterName;
X
X	Device = &Typesetter->Device;
X
X	printf("# Debugging output for suntroff of main device.\n");
X
X	printf("res %d\n",Device->res);
X	printf("hor %d\n",Device->hor);
X	printf("vert %d\n",Device->vert);
X	printf("unitwidth %d\n",Device->unitwidth);
X	printf("paperwidth %d\n",Device->paperwidth);
X	printf("paperlength %d\n",Device->paperlength);
X
X	printf("sizes");
X	for (i=0;i<Device->nsizes;i++){
X		printf(" %d",Typesetter->PointSizeTable[i]);
X	}
X	printf("\n");
X
X	printf("fonts %d",Device->nfonts);
X	fflush(stdout);
X	for (i=1;i<=Device->nfonts;i++){
X		if (Typesetter->FontInformation[i]){
X			printf(" %s",Typesetter->FontInformation[i]->namefont);
X		} else {
X			printf("FontInformation[i=%d] is null.\n",i);
X		}
X	}
X	printf("\n");
X
X	printf("charset\n");
X	
X	SpecialCharacterName = Typesetter->SpecialCharacterName;
X	SpecialCharacterNumber = Typesetter->SpecialCharacterNumber;
X
X	for (i=0;i<Device->nchtab;i++){
X		printf(" %2s",
X		       &SpecialCharacterName[SpecialCharacterNumber[i]]);
X		if (i%10 == 0)
X		  	printf("\n");
X	}
X       	printf("\n");
X
X#if	FONTDEBUG > 1
X	for (i=0;i<=Device->nfonts;i++){
X		PrintFont(Typesetter,i);
X	}
X#endif	FONTDEBUG > 1
X}
X
X/* PrintFont - Print out an ASCII representation for the information in
X *	a font description file.
X */
XPrintFont(Typesetter,i)
Xstruct Typesetter *Typesetter;
Xint	i;
X{
X	int	j;
X	struct Font **FontInformation1;
X	char	**AsciiTable, **CodeTable, **WidthTable;
X	short	*SpecialCharacterNumber;
X	char	*SpecialCharacterName;
X	struct Font **FontInformation;
X
X	FontInformation = Typesetter->FontInformation;
X	AsciiTable = Typesetter->AsciiTable;
X	CodeTable = Typesetter->CodeTable;
X	WidthTable = Typesetter->WidthTable;
X	SpecialCharacterNumber = Typesetter->SpecialCharacterNumber;
X	SpecialCharacterName = Typesetter->SpecialCharacterName;
X
X	if (!FontInformation[i]){
X		printf("There is no font information for font %d.\n",i);
X	}
X	printf("\n#\n");
X	printf("name %s\n",FontInformation[i]->namefont);
X	printf("internalname %s\n",FontInformation[1]->intname);
X	printf("ligatures ");
X	if (FontInformation[i]->ligfont & LFF) printf(" ff");
X	if (FontInformation[i]->ligfont & LFI) printf(" fi");
X	if (FontInformation[i]->ligfont & LFL) printf(" fl");
X	if (FontInformation[i]->ligfont & LFFI) printf(" ffi");
X	if (FontInformation[i]->ligfont & LFFL) printf(" ffl");
X	printf(" 0\ncharset\n");
X	for (j=0;j<FontInformation[i]->nwfont;j++){
X		int	k;
X
X		for (k=0;k<Typesetter->Device.nchtab+128-32;k++){
X			if (AsciiTable[i][k] == j){
X				break;
X			}
X		}
X		if (k < Typesetter->Device.nchtab+128-32){
X			if (k < 128-32){
X				printf("%c\t",k+32);
X			} else {
X				printf("%s\t",
X				       &SpecialCharacterName
X				       [SpecialCharacterNumber[k-(128-32)]]);
X			}
X		} else {
X			printf("Couldn't find %d\t",j);
X		}
X		printf("%d\t%d\t%d\n",
X		       WidthTable[i][j],0,CodeTable[i][j]);
X	}
X	fflush(stdout);
X}
X	  
X
X#endif	FONTDEBUG
X
X/* ReadFontDirectory - Given a Typesetter go out to the BITDIR directory
X *	and figure out which fonts exist.  This information is important
X *	because it will allow the VirtualLoadFont() routine to search through
X *	memory instead of probing the file system every time it wants to
X *	change fonts.  Reading the entire directory is much more efficient
X *	then trying to do random probes looking for the closest match to
X *	a font.
X */
X/* 
X *  For X Windows, the workstation that your display is on, and the
X *  machine you're running xtroff on may be quite different - and might
X *  have access to completely different fonts as a result. So we use
X *  XListFonts()
X */
XReadFontDirectory(Typesetter)
Xstruct Typesetter *Typesetter;
X{
X#ifdef SUNTOOLS
X	DIR	*dfp;
X	struct direct *DirectoryEntry;
X	char	Directory[BUFSIZ];
X#else
X	int nf;
X	char **fontNames;
X/* MAXDEVICE is the maximum length of the name of the device - (eg) devsun */
X#define MAXDEVICE 32
X	char fontfamily[MAXDEVICE+8];
X	char devname[MAXDEVICE];
X	int devnamelen;
X	char *dpi;
X	int dotsperinch;
X#endif
X	char	*FontName, *FontSize, *p;
X	char *FileName;
X	char	*Device;
X
X	Device = Typesetter->Name;
X	if (Typesetter->FontBitHead.NextFont){
X		return(1);
X	}
X	  
X#ifdef SUNTOOLS
X	sprintf(Directory,"%s/dev%s",BITDIR,Device);
X	dfp = opendir(Directory);
X	if (!dfp){
X		return(0);
X	}
X
X	while(DirectoryEntry = readdir(dfp)){
X
X		if (!DirectoryEntry->d_fileno){
X			continue;
X		}
X		FontSize = FontName = DirectoryEntry->d_name;
X#else SUNTOOLS
X	sprintf(devname, "dev%s", Device);
X	devnamelen = strlen(devname);
X	sprintf(fontfamily, "%s.*.*", devname);
X	/*
X	 *  Pity we can't give a better pattern - now if they had
X	 *  regular expressions......
X	 */
X	fontNames = XListFonts(dpy, fontfamily, MAX_XFONTS, &nf);
X	if (nf == 0)
X		return(0);
X	while(--nf >= 0){
X		FontSize = FontName = fontNames[nf] + devnamelen + 1;
X#endif SUNTOOLS
X		while (isalpha(*FontSize)){
X			FontSize++;
X		}
X		if (!*FontSize || FontName == FontSize)
X			continue;			/* No Size */
X		*FontSize = '\0';
X
X		p = ++FontSize;
X		while (isdigit(*p)){
X			p++;
X		}
X#ifdef SUNTOOLS
X		if (p == FontSize || *p != '\0'){
X			continue;
X		}
X		FileName = (char *)malloc(strlen(Directory)+strlen(FontName) 
X					  +strlen(FontSize)+4);
X		if (!FileName){
X			fatal("Can't allocate file name space.\n");
X		}
X		sprintf(FileName,"%s/%s.%s",Directory,FontName,FontSize);
X		InsertFont(Typesetter,FontName,atoi(FontSize),FileName);
X	}
X	closedir(dfp);
X#else SUNTOOLS
X		if (*p == '\0') {
X			dpi = "75";
X			dotsperinch = atoi(dpi);
X			FileName = (char *)emalloc(devnamelen + strlen(FontName) 
X			 + strlen(FontSize) + strlen(dpi) + 4);
X			sprintf(FileName, "%s.%s.%s", devname, FontName, FontSize);
X			InsertFont(Typesetter, FontName,
X			 (dotsperinch * atoi(FontSize) + (SUNRES / 2))
X			  / SUNRES, FileName);
X		} else {
X			if (p == FontSize || *p != '.'){
X				continue;
X			}
X
X			*p++ = '\0';
X			dpi = p;
X			while (isdigit(*p)) {
X				p++;
X			}
X
X			if (p == dpi || *p != '\0') {
X				continue;
X			}
X			dotsperinch = atoi(dpi);
X			FileName = (char *)malloc(devnamelen + strlen(FontName) 
X			 + strlen(FontSize) + strlen(dpi) + 4);
X			if (!FileName){
X				fatal("Can't allocate file name space.\n");
X			}
X			(void) sprintf(FileName, "%s.%s.%s.%s", devname,
X			 FontName, FontSize, dpi);
X			InsertFont(Typesetter, FontName,
X			 (dotsperinch * atoi(FontSize) + (SUNRES / 2))
X			  / SUNRES, FileName);
X		}
X	}
X	XFreeFontNames(fontNames);
X#endif SUNTOOLS
X	return(1);
X}
X
X/* PrintFontDirectory - Print out all the fonts found by the ReadFontDirectory
X *	routine.
X */
XPrintFontDirectory(Typesetter)
Xstruct Typesetter *Typesetter;
X{
X	struct FontBitStruct *FontPointer, *SizePointer;
X	char	*Device;
X
X	Device = Typesetter->Name;
X	printf("Found the following fonts for %s.",Device);
X
X	for (FontPointer = &Typesetter->FontBitHead;
X	     FontPointer;
X	     FontPointer = FontPointer->NextFont){
X		     printf("\n%s\t",FontPointer->Name);
X		     for (SizePointer = FontPointer;
X			  SizePointer;
X			  SizePointer = SizePointer -> NextSize){
X				  printf("%d ",SizePointer->Size);
X			  }
X	     }
X	printf("\n");
X}
X
X/* InsertFont - OK, we've found a file name in the BITDIR that looks like
X *	a proper font name, add it to the font list for the current 
X *	typesetter.  This routine just looks for the proper point in the
X *	two dimensional (name and size) linked list.  AddFont() does
X *	all the real work.
X */
XInsertFont(Typesetter,Name,Size,FileName)
Xstruct Typesetter *Typesetter;
Xchar	*Name, *FileName;
Xint	Size;
X{
X	struct FontBitStruct *FontPointer, *SizePointer, *CurrentFont;
X	struct FontBitStruct *AddFont();
X
X	for (FontPointer = &Typesetter->FontBitHead;
X	     FontPointer;
X	     FontPointer = FontPointer->NextFont){
X		if (STREQ(Name,FontPointer->Name)){
X			for (SizePointer = FontPointer;
X			     SizePointer;
X			     SizePointer = SizePointer->NextSize){
X				     if (SizePointer->Size == Size){
X					     return;
X				     }
X				     CurrentFont = SizePointer;
X			     }
X			CurrentFont->NextSize = AddFont(Name,Size,FileName);
X			return;
X		}
X		CurrentFont = FontPointer;
X	}
X	CurrentFont->NextFont = AddFont(Name,Size,FileName);
X}
X
X/* AddFont - Add a structure to the list of available fonts indicating that
X *	the font Name and Size are available in the indicated FileName.
X */
Xstruct FontBitStruct *
XAddFont(Name,Size,FileName)
Xchar	*Name, *FileName;
Xint	Size;
X{
X
X	struct FontBitStruct *font;
X
X	font = (struct FontBitStruct *)malloc(sizeof(*font));
X	if (!font){
X		fatal("Can't get storage for font cache.\n");
X	}
X	
X	strncpy(font->Name,Name,MaxFontName);
X	font->Size = Size;
X	font->NextFont = font->NextSize = NULL;
X	font->Bits = NULL;
X	font->FileName = FileName;
X	return(font);
X}
X
X/* VirtualLoadFont - Given a desired FontName and PointSize find the font
X *	that we have screen bits for that is as close as possible.  Close
X *	is defined as being the same name and the largest point size that
X *	is smaller than the desired.
X *
X *	If we don't have the correct font name then go ahead and use the
X *	"R" font.  We don't bother giving the user an error message, but
X *	we probably should.
X *
X *	Once we have the best font name, then look down the list until
X *	we can find the best point size match.  If we can't find an exact
X *	match then use the NextBestFont which is the largest point size
X *	that is smaller than the desired (we try to avoid overlapping the
X *	characters).  If we didn't find the exact match then we install
X *	our best approximation as the correct choice so the user only
X *	sees one point size substitution error message.
X */
Xstruct FontBitStruct *
XVirtualLoadFont(FontName,PointSize)
Xchar 	*FontName;				/* Actual Font Name */
Xint	PointSize;				/* Actual Point Size */
X{
X	struct FontBitStruct *NewFont, *NextBestFont, *FindFont(), *LastFont;
X
X	if (!FontName || FontName[0] == 0)
X		fatal("Bad font found in VirtualLoadFont.\n");
X
X#ifndef SUNTOOLS
X	/*
X	 *  X11 has this brain dead convention that all font names must
X	 *  be lower case! Case independent, forsooth...
X	 */
X	{
X	register char *s;
X	for(s = FontName; *s; s++)
X		if (isascii(*s) && isupper(*s)) 
X			*s = tolower(*s);
X	}
X#endif SUNTOOLS
X
X	if (CurrentFont && CurrentFont->Size == PointSize &&
X	 STREQ(CurrentFont->Name, FontName)){
X		return CurrentFont;
X	}
X
X	NewFont = FindFont(FontName);
X	if (!NewFont){
X		NewFont = FindFont(DEFAULTFONT);
X	}
X	if (!NewFont){
X		fatal("Couldn't find either the %s or the R font.",FontName);
X	}
X
X	NextBestFont = NewFont;
X
X#ifdef	FONTDEBUG
X	printf("Loading font name %s, point size %d.\n",
X	       FontName,PointSize);
X	if (CurrentFont)
X		printf("Current font is %s, point size %d.\n",
X			CurrentFont->Name, CurrentFont->Size);
X#endif
X
X	while (NewFont){
X		if (NewFont->Size == PointSize){
X			CurrentFont = NewFont;
X			return(CurrentFont);
X		}
X
X		if (NextBestFont->Size > PointSize &&
X		    NewFont->Size < NextBestFont->Size){
X		        NextBestFont = NewFont;
X
X		}
X		    
X		if (NewFont->Size < PointSize &&
X		    NextBestFont->Size < NewFont->Size){
X			    NextBestFont = NewFont;
X		}
X		LastFont = NewFont;
X		NewFont = NewFont->NextSize;
X	}
X	if (abs(PointSize - NextBestFont->Size) > 1){
X		warning("Couldn't find point size %d of the %s font. Using point size %d instead",
X		      PointSize,FontName, NextBestFont->Size);
X	}
X	/*
X	 * Don't have the correct size....so fake an entry so the user only
X	 * gets one error message.
X	 */
X	if (PointSize != NextBestFont->Size){
X		if (!LastFont ->NextSize){
X			NewFont = AddFont(FontName, PointSize,
X						     NextBestFont->FileName);
X			NewFont->Bits = NextBestFont->Bits;
X			NextBestFont = LastFont->NextSize = NewFont;
X		}
X	}
X	CurrentFont = NextBestFont;
X	return CurrentFont;
X}
X
X/* Findfont - Given a font name, find it on the list of available output
X *	type styles.  This routine is called by the VirtualLoadFont routine.
X */
Xstruct FontBitStruct *
XFindFont(FontName)
Xchar	*FontName;
X{
X	struct FontBitStruct *NewFont;
X
X	if (!OutputTypesetter){
X		fatal("Program error: No typesetter specified.\n");
X	}
X	for (NewFont= &OutputTypesetter->FontBitHead;
X	     NewFont;
X	     NewFont=NewFont->NextFont){
X		if (STREQ(NewFont->Name,FontName)){
X			return(NewFont);
X		}
X	}
X	return(0);
X}
X
X/* LoadFontBits - OK, the user has already requested a point size and
X *	typeface.  The VirtualLoadFont() routine has figured out which
X *	of the available output fonts is best to use.
X *
X *	Now this routine actually goes out and loads the correct (Versatec)
X *	font file.  All the real work is done by the SunTools pf_open()
X *	routine.  Thanks, Sun.
X */
X
XLoadFontBits(){
X#ifdef SUNTOOLS
X	struct pixfont *pf_open();
X
X	if (CurrentFont->Bits){
X		return;				/* Already Loaded */
X	}
X#ifdef	FONTDEBUG	
X	printf("Loading the bits from %s.\n",CurrentFont->FileName);
X#endif	FONTDEBUG	
X
X	CurrentFont->Bits = pf_open(CurrentFont->FileName);
X
X	if (!CurrentFont->Bits){
X		fatal("Can't read fonts from %s.\n",
X		      CurrentFont->FileName);
X	}
X#else SUNTOOLS
X	static Font curxfont = 0;
X	
X	if (CurrentFont->Bits){
X		if (curxfont != CurrentFont->Bits->fid) {
X#ifdef FONTDEBUG
X			printf("changing to font %s\n", CurrentFont->FileName);
X#endif FONTDEBUG
X			curxfont = CurrentFont->Bits->fid;
X			XSetFont(dpy, gc, curxfont);
X		}
X		return;				/* Already Loaded */
X	}
X
X#ifdef FONTDEBUG
X	printf("Loading the bits from %s.\n",CurrentFont->FileName);
X#endif FONTDEBUG
X
X	CurrentFont->Bits = XLoadQueryFont(dpy, CurrentFont->FileName);
X
X	if (!CurrentFont->Bits){
X		fatal("Can't read fonts from %s.\n",
X		      CurrentFont->FileName);
X	}
X	curxfont = CurrentFont->Bits->fid;
X	XSetFont(dpy, gc, curxfont);
X#endif SUNTOOLS
X}
END_OF_FILE
if test 29184 -ne `wc -c <'xtroff/font.c'`; then
    echo shar: \"'xtroff/font.c'\" unpacked with wrong size!
fi
# end of 'xtroff/font.c'
fi
echo shar: End of archive 15 \(of 18\).
cp /dev/null ark15isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 18 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0



More information about the Comp.sources.x mailing list