/***************************************************************************
 *                                                                         *
 *   REGISTRY.C                                                            *
 *                                                                         *
 *   Copyright (c) 1988-1997 Galacticomm, Inc.    All Rights Reserved.     *
 *                                                                         *
 *   This is the Worldgroup user "registry" module.                        *
 *                                                                         *
 *                                  - T. Stryker & S. Brinker 1/24/88      *
 *                                                                         *
 ***************************************************************************/

#include "gcomm.h"
#include "majorbbs.h"
#include "registry.h"
#include "galregis.h"

#define FILREV "$Revision: 14 $"

static VOID makrar(VOID);
GBOOL regnot(VOID);
INT gloreg(VOID);
GBOOL regrou(VOID);
static VOID regrou1(VOID);
static VOID regrou2(VOID);
static VOID regrou3(VOID);
static VOID regrou4(VOID);
static VOID regrou5(VOID);
static VOID regrou6(VOID);
static VOID regrou7(VOID);
static VOID regrou8(VOID);
static VOID regrou9(VOID);
static VOID regrou10(VOID);
static VOID regmnu(VOID);
static VOID shwpro(INT msg,INT msg2);
VOID shwprop(INT msg,INT msg2,struct regrec *rblkpt);
static INT pcts(CHAR *buf);
VOID reglst(VOID);
static VOID getdir(VOID);
static VOID go2mai(VOID);
VOID delreg(CHAR *uid);
VOID clsreg(VOID);
DFAFILE **getregbb(void);

struct module registry={      /* module interface block               */
     "",                      /*    name used to refer to this module */
     regnot,                  /*    user logon supplemental routine   */
     regrou,                  /*    input routine if selected         */
     reglst,                  /*    status-input routine if selected  */
     NULL,                    /*    "injoth" routine for this module  */
     NULL,                    /*    user logoff supplemental routine  */
     NULL,                    /*    hangup (lost carrier) routine     */
     NULL,                    /*    midnight cleanup routine          */
     delreg,                  /*    delete-account routine            */
     clsreg                   /*    finish-up (sys shutdown) routine  */
};

HMCVFILE REGEXP regmb;        /* registry named-message file block handle  */
DFAFILE * REGEXP regbb;       /* registry btrieve message file block ptr.  */

struct regusr {
     INT fldidx;              /* current field index for creation, editing */
     INT flags;               /* registry user's bit-definable flags       */
     LONG fpos;               /* file position for directory output        */
     struct regrec regblk;    /* user's current registry record in mem.    */
};                            /* dynamically allocated regusr array        */

                              /* definition of registry bit "flags"        */
#define CRTMNU 1              /* show create menu                          */
#define UPDYOU 2              /* need to update "your" user file           */
#define GOTONE 4              /* gotten a user-id lookup once already      */

struct reginf REGEXP reginf[MAXFLD]; /* array of registry field info              */

static
INT regstt;                   /* User Registry state                       */

INT REGEXP numfds;            /* number of configured fields               */

CHAR * REGEXP regkey,         /* key req'd to create registry entries      */
     * REGEXP viewkey,        /* key req'd to view other's entries         */
     * REGEXP delkey;         /* key req'd to delete other's registrys     */

GBOOL regnag;                 /* Nag users to fill out their registry?     */

#define regptr ((struct regusr *)vdaptr)

GBOOL reginit=FALSE;             /* flag to make sure init routine is only */
                                 /* done once.                             */

VOID EXPORT
init__galreg(VOID)               /* initialize registry module           */
{
     if (reginit == FALSE) {     /* ensure we only init once!            */
          stzcpy(registry.descrp,gmdnam("galreg.mdf"),MNMSIZ);
          regstt=register_module(&registry);
          regmb=opnmsg("galregis.mcv");
          regkey=stgopt(REGKEY);
          viewkey=stgopt(VIEWKEY);
          delkey=stgopt(DELKEY);
          regnag=ynopt(REGNAG);
          dclvda(sizeof(struct regusr));
          makrar();
          regbb=dfaOpen("galreg2.dat",sizeof(struct regrec),NULL);
          globalcmd(gloreg);
          inicsregis();
          reginit=TRUE;
     }
}

static VOID
makrar(VOID)                       /* make registry array from .MSG file   */
{
     INT curidx;
     CHAR *tmprmsg;

     curidx=0;
     for (numfds=0 ; numfds < MAXFLD ; numfds++) {
          tmprmsg=rawmsg(fldmsg(numfds)+PMTOFF);
          if (tmprmsg[0] != '\0') {
               if (strlen(tmprmsg) > outbsz) {
                    catastro("REGISTRY: QUESTION #%d IS TOO BIG!\n"
                             "The size of a registry question cannot be larger"
                             "than your output buffer size.",numfds+1);
               }
               stpans(tmprmsg=rawmsg(fldmsg(numfds)+SIZOFF));
               if ((reginf[numfds].anssiz=atoi(tmprmsg)) != 0) {
                    reginf[numfds].ansidx=curidx;
                    curidx+=reginf[numfds].anssiz+1;
                    if (curidx > PROSIZ) {
                         catastro("REGISTRY: TOTAL SIZE OF REGISTRY ANSWERS "
                                  "TOO LARGE!\nThe total of all the answers' "
                                  "lengths must not be\nmore than %d."
                                  ,PROSIZ-MAXFLD);
                    }
               }
               else {
                    catastro("REGISTRY: INVALID ANSWER SIZE SPECIFIED FOR"
                             " QUESTION #%d!",numfds+1);
               }
          }
          else {
               break;
          }
     }
}

GBOOL
regnot(VOID)                       /* notify user to fill out registry     */
{
     if (!(usrptr->flags&WSGCSU) && haskey(regkey)) {
          dfaSetBlk(regbb);
          setmbk(regmb);
          if (*(ncdate(usaptr->usedat)) != '\0' && !dfaQueryEQ(usaptr->userid,0)
           && haskey(regkey) && regnag) {
               prfmsg(REGPLS);
               outprf(usrnum);
          }
     }
     return(FALSE);
}

INT
gloreg(VOID)                       /* global registry-lookup command       */
{
     if (margc > 1 && sameas(margv[0],"/r")) {
          setmbk(regmb);
          if (haskey(viewkey)) {
               dfaSetBlk(regbb);
               rstrin();
               nxtcmd=margv[1];
               if (dfaAcqEQ(vdatmp,cncuid(),0)) {
                    prfmsg(ENTFOR,((struct regrec *)vdatmp)->userid);
                    shwprop(RENTRY,SUMDSP,(struct regrec *)vdatmp);
               }
               else {
                    prfmsg(NOSUID);
               }
          }
          else {
               prfmsg(NOVAXS);
          }
          outprf(usrnum);
          return(1);
     }
     else if (margc > 1 && sameas(margv[0],"/rdel")) {
          setmbk(regmb);
          if (haskey(delkey)) {
               dfaSetBlk(regbb);
               rstrin();
               nxtcmd=margv[1];
               if (dfaAcqEQ(vdatmp,cncuid(),0)) {
                    prfmsg(ENTDEL,((struct regrec*)vdatmp)->userid);
                    dfaDelete();
               }
               else {
                    prfmsg(NOSUID);
               }
               outprf(usrnum);
          }
          return(1);
     }
     return(0);
}

GBOOL
regrou(VOID)                       /* main registry input handler          */
{
     setmbk(regmb);
     dfaSetBlk(regbb);
     if ((margc == 1) && (sameas(margv[0],"x") || sameas(margv[0],"exit"))) {
          clrxrf();
          if (regptr->flags&UPDYOU) {
               regptr->flags&=~UPDYOU;
               dfaGetEQ(NULL,usaptr->userid,0);
               dfaUpdate(&regptr->regblk);
          }
          switch (usrptr->substt) {
          case 1:
               return(FALSE);
          case 4:
          case 5:
               prfmsg(NOTDUN);
          case 9:
          case 10:
               regptr->flags&=~GOTONE;
          case 2:
          case 3:
          case 6:
               btumil(usrnum,DFTIMX);
               go2mai();
               break;
          case 7:
          case 8:
               btumil(usrnum,DFTIMX);
               if (isripu()) {
                    prfmsg(YOUARE);
                    shwpro(EDTENT,SUMEDT);
               }
               prfmsg(EDTWHT);
               usrptr->substt=6;
               break;
          }
     }
     else {
          do {
               bgncnc();
               switch (usrptr->substt) {
               case 0:
                    setmem(regptr,vdasiz,0);
                    cncchr();
                    usrptr->flags&=~X2MAIN;
                    if (!dfaAcqEQ(&(regptr->regblk),usaptr->userid,0)) {
                         regptr->flags|=CRTMNU;
                         prfmsg(GENINF);
                    }
                    regmnu();
                    usrptr->substt=1;
                    break;
               case 1:
                    regrou1();
                    break;
               case 2:
                    regrou2();
                    break;
               case 3:
                    regrou3();
                    break;
               case 4:
                    regrou4();
                    break;
               case 5:
                    regrou5();
                    break;
               case 6:
                    regrou6();
                    break;
               case 7:
                    regrou7();
                    break;
               case 8:
                    regrou8();
                    break;
               case 9:
                    regrou9();
                    break;
               case 10:
                    regrou10();
                    break;
               }
          } while (!endcnc());
     }
     outprf(usrnum);
     return(TRUE);
}

static VOID
regrou1(VOID)                      /* registry menu sub-state handler      */
{
     if (margc == 0) {
          regmnu();
     }
     else {
          switch (cncchr()) {
          case 'G':
               prfmsg(GENINF);
          case '?':
               regmnu();
               break;
          case 'D':
               prfmsg(DIRPMT);
               btumil(usrnum,4);
               usrptr->substt=2;
               break;
          case 'Y':
               if (!haskey(regkey)) {
                    prfmsg(NOYSIR);
                    howbuy();
                    regmnu();
               }
               else {
                    if (numfds > 0) {
                         if (regptr->flags&CRTMNU) {
                              btumil(usrnum,reginf[0].anssiz);
                              regptr->fldidx=0;
                              prfmsg(BGNCRT);
                              prfmsg(fldmsg(0)+PMTOFF);
                              usrptr->substt=4;
                         }
                         else {
                              dfaGetEQ(&regptr->regblk,usaptr->userid,0);
                              prfmsg(YOUARE);
                              shwpro(EDTENT,SUMEDT);
                              prfmsg(EDTWHT);
                              usrptr->substt=6;
                         }
                    }
                    else {
                         prfmsg(ENTSUM);
                         btumil(usrnum,SUMSIZ-1);
                         usrptr->substt=5;
                    }
               }
               break;
          case 'L':
               if (haskey(viewkey)) {
                    prfmsg(UIDTOL);
                    usrptr->substt=9;
               }
               else {
                    prfmsg(NOVAXS);
                    howbuy();
                    regmnu();
               }
               break;
          default:
               prfmsg(NOSUCH);
               cncall();
               go2mai();
          }
     }
}

static VOID
regrou2(VOID)                      /* begin directory sub-state handler    */
{
     if (margc == 0) {
          prfmsg(DIRPMT);
     }
     else if (sameas(nxtcmd,"?")) {
          prfmsg(DINTRO);
     }
     else {
          if (dfaQueryGE(cncuid(),0)) {
               btumil(usrnum,DFTIMX);
               dfaAbsRec(&regptr->regblk,0);
               prfmsg(TITLIN2);
               prfmsg(DIRLIN,regptr->regblk.userid,regptr->regblk.sumlin);
               usrptr->substt=3;
               btuinj(usrnum,CYCLE);
               regptr->fpos=dfaAbs();
          }
          else {
               prfmsg(NEXIST);
               prfmsg(DIRPMT);
          }
     }
     cncall();
}

static VOID
regrou3(VOID)                      /* listing directory sub-state handler  */
{
     btuclo(usrnum);
     prfmsg(ABORTD);
     go2mai();
     cncall();
}

static VOID
regrou4(VOID)                      /* fill out registry sub-state handler  */
{
     if (margc == 0 || sameas(nxtcmd,"?")) {
          prfmsg(fldmsg(regptr->fldidx)+PMTOFF);
     }
     else if (pfnlvl > 1) {
          prfmsg(BCLEAN);
          prfmsg(fldmsg(regptr->fldidx)+PMTOFF);
     }
     else {
          movmem(cncall(),
               regptr->regblk.profil+reginf[regptr->fldidx].ansidx,
               reginf[regptr->fldidx].anssiz);
          regptr->fldidx++;
          if (regptr->fldidx < numfds) {
               btumil(usrnum,reginf[regptr->fldidx].anssiz);
               prfmsg(fldmsg(regptr->fldidx)+PMTOFF);
          }
          else {
               prfmsg(ENTSUM);
               btumil(usrnum,SUMSIZ-1);
               usrptr->substt=5;
          }
     }
     cncall();
}

static VOID
regrou5(VOID)                      /* fill out summary sub-state handler   */
{
     if (margc == 0 || sameas(nxtcmd,"?")) {
          prfmsg(ENTSUM);
     }
     else if (pfnlvl > 1) {
          prfmsg(BCLEAN);
          prfmsg(ENTSUM);
     }
     else {
          movmem(cncall(),regptr->regblk.sumlin,SUMSIZ-1);
          movmem(usaptr->userid,regptr->regblk.userid,UIDSIZ);
          dfaInsert(&regptr->regblk);
          btumil(usrnum,DFTIMX);
          regptr->flags&=~CRTMNU;
          prfmsg(THANKS);
          go2mai();
     }
     cncall();
}

static VOID
regrou6(VOID)                      /* edit registry sub-state handler      */
{
     INT temp;

     if (margc == 0) {
          if (isripu()) {
               prfmsg(YOUARE);
               shwpro(EDTENT,SUMEDT);
          }
          prfmsg(EDTWHT);
     }
     else if (sameas(nxtcmd,"?")) {
          prfmsg(YOUARE);
          shwpro(EDTENT,SUMEDT);
          prfmsg(EDTWHT);
          cncall();
     }
     else {
          if ((temp=cncint()) == 99) {
               prfmsg(ENTNSM);
               btumil(usrnum,SUMSIZ-1);
               usrptr->substt=8;
          }
          else if (temp < 1 || temp > numfds) {
               prfmsg(NOSUCH);
               if (isripu()) {
                    prfmsg(YOUARE);
                    shwpro(EDTENT,SUMEDT);
               }
               prfmsg(EDTWHT);
               cncall();
          }
          else {
               regptr->fldidx=temp-1;
               btumil(usrnum,reginf[regptr->fldidx].anssiz);
               prfmsg(ENTNEW,temp);
               usrptr->substt=7;
          }
     }
}

static VOID
regrou7(VOID)                      /* enter new info sub-state handler     */
{
     if (margc == 0 || sameas(nxtcmd,"?")) {
          prfmsg(NEWINF);
          cncall();
     }
     else if (pfnlvl > 1) {
          prfmsg(BCLEAN);
          prfmsg(NEWINF);
          cncall();
     }
     else {
          movmem(cncall(),
           regptr->regblk.profil+reginf[regptr->fldidx].ansidx,
           reginf[regptr->fldidx].anssiz);
          regptr->flags|=UPDYOU;
          btumil(usrnum,DFTIMX);
          prfmsg(UPDATD);
          if (isripu()) {
               prfmsg(YOUARE);
               shwpro(EDTENT,SUMEDT);
          }
          prfmsg(EDTWHT);
          usrptr->substt=6;
     }
}

static VOID
regrou8(VOID)                      /* enter new summary sub-state handler  */
{
     if (margc == 0 || sameas(nxtcmd,"?")) {
          prfmsg(ENTNSM);
          cncall();
     }
     else if (pfnlvl > 1) {
          prfmsg(BCLEAN);
          prfmsg(ENTNSM);
          cncall();
     }
     else {
          movmem(cncall(),regptr->regblk.sumlin,SUMSIZ-1);
          btumil(usrnum,DFTIMX);
          regptr->flags|=UPDYOU;
          prfmsg(UPDATD);
          if (isripu()) {
               prfmsg(YOUARE);
               shwpro(EDTENT,SUMEDT);
          }
          prfmsg(EDTWHT);
          usrptr->substt=6;
     }
}

static VOID
regrou9(VOID)                      /* look-up a user sub-state handler     */
{

     if (margc == 0 || sameas(nxtcmd,"?")) {
          prfmsg((regptr->flags&GOTONE) ? UIDTLN : UIDTOL);
     }
     else if (strlen(nxtcmd) < 3 && morcnc() == 'N') {
          cncchr();
          if (dfaAcqGT(&regptr->regblk,regptr->regblk.userid,0)) {
               prfmsg(ENTFOR,regptr->regblk.userid);
               shwpro(RENTRY,SUMDSP);
               regptr->flags|=GOTONE;
               prfmsg(UIDTLN);
          }
          else {
               regptr->flags&=~GOTONE;
               btumil(usrnum,DFTIMX);
               prfmsg(ALDONE);
               go2mai();
          }
     }
     else {
          regrou10();
     }
     cncall();
}

static VOID
regrou10(VOID)                     /* handle user-id input with hdluid()   */
{
     switch (hdluid(margc == 0 ? languages[clingo]->yes : cncall())) {
     case UIDPMT:
          prfmsg((regptr->flags&GOTONE) ? UIDTLN : UIDTOL);
          break;
     case UIDFND:
          if (dfaAcqEQ(&regptr->regblk,uidxrf.userid,0)) {
               prfmsg(ENTFOR,regptr->regblk.userid);
               shwpro(RENTRY,SUMDSP);
               regptr->flags|=GOTONE;
               prfmsg(UIDTLN);
          }
          else {
               clrxrf();
               prfmsg(NOSUID);
               prfmsg((regptr->flags&GOTONE) ? UIDTLN : UIDTOL);
          }
          break;
     case UIDCAL:
          usrptr->substt=10;
          return;
     }
     usrptr->substt=9;
}

static VOID
regmnu(VOID)                       /* display main registry menu           */
{
     prfmsg((regptr->flags&CRTMNU) ? CREMNU : EDTMNU);
}

static VOID
shwpro(msg,msg2)                   /* display a user's profile             */
INT msg,msg2;
{
     shwprop(msg,msg2,&regptr->regblk);
}

VOID
shwprop(msg,msg2,rblkpt)         /* display a profile pointed to by rblkpt */
INT msg,msg2;
struct regrec *rblkpt;
{
     CHAR *datptr,*orgbuf,*buf;
     INT i,hold,skount;

     datptr=rblkpt->profil;
     buf=rawmsg(msg);
     orgbuf=buf;
     i=0;
     while (*buf != '\0') {
          if ((skount=pcts(buf)) > 0) {
               buf+=skount;
               hold=*buf;
               *buf='\0';
               prf(orgbuf,datptr+reginf[i++].ansidx);
               *buf=hold;
               orgbuf=buf;
          }
          else {
               if (*buf == '\n') {
                    *buf='\r';
               }
               buf++;
          }
     }
     prf(orgbuf);
     prfmsg(msg2,rblkpt->sumlin);
}

static INT
pcts(buf)                          /* prf() utility for shwpro()           */
CHAR *buf;
{
     INT i;
     CHAR *bp;

     bp=buf;
     if (*bp == '%') {
          i=2;
          while (*++bp == '-' || isdigit(*bp) || *bp == '.') {
               i++;
          }
          if (*bp == 's') {
               return(i);
          }
          if (*bp == ESC) {
               catastro("ANSI codes inside one of the %%-symbols in a user\n"
                        "registry template.  (Try editing the text block and\n"
                        "removing all ANSI coding using <Alt-E>.)");
          }
          catastro("Bad symbol in user registry template: \"%s\"",
                   spr("%-0.*s",(INT)(bp-buf+1),buf));
     }
     return(0);
}

VOID
reglst(VOID)                       /* status handler: registry listing     */
{
     setmbk(regmb);
     if (usrptr->substt == 3 && status == CYCLE) {
          dfaSetBlk(regbb);
          getdir();
     }
     else {
          dfsthn();
     }
}

static VOID
getdir(VOID)                       /* get records in registry directory    */
{
     if ((btuoba(usrnum)) >= 500) {
          dfaGetAbs(NULL,regptr->fpos,0);
          if (dfaQueryNX()) {
               movmem(regbb->data,&regptr->regblk,sizeof(struct regrec));
               prfmsg(DIRLIN,regptr->regblk.userid,regptr->regblk.sumlin);
               outprf(usrnum);
               regptr->fpos=dfaAbs();
          }
          else {
               prfmsg(DIREND);
               go2mai();
               outprf(usrnum);
               return;
          }
     }
     btuinj(usrnum,CYCLE);
}

static VOID
go2mai(VOID)                     /* go back to main registry menu, or exit */
{
     condex();
     isripu() ? regmnu() : prfmsg(SHRMNU);
     usrptr->substt=1;
}

VOID
delreg(uid)                        /* delete utility: delete registry entry*/
CHAR *uid;
{
     dfaSetBlk(regbb);
     if (dfaAcqEQ(NULL,uid,0)) {
          dfaDelete();
     }
}

VOID
clsreg(VOID)                       /* close registry files for shutdown    */
{
     clsmsg(regmb);
     dfaClose(regbb);
}

DFAFILE ** EXPORT
getregbb(void)                     /* return the address of regbb          */
{
     return(&regbb);
}/*   this is left to support legacy ISV code which may seek it. -DFP */
