/***************************************************************************
 *                                                                         *
 *   GALFAP.C                                                              *
 *                                                                         *
 *   Copyright (c) 1992-1996 Galacticomm, Inc.    All Rights Reserved.     *
 *                                                                         *
 *   This is the fax module for Worldgroup that uses the fax API as        *
 *   its engine.  It allows users to fax text messages along with          *
 *   fax "attachments" that are kept in a fax database.                    *
 *                                                                         *
 *                                - C. Robert and B. Stephens  12/17/92    *
 *                                                                         *
 ***************************************************************************/

#include "gcomm.h"
#include "majorbbs.h"
#include "galfap.h"
#include "galfax.h"
#include "galfxc.h"

#define FILREV "$Revision: 2 $"

#define   FAPLSZ    4096           /* maximum file name list length        */
#define   TXTSIZ    16384          /* text message buffer size for editing */

#define fapusr      ((struct fapdef *)vdaptr)
#define othfap(x)   ((struct fapdef *)vdaoff(x))

static GBOOL fapinp(VOID);
static VOID fapsts(VOID);
static VOID faphup(VOID);
static VOID fapcup(VOID);
static VOID clsfap(VOID);

struct module fapblock={           /* module interface block               */
     "",                           /*   name used to refer to this module  */
     NULL,                         /*   user logon supplemental routine    */
     fapinp,                       /*   input routine if selected          */
     fapsts,                       /*   status-input routine if selected   */
     NULL,                         /*   "injoth" routine for this module   */
     NULL,                         /*   user logoff supplemental routine   */
     faphup,                       /*   hangup (lost carrier) routine      */
     fapcup,                       /*   midnight cleanup routine           */
     NULL,                         /*   delete-account routine             */
     clsfap                        /*   finish-up (sys shutdown) routine   */
};

struct fapdef {                    /* fax application user vda structure   */
     INT mnutyp;                   /*   reg/priv user? r=FAXMNU p=FPVMNU   */
     struct faplst fapitm;         /*   individual fax document struct     */
     CHAR edtnam[DOCLEN];          /*   saved doc name while editing       */
     INT rcvchn;                   /*   chan being received on (sysop)     */
     INT retsub;                   /*   substt to return to when done      */
     CHAR phonum[FAXPSZ];          /*   phone number to send to            */
     CHAR toname[NADSIZ];          /*   who this fax is "to"               */
     CHAR frname[NADSIZ];          /*   who this fax is "from"             */
     CHAR topic[FTPLEN];           /*   topic of this fax                  */
     LONG baschg;                  /*   charge for first page              */
     LONG addchg;                  /*   charge for additional pages        */
     INT numpps;                   /*   number of pages for this fax       */
     GBOOL sntmsg;                 /*   sent a message through editor?     */
     CHAR fillst[FAPLSZ];          /*   array for list of files            */
};

HMCVFILE fapmb;                    /* fax application message file pointer */
DFAFILE *fapbb;                    /* fax application data file pointer    */

static CHAR **fapbuf;              /* array of text message buffer pointers*/
static INT fapstt;                 /* fax application state                */

GBOOL realcr;                      /* only deduct "real" credits for faxes?*/
LONG chgpp;                        /* fax viewing charge per page          */
CHAR *faxsky;                      /* key required to be a fax sysop       */
CHAR *faxaky;                      /* key required to use C/S fax agent    */

static VOID hdlinq(VOID);
static VOID hdlmnu(VOID);
static VOID hdladd(VOID);
static VOID hdldel(VOID);
static VOID hdledt(VOID);
static VOID hdlsnd(VOID);
static VOID sndfax(VOID);
static VOID faxrcd(GBOOL ok);
static SHORT fapedn(SHORT flags);
static VOID faxpmt(INT msgno);
static VOID bgnlst(INT retsub);
static VOID lstcyc(VOID);
static VOID endlst(VOID);
static VOID chkbuf(VOID);

VOID EXPORT
init__galfap(VOID)                 /* initialize fax application module    */
{
     stlcpy(fapblock.descrp,gmdnam("GALFAP.MDF"),MNMSIZ);
     fapstt=register_module(&fapblock);
     fapbb=dfaOpen("galfap2.dat",sizeof(struct faplst),NULL);
     fapmb=opnmsg("galfap.mcv");
     realcr=ynopt(REALCR);
     chgpp=lngopt(VWPCHG,0L,9999999L);
     faxaky=stgopt(FAXAGKY);
     faxsky=stgopt(FAXSKY);
     dclvda(sizeof(struct fapdef));
     fapbuf=(CHAR **)alczer(nterms*sizeof(CHAR *));
     inicsfax();
     rtkick(30,chkbuf);
}

#if defined( WEBCAST )

VOID EXPORT
initwc__galfap(VOID)                 /* initialize fax application module    */
{
     init__galfap();
}

#endif


static GBOOL
fapinp(VOID)                       /* fax application main line            */
{
     setmbk(fapmb);
     dfaSetBlk(fapbb);
     if (margc == 1 && sameas(margv[0],"x") && usrptr->substt != 0) {
          cncall();
          if (usrptr->substt == fapusr->mnutyp) {
               return(FALSE);
          }
          else if (usrptr->substt == WT4FAX) {
               abort_receive(fapusr->rcvchn);
               prfmsg(RCVABT);
               faxpmt(fapusr->mnutyp);
          }
          else if (usrptr->substt == DLSTHD) {
               endlst();
          }
          else {
               faxpmt(fapusr->mnutyp);
          }
     }
     else if (margc == 0 && usrptr->substt != ENTLOK &&
              usrptr->substt != NEWLOK && usrptr->substt != SNDFNM) {
          if (usrptr->substt == DLSTHD) {
               endlst();
          }
          else {
               faxpmt(usrptr->substt);
          }
     }
     else {
          do {
               bgncnc();
               switch(usrptr->substt) {
               case 0:
                    if (!faxavl()) {
                         cncall();
                         prfmsg(FAXNAV);
                         outprf(usrnum);
                         return(FALSE);
                    }
                    cncchr();
                    fapusr->mnutyp=(haskey(faxsky) ? FPVMNU : FAXMNU);
                    faxpmt(fapusr->mnutyp);
                    break;
               case FPVMNU:
               case FAXMNU:
                    hdlmnu();
                    break;
               case CHGINQ:
                    hdlinq();
                    break;
               case DLSTHD:
                    cncall();
                    endlst();
                    break;
               case ADDFAX:
               case FAXXST:
               case ENTFIL:
               case RCVFNM:
               case CHNNUM:
               case WT4FAX:
               case ENTDES:
               case ENTLOK:
               case ADDITN:
                    hdladd();
                    break;
               case DELFAX:
               case DELSUR:
               case DELFLT:
                    hdldel();
                    break;
               case EDTFAX:
               case EDTMNU:
               case NEWNAM:
               case NEWDES:
               case NEWLOK:
                    hdledt();
                    break;
               case SNDPHO:
               case SNDTNM:
               case SNDFNM:
               case SNDEDT:
               case SNDTPC:
               case ATTDOC:
               case ENTDOC:
               case OKSEND:
               case SNDCPY:
               case CPYPHO:
               case CPYTNM:
               case CPYTPC:
                    hdlsnd();
                    break;
               }
          } while (!endcnc());
     }
     outprf(usrnum);
     return(TRUE);
}

static VOID
hdlinq(VOID)                       /* handle a charge inquiry              */
{
     static CHAR tmppho[FAXPSZ];

     stlcpy(tmppho,cncall(),FAXPSZ);
     stppho(tmppho);
     if (tmppho[0] == '\0') {
          faxpmt(usrptr->substt);
          return;
     }
     if (!valpho(tmppho)) {
          prfmsg(PHONAL);
     }
     else {
          prfmsg(FAXRAT,l2as(baschg(tmppho)),l2as(addchg(tmppho)));
     }
     faxpmt(fapusr->mnutyp);
}

static VOID
hdlmnu(VOID)                       /* handle a main menu selection         */
{
     CHAR tmpchr;

     switch (tmpchr=cncchr()) {
     case '?':
          cncall();
          faxpmt(fapusr->mnutyp);
          break;
     case 'S':
          faxpmt(SNDPHO);
          break;
     case 'L':
          bgnlst(fapusr->mnutyp);
          break;
     case 'I':
          faxpmt(CHGINQ);
          break;
     case 'D':
     case 'A':
     case 'E':
          if (haskey(faxsky)) {
               switch (tmpchr) {
               case 'A':
                    faxpmt(ADDFAX);
                    break;
               case 'E':
                    faxpmt(EDTFAX);
                    break;
               case 'D':
                    faxpmt(DELFAX);
                    break;
               }
               break;
          }
     default:
          if (margc != 0) {
               cncall();
               prfmsg(BADCHO,tmpchr);
          }
          faxpmt(fapusr->mnutyp);
     }
}

static VOID
hdladd(VOID)
{
     FILE *fp;
     INT i,ctr;
     struct user *usp;

     switch (usrptr->substt) {
     case ADDFAX:
          stlcpy(fapusr->fapitm.docnam,strupr(cncall()),DOCLEN);
          if (!dfaQueryEQ(fapusr->fapitm.docnam,0)) {
               faxpmt(FAXXST);
          }
          else {
               prfmsg(FAXDUP);
               faxpmt(usrptr->substt);
          }
          break;
     case FAXXST:
          switch (cncyesno()) {
          case 'Y':
               faxpmt(ENTFIL);
               break;
          case 'N':
               faxpmt(RCVFNM);
               break;
          default:
               prfmsg(YNAGIN);
               faxpmt(usrptr->substt);
          }
          break;
     case RCVFNM:
          stlcpy(fapusr->fapitm.filnam,fnmcse(cncwrd()),GCSTRPTH);
          if ((fp=fopen(fapusr->fapitm.filnam,FOPWB)) == NULL) {
               prfmsg(CNTOFN,fapusr->fapitm.filnam);
               faxpmt(RCVFNM);
               break;
          }
          fclose(fp);
          unlink(fapusr->fapitm.filnam);
          faxpmt(CHNNUM);
          break;
     case CHNNUM:
          if (morcnc() == '?') {
               prfmsg(FLSTHD);
               ctr=0;
               for (i=0 ; i < nterms ; i++) {
                    usp=usroff(i);
                    if (faxcap[grpnum[i]] && usp->usrcls == VACANT
                     && usp->state == AWAITC && !(usp->flags&NOHDWE)) {
                         prf("%-2s  ",spr("%x",channel[i]));
                         if ((++ctr)%18 == 0) {
                              prf("\n");
                         }
                    }
               }
               prf("\n");
               if (ctr == 0) {
                    clrprf();
                    prfmsg(NONAVL);
               }
               cncall();
               faxpmt(usrptr->substt);
          }
          else if ((ctr=usridx(cnchex())) == -1) {
               prfmsg(INVCHN);
               faxpmt(usrptr->substt);
          }
          else {
               if (receive_fax(ctr,fapusr->fapitm.filnam,faxrcd)) {
                    fapusr->rcvchn=ctr;
                    faxpmt(WT4FAX);
               }
               else {
                    prfmsg(CHNBSY);
                    faxpmt(usrptr->substt);
               }
          }
          break;
     case ENTFIL:
          stlcpy(fapusr->fapitm.filnam,fnmcse(cncwrd()),GCSTRPTH);
          if ((fapusr->fapitm.numpps=(SHORT)faxpps(fapusr->fapitm.filnam))
           != -1) {
               faxpmt(ENTDES);
          }
          else {
               prfmsg(BADFIL);
               faxpmt(FAXXST);
          }
          break;
     case WT4FAX:
          cncall();
          faxpmt(usrptr->substt);
          break;
     case ENTDES:
          stlcpy(fapusr->fapitm.docdes,cncall(),DESLEN);
          faxpmt(ENTLOK);
          break;
     case ENTLOK:
          stlcpy(fapusr->fapitm.lock,strupr(cncwrd()),KEYSIZ);
          faxpmt(ADDITN);
          break;
     case ADDITN:
          switch (cncyesno()) {
          case 'Y':
               if (dfaInsertDup(&fapusr->fapitm)) {
                    prfmsg(OKINSD,fapusr->fapitm.docnam);
               }
               else {
                    prfmsg(BDINSD,fapusr->fapitm.docnam);
               }
               faxpmt(fapusr->mnutyp);
               break;
          case 'N':
               prfmsg(OKABTD,fapusr->fapitm.docnam);
               faxpmt(fapusr->mnutyp);
               break;
          default:
               prfmsg(YNAGIN);
               faxpmt(usrptr->substt);
          }
          break;
     }
}

static VOID
hdldel(VOID)                       /* handle deletion of a fax document    */
{
     switch (usrptr->substt) {
     case DELFAX:
          if (morcnc() == '?') {
               bgnlst(usrptr->substt);
          }
          else {
               stlcpy(fapusr->fapitm.docnam,strupr(cncall()),DOCLEN);
               if (dfaAcqEQ(&fapusr->fapitm,fapusr->fapitm.docnam,0)) {
                    faxpmt(DELSUR);
               }
               else {
                    prfmsg(BADDNM);
                    faxpmt(usrptr->substt);
               }
          }
          break;
     case DELSUR:
          switch (cncyesno()) {
          case 'Y':
               if (dfaAcqEQ(&fapusr->fapitm,fapusr->fapitm.docnam,0)) {
                    dfaDelete();
               }
               prfmsg(OKDDEL);
               faxpmt(DELFLT);
               break;
          case 'N':
               faxpmt(fapusr->mnutyp);
               break;
          default:
               prfmsg(YNAGIN);
               faxpmt(usrptr->substt);
          }
          break;
     case DELFLT:
          switch (cncyesno()) {
          case 'Y':
               if (!fileiu(fapusr->fapitm.filnam)) {
                    unlink(fapusr->fapitm.filnam);
                    prfmsg(OKFDEL);
               }
               else {
                    prfmsg(CNTDEL);
               }
          case 'N':
               faxpmt(fapusr->mnutyp);
               break;
          default:
               prfmsg(YNAGIN);
               faxpmt(usrptr->substt);
          }
          break;
     }
}

static VOID
hdledt(VOID)                       /* handle editing of a fax document     */
{
     CHAR tmpchr;

     switch (usrptr->substt) {
     case EDTFAX:
          if (morcnc() == '?') {
               bgnlst(usrptr->substt);
          }
          else {
               stlcpy(fapusr->fapitm.docnam,strupr(cncall()),DOCLEN);
               if (dfaAcqEQ(&fapusr->fapitm,fapusr->fapitm.docnam,0)) {
                    stlcpy(fapusr->edtnam,fapusr->fapitm.docnam,DOCLEN);
                    faxpmt(EDTMNU);
               }
               else {
                    prfmsg(BADDNM);
                    faxpmt(usrptr->substt);
               }
          }
          break;
     case EDTMNU:
          switch (tmpchr=cncchr()) {
          case 'S':
               if (dfaAcqEQ(NULL,fapusr->edtnam,0)) {
                    if (dfaUpdateDup(&fapusr->fapitm)) {
                         prfmsg(OKDUPD);
                    }
                    else {
                         prfmsg(DOCDUP);
                    }
               }
               else {
                    prfmsg(DOCGON);
               }
               faxpmt(fapusr->mnutyp);
               break;
          case '1':
               faxpmt(NEWNAM);
               break;
          case '2':
               faxpmt(NEWDES);
               break;
          case '3':
               faxpmt(NEWLOK);
               break;
          default:
               prfmsg(BADCHO,tmpchr);
               cncall();
               faxpmt(usrptr->substt);
          }
          break;
     case NEWNAM:
          stlcpy(fapusr->fapitm.docnam,strupr(cncall()),DOCLEN);
          faxpmt(EDTMNU);
          break;
     case NEWDES:
          stlcpy(fapusr->fapitm.docdes,cncall(),DESLEN);
          faxpmt(EDTMNU);
          break;
     case NEWLOK:
          stlcpy(fapusr->fapitm.lock,strupr(cncwrd()),KEYSIZ);
          faxpmt(EDTMNU);
          break;
     }
}

static VOID
hdlsnd(VOID)                       /* handle sending of fax document(s)    */
{
     INT tmp;
     LONG tmpl;
     static CHAR filnam[GCMAXPTH],tmppho[FAXPSZ];

     switch (usrptr->substt) {
     case SNDPHO:
          fapusr->numpps=1;
          setmem(fapusr->fillst,FAPLSZ,0);
          stlcpy(fapusr->phonum,cncall(),FAXPSZ);
          strcpy(tmppho,fapusr->phonum);
          stppho(tmppho);
          if (tmppho[0] == '\0') {
               faxpmt(usrptr->substt);
          }
          else if (!valpho(tmppho)) {
               prfmsg(PHONAL);
               faxpmt(usrptr->substt);
          }
          else if (!accpho(tmppho,usaptr->userid)) {
               prfmsg(NOACCP);
               faxpmt(usrptr->substt);
          }
          else {
               fapusr->baschg=baschg(tmppho);
               fapusr->addchg=addchg(tmppho);
               if (fapusr->baschg != 0L || fapusr->addchg != 0L) {
                    prfmsg(FAXRAT,l2as(fapusr->baschg),l2as(fapusr->addchg));
               }
               faxpmt(SNDTNM);
          }
          break;
     case SNDTNM:
          stlcpy(fapusr->toname,cncall(),NADSIZ);
          faxpmt(SNDFNM);
          break;
     case SNDFNM:
          if (morcnc() == '\0') {
               stlcpy(fapusr->frname,usaptr->usrnam,NADSIZ);
          }
          else {
               stlcpy(fapusr->frname,cncall(),NADSIZ);
          }
          fapusr->sntmsg=FALSE;
          faxpmt(SNDEDT);
          break;
     case SNDEDT:
          switch (cncyesno()) {
          case 'Y':
               if (fapbuf[usrnum] == NULL) {
                    fapbuf[usrnum]=(CHAR *)alczer(TXTSIZ);
               }
               else {
                    setmem(fapbuf[usrnum],TXTSIZ,0);
               }
               bgnedt(TXTSIZ,fapbuf[usrnum],FTPLEN,fapusr->topic,fapedn,
                      ED_CLRTOP|ED_CLRTXT);
               break;
          case 'N':
               faxpmt(SNDTPC);
               break;
          default:
               prfmsg(YNAGIN);
               faxpmt(usrptr->substt);
          }
          break;
     case SNDTPC:
          stlcpy(fapusr->topic,cncall(),FTPLEN);
          prfmsg(haskey(faxsky) ? SDCHLP : DOCHLP);
          faxpmt(ENTDOC);
          break;
     case ATTDOC:
          switch (cncyesno()) {
          case 'Y':
               prfmsg(haskey(faxsky) ? SDCHLP : DOCHLP);
               faxpmt(ENTDOC);
               break;
          case 'N':
               faxpmt(OKSEND);
               break;
          default:
               prfmsg(YNAGIN);
               faxpmt(usrptr->substt);
          }
          break;
     case ENTDOC:
          if (morcnc() == '?') {
               bgnlst(usrptr->substt);
               return;
          }
          if (morcnc() == '.' && strlen(nxtcmd) == 1) {
               cncall();
               faxpmt(OKSEND);
               return;
          }
          if (morcnc() == '+' && haskey(faxsky)) {
               cncchr();
               stlcpy(filnam,fnmcse(cncall()),GCMAXPTH);
               cntdir(filnam);
               if (numfils != 1L) {
                    prfmsg(NOTFIL,filnam);
               }
               else {
                    if (addfil(fapusr->fillst,filnam,TXTFIL,FAPLSZ)) {
                         fapusr->numpps+=(tmp=txtpps(filnam));
                         prfmsg(OKFADD,filnam,tmp,tmp != 1 ? "s" : "");
                    }
                    else {
                         prfmsg(LSTFUL);
                         faxpmt(OKSEND);
                         return;
                    }
               }
          }
          else {
               stlcpy(fapusr->fapitm.docnam,strupr(cncall()),DOCLEN);
               if (dfaAcqEQ(&fapusr->fapitm,fapusr->fapitm.docnam,0)) {
                    if (!haskey(fapusr->fapitm.lock)) {
                         prfmsg(BADDNM);
                    }
                    else if (addfil(fapusr->fillst,fapusr->fapitm.filnam,
                             FAXFIL,FAPLSZ)) {
                         fapusr->numpps+=fapusr->fapitm.numpps;
                         prfmsg(OKFADD,fapusr->fapitm.docnam,
                                (INT)fapusr->fapitm.numpps,
                                fapusr->fapitm.numpps != 1 ? "s" : "");
                    }
                    else {
                         prfmsg(LSTFUL);
                         faxpmt(OKSEND);
                         return;
                    }
               }
               else {
                    prfmsg(BADDNM);
               }
          }
          faxpmt(usrptr->substt);
          break;
     case OKSEND:
          switch (cncyesno()) {
          case 'Y':
               tmpl=totchg(fapusr->baschg,fapusr->addchg,fapusr->numpps);
               if (!(realcr ? rtstcrd(tmpl) : tstcrd(tmpl))) {
                    prfmsg(BADCRD);
                    faxpmt(fapusr->mnutyp);
               }
               else {
                    faxpmt(SNDCPY);
               }
               break;
          case 'N':
               faxpmt(fapusr->mnutyp);
               break;
          default:
               prfmsg(YNAGIN);
               faxpmt(usrptr->substt);
          }
          break;
     case SNDCPY:
          switch (cncyesno()) {
          case 'Y':
               if (fapusr->sntmsg) {    /* temporarily remove DELFIL flag  */
                    modflg(fapusr->fillst,0,TXTFIL);
                    sndfax();
                    modflg(fapusr->fillst,0,TXTFIL|DELFIL);
               }
               else {
                    sndfax();
               }
               faxpmt(CPYPHO);
               break;
          case 'N':
               sndfax();
               faxpmt(fapusr->mnutyp);
               break;
          default:
               prfmsg(YNAGIN);
               faxpmt(usrptr->substt);
          }
          break;
     case CPYPHO:
          stlcpy(fapusr->phonum,cncall(),FAXPSZ);
          strcpy(tmppho,fapusr->phonum);
          stppho(tmppho);
          if (tmppho[0] == '\0') {
               faxpmt(usrptr->substt);
          }
          else if (!valpho(tmppho)) {
               prfmsg(PHONAL);
               faxpmt(usrptr->substt);
          }
          else if (!accpho(tmppho,usaptr->userid)) {
               prfmsg(NOACCP);
               faxpmt(usrptr->substt);
          }
          else {
               fapusr->baschg=baschg(tmppho);
               fapusr->addchg=addchg(tmppho);
               if (fapusr->baschg != 0L || fapusr->addchg != 0L) {
                    prfmsg(FAXRAT,l2as(fapusr->baschg),l2as(fapusr->addchg));
               }
               faxpmt(CPYTNM);
          }
          break;
     case CPYTNM:
          stlcpy(fapusr->toname,cncall(),NADSIZ);
          faxpmt(CPYTPC);
          break;
     case CPYTPC:
          stlcpy(fapusr->topic,cncall(),FTPLEN);
          faxpmt(OKSEND);
          break;
     }
}

static VOID
sndfax(VOID)                       /* go ahead and send the fax off now    */
{
     INT i;
     LONG tmp;
     CHAR *filnam;
     static CHAR tmppho[FAXPSZ];

     strcpy(tmppho,fapusr->phonum);
     stppho(tmppho);
     fixpho(tmppho);
     tmp=totchg(fapusr->baschg,fapusr->addchg,fapusr->numpps);
     if (realcr) {
          rdedcrd(tmp,1);
     }
     else {
          dedcrd(tmp,1);
     }
     begin_submit(usaptr->userid,tmp);
     submit_cover(fapusr->numpps,fapusr->toname,fapusr->frname,fapusr->topic);
     i=0;
     while (*(filnam=getfil(fapusr->fillst,i)) != '\0') {
          if (getflg(fapusr->fillst,i)&TXTFIL) {
               submit_text(filnam,getflg(fapusr->fillst,i));
          }
          else {
               submit_fax(filnam,getflg(fapusr->fillst,i));
          }
          i++;
     }
     prfmsg(OKSENT,l2as(end_submit(tmppho,"")));
}

static VOID
faxrcd(                            /* fax receive whndun routine           */
GBOOL ok)                          /*   was it received ok?                */
{
     INT i,savusn;
     struct user *usp;

     for (i=0 ; i < nterms ; i++) {
          usp=usroff(i);
          if (usp->state == fapstt && usp->substt == WT4FAX
           && othfap(i)->rcvchn == usrnum) {
               savusn=usrnum;
               curusr(i);
               clrprf();
               setmbk(fapmb);
               if (ok) {
                    fapusr->fapitm.numpps=faxpps(fapusr->fapitm.filnam);
                    prfmsg(OKRCVD);
                    faxpmt(ENTDES);
               }
               else {
                    prfmsg(BADRCV);
                    faxpmt(fapusr->mnutyp);
               }
               outprf(usrnum);
               rstmbk();
               curusr(savusn);
               break;
          }
     }
}

static SHORT
fapedn(                            /* fax text editing when done routine   */
SHORT flags)                       /*   various exit-point flags           */
{
     static CHAR filnam[GCMAXPTH];

     usrptr->state=fapstt;
     setmbk(fapmb);
     if (!(flags&ED_QUITEX) && fapbuf[usrnum][0] != '\0') {
          fapusr->sntmsg=TRUE;
          strcpy(filnam,FAXDIR SLS "TEXTMXXXXXX");
          if (mktemp(filnam) == NULL) {
               catastro("CAN'T FIND UNIQUE TEXT FILE NAME!");
          }
          fapusr->numpps+=puttxt(xltnln(fapbuf[usrnum]),"",filnam);
          addfil(fapusr->fillst,filnam,TXTFIL|DELFIL,FAPLSZ);
     }
     free(fapbuf[usrnum]);
     fapbuf[usrnum]=NULL;
     faxpmt(ATTDOC);
     rstmbk();
     outprf(usrnum);
     return(1);
}

static VOID
faxpmt(                            /* prompt a user with a new prompt      */
INT msgno)                         /*   message number to prompt with      */
{
     switch (msgno) {
     case CHGINQ:
     case SNDPHO:
     case CPYPHO:
          if (fixpup) {
               prfmsg(msgno);
          }
          else {
               prfmsg(msgno == CHGINQ ? CHGINE
                                      : (msgno == SNDPHO ? SNDPHE : CPYPHE));
          }
          break;
     case ADDITN:
          prfmsg(msgno,fapusr->fapitm.docnam,fapusr->fapitm.docdes,
                       fapusr->fapitm.lock,(INT)fapusr->fapitm.numpps,
                       fapusr->fapitm.filnam);
          break;
     case WT4FAX:
          prfmsg(msgno,spr("%x",channel[fapusr->rcvchn]));
          break;
     case DELSUR:
          prfmsg(msgno,fapusr->fapitm.docnam,fapusr->fapitm.docdes,
                       fapusr->fapitm.lock,(INT)fapusr->fapitm.numpps,
                       fapusr->fapitm.filnam);
          break;
     case DELFLT:
          prfmsg(msgno,fapusr->fapitm.filnam);
          break;
     case EDTMNU:
          prfmsg(msgno,fapusr->fapitm.docnam,fapusr->fapitm.docdes,
                       fapusr->fapitm.lock,(INT)fapusr->fapitm.numpps,
                       fapusr->fapitm.filnam);
          break;
     case SNDFNM:
          prfmsg(msgno,usaptr->usrnam);
          break;
     case ENTDOC:
          prfmsg(haskey(faxsky) ? SENTDC : msgno);
          break;
     case OKSEND:
          prfmsg(msgno,fapusr->toname,fapusr->phonum,fapusr->frname,
                 fapusr->topic,fapusr->numpps,l2as(totchg(fapusr->baschg,
                 fapusr->addchg,fapusr->numpps)),l2as(fapusr->baschg),
                 l2as(fapusr->addchg));
          break;
     case FAXMNU:
     case FPVMNU:
          if (usrptr->substt != 0) {
               condex();
          }
     default:
          prfmsg(msgno);
     }
     usrptr->substt=msgno;
}

static VOID
bgnlst(                            /* begin listing fax documents now      */
INT retsub)                        /*   return to this substt when done    */
{
     fapusr->retsub=retsub;
     dfaSetBlk(fapbb);
     if (dfaAcqLO(&fapusr->fapitm,0)) {
          faxpmt(DLSTHD);
          if (haskey(fapusr->fapitm.lock) || fapusr->mnutyp == FPVMNU) {
               prfmsg(DLSTLN,fapusr->fapitm.docnam,(INT)fapusr->fapitm.numpps,
                      fapusr->fapitm.docdes);
          }
          btuinj(usrnum,CYCLE);
     }
     else {
          prfmsg(NODOCS);
          endlst();
     }
     dfaRstBlk();
     cncall();
}

static VOID
lstcyc(VOID)                       /* listing fax documents cycled routine */
{
     if (btuoba(usrnum) > 512) {
          dfaSetBlk(fapbb);
          setmbk(fapmb);
          clrprf();
          if (dfaAcqGT(&fapusr->fapitm,fapusr->fapitm.docnam,0)) {
               if (haskey(fapusr->fapitm.lock) || fapusr->mnutyp == FPVMNU) {
                    prfmsg(DLSTLN,fapusr->fapitm.docnam,
                           (INT)fapusr->fapitm.numpps,fapusr->fapitm.docdes);
               }
               btuinj(usrnum,CYCLE);
          }
          else {
               endlst();
          }
          outprf(usrnum);
          dfaRstBlk();
          rstmbk();
     }
     else {
          btuinj(usrnum,CYCLE);
     }
}

static VOID
endlst(VOID)                       /* end listing of fax documents now     */
{
     faxpmt(fapusr->retsub);
}

static VOID
chkbuf(VOID)                       /* check the fapbuf list in case of hups*/
{
     INT i;

     for (i=0 ; i < nterms ; i++) {
          if (fapbuf[i] != NULL && usroff(i)->usrcls != ACTUSR) {
               free(fapbuf[i]);
               fapbuf[i]=NULL;
          }
     }
     rtkick(30,chkbuf);
}

static VOID
fapsts(VOID)                       /* fax application status handler       */
{
     if (usrptr->substt == DLSTHD) {
          lstcyc();
     }
}

static VOID
faphup(VOID)                       /* fax application hangup handler       */
{
     if (usrptr->state == fapstt) {
          if (usrptr->substt == WT4FAX) {
               abort_receive(fapusr->rcvchn);
          }
          if (fapbuf[usrnum] != NULL) {
               free(fapbuf[usrnum]);
               fapbuf[usrnum]=NULL;
          }
     }
}

static VOID
fapcup(VOID)                       /* cleanup routine to clean fax msgs    */
{
     INT tdy;
     struct ffblk fb;
     CHAR temp[GCMAXPTH];

     tdy=cofdat(today());
     if (fnd1st(&fb,FAXDIR SLS "textm*.*",0)) {
          do {
               if (tdy-cofdat(fb.ff_fdate) > 7) {
                    strcpy(temp,FAXDIR SLS);
                    strcat(temp,fb.ff_name);
                    unlink(temp);
               }
          } while (fndnxt(&fb));
     }
}

static VOID
clsfap(VOID)                       /* shutdown routine for fax application */
{
     dfaClose(fapbb);
     clsmsg(fapmb);
}
