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

📄 efax.c

📁 用于使用moden进行传真的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
  printcap ( "local  ", local ) ;  printcap ( "remote ", remote ) ;  for ( i=0 ; i<NCAP && i!=ST && i !=BR ; i++ )    session[i] = remote[i] < local[i] ? remote[i] : local[i] ;  session[BR] = brindex[ remote[BR] ] < brindex[ local[BR] ] ?    remote[BR] : local[BR] ;  session[ST] = msttab [ session[VR] ] [ remote[ST] ] ;  printcap ( "session", session ) ;  if ( local[WD] != session[WD] || local[LN] > session[LN] ||       local[DF] != session[DF] )     err = msg ("W3incompatible local and remote capabilities" ) ;  return err ;}/* Skip to start of first/next page (or to start of previous page   if dp is 0).  If ppm in not null, it is then set to EOP if   there are no pages following this one, MPS if the next page   has the same format as `local' (assumed to be the format of   the previous page), EOM if the page has a different format.   If local is non-NULL its format fields are set according to   the format of the new page.  Currently only considers the   file's y-resolution.   This function is called before send_data() and obtains the ppm   for that page.  It can be called again with dp=0 if a PIN or   RTN is received to restart the page.  Returns 0 or 2 on   errors. */int rdpage ( IFILE *f, int dp, int *ppm, cap local, int *changed ){  int err=0, m=EOP, yres, fVR, nVR  ;  if ( nextipage ( f, dp ) )    err = msg ( "E2 can't happen (rdpage: can't go to %s page)", 	       dp ? "next" : "same" ) ;    if ( ! err ) {    yres = f->page->yres ;    fVR = ( yres > (196+98)/2 ) ? 1 : 0 ;    if ( local && yres ) {      if ( local [ VR ] != fVR ) {	local [ VR ] = fVR ;	if ( changed ) *changed = 1 ;      } else {	if ( changed ) *changed = 0 ;      }    }    if ( lastpage ( f ) ) {      m = EOP ;    } else {      PAGE *p = f->page + 1 ;      nVR = ( p->yres > (196+98)/2 ) ? 1 : 0  ;      m = ( nVR != fVR ) ? EOM : MPS ;    }  }  if ( ppm ) {    *ppm = err ? EOP : m ;  }  return err ;}/* Terminate previous page if page number is non-zero and start   next output page if page number is non-negative. If page is -1   removes the most recently opened file. Returns 0 if OK, 2 on   errors. */int wrpage ( OFILE *f, int page ){  int err=0 ;  err = nextopage ( f, page ) ;  if ( ! err && page == -1 ) {    if ( remove ( f->cfname ) ) {      err = msg ( "ES2can't delete file %s:", f->cfname ) ;     } else {      msg ( "Fremoved %s", f->cfname ) ;     }  }    return err ;}/* Send data for one page.  Figures out required padding and 196->98 lpi   decimation based on local and session capabilitites, substitutes page   numbers in header string and enables serial port flow control.  Inserts   the page header before the input file data.  Converts each scan line to   T.4 codes and adds padding (FILL) and EOL codes before writing out.   Sends RTC when done.  Sends DLE-ETX and returns serial port to command   mode when done. Returns 0 if OK, non-0 on errors. */int send_data ( TFILE *mf, IFILE *f, int page, int pages,	       cap local, cap session, char *header, faxfont *font ){  int done=0, err=0, noise=0, nr=0, lastnr=0, line, pixels ;  int i, decimate, pwidth, minlen, dcecps, inheader, skip=0 ;  uchar buf [ MAXCODES + 2*EOLBITS/8 + 1 ], *p ;  short runs [ MAXRUNS ], lastruns [ MAXRUNS ] ;  char headerbuf [ MAXLINELEN ] ;  ENCODER e ;  newENCODER ( &e ) ;  dcecps = cps[session[BR]] ;  minlen = ( (long)dcecps * mst[session[ST]] - 1500 + 500 ) / 1000 ;  pwidth = pagewidth [ session [ WD ] ] ;  decimate = local[VR] > session[VR] ;  msg ( "T padding to %d bytes/scan line.%s", minlen+1,        decimate ? " reducing 196->98 lpi." : "" ) ;  if ( vfc )     msg ( "T limiting output to %d bps for %d byte modem buffer", 	 dcecps*8, MAXDCEBUF + MINWRITE  ) ;  if ( ckfmt ( header, 6 ) )    msg ( "W too many %%d escapes in header format string \"%s\"", header ) ;  else    sprintf ( headerbuf, header, page, pages, page, pages, page, pages ) ;  msg ("I header:[%s]", headerbuf ) ;        done = err = ttymode ( mf, SEND ) ;   mf->start = time(0) ;  mf->mstart = proc_ms() ;  mf->bytes = mf->pad = mf->lines = 0 ;  /* start T.4 data with some FILL and an EOL */  p = buf ;  for ( i=0 ; i<32 ; i++ ) {    p = putcode ( &e, 0, 8, p ) ;  }  p = putcode ( &e, EOLCODE, EOLBITS, p ) ;  if ( ! f || ! f->f )     err = msg ( "E2can't happen(send_data)" ) ;   mf->lines=0 ;  for ( line=0 ; ! done && ! err ; line++ ) {    if ( line < HDRSPCE ) {	/* insert blank lines at the top */      runs[0] = pwidth ;      pixels = pwidth ;      nr = 1 ;    } else {      if ( ( nr = readline ( f, runs, &pixels ) ) < 0 ) {	done = 1 ;	continue ;      }    }				/* generate and OR in header pixels */    if ( line >= HDRSTRT && line < HDRSTRT + HDRCHRH ) {      int hnr ;      short hruns [ MAXRUNS ] ;      hnr = texttorun ( (uchar*) headerbuf, font, line-HDRSTRT, 		       HDRCHRW, HDRCHRH, HDRSHFT,		       hruns, 0 ) ;      nr = runor ( runs, nr, hruns, hnr, 0, &pixels ) ;    }        inheader = line < HDRSTRT + HDRCHRH ;    if ( decimate || ( inheader && local[VR] == 0 ) ) {      if ( ++skip & 1 ) {	/* save the first of every 2 lines */   	memcpy ( lastruns, runs, nr * sizeof(short) ) ;   	lastnr = nr ;   	continue ;		/* get next line */      } else {			/* OR previous line into current line */   	nr = runor ( runs, nr, lastruns, lastnr, 0, &pixels ) ;      }    }    if ( nr > 0 ) {      if ( pixels ) {				/* make line the right width */	if ( pixels != pwidth ) nr = xpad ( runs, nr, pwidth - pixels ) ;				/* convert to MH coding */	p = runtocode ( &e, runs, nr, p ) ;				/* zero pad to minimum scan time */	while ( p - buf < minlen ) { 	  p = putcode ( &e, 0, 8, p ) ;	  mf->pad ++ ;	}				/* add EOL */	p = putcode ( &e, EOLCODE, EOLBITS, p ) ;	sendbuf ( mf, buf, p - buf, dcecps ) ;	mf->bytes += p - buf ;	mf->lines++ ;      } else {	/* probably read an EOL as part of RTC */      }      if ( tdata ( mf, 0 ) ) noise = 1 ;      p = buf ;    }  }  for ( i=0 ; i < RTCEOL ; i++ )    p = putcode ( &e, EOLCODE, EOLBITS, p ) ;  p = putcode ( &e, 0, 0, p ) ;  sendbuf ( mf, buf, p - buf, dcecps ) ;  mf->bytes += p - buf ;    if ( noise ) msg ("W- characters received while sending" ) ;  return err ;}int end_data ( TFILE *mf, cap session, int ppm, int *good ){  int err=0, c ;  uchar *p ;  long dt, draintime ;  if ( ! ppm ) p = DLE_ETX ;  else if ( ppm == MPS ) p = "\020," ;   else if ( ppm == EOM ) p = "\020;" ;   else if ( ppm == EOP ) p = "\020." ;   else {    p = "" ;    err = msg ( "E2 can't happen (end_data)" ) ;  }  tput ( mf, p, 2 ) ;  dt = time(0) - mf->start ;				/* time to drain buffers + 100% + 4s */  draintime = ( 2 * ( mf->bytes / cps[ session[BR] ] + 1 - dt ) + 4 ) * 10 ;  draintime = draintime < TO_DRAIN_D ? TO_DRAIN_D : draintime ;  c = ckcmd ( mf, 0, 0, (int) draintime, OK ) ;  if ( good ) *good = ( c == OK ) ? 1 : 0 ;  dt = time(0) - mf->start ;  msg ( "Isent %d+%d lines, %d+%d bytes, %d s  %d bps" ,        HDRSPCE, mf->lines-HDRSPCE,        mf->bytes-mf->pad, mf->pad, (int) dt, (mf->bytes*8)/dt ) ;  if ( mf->bytes / (dt+1) > cps[session[BR]] )    msg ( "E flow control did not work" ) ;  if ( ! err ) err = ttymode ( mf, COMMAND ) ;  return err ;}/* Read one scan line from fax device. If pointer pels is not   null it is used to save pixel count.  Returns number of runs   stored, EOF on RTC, or -2 on EOF, DLE-ETX or other error. */int readfaxruns ( TFILE *f, DECODER *d, short *runs, int *pels ){  int err=0, c=EOF, x, n ;  dtab *tab, *t ;  short shift ;  short *p, *maxp, *q, len=0 ;  uchar rd_state ;  maxp = ( p = runs ) + MAXRUNS ;  x = d->x ; shift = d->shift ; tab = d->tab ; /* restore decoder state */  rd_state = f->rd_state ;  do {    do {      while ( shift < 0 ) { 	c = tgetd ( f, TO_CHAR ) ;	rd_state = ( rd_state & rd_allowed[c] ) ?	  ( ( rd_state & rd_nexts[c] ) ? rd_state <<= 1 : rd_state ) : 	  RD_BEGIN ;	if ( rd_state == RD_END )	  msg ( "W+ modem response in data" ) ; 	if ( c < 0 )  {	  x = ( x << 15 ) | 1 ; shift += 15 ;  /* EOL pad at EOF */	} else {	  x = ( x <<  8 ) | c ; shift +=  8 ; 	}      }      t = tab + ( ( x >> shift ) & 0x1ff ) ;      tab = t->next ;      shift -= t->bits ;    } while ( ! t->code ) ;    if ( p < maxp ) *p++ = t->code ;  } while ( t->code != -1 ) ;  d->x = x ; d->shift = shift ; d->tab = tab ; /* save state */  f->rd_state = rd_state ;  if ( p >= maxp ) msg ( "Wrun length buffer overflow" ) ;  /* combine make-up and terminating codes and remove +1 offset     in run lengths */  n = p - runs - 1 ;  for ( p = q = runs ; n-- > 0 ; )    if ( *p > 64 && n-- > 0 ) {      len += *q++ = p[0] + p[1] - 2 ;      p+=2 ;    } else {      len += *q++ = *p++ - 1 ;    }  n = q - runs ;    /* check for RTC and errors */  if ( len )    d->eolcnt = 0 ;  else    if ( ++(d->eolcnt) >= RTCEOL ) err = EOF ;  if ( c < 0 ) err = - 2 ;  if ( pels ) *pels = len ;    return err ? err : n ;}/* Receive data. Reads scan lines from modem and writes to output   file.  Checks for errors by comparing received line width and   session line width.  Check that the output file is still OK   and if not, send one CANcel character and wait for protocol to   complete. Returns 0 if OK, 1 on DLE-ETX without RTC, or 2 if   there was a file write error. */int receive_data ( TFILE *mf, OFILE *f, cap session, int *nerr ){  int err=0, line, lines, nr, len ;  int pwidth = pagewidth [ session [ WD ] ] ;  short runs [ MAXRUNS ] ;  DECODER d ;  if ( ! f || ! f->f ) {    msg ( "E2 can't happen (writeline)" ) ;  }     newDECODER ( &d ) ;  lines=0 ;   for ( line=0 ; ( nr = readfaxruns ( mf, &d, runs, &len ) ) >= 0 ; line++ ) {    if ( nr > 0 && len > 0 && line ) { /* skip first line+EOL and RTC */      if ( len != pwidth ) { 	(*nerr)++ ;	if ( *nerr <= MAXERRPRT ) msg ("R-+ (%d:%d)", line, len ) ;	nr = xpad ( runs, nr, pwidth - len ) ;      }       writeline ( f, runs, nr, 1 ) ;      lines++ ;    }    if ( ferror ( f->f ) ) {      err = msg ("ES2file write:") ;      tput ( mf, CAN_STR, 1 ) ;      msg ("Wdata reception CANcelled") ;    }   }    if ( *nerr ) {    if ( *nerr > MAXERRPRT ) msg ("R-+ ....." ) ;    msg ("R-  : reception errors" ) ;    msg ("W- %d reception errors", *nerr ) ;  }  if ( nr == EOF ) {     while ( tgetd ( mf, TO_CHAR ) >= 0 ) ; /* got RTC, wait for DLE-ETX */  } else {    err = 1 ;			/* DLE-ETX without RTC - should try again */  }  msg ( "I- received %d lines, %d errors", lines, *nerr ) ;  return err ;}/* Send training check sequence of n zeroes.  Returns 0 or 2 on error. */int puttrain ( TFILE *f, char *s, int n  ){  int i, m, err=0 ;  uchar buf [ MINWRITE ] = { 0 } ;#ifdef ADDTCFRTC  ENCODER e ;  uchar *p ;#endif  ckcmd ( f, &err, s, TO_FT, CONNECT ) ;    if ( ! err ) {    ttymode ( f, SEND ) ;    /* send n bytes of zeros */    for ( i=0 ; i < n ; i += m ) {      m = n-i < MINWRITE ? n-i : MINWRITE ;      sendbuf ( f, buf, m, 0 ) ;    }#ifdef ADDTCFRTC    /* append RTC in case modem is looking for it */    newENCODER ( &e ) ;    p = buf ;    for ( i=0 ; i < RTCEOL ; i++ )      p = putcode ( &e, EOLCODE, EOLBITS, p ) ;    p = putcode ( &e, 0, 0, p ) ;    sendbuf ( f, buf, p - buf, 0 ) ;#endif    tput ( f, DLE_ETX, 2 ) ;     ckcmd ( f, &err, 0, TO_DRAIN_D, OK ) ;    msg ( "I- sent TCF - channel check of %d bytes", n ) ;    ttymode ( f, COMMAND ) ;  }    return err ;}/* Checks for an error-free run of at least n bytes in the   received training check sequence. Sets good if it's not null,   the run was long enough and there were no errors. Returns 0 or   3 on other errors.  */int gettrain ( TFILE *f, char *s, int n, int *good ) {   int err=0, c, i=0, maxrunl=0, runl=0 ;    ckcmd ( f, &err, s, T2, CONNECT ) ;    if ( ! err ) {    for ( i=0 ; ( c = tgetd ( f, T3S ) ) >= 0 ; i++ )      if ( c ) {   	if ( runl > maxrunl ) maxrunl = runl ;   	runl = 0 ;      } else {   	runl ++ ;      }        if ( c == EOF )      err = msg ( "E3timed out during training check data" ) ;    else      ckcmd ( f, &err, 0, TO_RTCMD, NO ) ;      }       if ( runl > maxrunl ) maxrunl = runl ;       if ( good ) *good = !err && maxrunl > n ;  if ( !err ) {    msg ( "I- received TCF - channel check (%sOK: run of %d in %d)",    	 maxrunl > n ? "" : "not ", maxrunl, i ) ;  }

⌨️ 快捷键说明

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