⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 efaxlib.c

📁 使用efax的fax工具程序
💻 C
📖 第 1 页 / 共 3 页
字号:
/* 	      efaxlib.c - utility routines for efax		     Copyright 1995 Ed Casas*/#include <ctype.h>#include <errno.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <stdarg.h> #include <time.h>#include "efaxlib.h"#define MAXTSTAMP 80		/* maximum length of a time stamp */#ifndef SEEK_SET#define SEEK_SET 0#endifchar *verb = "ewin" ;		char *argv0 = "" ;int optind = 1 ;char *optarg ;extern t4tab wtab [ ( 64 + 27 + 13 ) + 1 ] ; /* T.4 coding tables */extern t4tab btab [ ( 64 + 27 + 13 ) + 1 ] ;char *iformatstr[] = { "0text", "1pbm", "2fax", 0 } ;char *oformatstr[] = { "1pbm" , "2fax", "3pcl", "4ps",  "5pgm", 0 } ;     /* Print time stamp. */void tstamp ( int dotime ){  static time_t last = 0, now ;  char *fmt = 0, tbuf [ MAXTSTAMP ] ;  now = time ( 0 ) ;  if ( dotime || ( now - last >   0 ) ) fmt = " (%M:%S)" ;  if (             now - last > 600 )   fmt = " %c" ;  if ( fmt ) {    strftime ( tbuf, MAXTSTAMP, fmt, localtime( &now ) ) ;    fputs ( tbuf , LOGF ) ;    last = now ;   }}/* For systems without strerror(3) */char *strerror( int i )       {  extern int sys_nerr;  extern char *sys_errlist[];  return ( i >= 0 && i < sys_nerr ) ? sys_errlist[i] : "Unknown Error" ;}/* Return string corresponding to character c. */char *cname ( u_char c ) {#define CNAMEFMT "<0x%02x>"#define CNAMELEN 6+1  static char *cname [ 256 ] = {		/* character names */  "<NUL>","<SOH>","<STX>","<ETX>", "<EOT>","<ENQ>","<ACK>","<BEL>",  "<BS>", "<HT>", "<LF>", "<VT>",  "<FF>", "<CR>", "<SO>", "<SI>",   "<DLE>","<XON>","<DC2>","<XOFF>","<DC4>","<NAK>","<SYN>","<ETB>",  "<CAN>","<EM>", "<SUB>","<ESC>", "<FS>", "<GS>", "<RS>", "<US>" } ;  static char names[ (127-32)*2 + 129*(CNAMELEN) ], *p=names ;  static int i=0 ;      if ( ! i )     for ( i=32 ; i<256 ; i++ ) {      sprintf ( cname [ i ] = p , i<127 ? "%c" : CNAMEFMT , i ) ;      p += strlen ( p ) + 1 ;    }  return cname [ c ] ;} /* Print a message with a variable number of printf()-type arguments if the   first character appears in the global verb[ose] string.  Other leading   characters and digits do additional actions: + allows the message to be   continued on the same line, '-' buffers the message instead of printing   it, E, and W expand into strings, S prints the error message for the   most recent system error, 0-4 set the return value, a space is skipped   and ends prefix.  Returns 0 if no prefix digit. */int msg ( const char *fmt, ... ) {   int err=0, dolf=1, flush=1, dotime=0 ;  char *ps="", *pe="", *pw="" ;  const char *p ;  static int atcol1=1 ;  va_list ap ;  va_start ( ap, fmt ) ;  for ( p=fmt ; *p ; p++ ) {    switch ( *p ) {    case ' ': p++ ; goto print ;    case 'A': break ;				   /* program args */    case 'C': break ;				   /* commands/responses */    case 'M': break ;				   /* modem dialogue */    case 'N': break ;				   /* negotiation */    case 'E': pw = "Error: " ; break ;    case 'H': break ;				   /* HDLC frame data */    case 'I': break ;				   /* information */    case '+': dolf = 0 ; break ;    case '-': flush = 0 ; break ;    case 'R': break ;				   /* reception errors */    case 'S': ps = strerror ( errno ) ; break ;    case 'T': dotime = 1 ; break ;    case 'W': pw = "Warning: " ; break ;    case '0': case '1': case '2': case '3': case '4': case '5':       err = *p - '0' ; break ;    default: goto print ;    }  }  print:    if ( strchr ( verb , tolower ( *fmt ) ) ) {    if ( atcol1 ) fprintf ( LOGF , "%s: %s%s" , argv0 , pe , pw ) ;    vfprintf( LOGF, p , ap ) ;    fputs ( ps , LOGF ) ;    atcol1 = dolf ;    if ( atcol1 ) {      tstamp ( dotime ) ;       fputs ( "\n" , LOGF ) ;    }    if ( flush ) fflush ( LOGF ) ;  }  va_end ( ap ) ;  return err ;}/* Simple (one option per argument) version of getopt(3). */int nextopt( int argc, char **argv, char *args ){  char *a, *p ;  if ( optind >= argc || *(a = argv[optind]) != '-' ) return -1 ;  optind++ ;  if ( ! *(a+1) || ( ( p = strchr ( args , *(a+1) ) ) == 0 ) )    return msg ( "Eunknown option (%s)" , a ) , '?' ;   if ( *(p+1) != ':' ) optarg = 0 ;  else    if ( *(a+2) ) optarg = a+2 ;    else      if ( optind >= argc ) return msg ( "Eno argument for (%s)", a ) , '?' ;      else optarg = argv [ optind++ ] ;  return *(a+1) ;}/* Initialize state of encoder for variable-length code words. */void newENCODER ( ENCODER *e ){  e->x = 0 ;  e->shift = -8 ;}/* Store a code word `code' of length `bits' (<=24) in buffer pointed to by   `buf'.  Bits that don't fit in complete bytes are saved between calls.   To flush the remaining bits call the function with code=0 and bits=0.   Returns pointer to next free element in output buffer.  Calling function   must ensure at least bits/8 bytes are available in buffer.  */u_char *putcode ( ENCODER *e, short code, short bits , u_char *buf ){  e->x = ( e->x << bits ) | code ;  e->shift += bits ? bits : -e->shift ;  while ( e->shift >= 0 ) {    *buf++ = e->x >> e->shift ;    e->shift -= 8 ;  }  return buf ;}/* Convert run lengths to 1-D T.4-codes.  First run is white.  Silently   truncates run lengths that are too long. After using this function EOLs   may need to be added and/or the putcode() buffer flushed.  Returns   pointer to next free element in output buffer. */u_char *runtocode ( ENCODER *e, short *runs, int nr, u_char *codes ){  u_char col = 0, *maxcodes = codes + MAXCODES ;  t4tab *ctab = wtab, *p ;  short rlen ;  long x ;  short shift ;#define PUTCODE(p) { x = ( x << p->bits ) | p->code ;  shift += p->bits ; \	while ( shift >= 0 ) { *codes++ = x >> shift ; shift -= 8 ; } }  x = e->x ; shift = e->shift ;  while ( nr-- > 0 ) {    rlen = *runs++ ;    if ( rlen > 63 ) {				/* make-up code */      if ( rlen > MAXRUNLEN ) rlen = MAXRUNLEN ;      p = ctab + 63 + ( rlen >> 6 ) ;      if ( codes < maxcodes ) PUTCODE(p) ;    }    p = ctab + ( rlen & 0x3f ) ;		/* terminating code */    if ( codes < maxcodes ) PUTCODE(p) ;    ctab = ( col ^= 1 ) ? btab : wtab ;  }      e->x = x ; e->shift = shift ;  return codes ;}/* Pad/truncate run-length coded scan line 'runs' of 'nr' runs by 'pad'   pixels (truncate if negative).  Returns the new number of runs. */int xpad ( short *runs, int nr, int pad ){  if ( pad < 0 ) {		          /* truncate */    while ( pad < 0 ) pad += ( nr <= 0 ? -pad : runs [ --nr ] ) ;    runs [ nr++ ] = pad ;  } else {				  /* pad with white */    if ( nr & 1 ) runs [ nr - 1 ] += pad ;    else runs [ nr++ ] = pad ;  }  return nr ;}/* Shift a run-length coded scan line right by s pixels (left if negative).   If necessary, zero-length runs are created to avoid copying.  Returns   the pixel width change (+/-). */int xshift ( short *runs, int nr, int s ){  int i=0, n=0 ;  if ( s < 0 ) {    for ( i = 0 ; s < 0 && i < nr ; i++ ) {       s += runs [ i ] ;      n -= runs [ i ] ;      runs [ i ] = 0 ;     }    i-- ;  }  if ( i < nr ) {    runs [ i ] += s ;    n += s ;  }  return n ;}/* Scale nr run lengths in buffer pointed to by p to scale image   horizontally.  The scaling factor is xs/256. Returns new line width in   pixels. */int xscale ( short *p , int nr, int xs ){  int inlen=0, outlen=0 ;  for ( ; nr-- > 0 ; p++ ) {    inlen += *p ;    *p = ( ( inlen * xs + 128 ) >> 8 ) - outlen ;    outlen += *p ;  }  return outlen ;}/* Zero-terminated lists of run lengths for each byte. */u_char byteruns [ 1408 + 1 ] =    "8071061106205120511105210530413041210411110411204220421104310440"   "3140313103121103122031112031111103112103113032303221032111032120"   "3320331103410350215021410213110213202121202121110212210212302111"   "3021112102111111021111202112202112110211310211402240223102221102"   "2220221120221111022121022130233023210231110231202420241102510260"   "1160115101141101142011312011311101132101133011213011212101121111"   "0112112011222011221101123101124011114011113101111211011112201111"   "1120111111110111112101111130111230111221011121110111212011132011"   "1311011141011150125012410123110123201221201221110122210122301211"   "3012112101211111012111201212201212110121310121401340133101321101"   "3220131120131111013121013130143014210141110141201520151101610170"   "1701610151101520141201411101421014301313013121013111101311201322"   "0132110133101340121401213101212110121220121112012111110121121012"   "1130122301222101221110122120123201231101241012501115011141011131"   "1011132011121201112111011122101112301111130111112101111111101111"   "1120111122011112110111131011114011240112310112211011222011211201"   "1211110112121011213011330113210113111011312011420114110115101160"   "2602510241102420231202311102321023302213022121022111102211202222"   "0222110223102240211402113102112110211220211112021111110211121021"   "1130212302122102121110212120213202131102141021503503410331103320"   "3212032111032210323031130311210311111031112031220312110313103140"   "4404310421104220411204111104121041305305210511105120620611071080" ;/* Convert byte-aligned bit-mapped n-byte scan line into array of run   lengths.  Run length array must have *more* than 8*n elements.  First   run is white.  Returns number of runs coded.  */int bittorun ( u_char *bits, int n, short *runs ){  static u_char init=0, *rltab [ 256 ] ;  register u_char *p, c, lastc = 0x00 ;  short *runs0 = runs ;  if ( ! init ) {		/* initialize pointer and run tables */    int i = 0 ;    for ( rltab[ 0 ] = p = byteruns ; *p ; p++ )      if ( ! ( *p -= '0' ) && i < 255 ) 	rltab [ ++i ] = p+1 ;    init = 1 ;  }  *runs = 0 ;  for ( ; n > 0 ; n-- ) {    p = rltab [ c = *bits++ ] ;    if ( ( lastc & 0x01 ) ? ! ( c & 0x80 ) : ( c & 0x80 ) )      *(++runs) = *p++ ;		  /* new run */    else 			        *runs += *p++ ;			  /* continue run */    while ( *p )       *(++runs) = *p++ ;    lastc = c ;  }  return runs - runs0 + 1  ;}/* Bitwise-OR two run-length coded scan lines.  The run length   vectors a and b are OR-ed into c.  If c is null, the result is   placed in a.  The new image width is stored in pels if it is   not null.  Returns the number of runs in the result.  */int runor ( short *a, int na, short *b, int nb, short *c, int *pels ){  register short la, lb ;  int ia, ib, ic, np=0 ;  short tmp [ MAXRUNS ] ;  if ( ! c ) c = tmp ;  la = a [ ia = 0 ] ;  lb = b [ ib = 0 ] ;  c [ ic = 0 ] = 0 ;  while ( 1 ) {    if ( la <= lb ) {			  /* select shorter sub-run */      if ( ( ( ia | ib ) ^ ic ) & 1 )	  /* OR of subruns same colour as c? */	c [ ++ic ] = la ;		  /* no, new output run */      else 	c [ ic ] += la ;		  /* yes, add it */      lb -= la ;			  /* align subruns */      if ( ++ia >= na ) break ;		  /* done */      la = a [ ia ] ;			  /* get new subrun */    } else {				  /* same for line b ... */      if ( ( ( ia | ib ) ^ ic ) & 1 ) 	c [ ++ic ] = lb ;      else 	c [ ic ] += lb ;      la -= lb ;      if ( ++ib >= nb ) break ;      lb = b [ ib ] ;    }  }  if ( ia < na )    while ( 1 ) {      if ( ( ia ^ ic ) & 1 )	  	c [ ++ic ] = la ;		        else 	c [ ic ] += la ;		        if ( ++ia >= na ) break ;		        la = a [ ia ] ;			      }   else    while ( 1 ) {      if ( ( ib ^ ic ) & 1 ) 	c [ ++ic ] = lb ;      else 	c [ ic ] += lb ;      if ( ++ib >= nb ) break ;      lb = b [ ib ] ;    }  if ( c == tmp ) for ( ia=0 ; ia <= ic ; ia++ ) np += a[ia] = c[ia] ;  if ( pels ) *pels = np ;  return ic + 1 ;}    /* Check a raw PBM file header and get bitmap dimensions.  Leaves stream   positioned on first data byte.  Returns 0 or closes file and returns 2   on errors. */int openpbm ( FILE *f, int *w, int *h ){  int err = 0 ;  if ( f && fscanf ( f , "P4 %d %d%*c", w, h ) != 2 ) {    err = msg ("E2can't read (raw) PBM header" ) ;    fclose ( f ) ;    *w = *h = 0 ;  }     return err ;}/* Read a PBM font and fill in font structure.  If the file name is null or   there are errors, it initializes the font to the built-in font. Returns   0 if OK, 2 on errors. */int readfont ( char *fname, pbmfont *font ){  int err=0, i, j, n=0 ;  if ( fname ) {    FILE *f ;    if ( ( f = fopen ( fname , "rb" ) ) == 0 )      err = msg ("ES2can't open font file %s:\n", fname ) ;    if ( ! err && openpbm ( f, & font->w, & font->h ) != 0 )      err = msg ( "E2bad font file (%s) header", fname ) ;        if ( ! err && ( n = fread ( font->buf, 1, MAXFONTBUF, f ) ) != 	font->w * font->h / 8 )       err = msg ( "E2error reading font data" ) ;        if ( ! err && ( font->w / 256 > MAXFONTW || font->h > MAXFONTH ) ) {      err = msg ( "E2font size (%dx%d) too large", font->w, font->h ) ;    }    if ( err ) {      if ( f ) fclose ( f ) ;      font->w = font->h = 0 ;    } else {      font->w /= 256 ;	 /* convert PBM width to character width */      for ( i=0 ; i<256 ; i++ ) font->offset[i] = i*font->w ;      msg ("Iread %dx%d font %s (%d bytes)", font->w, font->h, fname, n ) ;    }  }      if ( err || ! fname ) {	           /* use built-in font */    font->w = STDFONTW ;    font->h = STDFONTH ;    for ( i=j=0 ; j<STDFONTBUF ; i++ )	   /* expand bit map */      if ( stdfont [ i ] == 0 )	for ( n = stdfont [ ++i ] ; n > 0 ; n-- ) 	  font->buf [ j++ ] = 0 ;      else	font->buf [ j++ ] = stdfont [ i ] ;    if ( i != 1980 ) err = msg ( "E2can't happen(readfont)" ) ;    for ( i=0 ; i<256 ; i++ ) font->offset[i] = i*font->w ;  }  return err ;}/* Append nb bits from in[from] to bit-mapped scan line buffer   where `from' is a bit (not byte) index.  Bits in bytes are   ordered from MS to LS bit. Initialize before each scan line by   calling with nb=0 and in pointing to output buffer.  Flush

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -