home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Oakland CPM Archive
/
oakcpm.iso
/
cpm
/
list
/
banner03.lbr
/
XBFONT.CZ
/
XBFONT.C
Wrap
Text File
|
1988-01-08
|
12KB
|
385 lines
/* this is bfont.c, by Burt Solomon, roughly 1984 or 1985:
SET YOUR EDITOR TO EXPAND TABS TO 4 SPACES!!!
RELEASE 0.3 NOTES:
Defining a character with "^a >" instead of "<a >" makes it a control
character.
----------------------------------
BS doesn't comment very well, but he sure is clever.
It compiles to a program which:
(1) inputs a file like font.1, and
(2) outputs a file like font1.d;
1987: porting to CP/M, AZTEC C: first tried changing some ints to longs
(character size wider than 16 won't work with int); then discovered that
no manipulations of longs work correctly in AZTEC C.
Please note that my version of AZTEC C dates from 1982, and they may
have improved things since then.
However, severe compiler braindamage requires extensive rewriting.
FORMAT OF (1) input file:
<X >
# #
# #
# #
##
# #
# #
# #
%
#
<Y et cetera
,where the lines heve the following meanings
<x > says "this is the letter x and its width is as specified by the <>"
## lines make a picture of the letter; the number of lines defines the
height of the letter.
% the ## lines that follow describe desenders (sic), as spelled by the
author.
## lines describe the descender.
< start of a new i.d. line ends the letter.
NOTE: allowing more than one letter definition on the same line complicates
the program.
FORMAT OF (2) output:
'C' program source -- declarations for static initializers to be used by
newfont.c -- to be #included there.
#ifdef DEBUG lines added while porting to aztec C 1987
*/
/* #define DEBUG */
#include "stdio.h"
#define nchars 128 /* number of chars in char set*/
/* changed for release 0.3: in a new font, ^A (for example) might
** be used for a special effect: to print some pretty picture...
*/
#define nlines 16 /*number of lines above base line in a banner character*/
#define dlines 3 /*number of lines desending in a banner character*/
#define mxl 19 /*number of lines max. in a banner character*/
#define mxw 32 /*max width of a banner character. */
#define wbytes 4 /* bytes used in a bitmask for this width. */
/* define the states for input to be in */
#define def_next 0
#define def_char 1
#define def_end 2
#define fil_char 3
#define desend 4
int inputchar; /* current character */
int line; /* current line being worked on */
int col; /* column on current line */
char curmap[wbytes]; /* working bitmap. */
char ctrlflag = 0;
struct chr
{
int tablechar; /* this character */
int startcol; /* starting column for this character */
int width; /* width of this character */
int height; /* height of this character */
int descent; /* decesending amount for this character */
char bitmap[mxl*wbytes]; /* one mask for each line */
}
ch[nchars];
main(argc,argp)
char **argp;int argc;
{
int bitnumber; /* number of bit in current scan. */
register int curchar; /* current character being worded on */
int first; /* first character current line */
int last; /* last character current line */
int dflag; /* desender flag */
int state; /* current state of affairs */
int workheight; /* working height of character. */
int bb, findflag;
for (curchar = 0; curchar < nchars; curchar++)
{
ch[curchar].tablechar = -1;
ch[curchar].startcol = ch[curchar].width = ch[curchar].height =
ch[curchar].descent = 0;
}
line = curchar = first = last =
col = dflag = 0; /* guarantee initial values. */
clrcmap(); /* clear working bitmap */
state = def_next; /* current working state */
while ((inputchar = getchar()) != EOF) /* till end of file */
{ if (inputchar == 13) continue; /* don't trust CP/M I/O */
if (inputchar == '!' && col == 0) /* comment in any state. */
while ((inputchar = getchar()) != EOF
&& inputchar != '\n'); /* do nothing. */
switch (state)
{
case def_next: /* start of a new character */
if (inputchar == '<' || inputchar == '^')
{ /* yes it starts a definition. */
ch[curchar].startcol = col; /* curchar starts at column */
state = def_char; /* next get characters name */
ctrlflag = (inputchar == '^');
}
else if (inputchar == '\n' || inputchar == '!')
{ /* end of "start definitions" line. */
if (curchar != first)
{ /* we had at least one full definition. */
state = fil_char; /* get contents of char. */
curchar = first; /* point to first on line. */
} /* else it is a blank line. */
if (inputchar == '!')
{ /* comment. */
while ((inputchar = getchar()) != EOF
&& inputchar != '\n'); /* do nothing. */
}
}
else if (inputchar != ' ') err ("Invalid define character");
break;
case def_char: /* name this character now */
if (inputchar < 0 || inputchar > 128)
{ err ("Invalid character name");
} /* changed release 0.3: allow definitions of funny
** characters. \n and \r will not work of course!
*/
if (ctrlflag) inputchar &= 0x1f;
ctrlflag = 0;
ch[curchar].tablechar = inputchar;
state = def_end;
break;
case def_end: /* mark the size of this character */
if (inputchar == '>')
{ /* found the end. */
ch[curchar].width = col - ch[curchar].startcol + 1;
if (ch[curchar].width > mxw)
err ( "character too wide!" );
dflag = ch[curchar].height = ch[curchar].descent = 0;
clrOmap(curchar); /* clear out its map. */
clrcmap(); /* clear working bitmap */
state = def_next; /* look for another on same line. */
curchar = ++last; /* point to next char. */
}
else if (inputchar != ' ') err ("Invalid define character");
break;
case desend: /* processing the start of desending */
if (dflag < 0)
{ /* waiting for end of "%" line. */
if (inputchar != '\n') err ("Invalid desending character");
dflag = 0;
break;
} /* else fall through to case fil_char */
case fil_char: /* fill in this characters mask now */
if (ch[curchar].startcol == col)
{ /* begin working on curchar. */
clrcmap(); /* clear working bitmap */
bitnumber = ch[curchar].width;
#ifdef DEBUG
printf("start curchar=%d dflag=%d workheight=%d bitnumber=%d\n",
curchar, dflag, workheight, bitnumber);
#endif
}
bitnumber--; /* proceed to next bit in final mask. */
#ifdef DEBUG
printf("curchar=%d dflag=%d workheight=%d bitnumber=%d\n",
curchar, dflag, workheight, bitnumber);
#endif
if (inputchar == '#')
{ /* specifies a position to be set. */
if (bitnumber < 0)
err("unexpected '#', check space between characters\n");
setcmap(bitnumber); /* set bit in curmap. */
}
if (bitnumber == 0)
{ /* width of curchar was used up. */
#ifdef DEBUG
printf("end of curchar=%d dflag=%d workheight=%d\n",
curchar, dflag, workheight);
#endif
if (col != (ch[curchar].startcol + ch[curchar].width -1))
err("Internal error 1!");
bitnumber = -1; /* yes this is a kludge */
workheight = ch[curchar].height + dflag;
cpycmap(curchar, workheight);
curchar++; /* point to next character. */
clrcmap(); /* clear working bitmap */
if (inputchar == ' ' || inputchar == '#') break;
}
if (inputchar == ' ') break;
if (inputchar == '#' && bitnumber >= 0) break;
if (inputchar == '\n')
{ /* end-of-line may be "premature" */
workheight = ch[curchar].height + dflag;
if (tstcmap()) cpycmap(curchar, workheight);
if (state == desend)
{ /* we are processing descenders. */
for (curchar = first; curchar < last; curchar++)
{ /* check all characters defined on these lines. */
workheight = ch[curchar].height + dflag;
if (tstOmap(curchar, workheight))
ch[curchar].descent = dflag + 1;
}
dflag++;
}
else
{ /* not descenders. workheight == ch[].height */
for (curchar = first; curchar < last; curchar++)
if (tstOmap(curchar, 0))
ch[curchar].height++;
}
clrcmap(); /* clear working bitmap */
}
else if (col == 0 && (inputchar == '<' || inputchar == '^'))
{ /* a new set of definitions. */
ctrlflag = (inputchar == '^');
state = def_char;
first = curchar = last;
ch[curchar].startcol = 0;
}
else if (col == 0 && inputchar == '%')
{ /* next line starts descenders. */
dflag = -1;
state = desend;
}
else
{ printf("curchar=%d workheight=%d state=%d\n",
curchar, workheight, state);
printf("first=%d last=%d dflag=%d\n",
first,last,dflag);
printf("ch[curchar].startcol=%d bitnumber=%d\n",
ch[curchar].startcol, bitnumber);
for (bb = 0; bb < curchar; bb++)
{ printf(
"ch[%d].tablechar=%x startcol=%d width=%d height=%d descent=%d\n",
bb, ch[bb].tablechar, ch[bb].startcol,
ch[bb].width, ch[bb].height, ch[bb].descent);
}
err ("Invalid fill character");
}
break;
default:
break;
}
col++;
if (inputchar == '\n')
{
curchar = first;
col = 0;
line++;
}
}
/* write out the table now */
for (inputchar = 0; inputchar < 128; inputchar++)
{ /* scan all possible banner characters in order. */
findflag = 0;
for (curchar = 0; curchar < nchars; curchar++)
if (ch[curchar].tablechar == inputchar)
{ /* curchar was defined. */
findflag = 1;
break;
}
if (findflag)
{ /* character was defined. */
#ifdef DEBUG
printf (" /* character 0x%x was defined: */\n", inputchar);
#endif
printf ("{%d,%d,%d", ch[curchar].width, ch[curchar].height,
ch[curchar].descent);
findflag = (ch[curchar].descent + ch[curchar].height) * wbytes;
for (bb = 0; bb < findflag; bb++)
{
printf(",0x%x%s",ch[curchar].bitmap[bb],
( ( bb % 8 ) == 7 ) ? "\n\t" : " " );
}
if (inputchar == 127 || inputchar <= ' ')
printf("}%s \/* 0x%x */\n",
((inputchar == 127) ? "" : ","),
inputchar);
else
printf("}%s \/* %c *\/\n",
((inputchar == 127) ? "" : ","),
inputchar);
}
else
{ /* undefined character. */
printf ("{0,0,0}%s \/* 0x%x *\/\n",
((inputchar == 127) ? "" : ","),
inputchar);
}
}
}
err(str)
char *str;
{
printf ("%s, inputchar=%x, line=%d, col=%d\n", str, inputchar, line,
col);
exit (1);
}
clrcmap()
{ int i;
for (i = 0; i < wbytes; i++)
curmap[i] = 0;
}
clrOmap(index)
{ int i;
for (i = 0; i < (mxl*wbytes); i++)
ch[index].bitmap[i] = 0;
}
cpycmap(index, entry)
{ int i, base;
base = entry * wbytes;
for (i = 0; i < wbytes; i++)
ch[index].bitmap[base+i] = curmap[i];
}
tstcmap()
{ /* is the working bitmap not all zeroes? */
int i;
for (i = 0; i < wbytes; i++)
if (curmap[i] != 0) return (1);
return (0);
}
tstOmap(index, entry)
{ /* see if a "long" in ch[index].bitmap[] is not all zeroes. */
int i, base;
base = entry * wbytes;
for (i = 0; i < wbytes; i++)
if (ch[index].bitmap[base + i] != 0) return (1);
return (0);
}
setcmap(bitno)
{ /* set a bit in curmap: 0 is curmap[wbytes-1]&1, max curmap[0]&0x80 */
int index;
char localmask;
index = wbytes - 1 - ( bitno / 8 );
/* bitno result (wbytes==4)
0 to 7 (4 - 1 - (0/8)) == 3
8 to 15 (3 - (15/8) == 2
and so forth.
*/
localmask = 1 << ( bitno % 8 );
curmap[index] |= localmask;
}