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

#include <errno.h>
#include "gcomm.h"
#include "majorbbs.h"
#include "wgsmajor.h"
#include "oprlow.h"
#include "statscns.h"
#ifdef GCWINNT
#include "majorwin.h"
#endif // GCWINNT

#define FILREV "$Revision: 24 $"

#define CMLSIZ 80             /* max input command-line length             */
#define SKBSIZ 50             /* max number of keys used to construct it   */

#define CMWYUL 19             /* command window y-top boundary             */
#define CMWXLR 77             /* command window x-right boundary           */
#define CMWXUL  2             /* command window x-left boundary            */
#define CMWYLR 21             /* command window y-bottom boundary          */

VOID (*shochl_hook)(INT chan)=NULL;     /* shochl hook for C/S applications*/
VOID (*rsyfad_hook)(VOID)=NULL;         /* rsyfad hook for C/S audit trail */
VOID dspact(CHAR *userid);
CHAR *rtmfmt(ULONG ntval);
VOID calrtm(VOID);
VOID sysrtm(VOID);

VOID fasadd(VOID);                 /* from AUDIT.C                         */

extern INT rsetop;            /* reset option: busy=B; no-answer=N         */
extern INT visbel;            /* bell setting when emulation is visible    */
extern INT invbel;            /* bell setting when emulation is hidden     */
extern INT sopaud;            /* route Audit Trail stuff to online Sysop   */
extern INT auxist;            /* secondary CRT support                     */
extern INT maxscns;           /* maximum number of screens                 */
extern INT kilipg;            /* kill-system command in progress           */
extern INT kilctr;            /* number of minutes to shutdown             */
extern INT kilsrc;            /* kill-cmd src (-1=console, -2=MCU, -3=auto)*/

extern INT errcod;            /* MS-DOS exit code (for batch files)        */

INT lblhue=0x1F;              /* soft-key labels display attribute code    */
static
INT kilnow;                   /* system has been slated for kill "NOW"     */

struct otrail {               /* trail structure for backspace key         */
     struct otrail *link;     /*   link                                    */
     INT opistt;              /*   operator input state                    */
     CHAR *cmlptr;            /*   command-line string pointer             */
} opinf;                      /* trail header                              */

CHAR cmlbuf[CMLSIZ];          /* command line input buffer                 */
INT skbuf[SKBSIZ],            /* soft-key input buffer                     */
    *skbptr,                  /* soft-key buffer pointer                   */
    *skbpeu,                  /* skbptr value upon transition to ENTUID    */
    quiefl;                   /* quiet soft-key legends just put in place  */
CHAR cskbuf[SKBSIZ];          /* collapsed (char-wise) soft-key input buf  */

#define SK_QUIET    0         /* nothing going on                          */
#define SK_DISPLAY  1         /* 'Display ...'                             */
#define SK_DISSAVR  2         /* 'Display saver after...                   */
#ifdef UNIX
#define SK_DISUNIX  3         /* 'Display unix specific info               */
#else
#define SK_DISAUXC  3         /* 'Display on aux crt...                    */
#endif
#define SK_SEND     4         /* 'Send...'                                 */
#define SK_KILL     5         /* 'Kill...'                                 */
#define SK_KILLCHN  6         /* 'Kill channel...'                         */
#define SK_KILLSYS  7         /* 'Kill system...'                          */
#define SK_ENTER    8         /* <ENTER>                                   */
#define SK_UID      9         /* Asking for UID (no enter)                 */
#define SK_UIDENTER 10        /* Asking for UID (and enter is ok)          */
#define SK_INPMSG   11        /* Inputting a message                       */
#define SK_KILLCHN2 12        /* 'Kill channel ?' (second digit)           */
#define SK_KILLCHNM 13        /* 'Kill channel xx' (get mode or enter only)*/
#define SK_INPCHN   14        /* Getting first digit of channel number     */
#define SK_INPCHN2  15        /* Getting second digit of channel number    */
#define SK_DISPOST  16        /* Display position set                      */
#define SK_PDORFREE 17        /* Paid or free credits?                     */
#define SK_CRDAMTS  18        /* list of popular numbers                   */
#define SK_MSGTOTS  19        /* totals of various msg types               */

#ifdef UNIX
                              /* soft-key legend table                     */
CHAR *sklegs[][10]={
/*0*/{" help  "," send  ","display"," post  ","detail","set msg"," login ","       ","       "," kill  "},
/*1*/{"mem usd","message","dsk avl","rsptime","accnts"," calls ","uploads","dnloads"," unix  "," saver "},
/*2*/{" 1 min "," 2 min "," 5 min ","30 min "," 1 hr "," never ","       ","       ","       ","       "},
/*3*/{" 1 min "," 5 min "," 15 min","freemem","      ","       ","       ","       ","       ","       "},
/*4*/{"  ALL  ","channel","       ","       ","      ","       ","       ","       ","       ","       "},
/*5*/{"User-ID","account","channel","       ","      ","       ","       ","       ","system ","       "},
/*6*/{"       ","       ","       ","       ","      ","       ","       ","       ","       ","       "},
/*7*/{"in 1min","in 2min","in 5min","in10min","      "," UNDO! ","       "," asap  ","       "," NOW!  "},
/*8*/{"       ","       ","       ","       ","      ","       ","       ","       ","<ENTER>","       "},
/*9*/{"       ","       ","       ","       ","      ","       ","       ","       ","       ","       "},
/*0*/{"       ","       ","       ","       ","      ","       ","       ","       ","<ENTER>","       "},
/*1*/{"  OK   ","       ","       ","       ","      ","       ","       ","       ","       "," QUIT  "},
/*2*/{"busyout","no-ansr","normal ","       ","      ","       ","       ","       ","<ENTER>","       "},
/*3*/{"busyout","no-ansr","normal ","       ","      ","       ","       ","       ","<ENTER>","       "},
/*4*/{"       ","       ","       ","       ","      ","       ","       ","       ","       ","       "},
/*5*/{"       ","       ","       ","       ","      ","       ","       ","       ","<ENTER>","       "},
/*6*/{"   1   ","   2   ","   3   ","   4   ","  5   ","   6   ","       ","       ","       ","       "},
/*7*/{" PAID  "," FREE  ","       ","       ","      ","       ","       ","       ","       ","       "},
/*8*/{" 1800  "," 3600  "," 7200  "," 18000 ","36000 ","72000  ","180000 ","360000 ","720000 ","       "},
/*9*/{" Total "," Email "," Forum ","       ","      ","       ","       ","       ","       ","       "},
};
#else
CHAR *sklegs[][10]={
/*0*/{" help  "," send  ","display"," post  ","detail","set msg"," login ","       ","       "," kill  "},
#ifdef GCDOS
/*1*/{"mem avl","message","dsk avl","rsptime","accnts"," calls ","uploads","dnloads","aux crt"," saver "},
#else
/*1*/{"mem avl","message","dsk avl","rsptime","accnts"," calls ","uploads","dnloads","       ","       "},
#endif // GCDOS
/*2*/{" 1 min "," 2 min "," 5 min ","30 min "," 1 hr "," never ","       ","       ","       ","       "},
/*3*/{"nothing","account"," audit ","emulate","stats ","monitor"," users "," about ","       ","       "},
/*4*/{"  ALL  ","channel","       ","       ","      ","       ","       ","       ","       ","       "},
/*5*/{"User-ID","account","channel","       ","      ","       ","       ","       ","system ","       "},
/*6*/{"       ","       ","       ","       ","      ","       ","       ","       ","       ","       "},
/*7*/{"in 1min","in 2min","in 5min","in10min","      "," UNDO! ","       "," asap  ","       "," NOW!  "},
/*8*/{"       ","       ","       ","       ","      ","       ","       ","       ","<ENTER>","       "},
/*9*/{"       ","       ","       ","       ","      ","       ","       ","       ","       ","       "},
/*0*/{"       ","       ","       ","       ","      ","       ","       ","       ","<ENTER>","       "},
/*1*/{"  OK   ","       ","       ","       ","      ","       ","       ","       ","       "," QUIT  "},
/*2*/{"busyout","no-ansr","normal ","       ","      ","       ","       ","       ","<ENTER>","       "},
/*3*/{"busyout","no-ansr","normal ","       ","      ","       ","       ","       ","<ENTER>","       "},
/*4*/{"       ","       ","       ","       ","      ","       ","       ","       ","       ","       "},
/*5*/{"       ","       ","       ","       ","      ","       ","       ","       ","<ENTER>","       "},
/*6*/{"   1   ","   2   ","   3   ","   4   ","  5   ","   6   ","       ","       ","       ","       "},
/*7*/{" PAID  "," FREE  ","       ","       ","      ","       ","       ","       ","       ","       "},
/*8*/{" 1800  "," 3600  "," 7200  "," 18000 ","36000 ","72000  ","180000 ","360000 ","720000 ","       "},
/*9*/{" Total "," Email "," Forum ","       ","      ","       ","       ","       ","       ","       "},
};
#endif                        /* UNIX                                      */

#define NUMOFP 9                   /* # audit trail entries visible at once*/
#define NOENTRIES 0xFFFFFFFFL      /* position if audit trail empty        */

LONG atbptr,                  /* (obsolete) audit trail window-bottom pos  */
     atptrs[NUMOFP];          /* (obsolete) audit trail record positions   */
DFAFILE *audbb=NULL;          /* (obsolete) Btrieve ptr for audit trail    */

HAUDFILE hAuditTrail=0;            /* audit trail file handle              */
ULONG sumLastVisible;              /* last audit trail entry on summary scr*/

extern ULONG audLastVisible;       /* last audit trail entry on audit scrn */

extern struct scrnid accnscn;           /* Account screen variables        */
extern INT acchdl;
extern struct scrnid audiscn;           /* Audit screen variables          */
extern INT audhdl;
extern struct scrnid emulscn;           /* Emulation screen variables      */
extern INT ehdl;
extern struct scrnid emfuscn;
extern INT emful;
extern struct scrnid statscn;           /* Graph screen variables          */
extern INT stahdl;
extern struct scrnid monascn;           /* monitor all screen variables    */
extern INT mhdl;
extern struct scrnid ussscn;            /* Users screen variables          */
extern INT usshdl;
extern struct scrnid abouscn;           /* about screen variables          */
extern INT ahdl;
extern struct scrnid lsesscn;           /* local login screen variables    */
extern INT lsehdl;
extern struct scrnid hlpscn;            /* help screen variables           */
extern INT hlphdl;

INT stthue=0x1D,              /* Audit Trail display attribute code        */
    ndfhue=0x13,              /* undefined channels display attribute code */
    gphhue=0x1E,              /* System load graph display attribute       */
    vtxhue=0x1A;              /* variable text display attribute code      */

INT vcx,vcy;                  /* virtual cursor location                   */

INT shdl;                     /* handle for the summary screen             */
INT atmess=0;                 /* has the audit trail been changed?         */
extern INT emubel;            /* period for emulation bells                */

USHORT c;                     /* key passed to us                          */
INT fiddle=0;                 /* have we processed this key?               */

struct uidisp *uidarr;        /* users screen info array                   */

#define LILYELBOX '\376'      /* little yellow box character               */

INT sysload[60];              /* System loading per minute                 */
INT intload;                  /* interval load accumulator                 */
INT invocnt;                  /* invocation counter                        */

static
CHAR savmins[10]={1,2,5,30,60,0,0,0,0,0};

INT sndchn;                   /* destination for message to be sent        */
CHAR txtstg[MTXSIZ],          /* message text string buffer                */
     *txtptr;                 /* message text string pointer               */

struct scrnid summscn={
     "wgss.bin",              /* screen filename                           */
     4000,                    /* length of screen (4000 for full screen)   */
     ALT_S,                   /* select scan code (from main screen)       */
                              /* ala 'Keyboard Accelerator'                */
     NULL,                    /* screen going away routine                 */
     sumrep,                  /* screen repaint routine                    */
     sumkey,                  /* key handler routine                       */
     sumocc,                  /* occasional update routine                 */
     15,                      /* 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?                         */
     0,                       /* should screen scroll?                     */
     1,1,79,20,               /* scrolling for window (default)            */
     NULL,                    /* perm. save buffer                         */
     NULL                     /* current location of screen                */
};

static
CHAR *minlabl="00   15   30   45   00   15   30   45   ";

#define RTMRAT 2              /* response time display rate (seconds)      */
#define RTMSMP 4              /* response time smooth factor (5s halflife) */
#define LOADFX 164L           /* rsptim/syslod ratio:  65536 * 2.5 / 1000  */
#define HRTONE 0x00010000UL   /* 1 second, in 1/65536 units (ala hrtval()) */

VOID (*oldsys)(VOID);         /* saved value for (*syscyc)()               */
ULONG rtmcnt=0L;              /* count of system cycles in RTMRAT period   */
ULONG rtmfst=0L;              /* hrtval() at 1st cycle in RTMRAT period    */
ULONG rtmlst=0L;              /* hrtval() at last cycle in RTMRAT period   */
ULONG rtmlls=0L;              /* hrtval() at next-to-last cycle in period  */
ULONG rsptim=0L;              /* avg response time, in 1/65536 sec units   */
static GBOOL fRespDataCollected=FALSE; // some response data has being collected

VOID sumPrintEntry(const struct audOldStyle *entry);

VOID
sumocc(VOID)                  /* Summary screen occasional update          */
{
     INT cmin;

     cmin=dtmin(now());
     if (invocnt%4 == 0) {
          sysload[cmin]=intload/4;
          intload=0;
          loadgph(cmin);
     }
     invocnt++;
     intload+=linsusd();
     doaditbx();
}

UINT
sumkey(                       /* Summary screen keystroke handler routine  */
UINT scncod)                       /* keystroke hit                        */
{
     ULONG nRecs;
     INT i;

     fiddle=0;
     c=scncod;
     if ((c == 8 || c == 27 || c == CRSRLF)
      && opinf.opistt != SK_INPMSG
      && opinf.opistt != SK_QUIET) {
          bckspc();
          fiddle=1;
     }
     else {
          switch(scncod) {
          case TAB:
               if (mainhdl == shdl) {
                    scn2mai(usshdl);
                    fiddle=1;
               }
               else {
                    i=skcipg;
                    skcipg=0;
                    keyhit(scncod);
                    skcipg=i;
               }
               break;
          case BAKTAB:
               if (mainhdl == shdl) {
                    scn2mai(mhdl);
                    fiddle=1;
               }
               else {
                    i=skcipg;
                    skcipg=0;
                    keyhit(scncod);
                    skcipg=i;
               }
               break;
          case HOME:
               nRecs=audLastRec();
               if (nRecs != NOENTRIES) {
                    nRecs=min(NUMOFP-2,nRecs);
               }
               if (nRecs != sumLastVisible) {
                    sumLastVisible=nRecs;
                    iniaud();
                    atmess=1;
               }
               fiddle=1;
               break;
          case END:
               nRecs=audLastRec();
               if (nRecs != sumLastVisible) {
                    sumLastVisible=nRecs;
                    iniaud();
                    atmess=0;
               }
               fiddle=1;
               break;
          case PGUP:
               scroat(-NUMOFP);
               fiddle=1;
               break;
          case PGDN:
               scroat(NUMOFP);
               fiddle=1;
               break;
          case CRSRUP:
               scroat(-1);
               fiddle=1;
               break;
          case CRSRDN:
               scroat(1);
               fiddle=1;
               break;
          default:
               if ((scncod >= F1 && scncod <= F10) || skcipg) {
                    softgroup();
                    fiddle=1;
               }
          }
     }
     skcipg=(opinf.opistt != SK_QUIET);
     if (!fiddle && scncod == ESC) {
          keyhit(F7);
     }
     return(fiddle ? 0 : scncod);
}

VOID
softgroup(VOID)
{
     actvscnsp(dfltmscn,CMWXUL,CMWYUL,CMWXLR,CMWYLR,1);
     switch (opinf.opistt) {
     case SK_QUIET:
          squiet();
          break;
     case SK_SEND:
          ssndac();
          break;
     case SK_DISPLAY:
          sseldsp();
          break;
     case SK_CRDAMTS:
          sentamt();
          break;
     case SK_PDORFREE:
          sentapf();
          break;
     case SK_KILL:
          skill();
          break;
     case SK_KILLSYS:
          sentmin();
          break;
     case SK_KILLCHN:
     case SK_KILLCHN2:
     case SK_KILLCHNM:
          scklmod();
          break;
     case SK_INPCHN:
          sinpchn();
          break;
     case SK_INPCHN2:
          sinpch2();
          break;
     case SK_ENTER:
          if (c == '\r' || c == F9) {
               retkey();
          }
          break;
     case SK_DISPOST:
          sselpos();
          break;
     case SK_MSGTOTS:
          smsgdsp();
          break;
#ifdef UNIX
     case SK_DISUNIX:
          sunxscr();
#else
     case SK_DISAUXC:
          sauxcrt();
#endif
          break;
     case SK_DISSAVR:
          sscnsav();
          break;
     case SK_UID:
          sentuid();
          break;
     case SK_UIDENTER:
          if (isuidc(c&eurmsk) && skbptr-skbpeu < UIDSIZ-1) {
               c=c&eurmsk;
               hdlskc(SK_UIDENTER);
          }
          if (c == '\r' || c == F9) {
               retkey();
          }
          break;
     case SK_INPMSG:
          dwtxte();
          break;
     }
}

VOID
squiet(VOID)                       /* main menu of soft keys               */
{
     switch (c) {
     case F1:
          if (chlpfn() != NULL) {
               iniscn(chlpfn(),actvscn(hlphdl));
               scn2mai(hlphdl);
          }
          break;
     case F2:
          hdlsk("Send a message to ",SK_SEND);
          break;
     case F3:
          hdlsk("Display ",SK_DISPLAY);
          break;
     case F4:
          hdlsk("Post ",SK_CRDAMTS);
          break;
     case F5:
          hdlsk("Detail info on User-ID: ",SK_UID);
          skbpeu=skbptr;
          break;
     case F6:
          hdlsk("Set log-on message",SK_ENTER);
          break;
     case F7:
          scn2mai(lsehdl);
          if (usroff(nterms-1)->usrcls == VACANT) {
               entlse(nterms-1);
          }
          break;
     case F10:
          hdlsk("Kill ",SK_KILL);
          break;
     }
}

VOID
sseldsp(VOID)                      /* select "display" variable            */
{
     switch (c) {
     case F1:
          hdlsk("memory available in position ",SK_DISPOST);
          break;
     case F2:
          hdlsk("messages: ",SK_MSGTOTS);
          break;
     case F3:
          hdlsk("disk space available in position ",SK_DISPOST);
          break;
     case F4:
          hdlsk("average response time in position ",SK_DISPOST);
          break;
     case F5:
          hdlsk("total number of accounts in position ",SK_DISPOST);
          break;
     case F6:
          hdlsk("total number of calls to date in position ",SK_DISPOST);
          break;
     case F7:
          hdlsk("total number of uploads to date in position ",SK_DISPOST);
          break;
     case F8:
          hdlsk("total number of downloads to date in position ",SK_DISPOST);
          break;
#ifdef UNIX
     case F9:
          hdlsk("Unix specific info: ",SK_DISUNIX);
          break;
#else
#ifndef GCWINNT
     case F9:
          hdlsk("on auxiliary CRT ",SK_DISAUXC);
          break;
#endif // GCWINNT
#endif // UNIX
#ifndef GCWINNT
     case F10:
          hdlsk("screen saver after ",SK_DISSAVR);
          break;
#endif // GCWINNT
     }
}

VOID
smsgdsp(VOID)                      /* select "display" variables           */
{
     switch (c) {
     case F1:
          hdlsk("total no. of E-mail & Forum msgs in position ",SK_DISPOST);
          break;
     case F2:
          hdlsk("open no. of E-mail msgs in position ",SK_DISPOST);
          break;
     case F3:
          hdlsk("open no. of Forum msgs in position ",SK_DISPOST);
          break;
     }
}

VOID
sscnsav(VOID)                      /* select screen saver option           */
{
     switch (c) {
     case F1:
          hdlsk("1 min. unused",SK_ENTER);
          break;
     case F2:
          hdlsk("2 min. unused",SK_ENTER);
          break;
     case F3:
          hdlsk("5 min. unused",SK_ENTER);
          break;
     case F4:
          hdlsk("30 min. unused",SK_ENTER);
          break;
     case F5:
          hdlsk("1 hour unused",SK_ENTER);
          break;
     case F6:
          hdlsk("never",SK_ENTER);
          break;
     }
}

VOID
skill(VOID)
{
     switch (c) {
     case F1:
          hdlsk("(suspend) User-ID: ",SK_UID);
          skbpeu=skbptr;
          break;
     case F2:
          hdlsk("user-account database record of User-ID: ",SK_UID);
          skbpeu=skbptr;
          break;
     case F3:
          hdlsk("channel no. ",SK_KILLCHN);
          break;
     case F9:
          hdlsk("system ",SK_KILLSYS);
          break;
     }
}

VOID
sentmin(VOID)                      /* select a minute count      */
{
     switch (c) {
     case F1:
          hdlsk("within 1 minute",SK_ENTER);
          break;
     case F2:
          hdlsk("within 2 minutes",SK_ENTER);
          break;
     case F3:
          hdlsk("within 5 minutes",SK_ENTER);
          break;
     case F4:
          hdlsk("within 10 minutes",SK_ENTER);
          break;
     case F6:
          hdlsk("UNDO!",SK_ENTER);
          break;
     case F8:
          hdlsk("as soon as possible",SK_ENTER);
          break;
     case F10:
          hdlsk("NOW",SK_ENTER);
          break;
     }
}

#ifdef UNIX
VOID
sunxscr(VOID)
{
     switch(c) {
     case F1:
          hdlsk("1 minute load average in position ", SK_DISPOST);
          break;
     case F2:
          hdlsk("5 minute load average in position ", SK_DISPOST);
          break;
     case F3:
          hdlsk("15 minute load average in position ", SK_DISPOST);
          break;
     case F4:
          hdlsk("Free Memory in position ", SK_DISPOST);
          break;
     }
}
#else
VOID
sauxcrt(VOID)                      /* select screen for aux. crt           */
{
     switch (c) {
     case F1:
          hdlsk("nothing",SK_ENTER);
          break;
     case F2:
          hdlsk("the account screen",SK_ENTER);
          break;
     case F3:
          hdlsk("the audit trail",SK_ENTER);
          break;
     case F4:
          hdlsk("the emulation screen",SK_ENTER);
          break;
     case F5:
          hdlsk("the statistics screen",SK_ENTER);
          break;
     case F6:
          hdlsk("the monitor-all screen",SK_ENTER);
          break;
     case F7:
          hdlsk("the users screen",SK_ENTER);
          break;
     case F8:
          hdlsk("the about screen",SK_ENTER);
          break;
     }
}
#endif

VOID
scklmod(VOID)                      /* enter a channel to kill and a mode   */
{
     if (opinf.opistt != SK_KILLCHNM && isxdigit(c&eurmsk)) {
          c=toupper(c&eurmsk);
          hdlskc(opinf.opistt == SK_KILLCHN ? SK_KILLCHN2 : SK_KILLCHNM);
     }
     else if (opinf.opistt != SK_KILLCHN) {
          switch (c) {
          case F1:
               hdlsk(" to \"BUSY-OUT\"",SK_ENTER);
               break;
          case F2:
               hdlsk(" to \"NO-ANSWER\"",SK_ENTER);
               break;
          case F3:
               hdlsk(" to normal",SK_ENTER);
               break;
          case F9:
          case '\r':
               retkey();
               break;
          }
     }
}

VOID
ssndac(VOID)                       /* send message to channel or all       */
{
     switch (c) {
     case F1:
          hdlsk("ALL online channels ",SK_ENTER);
          break;
     case F2:
          hdlsk("channel no. ",SK_INPCHN);
          break;
     }
}

VOID
sentamt(VOID)                      /* enter amount of credits to post      */
{
     CHAR tmpbuf[10];

     if (isdigit(c&eurmsk) || c == '-') {
          hdlskc(SK_PDORFREE);
     }
     else if (c >= F1 && c <= F10) {
          strcpy(tmpbuf,skpwht(sklegs[SK_CRDAMTS][(c-F1)>>8]));
          depad(tmpbuf);
          hdlskm(tmpbuf,SK_PDORFREE);
     }
}

VOID
sentapf(VOID)                      /* enter "paid" or "free" credits       */
{
     switch (c) {
     case F1:
          hdlsk(" PAID credits to User-ID: ",SK_UID);
          skbpeu=skbptr;
          break;
     case F2:
          hdlsk(" FREE credits to User-ID: ",SK_UID);
          skbpeu=skbptr;
          break;
     default:
          if (isdigit(c&eurmsk) && strlen(cmlbuf) < 13) {
               hdlskc(SK_PDORFREE);
          }
     }
}

VOID
sentuid(VOID)                      /* enter a user-id                      */
{
     if (isuidc(c&eurmsk)) {
          c=c&eurmsk;
          if (skbptr == skbpeu) {
               hdlskc(SK_UID);
          }
          else {
               if (skbptr-skbpeu < 2) {
                    hdlskc(SK_UID);
               }
               else {
                    hdlskc(SK_UIDENTER);
               }
          }
     }
}

VOID
dwtxte(VOID)                       /* deal with text entered               */
{
     INT clrcurs;

     locate(vcx,vcy);
     sstatr(lblhue);
     if (c == F1) {
          clrcurs=1;
          xltctls(txtstg);
          if (*(txtptr-1) == '\r') {
               *--txtptr='\0';
          }
          if (sndchn == -2) {
               strcpy(sv.lonmsg,txtstg);
          }
          else if (txtptr == txtstg) {
               sstatr(lblhue);
               printf(" \nNULL -- MESSAGE IGNORED ");
               clrcurs=0;
          }
          else if (sndchn >= 0) {
               snd2ch(sndchn,txtstg);
          }
          else if (sndchn == -1) {
               snd2al(txtstg);
          }
          vcx=curcurx();
          vcy=curcury();
          if (clrcurs) {
               setatr(lblhue);
               printf(" ");
          }
          quiesk(0);
          return;
     }
     else if (c == F10) {
          sstatr(lblhue);
          printf(" \nQUIT -- MESSAGE IGNORED ");
          vcx=curcurx();
          vcy=curcury();
          quiesk(0);
          return;
     }
     else if (c == 8 && txtptr != txtstg && *(txtptr-1) != '\r') {
          printf(" \10\10");
          *--txtptr='\0';
     }
     else if (txtptr-txtstg < MTXSIZ-1) {
          if (c == '\r') {
               printf(" \n");
               *txtptr++=(CHAR)c;
               *txtptr='\0';
          }
          else if (c >= ' ' && (c&eurmsk)) {
               printf("%c",c);
               *txtptr++=(CHAR)c;
               *txtptr='\0';
          }
     }
     vcx=curcurx();
     vcy=curcury();
     setatr(lblhue+0x80);
     printf("Ü");
     if (vcx >= 77) {
          printf("\b ");
          vcx=curcurx();
          vcy=curcury();
          printf("Ü");
     }
}

VOID
sselpos(VOID)                      /* select position for variables        */
{
     CHAR tbuf[2]={0,0};

     if (c >= '1' && c <= '6') {
          c=F1+((c-'1')<<8);
     }
     tbuf[0]='1'+((c-F1)>>8);
     if (tbuf[0] >= '1' && tbuf[0] <= '6') {
          hdlsk(tbuf,SK_ENTER);
     }
}

VOID
sinpchn(VOID)                      /* input a channel number (first digit) */
{
     if (isxdigit(c&eurmsk)) {
          c=toupper(c&eurmsk);
          hdlskc(SK_INPCHN2);
     }
}

VOID
sinpch2(VOID)                      /* input a channel number (second digit)*/
{
     if (isxdigit(c&eurmsk)) {
          c=toupper(c&eurmsk);
          hdlskc(SK_ENTER);
     }
     else if (c == '\r' || c == F9) {
          retkey();
     }
}

VOID
sumrep(VOID)                  /* Summary screen repaint routine            */
{
     loadgph(dtmin(now()));
     doaditbx();
}

VOID
inisho(VOID)
{
     INT rc;

     inilopr(maxscns,auxist);
     shdl=regscn(&summscn);
     backhdl=shdl;
     mhdl=regscn(&monascn);
     ahdl=regscn(&abouscn);
     emful=regscn(&emfuscn);
     ehdl=regscn(&emulscn);
     inidst();
     stahdl=regscn(&statscn);
     audhdl=regscn(&audiscn);
     acchdl=regscn(&accnscn);
     lsehdl=regscn(&lsesscn);
     hlphdl=regscn(&hlpscn);
     dfltmscn=shdl;
     quiesk(1);
     actvscn(shdl);
     scn2mai(shdl);
     auxups(sv.monmal);
     rc=audfOpen(&hAuditTrail,AUDITFILE,AUDMODE_READWRITE);
     if (rc == AUDERR_DAMAGED) {
          actvscn(shdl);
          setatr(stthue);
          printfat(32,20,"Rebuilding Audit Trail       ");
          rc=audfRecover(hAuditTrail);
          printfat(32,20,"                             ");
     }
     if (rc < AUDERR_OK) {
          if (rc == AUDERR_FIO) {
               catastro("I/O ERROR OPENING AUDIT TRAIL (%d)",errno);
          }
          else {
               catastro("ERROR OPENING AUDIT TRAIL (%d)",rc);
          }
     }
     sumLastVisible=audLastVisible=audLastRec();
     oldsys=syscyc;
     syscyc=sysrtm;
     rtkick(1,calrtm);
}

VOID
inisho2(VOID)
{
     INT i;
     struct uidisp *uidptr;

     uidarr=(struct uidisp *)alcmem(hichp1*sizeof(struct uidisp));
     for (i=0,uidptr=uidarr ; i < hichp1 ; i++,uidptr++) {
          uidptr->attrib=ndfhue;
          uidptr->sing=LILYELBOX;
          uidptr->labl[0]='\0';
     }
     usshdl=regscn(&ussscn);
     emuchn(0);
#ifdef GCWINNT
     sv.savmin=0;                  // no built-in screen saver under NT
#endif // GCWINNT
     cur2sav=sec2sav=sv.savmin*60;
     doaditbx();
}

VOID
finsho(VOID)                       /* finish up stuff for shutdown         */
{
#ifndef GCWINNT
     INT i;
#endif

     clssysinf();
     if (hAuditTrail != 0) {
          audfClose(hAuditTrail);
     }
     locate(0,24);
#ifndef GCWINNT   //disable annoying beep during shutdown
     for (i=0 ; i < 2 ; i++) {
          belper(600);
          printf("\7\7");
          belper(800);
          printf("\7\7");
     }
#endif
     endlopr();
}

VOID
dwopr(VOID)
{
     if (kbhit()) {
          keyhit(getchc());
     }
     emulupd();
     lsesupd();
     conupd();
}

VOID
iniaud(VOID)                       /* initialize audit trail display       */
{
     INT i;
     struct audOldStyle buf;

     sstatr(stthue);
     actvscnsp(shdl,23,1,70,9,1);
     printf("\14");
     for (i=0 ; i < NUMOFP ; ++i) {
          locate(23,1+i);
          if (sumLastVisible != NOENTRIES && sumLastVisible >= (NUMOFP-1)-i) {
               audGetEntry(sumLastVisible-((NUMOFP-1)-i),&buf);
          }
          else {
               memset(&buf,0,sizeof(buf));
          }
          sumPrintEntry(&buf);
     }
}

VOID
shocst(                            /* display text in audit trail          */
const CHAR *brief,                 /*   brief desc. of audit trail entry   */
const CHAR *detail,                /*   detailed description               */
...)                               /*   variable parameters                */
{
     struct audEntry entry;
     struct audOldStyle oldBuf;
     ULONG nRecs;
     INT rc;
     CHAR chanStr[AUDCHANSIZ];
     va_list ap;

     nRecs=audfNumRecs(hAuditTrail);
     va_start(ap,detail);
     audfChannelStr(chanStr,AUDCHANSIZ);
     audfFormatEntry(&entry,sizeof(entry),brief,chanStr,detail,ap);
     rc=audfAddLowLevel(hAuditTrail,&entry,sizeof(entry));
     if (rc < AUDERR_OK) {
          if (rc == AUDERR_FIO) {
               if (errno == ENOSPC) {
                    catastro("OUT OF DISK SPACE WRITING TO AUDIT TRAIL");
               }
               else {
                    catastro("I/O ERROR WRITING TO AUDIT TRAIL (%d)",errno);
               }
          }
          else {
               catastro("ERROR WRITING TO AUDIT TRAIL (%d)",rc);
          }
     }
     va_end(ap);
#ifdef GCWINNT
     sendAuditTrailToMainWin(entry.brief,entry.detail);
#endif // GCWINNT
     audfCvtEntryToOld(&entry,&oldBuf,sizeof(oldBuf));
     if (sopaud && ntfysopr != NULL) {
          (*ntfysopr)((CHAR *)&oldBuf);
     }
     if (nRecs == 0 || sumLastVisible == nRecs-1) {
          sstatr(stthue);
          actvscnsp(shdl,23,1,70,9,1);
          locate(23,9);
          printf("\n");
          sumPrintEntry(&oldBuf);
          sumLastVisible=nRecs;
          rstloc();
          rstwin();
     }
     fasadd();
     doaditbx();
     if (rsyfad_hook != NULL) {
          (*rsyfad_hook)();
     }
}

VOID
scroat(                            /* scroll audit trail window            */
INT num)                           /*   number of lines to scroll          */
{
     ULONG lastRec,newPos;
     GBOOL newMoved;

     newMoved=TRUE;
     lastRec=audLastRec();
     if (lastRec != NOENTRIES) {
          newPos=sumLastVisible;
          if (num < 0 && newPos < -num) {
               newPos=0;
          }
          else {
               newPos+=num;
          }
          if (newPos >= lastRec) {
               newPos=lastRec;
               newMoved=FALSE;
          }
          else if (newPos < NUMOFP-2) {
               newPos=min(lastRec,NUMOFP-2);
          }
     }
     if (newPos != sumLastVisible) {
          sumLastVisible=newPos;
          iniaud();
          atmess=newMoved;
     }
}

VOID
sumPrintEntry(                     /* print entry at current position      */
const struct audOldStyle *entry)   /*   entry to print                     */
{
     printf("%14.14s %-32.32s",entry->stamp,entry->brief);
}

VOID
shochl(                            /* show legend for chan with any attrib   */
CHAR *legend,
CHAR sing,
INT attr)
{
     INT chan;
     INT chncol,chnrow;
     CHAR *vptr;

     vptr=actvscn(shdl);
     chan=channel[usrnum];
     sprintf(uidarr[chan].labl,"%-*.*s",LGNSIZ-1,LGNSIZ-1,legend);
     uidarr[chan].attrib=attr;
     uidarr[chan].sing=sing;
     chnrow=chan&0x0F;
     chncol=(chan&0xF0)>>4;
     if (vptr == NULL) {
          scnputc(((chnrow+2)*160)+(2*(chncol+3))+1,scncolor(attr|0x08));
          scnputc(((chnrow+2)*160)+(2*(chncol+3)),sing);
     }
     else {
          *(vptr+((chnrow+2)*160)+(2*(chncol+3))+1)=scncolor(attr|0x08);
          *(vptr+((chnrow+2)*160)+(2*(chncol+3)))=sing;
     }
     if (shochl_hook != NULL) {
          (*shochl_hook)(chan);
     }
     usrchl();
}

VOID
loadgph(min)                  /* draw the load graph!                      */
INT min;
{
     INT loff,i,j,avld,modmin;
     INT l1,l2,l3,thmin;

     modmin=min%3;
     thmin=((min+3)%60)-modmin;         /* graph begins on 3 minute bound  */
     loff=thmin/3;                      /* label offset                    */
     actvscn(shdl);
     sstatr(gphhue);
     printfat(25,17,"%20.20s",minlabl+loff);
     for (i=0 ; i < 20 ; i++) {
          l1=l2=l3=sysload[(thmin+(3*i))%60];
          if (i != 19 || modmin > 0) {
               l2=sysload[(thmin+(3*i)+1)%60];
          }
          if (i != 19 || modmin > 1) {
               l3=sysload[(thmin+(3*i)+2)%60];
          }
          avld=((nterms+(nterms>>1))+10*(l1+l2+l3))/(3*nterms);
          for (j=0 ; j < 10 ; j+=2) {
               if (avld >= j+1) {
                    printfat(25+i,16-(j/2),"Û");
               }
               else if (avld == j) {
                    printfat(25+i,16-(j/2),"Ü");
               }
               else {
                    printfat(25+i,16-(j/2)," ");
               }
          }
     }
}

INT
linsusd(VOID)                 /* return number of lines in use             */
{
     INT i,y;

     y=0;
     for (i=0 ; i < nterms ; i++) {
          if (usroff(i)->usrcls != VACANT) {
               y++;
          }
     }
     return(y);
}

VOID
doaditbx(VOID)                     /* Do green additional info box         */
{
     static INT wycoor[6]={12,13,14,15,16,17};
     INT i;
     ULONG eavl;
#ifdef UNIX
     extern ULONG memusd(VOID);
     extern FLOAT lodavg(INT minute);
#endif

     actvscnsp(shdl,48,12,71,18,0);
     if (kilipg) {
          sstatr(0x09c);
          if (kilctr > 0) {
               printfat(48,11,"Shutdown in %2.2d min.",kilctr);
          }
          else if (kilctr == 0) {
               printfat(48,11,"Shutting down NOW! ",kilctr);
          }
          else {
               printfat(48,11,"Shutting down ASAP ",kilctr);
          }
     }
     else {
          sstatr(vtxhue);
          printfat(48,11,"%-5.5s %s    ",nctime(now()),ncdatel(today()));
     }
     sstatr(vtxhue);
     for (i=0 ; i < 6 ; i++) {
          locate(48,wycoor[i]);
          sstatr(vtxhue);
          switch (sv.dspopt[i]) {
          case 0:
               break;
          case 1:
#ifdef UNIX
               printf("Memory used:    %7.7s",dbytes(memusd()));
               break;
#else
#ifdef GCDOS
               DosMemAvail(&eavl);
#else
               eavl=sizmem();
#endif // GCDOS
               if (eavl < 4096L) {
                    sstatr(0x9c);
               }
               printf("Memory avail:  %8.8s",dbytes(eavl/1024L));
               break;
#endif // UNIX
          case 3:
               eavl=dskfre(".");
               if (eavl < 1024L) {
                    sstatr(0x9c);
               }
               printf("HD room avail:  %7.7s",dbytes(eavl));
               break;
          case 4:
               printf("Response time:  %s",rtmfmt(rsptim));
               break;
          case 5:
               printf("Active accnts: %8.8s",l2as(sv2.numact));
               break;
          case 6:
               printf("Calls to date: %8.8s",l2as(sv2.totcalls));
               break;
          case 7:
               printf("Tot uploads:   %8.8s",l2as(sv.uplds));
               break;
          case 8:
               printf("Tot dnloads:   %8.8s",l2as(sv.dwnlds));
               break;
          case 21:
               printf("Tot mail/Forum: %7.7s",l2as(sv.msgtot));
               break;
#ifdef UNIX
          case 22:
               printf("Opn E-mail:   %9u",sv.emlopn);
               break;
          case 23:
               printf("Opn Forum msgs: %7u",sv.sigopn);
               break;
          case 31:
               printf("1 min loadavg:    %5s",spr("%4.2f",lodavg(0)));
               break;
          case 32:
               printf("5 min loadavg:    %5s",spr("%4.2f",lodavg(1)));
               break;
          case 33:
               printf("15 min loadavg:   %5s",spr("%4.2f",lodavg(2)));
               break;
          case 34:
               printf("Free memory:    %7.7s",dbytes(sizmem()));
               break;
#else
          case 22:
               printf("Opn E-mail:   %9u",sv.emlopn);
               break;
          case 23:
               printf("Opn Forum msgs: %7u",sv.sigopn);
               break;
#endif
          }
     }
}

VOID
quiesk(INT blk)                    /* quiescent soft key legends setup     */
{
     INT dif;

     actvscnsp(dfltmscn,CMWXUL,CMWYUL,CMWXLR,CMWYLR,1);
     if (blk == 1) {
          dif=(INT)(opinf.cmlptr-cmlbuf);
          if (dif >= 0 && dif <= 78) {
               locate(CMWXUL+dif,CMWYLR);
               setatr(lblhue);
               printf(" ");
          }
     }
     zappo();
     opinf.opistt=SK_QUIET;
     plosk(0);
     *(opinf.cmlptr=cmlbuf)='\0';
     *(skbptr=skbuf)=0;
     acckey();
     quiefl=1;
     skcipg=0;
}

VOID
zappo(VOID)                        /* unravel soft key linked-list trail   */
{
     struct otrail *otrptr;

     while ((otrptr=opinf.link) != NULL) {
          opinf.link=otrptr->link;
          free(otrptr);
     }
}

VOID
plosk(sktnum)                      /* "plot" soft key table no. sktnum     */
INT sktnum;
{
     CHAR **plskpt;
     INT i;

     actvscn(dfltmscn);
     sstatr(lblhue);
     zapskl();
     for (plskpt=sklegs[sktnum],i=1 ; i <= 10 ; plskpt++,i++) {
          lblsk(i,*plskpt);
     }
}

VOID
zapskl(VOID)                  /*  clear soft key legends                   */
{
     INT i;

     for (i=1 ; i <= 10 ; i++) {
          lblsk(i,i == 5 ? "      ": "       ");
     }
}

VOID
lblsk(sknum,lblstg)           /* label soft keys with legends              */
INT sknum;
CHAR *lblstg;
{
     locate((sknum-1)*8+(sknum < 6),23);
     printf(lblstg);
}

VOID
acckey(VOID)                  /* accept a soft-key keystroke (build trail) */
{
     struct otrail *otrptr;

     otrptr=(struct otrail *)alcmem(sizeof(struct otrail));
     movmem(&opinf,otrptr,sizeof(struct otrail));
     opinf.link=otrptr;
}

VOID
bckspc(VOID)                  /* backspace over previous soft-key command  */
{
     struct otrail *otrptr;

     if (opinf.link->link != NULL) {
          otrptr=opinf.link;
          opinf.link=otrptr->link;
          free(otrptr);
          otrptr=opinf.link;
          movmem(otrptr,&opinf,sizeof(struct otrail));
          opinf.link=otrptr;
          plosk(opinf.opistt);
          *opinf.cmlptr='\0';
          *--skbptr='\0';
          actvscnsp(dfltmscn,CMWXUL,CMWYUL,CMWXLR,CMWYLR,1);
          locate(CMWXUL+((INT)(opinf.cmlptr-cmlbuf)),CMWYLR);
          if (curcurx() > CMWXUL) {
               setatr(lblhue+0x80);
               printf("Ü");
          }
          sstatr(lblhue);
          cleareol();
          cursact(0);
     }
}

VOID
hdlskm(echstg,opistt)              /*  handle entry of a soft key macro    */
CHAR *echstg;
INT opistt;
{
     INT i;

     for (i=0 ; i < strlen(echstg) ; i++) {
          c=echstg[i];
          hdlskc(opistt);
     }
}

VOID
hdlskc(                            /* handle entry of a soft key command   */
INT opistt)
{
     static CHAR stg[2]={0,0};

     stg[0]=(CHAR)c;
     hdlsk(stg,opistt);
}

VOID
hdlsk(                        /* handle entry of a soft key command utility*/
CHAR *echstg,
INT opistt)
{
     fiddle=1;
     strcpy(opinf.cmlptr,echstg);
     opinf.cmlptr+=strlen(echstg);
     actvscnsp(dfltmscn,CMWXUL,CMWYUL,CMWXLR,CMWYLR,1);
     locate(CMWXUL,CMWYLR);
     sstatr(lblhue);
     if (quiefl) {
          quiefl=0;
          printf("\n");
     }
     printf("%s",cmlbuf);
     setatr(lblhue+0x80);
     printf("Ü");
     *skbptr++=c;
     *skbptr=0;
     cursact(0);
     plosk(opistt);
     opinf.opistt=opistt;
     acckey();
}

VOID
retkey(VOID)                       /* handle soft-key commands now         */
{
     INT tmplen,real;

     collap();
     actvscnsp(dfltmscn,CMWXUL,CMWYUL,CMWXLR,CMWYLR,1);
     locate(CMWXUL+((INT)(opinf.cmlptr-cmlbuf)),CMWYLR);
     fiddle=1;
     switch (skbuf[0]) {
     case F2:
          if (skbuf[1] == F1) {
               sndchn=-1;
          }
          else {
               locate(curcurx()+strlen(&cskbuf[2])-1,CMWYLR);
               sscanf(&cskbuf[2],"%x",&sndchn);
               if ((sndchn=usridx(sndchn)) < 0) {
                    break;
               }
          }
          sstatr(lblhue);
          if ((skbuf[1] == F1) || (skbuf[1] != F1 && skbptr-skbuf == 4)) {
               printf("\b");
          }
          printf(": \n");
          *(txtptr=txtstg)='\0';
          vcx=2;
          vcy=21;
          setatr(lblhue+0x80);
          printf("Ü");
          plosk(opinf.opistt=SK_INPMSG);
          break;
     case F3:
#ifdef UNIX
          if (skbuf[1] == F9) {                        /* Unix specific    */
               sv.dspopt[(skbuf[3]-F1)>>8]=((skbuf[2]-F1)>>8)+31;
               auxups(sv.monmal);
          }
#else
          if (skbuf[1] == F9) {                        /* aux crt          */
               sv.monmal=(CHAR)((skbuf[2]-F1)>>8);
               auxups(sv.monmal);
          }
#endif
          else if (skbuf[1] == F10) {                  /* saver control    */
               sv.savmin=savmins[(skbuf[2]-F1)>>8];
               cur2sav=sec2sav=sv.savmin*60;
          }
          else if (skbuf[1] == F2) {
               sv.dspopt[(skbuf[3]-F1)>>8]=((skbuf[2]-F1)>>8)+21;
          }
          else {
               sv.dspopt[(skbuf[2]-F1)>>8]=((skbuf[1]-F1)>>8)+1;
          }
          quiesk(1);
          doaditbx();
          break;
     case F4:
          usrnum=-1;
          tmplen=strlen(&cskbuf[1]);
          real=(skbuf[tmplen+1] == F1);
          switch (addcrd(&cskbuf[tmplen+2],&cskbuf[1],real)) {
          case 1:
               saycrd(&cskbuf[1],real);
          case 0:
               quiesk(1);
          }
          break;
     case F5:
          quiesk(1);
          dspact(&cskbuf[1]);
          scn2mai(acchdl);
          break;
     case F6:
          sstatr(lblhue);
          printf(": \n");
          sndchn=-2;
          *(txtptr=txtstg)='\0';
          vcx=2;
          vcy=21;
          plosk(opinf.opistt=SK_INPMSG);
          break;
     case F10:
          switch (skbuf[1]) {
          case F1:
               usrnum=-1;
               if (kiluid(&cskbuf[2]) >= 0) {
                    quiesk(1);
               }
               break;
          case F2:
               usrnum=-1;
               if (delacct(&cskbuf[2]) >= 0) {
                    quiesk(1);
               }
               break;
          case F3:
               sscanf(&cskbuf[2],"%x",&usrnum);
               if ((usrnum=usridx(usrnum)) < 0) {
                    break;
               }
               else {
                    switch (!isxdigit(skbuf[3]&eurmsk) ? skbuf[3] : skbuf[4]) {
                    case 0:
                         hdlsk(" to normal",SK_ENTER);
                    case F3:
                         rsmode=NORMRS;
                         break;
                    case F2:
                         rsmode=NANSRS;
                         break;
                    case F1:
                         rsmode=BUSYRS;
                         break;
                    }
                    rsmodes[usrnum]=rsmode;
                    kilchn(usrnum);
               }
               quiesk(1);
               break;
          case F9:
               if (skbuf[2] == F6) {         /* kill system UNDO           */
                    if (!kilnow) {
                         kilipg=0;
                         rsmode=NORMRS;
                         prepff();
                         kilctr=-1;
                    }
               }
               else {
                    kilsrc=-1;
                    switch (skbuf[2]) {
                    case F1:                 /* kill system in 1 minute    */
                         kilctr=1;
                         break;
                    case F2:
                         kilctr=2;
                         break;
                    case F3:
                         kilctr=5;
                         break;
                    case F4:
                         kilctr=10;
                         break;
                    case F8:
                         kilctr=-1;                    /* kill system ASAP */
                         break;
                    case F10:
                         kilctr=0;                     /* kill system NOW  */
                         kilnow=1;
                         break;
                    }
                    fupkil();
               }
               quiesk(1);
               break;
          }
     }
}

VOID
auxups(CHAR snum)            /* display an aux. screen                    */
{
     switch (snum) {
     case 0:
          break;
     case 1:
          scn2aux(acchdl);
          break;
     case 2:
          scn2aux(audhdl);
          break;
     case 3:
          scn2aux(emful);
          break;
     case 4:
          scn2aux(stahdl);
          break;
     case 5:
          scn2aux(mhdl);
          break;
     case 6:
          scn2aux(usshdl);
          break;
     case 7:
          scn2aux(ahdl);
          break;
     }
}

VOID
collap(VOID)                  /* collapse 2-bytes/key to 1-byte/key buffer */
{
     INT *skptr;
     CHAR *cskptr;

     setmem(cskbuf,sizeof(cskbuf),0);
     for (skptr=skbuf,cskptr=cskbuf ; skptr != skbptr ; ) {
          *cskptr++=(CHAR)((*skptr++)&255);
     }
}

VOID
fupkil(VOID)                       /* prep for kill from remote sysop      */
{
     INT kilib4,temp;

     rsmode=rsetop;
     kilib4=kilipg;
     kilipg=1;
     temp=usrnum;
     prepff();
     if (!kilib4 || kilctr == 0) {
          kiloop();
     }
     curusr(temp);
}

VOID
snd2ch(chan,text)                  /* send text to a specific channel      */
INT chan;
CHAR *text;
{
     if (usroff(chan)->usrcls > SUPIPG) {
          othusn=chan;
          setmbk(mjrmb);
          prfmlt(FRMSYS,text);
          prfmlt(FSYSTRL);
          injoth();
          rstmbk();
     }
}

VOID
snd2al(text)                       /* send text to all online channels     */
CHAR *text;
{
     INT i;

     for (i=0 ; i < nterms ; i++) {
          snd2ch(i,text);
     }
}

VOID
dftbel(local)                      /* set belper() for screen update       */
INT local;                              /* local session? (1 or 0=emulated)*/
{
     if ((local && mainhdl == lsehdl)
      || (!local && (mainhdl == ehdl || mainhdl == emful))) {
          emubel=visbel;
     }
     else {
          emubel=invbel;
     }
     belper(emubel);
}

CHAR *
chlpfn(VOID)                       /* get current screen's help file name  */
{
     if (mainhdl == acchdl) {
          return("wgsachlp.bin");
     }
     if (mainhdl == audhdl) {
          return("wgsathlp.bin");
     }
     if (mainhdl == stahdl) {
          return("wgssthlp.bin");
     }
     if (mainhdl == mhdl) {
          return("wgsmohlp.bin");
     }
     if (mainhdl == shdl) {
          return("wgssmhlp.bin");
     }
     if (mainhdl == usshdl) {
          return("wgsushlp.bin");
     }
     if (mainhdl == ahdl) {
          return("wgsabhlp.bin");
     }
     if (mainhdl == ehdl || mainhdl == emful) {
          return("wgsemhlp.bin");
     }
     return(NULL);
}

VOID
psmatm(VOID)                       /* old form of sysop page               */
{
     if (margc > 2) {
          psmatms(margv[2]);
     }
}

VOID
psmatms(                           /* other old form of sysop page         */
CHAR *pagmsg)
{
     sendSysopPage(usaptr->userid, pagmsg);
}

VOID
sendSysopPage(                     /* send sysop page to main console      */
const CHAR *user,                  /*  user to send message                */
const CHAR *pagmsg)                /*  message to send                     */
{
#ifdef GCWINNT
     CHAR *pageText;
     INT i;
#endif // GCWINNT

     ASSERT(pagmsg != NULL && user != NULL);

     if (pagmsg != NULL && user != NULL && opinf.opistt == SK_QUIET
      && pagmsg[0] != '\0' && user[0] != '\0') {
          if (sec2sav > 0 && cur2sav == 0) {
               unsavscns();
               cur2sav=sec2sav;
          }
          actvscnsp(dfltmscn, CMWXUL, CMWYUL, CMWXLR, CMWYLR, 1);
          locate(CMWXUL, CMWYLR);
          sstatr(lblhue);
          rstrin();
          printf("\n%s paged (%-5.5s): %s", user, nctime(now()), pagmsg);
#ifdef GCWINNT
          // +4 is for the 2 spaces, 1 dash, and the null
          pageText=alczer(strlen(user)+strlen(pagmsg)+4);
          sprintf(pageText,"%s - %s", user, pagmsg);
          for (i=0 ; pageText[i] != '\0' ; i++) {
               if (pageText[i] == '\n' || pageText[i] == '\r') {
                    pageText[i]=' ';
               }
          }
          sendSysopPageToMainWin(pageText);
          free(pageText);
#endif // GCWINNT
          quiefl=1;
          updbckgnd();
     }
}

VOID
sendConsole(                       /* send page message DOS style console  */
const CHAR *pagmsg)                /*  formatted message to send           */
{
     ASSERT(pagmsg != NULL);

     if (pagmsg != NULL && opinf.opistt == SK_QUIET && pagmsg[0] != '\0') {
          if (sec2sav > 0 && cur2sav == 0) {
               unsavscns();
               cur2sav=sec2sav;
          }
          actvscnsp(dfltmscn,CMWXUL,CMWYUL,CMWXLR,CMWYLR,1);
          locate(CMWXUL,CMWYLR);
          sstatr(lblhue);
          rstrin();
          printf("\n%s",pagmsg);
          quiefl=1;
          updbckgnd();
     }
}

CHAR *
rtmfmt(                            /* format Response Time number          */
ULONG ntval)                       /* interval, 1/65536 second units       */
{                                  /* returns pointer to 7-character string*/
     CHAR *cp;

     if (ntval >= HRTONE) {
          if (strlen(cp=ul2as((ntval+HRTONE/2)>>16)) > 3) {
               return("999 sec");
          }
          else if ((ntval=((ntval+HRTONE/20)*10)>>16) > 99L) {
               return(spr("%3s sec",cp));
          }
          else {
               return(spr("%d.%d sec",((INT)ntval)/10,((INT)ntval)%10));
          }
     }
     else {
          if (strlen(cp=ul2as(ntval=((ntval+HRTONE/2000)*1000)>>16)) > 3) {
               return(" 999 ms");
          }
          else if (ntval > 0L) {
               return(spr("%4s ms",cp));
          }
          else {
               return(" < 1 ms");
          }
     }
}

VOID
calrtm(VOID)                            /* calculate system response time  */
{
     ULONG cyctim;                      /* cycle time (2*avg response time)*/
#ifdef GCWINNT
     CHAR rtBuf[32];
#endif // GCWINNT

     if (fRespDataCollected) {
          if (rtmcnt <= 1L) {
               cyctim=max(rtmlst-rtmlls,hrtval()-rtmlst);
          }
          else {
               cyctim=(rtmlst-rtmfst)/(rtmcnt-1L);
          }
          rsptim=(cyctim/2+(RTMSMP-1)*rsptim+RTMSMP/2)/RTMSMP;
          if (rsptim > LOADFX*65535U) {
               syslod=65535U;
          }
          else {
               syslod=(unsigned)(rsptim/LOADFX);
          }
          rtmcnt=0L;
#ifdef GCWINNT
          strcpy(rtBuf,rtmfmt(rsptim));
          sendSysLoadToMainWin(rtBuf);
#endif // GCWINNT
     }
     rtkick(RTMRAT,calrtm);
}

VOID
sysrtm(VOID)                            /* record info for response time   */
{
     rtmlls=rtmlst;
     rtmlst=hrtval();
     if (rtmcnt == 0L) {
          rtmfst=rtmlst;
     }
     rtmcnt++;
     if (!fRespDataCollected && rtmcnt > 2) {
          fRespDataCollected=TRUE;
     }
     (*oldsys)();
}

#if 0
VOID
sysrtm(VOID)                            /* record info for response time   */
{
     static INT cnt=0;
     static ULONG oldTime=0;
     static ULONG newTime=0;
#ifdef GCWINNT
     CHAR rtBuf[32];
#endif // GCWINNT

     if (oldTime == 0) {
          oldTime=hrtval();
          rsptim=0;
     }
     if (++cnt == 200) {
          newTime=hrtval();
          rsptim=(newTime-oldTime)/400;
          oldTime=newTime;
          cnt=0;
#ifdef GCWINNT
          strcpy(rtBuf,rtmfmt(rsptim));
          sendSysLoadToMainWin(rtBuf);
#endif // GCWINNT
     }
     (*oldsys)();
}
#endif
