/***************************************************************************
 *                                                                         *
 *   ACCSCN.C                                                              *
 *                                                                         *
 *   Copyright (c) 1992-1997 Galacticomm, Inc.      All Rights Reserved.   *
 *                                                                         *
 *   Account screen code                                                   *
 *                                                                         *
 *                                            - Robert A. Rose 02/14/92    *
 *                                                                         *
 ***************************************************************************/

#include "gcomm.h"
#include "majorbbs.h"
#include "oprlow.h"

#define FILREV "$Revision: 9 $"

VOID actrep(VOID);
VOID zappsw(VOID);
UINT actkey(UINT scncod);
VOID iniaed(UINT scncod);
VOID optedt(struct edtopt *p);
VOID optkil(VOID);
static VOID edtdone(INT sav);
VOID otipre(struct edtopt *p,INT cf);
VOID ostsho(struct edtopt *p);
VOID osysho(struct edtopt *p);
VOID oicsho(struct edtopt *p);
VOID ochsho(struct edtopt *p);
VOID oldsho(struct edtopt *p);
VOID obfsho(struct edtopt *p);
VOID oedsho(struct edtopt *p);
VOID odtsho(struct edtopt *p);
VOID ouisho(struct edtopt *p);
VOID otisho(struct edtopt *p);
VOID opwsho(struct edtopt *p);
VOID ostedt(struct edtopt *p,INT cod);
VOID osyedt(struct edtopt *p,INT cod);
VOID oicdun(INT sav);
VOID oicedt(struct edtopt *p,INT cod);
VOID ochedt(struct edtopt *p,INT cod);
VOID olddun(INT sav);
VOID oldedt(struct edtopt *p,INT cod);
VOID otidun(INT sav);
VOID otiedt(struct edtopt *p,INT cod);
VOID odtdun(INT sav);
VOID odtedt(struct edtopt *p,INT cod);
VOID obddun(INT sav);
VOID obdedt(struct edtopt *p,INT cod);
VOID olgdun(INT sav);
VOID olgedt(struct edtopt *p,INT cod);
VOID ouidun(INT sav);
VOID opwedt(struct edtopt *p,INT cod);
VOID opwdun(INT sav);
VOID ouiedt(struct edtopt *p,INT cod);
VOID obfedt(struct edtopt *p,INT cod);
VOID oededt(struct edtopt *p,INT cod);
VOID put2scn(struct usracc *accptr);
VOID filnscn(VOID);
VOID dnxact(VOID);
VOID dpract(VOID);
VOID dspact(CHAR *userid);
VOID wrifnb(VOID);
VOID updact(struct usracc *oldacp,struct usracc *newacp);
VOID clrhold(CHAR *userid);

extern INT ahdl;                   /* handle for the about screen          */
INT acchdl;                        /* account screen handle                */
extern INT audhdl;                 /* handle for the audit screen          */

#define REVHUE      0x70
#define FRAMHUE     0x1B
#define HELPHUE     0x1E

struct scrnid accnscn={
     "wgsacc.bin",                 /* screen filename                      */
     3040,                         /* length of screen (4000 for full scrn)*/
     ALT_A,                        /* select scan code (from main screen)  */
                                   /* ala 'Keyboard Accelerator'           */
     NULL,                         /* screen going away routine            */
     actrep,                       /* screen repaint routine               */
     actkey,                       /* key handler routine                  */
     NULL,                         /* occasional update routine            */
     0,                            /* seconds between occasional updates   */
     0,                            /* seconds to go before next update     */
     NULL,                         /* called every cycle when displayed    */
     2,0,                          /* current cursor position on screen    */
     0,                            /* does cursor move?                    */
     1,                            /* should screen scroll?                */
     1,1,70,17,                    /* scrolling for window (default)       */
     NULL,                         /* perm. save buffer                    */
     NULL                          /* current location of screen           */
};

#define O_ST 0           /* Get a string answer (spcl=max length)          */
#define O_SY 1           /* System type                                    */
#define O_IC 2           /* Get decimal (char len)                         */
#define O_CH 3           /* Get one character                              */
#define O_LD 4           /* Long decimal                                   */
#define O_BF 5           /* Bit flag type  (spcl=bit value in word)        */
#define O_DT 6           /* Date type                                      */
#define O_TI 7           /* Time type                                      */
#define O_UI 8           /* Unsigned int type                              */
#define O_ED 9           /* Default editor type                            */
#define O_BD 10          /* Date of Birth type                             */
#define O_LG 11          /* Language type                                  */
#define O_PW 12          /* SPECIAL CASE FOR USER PASSWORD IF ENABLED      */
#define O_NOEDT 128      /* Option is NOT EDITABLE                         */

INT accchg=0;            /* has account changed? (i.e. write it to disk?)  */
INT lngchg=0;            /* has language been changed?                     */
INT holdfil=0;           /* is there a valid account in holdbuf?           */
struct usracc holdbuf;   /* holding buffer for user data while editing     */
struct bbsgen holdgen;   /* buffer for holding user language, etc.         */
struct usracc mergbuf;   /* buffer for merging old data with new to update */
CHAR birthdate[LDATSIZ]; /* buffer for editing user's birthdate            */
static CHAR lstuid[UIDSIZ]="";

struct edtopt {                    /* editable option format               */
     CHAR up;                      /* index to go to when arrows are hit   */
     CHAR down;
     CHAR left;
     CHAR right;
     CHAR fldtyp;                  /* what type of field it is             */
     INT x,y;                      /* start of field on screen             */
     CHAR attr;                    /* attribute for field                  */
     VOID *field;                  /* location for result                  */
     INT spcl;                     /* special value (depndnt upon type)    */
};

struct edtopt *cedto,         /* option currently being edited             */
              *edbas;         /* base of option array currently being edtd */

struct edtopt accopt[]={
  { 0, 0, 0, 0,   0, 0, 0, 0,NULL,0},                 /* no editing at all        0 */
  {18, 2,20, 2,O_ST        ,10, 1,27,holdbuf.usrnam,NADSIZ-1},   /* Name                     1 */
  { 1, 3, 1, 3,O_ST        ,10, 2,27,holdbuf.usrad1,NADSIZ-1},   /* Addr1                    2 */
  { 2, 4, 2, 4,O_ST        ,10, 3,27,holdbuf.usrad2,NADSIZ-1},   /* Addr2                    3 */
  { 3, 5, 3, 5,O_ST        ,10, 4,27,holdbuf.usrad3,NADSIZ-1},   /* Addr3                    4 */
  { 4, 6, 4, 6,O_ST        ,10, 5,27,holdbuf.usrad4,NADSIZ-1},   /* Addr4                    5 */
  { 5, 7, 5, 7,O_ST        ,10, 6,27,holdbuf.usrpho,PHOSIZ-1},   /* Phone                    6 */
  { 6, 9, 6, 8,O_BD        ,10, 7,27,birthdate,LDATSIZ-1},       /* Date of Birth            7 */
  { 6, 9, 7,25,O_CH        ,27, 7,27,&holdbuf.sex,0},            /* Sex                      8 */
  {25,10,25,10,O_SY        ,10, 8,27,&holdbuf.systyp,0},         /* System                   9 */
  { 9,13, 9,11,O_IC        ,10, 9,27,&holdbuf.scnwid,0},         /* Screen width            10 */
  { 9,13,10,12,O_IC        ,16, 9,27,&holdbuf.scnfse,0},         /* Screen height           11 */
  { 9,26,11,13,O_IC        ,28, 9,27,&holdbuf.scnbrk,0},         /* Screen page breaks      12 */
  {10,24,12,26,O_ST        ,10,10,30,holdbuf.curcls,KEYSIZ-1},   /* Class                   13 */
  {24,15,24,25,O_LD+O_NOEDT,15,12,29,&holdbuf.creds,0},          /* Creds avail             14 */
  {14,16,14,16,O_LD+O_NOEDT,15,13,29,&holdbuf.totcreds,0},       /* Creds total             15 */
  {15,17,15,17,O_LD+O_NOEDT,15,14,29,&holdbuf.totpaid,0},        /* Creds paid              16 */
  {24,18,24,19,O_BF        ,18,16,30,&holdbuf.flags,HASMST},     /* master flag             17 */
  {17, 1,19,20,O_BF        ,18,17,30,&holdbuf.flags,DELTAG},     /* tag for kill flag       18 */
  {24,20,17,18,O_BF        ,35,16,30,&holdbuf.flags,SUSPEN},     /* Suspended flag          19 */
  {19, 1,18, 1,O_BF        ,35,17,30,&holdbuf.flags,UNDAXS},     /* Protected flag          20 */
  { 1,22, 2, 3,O_DT+O_NOEDT,59, 2,29,&holdbuf.credat,0},         /* Creation date           21 */
  {21,23, 3, 4,O_DT+O_NOEDT,59, 3,29,&holdbuf.usedat,0},         /* last call date          22 */
  {22, 5, 4, 5,O_TI+O_NOEDT,59, 4,29,&holdbuf.timtdy,0},         /* used today              23 */
  {13,17,26,17,O_PW        ,10,11,30,&holdbuf.psword,PSWSIZ-1},  /* password                24 */
  { 6, 9, 8, 9,O_ED        ,49, 7,27,&holdbuf.usrprf,PRFLIN},    /* default editor          25 */
  {12,24,13,24,O_LG        ,37,10,30,holdgen.lngnam ,LNGSIZ-1}}; /* default language        26 */

#define ACOSIZ (sizeof(accopt)/sizeof(accopt[0]))

                              /* number of accounting options              */

INT cedtoa,                   /* attribute of option currently being high'd*/
    bufpnt=-1;                /* buffer point being edited (-1=no editing) */
CHAR teb[20];                 /* temporary editing buffer                  */
CHAR *origbuf;
VOID (*dunrou)(INT sav);      /* routine after done with special edit      */

static                        /* Display functions for O_?? types          */
VOID (*shofcs[])(struct edtopt *)={ostsho,osysho,oicsho,ochsho,oldsho,
                                   obfsho,odtsho,otisho,ouisho,oedsho,
                                   ostsho,ostsho,opwsho};

static                        /* Editing functions for O_?? types          */
VOID (*edtfcs[])(struct edtopt *,INT cod)={ostedt,osyedt,oicedt,ochedt,oldedt,
                                           obfedt,odtedt,otiedt,ouiedt,oededt,
                                           obdedt,olgedt,opwedt};

VOID
actrep(VOID)                       /* account screen repaint routine       */
{
     if (accbb == NULL) {          /* accbb=NULL only at init time         */
          edbas=accopt;
          if (!vispsw) {
               zappsw();
          }
          return;
     }
     dfaSetBlk(accbb);
     if (!dfaAcqGE(NULL,lstuid,0)) {
          dfaAcqLO(NULL,0);
     }
     dspact(((struct usracc *)accbb->data)->userid);
}

VOID
zappsw(VOID)                       /* alter array so password is !visible  */
{
     INT i,j;
     CHAR *notvis;

     for (i=0 ; i < ACOSIZ ; i++) {
          if (accopt[i].field == holdbuf.psword) {
               break;
          }
     }
     if (i != ACOSIZ) {  /* password field not found: shouldn't happen now */
          for (j=0 ; j < ACOSIZ ; j++) {
               if (accopt[j].up == i) {
                    accopt[j].up=accopt[i].up;
               }
               if (accopt[j].down == i) {
                    accopt[j].down=accopt[i].down;
               }
               if (accopt[j].left == i) {
                    accopt[j].left=accopt[i].left;
               }
               if (accopt[j].right == i) {
                    accopt[j].right=accopt[i].right;
               }
          }
          notvis="<not displayed, for security reasons>";
          accopt[i].field=notvis;
          accopt[i].spcl=strlen(notvis);
     }
}

UINT
actkey(                       /* accnt screen keystroke handler routine    */
UINT scncod)
{
     actvscn(acchdl);
     if (scncod >= F1 && scncod <= F10) {
          optkil();
          wrifnb();
          return(scncod);
     }
     if (bufpnt == -1) {
          switch (scncod) {
          case TAB:
               optkil();
               wrifnb();
               scn2mai(audhdl);
               break;
          case BAKTAB:
               optkil();
               wrifnb();
               scn2mai(ahdl);
               break;
          case PGUP:
               optkil();
               wrifnb();
               dpract();
               break;
          case PGDN:
               optkil();
               wrifnb();
               dnxact();
               break;
          case ESC:
               optkil();
               dspact(lstuid);
               break;
          case CRSRUP:
               if (cedto == NULL) {
                    optedt(&edbas[1]);
               }
               else {
                    optedt(&edbas[cedto->up]);
               }
               break;
          case CRSRDN:
               if (cedto == NULL) {
                    optedt(&edbas[1]);
               }
               else {
                    optedt(&edbas[cedto->down]);
               }
               break;
          case CRSRLF:
               if (cedto == NULL) {
                    optedt(&edbas[1]);
               }
               else {
                    optedt(&edbas[cedto->left]);
               }
               break;
          case CRSRRT:
               if (cedto == NULL) {
                    optedt(&edbas[1]);
               }
               else {
                    optedt(&edbas[cedto->right]);
               }
               break;
          case INS:
          case DEL:
          case HOME:
          case END:
               if (cedto == NULL) {
                    optedt(&edbas[1]);
               }
               iniaed(scncod);
               break;
          case 0x0d:                    /* start editing an option         */
          default:
               if (scncod <= ALT_M && scncod >= ALT_Q) {
                    optkil();
                    wrifnb();
                    return(scncod);
               }
               if (scncod == '\x0d' || (scncod >= ' ' && scncod <= '~')
                || (scncod >= '€' && scncod <= '¥')
                || (scncod >= 'à' && scncod <= 'ï')) {
                    if (cedto == NULL) {
                         optedt(&edbas[1]);
                    }
                    iniaed(scncod);
                    return(0);
               }
          }
     }
     else {
          if ((cedto->fldtyp&0x7f) > 9) {
               catastro("BAD FLDTYP! (%d)",cedto->fldtyp);
          }
          if (cedto->fldtyp < 0x7f) {
               (edtfcs[cedto->fldtyp&0x7f])(cedto,scncod);
          }
     }
     return(0);
}

VOID
iniaed(UINT scncod)                /* start editing an option (uses bufpnt)*/
{
     if (holdfil && cedto->fldtyp < 0x7f) {
          bufpnt=0;
          scnids[acchdl].curmove=1;
          if (mainhdl == acchdl) {
               cursiz(GVIDLILCURS);
          }
          locate(cedto->x,cedto->y);
          (edtfcs[cedto->fldtyp&0x7f])(cedto,scncod);
     }
}

static VOID
clrhold(                      /* clear holding buffer (acct doesn't exist) */
CHAR *userid)                 /*   userid to label blank acct screen with  */
{
     CHAR tmpuid[UIDSIZ];     /* (in case userid points at holdbuf.userid) */

     stzcpy(tmpuid,userid,UIDSIZ);
     memset(&holdbuf,0,sizeof(holdbuf));
     strcpy(holdbuf.userid,tmpuid);
     memset(&holdgen,0,sizeof(holdgen));
     memset(birthdate,0,sizeof(birthdate));
     accchg=lngchg=holdfil=0;
}

VOID
optedt(struct edtopt *p)           /* make this option the input focus     */
{
     if (holdfil && p->fldtyp < 0x7f) {
          optkil();
          cedtoa=p->attr;
          cedto=p;
          p->attr=REVHUE;
          otipre(p,0);
          (shofcs[p->fldtyp&0x7f])(p);
     }
}

VOID
optkil(VOID)                  /* make the input focus NO LONGER the focus  */
{
     if (cedto != NULL) {
          cedto->attr=cedtoa;
          otipre(cedto,0);
          (shofcs[cedto->fldtyp&0x7f])(cedto);
          cedto=NULL;
     }
     if (mainhdl == acchdl) {
          cursiz(GVIDNOCURS);
     }
     bufpnt=-1;
}

static
VOID
edtdone(INT sav)                   /* come here when done editing a field  */
{
     if (dunrou != NULL) {
          (*dunrou)(sav);
     }
     dunrou=NULL;
     bufpnt=-1;
     scnids[acchdl].curmove=0;
     cedto->attr=cedtoa;
     otipre(cedto,0);
     (shofcs[cedto->fldtyp&0x7f])(cedto);
}

VOID
otipre(struct edtopt *p,INT cf)    /* setup to edit an option, w|w/o cursor*/
{
     if (mainhdl == acchdl) {
          cursiz(cf ? GVIDLILCURS : GVIDNOCURS);
          cursact(cf);
     }
     locate(p->x,p->y);
     sstatr(p->attr);
}

VOID
ostsho(struct edtopt *p)           /* show a string answer                 */
{
     CHAR buff[60];

     if (p->field) {
          sprintf(buff,"%-*.*s",p->spcl,p->spcl,(CHAR *)p->field);
          printf("%s",buff);
     }
}

VOID
osysho(struct edtopt *p)           /* show a system type                   */
{
     printf("%-30.30s",sysstg[(SHORT)*(CHAR *)(p->field)]);
}

VOID
oicsho(struct edtopt *p)      /* show an integer (one byte long though)    */
{
     CHAR buf[4];

     sprintf(buf,"%d",(INT)*(CHAR *)p->field);
     printf("%-3.3s",buf);
}

VOID
ochsho(struct edtopt *p)           /* show a character                     */
{
     printf("%c",*(CHAR *)(p->field));
}

VOID
oldsho(struct edtopt *p)           /* show a long decimal                  */
{
     CHAR tmp[25];

     sprintf(tmp,"%ld",lngval(p->field));
     printf("%11.11s",tmp);
}

VOID
obfsho(struct edtopt *p)           /* show a bit flag                      */
{
     if (((*(CHAR *)(p->field))&p->spcl) != 0) {
          printf("YES");
     }
     else {
          printf("NO ");
     }
}

VOID
oedsho(struct edtopt *p)           /* show a editor bit flag               */
{

     if (((*(CHAR *)(p->field))&p->spcl) != 0) {
          printf("LINE");
     }
     else {
          printf("FSE ");
     }
}

VOID
odtsho(struct edtopt *p)           /* show a date                          */
{
     printf("%s",shtval(p->field) == 0 ? "----------"
                                       : ncdatel(shtval(p->field)));
}

VOID
ouisho(struct edtopt *p)           /* show an unsigned int                 */
{
     printf("%5.5u",shtval(p->field));
}

VOID
otisho(struct edtopt *p)           /* show a time                          */
{
     INT hr,mn,sc;
     LONG tim;

     tim=lngval(p->field);
     sc=(INT)(tim%60);
     tim/=60;
     mn=(INT)(tim%60);
     tim/=60;
     hr=(INT)tim;
     printf("%2.2d:%02.2d:%02.2d",hr,mn,sc);
}

VOID
opwsho(struct edtopt *p)           /* show special password                */
{
     CHAR buff[60];

     if (p->field) {
          sprintf(buff,"%-*.*s",p->spcl,p->spcl,(CHAR *)p->field);
          printf("%s",buff);
     }
}

VOID
ostedt(struct edtopt *p,INT cod)   /* edit a string option value           */
{
     INT i;
     CHAR *cp;

     switch (cod) {
     case CRSRUP:
     case CRSRDN:
     case 0x0d:
          for (i=strlen(p->field)-1 ; i >= 0 ; i--) {
               if (*((CHAR *)p->field+i) > ' ') {
                    break;
               }
               *((CHAR *)p->field+i)='\0';
          }
          edtdone(1);
          if (cod == CRSRUP || cod == CRSRDN) {
               actkey(cod);
          }
          return;
     case ESC:
          edtdone(0);
          optkil();
          dspact(lstuid);
          return;
     case HOME:
          bufpnt=0;
          break;
     case END:
          bufpnt=-1;
          for (i=p->spcl-1 ; i >= 0 ; i--) {
               if (*((CHAR *)p->field+i) > ' ') {
                    bufpnt=i;
                    break;
               }
          }
          if (bufpnt != p->spcl-1) {
               bufpnt++;
          }
          break;
     case 0x08:
          if (bufpnt > 0) {
               movmem((CHAR *)p->field+bufpnt,(CHAR *)p->field+bufpnt-1,
                p->spcl-bufpnt);
               *((CHAR *)p->field+p->spcl-1)=' ';
               bufpnt--;
               accchg=1;
          }
          break;
     case INS:
          movmem((CHAR *)p->field+bufpnt,(CHAR *)p->field+bufpnt+1,
           p->spcl-bufpnt-1);
          *((CHAR *)p->field+bufpnt)=' ';
          accchg=1;
          break;
     case 0x7f:
     case DEL:
          movmem((CHAR *)p->field+bufpnt+1,(CHAR *)p->field+bufpnt,
           p->spcl-bufpnt-1);
          *((CHAR *)p->field+p->spcl-1)=' ';
          accchg=1;
          break;
     case CRSRLF:
          if (bufpnt > 0) {
               bufpnt--;
          }
          break;
     case CRSRRT:
          if (bufpnt < p->spcl && (*((CHAR *)p->field+bufpnt) != 0)) {
               bufpnt++;
          }
          break;
     default:
          if (bufpnt < p->spcl && (cod >= ' ' && cod <= '~'
           || cod >= '€' && cod <= '¥' || cod >= 'à' && cod <= 'ï')) {
               cp=((CHAR *)p->field+bufpnt++);
               if (*cp == '\0') {
                    *(cp+1)='\0';
               }
               *cp=cod;
               accchg=1;
          }
     }
     otipre(p,1);
     ostsho(p);
     locate(p->x+bufpnt,p->y);
     cursact(0);
}

VOID
osyedt(struct edtopt *p,INT cod)   /* edit the "system type" field value   */
{
     switch (cod) {
     case 0x0d:
          edtdone(1);
          return;
     case ESC:
          edtdone(0);
          optkil();
          dspact(lstuid);
          return;
     default:
          *(CHAR *)(p->field)=((*(CHAR *)(p->field))+1)%8;
          accchg=1;
          otipre(p,1);
          osysho(p);
     }
}

VOID
oicdun(INT sav)               /* done editing single-byte integer value    */
{
     INT ev;

     sscanf(teb,"%d",&ev);
     cedto->field=origbuf;
     cedto->fldtyp=O_IC;
     cedto->spcl=0;
     if (sav) {
          *(CHAR *)(cedto->field)=(CHAR)(ev&0xFF);
          accchg=1;
     }
}

VOID
oicedt(struct edtopt *p,INT cod)   /* edit a single-byte integer value     */
{
     p->fldtyp=O_ST;
     origbuf=p->field;
     p->field=teb;
     p->spcl=3;
     dunrou=oicdun;
     printf("%-3.3d",*(CHAR *)(p->field));
     setmem(teb,sizeof(teb),0);
     iniaed(cod);
}

VOID
ochedt(struct edtopt *p,INT cod)  /* edit a single-character sex field value */
{
     switch (cod) {
     case 0x0d:
          edtdone(1);
          return;
     case ESC:
          edtdone(0);
          optkil();
          dspact(lstuid);
          break;
     default:
          if ((cod&0xFF80) == 0 && ((cod=toupper(cod)) == 'M' || cod == 'F')) {
               *(CHAR *)(p->field)=cod;
               accchg=1;
          }
          otipre(p,1);
          ochsho(p);
          cursact(1);
          locate(p->x+bufpnt,p->y);
     }
}

VOID
olddun(INT sav)               /* done editing a long decimal field value   */
{
     LONG ev;

     sscanf(teb,"%ld",&ev);
     cedto->field=origbuf;
     cedto->fldtyp=O_LD;
     cedto->spcl=0;
     if (sav) {
          lngset(cedto->field,ev);
          accchg=1;
     }
}

VOID
oldedt(struct edtopt *p,INT cod)   /* edit a long decimal field value      */
{
     p->fldtyp=O_ST;
     origbuf=p->field;
     p->field=teb;
     p->spcl=11;
     dunrou=olddun;
     printf("%-11.11ld",lngval(p->field));
     setmem(teb,sizeof(teb),0);
     iniaed(cod);
}

VOID
otidun(INT sav)               /* done editing a time (HH:MM:SS) value      */
{
     ULONG ev;
     UINT hour,mint,sec;

     hour=mint=sec=0;
     sscanf(teb,"%d:%d:%d",(INT *)&hour,(INT *)&mint,(INT *)&sec);
     ev=sec+(LONG)(mint*60L)+(LONG)(hour*3600L);
     cedto->field=origbuf;
     cedto->fldtyp=O_TI;
     cedto->spcl=0;
     if (sav && ev != 0xFFFFFFFFUL) {
          *(ULONG *)(cedto->field)=ev;
          accchg=1;
     }
}

VOID
otiedt(struct edtopt *p,INT cod)   /* edit a time field value              */
{
     p->fldtyp=O_ST;
     origbuf=p->field;
     p->field=teb;
     p->spcl=8;
     dunrou=otidun;
     setmem(teb,sizeof(teb),0);
     iniaed(cod);
}

VOID
odtdun(INT sav)               /* done editing a date field value           */
{
     INT ev;

     ev=dcdate(teb);
     cedto->field=origbuf;
     cedto->fldtyp=O_DT;
     cedto->spcl=0;
     if (sav && ev != -1) {
          shtset(cedto->field,ev);
          accchg=1;
     }
}

VOID
odtedt(struct edtopt *p,INT cod)   /* edit a date field value              */
{
     p->fldtyp=O_ST;
     origbuf=p->field;
     p->field=teb;
     p->spcl=8;
     dunrou=odtdun;
     setmem(teb,sizeof(teb),0);
     iniaed(cod);
}

VOID
obddun(INT sav)               /* done editing a date of birth field value  */
{
     INT y,m,d;
     CHAR tmpbuf[LDATSIZ];

     cedto->field=origbuf;
     cedto->fldtyp=O_BD;
     stlcpy(tmpbuf,teb,LDATSIZ);
     if (sav && okbday(tmpbuf)) {
          sDateDecode(tmpbuf,&y,&m,&d);
          ASSERT(validDate(y,m,d));
          prnDate(y,m,d,cedto->field,LDATSIZ,PRND_MDYY,'/');
          accchg=1;
     }
}

VOID
obdedt(struct edtopt *p,INT cod)   /* edit a date of birth field value     */
{
     p->fldtyp=O_ST;
     origbuf=p->field;
     p->field=teb;
     dunrou=obddun;
     setmem(teb,sizeof(teb),0);
     iniaed(cod);
}

VOID
olgdun(INT sav)               /* done editing a language field value       */
{
     INT ilingo;

     cedto->field=origbuf;
     cedto->fldtyp=O_LG;
     if (sav) {
          if (teb[0] == '\0') {
               ((CHAR *)cedto->field)[0]='\0';
               accchg=lngchg=1;
          }
          else if ((ilingo=lngfnd(teb)) != -1) {
               strcpy(cedto->field,languages[ilingo]->name);
               accchg=lngchg=1;
          }
     }
}

VOID
olgedt(struct edtopt *p,INT cod)   /* edit a language field value          */
{
     p->fldtyp=O_ST;
     origbuf=p->field;
     p->field=teb;
     dunrou=olgdun;
     setmem(teb,sizeof(teb),0);
     iniaed(cod);
}

VOID
ouidun(INT sav)               /* done editing an unsigned integer value    */
{
     UINT ev;

     sscanf(teb,"%u",(INT *)&ev);
     cedto->field=origbuf;
     cedto->fldtyp=O_UI;
     cedto->spcl=0;
     if (sav) {
          *(UINT *)(cedto->field)=ev;
          accchg=1;
     }
}

VOID
ouiedt(struct edtopt *p,INT cod)   /* edit an unsigned integer field value */
{
     p->fldtyp=O_ST;
     origbuf=p->field;
     p->field=teb;
     p->spcl=5;
     dunrou=ouidun;
     printf("%5.5u",*(UINT *)(p->field));
     setmem(teb,sizeof(teb),0);
     iniaed(cod);
}

VOID
obfedt(struct edtopt *p,INT cod)   /* edit a binary flag value             */
{
     if (cod == 0x0d) {
          edtdone(1);
          return;
     }
     if (cod == ESC) {
          edtdone(0);
          optkil();
          dspact(lstuid);
          return;
     }
     if (((*(CHAR *)(p->field))&p->spcl) == 0) {
          *(CHAR *)(p->field)|=p->spcl;
     }
     else {
          *(CHAR *)(p->field)&=(~p->spcl);
     }
     accchg=1;
     otipre(p,1);
     obfsho(p);
}

VOID
oededt(struct edtopt *p,INT cod)   /* edit a editor flag value             */
{
     if (cod == 0x0d) {
          edtdone(1);
          return;
     }
     if (cod == ESC) {
          edtdone(0);
          optkil();
          dspact(lstuid);
          return;
     }
     if (((*(CHAR *)(p->field))&p->spcl) == 0) {
          *(CHAR *)(p->field)|=p->spcl;
     }
     else {
          *(CHAR *)(p->field)&=(~p->spcl);
     }
     accchg=1;
     otipre(p,1);
     oedsho(p);
}

VOID
opwedt(struct edtopt *p,INT cod)   /* edit a password option with minimum  */
{
     p->fldtyp=O_ST;
     origbuf=p->field;
     p->field=teb;
     p->spcl=PSWSIZ-1;
     dunrou=opwdun;
     printf("%-*.*d",PSWSIZ-1,PSWSIZ-1,*(CHAR *)(p->field));
     setmem(teb,sizeof(teb),0);
     iniaed(cod);
}

VOID
opwdun(INT sav)                    /* done editing password field          */
{
     cedto->field=origbuf;
     cedto->fldtyp=O_PW;
     if (sav) {
          if (strlen(teb) >= minpwd) {
               stzcpy(cedto->field,teb,PSWSIZ);
               accchg=1;
               return;
          }
     }
     accchg=0;
}

VOID
put2scn(accptr)               /* put changed credit data to screen if nec  */
struct usracc *accptr;
{
     if (sameas(accptr->userid,holdbuf.userid)) {
          holdbuf.creds=accptr->creds;
          holdbuf.totcreds=accptr->totcreds;
          holdbuf.totpaid=accptr->totpaid;
          strcpy(holdbuf.curcls,accptr->curcls);
          filnscn();
     }
}

VOID
filnscn(VOID)                 /* fill in the screen image based on acc     */
{
     INT i;
     struct edtopt *opt;

     actvscn(acchdl);
     sstatr(REVHUE);
     printfat(12,0,"%s ",holdbuf.userid);
     sstatr(FRAMHUE);
     for (i=strlen(holdbuf.userid)+1 ; i < 37 ; i++) {
          printf("Í");
     }
     for (i=0 ; i < ACOSIZ ; i++) {
          opt=&(edbas[i]);
          otipre(opt,0);
          (shofcs[opt->fldtyp&0x7f])(opt);
     }
     sstatr(HELPHUE);
     if (holdfil) {
          printfat(45,13,"®¯   Pick field to edit");
          printfat(45,14,"ENTER  Save changed info ");
          printfat(45,15,"ESC    Don't save changes");
     }
     else {
          printfat(45,13,"This account record does ");
          printfat(45,14,"   not exist on disk!    ");
          printfat(45,15,"ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ");
     }
}

VOID
dnxact(VOID)                       /* display next account screen          */
{
     dfaSetBlk(accbb);
     if (dfaAcqGT(NULL,lstuid,0) || dfaAcqHI(NULL,0)) {
          dspact(((struct usracc *)accbb->data)->userid);
     }
}

VOID
dpract(VOID)                       /* display previous account screen      */
{
     dfaSetBlk(accbb);
     if (dfaAcqLT(NULL,lstuid,0) || dfaAcqLO(NULL,0)) {
          dspact(((struct usracc *)accbb->data)->userid);
     }
}

VOID
dspact(CHAR *userid)               /* detail account screen routine        */
{
     dfaSetBlk(accbb);
     strcpy(lstuid,userid);
     holdfil=1;
     accchg=lngchg=0;
     if (onsysn(userid,1)) {
          movmem(othuap,&holdbuf,sizeof(struct usracc));
          strcpy(holdgen.userid,userid);
          strcpy(holdgen.modnam,BBSGMX);
          strcpy(holdgen.lngnam,languages[othusp->lingo]->name);
          stlcpy(birthdate,strBirthdate(holdbuf.birthd),LDATSIZ);
     }
     else if (dfaAcqEQ(&holdbuf,userid,0)) {
          getgen(&holdgen,userid);
          stlcpy(birthdate,strBirthdate(holdbuf.birthd),LDATSIZ);
     }
     else {
          clrhold(userid);
     }
     filnscn();
}

VOID
wrifnb(VOID)                  /* write account if need be                  */
{
     INT ilingo;
     CHAR tmpbdy[LDATSIZ];

     dfaSetBlk(accbb);
     if (accchg) {
          if (lngchg) {
               getgen(&genbuf,holdbuf.userid);
               if (!sameas(holdgen.lngnam,genbuf.lngnam)) {
                    strcpy(genbuf.lngnam,holdgen.lngnam);
                    setgen(&genbuf);
               }
          }
          stlcpy(tmpbdy,birthdate,LDATSIZ);
          if (okbday(tmpbdy)) {
               stlcpy(holdbuf.birthd,tmpbdy,DATSIZ);
          }
          if (onsysn(holdbuf.userid,1)) {
               updact(othuap,&holdbuf);
               if (lngchg && (ilingo=lngfnd(holdgen.lngnam)) != -1) {
                    othusp->lingo=ilingo;
               }
          }
          else {
               dfaGetEQ(&mergbuf,holdbuf.userid,0);
               updact(&mergbuf,&holdbuf);
               dfaUpdate(&mergbuf);
               if (onbbs(holdbuf.userid,1)) {
                    movmem(&mergbuf,uacoff(uisusn),sizeof(struct usracc));
               }
          }
     }
     dfaRstBlk();
     accchg=lngchg=0;
}

static VOID
updact(                            /* update edited account fields         */
struct usracc *oldacp,
struct usracc *newacp)
{
     movmem(newacp->userid,oldacp->userid,
         (INT)((CHAR *)&newacp->credat-newacp->userid));
     oldacp->flags=newacp->flags;
     stzcpy(oldacp->birthd,newacp->birthd,DATSIZ);
     if (!sameas(newacp->curcls,oldacp->curcls)) {
          if (fndcls(newacp->curcls) != NULL) {
               swtcls(oldacp,1,newacp->curcls,3,0);
          }
     }
}
