/*->c.txfax */


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "os.h"
#include "bbc.h"
#include "h.sprite"
#include "h.wimp"
#include "h.werr"
#include "h.flex"


#include "h.DrawLevel0"

#include "h.etc"

#include "h.wos"
#include "h.mym"
#include "h.ram"
#include "h.strdef"
#include "h.file"
#include "h.tiff"
#include "h.fsx"
#include "h.xext"
#include "h.def"
#include "h.view"
#include "h.fax"
#include "h.dir"
#include "h.batch"
#include "h.buffer"
#include "h.serial"
#include "h.err"
#include "h.timex"
#include "h.sched"
#include "h.config"

#include "h.code"

#include "h.con"
#include "h.ident"
#include "h.dbug"
#include "h.state"

#include "h.rxfax"

#include "h.txfax"


/*****************************************************************************/

#define TXIDLEN 32

char     txdocname[256];
char     txnumber[PREFIXLEN+NUMLEN];
char     txname[PREFIXLEN+NUMLEN];
int      txsn;
int      txsnline;
int      txdocuments;
int      txpages;
int      txresolution;
int      txwidth;
int      txband;
int      txdirn;
int      txmode;
int      txanswer;



static int     txpadcount;

static int     txbitrate;
static int     txscantime;

static int     txdatacompression;
static int     txerrorcorrection;
static int     txbinaryftp;
static int     txpagelengthcode;


static framestr txframe;
static int      txfh;

static char     txid[TXIDLEN];


int ratecode[6]={2400,4800,7200,9600,12000,14400};
int scancode[8][2]={
                             0, 0,
                             5, 5,
                            10, 5,
                            10,10,
                            20,10,
                            20,20,
                            40,20,
                            40,40
                   };


void faxtxscan(int fp)
{
 txbitrate =stack[fp+0];
 txscantime=stack[fp+1];
}


/* faxtxparams(txpagelength,txdatacompression,txerrorcorrection,txbinaryftp);*/

void faxtxparams(int fp)
{
 txpagelengthcode=stack[fp+0];
 txdatacompression=stack[fp+1];
 txerrorcorrection=stack[fp+2];
 txbinaryftp=stack[fp+3];
}



/* int faxtxopendocument(void) */

int faxtxopendocument(int fp)
{
 os_error * ep;

 conaction("{CON04}");
 confax(leaf(txdocname));

 ep=fs_open(txdocname,'r',&txfh);
 if(!ep)
 {
  ep=tiff_readhdr(txfh);
  if(!ep) ep=tiff_readframe(txfh,&txframe);
 }

 return(0);
 fp=fp;
}




/* int faxtxclosedocument(int docok) */

int faxtxclosedocument(int fp)
{
 os_error * ep;
 int        docok;
 int        bn;


 conaction("{CON05}");
 conclrfax();

 docok=stack[fp];

 ep=fs_close(txfh,NULL);

 bn=findviewsn(txsn);
 strcpy(vtable[TXBFILE][bn].ident,txid);

 if(!docok)
 {
  schedsentdoc();
  writetolog("{LOG11} %s {LOG12}\n",leaf(txdocname));
 }

 txnexttarget();
 faxtxprelims();

 return(0);
}



#define TXBUFFSIZE 0x10000


static int serialerror;
static int serialcount; /* counting how many characters we output           */
static int serialinput; /* counting how many characters are sent back to us */
static int txbitrev=0;


static buffer xbitbuf;

static codestr cxin;
static codestr cxout;


void settxbor(int fp)
{
 txbitrev=stack[fp];
}

void faxtxclear(void)
{
 txbitrev=0;
}


static os_error * sr_put(buffer * bf,int c)
{
 if(serialerror) return(NULL);

 serialcount++;

 if(txbitrev) c=bitrev[c];

 if(c==DLE)
 {
  outbyteb(DLE);
  outbyteb(DLE);
 }
 else
 {
  outbyteb(c);
 }

 if(!(serialcount & 0xFF))
 {
  c=getbyte();
  if(c==CAN)
  {
   outbyteb(CAN);
   serialerror=1;
  }
  else     /* if the modem starts to reflect, then do an error */
  {
   if(c>31)
   {
    serialinput++;
    if(serialinput>8) serialerror=1;
   }
  }
 }

 return(NULL);
 bf=bf;
}



/* converted page width to width in pixels at this point */

static os_error * sendpage(int txresln,int txpagewidth)
{
 os_error  * ep;
 int         copies;
 int         skip;
 int         pccomplete;
 int         pcbreak;
 int         eof;
 int         xline;

 serialerror=0;
 setdbdataphase(1,0);


 if(txresln  && txresolution)  {copies=1;skip=0;}
 else
 if(!txresln && !txresolution) {copies=1;skip=0;}
 else
 if(txresln  && !txresolution) {copies=2;skip=0;}
 else
 if(!txresln && txresolution)  {copies=1;skip=1;}
 else                          {copies=1;skip=0;} /* keep compiler happy */

/* dprintf(0,"txresln=%d txpagewidth=%d copies=%d skip=%d",
                                    txresln,txpagewidth,copies,skip); */


 cxin.width=txframe.xpix;
 cxin.bitrev=txframe.bitrev;
 cxin.height=txframe.ypix;
 cxin.getbyte=bf_get;
 cxin.bf=&xbitbuf;
 cxin.type=txframe.compression;
 cxin.newbuffer=1;

 cxout.width=cxin.width;
 cxout.bitrev=0;
 cxout.height=(cxin.height*copies)/(1+skip);
 cxout.putbyte=sr_put;
 cxout.bf=NULL;
 if(txdatacompression) cxout.type=FAXCCITT4;
 else                  cxout.type=FAXCCITT3;
 cxout.newbuffer=0;

         ep=codeinit(&cxout);
 if(!ep) ep=decodeinit(&cxin);

 pccomplete=0;
 pcbreak=0;

 if(!ep)
 {
  while(1)
  {
   setblockmode();

   cxin.getline(&cxin,&eof);
   if(eof) break;

   if(cxin.line>=pcbreak)
   {
    concomplete(pccomplete);
    pccomplete+=5;
    pcbreak=(pccomplete*cxin.height)/100;
   }

   cxout.run=cxin.run;
   cxout.runs=cxin.runs;

  /*
     if((column_number+runlength)>txpagewidth) 
                                   runlength=txpagewidth-column_number;
   */


   if(txresln) xline=cxout.line/2;
   else        xline=cxout.line;


   xline-=identshift;

   if(xline>=0 && xline<IDENTHEIGHT)
   {
    writeident(xline,&cxout.run,cxout.runs);
   }

   /* now read one line */

   if(skip>=0 && cxout.run)
   {
    cxout.putline(&cxout,txpadcount,copies);
   }
   skip=-skip;
   clrblockmode();
  }

  /* now read an entire page */

  cxout.puteop(&cxout);

  if(!noeopdle)
  {
   outbyte(DLE);
   outbyte(ETX);
  }

  decodefinit(&cxin);
  codefinit(&cxout);
 }

 concomplete(100);

 if(serialerror) ep=&err_serial;

 setdbdataphase(0,0);

 return(ep);

 USE(txpagewidth);
}


/* function called if someone hits Cancel button */

static void txcancel(void)
{
 serialerror=1;
}


/* int faxtxpage(page,txpagewidth,txresln); */

int faxtxpage(int fp)
{
 os_error * ep;

 int page;
 int txpagewidth;
 int txresln;

 setfaxcancelhandler(txcancel);

 page=stack[fp];
 txpagewidth=stack[fp+1];
 txresln=stack[fp+2];


 if(txscantime && scanpad)
 {
  txpadcount=((scancode[txscantime][txresln]*ratecode[txbitrate])/(1000*8))+1;
 }
 else
 {
  txpadcount=0;
 }

 conaction("{CON06}");
 conpage(page+1,txpages);
 conparam(txbitrate,txresln,txdatacompression);

 while(1)
 {
  if((txframe.pn-1)==page)
  {
   ep=fs_seek(txfh,txframe.strip);
   break;
  }
  else
  {
   if(!txframe.next)
   {
    ep=&err_noframe;
    break;
   }

   ep=fs_seek(txfh,txframe.next);
   if(!ep) ep=tiff_readframe(txfh,&txframe);
  }
 }

 if(!ep) ep=bf_alloc(&xbitbuf,TXBUFFSIZE,txfh,txframe.length);
 if(!ep)
 {
  ep=identopen(txframe.xpix,txpages,page+1);

  if(!ep)
  {
   ep=sendpage(txresln,faxt3widthtable[txpagewidth]);

   if(!ep) ep=bf_dealloc(&xbitbuf);
   else       bf_dealloc(&xbitbuf);

   identclose();
  }
 }

 clearfaxcancelhandler();

 return(ep!=NULL);
}


void xfaxtxid(char * string)
{
 strcpy(txid,string);
 writetolog("{LOG13}%s\n",txid);
 conid(txid);
}


void faxtxid(int fp)
{
 char string[TXIDLEN];
 strncpy(string,stringptr(stack[fp]),TXIDLEN-1);
 string[TXIDLEN-1]=0;
 xfaxtxid(string);
}



void faxtxprelims(void)
{
 /* dprintf(0,"prelims pages=%d\n",txpages); */

 xexec4("faxmodem_txparams",&txpages,&txresolution,&txwidth,NULL);
}


