Category : Word Processors
Archive   : CAWF.ZIP
Filename : FONTFILT.C

 
Output of file : FONTFILT.C contained in archive : CAWF.ZIP
/*
* fontfilt.c - cawf post-processing font filter
*
* V. Abell
* Purdue University Computing Center
*
* Fontfilt filters output from cawf, the C version of Henry Spencer's
* Amazingly Workable (text) Formatter, awf, to produce printer-specific
* codes for bold and italic characters. (Cawf provides modest support
* for documents formatted with nroff's man(7) and ms(7) macros.)
*
* Fontfilt is based on work by and suggestions from Chet Creider
* .
*/


/*
* Copyright (c) 1991 Purdue University Research Foundation,
* West Lafayette, Indiana 47907. All rights reserved.
*
* Written by Victor A. Abell , Purdue
* University Computing Center. Not derived from licensed software;
* derived from work by Chet Creider .
*
* Permission is granted to anyone to use this software for any
* purpose on any computer system, and to alter it and redistribute
* it freely, subject to the following restrictions:
*
* 1. The author is not responsible for any consequences of use of
* this software, even if they arise from flaws in it.
*
* 2. The origin of this software must not be misrepresented, either
* by explicit claim or by omission. Credits must appear in the
* documentation.
*
* 3. Altered versions must be plainly marked as such, and must not
* be misrepresented as being the original software. Credits must
* appear in the documentation.
*
* 4. This notice may not be removed or altered.
*/


/*
* Usage:
*
* fontfilt [-c config] [-d device] [-f font] [file(s)]
*
* where:
*
* -c config specifies an alternate configuration file
* (default directory = CAWFLIB definition or
* CAWFLIB env. variable)
*
* -d device specifies the output device
*
* -f font specifies the font to be used on the
* output device
*
* file(s) the path(s) to the file(s) containing cawf,
* -fe format output
*
* Cawf's font ESCape mode must be used - e. g.,
*
* % cawf -fe -man cawf.1 | fontfilt -dlj3 -flg12
*/


/*
* See fontfilt.cf for a list of supported devices and fonts, or use
* the -h (help) option. The default device is the last device named
* in fontfilt.cf.
*/

#include
#ifdef STDLIB
#include
#endif
#ifdef UNIX
#ifdef USG
#include
#else
#include
#endif
#else
#include
#endif
#include
#include
#include

#include "cawflib.h"


/*
* Local definitions
*/

#define BOLD 'B'
#define CONFIG "fontfilt.cf"
#define ESC 0x1b
#define ITALIC 'I'
#define MAXLINE 512
#define ROMAN 'R'


/*
* Local global variables
*/

static char *Besc = NULL; /* bold font escape string pointer */
static char *Conf = NULL; /* configuration file path */
static char *Defdev = NULL; /* default device name (last name of
* fontfilt.cf */
static char Font = ROMAN; /* current font */
static char *Iesc = NULL; /* italic font escape string pointer */
static char *Pname; /* program name */
static char *Resc = NULL; /* roman font escape string pointer */


/*
* Structure for font definitions
*/

struct font {
char *nm; /* font name */
char *fi; /* font initialization character sequence */
struct font *next; /* next font fot this device */
};


/*
* Device structure
*/

struct dev {
char *nm; /* device name */
struct font *f; /* supported fonts */
char *b; /* bold font ESCape sequence */
char *i; /* italic font ESCape sequence */
char *r; /* Roman font ESCape sequence */
struct dev *next; /* next device */
} *Dp = NULL;


/*
* Externals
*/

extern char *optarg; /* getopt(3) argument pointer */
extern int optind; /* getopt(3) index */


/*
* Function definitions
*/

static char *Convstr();
static int Convfont(), Readcf();
static void Bold(), Getec(), Italic(), Roman();

#ifndef STDLIB
char *getenv(), *malloc(), *strchr(), *strrchr();
#endif


/*
* Main program
*/

main(argc, argv)
int argc; /* argument count */
char *argv[]; /* argument pointers */
{
register int c; /* character buffer */
char *cnm = NULL; /* config file name */
char *dnm = NULL; /* device name */
struct dev *dp; /* device */
char *fnm = NULL; /* font name */
int err = 0; /* argument error count */
int fc, fx; /* file count and index */
struct font *fp; /* font pointer */
FILE *fs; /* file stream */
int help = 0; /* -h status */
struct stat sbuf; /* file stat() buffer */
char *sep; /* separator pointer */
/*
* Save program name.
*/
if ((Pname = strrchr(argv[0], '\\')) != NULL)
Pname++;
else if ((Pname = strrchr(argv[0], '/')) != NULL)
Pname++;
else
Pname = argv[0];
/*
* Process options.
*/
while ((c = getopt(argc, argv, "c:d:f:h")) != EOF) {
switch (c) {
/*
* -c config -- specify configuration file
*/
case 'c':
if (cnm != NULL) {
(void) fprintf(stderr,
"%s: duplicate config name\n", Pname);
err = 1;
} else
cnm = optarg;
break;
/*
* -d device -- specify device
*/
case 'd':
if (dnm != NULL) {
(void) fprintf(stderr,
"%s: duplicate device name\n", Pname);
err = 1;
} else
dnm = optarg;
break;
/*
* -f font -- specify font
*/
case 'f':
if (fnm != NULL) {
(void) fprintf(stderr,
"%s: duplicate font name\n", Pname);
err = 1;
} else
fnm = optarg;
break;
/*
* -h -- request help
*/
case 'h':
help++;
break;
/*
* unknown option
*/
case '?':
err = 1;
}
}
/*
* Handle file arguments.
*/
if (optind >= argc)
fc = 0;
else {
fc = argc;
for (fx = optind; fx < fc; fx++) {
if (stat(argv[fx], &sbuf) != 0) {
(void) fprintf(stderr, "%s: can't find %s\n",
Pname, argv[fx]);
err++;
}
}
}
/*
* Read configuration file.
*/
if (Readcf(cnm) == 0)
err++;
/*
* Validate device name.
*/
if (dnm == NULL)
dnm = Defdev;
for (dp = Dp; dp; dp = dp->next) {
if (strcmp(dnm, dp->nm) == 0)
break;
}
if (dp) {
if (fnm == NULL && dp->f)
fnm = (dp->f)->nm;
} else {
if (dnm == NULL)
(void) fprintf(stderr, "%s: no device specified\n",
Pname);
else
(void) fprintf(stderr, "%s: unknown device: %s\n",
Pname, dnm);
err++;
dp = NULL;
}
/*
* Validate font name.
*/
if (fnm != NULL && dp) {
for (fp = dp->f; fp; fp = fp->next) {
if (strcmp(fnm, fp->nm) == 0)
break;
}
if (fp == NULL) {
(void) fprintf(stderr,
"%s: font %s not defined for device %s\n",
Pname, fnm, dnm);
err++;
}
} else
fp = NULL;
/*
* Go no further if errors have been detected, or help has been requested.
*/
if (err || help) {
(void) fprintf(stderr,
"%s usage: [-c config ] [-d device]", Pname);
(void) fprintf(stderr,
" [-f font] [file(s)]\n");
(void) fprintf(stderr,
"\t-c config specify configuration file path\n");
if (Conf != NULL) {
(void) fprintf(stderr,
"\t (currently using %s)\n", Conf);
}
(void) fprintf(stderr,
"\t-d device specify device name\n");
if (Defdev != NULL) {
(void) fprintf(stderr,
"\t (default = %s)\n", Defdev);
}
(void) fprintf(stderr,
"\t-f font specify font name\n");
(void) fprintf(stderr,
"\tfile(s) specify cawf -fe output files\n");
(void) fprintf(stderr,
"\t (default = standard input)\n");
(void) fprintf(stderr,
"-d -f (first font is default)\n");
for (dp = Dp; dp; dp = dp->next) {
(void) fprintf(stderr, "%-8.8s ", dp->nm);
if ((fp = dp->f) == NULL)
(void) fprintf(stderr, "none\n");
else {
sep = "";
while (fp) {
(void) fprintf(stderr,
"%s%s", sep, fp->nm);
sep = "|";
fp = fp->next;
}
(void) putc('\n', stderr);
}
}
if (err)
exit(1);
exit(0);
}
/*
* Issue font selection, if any, and set up font escape string pointers.
*/
if (fp && fp->fi)
fputs(fp->fi, stdout);
Besc = dp->b;
Iesc = dp->i;
Resc = dp->r;
/*
* Loop through the input files.
*/
fx = optind;
do {

/*
* If there are no files, use standard input (once).
*/
if (fc == 0)
fs = stdin;
else {
/*
* Open the named file.
*/
#ifdef UNIX
if ((fs = fopen(argv[fx], "r")) == NULL)
#else
if ((fs = fopen(argv[fx], "rt")) == NULL)
#endif
{
(void) fprintf(stderr, "%s: can't open %s\n",
Pname, argv[fx]);
exit(1);
}
}
/*
* Read and process the file.
*/
while ( ! feof(fs) && (c = getc(fs)) != EOF) {
switch (c) {

case ESC:
Getec(fs);
if ( ! feof(fs) && (c = getc(fs)) != EOF)
putchar(c);
break;
default:
Roman();
putchar(c);
break;
}
}
if (fc != 0)
(void) fclose(fs);
} while (++fx < fc);
exit(0);
}


/*
* Bold() - set bold font
*/

static void
Bold()

{
if (Font == BOLD)
return;
if (Besc)
fputs(Besc, stdout);
Font = BOLD;
}


/*
* Convfont(dp, s) - convert a font for a device
*
* entry:
* dp = device structure pointer
* s = font definition string -- "name=initialization"
*
* exit:
* return = 0 if errors detected
*/

static int
Convfont(dp, s)
struct dev *dp; /* device structure pointer */
char *s; /* font definition string */
{
char *cp; /* temporary character pointer */
char *fn; /* font name */
struct font *fp; /* font structure pointer */
struct font *tfp; /* temporary font structure pointer */
/*
* Get the font name allocate space for it and allocate space for
* a font structure.
*/
if ((cp = strchr(s, '=')) == NULL) {
(void) fprintf(stderr, "%s: bad %s font line format: %s\n",
Pname, dp->nm, s);
return(0);
}
if ((fn = malloc(cp - s + 1)) == NULL) {
(void) fprintf(stderr, "%s: no space for %s font name %s\n",
Pname, dp->nm, s);
return(0);
}
(void) strncpy(fn, s, cp - s);
fn[cp - s] = '\0';
if ((fp = (struct font *)malloc(sizeof(struct font))) == NULL) {
(void) fprintf(stderr, "%s: no space for %s font struct %s\n",
Pname, dp->nm, fn);
return(0);
}
/*
* Fill in the font structure with the font name and the initialization
* string.
*/
fp->nm = fn;
fp->next = NULL;
if (dp->f == NULL)
dp->f = fp;
else {
for (tfp = dp->f; tfp; tfp = tfp->next) {
if (tfp->next == NULL) {
tfp->next = fp;
break;

}
}
}
if ((fp->fi = Convstr(cp + 1)) == NULL)
return(0);
return(1);
}


/*
* Convstr(s) - convert a string
*
* entry:
* s = input string
*
* exit:
* return = converted string address
* NULL = error
*/

static char *
Convstr(s)
char *s; /* input string */
{
int c; /* character assembly */
char *cp; /* temporary character pointer */
char *em; /* error message */
int i; /* temporary index */
int l; /* length */
char *r; /* result string */
/*
* Make space for the result.
*/
if ((r = malloc(strlen(s) + 1)) == NULL) {
(void) fprintf(stderr, "%s: out of string space at %s\n",
Pname, r);
return(NULL);
}
/*
* Copy the input string to the result, processing '\\' escapes.
*/
for (cp = r; *s;) {
switch (*s) {

case '\\':
s++;
if (*s >= '0' && *s <= '7') {
/*
* '\xxx' -- octal form
*/
for (c = i = 0; i < 3; i++, s++) {
if (*s < '0' || *s > '7') {
em = "non-octal char";
bad_string:
(void) fprintf(stderr,
"%s: %s : %s\n",
Pname, em, r);
return(NULL);
}
c = (c << 3) + *s - '0';
}
if (c > 0377) {
em = "octal char > 0377";
goto bad_string;
}
*cp++ = c;
} else if (*s == 'x') {
/*
* '\xyy' -- hexadecimal form
*/
s++;
for (c = i = 0; i < 2; i++, s++) {
if ( ! isascii(*s) && ! isalpha(*s)
&& ! isdigit(*s)) {
non_hex_char:
em = "non-hex char";
goto bad_string;
}
c = c << 4;
if (*s >= '0' && *s <= '9')
c += *s - '0';
else if ((*s >= 'a' && *s <= 'f')
|| (*s >= 'A' && *s <= 'F'))
c += *s + 10 -
(isupper(*s) ? 'A' : 'a');
else
goto non_hex_char;
}
*cp++ = c;
} else if (*s == 'E' || *s == 'e') {
/*
* '\E' or '\e' -- ESCape
*/
*cp++ = ESC;
} else if (*s == '\0') {
em = "no char after \\";
goto bad_string;
} else
/*
* escaped character (for some reason)
*/
*cp++ = *s++;
break;
/*
* Copy a "normal" character.
*/
default:
*cp++ = *s++;
}
}
*cp = '\0';
return(r);
}


/*
* Getec(fs) - get ESCape follower character
*
* entry:
* fs = file stream
*/

static void
Getec(fs)
FILE *fs; /* file stream */
{
register int c;

if (feof(fs) || (c = getc(fs)) == EOF)
return;
switch (c) {

case ROMAN:
Roman();
break;
case ITALIC:
Italic();
break;
case BOLD:
Bold();
break;
default:
(void) fprintf (stderr,
"%s: unknown escape sequence ESC-0x%x\n",
Pname, c);
break;
}
}


/*
* Italic() - set italic font
*/

static void
Italic()

{
if (Font == ITALIC)
return;
if (Iesc)
fputs(Iesc, stdout);
Font = ITALIC;
}


/*
* Roman() - set Roman font
*/

static void
Roman()

{
if (Font == ROMAN)
return;
if (Resc)
fputs(Resc, stdout);
Font = ROMAN;
}


/*
* Readcf(p) - read configuration file
*
* entry:
* p = configuration file path
*
* exit:
* return = 0 if error detected
*/

static int
Readcf(p)
char *p; /* configuration file path */
{
FILE *fs; /* file stream */
char *dn; /* device name */
struct dev *dp; /* device structure pointer */
int err = 0; /* errror count */
int l; /* length */
char line[MAXLINE]; /* line buffer */
char *s; /* temporary string pointer */
/*
* If a path is supplied, use it.
*/
if (p)
Conf = p;
else {

/*
* Use the CAWFLIB environment if it is defined.
*/
if ((Conf = getenv("CAWFLIB")) == NULL)
Conf = CAWFLIB;
l = strlen(Conf) + 1 + strlen(p ? p : CONFIG) + 1;
if ((s = malloc(l)) == NULL) {
(void) fprintf(stderr, "%s: no space for %s name\n",
Pname,
p ? p : CONFIG);
return(0);
}
(void) sprintf(s, "%s/%s", Conf, p ? p : CONFIG);
Conf = s;
}
/*
* Open the configuration file.
*/
#ifdef UNIX
if ((fs = fopen(Conf, "r")) == NULL)
#else
if ((fs = fopen(Conf, "rt")) == NULL)
#endif
{
(void) fprintf(stderr, "%s: can't open config file: %s\n",
Pname, Conf);
return(0);
}
*line = ' ';
/*
* Look for a device definition line -- a line that begins with a name.
*/
while ( ! feof(fs)) {
if (isascii(*line) && (isspace(*line) || *line == '#')) {
(void) fgets(line, MAXLINE, fs);
continue;
}
if ((s = strrchr(line, '\n')) != NULL)
*s = '\0';
else
line[MAXLINE-1] = '\0';
/*
* Allocate space for the name and the device structure.
*/
if ((dn = malloc(strlen(line) + 1)) == NULL) {
(void) fprintf(stderr,
"%s: no string space for device %s\n",
Pname, line);
return(0);
}
(void) strcpy(dn, line);
if ((dp = (struct dev *)malloc(sizeof(struct dev))) == NULL) {
(void) fprintf(stderr,
"%s: no space for structure for device %s\n",
Pname, dn);
return(0);
}
dp->next = Dp;
Dp = dp;
Defdev = dp->nm = dn;
dp->b = dp->i = dp->r = NULL;
dp->f = NULL;
/*
* Read the parameter lines for the device.
*/
while (fgets(line, MAXLINE, fs) != NULL) {
if ( ! isascii(*line) || *line != '\t')
break;
if ( ! isascii(line[1]) || ! isalpha(line[1])
|| line[2] != '=')
break;
if ((s = strrchr(line, '\n')) != NULL)
*s = '\0';
else
line[MAXLINE-1] = '\0';
switch (line[1]) {
/*
* \tb=
*/
case 'b':
if ((dp->b = Convstr(&line[3])) == NULL)
err++;
break;
/*
* \ti=
*/
case 'i':
if ((dp->i = Convstr(&line[3])) == NULL)
err++;
break;
/*
* \tr=
*/
case 'r':
if ((dp->r = Convstr(&line[3])) == NULL)
err++;
break;
/*
* \tf==
*/
case 'f':
if (Convfont(dp, &line[3]) == 0)
err++;
break;
/*
* ????
*/
default:
(void) fprintf(stderr,
"%s: unknown device %s line %s\n",
Pname, dp->nm, line);
err++;
}
}
}
(void) fclose(fs);
if (err)
return(0);
return(1);
}


  3 Responses to “Category : Word Processors
Archive   : CAWF.ZIP
Filename : FONTFILT.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/