/*->c.config */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <signal.h>
#include <ctype.h>
#include <time.h>

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

#include "h.Drawlevel0"

#include "h.def"
#include "h.wos"
#include "h.timex"
#include "h.xext"
#include "h.main"
#include "h.mym"
#include "h.strdef"
#include "h.fax"
#include "h.serial"
#include "h.ram"
#include "h.file"
#include "h.pr"
#include "h.key"
#include "h.script"
#include "h.dir"
#include "h.view"
#include "h.batch"
#include "h.fo"
#include "h.pic"
#include "h.vx"
#include "h.trans"
#include "h.rxfax"
#include "h.txfax"
#include "h.state"
#include "h.log"
#include "h.dbug"
#include "h.ser"
#include "h.replay"
#include "h.newfax"
#include "h.band"


#include "h.config"


static void voicefix(void);


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


static int  modemdriverloaded;
static char drivername[12];
static int  pendingdriver;
static char pendname[12];
static char xpendname[12];
static int  xpendingdriver;


static int  tonedial;
       int  rings;
       int  answermode;
       int  scanpad;
       int  quietboot;
       int  modemanswerorginate;

static int  maxbitrate;
static int  minbitrate;
static int  width;
static int  length;
static char ident[IDLEN];
       char identline[IDLEN];
static int  doident;
       int  doidentline;
static int  fine;
static int  retries;
       int  faxerrors;
       int  textdumpmode;
static int  curtextfont;
static int  setcurtextfont;
       int  datacompression;
static int  binary;
static int  errorcorrection;



char textfontname[64];


static char * ratenames[6]  ={"2400","4800","7200","9600","12000","14400"};
static char * widthnames[3] ={"1728","2048","2432"};
static char * lengthnames[3]={"A4 297mm","B4 364mm","Variable"};

int    faxt3widthtable[3]={1728,2048,2432};


int faxt3res(int xres,int yres)
{
 if(xres==XRES && yres<((YRESLO+YRESHI)/2)) return(0);
 else                                       return(1);
}


int faxt3width(int width)
{
 if(width<=1728) return(0);
 else
 if(width<=2048) return(1);
 else
 if(width<=2432) return(2);
 else            return(0);
}



static void setmodemparams(void)
{
 char string[32];

 xexec4("faxmodem_params",&fine,&maxbitrate,&length,&width);
 xexec4("faxmodem_params2",&datacompression,&errorcorrection,
                           &binary,&minbitrate);

 xexec4("voicemodem_params",&voicecomp,&voicebps,&voicesps,NULL);
 xexec4("voicemodem_params2",&voicesdet,&voicemax,NULL,NULL);


 if(doident) strcpy(string,ident);
 else        *string=0;

 xexec("faxmodem_id",string,NULL,NULL);
}


void specifydriver(int fp)
{
 char * p=stringptr(stack[fp]);
 int    len=strlen(p);

 if(len && len<12)
 {
  strcpy(pendname,p);
  pendingdriver=1;
 }
}


void changedriver(void)
{
 char string[128];

 if(pendingdriver && zlevel==0)
 {
  if(modemdriverloaded)
  {
   xremfile();
   modemdriverloaded=0;
  }

  faxrxclear();
  faxtxclear();

  sprintf(string,"%s.%s",path(DRVP),pendname);
  if(xaddfile(string,0,1))
  {
   modemdriverloaded=1;
   strcpy(drivername,pendname);
   tonedial=drivertonedial(tonedial);
   retries=driverretries(retries);
   voicemodeminit();
   voicefix();
   setmodemparams();
  }
  pendingdriver=0;
 }
}


/* we assume that myrambuff contains menu */

void setpopdriver(void)
{
 int * menu=(int*)myrambuff;
 int   item;

 item=0;

 while(modemdriverloaded)
 {
  tickst(menu,item,!strcmp(menuaddr(menu,item),xpendname));
  if(islastm(menu,item)) break;
  item++;
 }
}


void setmodem(int fp)
{
 setvar(fp+0,&tonedial);
 tonedial=drivertonedial(tonedial);
 rings=stack[fp+1];
 answermode=stack[fp+2];
 scanpad=stack[fp+3];
 quietboot=stack[fp+4];
 modemanswerorginate=stack[fp+5];
}



void seterrors(int fp)
{
 retries=driverretries(stack[fp]);
 faxerrors=stack[fp+1];
}


void setlogfile(int fp)
{
 setvar(fp+0,&logfile);
 strcpy(logname,stringptr(stack[fp+1]));
}


void settextoptions(int fp)
{
 setvar(fp+0,&textdumpmode);
 strcpy(textfontname,stringptr(stack[fp+1]));
}


void setprintoptions(int fp)
{
 setvar(fp+0,&vxautoprint);
 setvar(fp+1,&vxautohdr);
}


void setfaxident(int fp)
{
 setvar(fp+0,&doident);
 strcpy(ident,stringptr(stack[fp+1]));
}


void setfaxheader(int fp)
{
 setvar(fp+0,&doidentline);
 strcpy(identline,stringptr(stack[fp+1]));
}


void setfaxparams(int fp)
{
 fine   =stack[fp];
 maxbitrate=stack[fp+1];
 width  =stack[fp+2];
 length =stack[fp+3];
}


void setfaxparams2(int fp)
{
 datacompression=stack[fp];
 errorcorrection=stack[fp+1];
 binary=stack[fp+2];
 minbitrate=stack[fp+3];
}


void setvoiceparams(int fp)
{
 voicecomp=stack[fp];
 voicebps=stack[fp+1];
 voicesps=stack[fp+2];
}


void setvoiceparams2(int fp)
{
 voicesdet=stack[fp];
 voicemax=stack[fp+1];
}



static char * bsize[3]=
{
 "LARGE", "SMALL", "INFO"
};

static char * bsort[4]=
{
 "NAME", "TYPE", "SIZE", "DATE"
};



void savechoices(void)
{
 FILE * fp;
 char   string[256];

 sprintf(string,"%s.!Choices",path(AUTOP));
 fp=fopen(string,"wb");

 if(fp)
 {
  hsystdheader(fp,"!Choices");

  rfprintf(fp,"void main(void)\n{\n");

  if(modemdriverloaded) rfprintf(fp,"specifydriver(\"%s\");\n",drivername);
  rfprintf(fp,"setautoredial(%d,%d);\n",attempts,ardelay/100);
  rfprintf(fp,"setbatch(%s,%s);\n",bsize[display],bsort[sort]);
  rfprintf(fp,"setbatchconfig(%cREMOVE,%cDISCARD,%cPOPUP,%cPOPUP,%cWARN,%cNEWFAX);\n",
     33-autoremove,33-batdiscard,33-batpopup,33-txbatpopup,
     33-unsentwarn,33-newfaxpopup);

  rfprintf(fp,"setbatchconfig2(%cFORWARD,\"%s\");\n",33-batforward,
                                                        batforwardname);

  rfprintf(fp,"setnewfax(%cOVERRIDE,%d,%d,%cPREFIX,\"%s\",%d);\n",
     33-defnewbits.apply,bataftertime,
     batbeforetime,33-defnewbits.prefix,bandname(defnewbits.band),
                      defnewbits.priority);

  rfprintf(fp,"setbatchlimit(%d,%d,0,0);\n",batchlimit,batchlimitn);

  *string=0;
  if(answermode & AVOICE) strcpy(string,"VOICE");
  if(answermode & AFAX) strcat(string,"|FAX");
  if(answermode & ADATA) strcat(string,"|DATA");
  if(*string=='|') *string=' ';
  else
  if(!(*string)) strcpy(string,"0");

  rfprintf(fp,"setmodem(%cTONE,%d,%s,%cSCAN,%cQUIET,%cANSWER);\n",
    33-tonedial,rings,string,33-scanpad,33-quietboot,33-modemanswerorginate);


  rfprintf(fp,"seterrors(%d,%d);\n",retries,faxerrors);
  rfprintf(fp,"setfaxident(%cIDENT,\"%s\");\n",33-doident,ident);
  rfprintf(fp,"setfaxheader(%cHEADER,\"%s\");\n",33-doidentline,identline);

  rfprintf(fp,"setlogfile(%cLOGFILE,\"%s\");\n",33-logfile,logname);

  rfprintf(fp,"setfaxparams(%d,%d,%d,%d);\n",fine,maxbitrate,width,length);
  rfprintf(fp,"setfaxparams2(%d,%d,%d,%d);\n",datacompression,
                                           errorcorrection,binary,minbitrate);

  rfprintf(fp,"setvoiceparams(%d,%d,%d);\n",voicecomp,voicebps,voicesps);
  rfprintf(fp,"setvoiceparams2(%d,%d);\n",voicesdet,voicemax);

  rfprintf(fp,"setcomms(%cPREFIX);\n",33-prefix);
  rfprintf(fp,"settextoptions(%cPORTRAIT,\"%s\");\n",33-textdumpmode,
                                                        textfontname);

  rfprintf(fp,"setserver(%cACTIVE,\"%s\",\"%s\",\"%s\");\n",33-server,
                                    servername,servercom1,servercom2);

  savevxps(fp);
  rfprintf(fp,"setprintoptions(%cAUTO,%cHEADER);\n",33-vxautoprint,
                                                    33-vxautohdr);

  rfprintf(fp,"setzoom(%d,%d,%d);\n",defltzoom.mul,defltzoom.div,defltzoom.var);  rfprintf(fp,"setprocessmode(HIRES,%d,%d,%d,%d,%d);\n",
                defltimage.hi,defltimage.himode[0],defltimage.himode[1],
                              defltimage.himode[2],defltimage.himode[3]);
  rfprintf(fp,"setprocessmode(LORES,%d,%d,%d,%d,%d);\n",
                defltimage.lo,defltimage.lomode[0],defltimage.lomode[1],
                              defltimage.lomode[2],defltimage.lomode[3]);
  rfprintf(fp,"setprocess(%cMIRRORLR,%cMIRRORUD,%cROTATE,%cPLUS90);\n",
                33-defltimage.mirrorlr,33-defltimage.mirrorud,
                33-defltimage.rotate,33-defltimage.plus90);
  rfprintf(fp,"setprocessscale(%d,%d,%d,%d);\n",
       defltimage.xsmul,defltimage.xsdiv,defltimage.ysmul,defltimage.ysdiv);


  rfprintf(fp,"}\n\n");

  fclose(fp);

  sprintf(string,"%s.!Choices",path(AUTOP));
  setftype(string,SCRIPT);
 }
}




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

static int  xmaxbitrate;
static int  xminbitrate;
static int  xwidth;
static int  xlength;
static int  xfine;
static int  xbatdiscard;
static int  xautoremove;
static int  xdoident;
static int  xdoidentline;
static int  xlogfile;
static int  xtextdumpmode;
static int  xbatpopup;
static int  xtxbatpopup;
static int  xnewfaxpopup;
static int  xdatacompression;
static int  xvxautoprint;
static int  xvxautohdr;
static int  xunsentwarn;
static int  xanswermode;
static int  xscanpad;
static int  xquietboot;
static int  xmodemanswerorginate;
static int  xtonedial;
static int  xbatforward;
static int  xbataftertime;
static int  xbatbeforetime;
static int  xnewprefix;
static int  xnewpriority;
static int  xnewband;
static int  xnewapply;
static int  xbatchlimit;

/*****************************************************************************/
/* Printer dbox */


void decodefontmenu(int m2)
{
 writeicon(whandle[PRINTER],2,fontname(m2));
 untick(font_menu,curtextfont);
 curtextfont=m2;
 tick(font_menu,curtextfont);
}


void closeconfigprinter(int ok)
{
 int handle;

 if(ok)
 {
  handle=whandle[PRINTER];

  textdumpmode=xtextdumpmode;
  vxautoprint=xvxautoprint;
  vxautohdr=xvxautohdr;

  if(setcurtextfont && !fontinit()) /* was in modem demon */
  {
   strcpy(textfontname,fontname(curtextfont));
  }
 }
 closedownt(PRINTER);
}

void configprintericon(int icon)
{
 switch(icon)
 {
  case  5:
          if(!fontinit())
          {
           setupfontmenu();
           if(!setcurtextfont) curtextfont=findfontnumber(textfontname);
           setcurtextfont=1;
           tick(font_menu,curtextfont);
           popmenu(font_menu);
          }
          break;

  case  8:                    /* Portrait  */
          if(!xtextdumpmode)
          {
           select(ewindow,8);
           deselect(ewindow,7);
           xtextdumpmode=1;
          }
          break;

  case  7:                    /* Landscape */
          if(xtextdumpmode)
          {
           select(ewindow,7);
           deselect(ewindow,8);
           xtextdumpmode=0;
          }
          break;

  case  6:
  case  4:
          closeconfigprinter(icon==6);
          break;

  case  9:
          selectst(ewindow,icon,xvxautoprint^=1);
          break;

  case 10:
          selectst(ewindow,icon,xvxautohdr^=1);
          break;

 }
}

static void openconfigprinter(void)
{
 int handle;

 handle=createwindow(PRINTER);
 if(handle)
 {

  writeicon(handle,2,textfontname);
  setcurtextfont=0;
  xtextdumpmode=textdumpmode;
  selectst(handle,8,textdumpmode);
  selectst(handle,7,!textdumpmode);

  xvxautoprint=vxautoprint;
  xvxautohdr=vxautohdr;

  selectst(handle,9,xvxautoprint);
  selectst(handle,10,xvxautohdr);

  popup(handle,0);
 }
}


              /* N L R D U */

static char configprintericlst[8][5]=
{
         17,          0,           0,          15,           50,
         15,          0,           0,          14,           17,
         14,          0,           0,          21,           15,
         21,          0,           0,          47,           14,
         47,          0,           0,          48,           21,
         48,          0,           0,           8,           47,
          8,          0,           0,          50,           48, 
         50,          0,           0,          17,            8
};




void configprinterkey(int * key)
{
 int cicon;
 int j;
 int ch;

 ch=*key;

 switch(ch)
 {
       case 27:
               closeconfigprinter(0);
               break;

       case CR:
      case TAB:
               ch=CDOWN;

    case 0x18E:
    case 0x18F:
    case 0x19C:
    case 0x19D:
    case 0x19E:
    case 0x19F:
               ch&=0x18F;
               for(j=0;j<7;j++) if(configprintericlst[j][0]==icon) break;
               cicon=configprintericlst[j][(ch-0x18B)];
               if(cicon) iecarrot(whandle[PRINTER],cicon);
               break;

    default:return;
 }
 *key=-1;
}


/*****************************************************************************/
/* Modem dbox */

static xmodemchangedemonsave;

void modemchangedemon(void)
{
 if(zlevel!=0)
 {
  addzeroevent(MODEMCHANGEZERO);
 }
 else
 {
  statesavequiet();

  if(xpendingdriver)
  {
   pendingdriver=1;
   strcpy(pendname,xpendname);
   changedriver();
  }

  setmodemparams();
  retries=driverretries(retries);
  tonedial=drivertonedial(tonedial);

  stateload();

  remzeroevent(MODEMCHANGEZERO);

  if(xmodemchangedemonsave) savechoices();
 }
}


void decodedriver(int m2)
{
 if(m2>=0)
 {
  strcpy(xpendname,menuaddr((int*)myrambuff,m2));
  xpendingdriver=1;
  setpopdriver();
  writeicon(whandle[MODEM],2,xpendname);
 }
 setpopdriver();
}


void closeconfigmodem(int ok)
{
 int handle;

 if(ok)
 {
  handle=whandle[MODEM];

  geticonint(handle,4,&rings);

  answermode=xanswermode;
  scanpad=xscanpad;
  quietboot=xquietboot;
  modemanswerorginate=xmodemanswerorginate;
  tonedial=xtonedial;

  if(ok==2) xmodemchangedemonsave=1;
  else      xmodemchangedemonsave=0;

  modemchangedemon();
 }
 closedownt(MODEM);
}

void configmodemicon(int icon)
{
 switch(icon)
 {
   case 3:
          setupdrivermenu();
          setpopdriver();
          popmenu(driver_menu);
          break;

  case  5:
          selectst(ewindow,icon,xtonedial^=1);
          break;

  case 11:
  case  1:
          closeconfigmodem(icon==11);
          break;


  case  6:
          selectst(ewindow,icon,(xanswermode^=AVOICE)&AVOICE);
          break;

  case  7:
          selectst(ewindow,icon,(xanswermode^=AFAX)&AFAX);
          break;

  case  8:
          selectst(ewindow,icon,(xanswermode^=ADATA)&ADATA);
          break;

  case  9:
          selectst(ewindow,icon,xscanpad^=1);
          break;

  case 10:
          selectst(ewindow,icon,xquietboot^=1);
          break;

  case 13:  /* answer */
          if(!xmodemanswerorginate)
          {
           select(ewindow,icon);
           deselect(ewindow,15);
           xmodemanswerorginate=1;
          }
          break;

  case 15:
          if(xmodemanswerorginate)
          {
           select(ewindow,icon);
           deselect(ewindow,13);
           xmodemanswerorginate=0;
          }
          break;
 }
}


static void openconfigmodem(void)
{
 int handle;

 handle=createwindow(MODEM);
 if(handle)
 {
  writeiconf(handle,4,"%d",rings);
  writeicon(handle,2,drivername);
  xpendingdriver=0;
  strcpy(xpendname,drivername);
  xanswermode=answermode;
  xscanpad=scanpad;
  xquietboot=quietboot;
  xmodemanswerorginate=modemanswerorginate;
  xtonedial=tonedial;

  selectst(handle,5,xtonedial);
  selectst(handle,6,xanswermode & AVOICE);
  selectst(handle,7,xanswermode & AFAX);
  selectst(handle,8,xanswermode & ADATA);
  selectst(handle,9,xscanpad);
  selectst(handle,10,xquietboot);
  selectst(handle,13,xmodemanswerorginate);
  selectst(handle,15,!xmodemanswerorginate);

  popup(handle,3);
 }
}


#define MODEMKEYS 1

              /* N L R D U */

static char configmodemiclst[MODEMKEYS][5]=
{
          4,          0,           0,           0,            0,
};




void configmodemkey(int * key)
{
 int cicon;
 int j;
 int ch;

 ch=*key;

 switch(ch)
 {
       case 27:
               closeconfigmodem(0);
               break;

       case CR:
      case TAB:
               ch=CDOWN;

    case 0x18E:
    case 0x18F:
    case 0x19C:
    case 0x19D:
    case 0x19E:
    case 0x19F:
               ch&=0x18F;
               for(j=0;j<MODEMKEYS;j++) if(configmodemiclst[j][0]==icon) break;
               cicon=configmodemiclst[j][(ch-0x18B)];
               if(cicon) iecarrot(whandle[MODEM],cicon);
               break;

    default:return;
 }
 *key=-1;
}


/*****************************************************************************/
/* Fax dbox */

static int maxmenu;

static void setpoprate(void)
{
 int i;
 for(i=0;i<6;i++) tickst(rate_menu,i,
                                 maxmenu?(i==xmaxbitrate):(i==xminbitrate));
}

void decoderate(int m1)
{
 if(m1>=0)
 {
  if(maxmenu) xmaxbitrate=m1;
  else        xminbitrate=m1;
  setpoprate();
  writeicon(whandle[FAX],maxmenu?9:24,
                                ratenames[maxmenu?xmaxbitrate:xminbitrate]);
 }
}

static void setpoplength(void)
{
 int i;
 for(i=0;i<3;i++) tickst(length_menu,i,i==xlength);
}

void decodelength(int m1)
{
 if(m1>=0)
 {
  xlength=m1;
  setpoplength();
  writeicon(whandle[FAX],11,lengthnames[xlength]);
 }
}


static void setpopwidth(void)
{
 int i;
 for(i=0;i<3;i++) tickst(width_menu,i,i==xwidth);
}


void decodewidth(int m1)
{
 if(m1>=0)
 {
  xwidth=m1;
  setpopwidth();
  writeicon(whandle[FAX],10,widthnames[xwidth]);
 }
}


void closeconfigfax(int ok)
{
 int handle;

 if(ok)
 {
  handle=whandle[FAX];

  geticonint(handle,15,&faxerrors);
  geticonint(handle,16,&retries);

  strcpy(ident,iconaddr(handle,21));
  strcpy(identline,iconaddr(handle,12));

  width=xwidth;
  length=xlength;
  doident=xdoident;
  doidentline=xdoidentline;
  fine=xfine;
  datacompression=xdatacompression;
  maxbitrate=xmaxbitrate;
  minbitrate=xminbitrate;

  setmodemparams();
 }
 closedownt(FAX);
}

void configfaxicon(int icon)
{
 switch(icon)
 {
  case 14: /* fine */
          selectst(ewindow,icon,xfine^=1);
          break;

  case 19:
          selectst(ewindow,icon,xdatacompression^=1);
          break;

  case 17:
  case 25:
          maxmenu=(icon==17);
          setpoprate();
          popmenu(rate_menu);
          break;

  case 18:
          setpopwidth();
          popmenu(width_menu);
          break;

  case 22:
          setpoplength();
          popmenu(length_menu);
          break;

  case 20:
          selectst(ewindow,icon,xdoident^=1);
          break;

  case 13:
          selectst(ewindow,icon,xdoidentline^=1);
          break;

   case 6: 
   case 4:          
          closeconfigfax(icon==6);
          break;
 }
}

static void openconfigfax(void)
{
 int handle;

 handle=createwindow(FAX);

 if(handle)
 {
  xfine=fine;
  selectst(handle,14,xfine);
  xdatacompression=datacompression;
  selectst(handle,19,xdatacompression);

  writeiconf(handle,15,"%d%%",faxerrors);
  writeiconf(handle,16,"%d",retries);

  writeicon(handle,21,ident);
  writeicon(handle,12,identline);

  xdoident=doident;
  xdoidentline=doidentline;
  selectst(handle,20,xdoident);
  selectst(handle,13,xdoidentline);

  xmaxbitrate=maxbitrate;
  xminbitrate=minbitrate;
  writeicon(handle, 9,ratenames[xmaxbitrate]);
  writeicon(handle,24,ratenames[xminbitrate]);

  xwidth=width;
  writeicon(handle,10,widthnames[xwidth]);

  xlength=length;
  writeicon(handle,11,lengthnames[xlength]);

  popup(handle,1);
 }
}


#define FAXKEYS 4


              /* N L R D U */

static char configfaxiclst[FAXKEYS][5]=
{
         12,          0,           0,          21,            0,
         21,          0,           0,          15,           12,
         15,          0,           0,          16,           21,
         16,          0,           0,           0,           15,
};



void configfaxkey(int * key)
{
 int cicon;
 int j;
 int ch;

 ch=*key;

 switch(ch)
 {
       case 27:
               closeconfigfax(0);
               break;

       case CR:
      case TAB:
               ch=CDOWN;

    case 0x18E:
    case 0x18F:
    case 0x19C:
    case 0x19D:
    case 0x19E:
    case 0x19F:
               ch&=0x18F;
               for(j=0;j<FAXKEYS;j++) if(configfaxiclst[j][0]==icon) break;
               cicon=configfaxiclst[j][(ch-0x18B)];
               if(cicon) iecarrot(whandle[FAX],cicon);
               break;

    default:return;
 }
 *key=-1;
}




/*****************************************************************************/
/* New fax dbox */


void closeconfignewfax(int ok)
{
 int handle;

 if(ok)
 {
  handle=whandle[SETNEWFAX];

  bataftertime=xbataftertime;
  batbeforetime=xbatbeforetime;

  defnewbits.apply=xnewapply;
  defnewbits.prefix=xnewprefix;
  defnewbits.priority=xnewpriority;
  defnewbits.band=xnewband;
 }
 closedownt(SETNEWFAX);
}


static int newfaxbandf(int band)
{
 xnewband=band;
 writeicon(whandle[SETNEWFAX],9,bandname(band));
 return(band);
}

static int newfaxpriorityf(int priority)
{
 xnewpriority=priority;
 writeicon(whandle[SETNEWFAX],7,priorityname(priority));
 return(priority);
}



static void writeaftertime(int xtime,int icon)
{
 char string[16];
 writehmap(string,xtime);
 writeicon(whandle[SETNEWFAX],icon,string);
}



static void changehours(int inc,int icon,int * xtime)
{
 if(inc)
 {
  *xtime+=3600;
  if(*xtime>3600*24) *xtime-=3600*24;
 }
 else
 {
  *xtime-=3600;
  if(*xtime<0) *xtime+=3600*24;
 }

 writeaftertime(*xtime,icon);
}



static void changeminutes(int inc,int icon,int * xtime)
{
 if(inc)
 {
  *xtime+=60;
  if(*xtime>3600*24) *xtime-=3600*24;
 }
 else
 {
  *xtime-=60;
  if(*xtime<0) *xtime+=3600*24;
 }

 writeaftertime(*xtime,icon);
}



void confignewfaxicon(int icon)
{
 int adjust;
 int handle=whandle[SETNEWFAX];

 adjust=(buttons==1);

 switch(icon)
 {
  case 10:
          popband(newfaxbandf,xnewband);
          break;

  case  2:
          poppriority(newfaxpriorityf,xnewpriority);
          break;

  case  1:
          selectst(handle,1,xnewprefix^=1);
          break;

  case 23:
          selectst(handle,23,xnewapply^=1);
          break;

  case  4:
  case  5:
          closeconfignewfax(icon==5);
          break;

  case 13:
  case 15:
          changehours(adjust?icon==13:icon==15,17,&xbataftertime);
          break;

  case 16:
  case 14:
          changeminutes(adjust?icon==16:icon==14,17,&xbataftertime);
          break;

  case 18:
  case 22:
          changehours(adjust?icon==18:icon==22,21,&xbatbeforetime);
          break;

  case 20:
  case 19:
          changeminutes(adjust?icon==20:icon==19,21,&xbatbeforetime);
          break;
 }
}



static void openconfignewfax(void)
{
 int handle;

 handle=createwindow(SETNEWFAX);
 if(handle)
 {
  xbataftertime=bataftertime;
  xbatbeforetime=batbeforetime;
  xnewprefix=defnewbits.prefix;
  xnewapply=defnewbits.apply;
  xnewpriority=defnewbits.priority;
  xnewband=defnewbits.band;

  writeaftertime(bataftertime,17);
  writeaftertime(batbeforetime,21);

  selectst(handle,23,xnewapply);

  selectst(handle,1,xnewprefix);

  writeicon(handle,9,bandname(xnewband));
  writeicon(handle,7,priorityname(xnewpriority));

  popup(handle,2);
 }
}


void setnewfax(int fp)
{
 defnewbits.apply=stack[fp+0];
 bataftertime=stack[fp+1];
 batbeforetime=stack[fp+2];
 defnewbits.prefix=stack[fp+3];
 defnewbits.band=bandnametoband(stringptr(stack[fp+4]));
 defnewbits.priority=stack[fp+5];
}



/*****************************************************************************/
/* Batch dbox */


int savelog(char * filename)
{
 writeicon(whandle[BATCH],1,filename);
 return(1);
}


void closeconfigbatch(int ok)
{
 int handle;

 if(ok)
 {
  handle=whandle[BATCH];

  autoremove=xautoremove;
  batdiscard=xbatdiscard;
  batpopup=xbatpopup;
  txbatpopup=xtxbatpopup;
  newfaxpopup=xnewfaxpopup;
  unsentwarn=xunsentwarn;
  batchlimit=xbatchlimit;

  batforward=xbatforward;
  strcpy(batforwardname,iconaddr(handle,16));

  geticonint(handle,13,&attempts);
  geticonint(handle,21,&batchlimitn);
  strcpy(logname,iconaddr(handle,1));
  logfile=xlogfile;

  geticonint(handle,11,&ardelay);
  ardelay*=100;

 }
 closedownt(BATCH);
}



static os_error * forwardfn(char * name)
{
 writeicon(whandle[BATCH],16,name);
 return(NULL);
}



void configbatchicon(int icon)
{
 int adjust;

 adjust=(buttons==1);


 switch(icon)
 {
  case  9:
          selectst(ewindow,icon,xautoremove^=1);
          break;

  case  8:
          selectst(ewindow,icon,xbatdiscard^=1);
          break;

  case  6:
          selectst(ewindow,icon,xbatpopup^=1);
          break;

  case  7:
          selectst(ewindow,icon,xtxbatpopup^=1);
          break;

  case 19:
          selectst(ewindow,icon,xnewfaxpopup^=1);
          break;

  case 14:
          selectst(ewindow,icon,xunsentwarn^=1);
          break;

  case  3:
          selectst(ewindow,icon,xlogfile^=1);
          break;

  case  2:
          menuwindow(setsave(SAVELOG));
          break;

  case  4:
  case  5:
          closeconfigbatch(icon==5);
          break;

  case 17:
          openentrymenu(forwardfn);
          break;

  case 18:
          selectst(ewindow,icon,xbatforward^=1);
          break;

  case 20:
          selectst(ewindow,icon,xbatchlimit^=1);
          break;

 }
}



static void openconfigbatch(void)
{
 int handle;

 handle=createwindow(BATCH);
 if(handle)
 {
  xautoremove=autoremove;
  selectst(handle,9,xautoremove);
  xbatdiscard=batdiscard;
  selectst(handle,8,xbatdiscard);
  xbatpopup=batpopup;
  xtxbatpopup=txbatpopup;
  xnewfaxpopup=newfaxpopup;
  xunsentwarn=unsentwarn;
  xbatchlimit=batchlimit;

  selectst(handle,6,xbatpopup);
  selectst(handle,7,xtxbatpopup);
  selectst(handle,19,xnewfaxpopup);
  selectst(handle,14,xunsentwarn);
  writeiconf(handle,11,"%d",ardelay/100);
  writeiconf(handle,13,"%d",attempts);
  writeicon(handle,1,logname);
  xlogfile=logfile;
  selectst(handle,3,xlogfile);

  xbatforward=batforward;
  writeicon(handle,16,batforwardname);

  selectst(handle,18,xbatforward);

  selectst(handle,20,xbatchlimit);
  writeiconf(handle,21,"%d",batchlimitn);

  popup(handle,2);
 }
}

#define BATCHKEYS 5


              /* N L R D U */

static char configbatchiclst[BATCHKEYS][5]=
{
         21,          0,           0,          11,            0,
         11,          0,           0,          13,           21,
         13,          0,           0,           1,           11,
          1,          0,           0,          16,           13,
         16,          0,           0,           0,            1,
};



void configbatchkey(int * key)
{
 int cicon;
 int j;
 int ch;

 ch=*key;

 switch(ch)
 {
       case 27:
               closeconfigbatch(0);
               break;

      case TAB:
       case CR:
               ch=CDOWN;

    case 0x18E:
    case 0x18F:
    case 0x19C:
    case 0x19D:
    case 0x19E:
    case 0x19F:
               ch&=0x18F;
               for(j=0;j<BATCHKEYS;j++) if(configbatchiclst[j][0]==icon) break;
               cicon=configbatchiclst[j][(ch-0x18B)];
               if(cicon) iecarrot(whandle[BATCH],cicon);
               break;

    default:return;
 }
 *key=-1;
}


/*****************************************************************************/
/* Voice dbox */

static int xvoicecomp;


static void setpopvoicemenu(void)
{
 int i;

 for(i=0;i<voicenames;i++) untick(voice_menu,i);

 tick(voice_menu,voiceindex(xvoicecomp));
}


void decodevoicemenu(int m3)
{
 if(m3>=0 && m3<voicenames)
 {
  xvoicecomp=voicecompressionmodemcode[m3];
  writeicon(whandle[VOICE],2,voicecompressionname[m3]);
 }

 setpopvoicemenu();
}



void closeconfigvoice(int ok)
{
 int handle;

 if(ok)
 {
  handle=whandle[VOICE];

  geticonint(handle,4,&voicebps);
  geticonint(handle,9,&voicesps);
  geticonint(handle,11,&voicesdet);
  geticonint(handle,12,&voicemax);

  voicecomp=xvoicecomp;

  xexec4("voicemodem_params",&voicecomp,&voicebps,&voicesps,NULL);
  xexec4("voicemodem_params2",&voicesdet,&voicemax,NULL,NULL);
 }
 closedownt(VOICE);
}

void configvoiceicon(int icon)
{
 switch(icon)
 {
  case 0:  /* OK */
  case 1:
         closeconfigvoice(!icon);
         break;

  case 3:
         if(voicenames)
         {
          setupvoicecompmenu();
          setpopvoicemenu();
          popmenu(voice_menu);
         }
         break;
 }
}


void openconfigvoice(void)
{
 int handle;
 int index;

 handle=createwindow(VOICE);
 if(handle)
 {
  writeicon(handle,2,voicecompressionname[voicecomp]);
  writeiconf(handle,4,"%d",voicebps);
  writeiconf(handle,9,"%d",voicesps);
  writeiconf(handle,11,"%d",voicesdet);
  writeiconf(handle,12,"%d",voicemax);

  xvoicecomp=voicecomp;

  index=voiceindex(xvoicecomp);
  if(index<0) 
  { 
   xvoicecomp=voicecompressionmodemcode[0];
   index=0;
  }

  popup(handle,2);
 }
}



static void voicefix(void)
{
 if(whandle[VOICE] && !(modemtype & AVOICE)) closeconfigvoice(0);

 if(whandle[STATUS])
 {
  shadeiconst(whandle[STATUS],5,!(modemtype & AVOICE));
 }
}



#define VOICEKEYS 4


              /* N L R D U */

static char configvoiceiclst[VOICEKEYS][5]=
{
          4,          0,           0,           9,            0,
          9,          0,           0,          11,            4,
         11,          0,           0,          12,            9,
         12,          0,           0,           0,           11,
};



void configvoicekey(int * key)
{
 int cicon;
 int j;
 int ch;

 ch=*key;

 switch(ch)
 {
       case 27:
               closeconfigvoice(0);
               break;

      case TAB:
       case CR:
               ch=CDOWN;

    case 0x18E:
    case 0x18F:
    case 0x19C:
    case 0x19D:
    case 0x19E:
    case 0x19F:
               ch&=0x18F;
               for(j=0;j<VOICEKEYS;j++) if(configvoiceiclst[j][0]==icon) break;
               cicon=configvoiceiclst[j][(ch-0x18B)];
               if(cicon) iecarrot(whandle[VOICE],cicon);
               break;

    default:return;
 }
 *key=-1;
}


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

static char xservername[SNAMELEN];
static char xcom1[SCOMMANDLEN];
static char xcom2[SCOMMANDLEN];
static int  xserver;


static serverfn sfn;

static void setpopservermenu(char * name)
{
 int   item;

 item=0;

 while(1)
 {
  tickst(server_menu,item,!cstrcmp(menuaddr(server_menu,item),name));
  if(islastm(server_menu,item)) break;
  item++;
 }
}


void popservermenu(serverfn ser,char * name)
{
 sfn=ser;

 setupservermenu();
 if(server_menu)
 {
  setpopservermenu(name);
  popmenu(server_menu);
 }
}


void decodeservermenu(int m3)
{
 char * p;

 if(m3>=0) 
 {
  p=sfn(menuaddr((int*)myrambuff,m3));
  setpopservermenu(p);
 }
}


static char * serverf(char * name)
{
 strcpy(xservername,name);
 writeicon(whandle[SERVER],2,xservername);
 return(xservername);
}


void closeconfigserver(int ok)
{
 int handle;

 if(ok)
 {
  handle=whandle[SERVER];

  server=xserver;
  strcpy(servername,xservername);
  strcpy(servercom1,xcom1);
  strcpy(servercom2,xcom2);
 }
 closedownt(SERVER);
}



void configservericon(int icon)
{
 switch(icon)
 {
  case 3:   /* OK */
  case 4:
         closeconfigserver(icon==3);
         break;

  case 5:
         popservermenu(serverf,xservername);
         break;


  case 9:
         selectst(ewindow,9,xserver^=1);
         break;
 }
}


void openconfigserver(void)
{
 int handle;

 handle=createwindow(SERVER);
 if(handle)
 {
  xserver=server;

  strcpy(xservername,servername);
  strcpy(xcom1,servercom1);
  strcpy(xcom2,servercom2);

  setindirect(handle,8,SCOMMANDLEN,xcom1);
  setindirect(handle,7,SCOMMANDLEN,xcom2);

  selectst(handle,9,xserver);

  writeicon(handle,2,xservername);
  popup(handle,2);
 }
}

#define SERVERKEYS 2


              /* N L R D U */

static char configservericlst[SERVERKEYS][5]=
{
          8,          0,           0,           7,            0,
          7,          0,           0,           0,            8,
};



void configserverkey(int * key)
{
 int cicon;
 int j;
 int ch;

 ch=*key;

 switch(ch)
 {
       case 27:
               closeconfigserver(0);
               break;

      case TAB:
       case CR:
               ch=CDOWN;

    case 0x18E:
    case 0x18F:
    case 0x19C:
    case 0x19D:
    case 0x19E:
    case 0x19F:
               ch&=0x18F;
               for(j=0;j<SERVERKEYS;j++) 
                       if(configservericlst[j][0]==icon) break;
               cicon=configservericlst[j][(ch-0x18B)];
               if(cicon) iecarrot(whandle[SERVER],cicon);
               break;

    default:return;
 }
 *key=-1;
}



/*****************************************************************************/
/* Main config dbox */


/* 0==Cancel, 1=Save+Close 2==Save */

void closeconfig(int ok)
{
 int handle;

 if(ok)
 {
  handle=whandle[STATUS];
  savechoices();
 }

 if(ok<2) closedownt(STATUS);
}


void configicon(int icon)
{
 switch(icon)
 {
  case 0: /* Save */
         closeconfig(buttons==4?1:2);
         break;


  case 7:
         openconfignewfax();
         break;


  case 6:
         openconfigserver();
         break;

  case 5:
         openconfigvoice();
         break;

  case 4:
         openconfigmodem();
         break;

  case 3:
         openconfigbatch();
         break;

  case 1:
         openconfigfax();
         break;

  case 2:
         openconfigprinter();
         break;
 }
}


void openconfig(void)
{
 int handle;

 handle=createwindow(STATUS);
 if(handle)
 {
  voicefix();
  popup(handle,0);
 }
}


void configkey(int * key)
{
 key=key;
}

