MAG - CGAZV5N1.ZIP - DLFONT.C

 
Output of file : DLFONT.C contained in archive : CGAZV5N1.ZIP

/*--------------------------------------------------------------------*/
/* D L F O N T . C */
/*--------------------------------------------------------------------*/
/* FILE: DLFONT.C */
/* DESCRIPTION: Version 2 of the HP Font Downloading Program. */
/* (1) Implements partial downloading of a font. */
/* (2) Allows conversion of proportional font to fixed. */
/* COMPILER(s): Borland 2.0+, MS 5.0+, Zortech C/C++ 2.0+ */
/* AUTHOR: Marv Luse, Ithaca Street Software, Inc. */
/* DATE: July, 1990 */
/* (c) 1990 C Gazette. Use freely but acknowledge authorand magazine */
/*--------------------------------------------------------------------*/

#include "stdlib.h"
#include "stdio.h"
#include "string.h"
#include "ctype.h"
#include "dos.h"

#include "hpdesc.h"

/*--------------------------------------------------------------------*/
/* Globally referenced variables... */
/*--------------------------------------------------------------------*/

char *fnt_file, /* font file name */
*prt_port, /* printer port name */
*prt_def = "LPT1"; /* default printer port name */

FILE *fnt_fp, /* font stream */
*prt_fp; /* printer stream */

int font_id, /* font id number */
make_fixed, /* flag - convert to monospaced */
select_fnt, /* flag - select this font */
reset_prt, /* flag - reset printer */
is_perm, /* flag - perm font */
cellW, cellH, /* font's design cell dimensions */
cur_chr; /* ascii value of current char */

double cpi; /* if nonzero, force this pitch */

long bytes_read, /* read from font */
bytes_written; /* sent to printer */

#define BUF_SIZ 512
#define ESQ_SIZ 512

char io_buf[BUF_SIZ], /* file i/o buffer */
esq_buf[ESQ_SIZ+1], /* escape seq holding area */
dld_chr[256]; /* flags - set ==> download */

/* macro to test for a capital letter - indicates end of sequence */
#define isTERMCHR( c ) ( ((c>=64) && (c<=94)) ? 1 : 0 )

/* macro to reverse bytes in a word (signed or unsigned) */
#define REV_WRD( w ) ( ((w >> 8) & 0xFF) | (w << 8) )

/* escape sequence types to be processed */
#define UNUSED_SEQ 0 /* sequence ignored */
#define DEFINE_FNT 1 /* font descriptor */
#define DEFINE_CHR 2 /* char descriptor */
#define DEFINE_ASC 3 /* set char's ascii code */

/*--------------------------------------------------------------------*/
/* Escape sequences... */
/*--------------------------------------------------------------------*/

char *pRESET = "\033E"; /* printer reset */
char *fPERM = "\033*c5F"; /* make font permanent */
char *fSETID = "\033*c???D"; /* set font id to ??? */
char *fSELECT = "\033(???X"; /* make font ??? primary */

/*--------------------------------------------------------------------*/
/* Print a message and exit the pgm... */
/*--------------------------------------------------------------------*/

void exit_pgm( int retc, char *msg )
{
printf( "\n%s", msg );
exit( retc );
}

/*--------------------------------------------------------------------*/
/* Explain ourselves... */
/*--------------------------------------------------------------------*/

void explain_pgm( void )
{
printf( "\n" );
printf( "\nusage: DLFONT font_file [prt_port] [switches]" );
printf( "\n" );
printf( "\n font_file = path to an HP font file" );
printf( "\n prt_port = printer location (def = LPT1)" );
printf( "\n" );
printf( "\nswitches: /F = convert font to fixed width" );
printf( "\n /In = set font id to n (def = 1)" );
printf( "\n /P = make font permanent (def = temp)" );
printf( "\n /R = reset printer before download" );
printf( "\n /S = select font (make current)" );
printf( "\n /Wd.d = force width (pitch) to d.d cpi" );
printf( "\n /{xxx} = specify chars to download" );
}

/*--------------------------------------------------------------------*/
/* Set variables and override from command line... */
/*--------------------------------------------------------------------*/

void process_args( int argc, char *argv[] )
{
int i, j;
char sw, *swval;

/* set defaults */
fnt_file = NULL;
prt_port = prt_def;
font_id = 1;
is_perm = 0;
reset_prt = 0;
select_fnt = 0;
make_fixed = 0;
cpi = 0.0;
for( j = 0; j < 256; j++ )
dld_chr[j] = 1;

/* inspect command line */
for( i = 1; i < argc; i++ )
{
/* a switch */
if( (*argv[i] == '/') || (*argv[i] == '-') )
{
sw = *(argv[i] + 1);
swval = argv[i] + 2;

switch( toupper(sw) )
{
case 'F' : /* force fixed width font */
make_fixed = 1;
break;

case 'I' : /* set font id */
sscanf( swval, "%d", &font_id );
break;

case 'P' : /* make font permanent */
is_perm = 1;
break;

case 'R' : /* reset printer */
reset_prt = 1;
break;

case 'S' : /* select font at printer */
select_fnt = 1;
break;

case 'W' : /* force width of d.d cpi */
sscanf( swval, "%lf", &cpi );
break;

case '{' : /* specify chars to download */
for( j = 0; j < 256; j++ )
dld_chr[j] = 0;
while( *swval && (*swval != '}') )
dld_chr[*swval++] = 1;
break;

default : /* undefined */
printf( "undefined switch '%s'", argv[i] );
exit_pgm( 4, "program terminated" );
break;
}
}
else if( fnt_file == NULL ) /* font file name */
fnt_file = argv[i];
else /* printer destination */
prt_port = argv[i];
}

/* make sure we have a font name */
if( fnt_file == NULL )
exit_pgm( 8, "Error - no font file name specified" );

/* check for a valid font id */
if( (font_id < 0) || (font_id > 999) )
exit_pgm( 8, "Error - specify font id in range 0-999" );
}

/*--------------------------------------------------------------------*/
/* Use DOS function 44h (IOCTL) to set raw mode if a char device... */
/*--------------------------------------------------------------------*/

void set_binary_mode ( FILE *fptr )
{
int hand;
union REGS r;

/* get file handle */
hand = fileno(fptr);

/* get device info */
r.h.ah = 0x44;
r.h.al = 0x00;
r.x.bx = hand;
r.x.dx = 0;
int86(0x21, &r, &r);

/* check the device... */
if( (r.h.dl & 0x80) ) /* char device ? */
{
if( ! (r.h.dl & 0x20) ) /* cooked mode ? */
{
r.h.ah = 0x44;
r.h.al = 0x01;
r.x.bx = hand;
r.h.dh = 0x00;
r.h.dl |= 0x20; /* set raw mode */
int86(0x21, &r, &r);
}
}
}

/*--------------------------------------------------------------------*/
/* Open files, set device mode... */
/*--------------------------------------------------------------------*/

void open_files( void )
{
fnt_fp = fopen( fnt_file, "rb" );
if( fnt_fp == NULL )
exit_pgm( 8, "Could not find font file" );
prt_fp = fopen( prt_port, "wb" );
if( prt_fp == NULL )
exit_pgm( 8, "Error opening printer" );
set_binary_mode( prt_fp );
printf( "\ndownloading '%s' to '%s'...", fnt_file, prt_port );
}

/*--------------------------------------------------------------------*/
/* Close all files... */
/*--------------------------------------------------------------------*/

void close_files( void )
{
fclose( fnt_fp );
fclose( prt_fp );
printf( "done" );
}

/*--------------------------------------------------------------------*/
/* Modify fd and save values needed to convert font to fixed... */
/*--------------------------------------------------------------------*/

void modify_fd( font_desc *fd )
{
int w;

/* if forcing fixed-width, set fd flag */
if( make_fixed )
fd->proportional = 0;

/* save cell dimensions in quarter-dot units */
cellW = REV_WRD( fd->cell_width ) * 4;
cellH = REV_WRD( fd->cell_height ) * 4;

/* if cpi is nonzero, force specified pitch */
if( cpi > 0.0 )
{
/* save actual cell width */
w = cellW;

/* compute required cell width */
cellW = (int) ((1200.0 / cpi) + 0.5);

/* design width must be at least this value, */
/* otherwise char defs will be invalidated. */
/* update value if needed (units = dots). */
if( w < cellW )
fd->cell_width = REV_WRD( (cellW+3)/4 );
}

/* set font's default pitch from cell size. */
/* note that pitch is expressed in qtr-dots, */
/* and indicates distance, not cpi. */

if( fd->orient ) /* landscape font */
fd->pitch = REV_WRD( cellH );
else /* portrait font */
fd->pitch = REV_WRD( cellW );
}

/*--------------------------------------------------------------------*/
/* Modify cd for use as monospaced font... */
/*--------------------------------------------------------------------*/

void modify_cd( char_desc *cd )
{
int ofs, wid;

if( cd->orient ) /* char is for landscape mode */
{
wid = REV_WRD( cd->char_height );
/* ofs is in dots, cellH is in qtr-dots */
ofs = ((cellH>>2) + wid) / 2;
cd->delta_x = REV_WRD( cellH );
cd->top_ofs = REV_WRD( ofs );
}
else /* char is for portrait mode */
{
wid = REV_WRD( cd->char_width );
/* ofs is in dots, cellW is in qtr-dots */
ofs = ((cellW>>2) - wid) / 2;
cd->delta_x = REV_WRD( cellW );
cd->left_ofs = REV_WRD( ofs );
}
}

/*--------------------------------------------------------------------*/
/* Send prefix escape sequences to the printer... */
/*--------------------------------------------------------------------*/

void send_pfx( void )
{
/* if requested, reset printer */
if( reset_prt )
if( fwrite( pRESET, strlen(pRESET), 1, prt_fp ) != 1 )
exit_pgm( 8, "Error writing to printer" );

/* set id for font to follow (if not writing to disk ) */
if( strchr( prt_port, '.' ) == NULL )
{
sprintf( fSETID, "\033*c%dD", font_id );
if( fwrite( fSETID, strlen(fSETID), 1, prt_fp ) != 1 )
exit_pgm( 8, "Error writing to printer" );
}

}

/*--------------------------------------------------------------------*/
/* Send suffix escape sequences to the printer... */
/*--------------------------------------------------------------------*/

void send_sfx( void )
{
/* if requested, make font permanent */
if( is_perm )
if( fwrite( fPERM, strlen(fPERM), 1, prt_fp ) != 1 )
exit_pgm( 8, "Error writing to printer" );

/* if requested, make font the current font */
if( select_fnt )
{
sprintf( fSELECT, "\033(%dX", font_id );
if( fwrite( fSELECT, strlen(fSELECT), 1, prt_fp ) != 1 )
exit_pgm( 8, "Error writing to printer" );
}
}

/*--------------------------------------------------------------------*/
/* Skip next nbytes from input... */
/*--------------------------------------------------------------------*/

void skip_inp( int nbytes )
{
int nout;

while( nbytes > 0 )
{
nout = (nbytes > BUF_SIZ) ? BUF_SIZ : nbytes;
nbytes -= nout;
if( fread(io_buf, 1, nout, fnt_fp) != nout )
exit_pgm( 8, "Unexpected EOF reading font file" );
bytes_read += nout;
}
}

/*--------------------------------------------------------------------*/
/* Copy next nbytes from input to printer... */
/*--------------------------------------------------------------------*/

void copy_inp( int nbytes )
{
int nout;

while( nbytes > 0 )
{
nout = (nbytes > BUF_SIZ) ? BUF_SIZ : nbytes;
nbytes -= nout;
if( fread(io_buf, 1, nout, fnt_fp) != nout )
exit_pgm( 8, "Unexpected EOF reading font file" );
bytes_read += nout;
if( fwrite(io_buf, 1, nout, prt_fp) != nout )
exit_pgm( 8, "Error writing to printer" );
bytes_written += nout;
}
}

/*--------------------------------------------------------------------*/
/* Read nbytes from input into passed buffer... */
/*--------------------------------------------------------------------*/

void read_buf( void *buf, int nbytes )
{
if( fread( buf, 1, nbytes, fnt_fp ) != nbytes )
exit_pgm( 8, "Unexpected EOF reading font file" );
bytes_read += nbytes;
}

/*--------------------------------------------------------------------*/
/* Send passed buffer to printer... */
/*--------------------------------------------------------------------*/

void send_buf( void *buf, int nbytes )
{
if( fwrite( buf, 1, nbytes, prt_fp ) != nbytes )
exit_pgm( 8, "Error writing to printer" );
bytes_written += nbytes;
}

/*--------------------------------------------------------------------*/
/* Determine esq type and its numeric argument... */
/*--------------------------------------------------------------------*/

void get_esq_values( char esq_buf[], int *type, int *parm )
{
int i;
char c1, c2, clast;

/* determine type */
c1 = esq_buf[1];
c2 = esq_buf[2];
i = 0;
while( esq_buf[i] ) i++;
clast = esq_buf[i-1];
if( (c1==')') && (c2=='s') && (clast=='W') )
*type = DEFINE_FNT;
else if( (c1=='(') && (c2=='s') && (clast=='W') )
*type = DEFINE_CHR;
else if( (c1=='*') && (c2=='c') && (clast=='E') )
*type = DEFINE_ASC;
else
*type = UNUSED_SEQ;

/* get the sequence's value field */
*parm = 0;
i = 0;
while( (esq_buf[i]) && (! isdigit(esq_buf[i])) ) i++;
if( isdigit(esq_buf[i]) )
sscanf( esq_buf+i, "%d", parm );
}

/*--------------------------------------------------------------------*/
/* Process the escape seq now in the buffer... */
/*--------------------------------------------------------------------*/

void do_esq( char esq_buf[] )
{
font_desc fd;
char_desc cd;
int esq_type, esq_parm;

/* get the escape sequence type and the imbedded value field */
get_esq_values( esq_buf, &esq_type, &esq_parm );

bytes_read += strlen( esq_buf );

/* process the sequence */
switch( esq_type )
{
case DEFINE_FNT: /* font descriptor */

/* send the sequence */
send_buf( esq_buf, strlen(esq_buf) );

/* if converting to fixed, read-modify-write */
if( make_fixed )
{
/* read the descriptor */
read_buf( &fd, sizeof(font_desc) );
/* modify as necessary */
modify_fd( &fd );
/* send the descriptor */
send_buf( &fd, sizeof(font_desc) );
/* send any trailing info */
if( esq_parm > sizeof(font_desc) )
copy_inp( esq_parm-sizeof(font_desc) );

}
/* otherwise, just send the descriptor */
else
copy_inp( esq_parm );
break;

case DEFINE_CHR: /* char descriptor */

if( dld_chr[cur_chr] ) /* are we using this char ? */
{
/* send the sequence */
send_buf( esq_buf, strlen(esq_buf) );

/* if converting to fixed, read-modify-write */
if( make_fixed )
{
/* read the descriptor */
read_buf( &cd, sizeof(char_desc) );
/* modify as necessary */
modify_cd( &cd );
/* send the descriptor */
send_buf( &cd, sizeof(char_desc) );
/* send the bitmap which follows */
if( esq_parm > sizeof(char_desc) )
copy_inp( esq_parm-sizeof(char_desc) );
}
/* otherwise, just send the descriptor */
else
copy_inp( esq_parm );
}
else
/* skip the descriptor */
skip_inp( esq_parm );
break;

case DEFINE_ASC: /* specify character code ADE */

cur_chr = esq_parm;

/* send the sequence */
if( dld_chr[cur_chr] )
send_buf( esq_buf, strlen(esq_buf) );
break;

case UNUSED_SEQ: /* unexpected sequence - ignore it */

printf( "Unexpected sequence '%s' ignored", esq_buf );
send_buf( esq_buf, strlen(esq_buf) );
break;
}
}

/*--------------------------------------------------------------------*/
/* Read the next esc seq from the font file... */
/*--------------------------------------------------------------------*/

int get_esq( char esq_buf[], int buf_len )
{
int i, nbytes;

nbytes = 0;
while( (i=fgetc(fnt_fp)) != EOF )
{
esq_buf[nbytes] = (char) i;
nbytes++;
/* capital letter signals last character in sequence */
if( isTERMCHR( i ) ) break;
if( nbytes == buf_len )
exit_pgm( 8, "Error - escape sequence buffer overflow" );
}

/* validity check - first character should be decimal 27 */
if( (nbytes > 0) && (esq_buf[0] != 27) )
exit_pgm( 8, "Error - escape sequence expected but not found" );

/* add a terminating null */
esq_buf[nbytes] = 0;
return( nbytes );
}

/*--------------------------------------------------------------------*/
/* Send the font file to the printer... */
/*--------------------------------------------------------------------*/

void send_fnt( void )
{
while( get_esq( esq_buf, ESQ_SIZ ) > 0 )
do_esq( esq_buf );
}

/*--------------------------------------------------------------------*/
/* M A I N */
/*--------------------------------------------------------------------*/

void main ( int argc, char *argv[] )
{
char msg[80];

/* sign on */
printf("\n----------- HP Font File Download Utility -----------");

/* enough args ? */
if( (argc < 2) || (*(argv[1]) == '?') )
{
explain_pgm();
exit_pgm( 0, "" );
}

/* set values from command line */
process_args( argc, argv );

/* init counters */
bytes_read = 0;
bytes_written = 0;

/* do the download... */
open_files();
send_pfx();
send_fnt();
send_sfx();
close_files();

/* summarize activity */
sprintf( msg, "%ld bytes downloaded out of %ld bytes read",
bytes_written, bytes_read );
exit_pgm( 0, msg );
}