[net.sources] Simple Berkeley Font Editor

jdm@tropix.UUCP (Jeff D. Mullen ) (09/26/84)

: Run this shell script with "sh" not "csh"
PATH=:/bin:/usr/bin:/usr/ucb
export PATH
all=FALSE
if [ $1x = -ax ]; then
	all=TRUE
fi
/bin/echo 'Extracting README'
sed 's/^X//' <<'//go.sysin dd *' >README
		Sfed:  a Simple Font Editor

Sfed is a program which allows the editing of fonts in unix format.
Unlike its counterpart fed(1) at Berkely, which only works on an HP 2648
graphics terminal, sfed will allow the use of any unix-supported terminal
as well as a choice of editors.  This latter is accomplished by setting an
EDITOR environment variable (default editor is vi(1)).

When you invoke sfed(1), you must specify a font file on the command
line.  The program will then prompt by asking you to select a glyph.
It will accept input in the form of either an integer offset into the 
specified font or as a character (in the latter case, sfed(1) converts
the letter into its ascii equivalent, so this feature won't be too useful
for special fonts nor for those in ditroff order--needless to say, it isn't much
of a hack to change this latter fact, though).  In order to edit the
glyphs of digits and other unmentionables, preceeding a character by a
tilde (~) will cause it to convert the character to its ascii equivalent
no-questions-asked.

The actual editing is accomplished by making a file that contains a
pattern of *'s and spaces that represent a glyph (character), allowing
you to edit that, and reading the result back into its own memory.
While it writes out only *'s and spaces, it isn't completely stupid.
It interprets anything that isn't a space or a tab as if it were an
asterisk, and handles tabs as if tab stops were set at every 8th place
along the line.

As for personal testimony, I can assert that this program has already
proved itself invaluable by allowing things like font fixing (just try
adding ff, ffi, or ffl glyphs to the Berkely times-roman font without
an HP 2648 on hand) and the manufacture of a custom company logo in
position 7 of the special font.  It has worked on fonts from Bell Labs
and from Berkely.

			
			Jeff Mullen
			(tropix!jdm)
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 664 README
	/bin/echo -n '	'; /bin/ls -ld README
fi
/bin/echo 'Extracting sfed.1'
sed 's/^X//' <<'//go.sysin dd *' >sfed.1
X.TH SFED 1 local
X.SH NAME
sfed\-simple font editor
X.SH SYNOPSIS
sfed fontname
X.SH DESCRIPTION
X.I Sfed
allows the editing of fonts that are in the Berkeley font format.
It is useful for creating new fonts, changing glyphs (a
X.IR glyph ,
in this context, is the bit pattern of a character in a font),
and adjusting the position at which
X.IR vtroff (1)
prints a glyph relative to the glyphs around it in a piece
of text.
X.PP
The
X.I fontname
argument is the name of the font that is to be edited.
X.PP
X.I Sfed,
when invoked, prompts for a glyph.
It has several mechanisms by which nonstandard glyphs
may be accessed.
Entering a number between 0 and 256 will give the
glyph at that offset from the beginning of the font
(note that this means that the glyphs for the digits
0 through 9 cannot be selected using this method).
For other characters, such as the plus sign, preceding the
glyph's selection with a tilde (~), will cause
X.I sfed
to edit that glyph.
Any glyph from one's terminal keyboard may be selected with the
~ operator.
To quit, type control-D.
X.PP
X.I sfed
works by placing an array of asterisks (*'s) and spaces into
a temporary file along with information about the
glyph's relative placement.
It then invokes
X.IR vi (1)
or the editor specified by the EDITOR environment variable
(see
X.IR environ (5))
on the temporary file and allows one to edit the glyph.
When the editing session is terminated,
X.I sfed
rereads the glyph into a buffer within sfed (there is one
such buffer for each glyph).
It writes these buffers back into the file
X.I fontname
just before it exits.
The temporary file is removed.
X.SH FILES
X.TP 10
X/tmp/fd*
temporary file that holds a glyph's pattern.
X.SH SEE ALSO
environ(5), nroff(1), vfont(5), vfontinfo(1), vi(1)
X.br
The Berkeley Font Catalog
X.br
An Introduction to Display Editing With VI
X.SH DIAGNOSTICS
Sfed:  bad input:  <<CHARACTER>>.  Please try again.
X.br
Sfed:  offset <<NUMBER>> is out of range.  Please try again.
X.br
Complains about not being able to access the temporary or
font files.
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 sfed.1
	/bin/echo -n '	'; /bin/ls -ld sfed.1
fi
/bin/echo 'Extracting sfed.c'
sed 's/^X//' <<'//go.sysin dd *' >sfed.c
X/* sfed font editor written by Jeff Mullen for GCA, Tropel division. */

#include <ctype.h>
#include <stdio.h>
#include <sys/types.h>
#include <vfont.h>

#define YES 1		/* normal return status */
#define NO 0		/* abnormal return status */
#define STOP -1		/* halt/error return code from some routines */
#define TABSTOP 8	/* length of a tabstop, in characters */
#define NUMCHARS 256	/* number of characters in a font */
#define NUMREAD NUMCHARS*sizeof(struct dispatch)
			/* number of bytes to read into dispatch buffers */

#define NUMDIGS 4
	/* max number of digits user may use to specify offset
		into font at which glyph is to be found */

#define NMSIZ 1025
	/* length of string which invokes editor on temporary file
		which holds dot pattern for selected glyph */

#define EDSIZ 512
	/* length of string which holds name of editor which is
		declared as environment variable */

#define BUFSIZ 1024
	/* size of buffer which holds bitwise representation for glyph */

#define BIGGER(X,Y) (X > Y) ? X : Y	/* return larger of two arguments */

typedef struct gylph {	/* glyph descriptor */
	int offset;
	struct dispatch dis;
	char *buf;
		} glyph, *glyphpt;

FILE *fopen();
char *mktemp();

FILE *tmpfl;		/* temporary file to hold human-readable glyph */
char *name;		/* name of above temporary file */

struct header head;	/* header for font */

glyph gltab[NUMCHARS];	/* to hold core image of font */

static int mask[] = {0x80, 0x40, 0x20, 0x10, 8, 4, 2, 1, 0 };
	/* mask used to select each bit of a glyph's representation */

int gwid;	/* width of the current glyph */


swap(p)

X/* swap changes short words from VAX byte order to 68000
	byte order or vice versa */

X/* It was not known at the time of its writing that the
	system routine swab(2) can do the same thing faster */

short *p;

{
*p = ((*p & 0xff) << 8) | ((*p >> 8) & 0xff);
}


nextmask(bits,bytes)
int *bits;		/* individual bit of the byte in question */
int *bytes;		/* the byte in question */

X/* nextmask increments the indexes bits and bytes as appropriate and
	returns the mask of the bit which these values then indicate */

{
register int m;		/* accesses individual bits of glyph's matrix */

if (*bits < 7)
	(*bits)++;
else	/* return to first mask */
	{
	*bits = 0;
	(*bytes)++;	/* keep track of glyph's size */
	}
m = mask[*bits];
return(m);
}


getval(valu)
int *valu;

X/* getval gets an integer from the file file, which is assumed
to be opened for reading */

{
int c,				/* input acceptor */
    i;				/* index into character array */
char d[NUMDIGS * 2];

i = 0;
if ((c = getc(tmpfl)) == EOF)
	{
	*valu = 0;
	return(EOF);
	}
if (!(isdigit(c)) && c != '-')	/* ERROR */
	{
	fprintf(stderr,"sfed:  bad value for dispatch:  %d (%c).  Re-edit glyph.\n",c,c);
	*valu = 0;
	return(STOP);
	}
d[i++] = c;
while ((c = getc(tmpfl)) != '	' && c != '\n' && c != EOF && i < NUMDIGS * 2)
	{
	if (!isdigit(c))
		{
		fprintf(stderr,"sfed:  bad value for dispatch:  %d (%c).  Re-edit glyph.\n",c,c);
		*valu = 0;
		return(STOP);
		}
	d[i++] = c;
	}
if (i == NUMDIGS * 2)
	{
	fprintf(stderr,"sfed:  bad value for dispatch.  Re-edit glyph.\n");
	*valu = 0;
	return(STOP);
	}
d[i] = '\0';
*valu = atoi(d);
return(YES);
}


selectchar()		/* font interpreter */

{
int bad,		/* indicates bad input */
      c;		/* input acceptor, and offset of char in font */
char d[NUMDIGS];	/* string which indicates offset into font,
			if character to edit is indicated by an offset */
register int i;	/* loop index */

printf("\n\n\n\n\n");	/* clear some space on screen */
bad = YES;
while (bad == YES)
	{
	printf("Select glyph (^D = quit):  ");
	if ((bad = getchar()) == EOF)
		{
		printf("^D\n");
		return(STOP);
		}
	d[0] = bad;
	bad = NO;
	if (d[0] != '\n')
		{
		for (i = 1; i < NUMDIGS - 1 && (d[i] = getchar()) != '\n';i++);
		if (d[i] != '\n')
			while ((c = getchar()) != '\n');
		}
	if ((c = d[0]) == '~')		/* glyph of a digit */
		c = d[1];
	else if ((isdigit(c)))		/* offset into font file */
		{
		i = 1;
		while ((c = d[i++]) != '\n' && i < (NUMDIGS - 1))
			{
			if (!(isdigit(c)))	/* ***ERROR*** */
				{
				fprintf(stderr,"sfed:  bad input:  %s%c.  Please try again.\n",d,c);
				bad = YES;
				c = '\n';	/* break loop */
				}
			}
		if(bad == NO)
			{
			d[i] = '\0';
			c = atoi(d);
			}
		}
	else if (!(isalpha(c)))		/* ***ERROR*** */
		{
		bad = YES;
		if (c != '\n')
			fprintf(stderr,"sfed:  bad input:  %c.  Please try again.\n",c);
		}
	if (c < 0 || c >= NUMCHARS)
		{
		fprintf(stderr,"sfed:  offset %d out of range.  Please try again.\n",c);
		bad = YES;
		}
	}
return(c);
}


printchar(indx)

X/* printchar takes the character at position indx in the font file font
	and prints it out in comprehensible form in the temporary
	file name (name is assumed to be a global value).  It also
	assumes that both the font file and temporary file which
	it uses but does not create are closed at the time of its invokation. */

{

int go;			/* return code from temp file close */
char *p;		/* traverses buf */
static int cnt;		/* bit number */
register int i,		/* loop index */
	     m;		/* indexes bit masks of glyphs bitwise matrix */

X/* open temporary file for writing */

if ((tmpfl = fopen(name,"w")) == (FILE *)NULL)
	{
	fprintf(stderr,"sfed: cannot open temporary font file.\n");
	return(NO);
	}

X/* place copy of glyph into file: */
X/*--first, dump dispatch */

fprintf(tmpfl,"width\tup\tdown\tleft\tright\n");
fprintf(tmpfl,"%d\t%d\t%d\t%d\t%d\n",
	gltab[indx].dis.width,
	gltab[indx].dis.up,
	gltab[indx].dis.down,
	gltab[indx].dis.left,
	gltab[indx].dis.right);

if (gltab[indx].dis.nbytes > 0 && gltab)
	{
	if (gltab[indx].dis.up + gltab[indx].dis.down != 0)
		gwid = gltab[indx].dis.nbytes / (gltab[indx].dis.up + gltab[indx].dis.down) * 8;
	else
		gwid = 0;
	p =  gltab[indx].buf;
	cnt = -1;
	for(i = 1; i < 8 * gltab[indx].dis.nbytes; i++)
		{
		if (cnt < 7)
			cnt++;
		else
			{
			p++;
			cnt = 0;
			}
		m = mask[cnt];
		if ((*p & m) == 0)
			putc(' ',tmpfl);
		else
			putc('*',tmpfl);
		if (gwid != 0 && i % gwid == 0)
			putc('\n',tmpfl);
		}
	putc('\n',tmpfl);
	}

X/* close temporary file */

if ((go = fclose(tmpfl)) == EOF)
	{
	fprintf(stderr,"sfed: cannot close temporary font file.\n");
	return(NO);
	}
return(YES);
}


recalc(offset)
int offset;		/* offset of current glyph in font */

{
int   c,		/* to recieve argument(s) from temporary file */
 bitcnt,		/* number of bits placed in current byte */
bytecnt,		/* number of bytes accessed so far */
     up,		/* allow the conversion of the values in the input... */
   down,		/* file from int (in input file) to char (in struct */
   left,		/* dispatch) */
  right,
  width,
 rcodes,		/* return codes */
 nlflag;		/* helps editor account for newline characters */
register int i,		/* loop index */
         index,		/* helps editor account for short lines */
        column,		/* helps account for tabs */
             m;		/* accesses individual bits of glyph's matrix */
char *malloc();

	/* open temporary file for reading */

if ((tmpfl = fopen(name,"r")) == (FILE *)NULL)
	{
	fprintf(stderr,"sfed:  cannot access temporary file.\n");
	return(NO);
	}

X/* read glyph from temporary file */

while((c = getc(tmpfl)) != '\n' && c != EOF);
if ((rcodes = getval(&width)) == STOP || rcodes == EOF)
	return(STOP);
if ((rcodes = getval(&up)) == STOP || rcodes == EOF)
	return(STOP);
if ((rcodes = getval(&down)) == STOP || rcodes == EOF)
	return(STOP);
if ((rcodes = getval(&left)) == STOP || rcodes == EOF)
	return(STOP);
if ((rcodes = getval(&right)) == STOP || rcodes == EOF)
	return(STOP);
gltab[offset].dis.width = width;
gltab[offset].dis.up = up;
gltab[offset].dis.down =down;
gltab[offset].dis.left = left;
gltab[offset].dis.right = right;

X/* count number of bytes in new glyph */

column = index = bytecnt = 0;
nlflag = NO;
bitcnt =  -1;
c = getc(tmpfl);
while (c != EOF)
	if (c != ' ' && c != '\n' && c != '\t')
		{
		nlflag = NO;
		incr(&bitcnt,&bytecnt);
		index++;
		column++;
		c = getc(tmpfl);
		}
	else if (c == '\n')
		{	/* <-- THIS BRACKET IS NEEDED */
		if ((c = getc(tmpfl)) != EOF)
			{
			column = 0;
			if (gwid != 0 && (index % gwid) != 0)
				while ((index % gwid) != 0)
					{
					incr(&bitcnt,&bytecnt);
					index++;
					}
			else if (nlflag == YES)
				{
				incr(&bitcnt,&bytecnt);
				index++;
				if (gwid != 0)
					while ((index % gwid) != 0)
						{
						incr(&bitcnt,&bytecnt);
						index++;
						}
				}
			nlflag = YES;
			}
		}	/* <-- THIS BRACKET IS NEEDED */
	else if (c != ' ')	/* got a tab character */
		{
		while (column % TABSTOP != 0 && (gwid == 0 || column < gwid))
			/* won't expand a tab past end of line */
			{
			index++;
			column++;
			incr(&bitcnt,&bytecnt);
			}
		nlflag = NO;
		c = getc(tmpfl);
		}
	else	/* got a space */
		{
		nlflag = NO;
		incr(&bitcnt,&bytecnt);
		index++;
		column++;
		c = getc(tmpfl);
		}
if (mask[bitcnt] != 0)
	bytecnt++;

if (bytecnt != gltab[offset].dis.nbytes)
	{
	free(gltab[offset].buf);

X/* now allocate a buffer that's EXACTLY the proper size */

	if ((gltab[offset].buf = malloc(bytecnt)) == (char *)NULL)
		{
		fprintf(stderr,"sfed: not enough memory to change glyph.  QUIT.\n");
		return(NO);
		}
	}

X/* set buffer to all 0's */

for (i = 0; i < bytecnt; i++)
	gltab[offset].buf[i] = (char)0;

X/* now go back... */

if ((rcodes = rewind(tmpfl)) == STOP)
	{
	fprintf(stderr,"sfed: cannot read new glyph.\n");
	return(NO);
	}

while ((c = getc(tmpfl)) != '\n');
while ((c = getc(tmpfl)) != '\n');

X/* ... and read glyph into its custom-made buffer */

column = index = bytecnt = 0;
nlflag = NO;
bitcnt =  -1;
c = getc(tmpfl);
while (c != EOF)
	if (c != ' ' && c != '\n' && c != '\t')
		{
		nlflag = NO;
		m = nextmask(&bitcnt,&bytecnt);
		gltab[offset].buf[bytecnt] |= m;
		index++;
		column++;
		c = getc(tmpfl);
		}
	else if (c == '\n')
		{	/* <-- THIS BRACKET IS NEEDED */
		if ((c = getc(tmpfl)) != EOF)
			{
			column = 0;
			if (gwid != 0 && (index % gwid) != 0)
				while ((index % gwid) != 0)
					{
					incr(&bitcnt,&bytecnt);
					index++;
					}
			else if (nlflag == YES)
				{
				incr(&bitcnt,&bytecnt);
				index++;
				if (gwid != 0)
					while ((index % gwid) != 0)
						{
						incr(&bitcnt,&bytecnt);
						index++;
						}
				}
			nlflag = YES;
			}
		}	/* <-- THIS BRACKET IS NEEDED */
	else if (c != ' ')	/* got a tab character */
		{
		while (column % TABSTOP != 0 && (gwid == 0 || column < gwid))
			/* won't expand a tab past end of line */
			{
			index++;
			column++;
			incr(&bitcnt,&bytecnt);
			}
		nlflag = NO;
		c = getc(tmpfl);
		}
	else	/* got a space */
		{
		nlflag = NO;
		incr(&bitcnt,&bytecnt);
		index++;
		column++;
		c = getc(tmpfl);
		}
if (mask[bitcnt] != 0)	/* round to next even byte */
	bytecnt++;

gltab[offset].dis.nbytes = bytecnt;
head.maxx = BIGGER(head.maxx,gltab[offset].dis.left);
head.maxy = BIGGER(head.maxy,gltab[offset].dis.up);

X/* now close temporary file */

if ((rcodes = fclose(tmpfl)) == EOF)
	{
	fprintf(stderr,"sfed:  cannot reclose temporary file\n");
	return(NO);
	}
return(YES);
}


incr(bits,bytes)
int *bits;		/* individual bit of the byte in question */
int *bytes;		/* the byte in question */

X/* nextmask increments the indexes bits and bytes as appropriate and
	returns the mask of the bit which these values then indicate */

{
if (*bits < 7)
	(*bits)++;
else	/* return to first mask */
	{
	*bits = 0;
	(*bytes)++;	/* keep track of glyph's size */
	}
}


readfont(font)
char *font;	/* font to be read */

X/* readfont reads the font into the font table 
   it assumes that the file described by fontp is closed */

{
register int i,		/* loop counter */
	     j;
int fontp;		/* file descriptor of font to be edited */
short val;		/* return code from close */
char *malloc();

X/* open file */

if ((fontp = open(font,0)) == STOP)
	{
	fprintf(stderr,"sfed:  cannot open %s\n",font);
	return(NO);
	}

X/* read font header */

if ((val = read(fontp,&head,sizeof(head))) == STOP)
	{
	fprintf(stderr,"sfed:  cannot read from file %s\n",font);
	return(NO);
	}
swap(&head.magic);	/* change byte order to make font... */
swap(&head.size);	/* ...68000 readable */
swap(&head.maxx);
swap(&head.maxy);
swap(&head.xtend);

X/* read in glyph headers and prepare buffers for inclming bit patterns */

for (i = 0; i < NUMCHARS; i++)
	{
	if ((val == read(fontp,&gltab[i].dis,sizeof(struct dispatch))) == STOP)
		{
		fprintf(stderr,"sfed:  cannot read glyph dispatch\n");
		return(NO);
		}
	swap(&gltab[i].dis.addr);	/* change byte order to make font... */
	swap(&gltab[i].dis.nbytes);	/* ...68000 readable */
	swap(&gltab[i].dis.width);

	if ((gltab[i].buf = malloc(gltab[i].dis.nbytes)) == (char *)NULL)
		{
		fprintf(stderr,"sfed: not enough memory--Quit!\n");
		return(NO);
		}

	for (j = 0;j < gltab[i].dis.nbytes;j++)
		gltab[i].buf[j] = (char)0;
	}

X/* read bit patterns */

for (i = 0;i < NUMCHARS; i++)
	if (gltab[i].dis.nbytes > 0)
		{
		if ((val = lseek(fontp,sizeof(head) + (long)NUMREAD + gltab[i].dis.addr,0)) == STOP)
			{
			fprintf(stderr,"sfed:  cannot find bit pattern\n");
			return(NO);
			}
		if ((val = read(fontp,gltab[i].buf,gltab[i].dis.nbytes)) == STOP)
			{
			fprintf(stderr,"sfed:  cannot read bit pattern\n");
			return(NO);
			}
		}

X/* done reading, so close file */

if ((val = close(fontp)) == STOP)
	{
	fprintf(stderr,"sfed: cannot close %s\n",font);
	return(NO);
	}
return(YES);
}


writefont(font)
char *font;

X/* writefont writes out the current glyph to the current font.
   It assumes that the file font is closed */

{
int buffp,		/* file descriptor of font (buffers) */
    disfp;		/* file descriptor of font (dispatches) */
short mismatch,		/* indicates that a glyph would be overwritten */
	    ok,		/* return codes */
         fudge,		/* # of bytes of a node which would be overwritten */
       savecnt;		/* holds # of bytes in glyph, as said value will be byte
				swapped */
unsigned short addr;	/* address (original gets byte swapped) */
register int i;		/* loop index */

if ((buffp = open(font,2)) == STOP)
	{
	fprintf(stderr,"sfed: cannot write glyphs to %s.\n",font);
	return(NO);
	}
if ((disfp = open(font,2)) == STOP)
	{
	fprintf(stderr,"sfed: cannot write dispatches to %s.\n",font);
	return(NO);
	}

if ((ok = lseek(disfp,(long)sizeof(head),0)) == STOP)
	{
	fprintf(stderr,"sfed: can't find place for dispatches.\n");
	return(NO);
	}
if ((ok = lseek(buffp,(long)(sizeof(head) + NUMREAD),0)) == STOP)
	{
	fprintf(stderr,"sfed: can't find place for glyphs.\n");
	return(NO);
	}

for (addr = i = 0;i < NUMCHARS; i++)
	{

	savecnt = gltab[i].dis.nbytes;
	if (savecnt)
		gltab[i].dis.addr = addr;
	else
		gltab[i].dis.addr = 0;

	/* write dispatch */

	swap(&gltab[i].dis.addr);
	swap(&gltab[i].dis.nbytes);
	swap(&gltab[i].dis.width);

	if ((ok=write(disfp,&gltab[i].dis,sizeof(struct dispatch)))!=sizeof(struct dispatch))
		{
		fprintf(stderr,"sfed: cannot write dispatch.\n");
		return(NO);
		}

	/* write glyph bit pattern/buffer */

	if (savecnt > 0)     /* null glyphs screw up fonts */
		{
		if ((ok = write(buffp,gltab[i].buf,savecnt)) != savecnt)
			{
			fprintf(stderr,"sfed: cannot write glyph %d.\n",i);
			return(NO);
			}
		}
	free(gltab[i].buf);
	addr += (unsigned short)savecnt;
	}

X/* write font header */

if ((ok = lseek(disfp,(long)0,0)) == STOP)
	{
	fprintf(stderr,"sfed: can't find place for font header.\n");
	return(NO);
	}

swap(&head.magic);
swap(&head.size);
swap(&head.maxx);
swap(&head.maxy);
swap(&head.xtend);
if ((ok = write(disfp,&head,sizeof(head))) != sizeof(head))
	{
	fprintf(stderr,"sfed: cannot write font header.\n",font);
	return(NO);
	}


X/* close font file */

if ((ok = close(disfp)) == STOP)
	{
	fprintf(stderr,"sfed: cannot close dispatch file %s.\n",font);
	return(NO);
	}
if ((ok = close(buffp)) == STOP)
	{
	fprintf(stderr,"sfed: cannot close buffer file %s.\n",font);
	return(NO);
	}

return(YES);
}


main (argc,argv)
int argc;
char **argv;

X/* main controls and supervises the subprograms of the editor:
	the font reader, the user interface, the vi editor,
	and the font writer. */

{
int stilgood,		/* indicates enough core for all current glyphs */
          go,		/* flag to terminate program */
     problem,		/* indicates problems in the returned glyph */
	mess;		/* indicates that someone's messed up the temp file */
char edname[NMSIZ],	/* system command to invoke vi on temporary file */
     * editor;		/* name of editor declared as environment variable */
char *getenv();

X/* EXECUTION STARTS HERE */

if (argc != 2)
	{
	fprintf(stderr,"Usage:  sfed font\n");
	exit(1);
	}

if ((go = readfont(argv[1])) == NO)
	exit(1);

umask(0);

X/* make temporary file */

name = mktemp("/tmp/fdXXXXXX");
creat(name,0666);
if ((editor = getenv("EDITOR")) == (char *)NULL)
	sprintf(edname,"vi %s",name);
else
	sprintf(edname,"%s %s",editor,name);

problem = NO;
while(problem == NO && (go = selectchar()) != STOP)
	{
	mess =  NO;
	while (mess == NO)
		{
		if ((stilgood = printchar(go)) == STOP)
			{
			mess = problem = YES;
			}
		system(edname);
		if ((stilgood = recalc(go)) == NO)
			problem = mess = YES;
		if (stilgood != STOP) /* break loop--don't reedit forever */
			mess = YES;
		}
	}
unlink(name);
if ((go = writefont(argv[1])) == NO)
	exit(1);
exit(0);
}	/* THE END */
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 664 sfed.c
	/bin/echo -n '	'; /bin/ls -ld sfed.c
fi