(*****************************************************************************)
(*>                                                                         <*)
(*>                     Telegard Bulletin Board System                      <*)
(*>         Copyright 1995,1996 by Tim Strike.  All rights reserved.        <*)
(*>                                                                         <*)
(*>                      Data types and structures                          <*)
(*>                                                                         <*)
(*****************************************************************************)
(*****************************************************************************)
(* ------------- IMPORTANT NOTICE -- PLEASE READ CAREFULLY ----------------- *)
(*****************************************************************************)

{                                                         June 9th, 1996

   Note to all Telegard 3.0 developers:

   These structures are the final release structures for Telegard 3.0.

   These structures may be used to modify and create new programs which
   will be compatible with Telegard 3.0.  Enclosed with this structure kit
   are several documents which outline the various data file formats that
   Telegard 3.0 uses.  The development documentation, DEVEL300.DOC, has
   many helpful hints and information regarding most of the data file which
   Telegard uses -- please read it before attempting to use the data
   structures.

   The structures have been commented as best as possible.  If you need
   more information on how to use/access data within these structures,
   please see the accompanying documentation for contact methods.

   Several portions of these structures outline multinode capabilities.  As
   of Telegard 3.0, the BBS is not fully multinode compatible.  A release
   will be made as soon as possible which will accommodate full multinode
   features.  Until then, presume that the features that have been outlined
   in this document are up-to-date and working in Telegard 3.0.

   Thanks for your interest in Telegard 3.0.  Utility developers who wish
   more information regarding distribution should look at the accompanying
   documentation -- there are several helpful areas which should be read.

   We can use all the questions, comments and ideas that you can think of.

   Thanks,
   Telegard 3.0 Development Team
   }

(*****************************************************************************)
(* ------------------------ CONSTANT DEFINITIONS --------------------------- *)
(*****************************************************************************)

const

  maxword      = 65535;                       { TP/BP shortcoming . . . }

  maxarcs      = 10;                          { archive records  (1..max) }
  maxprotocol  = 26;                          { protocol records (A..Z) }
  maxlevel     = 26;                          { level records (A..Z) }
  maxevents    = 15;                          { scheduled events (0..max) }
                                              {  0 = -X[n] cmd (RESERVED) }
  maxmenucmds  = 75;                          { menu commands    (1..max) }
  maxqueue     = 20;                          { queue storage    (1..max) }
  numvoteas    = 15;                          { voting answers   (0..max) }
  numvoteqs    = 20;                          { voting questions (1..max) }

  mJAM         = 1;                           { JAM format }
  mSquish      = 2;                           { Squish format }

  mLocal       = 1;                           { Local }
  mNetmail     = 2;                           { Netmail }
  mEchomail    = 3;                           { Echomail }

  mPublic      = 1;                           { Public Messages }
  mPrivate     = 2;                           { Private Messages }
  mPubPriv     = 3;                           { Public/Private Messages }

  atNo         = 1;                           {  No anonymous allowed }
  atYes        = 2;                           {  Anonymous allowed }
  atForced     = 3;                           {  Forced anonymous }
  atDearabby   = 4;                           {  "Dear Abby" message base }
  atAnyname    = 5;                           {  Anyname posting }

(*****************************************************************************)
(* -------------------------- TYPE DEFINITIONS ----------------------------- *)
(*****************************************************************************)

type

  acstring  = string[40];                     { Access Control System string }
  intrange  = array[0..255] of integer;       { security tables - integers }
  byterange = array[0..255] of byte;          { security tables - bytes }

  unixtime  = longint;                        { unix time stamp - seconds
                                                  since 01/01/70 }

  acrq      = '@'..'Z';                       { AR flags }
  acrqs     = set of acrq;                    { AR flags set }
  uflag =                                     { user AC flags }
  (
    rlogon,                                   { L - One call per day }
    rchat,                                    { C - Can't page the SysOp }
    rnetmaildel,                              { F - Force Netmail deletion }
    ramsg,                                    { A - Can't post AutoMessage }
    rpostan,                                  { * - Can't post anonymously }
    rpostpvt,                                 { E - Can't post private }
    rpostnet,                                 { N - Can't post NetMail }
    rpost,                                    { P - Can't post at all }
    rvoting,                                  { K - Can't vote }
    rmsg,                                     { M - Force Email deletion }
    rpostecho,                                { G - Can't post EchoMail }
    fnodlratio,                               { 1 - No UL/DL ratio }
    fnopostratio,                             { 2 - No post/call ratio }
    fnofilepts,                               { 3 - No file points checking }
    fnodeletion,                              { 4 - Protection from deletion }
    fnodailyratio,                            { 5 - No daily DL ratio }
    fnodltime,                                { 6 - No DL time check }
    fnopwchange,                              { 7 - No forced pw change }
    ftimepercall                              { 8 - Time on per call basis }
 );
  uflags = set of uflag;                      { set of user AC flags }

  bitmapdate =                                { Bitmapped date format }
  record
     date,                                    { date  5432109876543210 }
                                              {       Y----->M-->D---> }
     time  : word;                            { time  5432109876543210 }
                                              {       H--->M---->S---> }
  end;

(*****************************************************************************)
(* ------------------- CONFIGURATION DATA STRUCTURES ----------------------- *)
(*****************************************************************************)

  configrec=            { CONFIG.TG : System configuration }
  record
     versionid:word;                          { version (eg $3000 = v3.0) }

     datapath,                                { DATA path }
     textpath,                                { TEXT path }
     langpath,                                { LANGUAGES path }
     menupath,                                { MENUS path }
     logspath,                                { LOG path }
     msgpath,                                 { MSGS path }
     semaphore,                               { SEMAPHORE path }
     attachpath,                              { FILE ATTACH path }
     swappath    : string[79];                { SWAP path }
     arcpath,                                 { ARCHIVE path }
     protpath    : string[40];                { PROTOCOL path }
     filepath    : string[79];                { FILE PATH }
     reserved1   : array[1..120] of byte;     { RESERVED }

     bbsname     : string[80];                { BBS name }
     bbsphone    : string[20];                { BBS phone number }
     bbslocation : string[50];                { BBS location }
     sysopname   : string[30];                { SysOp's full name or alias }
     multinode   : boolean;                   { System is Multinode? }
     bulletprefix: string[8];                 { default bulletin prefix }
     highbitinfo : boolean;                   { High-bit in user info? }
     nodecheck   : byte;                      { NodeCheck threshold (s) }
     nodetask    : boolean;                   { node from TASK environment }
                                              {   if -Nnn not specified }
     hiddenPW    : boolean;                   { Passwords are hidden? }
                                              { 1. Always verify passwords
                                              {    against user.pwcrc
                                              { 2. TRUE  user.pwtext='' }
                                              { 3. FALSE check user.pwcrc }
                                              {    if crc(input)=user.pwcrc }
                                              {    then set user.pwtext=pw }
                                              { 4. If changing pw, always }
                                              {    update CRC field -- VERY }
                                              {    important! }
     reserved2   : array[1..4] of byte;       { RESERVED }
     localtimeout: boolean;                   { local timeout logoff? }
     sysoppw     : string[20];                { SysOp PW }
     timeoutbell,                             { minutes before timeout bell }
     timeout,                                 { minutes before timeout logoff }
     backsysoplogs,                           { days to keep SYSOP##.LOG }
     slogtype    : byte;                      { SysOp log type
                                                   0 - File
                                                   1 - Printer
                                                   2 - Both }
     stripclog,                               { strip colors from SysOp log? }
     compressbases: boolean;                  { "compress" base numbers? }
     reserved3    : array[1..100] of byte;    { RESERVED }

     audiolowtime,                            { allowed audio hours }
     audiohitime  : word;
     monoscreen,                              { Monochrome screen }
     useems,                                  { use EMS for overlay }
     usebios,                                 { Use BIOS for local video output }
     cgasnow      : boolean;                  { Suppress snow on CGA systems }
     screensize,                              { screen size
                                                   0 - Default/Auto
                                                   1 - 25
                                                   2 - 28 (VGA)
                                                   3 - 43/50 (EGA/VGA) lines }
     wfcblanktime : byte;                     { minutes to blank WFC menu screen }
     printerport  : byte;                     { printer port (1-3) }
     openfiledelay,                           { OpenFile delay b/w attempts }
     openfileatt,                             { OpenFile attempts }
     openfiletimeout,                         { OpenFile timeout message }
     openfileabort : byte;                    { OpenFile timed abort }
     reserved4    : array[1..20] of byte;     { RESERVED }

     chatpagelen,                             { Page length in seconds }
     chatattempts,                            { # of chat attempts }
     sysopcolor,                              { SysOp chat colour }
     usercolor    : byte;                     { User chat colour }
     chatreason,                              { Ask for a chat reason? }
     chattime     : boolean;                  { Refund chat time? }
     externalchat : string[79];               { External chat command }
     chatdoortype : byte;                     { Chat door file type:        }
                                              {   0: none       3: WWIV     }
                                              {   1: GAP        4: PcBoard  }
                                              {   2: RBBS-PC                }
     reserved5    : array[1..74] of byte;     { RESERVED }

     fsecmd       : string[40];               { full screen editor command }
     fsedoortype,                             { FSE door file type:         }
                                              {   0: none       3: WWIV     }
                                              {   1: GAP        4: PcBoard  }
                                              {   2: RBBS-PC                }
     swapshelltype: byte;                     { swap shell type: }
                                              {   0: disk       2: XMS }
                                              {   1: EMS               }
     swaponarchive,                           { swap on archive command }
     swapondoor,                              { swap on door command }
     swapondosshell,                          { swap on DOS shell }
     swaponevent,                             { swap on DOS Shell event }
     swaponfse,                               { swap on full-screen editor }
     swaponsysbat,                            { swap on system batch files }
     swaponxfer,                              { swap on file transfer }
     swapshell    : boolean;                  { swap shell function enabled? }
     envspace     : word;                     { DOS Environment Space }
     reserved6    : array[1..48] of byte;     { RESERVED }

     timeallow    : intrange;                 { daily time }
     callallow,                               { daily calls }
     dlratio      : byterange;                { # ULs/# DLs ratios }
     dlkratio     : intrange;                 { DL/UL KB ratios }
     postratio,                               { post/call ratios }
     dailyratio   : byterange;                { daily DL #files ratios }
     dailykratio,                             { daily DL KB ratios }
     timebankmax  : intrange;                 { timebank max limit }
     timedeposit,                             { timebank daily deposit }
     timewithdraw : byterange;                { timebank daily withdraw }

     ansitype,                                { ANSI Logon -
                                                   0  Ask
                                                   1  Detect
                                                   2  Force NO
                                                   3  Force YES }
     lastcallers,                             { days of last callers }
     maxlogontries,                           { tries for PW's at logon }
     maxlogonmins : byte;                     { minutes allowed for logon }
     allowalias,                              { allow aliases? (handles) }
     datapw,                                  { data phone # password }
     voicepw,                                 { voice phone # password }
     localsec,                                { is local security ON? }
     displaysec,                              { is local screen-security ON? }
     globaltrap,                              { trap ALL USER'S activity? }
     autochatopen,                            { auto open chat capture? }
     languagefirst: boolean;                  { language selection first? }
     reserved6a   : byte;
     lcallinlogon : byte;                     { "Last Calls" list in logon? }
     reserved7    : byte;                     { RESERVED }
     offhooklocallogon,                       { phone off-hook for local? }
     forcevoting,                             { logon voting mandatory? }
     iemsi,                                   { allow IEMSI logons }
     checkmulti   : boolean;                  { check for mutliple logons }
     reserved8    : array[1..41] of byte;     { RESERVED }
     logonmenu,                               { logon menu to start users on }
     watcharea,                               { area for pw attempt warnings }
     inquiryarea  : string[8];                { area for forgotten pw inquiry }
     passdays     : word;                     { # of days to change password }
     updatelocal  : boolean;                  { local calls in statistics }
     timeleftbank : boolean;                  { timebank prompt w/no time? }
     minbaud,                                 { minimum logon baudrate }
     graphicsbaud : longint;                  { minimum graphics baudrate }
     reserved9    : array[1..63] of byte;     { RESERVED }

     newapp       : string[36];               { new user letter to user }
     opensystem,                              { allow new users? }
     newiemsi     : boolean;                  { Allow IEMSI new user logons }
     linelen,                                 { default video line length }
     pagelen,                                 { default video page length }
     datefmt      : byte;                     { date format - 0 ASK }
     scanphone,                               { Scan for duplicate phone #'s }
     autopassword : boolean;                  { Allow auto-created pw's }
     language     : string[8];                { Default language, ''  Ask }
     ansi,                                    { ANSI               0  Ask }
     avatar,                                  { Avatar             1  Yes }
     clrscr,                                  { Clear Screen       2  No }
     pause,                                   { Screen Pause }
     hotkeys,                                 { Hotkeys }
     fse          : byte;                     { Full Screen Editor }
     mailaddress,                             { Ask for Mail Address }
     gender,                                  {         Gender }
     dataph,                                  {         Data Phone }
     voiceph,                                 {         Voice Phone }
     dob          : boolean;                  {         Date of Birth }
     newuserlevel : char;                     { New User level }
     flinput      : byte;                     { Full-line input   0 Ask }
                                              {                   1 Yes }
                                              {                   2 No }
     countryinput : byte;                     { Country input   0 Ask }
                                              {                 1 U.S. }
                                              {                 2 Canada }
                                              {                 3 Int'l }
     killcolor    : boolean;                  { Strip colour from entry fields }
     reserved10   : array[1..30] of byte;     { RESERVED }
     crosspost    : acstring;                 { Cross post message }

     batchfileext : string[3];                { batch filename extension }
     reserved11   : array[1..32] of byte;     { RESERVED }

     minspaceforpost: word;                   { minimum drive space to post }
     emaillist,                               { allow email user listing? }
     smartquote,                              { use smartquote features? }
     quickquote    : boolean;                 { use quickquote features? }
     ccmail,                                  { carbon copy messages }
     creq,                                    { request confirm receipt }
     fileattach,                              { attach file - non-netmail }
     normpubpost,                             { post public messages }
     normprivpost,                            { post private messages }
     normnetpost,                             { post netmail messages }
     nopostratio,                             { no post/call ratio }
     anonpubread,                             { see who posted public anon }
     anonprivread,                            { see who posted private anon }
     anonpubpost,                             { post anon public messages }
     anonprivpost  : acstring;                { post anon private messages }
     netconfirm,                              { honour confirmation request }
     msguploads,                              { allow upload of messages }
     nodelookup    : boolean;                 { allow nodelist lookup }
     fileattachnet : acstring;                { attach file - netmail }
     antiqueUUCP   : boolean;                 { antique UUCP; UUCP in header,
                                                   TO: in message }
     writescanlog  : string[40];              { path to ECHOMAIL.JAM/NETMAIL.JAM }
     checkfsesave  : boolean;                 { check fse save }
     reserved13    : array[1..15] of byte;    { RESERVED }

     sop,                                     { SysOp }
     csop,                                    { Co-SysOp }
     spw           : acstring;                { SysOp PW at logon }

     wfc           : array[1..15] of byte;    { WFC Menu Colours }
     heartbeat     : boolean;                 { WFC "Heartbeat" }
     reserved14    : array[1..25] of byte;    { RESERVED }

     qwkpktname,                              { packet name }
     qwkwelcomefile,                          { BBS welcome file }
     qwknewsfile,                             { BBS news file }
     qwkgoodbyefile: string[8];               { BBS goodbye file }
     qwklocaldlpath,                          { local QWK download path }
     qwklocalulpath : string[40];             { local REP upload path }
     reserved15   : array[1..41] of byte;     { RESERVED }
     qwkmaxmsgs   : word;                     { max messages to DL (0=unlim) }
     qwkarc       : string[3];                { default archive }
     qwkextctrl   : boolean;                  { extended CONTROL.DAT info }
     qwknewsgen   : string[60];               { news program }
     qwkfilesgen  : string[60];               { new files program }
     qwknews,                                 { include news       0 Ask }
     qwkwelcome,                              { include welcome    1 Yes }
     qwkgoodbye,                              { include goodbye    2 No  }
     qwknewfiles,                             { include new files list }
     qwksession   : byte;                     { include session texts }

     reserved16   : array[1..95] of byte;     { RESERVED }

     ulbase       : string[8];                { default UL base }
     showulname   : boolean;                  { Show upload name }
     blindulacs   : acstring;                 { blind upload ACS }
     filetest     : byte;                     { file upload test type }
                                              {    0 : none }
                                              {    1 : archive integrity }
                                              {    2 : upload processor }
     filepwacs    : acstring;                 { acs for users to add pw }
     truncdesc    : boolean;                  { truncate file_id/testinfo }
                                              {   imported descriptions }
     drive_tblupd : byte;                     { CD-ROM drive table update }
                                              {     0 : every call }
                                              { 1-254 : once every n hours }
                                              {   255 : never }
     searchdup,                               { search for dupe filenames }
     globaldl,                                { global downloads }
     allowdldesc,                             { allow description download }
     importfileid,                            { import file descriptions }
     nodupeext    : boolean;                  { no check of extension on dupe files }
     reserved17   : byte;                     { RESERVED }
     unlistfp,                                { file points for unlisted DLs }
     ulrefund,                                { percent time refund for ULs }
     dlchecktype  : byte;                     { DL checking (0=off,1=UL/DL,2=points) }
     maxintemp,                               { max KB allowed in TEMP\ARC\ }
     minspaceul,                              { minimum KB drive space left to upload }
     ulfpkbyte,                               { UL K-bytes per file point }
     ulfpforfile,                             { UL # points assigned to file }
     ulfpforuser  : word;                     { UL # points assigned to user }
     sysopulbase  : string[8];                { file base for SysOp uploads }
     seeunval,                                { see unvalidated files }
     dlunval,                                 { DL unvalidated files }
     ulvalreq     : acstring;                 { UL validated not-required }
     virusscanner : string[80];               { Virus Scanner Command }
     passederrlvl : byte;                     { Passed Scanner Errorlevel }
     gifspectype  : byte;                     { Gifspec type   0 Last line }
                                              {                1 Before* }
                                              { * old method, desc is }
                                              { truncated if necessary }
     useTESTINFO  : boolean;                  { import TESTINFO.DAT -- if }
                                              { virus scanner creates it }
     testpath     : string[40];               { path to TESTINFO.DAT }
     textview     : boolean;                  { allow text w/archive view }
     pausebefore  : boolean;                  { pause list before next dir }
     dlunavail    : acstring;                 { dl unavailable (failed) files }
  end;

  systemrec=            { SYSTEM.DAT : System operational variables }
  record
     usereditlvl,                             { type of user editor }
                                              {    0..2 - Short..Long }
     curwindow    : byte;                     { type of SysOp window }
     istopwindow  : boolean;                  { SysOp window on top? }
     callernum    : longint;                  { total number of callers }
     windowon     : boolean;                  { is SysOp window on? }
     reserved     : array[1..400] of byte;    { RESERVED }
  end;

(*****************************************************************************)
(* ------------------------ USER DATA STRUCTURES --------------------------- *)
(*****************************************************************************)

  userstat=             { USERS.DAT status flags }
  (
     lockedout,                               { if locked out }
     udeleted,                                { if deleted }
     trapactivity,                            { if trapping users activity }
     trapseparate,                            { if trap to separate TRAP file }
     chatauto,                                { if auto chat trapping }
     chatseparate,                            { if separate chat file to trap to }
     slogseparate,                            { if separate SysOp log }
     alert                                    { alert SysOp when user logs on }
  );
  userstatus = set of userstat;

  userflag=             { USERS.DAT user flags }
  (
     newusermsg,                              { sent newuser message }
     clsmsg,                                  { clear screen before messages }
     flinput,                                 { full line input }
     hotkey,                                  { menu hotkeys active }
     pause,                                   { pause }
     novice,                                  { user is at novice help level }
     hiddenlog,                               { not displayed in call/online listings }
     hiddenlist                               { not displayed in user listings }
  );
  userflags = set of userflag;

  userrec=              { USERS.DAT : User account records }
  record
     name,                                    { user name }
     realname   : string[36];                 { real name }
     street,                                  { mailing address }
     location   : string[30];                 { city, province }
     postalcode : string[10];                 { postal code }
     voiceph,                                 { voice phone # }
     dataph     : string[20];                 { data phone # }

     pwtext     : string[20];                 { user password }
  
     { DEVELOPERS NOTE:  The pwtext field *may* be empty.  Please observe
     the following when updating passwords:

        1. All password input is UPPERCASE
        2. If ConfigRec.HiddenPW = TRUE, then only the CRC32 of the password
           is stored in the user record (userrec.crcpw). 
        3. If ConfigRec.HiddenPW = FALSE, both the CRC32 and the actual
           password are stored in the user record.
       *4. When checking input passwords against the file, only the CRC32
           value should be tested (the pwtext may or may not be correct).  
           If ConfigRec.HiddenPW = FALSE, and the pwtext field is EMPTY, 
           then after a correct password the field will be automatically
           updated.  If ConfigRec.HiddenPW = TRUE, the pwtext will *not* be 
           updated (this is obvious).
       *5. Passwords should *only* be displayed (pwtext) if the CRC32 of
           the pwtext field *matches* the pwcrc field.  Otherwise, the 
           pwtext field is likely incorrect.  When changing passwords, the
           user should be prompted only, not shown their previous password.
     }    

     lastdate   : unixtime;                   { laston date/time }
     firstdate,                               { firston date }
     pwdate,                                  { last date of pw change }
     birthdate  : string[8];                  { birth date }
     gender     : char;                       { gender - M/F }
     subdate,                                 { subscription started }
     expiredate : string[8];                  { subscription expires }
     expireto   : char;                       { expire to level A..Z,
                                                  !=Delete }
     comment    : string[40];                 { SysOp comment on User }
     notes      : array[1..3] of              { SysOp definable variables }
                  string[40];
     lockfile   : string[8];                  { lockout msg to print }

     pwcrc      : longint;                    { CRC-32 of user password }

     reserved1  : array[1..14] of byte;       { RESERVED }
     ugraphics  : byte;                       { user graphics protocol }
                                              {   0 : TTY - no fallback }
                                              {   1 : ANSI   }
                                              {   2 : Avatar }
                                              {   3 : RIP    }
     fallback   : byte;                       { 2nd fallback protocol }
                                              {   1 : ANSI   }
                                              {   2 : Avatar }
                                              {   3 : RIP    }
                                              { 3rd TTY }
     linelen,                                 { line length (# cols) }
     pagelen    : byte;                       { page length (# rows) }
     flags      : userflags;                  { flags (see above) }
     status     : userstatus;                 { status (see above) }
     reserved2  : byte;                       { RESERVED }

     sl         : byte;                       { SL }
     ac         : uflags;                     { user flags }
     aflags1,                                 { Access flags - Set 1 }
     aflags2    : acrqs;                      { Access flags - Set 2 }
     userID     : longint;                    { unique User-ID - THIS VALUE
                                                SHOULD NOT BE CHANGED BY
                                                ANY PROGRAM }
     level      : char;                       { current validation level }
     datefmt    : byte;                       { Date Format }
                                              {   0 - MM/DD/YY }
                                              {   1 - DD/MM/YY }
                                              {   2 - YY/MM/DD }
     reserved7  : char;                       { RESERVED }              
     macroptr   : longint;                    { pointer for MACROS.DAT
                                                  -1 = none }
     votedate   : unixtime;                   { last vote }
     reserved3  : array[1..17] of byte;       { RESERVED }

     lastconf   :char;                        { last conference }
     lastmsg,                                 { last message base # }
     pubpost,                                 { # public posts }
     privpost,                                { # private posts }
     netpost    : word;                       { # netmail posts }
     mailbox    : string[36];                 { mailbox status
                                                  ''        Open/Normal
                                                  'CLOSED'  Closed
                                                  Username  Forwarded to... }
     credit,                                  { Netmail points (credit) }
     debit      : longint;                    { Netmail points (debit) }
     fsetype    : byte;                       { FSE usage (0=never,1=always,2=ask) }
     
     reserved4  : array[1..32] of byte;       { RESERVED }

     qwkarc     : string[3];                  { QWK default archiver }
     qwkfromyou,                              { bundle from user }
     qwkbwctrl,                               { create BW control file }
     qwknews,                                 { include news }
     qwkwelcome,                              { include welcome }
     qwkgoodbye,                              { include goodbye }
     qwknewfiles,                             { include new files list }
     qwkpointer,                              { include pointer file }
     qwksession : boolean;                    { include session listing }
     reserved5  : array[1..23] of byte;       { RESERVED }

     defprotocol: char;                       { default protocol (A-Z) }
                                              {   ! Select at download time }
     lastfile,                                { last file base # }
     uploads,                                 { amount ULed (files) }
     downloads,                               { amount DLed (files) }
     todaydl    : word;                       { amount DLed today (files) }
     uk,                                      { amount ULed (kbytes) }
     dk,                                      { amount DLed (kbytes) }
     todaydk,                                 { amount DLed today (kbytes) }
     filepoints : longint;                    { file points remaining }

     totaltime  : longint;                    { total time on system }
     timebank,                                { # mins in Time Bank }
     totalcalls : word;                       { total calls to system }
     tltoday,                                 { time left today }
     tbtoday    : integer;                    { bank activity +/- time }
     todaycalls,                              { calls to system today }
     illegal    : byte;                       { illegal logons }
     vote       : array[1..numvoteqs]         { voting information }
                     of byte;
     language   : string[8];                  { language }
     reserved6  : byte;                       { RESERVED}
  end;

  useridxrec=           { USERS.IDX : Sorted names listing }
  record
     name   : string[36];                     { user name/handle }
     number : integer;                        { user record # }
                                              {    -1 = Deleted }
  end;

  IDidxrec=             { USERID.IDX : Sorted ID listing }
  record
     userID : longint;                        { User-ID from user record }
     number : integer;                        { user record # }
                                              {    -1 = Deleted }
  end;

(*****************************************************************************)
(* ------------------------ AREA DATA STRUCTURES --------------------------- *)
(*****************************************************************************)

  areaidxrec=           { FAREAS.IDX/MAREAS.IDX: Area index records }
  record
     name   : string[8];                      { base filename }
     number : integer;                        { base record # }
                                              {    -1 = Deleted }
  end;

(*****************************************************************************)
(* ---------------------- FILE AREA DATA STRUCTURES ------------------------ *)
(*****************************************************************************)

  fareaflags=           { FAREAS.DAT status flags }
  (
     fbnoratio,                               { < No Ratio > active }
     fbvisible,                               { Visible to users w/o access }
     fbRESERVED1,                             { RESERVED }
     fbcdrom,                                 { CD-ROM/read-only media }
     fbusegifspecs                            { whether to use GifSpecs }
  );

  farearec=             { FAREAS.DAT : File base records }
  record
     desc       : string[40];                 { area description }
     filename,                                { filename }
     infofile   : string[8];                  { info filename }
     path       : string[40];                 { path }
     arctype    : string[3];                  { archive (''=inactive) }
     reserved1  : byte;                       { RESERVED }
     fstatus    : set of fareaflags;          { file area status }
     sysopacs,                                { SysOp access }
     listacs,                                 { list/view access }
     nameacs,                                 { see uploader name access }
     ulacs,                                   { upload access }
     dlacs      : acstring;                   { download access }
     scantype   : byte;                       { scan type  0 = Default ON
                                                           1 = Default OFF
                                                           2 = Always }
     cdlabel    : string[11];                 { CD-ROM label }
     createdate : unixtime;                   { base creation date }
     filepath   : string[40];                 { *.FB? storage path }
     reserved2  : array[1..42] of byte;       { RESERVED }
  end;

  fileidxrec=           { FILES.IDX: File index record }
  record
     filename   : string[12];                 { filename [key] }
     filebase,                                { filebase }
                                              {   -1 = deleted }
     filerecord : integer;                    { file offset }
     reserved   : array[1..4] of byte;        { RESERVED }
  end;

  fbstat=               { *.FB status flags }
  (
     freedl,                                  { if file is free }
     notime,                                  { if file is time check free }
     validated,                               { if file is validated }
     available,                               { if file is available - will }
                                              {    be toggled FALSE only }
                                              {    if failed by filescan }
     offline,                                 { if file is offline }
     hatch                                    { if file hatched via SDS }
  );

  fbrec=                { *.FB : File records }
  record
     filename    : string[12];                { filename }
     description : string[45];                { description }
     extended,                                { pointer to extended desc }
                                              {    -1 = no extended desc }
     size        : longint;                   { length of file (bytes) }
     uldate,                                  { date uploaded }
     filedate,                                { date on file }
     dldate      : unixtime;                  { date last downloaded }
     filestatus  : set of fbstat;             { file status }
     filepoints,                              { points }
     downloads   : Word;                      { number downloads }
     uploader    : string[36];                { uploader's name }
     passwordCRC : longint;                   { CRC of password to dl }
     reserved    : array[1..20] of byte;      { RESERVED }
  end;

  fbextrec=             { *.FBE : Extended descriptions }
  record
     filename : string[12];                   { filename (for reference) }
     desc     : array[1..5] of string[45];    { description }
     nextlink : longint;                      { offset to next record }
                                              {    -1 = last record }
     reserved : array[1..10] of byte;         { RESERVED }
  end;

 { The record offset into the *.FSI file is userrec.userid-1 (ie, if userid
   field = 2 then the record offset into file scan tables file is 1). }

  fbscanrec=            { *.FSI : File scan records }
  record
     filescan  : boolean;                     { base in file scan }
  end;

  driverec=             { DRIVES.DAT : CDROM/Network label storage }
  record
     update    : unixtime;                    { last update }
     disktype  : array[0..25] of byte;        { drive type }
                                              { 0-2: None, Floppy, HD }
                                              {  3 - CDROM }
                                              {  4 - Network }
     disklabel : array[0..25] of string[11];  { drive labels }
  end;

  queuerec=             { *.QQQ transfer queue record }
  record
     filename  : string[12];                  { filename }
     filearea  : longint;                     { file base # }
                                              { UL: -1  SysOp Area }
     desc      : string[45];                  { description }
     extended  : longint;                     { desc offset in *.QQD }
     path      : string[55];                  { DL: path of file }
     filepw    : longint;                     { UL: File password }
     reserved  : byte;                        { RESERVED }
     points    : integer;                     { DL: # file points }
     filesize  : longint;                     { DL: filesize (bytes) }
     freeratio,                               { DL: file is FREE ratio }
     freetime  : boolean;                     { DL: file is FREE time }
     readonly  : boolean;                     { Dl: file on read-only media }
  end;

(*****************************************************************************)
(* -------------------- MESSAGE AREA DATA STRUCTURES ----------------------- *)
(*****************************************************************************)

  mareaflags=           { MAREAS.DAT status flags }
  (
     mbrealname,                              { real names are forced }
     mbvisible,                               { visible to users w/o access }
     mbansi,                                  { filter ANSI }
     mb8bit,                                  { filter 8-bit }
     mbstrip,                                 { strip center/title codes }
     mbaddtear,                               { add tear/origin lines }
     mbnopubstat,                             { messages not added to user }
                                              {   public post total - i.e. }
                                              {   will not calculate in PCR }
     mbnocredit,                              { Netmail credit not used }
     mbinternet,                              { Internet (UUCP) handling }
     mbfattach,                               { allow file attaches }
     mbstripcolour                            { strip TG colour codes }
  );

  marearec=             { MAREAS.DAT : Message base records }
  record
     name,                                    { message base description }
     msgpath    : string[40];                 { messages pathname }
     filename,                                { data filenames }
     infofile   : string[8];                  { base info filename }
     readacs,                                 { read access }
     postacs,                                 { post access }
     sysopacs,                                { SysOp access }
     netacs     : acstring;                   { network access }
     maxmsgs,                                 { max message count }
     maxdays    : word;                       { max days to keep messages }
     mstatus    : set of mareaflags;          { status }
     mbformat,                                { message base format }
     mbtype,                                  { message base type }
     anonymous,                               { anonymous type }
     mbpost     : byte;                       { message base posting type }
     origin     : string[50];                 { origin line }
     kludge_color,                            { color of kludge line }
     quote_color,                             { color of quoted line }
     tear_color,                              { color of tear line }
     origin_color,                            { color of origin line }
     addr,                                    { network addr (0:AKA) }
     scantype   : byte;                       { scan type  0 = Default ON
                                                           1 = Default OFF
                                                           2 = Mandatory }
     createdate : unixtime;                   { base creation date }
     qwkindex   : longint;                    { QWK-permanent index }
     text_color : byte;                       { color of text line }
     reserved   : array[1..40] of byte;       { RESERVED }
  end;

 { The record offset into the *.MSI file is userrec.userid-1 (ie, if userid
   field = 2 then the record offset into message scan tables file is 1).
   This is the same offset that is used for the Squish (*.SQL) last read
   files.  The JAM (*.JLR) records can be searched for the matching userID
   to load lastread record. }

  mbscanrec=            { *.MSI : Message scan/lastread pointers }
  record
     mailscan,                                { base in mail scan }
     qwkscan   : boolean;                     { base in qwk scan }
  end;

  qwkidxrec=            { QWK.IDX : QWK message base index }
  record
     areanum : integer;                       { QWK area number }
     areatag : string[8];                     { message base filename }
  end;

  qptrrec=              { packetid.QPT : QWK lastread pointer record }
  record
     areanum  : integer;                      { QWK area number }
     lastread : longint;                      { last read pointer }
  end;


(*****************************************************************************)
(* ----------------------- OTHER DATA STRUCTURES --------------------------- *)
(*****************************************************************************)

  menuflag=            { Menu header status flags }
  (
     clrscrbefore,                            { C: clrscr before menu? }
     dontcenter,                              { D: don't center titles! }
     forcefullline,                           { F: force full line input }
     nomenuprompt,                            { N: no menu prompt }
     forcepause,                              { P: force pause before menu? }
     autotime,                                { T: auto time display? }
     dontcentersub,                           { S: don't center subtitles! }
     forcekey                                 { K: force key input }
  );

  menurec=              { *.MNU : Menu header }
  record
     menutitle : array[1..3] of               { menu titles }
                       string[100];
     dispfile,                                { help file displayed }
                                              {   ''       Generic }
     helpfile  : string[12];                  { tutorial help file }
                                              {   ''       Generic }
                                              {   '*OFF*'  Disabled }
     prompt    : string[120];                 { menu prompt }
     menuacs   : acstring;                    { access requirements }
     password  : string[15];                  { password required }
     fallback  : string[8];                   { fallback menu }
     helplevel,                               { forced help level for menu }
     columns   : byte;                        { generic menu: # of columns }
     colours   : array[1..6] of byte;         { generic menu: colours }
     menuflags : set of menuflag;             { menu status variables }
     global    : boolean;                     { load global menu }
     reserved1 : word;                        { RESERVED }
     nodestat  : string[36];                  { Who's Online Status }
     reserved2 : array[1..10] of byte;        { RESERVED }
  end;

  commandrec=           { *.MNU : Command records }
  record
     ldesc     : string[70];                   { long description }
     sdesc     : string[35];                   { short description }
     reserved  : string[15];                   { RESERVED }
     keys      : string[14];                   { execute keys }
                                               {   'FIRSTCMD' = Exec. Menu Loaded }
                                               {   'TITLE' = Sub-title }
                                               {   'ENTER' = <ENTER> }
                                               {   'SPACE' = <SPACEBAR> }
     acs       : acstring;                     { access requirements }
     cmdtype   : string[2];                    { command type }
     options   : string[50];                   { command options }
     viewtype  : byte;                         { display of command }
                                               {    0  ACS dependent }
                                               {    1  Always visbile }
                                               {    2  Always hidden }
  end;

(*---------------------------------------------------------------------------*)

  bbslistrec=           { *.BBS : BBS Listings }
  record
     phone          : string[20];             { BBS Phone Number }
     name,                                    { BBS Name }
     sysop          : string[30];             { BBS SysOp Name }
     description    : string[30];             { Other Description }
     speed          : string[4];              { Speed }
     software       : string[8];              { Software }
     firstdate,                               { First date added }
     lastedit       : unixtime;               { Last date edited }
     editor         : string[36];             { entry editor }
  end;

(*---------------------------------------------------------------------------*)

  archiverec=           { ARCHIVE.DAT : Archiver Setup }
  record
     active      : boolean;                   { is this format active? }
     extension   : string[3];                 { archive extension }
     description,                             { archiver description }
     compress,                                { pack archive command }
     decompress,                              { unpack archive command }
     test,                                    { test archive command }
     view,                                    { view archive command }
                                              {   ''=internal (if avail) }
     comment     : string[50];                { comment archive command }
     success     : byte;                      { success errorlevel }
     viewcapture : boolean;                   { redirect external viewer }
     reserved    : array[1..34] of byte;      { RESERVED }
  end;

(*---------------------------------------------------------------------------*)

  confrec=              { GROUPS.DAT : Group data }
  array['@'..'Z'] of
  record
     acs      : acstring;                     { ACS requirement }
     name     : string[40];                   { name of conference }
     visible  : boolean;                      { visible w/o ACS }
     reserved : array[1..20] of byte;         { RESERVED }
  end;

(*---------------------------------------------------------------------------*)

  eventflags=           { EVENTS.DAT status flags }
  (
     active,                                  { event is active }
     busyduring,                              { phone off-hook during event }
     monthly,                                 { event is executed monthly }
     forced                                   { event is forced }
  );

  eventrec=             { EVENTS.DAT : Scheduled event records }
  array[0..maxevents] of
     record
     flags    : set of eventflags;            { status flags }
     desc     : string[30];                   { description }
     etype    : char;                         { event type:
                                                 A:ACS,
                                                 C:Chat,
                                                 E:External,
                                                 O:OS }
     execdata : string[40];                   { event data:
                                                 ACS:  ACS command
                                                 OS:   OS command
                                                 Exit: ERRORLEVEL for exit }
     exectime,                                { execution time (minutes) }
     duration : word;                         { event duration (minutes) }
     execdays : byte;                         { monthly: day (1-28)
                                                  daily: days (bitwise) }
     lastexec : unixtime;                     { date event last executed }
     node     : word;                         { affected nodes (0=all) }
  end;

(*---------------------------------------------------------------------------*)

  historyrec =          { HISTORY.DAT : History logs }
  record
     date      : string[8];                   { history date }
     userbaud  : array[0..25] of word;        { logon BPS rates   }
                                              {    0 - Local   10 - 16800  }
                                              {    1 - 300     11 - 19200  }
                                              {    2 - 1200    12 - 21600  }
                                              {    3 - 1275    13 - 24000  }
                                              {    4 - 2400    14 - 26400  }
                                              {    5 - 4800    15 - 28800  }
                                              {    6 - 7200    16 - 38400  }
                                              {    7 - 9600    17 - 57600  }
                                              {    8 - 12000   18 - 64000  }
                                              {    9 - 14400   19 - 115200 }
     active,                                  { % activity }
     calls,                                   { # of calls }
     newusers,                                { # of new users }
     pubpost,                                 { # of public posts }
     privpost,                                { # of private posts }
     netpost,                                 { # of netmail posts }
     criterr,                                 { # of critical errors }
     uploads,                                 { # of uploads }
     downloads : word;                        { # of downloads }
     uk,                                      { amount ULed in KB }
     dk        : longint;                     { amount DLed in KB }
     reserved  : array[1..16] of byte;        { RESERVED }
  end;

(*---------------------------------------------------------------------------*)

  iemsirec=             { IEMSI.DAT : IEMSI connection record }
  record
     realname,                                { User's Real Name }
     handle       : string[36];               { User's Handle }
     location     : string[30];               { User's Location }
     dataph,                                  { User's Data Phone # }
     voiceph,                                 { User's Voice Phone # }
     password     : string[20];               { User's Password }
     birthdate    : unixtime;                 { User's Birthdate }
     linelen,                                 { Screen Width }
     pagelen      : byte;                     { Screen Length }
     screentype   : byte;
     protocols    : string[10];               { Protocol to use }
                                              {    DZA* DirectZAP Zmodem
                                                   ZAP* ZedZap Zmodem -> 8K
                                                   ZMO  Zmodem -> 1K (Z)
                                                   SLK* SEAlink
                                                   KER* Kermit }
     capabilities : string[25];               { System Capabilities }
                                              {    CHT*    IEMSI chats
                                                   MNU*    Image Downloading
                                                   TAB*    TAB support
                                                   ASCII8* 8-bit ASCII supprt }
     requests     : string[40];               { Requests }
                                              {    NEWS    Bulletins, news, etc.
                                                   MAIL*   Logon - Mail Check
                                                   FILE*   Logon - File Check
                                                   HOT     Hot-Keys
                                                   CLR     Screen clearing
                                                   HUSH*   Do not disturb
                                                   MORE    Page pausing
                                                   FSED    Full-screen editor }
     software     : string[70];               { Terminal Software }
  end;

  {
    *These items are are currently not supported in Telegard because they
    are things which were provided for systems with these capabilities.  They
    are listed here for convenience and so that utility authors can make
    use of them if neccessary.  Some of these options may be used in
    future versions of Telegard.

    (Z)The protocol that is selected by having the ZMO flag is protocol Z.
    If that protocol does not exist, it is not selected.  Protocol Z should
    be ZMODEM, otherwise the wrong protocol may be selected!
  }

(*---------------------------------------------------------------------------*)

  languagerec=          { LANGUAGE.DAT : Language records }
  record
     filename   : string[8];                  { language filename }
     desc       : string[30];                 { language description }
     acs        : acstring;                   { language ACS }
     textpath,                                { primary text path }
     menuspath  : string[75];                 { primary menus path }
                                              {   '' = use default }
     checktext  : boolean;                    { if primary path <> '' }
     checkmenus : boolean;                    {   and file not found, check }
                                              {   default path? }
  end;

(*---------------------------------------------------------------------------*)

  lcallers=             { LASTON.DAT : Last callers records }
  record
     caller     : longint;                    { system caller number }
     realname,                                { real name of caller }
     handle     : string[36];                 { user name of caller }
     location   : string[30];                 { location of caller }
     logonspeed : longint;                    { logon speed }
     logontime  : unixtime;                   { logon time }
     newuser,                                 { was newuser? }
     reserved1,                               { RESERVED }
     hidden     : boolean;                    { hidden from display? }
     node       : byte;                       { node }
     logofftime : unixtime;                   { logoff time }
     uploads,                                 { number of ul/dl }
     downloads  : word;
     uk,                                      { number of ul/dl kB }
     dk         : longint;
     reserved2  : array[1..8] of byte;        { RESERVED }
  end;

(*---------------------------------------------------------------------------*)

  levelsrec=            { LEVELS.DAT : Membership/validation levels }
  record
     desc      : string[50];                  { Description }
     sl        : byte;                        { SL level }
     flags1,                                  { Access flags - Set 1 }
     flags2    : acrqs;                       { Access flags - Set 2 }
     ac        : uflags;                      { Restriction flags }
     addfp,                                   { Bonus FilePoints (added) }
     addcredit,                               { Bonus NetCredits (added) }
     addtb,                                   { Bonus Timebank (added) }
     expireday : word;                        { Expire in ## days
                                                   0 = Never }
     tolevel   : char;                        { Expire to level A..Z,
                                                   ! = Delete }
     reserved  : array[1..25] of byte;        { RESERVED }
  end;

(*---------------------------------------------------------------------------*)

  macrorec=             { MACROS.DAT : Keyboard macro records }
  record
     userid : longint;                        { user-ID - from user record }
                                              {   checked to verify that }
                                              {   macro pointers are to }
                                              {   the correct macros }
     smacro : array[1..4] of string[240];     { stored keystrokes }
  end;

(*---------------------------------------------------------------------------*)

  modemflags=           { MODEM.DAT/MODEMxxx.DAT status flags }
  (
     xonxoff,                                 { XON/XOFF (software) flowctl }
     ctsrts,                                  { CTS/RTS (hardware) flowctl }
     dtrdrop,                                 { drop DTR to hang up modem }
     fossilhot,                               { FOSSIL active during DOS }
     int14                                    { INT 14 driven (no fossil) }
  );

  modemrec=             { MODEM.DAT/MODEMxxx.DAT : Modem configuration }
  record
     desc         : string[50];               { modem reference description }
     comport      : byte;                     { COM port number }
     waitbaud,                                { modem bps rate }
     lockedbaud   : longint;                  { locked bps rate }
                                              {    0 = Not Locked }
     init         : string[80];               { initialization command }
     answer,                                  { answer command }
     hangup,                                  { hangup command }
     offhook      : string[40];               { phone off-hook command }
     code_ok,                                 { OK result code }
     code_error,                              { ERROR result code }
     code_ring,                               { RING result code }
     code_nocarrier,                          { NO CARRIER result code }
     code_arq     : string[16];               { error correction string }
     code_connect : array[1..25] of           { connect strings }
                       string[16];            {    1 - 300     11 - 19200  }
                                              {    2 - 1200    12 - 21600  }
                                              {    3 - 1275    13 - 24000  }
                                              {    4 - 2400    14 - 26400  }
                                              {    5 - 4800    15 - 28800  }
                                              {    6 - 7200    16 - 38400  }
                                              {    7 - 9600    17 - 57600  }
                                              {    8 - 12000   18 - 64000  }
                                              {    9 - 14400   19 - 115200 }
                                              {   10 - 16800 }
     reinittime,                              { inactivity re-initialization }
     delay_cmd,                               { delay after cmd (1/10th) }
     delay_answer,                            { answer delay (1/10th) }
     delay_dtr    : byte;                     { delay for DTR drop (1/10th) }
     flags        : set of modemflags;        { status flags (see above) }
     irq          : byte;                     { IRQ for non-standard port }
     address      : string[4];                { base I/O address for port } 
     ansrings,                                { # rings before answering }
     ansreset     : byte;                     { seconds before counter reset }
     reserved     : array[1..67] of byte;     { RESERVED }
  end;

(*---------------------------------------------------------------------------*)

  netflags=             { NETWORK.DAT status flags }
  (
     nstrip,                                  { strip message codes? }
     naddtear,                                { add tear/origin lines? }
     nholduser,                               { hold all non-SysOp NetMail? }
     nhold,                                   { def NetMail to "hold"? }
     ncrash,                                  { def NetMail to "crash"? }
     nkill,                                   { def NetMail to "kill/sent"? }
     nstripcolour                             { strip colour codes? }
  );

  netaddress=           { NETWORK.DAT : Net address }
  record
     zone,net,node,point : word;              { (zone:net/node.point) }
  end;

  netaddrrec=           { NETWORK.DAT : Node information }
  record
     addr     : netaddress;                   { (zone:net/node.point) }
     akazone,                                 { aka matching zone:net }
     akanet   : word;                         { if net=0, match zone only }
     replynet : string[8];                    { areaname of replies for aka }
     RESERVED : array[1..18] of byte;         { RESERVED }
  end;

  networkrec=           { NETWORK.DAT : Network information }
  record
     netaddr      : array[1..20] of           { network addresses }
                       netaddrrec;
     origin       : string[50];               { origin line }
     kludge_color : byte;                     { color of kludge line }
     quote_color  : byte;                     { color of quoted text }
     tear_color   : byte;                     { color of tear line }
     origin_color : byte;                     { color of origin line }
     flags        : set of netflags;          { status flags }
     readacs,                                 { Default read ACS }
     postacs      : acstring;                 { Default post ACS }
     text_color,                              { color of text line }
     areaformat,                              { Default area format }
     areascan,                                { Default scan type }
     defaddr      : byte;                     { Default address }
     reserved1    : array[1..37] of byte;     { RESERVED }
     nodepath     : string[40];               { nodelist path }
     nodelisttype : byte;                     { Nodelist type
                                                   0 : None
                                                   1 : Version 6
                                                   2 : Version 7
                                                   3 : FrontDoor }
     UUCPgate     : netaddress;               { (zone:net/node.point) }
     sysopacs     : acstring;                 { Default sysop ACS }
     reserved2    : array[1..26] of byte;     { RESERVED }
  end;

(*---------------------------------------------------------------------------*)

  whosonflags=          { NODES.DAT : Who's Online status flags }
  (
     ishidden,                               { user is hidden }
     isquiet                                 { user not to be disturbed }
  );

  nodesrec=             { NODES.DAT : Multi-Node setup }
  record
     active      : boolean;                   { node can accept calls }
     logonbegin,                              { logon starts (0-1440) }
     logonend    : word;                      { logon ends (0-1440) }
     logonacs    : acstring;                  { access to logon }
     logonbps    : longint;                   { minimum logon bps }
     nodephone   : string[20];                { node phone number }
     reserved1   : array[1..45] of byte;      { RESERVED }

     realname,                                { realname }
     handle      : string[36];                { handle }
     location    : string[30];                { location }
     logontime   : unixtime;                  { logon time }
     statusid    : byte;                      { 0 - waiting for call }
                                              { 1 - unavailable (offline/down) }
                                              { 2 - event }
                                              { 3 - CONNECTED }
                                              { 4 - waiting for reset }
     status      : string[36];                { status }
     bpsrate     : longint;                   { bps rate }
     userid      : longint;                   { user-ID }
     flags       : set of whosonflags;        { status }
  
     reserved2   : array[1..45] of byte;      { RESERVED }
  end;

(*---------------------------------------------------------------------------*)

  protrec=              { PROTOCOL.DAT : File transfer protocols }
  record
     desc     : string[25];                   { description }
     active,                                  { active? }
     batch    : boolean;                      { batch? (=filelist) }
     acs      : acstring;                     { access control }
     ulcmd,                                   { UL command line }
     dlcmd    : string[60];                   { DL command line }
     ulcode,                                  { UL result code }
     dlcode   : array [1..3] of string[6];    { DL result code }
     envcmd   : string[60];                   { environment command }
     templog  : string[25];                   { temporary log file }
     flist    : string[5];                    { DL file list }
     logpf,                                   { log - word # (filename) }
     logpr    : byte;                         { log - word # (result) }
     success  : boolean;                      { results = success? }
     bidirec  : boolean;                      { bi-directional? }
  end;

(*---------------------------------------------------------------------------*)

  shortmsgrec=          { SHORTMSG.DAT/INODEnnn.DAT : Logon/Node Receipts }
  record
     userid   : longint;                      { to user id (0=deleted) }
     msg      : string[155];                  { message to user }
     msgid    : byte;                         { msgid - INTERNAL USE }
                                              { should *always* be 0 }
                                              { if set by external utils }
     reserved : array[1..4] of byte;          { RESERVED }
  end;

(*---------------------------------------------------------------------------*)

  smacrorec =           { SMACROS.DAT : SysOp Macros }
  record
     macro : array[1..10] of string[120];    { SysOp macros F1..F10 }
  end;

(*---------------------------------------------------------------------------*)

  timelogrec=           { TIMELOG.DAT : Daily/hourly usage tracking }
  record
     startdate      : unixtime;               { date graph started }
     busyperhour    : array[0..23] of word;   { busy per hour }
     busyperday     : array[0..6] of          { busy per dow, 20 minute }
                        array[0..71] of word; {    intervals }
  end;

(*---------------------------------------------------------------------------*)

  voterec=              { VOTING.DAT : Voting records }
  record
     active    : boolean;                     { active? }
     question  : string[75];                  { voting question }
     initdate  : longint;                     { initialization date }
     voteacs,                                 { voting acs }
     addacs    : acstring;                    { add answer acs }
     numusers  : word;                        { # user's answering question }
     numans    : byte;                        { # of active answers }
     answer    : array[0..numvoteas] of
                    record
                       desc   : string[60];   { answer description }
                       numres : word;         { # votes for this answer }
                    end;
  end;

(*****************************************************************************)
(* ---------------------- EXTERNAL DATA STRUCTURES ------------------------- *)
(*****************************************************************************)

 {
    The following structures are all derived from external sources and are
    not internal to Telegard 3.0 (i.e. the same format listed below is used
    for all other compatible products using the same specifications).

    For more information on the structures which are listed below, please
    refer to the DEVEL300.DOC documentation, which contains contact
    information and further reference listings for these structures.
 }

(*****************************************************************************)
(* ------------ NODELIST FILE STRUCTURES ("VERSION 6" FORMAT) -------------- *)
(*****************************************************************************)

  nodeflags=            { NODELIST.DAT status flags }
  (
     hub,                                     { node is a net hub }
     host,                                    { node is a net host }
     region,                                  { node is region coord }
     zone,                                    { node is a zone coord }
     cm                                       { runs continuous mail }
  );

  modemtypes=           { NODELIST.DAT modem type flags }
  (
     hst,                                     { node uses a USRobotics HST modem }
     pep,                                     { node uses a Telebit PEP modem }
     v32,                                     { node uses a V.32 modem }
     v32b,                                    { node uses a V.32bis modem }
     h96                                      { node uses a Hayes Express96 modem }
  );

  nodedatarec=          { NODELIST.DAT : Version 6 nodelist data }
  record
     net:integer;                             { net number }
     node:integer;                            { node number }
     cost:integer;                            { cost per minute to call }
     name:array[0..33] of char;               { node name }
     phone:array[0..39] of char;              { phone number }
     city:array[0..29] of char;               { city and state }
     password:array[0..7] of byte;            { password }
     realcost:integer;                        { phone company's charge }
     hubnode:integer;                         { node # of this node's hub (0=none) }
     rate:byte;                               { actual bps rate divided by 300 }
     modem:set of modemtypes;                 { modem type codes }
     res1:byte;                               { RESERVED }
     flags:set of nodeflags;                  { set of flags }
     res:array[1..2] of byte;                 { RESERVED }
  end;

  nodeindexrec=         { NODELIST.IDX : Version 6 nodelist index }
  record
     node : integer;                          { node number }
     net  : integer;                          { net number }
  end;

(*****************************************************************************)
(* ------------ NODELIST FILE STRUCTURES ("VERSION 7" FORMAT) -------------- *)
(*****************************************************************************)

  node7flags=            { NODELIST.DAT Version 7 status flags }
  (
     ishub,                                   { node is a net hub }
     ishost,                                  { node is a net host }
     isregion,                                { node is region coord }
     isgate,                                  { node is a zone gateway }
     iscm,                                    { runs continuous mail }
     res1,res2,res3,res4,res5,                { RESERVED }
     res6,res7,
     ispoint                                  { node is a point }
  );

  node7datarec=          { NODELIST.DAT : Version 7 nodelist data }
  record
     zone,net,node:integer;                   { node address }
     hubnode:integer;                         { hub node address }
     callcost,                                { Cost of call }
     msgfee    : word;                        { Cost to user }
     flags     : set of node7flags;           { nodelist flags }
     modem     : byte;                        { RESERVED }
     phlen,                                   { Phone # length }
     pwlen,                                   { PW length }
     boardlen,                                { Board name length }
     sysoplen,                                { SysOp name length }
     citylen,                                 { City length }
     packlen   : byte;                        { Pack total length }
     baudrate  : byte;                        { bps rate divided by 300 }
     { ... data ... }                         { packed data - length packlen }
  end;

(*****************************************************************************)
(* ------------------- QWK OFFLINE MAIL FILE STRUCTURES -------------------- *)
(*****************************************************************************)

  qdatrec=              { MESSAGES.DAT : Message file header record }
  record
     status:char;                             { message status flag:             }
                                              { ' ' = public, unread             }
                                              { '-' = public, read               }
                                              { '+' = private, unread            }
                                              { '*' = private, read              }
                                              { '~' = comment to SysOp, unread   }
                                              { '`' = comment to SysOp, read     }
                                              { '%' = password protected, unread }
                                              { '^' = password protected, read   }
                                              { '!' = group password, unread     }
                                              { '#' = group password, read       }
                                              { '$' = group password to all      }
     number:array[1..7] of char;              { message number }
     date:array[1..8] of char;                { date (MM-DD-YY) }
     time:array[1..5] of char;                { time (HH:MM) }
     msgto:array[1..25] of char;              { To (uppercase) }
     msgfrom:array[1..25] of char;            { From (uppercase) }
     subject:array[1..25] of char;            { Subject }
     password:array[1..12] of char;           { password }
     reference:array[1..8] of char;           { reference message number }
     blocks:array[1..6] of char;              { # of blocks in message,  }
                                              {   including header block }
     active:byte;                             { $E1=active, $E2=to be deleted }
     areanum:word;                            { QWK area number }
     res:array[1..2] of byte;                 { NOT USED }
     tagline:char;                            { contains network tagline:     }
                                              { '*' = network tagline present }
                                              { ' ' = no tagline present      }
  end;

  qndxrec=              { *.NDX : Message area index record }
  record
     recnum:longint;                          { record number in MESSAGES.DAT,    }
                                              {   stored in Microsoft MKS$ format }
     areanum:byte;                            { QWK area number (unused) }
  end;

(****************************************************************************)
(* --------------------------- JAM STRUCTURES ----------------------------- *)
(****************************************************************************)

  jaminforec =          { *.JHR: JAM message base header - first record }
  record
     signature   : array[1..4]                { message Signature }
                      of char;                { <J><A><M> followed by <NUL> }
     datecreated,                             { creation Date }
     modifycount,                             { modification counter }
     activemsgs,                              { active Messages }
     passwordCRC,                             { CRC of password, -1 = none }
     basemsgnum  : longint;                   { lowest number in index }
     reserved    : array[1..1000]             { reserved by JAM authors }
                      of char;
  end;

  jammsgattr =          { JAM message base attributes }
  (
     jlocal,                                  { local }
     jintransit,                              { in-transit }
     jprivate,                                { private }
     jread,                                   { read by receiver }
     jsent,                                   { sent }
     jkillsent,                               { kill msg/sent }
     jarchivesent,                            { archive msg/sent }
     jhold,                                   { hold }
     jcrash,                                  { crash }
     jimmediate,                              { immediate }
     jdirect,                                 { direct }
     jgate,                                   { gate }
     jfilereq,                                { file requests }
     jfileattach,                             { files attached }
     jtruncfiles,                             { truncate (0 len) sent files }
     jkillfiles,                              { kill sent files }
     jreceiptreq,                             { receipt requested }
     jconfirmreq,                             { confirmation of receipt }
     jorphan,                                 { orphaned message }
     jencrypt,                                { encrypted message* }
     jcompress,                               { compressed message* }
     jescaped,                                { escaped message* }
     jforcepickup,                            { force pickup }
     jtypelocal,                              { local only }
     jtypeecho,                               { for echo dist'n }
     jtypenet,                                { for netmail dist'n }
     jRESERVED,                               { 0x04000000L }
     jRESERVED1,                              { 0x08000000L }
     jRESERVED2,                              { 0x10000000L }
     jnomsgdisplay,                           { no message display }
     jlocked,                                 { locked message }
     jdeleted                                 { deleted message }
  );

  jamhdrrec =           { *.JHR: JAM message headers }
  record
     signature   : array[1..4]                { message signature }
                      of char;                { <J><A><M> followed by <NUL> }
     revision,                                { JAM revision level }
     reserved1   : word;                      { reserved by JAM authors }
     subfieldlen,                             { length of subfields }
     timesread,                               { # times message read }
     msgidCRC,                                { CRC-32 of MSGID line }
     replyCRC,                                { CRC-32 of REPLY line }
     replyto,                                 { reply to # }
     reply1st,                                { 1st reply number }
     replynext   : longint;                   { reply next }
     date,                                    { date written }
     datercvd,                                { date received }
     dateproc    : unixtime;                  { date processed (tosser/scanner) }
     msgnum      : longint;                   { message number }
     attribute   : set of jammsgattr;         { attributes }
     reserved2,                               { reserved by JAM authors }
     textoffset,                              { offset of text in *.JDT file }
     textlen,                                 { length of text }
     passwordCRC,                             { CRC-32 of password }
     cost        : longint;                   { cost of message }
  end;

  jamsubfieldrec =      { *.JHR: subfield records }
  record
     fieldid,                                 { subfield ID }
     reserved1   : word;                      { reserved by JAM authors }
     datalen     : longint;                   { length of buffer }
  end;

  jamindexrec =         { *.JDX: JAM quick index }
  record
     userCRC,                                 { CRC-32 of receipients name (lower) }
     hdroffset   : longint;                   { offset to jamhdrrec }
  end;

  jamreadrec =          { *.JLR: JAM last read storage }
  record
     userCRC,                                 { CRC-32 of users name (lower) }
     userID,                                  { unique user-ID }
     lastread,                                { last read pointer }
     highread    : longint;                   { high read pointer }
  end;

(****************************************************************************)
(* ------------------------- SQUISH STRUCTURES ---------------------------- *)
(****************************************************************************)

 sqbaserec =            { *.SQD: Squish message base header - first record }
 record
    len_sqbase,                               { length of this structure }
    reserved   : word;                        { RESERVED }
    nummsgs,                                  { number of messages }
    highmsg,                                  { highest message (=nummsgs) }
    keepmsgs,                                 { # of messages to keep }
    hwmsgid,                                  { High water message msg-ID # }
    lastmsgid  : longint;                     { Last message msg-ID # }
    basename   : array[1..80] of char;        { basename for Squishfile }
    beginframe,                               { offset to first message header }
    lastframe,                                { offset to last message header }
    freeframe,                                { offset to first FREE header }
    lastfreeframe,                            { offset to last FREE header }
    endframe,                                 { offset of end of file }
    maxmsgs    : longint;                     { maximum number of messages }
    keepdays   : word;                        { days to keep messages }
    sqhdrsize  : word;                        { size of header record }
    reserved2  : array[1..124] of byte;       { RESERVED }
   end;

 sqhdrrec =             { *.SQD: Message header }
 record
    sqid,                                     { squish ID - $AFAE4453 }
    nextmsg,                                  { offset to last message }
    prevmsg,                                  { offset to previous message }
    framelength,                              { length of header & message }
    msglength,                                { length of message }
    ctrllength : longint;                     { length of control information }
    headertype,                               { Header type
                                                   Message = 0
                                                   Free    = 1 }
    reserved    : word;                       { RESERVED }
  end;

  sqshmsgattr =         { Squish Message Attributes }
  (
     sprivate,                                { private }
     scrash,                                  { crash }
     sread,                                   { read by receiver }
     ssent,                                   { sent }
     sfileattach,                             { files attached }
     sintransit,                              { in-transit }
     sorphan,                                 { orphaned message }
     skillsent,                               { kill msg/sent }
     slocal,                                  { local }
     shold,                                   { hold }
     sreserved,                               { reserved }
     sfilereq,                                { file requests }
     sreceiptreq,                             { receipt requested }
     sconfirmreq,                             { confirmation of receipt }
     saudit,                                  { audit trail requested }
     supdate,                                 { update request }
     sscanned,                                { echomail scanned }
     smsgid,                                  { valid msgid? }
     sres1,  sres2,  sres3,  sres4,           { reserved }
     sres5,  sres6,  sres7,  sres8,
     sres9,  sres10, sres11, sres12,
     sres13, sres14
  );

 sqxmsgrec =            { *.SQD: Message Info Header }
 record
    attribute   : set of sqshmsgattr;         { Message attributes }
    msgfrom     : array[1..36] of char;       { Message from - NUL terminated }
    msgto       : array[1..36] of char;       { Message to - NUL terminated }
    subject     : array[1..72] of char;       { Message subject - NUL terminated }
    origaddr,                                 { Origin/Destination addresses }
    destaddr    : record
                     zone, net,
                     node, point : word;
                  end;
    origdate,                                 { Original date (utc) }
    msgdate     : bitmapdate;                 { Arrival (system) date (utc) }
    utcoffset   : word;                       { Minutes offset of UTC }
    replyto     : longint;                    { Reply-to msg-ID # }
    replies     : array[1..9] of              { Replies msg-ID # }
                     longint;
    msgid       : longint;                    { Message ID }
    rawdate     : array[1..20] of char;       { ASCII date - NUL terminated }
 end;

 sqindexrec =           { *.SQI: Squish Message Index }
 record
    msgptr,                                   { offset of sqfhdr record }
    msgid,                                    { msg-ID # }
    hash   : longint;                         { hash of 'to' name }
 end;

 sqreadrec =            { *.SQL: Squish Last Read Index }
 record
    msgid : longint;                          { msg-ID # }
 end;

(****************************************************************************)
(* ------------------------ TESTINFO.DAT FORMAT --------------------------- *)
(****************************************************************************)

 testinfofilerec =      { TESTINFO.DAT: individual file record }
 record
    sfx,                                      { is self-extracting file? }
    exists     : boolean;                     { file exists }
    full_path,                                { full file path }
    path       : string[60];                  { file path }
    drive      : string[2];                   { file drive (incl colon) }
    name       : string[8];                   { filename (raw) }
    ext,                                      { extension }
    filetype   : string[3];                   { file type* }
    date       : longint;                     { file date_time (packed) }
    size       : longint;                     { file size }
 end;

 testinforec =          { TESTINFO.DAT }
 record
    processed,                                { record has been processed }
    desc_vendinfo,                            { vendinfo.diz description }
    desc_import,                              { import descriptions? }
    addtofdb,                                 { add file to file data base }
    file_conv,                                { file converted? }
    user_ansi,                                { detected ansi }
    user_avatar,                              { detected avatar }
    user_carrier,                             { carrier detected last check }
    bbsprocessed     : boolean;               { processed by BBS? }
    reserved1        : array[1..8] of byte;   { RESERVED }
    check_count,                              { update/check count }
    bbs_type,                                 { BBS type ( TG3.0 = 6 ) }
    user_comport,                             { user com port }
    exit_level,                               { exit level for test }
    revision         : byte;                  { testinfo.dat revision level }
    reserved2        : array[1..9] of byte;   { RESERVED }
    test_datetime    : longint;               { testing date/time }
    reserved3        : array[1..40] of byte;  { RESERVED }
    thd_options,                              { THDPRO command line options }
    bbs_path,                                 { path to BBS data files }
    creator,                                  { TESTINFO.DAT creator }
    thd_log          : string[60];            { THDPRO log path }
    reserved4        : array[1..183] of byte; { RESERVED }
    ver_major,                                { creator - major version }
    ver_minor        : string[2];             { creator - minor version }
    thd_session      : string[3];             { THDPRO session number }
    desc_filename    : string[12];            { description file filename }
    reserved5        : array[1..39] of byte;  { RESERVED }
    file_original,                            { original file information }
    file_finished    : testinfofilerec;       { finished file information }
    reserved6        : array[1..10] of byte;  { RESERVED }
    desc_length      : integer;               { length fo description }
    desc             : array[1..1500] of      { description }
                          char;
 end;

