Renegade-1.19/SOURCE/COMMON.PAS

5077 lines
141 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{$IFDEF WIN32}
{$I DEFINES.INC}
{$ENDIF}
{$A+,B-,D-,E-,F+,I-,L-,N+,O-,R-,S-,V-}
UNIT Common;
INTERFACE
USES
Crt,
Dos,
MyIO,
TimeFunc;
{$I RECORDS.PAS}
CONST
StrLen = 119;
TYPE
MCIFunctionType = FUNCTION(CONST s: AStr; Data1, Data2: Pointer): STRING;
MemMenuRec = RECORD { Menu Record }
LDesc: ARRAY[1..3] OF STRING[100]; { menu name }
ACS: ACString; { access requirements }
NodeActivityDesc: STRING[50];
MenuFlags: MenuFlagSet; { menu status variables }
LongMenu: STRING[12]; { displayed IN place OF long menu }
MenuNum: Byte; { menu number }
MenuPrompt: STRING[120]; { menu Prompt }
Password: STRING[20]; { password required }
FallBack: Byte; { fallback menu }
Directive: STRING[12];
ForceHelpLevel: Byte; { forced help Level FOR menu }
GenCols: Byte; { generic menus: # OF columns }
GCol: ARRAY[1..3] OF Byte; { generic menus: colors }
END;
MemCmdRec = RECORD { Command records }
LDesc: STRING[100]; { long command description }
ACS: ACString; { access requirements }
NodeActivityDesc: STRING[50];
CmdFlags: CmdFlagSet; { command status variables }
SDesc: STRING[35]; { short command description }
CKeys: STRING[14]; { command-execution keys }
CmdKeys: STRING[2]; { command keys: type OF command }
Options: STRING[50]; { MString: command data }
END;
LightBarRecordType = RECORD
XPos,
YPos: Byte;
CmdToExec: SmallInt;
CmdToShow: STRING[40];
END;
States =
(Waiting,
Bracket,
Get_Args,
Get_Param,
Eat_Semi,
In_Param,
GetAvCmd,
GetAvAttr,
GetAvRLE1,
GetAvRLE2,
GetAvX,
GetAvY);
StorageType =
(Disk,
CD,
Copied);
TransferFlagType =
(lIsAddDLBatch,
IsFileAttach,
IsUnlisted,
IsTempArc,
IsQWK,
IsNoFilePoints,
IsNoRatio,
IsCheckRatio,
IsCDRom,
IsPaused,
IsAutoLogOff,
IsKeyboardAbort,
IsTransferOk);
TransferFlagSet = SET OF TransferFlagType;
BatchDLRecordType = RECORD
BDLFileName: Str52;
BDLOwnerName: Str36;
BDLStorage: StorageType;
BDLUserNum,
BDLSection,
BDLPoints,
BDLUploader: SmallInt;
BDLFSize,
BDLTime: LongInt;
BDLFlags: TransferFlagSet;
END;
BatchULRecordType = RECORD
BULFileName: Str12;
BULUserNum,
BULSection: SmallInt;
BULDescription: Str50;
BULVPointer: LongInt;
BULVTextSize: SmallInt;
END;
ExtendedDescriptionArray = ARRAY [1..99] OF Str50;
IEMSIRecord = RECORD
UserName,
Handle: STRING[36];
CityState: STRING[30];
Ph: STRING[12];
PW: STRING[20];
BDate: STRING[10];
END;
StrPointerRec = RECORD
Pointer,
TextSize: LongInt;
END;
MemCmdPointer = ^MemCmdArray;
MemCmdArray = ARRAY [1..MaxCmds] OF MemCmdRec;
MCIBufferType = ARRAY [1..MaxConfigurable] OF Char;
MCIBufferPtr = ^MCIBufferType;
Multitasker =
(None, (* Dos 5 thu 9 *)
DV,
Win,
OS2,
Win32,
DOS5N);
InputFlagType =
(UpperOnly, { Uppercase only }
ColorsAllowed, { Colors allowed }
NoLineFeed, { Linefeeds OFF - no linefeed after <CR> pressed }
ReDisplay, { Display old IF no change }
CapWords, { Capitalize characters }
InterActiveEdit, { Interactive editing }
NumbersOnly,
DisplayValue,
NegativeAllowed); { Numbers only }
InputFlagSet = SET OF InputFlagType;
ValidationKeyType = SET OF '!'..'~'; (* Remove q and Q *)
ConferenceKeyType = SET OF '@'..'Z';
CompArrayType = ARRAY[0..1] OF SMALLINT;
CONST
MCIBuffer: MCIBufferPtr = NIL;
DieLater: Boolean = FALSE; { IF TRUE, Renegade locks up }
F_HOME = 18176; { 256 * Scan Code }
F_UP = 18432;
F_PGUP = 18688;
F_LEFT = 19200;
F_RIGHT = 19712;
F_END = 20224;
F_DOWN = 20480;
F_PGDN = 20736;
F_INS = 20992;
F_DEL = 21248;
F_CTRLLEFT = 29440;
F_CTRLRIGHT = 29696;
NoCallInitTime = (30 * 60); { thirty minutes between modem inits }
Tasker: Multitasker = None;
LastScreenSwap: LongInt = 0;
ParamArr: ARRAY [1..5] OF Word = (0,0,0,0,0);
Params: Word = 0; { number OF parameters }
NextState: States = Waiting; { Next state FOR the parser }
TempSysOp: Boolean = FALSE; { is temporary sysop? }
Reverse: Boolean = FALSE; { TRUE IF Text attributes are reversed }
TimeLock: Boolean = FALSE; { IF TRUE, DO NOT HangUp due TO time! }
SaveX: Byte = 0; { FOR ANSI driver}
SaveY: Byte = 0; { FOR ANSI driver}
TempPause: Boolean = TRUE; { is Pause on OR off? Set at prompts, OneK, used everywhere }
OfflineMail: Boolean = FALSE; { are we IN the offline mail system? }
MultiNodeChat: Boolean = FALSE; { are we IN MultiNode chat?}
ChatChannel: Integer = 0; { What chat channel are we IN? }
DisplayingMenu: Boolean = FALSE; { are we displaying a menu? }
InVisEdit: Boolean = FALSE; { are we IN the visual editor? }
MenuAborted: Boolean = FALSE; { was the menu Aborted? }
AllowAbort: Boolean = TRUE; { are Aborts allowed? }
MCIAllowed: Boolean = TRUE; { is mci allowed? }
ColorAllowed: Boolean = TRUE; { is color allowed? }
Echo: Boolean = TRUE; { is Text being echoed? (FALSE=use echo Chr)}
HangUp: Boolean = TRUE; { is User offline now? }
TimedOut: Boolean = FALSE; { has he timed out? }
NoFile: Boolean = TRUE; { did last pfl() FILE NOT Exist? }
SLogging: Boolean = TRUE; { are we outputting TO the SysOp log? }
SysOpOn: Boolean = TRUE; { is SysOp logged onto the WFC menu? }
WantOut: Boolean = TRUE; { output Text locally? }
WColor: Boolean = TRUE; { IN chat: was last key pressed by SysOp? }
BadDLPath: Boolean = FALSE; { is the current DL path BAD? }
BadUlPath: Boolean = FALSE; { is the current UL path BAD? }
BeepEnd: Boolean = FALSE; { whether TO beep after caller logs off }
FileAreaNameDisplayed: Boolean = FALSE; { was FILE area name printed yet? }
CFO: Boolean = FALSE; { is chat FILE open? }
InChat: Boolean = FALSE; { are we IN chat Mode? }
ChatCall: Boolean = FALSE; { is the chat call "noise" on? }
ContList: Boolean = FALSE; { continuous message listing Mode on? }
CROff: Boolean = FALSE; { are CRs turned off? }
CtrlJOff: Boolean = FALSE; { turn color TO #1 after ^Js?? }
DoneAfterNext: Boolean = FALSE; { offhook AND Exit after Next logoff? }
DoneDay: Boolean = FALSE; { are we done now? ready TO drop TO DOS?}
DOSANSIOn: Boolean = FALSE; { output chrs TO DOS FOR ANSI codes?!!? }
FastLogon: Boolean = FALSE; { IF a FAST LOGON is requested }
HungUp: Boolean = FALSE; { did User drop carrier? }
InCom: Boolean = FALSE; { accepting input from com? }
InWFCMenu: Boolean = FALSE; { are we IN the WFC menu? }
LastCommandGood: Boolean = FALSE;{ was last command a REAL command? }
LastCommandOvr: Boolean = FALSE; { override Pause? (NO Pause?) }
LocalIOOnly: Boolean = FALSE; { local I/O ONLY? }
MakeQWKFor: Integer = 0; { make a qwk packet ONLY? }
UpQWKFor: Integer = 0; { upload a qwk packet ONLY? }
RoomNumber: Integer = 0; { Room OF teleconference }
PackBasesOnly: Boolean = FALSE; { pack message bases ONLY? }
SortFilesOnly: Boolean = FALSE; { sort FILE bases ONLY? }
FileBBSOnly: Boolean = FALSE;
NewMenuToLoad: Boolean = FALSE; { menu command returns TRUE IF new menu TO load }
OvrUseEMS: Boolean = TRUE;
OverLayLocation: Byte = 0; { 0=Normal, 1=EMS, 2=XMS }
OutCom: Boolean = FALSE; { outputting TO com? }
DirFileopen1: Boolean = TRUE; { whether DirFile has been opened before }
ExtFileOpen1: Boolean = TRUE;
PrintingFile: Boolean = FALSE; { are we printing a FILE? }
AllowContinue: Boolean = FALSE; { Allow Continue prompts? }
QuitAfterDone: Boolean = FALSE; { quit after Next User logs off? }
Reading_A_Msg: Boolean = FALSE; { is User reading a message? }
ReadingMail: Boolean = FALSE; { reading private mail? }
ShutUpChatCall: Boolean = FALSE; { was chat call "SHUT UP" FOR this call? }
Trapping: Boolean = FALSE; { are we Trapping users Text? }
UserOn: Boolean = FALSE; { is there a User on right now? }
WasNewUser: Boolean = FALSE; { did a NEW User log on? }
Write_Msg: Boolean = FALSE; { is User writing a message? }
NewEchoMail: Boolean = FALSE; { has new echomail been entered? }
TimeWarn: Boolean = FALSE; { has User been warned OF time shortage? }
TellUserEvent: Byte = 0; { has User been told about the up-coming event? }
ExitErrors: Byte = 1; { errorLEVEL FOR Critical error Exit }
ExitNormal: Byte = 0; { errorLEVEL FOR Normal Exit }
TodayCallers: Integer = 0; { new system callers }
lTodaynumUsers: Integer = 0; { new number OF users }
ThisNode: Byte = 0; { node number }
AnswerBaud: LongInt = 0; { baud rate TO answer the phone at }
ExtEventTime: Word = 0; { # minutes before External event }
IsInvisible: Boolean = FALSE; { Run IN invisible Mode? }
SaveNDescription: STRING[50] = 'Miscellaneous';
SaveNAvail: Boolean = FALSE;
LastWFCX: Byte = 1;
LastWFCY: Byte = 1;
ANSIDetected: Boolean = FALSE;
{ Added June 21, 2013 //sk5 }
PauseIsNull : Boolean = FALSE; { Added for null pause }
BuildDate : Array [1..5] of Word = ( 5, 27, 2013, 9, 19 ); { Build date MM, DD, YYYY, HR, MIN }
VAR
LightBarArray: ARRAY[1..50] OF LightBarRecordType;
LightBarCmd,
LightBarCounter: Byte;
LightBarFirstCmd: Boolean;
Telnet: Boolean;
HangUpTelnet: Boolean;
DatFilePath: STRING[40];
Interrupt14: Pointer; { far ptr TO interrupt 14 }
{$IFDEF MSDOS}
Ticks: LongInt ABSOLUTE $0040:$006C;
{$ENDIF}
IEMSIRec: IEMSIRecord;
FossilPort: Word;
SockHandle: STRING; { Telnet Handle }
CallerIDNumber: STRING[40]; { Caller ID STRING obtained from modem }
ActualSpeed: LongInt; { Actual connect rate }
Reliable: Boolean; { error correcting connection? }
ComPortSpeed: LongInt; { com port rate }
LastError: Integer; { Results from last IOResult, when needed }
General: GeneralRecordType; { configuration information }
DirInfo: SearchRec;
{ LastCallers }
LastCallerFile : FILE OF LastCallerRec;
LastCallers : LastCallerRec;
{ Today's History }
HistoryFile : FILE OF HistoryRecordType;
HistoryRec : HistoryRecordType;
{ Voting Variables }
VotingFile: FILE OF VotingRecordType;
Topic: VotingRecordType;
NumVotes: Byte;
BBSListFile: FILE OF BBSListRecordType; { bbslist.dat }
{ Conference Variables }
ConferenceFile: FILE OF ConferenceRecordType; { CONFRENC.DAT }
Conference: ConferenceRecordType; { Conferences }
ConfKeys: ConferenceKeyType;
NumConfKeys: Integer;
CurrentConf: Char; { Current conference tag }
ConfSystem: Boolean; { is the conference system enabled? }
{ Validation Variables }
ValidationFile: FILE OF ValidationRecordType;
Validation: ValidationRecordType;
NumValKeys: Byte;
ValKeys: ValidationKeyType;
NumArcs: Byte;
NodeFile: FILE OF NodeRecordType; { multi node FILE }
NodeR: NodeRecordType;
NodeChatLastRec: LongInt; { last record IN group chat FILE Read }
Liner: LineRec;
SysOpLogFile, { SYSOP.LOG }
SysOpLogFile1, { SLOGxxxx.LOG }
TrapFile, { TRAP*.MSG }
ChatFile: Text; { CHAT*.MSG }
{ User Variables }
UserFile: FILE OF UserRecordType; { User.LST }
UserIDXFile: FILE OF UserIDXRec; { User.IDX }
ThisUser: UserRecordType; { User's account records }
{ Color Scheme Variables }
SchemeFile: FILE OF SchemeRec; { SCHEME.DAT }
Scheme: SchemeRec;
NumSchemes: Integer;
{ Event Variables }
EventFile: FILE OF EventRecordType;
MemEventArray: ARRAY [1..MaxEvents] OF ^EventRecordType;
Event: EventRecordType;
NumEvents: Integer; { # OF events }
{ Protocol Variables }
ProtocolFile: FILE OF ProtocolRecordType; { PROTOCOL.DAT }
Protocol: ProtocolRecordType; { protocol IN memory }
NumProtocols: Integer;
{ File Variables }
FileAreaFile: FILE OF FileAreaRecordType; { FBASES.DAT }
MemFileArea,
TempMemFileArea: FileAreaRecordType; { File area and temporary file area in memory }
FileInfoFile: FILE OF FileInfoRecordType; { *.DIR }
ExtInfoFile: FILE; { *.EXT }
FileInfo: FileInfoRecordType;
ExtendedArray: ExtendedDescriptionArray;
NewFilesF: Text; { For NEWFILES.DAT in the qwk system }
FileArea, { File base User is in }
NumFileAreas, { Max number OF FILE bases }
ReadFileArea, { current uboard # IN memory }
LowFileArea,
HighFileArea: Integer;
NewScanFileArea: Boolean; { New scan this base? }
{ Batch Download Variables }
BatchDLFile: FILE OF BatchDLRecordType;
BatchDL: BatchDLRecordType;
NumBatchDLFiles: Byte; { # files IN DL batch queue }
BatchDLSize,
BatchDLPoints,
BatchDLTime: LongInt; { }
{ Batch Upload Variables }
BatchULFile: FILE OF BatchULRecordType;
BatchULF: FILE;
BatchUL: BatchULRecordType;
NumBatchULFiles: Byte; { # files IN UL batch queue }
{ Message Variables }
EmailFile: FILE OF MessageAreaRecordType;
MsgAreaFile: FILE OF MessageAreaRecordType; { MBASES.DAT }
MemMsgArea: MessageAreaRecordType; { MsgArea IN memory }
MsgHdrF: FILE OF MHeaderRec; { *.HDR }
MsgTxtF: FILE; { *.DAT }
LastReadRecord: ScanRec;
LastAuthor, { Author # OF the last message }
NumMsgAreas, { Max number OF msg bases }
MsgArea,
ReadMsgArea,
LowMsgArea,
HighMsgArea: Integer;
Msg_On: Word; { current message being Read }
{ Menu Variables }
MenuFile: FILE OF MenuRec;
MenuR: MenuRec;
MemMenu: MemMenuRec; { menu information }
MemCmd: MemCmdPointer; { Command information }
MenuRecNumArray: ARRAY [1..MaxMenus] OF Integer;
CmdNumArray: ARRAY [1..MaxMenus] OF Byte;
MenuStack: ARRAY [1..MaxMenus] OF Byte; { menu stack }
MenuKeys: AStr; { keys TO Abort menu display WITH }
NumMenus,
NumCmds,
GlobalCmds,
MenuStackPtr,
FallBackMenu,
CurMenu,
CurHelpLevel: Byte;
Buf: STRING[255]; { macro buffer }
MLC: STRING[255]; { multiline FOR chat }
ChatReason, { last chat reason }
LastLineStr, { "last-line" STRING FOR Word-wrapping }
StartDir: AStr; { Directory BBS was executed from }
TempDir, { Temporary Directory base name }
InResponseTo: STRING[40]; { reason FOR reply }
LastDIRFileName: Str12; { last filename FOR recno/nrecno }
CurrentColor, { current ANSI color }
ExiterrorLevel, { errorLEVEL TO Exit WITH }
TShuttleLogon, { type OF special Shuttle Logon command }
TFilePrompt, { type OF special FILE Prompt command }
TReadPrompt, { type OF special Read Prompt command }
PublicPostsToday, { posts made by User this call }
FeedBackPostsToday, { feedback sent by User this call }
PrivatePostsToday: Byte; { E-mail sent by User this call }
LastDIRRecNum, { last record # FOR recno/nrecno }
ChatAttempts, { number chat attempts made by User }
LIL, { lines on screen since last PauseScr() }
PublicReadThisCall, { # public messages has Read this call }
UserNum: Integer; { User's User number }
Rate: Word; { cps FOR FILE transfers }
NewFileDate, { NewScan Pointer date }
DownloadsToday, { download sent TO User this call }
UploadsToday, { uploads sent by User this call }
DownloadKBytesToday, { download k by User this call }
UploadKBytesToday, { upload k by User this call }
CreditsLastUpdated, { Time Credits last updated }
TimeOn, { time User logged on }
LastBeep,
LastKeyHit,
ChopTime, { time TO chop off FOR system events }
ExtraTime, { extra time - given by F7/F8, etc }
CreditTime, { credit time adjustment }
FreeTime: LongInt; { free time }
BlankMenuNow, { is the wfcmenu blanked out? }
Abort,
Next, { global Abort AND Next }
RQArea,
FQArea,
MQArea,
VQArea: Boolean;
{$IFDEF WIN32}
procedure Sound(hz: Word; duration: Word);
function Ticks: LongInt;
{$ENDIF}
FUNCTION GetC(c: Byte): STRING;
PROCEDURE ShowColors;
FUNCTION CheckDriveSpace(S,Path: AStr; MinSpace: Integer): Boolean;
FUNCTION StripLeadSpace(S: STRING): STRING;
FUNCTION StripTrailSpace(S: STRING): STRING;
FUNCTION SemiCmd(S: AStr; B: Byte): STRING;
FUNCTION ExistDrive(Drive: Char): Boolean;
PROCEDURE RenameFile(DisplayStr: AStr; OldFileName,NewFileName: AStr; VAR ReNameOk: Boolean);
FUNCTION GetFileSize(FileName: AStr): LongInt;
PROCEDURE GetFileDateTime(CONST FileName: AStr; VAR FileTime: LongInt);
PROCEDURE SetFileDateTime(CONST FileName: AStr; FileTime: LongInt);
FUNCTION PHours(CONST DisplayStr: AStr; LoTime,HiTime: Integer): AStr;
FUNCTION RGSysCfgStr(StrNum: LongInt; PassValue: Boolean): AStr;
FUNCTION RGNoteStr(StrNum: LongInt; PassValue: Boolean): AStr;
FUNCTION RGMainStr(StrNum: LongInt; PassValue: Boolean): AStr;
FUNCTION lRGLNGStr(StrNum: LongInt; PassValue: Boolean): AStr;
PROCEDURE GetPassword(VAR PW: AStr; Len: Byte);
PROCEDURE MakeDir(VAR Path: PathStr; AskMakeDir: Boolean);
PROCEDURE Messages(Msg,MaxRecs: Integer; AreaName: AStr);
PROCEDURE DisplayBuffer(MCIFunction: MCIFunctionType; Data1, Data2:Pointer);
FUNCTION ReadBuffer(FileName: AStr): Boolean;
FUNCTION chinkey: Char;
FUNCTION FormatNumber(L: LongInt): STRING;
FUNCTION ConvertBytes(BytesToConvert: LongInt; OneChar: Boolean): STRING;
FUNCTION ConvertKB(KBToConvert: LongInt; OneChar: Boolean): STRING;
PROCEDURE WriteWFC(c: Char);
FUNCTION AccountBalance: LongInt;
PROCEDURE AdjustBalance(Adjustment: LongInt);
PROCEDURE BackErase(Len: Byte);
FUNCTION UpdateCRC32(CRC: LongInt; VAR Buffer; Len: Word): LongInt;
FUNCTION CRC32(s: AStr): LongInt;
FUNCTION FunctionalMCI(CONST s: AStr; FileName,InternalFileName: AStr): STRING;
FUNCTION MCI(CONST s: STRING): STRING;
FUNCTION Plural(InString: STRING; Number: Byte): STRING;
FUNCTION FormattedTime(TimeUsed: LongInt): STRING;
FUNCTION SearchUser(Uname: Str36; RealNameOK: Boolean): Integer;
PROCEDURE PauseScr(IsCont: Boolean);
PROCEDURE Com_Send_Str(CONST InString: AStr);
PROCEDURE dophoneHangup(ShowIt: Boolean);
PROCEDURE DoTelnetHangUp(ShowIt: Boolean);
PROCEDURE DoPhoneOffHook(ShowIt: Boolean);
PROCEDURE InputPath(CONST DisplayStr: AStr; VAR DirPath: Str40; CreateDir,AllowExit: Boolean; VAR Changed: Boolean);
FUNCTION StripName(InString: STRING): STRING;
PROCEDURE PurgeDir(s: AStr; SubDirs: Boolean);
PROCEDURE DOSANSI(CONST c: Char);
FUNCTION HiMsg: Word;
FUNCTION OnNode(UserNumber: Integer): Byte;
FUNCTION MaxUsers: Integer;
PROCEDURE Kill(CONST FileName: AStr);
PROCEDURE ScreenDump(CONST FileName: AStr);
PROCEDURE ScanInput(VAR s: AStr; CONST Allowed: AStr);
PROCEDURE Com_Flush_Recv;
PROCEDURE Com_Flush_Send;
PROCEDURE Com_Purge_Send;
FUNCTION Com_Carrier: Boolean;
FUNCTION Com_Recv: Char;
FUNCTION Com_IsRecv_Empty: Boolean;
FUNCTION Com_IsSend_Empty: Boolean;
PROCEDURE Com_Send(c: Char);
PROCEDURE Com_Set_Speed(Speed: LongInt);
PROCEDURE Com_DeInstall;
PROCEDURE Com_Install;
PROCEDURE CheckHangup;
PROCEDURE SerialOut(s: STRING);
FUNCTION Empty:Boolean;
PROCEDURE DTR(Status: Boolean);
PROCEDURE BackSpace;
PROCEDURE DoBackSpace(Start,Finish: Byte);
FUNCTION LennMCI(CONST InString: STRING): Integer;
FUNCTION MsgSysOp: Boolean;
FUNCTION FileSysOp: Boolean;
FUNCTION CoSysOp: Boolean;
FUNCTION SysOp: Boolean;
FUNCTION Timer: LongInt;
PROCEDURE TeleConfCheck;
FUNCTION Substitute(Src: STRING; CONST old,New: STRING): STRING;
PROCEDURE NewCompTables;
FUNCTION OkANSI: Boolean;
FUNCTION OkAvatar: Boolean;
FUNCTION OkRIP: Boolean;
FUNCTION OkVT100: Boolean;
FUNCTION NSL: LongInt;
FUNCTION AgeUser(CONST BirthDate: LongInt): Word;
FUNCTION AllCaps(Instring: STRING): STRING;
FUNCTION Caps(Instring: STRING): STRING;
PROCEDURE Update_Screen;
FUNCTION PageLength: Word;
PROCEDURE lStatus_Screen(WhichScreen: Byte; Message: AStr; OneKey: Boolean; VAR Answer: AStr);
FUNCTION CInKey: Char;
FUNCTION CheckPW: Boolean;
FUNCTION StripColor(CONST InString: STRING): STRING;
PROCEDURE sl1(s: AStr);
PROCEDURE SysOpLog(s: AStr);
FUNCTION StrToInt(S: Str11): LongInt;
FUNCTION RealToStr(R: Real; W,D: Byte): STRING;
FUNCTION ValueR(S: AStr): REAL;
PROCEDURE ShellDos(MakeBatch: Boolean; CONST Command: AStr; VAR ResultCode: Integer);
PROCEDURE SysOpShell;
PROCEDURE RedrawForANSI;
PROCEDURE Star(InString: AStr);
FUNCTION GetKey: Word;
PROCEDURE SetC(C: Byte);
PROCEDURE UserColor(Color: Byte);
PROCEDURE Prompt(CONST InString: STRING);
FUNCTION SQOutSp(InString: STRING): STRING;
FUNCTION ExtractDriveNumber(s: AStr): Byte;
FUNCTION PadLeftStr(InString: STRING; MaxLen: Byte): STRING;
FUNCTION PadRightStr(InString: STRING; MaxLen: Byte): STRING;
FUNCTION PadLeftInt(L: LongInt; MaxLen: Byte): STRING;
FUNCTION PadRightInt(L: LongInt; MaxLen: Byte): STRING;
PROCEDURE Print(CONST InString: STRING);
PROCEDURE NL;
PROCEDURE Prt(CONST Instring: STRING);
PROCEDURE MPL(MaxLen: Byte);
FUNCTION CTP(t,b: LongInt): STRING;
PROCEDURE TLeft;
PROCEDURE LoadNode(NodeNumber: Byte);
PROCEDURE Update_Node(NActivityDesc: AStr; SaveVars: Boolean);
FUNCTION MaxNodes: Byte;
FUNCTION MaxChatRec: LongInt;
PROCEDURE SaveNode(NodeNumber: Byte);
PROCEDURE LoadURec(VAR User: UserRecordType; UserNumber: Integer);
PROCEDURE SaveURec(User: UserRecordType; UserNumber:Integer);
FUNCTION MaxIDXRec: Integer;
FUNCTION InKey: Word;
PROCEDURE OutKey(c: Char);
PROCEDURE CLS;
PROCEDURE Wait(b: Boolean);
FUNCTION DisplayARFlags(AR: ARFlagSet; C1,C2: Char): AStr;
PROCEDURE ToggleARFlag(Flag: Char; VAR AR: ARFlagSet; VAR Changed: Boolean);
FUNCTION DisplayACFlags(Flags: FlagSet; C1,C2: Char): AStr;
PROCEDURE ToggleACFlag(Flag: FlagType; VAR Flags: FlagSet);
PROCEDURE ToggleACFlags(Flag: Char; VAR Flags: FlagSet; VAR Changed: Boolean);
PROCEDURE ToggleStatusFlag(Flag: StatusFlagType; VAR SUFlags: StatusFlagSet);
PROCEDURE ToggleStatusFlags(Flag: Char; VAR SUFlags: StatusFlagSet);
FUNCTION TACCH(Flag: Char): FlagType;
PROCEDURE LCmds(Len,c: Byte; c1,c2: AStr);
PROCEDURE LCmds3(Len,c: Byte; c1,c2,c3: AStr);
PROCEDURE InitTrapFile;
FUNCTION AOnOff(b: Boolean; CONST s1,s2: AStr): STRING;
FUNCTION ShowOnOff(b: Boolean): STRING;
FUNCTION ShowYesNo(b: Boolean): STRING;
FUNCTION YN(Len: Byte; DYNY: Boolean): Boolean;
FUNCTION PYNQ(CONST InString: AStr; MaxLen: Byte; DYNY: Boolean): Boolean;
PROCEDURE InputLongIntWC(S: AStr; VAR L: LongInt; InputFlags: InputFlagSet; LowNum,HighNum: LongInt; VAR Changed: Boolean);
PROCEDURE InputLongIntWOC(S: AStr; VAR L: LongInt; InputFlags: InputFlagSet; LowNum,HighNum: LongInt);
PROCEDURE InputWordWC(S: AStr; VAR W: SmallWord; InputFlags: InputFlagSet; LowNum,HighNum: Word; VAR Changed: Boolean);
PROCEDURE InputWordWOC(S: AStr; VAR W: SmallWord; InputFlags: InputFlagSet; LowNum,HighNum: Word);
PROCEDURE InputIntegerWC(S: AStr; VAR I: SmallInt; InputFlags: InputFlagSet; LowNum,HighNum: Integer; VAR Changed: Boolean);
PROCEDURE InputIntegerWOC(S: AStr; VAR I: SmallInt; InputFlags: InputFlagSet; LowNum,HighNum: Integer);
PROCEDURE InputByteWC(S: AStr; VAR B: Byte; InputFlags: InputFlagSet; LowNum,HighNum: Byte; VAR Changed: Boolean);
PROCEDURE InputByteWOC(S: AStr; VAR B: Byte; InputFlags: InputFlagSet; LowNum,HighNum: Byte);
PROCEDURE InputDefault(VAR S: STRING; v: STRING; MaxLen: Byte; InputFlags: InputFlagSet; LineFeed: Boolean);
PROCEDURE InputFormatted(DisplayStr: AStr; VAR InputStr: STRING; v: STRING; Abortable: Boolean);
PROCEDURE InputWN1(DisplayStr: AStr; VAR InputStr: AStr; MaxLen: Byte; InputFlags: InputFlagSet; VAR Changed: Boolean);
PROCEDURE InputWNWC(DisplayStr: AStr; VAR InputStr: AStr; MaxLen: Byte; VAR Changed: Boolean);
PROCEDURE InputMain(VAR s: STRING; MaxLen: Byte; InputFlags: InputFlagSet);
PROCEDURE InputWC(VAR s: STRING; MaxLen: Byte);
PROCEDURE Input(VAR s: STRING; MaxLen: Byte);
PROCEDURE InputL(VAR s: STRING; MaxLen: Byte);
PROCEDURE InputCaps(VAR s: STRING; MaxLen: Byte);
PROCEDURE OneK(VAR C: Char; ValidKeys: AStr; DisplayKey,LineFeed: Boolean);
PROCEDURE OneK1(VAR C: Char; ValidKeys: AStr; DisplayKey,LineFeed: Boolean);
PROCEDURE LOneK(DisplayStr: AStr; VAR C: Char; ValidKeys: AStr; DisplayKey,LineFeed: Boolean);
PROCEDURE Local_Input1(VAR S: STRING; MaxLen: Byte; LowerCase: Boolean);
PROCEDURE Local_Input(VAR S: STRING; MaxLen: Byte);
PROCEDURE Local_InputL(VAR S: STRING; MaxLen: Byte);
PROCEDURE Local_OneK(VAR C: Char; S: STRING);
FUNCTION Centre(InString: AStr): STRING;
PROCEDURE WKey;
PROCEDURE PrintMain(CONST ss: STRING);
PROCEDURE PrintACR(InString: STRING);
PROCEDURE SaveGeneral(X: Boolean);
PROCEDURE pfl(FN: AStr);
PROCEDURE PrintFile(FileName: AStr);
FUNCTION BSlash(InString: AStr; b: Boolean): AStr;
FUNCTION Exist(FileName: AStr): Boolean;
FUNCTION ExistDir(Path: PathStr): Boolean;
PROCEDURE PrintF(FileName: AStr);
PROCEDURE SKey1(VAR c: Char);
FUNCTION VerLine(B: Byte): STRING;
FUNCTION AACS1(User: UserRecordType; UNum: Integer; S: ACString): Boolean;
FUNCTION AACS(s: ACString): Boolean;
FUNCTION DiskKBFree(DrivePath: AStr): LongInt;
FUNCTION IntToStr(L: LongInt): STRING;
IMPLEMENTATION
USES
Common1,
Common2,
Common3,
Common4,
Events,
File0,
File11,
Mail0,
MultNode,
{$IFDEF MSDOS}
SpawnO,
{$ENDIF}
SysOp12,
Vote
{$IFDEF WIN32}
,VPSysLow
,VPUtils
,Windows
{$ENDIF}
;
{$IFDEF WIN32}
procedure Sound(hz: Word; duration: Word);
begin
Windows.Beep(hz, duration);
end;
function Ticks: LongInt;
begin
Ticks := GetTimeMSec div 55;
end;
{$ENDIF}
{$IFDEF MSDOS}
FUNCTION UpdateCRC32(CRC: LongInt; VAR Buffer; Len: Word): LongInt; EXTERNAL;
{$L CRC32.OBJ }
{$ENDIF}
{$IFDEF WIN32}
CONST
CRC_32_TAB : array[0..255] of LongInt = (
$00000000, $77073096, $ee0e612c, $990951ba, $076dc419,
$706af48f, $e963a535, $9e6495a3, $0edb8832, $79dcb8a4,
$e0d5e91e, $97d2d988, $09b64c2b, $7eb17cbd, $e7b82d07,
$90bf1d91, $1db71064, $6ab020f2, $f3b97148, $84be41de,
$1adad47d, $6ddde4eb, $f4d4b551, $83d385c7, $136c9856,
$646ba8c0, $fd62f97a, $8a65c9ec, $14015c4f, $63066cd9,
$fa0f3d63, $8d080df5, $3b6e20c8, $4c69105e, $d56041e4,
$a2677172, $3c03e4d1, $4b04d447, $d20d85fd, $a50ab56b,
$35b5a8fa, $42b2986c, $dbbbc9d6, $acbcf940, $32d86ce3,
$45df5c75, $dcd60dcf, $abd13d59, $26d930ac, $51de003a,
$c8d75180, $bfd06116, $21b4f4b5, $56b3c423, $cfba9599,
$b8bda50f, $2802b89e, $5f058808, $c60cd9b2, $b10be924,
$2f6f7c87, $58684c11, $c1611dab, $b6662d3d, $76dc4190,
$01db7106, $98d220bc, $efd5102a, $71b18589, $06b6b51f,
$9fbfe4a5, $e8b8d433, $7807c9a2, $0f00f934, $9609a88e,
$e10e9818, $7f6a0dbb, $086d3d2d, $91646c97, $e6635c01,
$6b6b51f4, $1c6c6162, $856530d8, $f262004e, $6c0695ed,
$1b01a57b, $8208f4c1, $f50fc457, $65b0d9c6, $12b7e950,
$8bbeb8ea, $fcb9887c, $62dd1ddf, $15da2d49, $8cd37cf3,
$fbd44c65, $4db26158, $3ab551ce, $a3bc0074, $d4bb30e2,
$4adfa541, $3dd895d7, $a4d1c46d, $d3d6f4fb, $4369e96a,
$346ed9fc, $ad678846, $da60b8d0, $44042d73, $33031de5,
$aa0a4c5f, $dd0d7cc9, $5005713c, $270241aa, $be0b1010,
$c90c2086, $5768b525, $206f85b3, $b966d409, $ce61e49f,
$5edef90e, $29d9c998, $b0d09822, $c7d7a8b4, $59b33d17,
$2eb40d81, $b7bd5c3b, $c0ba6cad, $edb88320, $9abfb3b6,
$03b6e20c, $74b1d29a, $ead54739, $9dd277af, $04db2615,
$73dc1683, $e3630b12, $94643b84, $0d6d6a3e, $7a6a5aa8,
$e40ecf0b, $9309ff9d, $0a00ae27, $7d079eb1, $f00f9344,
$8708a3d2, $1e01f268, $6906c2fe, $f762575d, $806567cb,
$196c3671, $6e6b06e7, $fed41b76, $89d32be0, $10da7a5a,
$67dd4acc, $f9b9df6f, $8ebeeff9, $17b7be43, $60b08ed5,
$d6d6a3e8, $a1d1937e, $38d8c2c4, $4fdff252, $d1bb67f1,
$a6bc5767, $3fb506dd, $48b2364b, $d80d2bda, $af0a1b4c,
$36034af6, $41047a60, $df60efc3, $a867df55, $316e8eef,
$4669be79, $cb61b38c, $bc66831a, $256fd2a0, $5268e236,
$cc0c7795, $bb0b4703, $220216b9, $5505262f, $c5ba3bbe,
$b2bd0b28, $2bb45a92, $5cb36a04, $c2d7ffa7, $b5d0cf31,
$2cd99e8b, $5bdeae1d, $9b64c2b0, $ec63f226, $756aa39c,
$026d930a, $9c0906a9, $eb0e363f, $72076785, $05005713,
$95bf4a82, $e2b87a14, $7bb12bae, $0cb61b38, $92d28e9b,
$e5d5be0d, $7cdcefb7, $0bdbdf21, $86d3d2d4, $f1d4e242,
$68ddb3f8, $1fda836e, $81be16cd, $f6b9265b, $6fb077e1,
$18b74777, $88085ae6, $ff0f6a70, $66063bca, $11010b5c,
$8f659eff, $f862ae69, $616bffd3, $166ccf45, $a00ae278,
$d70dd2ee, $4e048354, $3903b3c2, $a7672661, $d06016f7,
$4969474d, $3e6e77db, $aed16a4a, $d9d65adc, $40df0b66,
$37d83bf0, $a9bcae53, $debb9ec5, $47b2cf7f, $30b5ffe9,
$bdbdf21c, $cabac28a, $53b39330, $24b4a3a6, $bad03605,
$cdd70693, $54de5729, $23d967bf, $b3667a2e, $c4614ab8,
$5d681b02, $2a6f2b94, $b40bbe37, $c30c8ea1, $5a05df1b,
$2d02ef8d);
FUNCTION UpdateCRC32(CRC: LongInt; VAR Buffer; Len: Word): LongInt;
VAR
i: Integer;
Octet: ^Byte;
BEGIN
Octet := @buffer;
for i := 1 to Len do
begin
CRC := CRC_32_TAB[Byte(Crc XOR LongInt(Octet^))] XOR ((Crc SHR 8) AND $00FFFFFF);
Inc(Octet);
end;
UpdateCRC32 := CRC;
END;
{$ENDIF}
FUNCTION CheckPW: Boolean;
BEGIN
CheckPW := Common1.CheckPW;
END;
PROCEDURE NewCompTables;
BEGIN
Common1.NewCompTables;
END;
PROCEDURE Wait(B: Boolean);
BEGIN
Common1.Wait(B);
END;
PROCEDURE InitTrapFile;
BEGIN
Common1.InitTrapFile;
END;
PROCEDURE Local_Input1(VAR S: STRING; MaxLen: Byte; LowerCase: Boolean);
BEGIN
Common1.Local_Input1(S,MaxLen,LowerCase);
END;
PROCEDURE Local_Input(VAR S: STRING; MaxLen: Byte);
BEGIN
Common1.Local_Input(S,MaxLen);
END;
PROCEDURE Local_InputL(VAR S: STRING; MaxLen: Byte);
BEGIN
Common1.Local_InputL(S,MaxLen);
END;
PROCEDURE Local_OneK(VAR C: Char; S: STRING);
BEGIN
Common1.Local_OneK(C,S);
END;
PROCEDURE SysOpShell;
BEGIN
Common1.SysOpShell;
END;
PROCEDURE RedrawForANSI;
BEGIN
Common1.RedrawForANSI;
END;
PROCEDURE SKey1(VAR C: Char);
BEGIN
Common2.SKey1(C);
END;
PROCEDURE SaveGeneral(X: Boolean);
BEGIN
Common2.SaveGeneral(X);
END;
PROCEDURE Update_Screen;
BEGIN
Common2.Update_Screen;
END;
PROCEDURE lStatus_Screen(WhichScreen: Byte; Message: AStr; OneKey: Boolean; VAR Answer:AStr);
BEGIN
Common2.lStatus_Screen(WhichScreen,Message,OneKey,Answer);
END;
PROCEDURE TLeft;
BEGIN
Common2.TLeft;
END;
PROCEDURE InputLongIntWC(S: AStr; VAR L: LongInt; InputFlags: InputFlagSet; LowNum,HighNum: LongInt; VAR Changed: Boolean);
BEGIN
Common3.InputLongIntWC(S,L,InputFlags,LowNum,HighNum,Changed);
END;
PROCEDURE InputLongIntWOC(S: AStr; VAR L: LongInt; InputFlags: InputFlagSet; LowNum,HighNum: LongInt);
BEGIN
Common3.InputLongIntWOC(S,L,InputFlags,LowNum,HighNum);
END;
PROCEDURE InputWordWC(S: AStr; VAR W: SmallWord; InputFlags: InputFlagSet; LowNum,HighNum: Word; VAR Changed: Boolean);
BEGIN
Common3.InputWordWC(S,W,InputFlags,LowNum,HighNum,Changed);
END;
PROCEDURE InputWordWOC(S: AStr; VAR W: SmallWord; InputFlags: InputFlagSet; LowNum,HighNum: Word);
BEGIN
Common3.InputWordWOC(S,W,InputFlags,LowNum,HighNum);
END;
PROCEDURE InputIntegerWC(S: AStr; VAR I: SmallInt; InputFlags: InputFlagSet; LowNum,HighNum: Integer; VAR Changed: Boolean);
BEGIN
Common3.InputIntegerWC(S,I,InputFlags,LowNum,HighNum,Changed);
END;
PROCEDURE InputIntegerWOC(S: AStr; VAR I: SmallInt; InputFlags: InputFlagSet; LowNum,HighNum: Integer);
BEGIN
Common3.InputIntegerWOC(S,I,Inputflags,LowNum,HighNum);
END;
PROCEDURE InputByteWC(S: AStr; VAR B: Byte; InputFlags: InputFlagSet; LowNum,HighNum: Byte; VAR Changed: Boolean);
BEGIN
Common3.InputByteWC(S,B,InputFlags,LowNum,HighNum,Changed);
END;
PROCEDURE InputByteWOC(S: AStr; VAR B: Byte; InputFlags: InputFlagSet; LowNum,HighNum: Byte);
BEGIN
Common3.InputByteWOC(S,B,InputFlags,LowNum,HighNum)
END;
PROCEDURE InputDefault(VAR S: STRING; v: STRING; MaxLen: Byte; InputFlags: InputFlagSet; LineFeed: Boolean);
BEGIN
Common3.InputDefault(S,v,MaxLen,InputFlags,LineFeed);
END;
PROCEDURE InputFormatted(DisplayStr: AStr; VAR InputStr: STRING; v: STRING; Abortable: Boolean);
BEGIN
Common3.InputFormatted(DisplayStr,InputStr,v,Abortable);
END;
PROCEDURE InputWN1(DisplayStr: AStr; VAR InputStr: AStr; MaxLen: Byte; InputFlags: InputFlagSet; VAR Changed: Boolean);
BEGIN
Common3.InputWN1(DisplayStr,InputStr,MaxLen,InputFlags,Changed);
END;
PROCEDURE InputWNWC(DisplayStr: AStr; VAR InputStr: AStr; MaxLen: Byte; VAR Changed: Boolean);
BEGIN
Common3.InputWNWC(DisplayStr,InputStr,MaxLen,Changed);
END;
PROCEDURE InputMain(VAR s: STRING; MaxLen: Byte; InputFlags: InputFlagSet);
BEGIN
Common3.InputMain(s,MaxLen,InputFlags);
END;
PROCEDURE InputWC(VAR s: STRING; MaxLen: Byte);
BEGIN
Common3.InputWC(s,MaxLen);
END;
PROCEDURE Input(VAR s: STRING; MaxLen: Byte);
BEGIN
Common3.Input(s,MaxLen);
END;
PROCEDURE InputL(VAR s: STRING; MaxLen: Byte);
BEGIN
Common3.InputL(s,MaxLen);
END;
PROCEDURE InputCaps(VAR s: STRING; MaxLen: Byte);
BEGIN
Common3.InputCaps(s,MaxLen);
END;
PROCEDURE Com_Flush_Recv;
BEGIN
Common4.Com_Flush_Recv;
END;
PROCEDURE Com_Flush_Send;
BEGIN
Common4.Com_Flush_Send;
END;
PROCEDURE Com_Purge_Send;
BEGIN
Common4.Com_Purge_Send;
END;
FUNCTION Com_Carrier: Boolean;
BEGIN
Com_Carrier := Common4.Com_Carrier;
END;
FUNCTION Com_Recv: Char;
BEGIN
Com_Recv := Common4.Com_Recv;
END;
FUNCTION Com_IsRecv_Empty: Boolean;
BEGIN
Com_IsRecv_Empty := Common4.Com_IsRecv_Empty;
END;
FUNCTION Com_IsSend_Empty: Boolean;
BEGIN
Com_IsSend_Empty := Common4.Com_IsSend_Empty;
END;
PROCEDURE Com_Send(c: Char);
BEGIN
Common4.Com_Send(c);
END;
PROCEDURE Com_Set_Speed(Speed: LongInt);
BEGIN
Common4.Com_Set_Speed(Speed);
END;
PROCEDURE Com_DeInstall;
BEGIN
Common4.Com_DeInstall;
END;
PROCEDURE Com_Install;
BEGIN
Common4.Com_Install;
END;
PROCEDURE CheckHangup;
BEGIN
Common4.checkhangup;
END;
PROCEDURE SerialOut(s: STRING);
BEGIN
Common4.SerialOut(s);
END;
FUNCTION Empty: Boolean; BEGIN
Empty := Common4.Empty;
END;
PROCEDURE DTR(Status: Boolean);
BEGIN
Common4.DTR(Status);
END;
PROCEDURE ShowColors;
VAR
Counter: Byte;
BEGIN
FOR Counter := 1 TO 10 DO
BEGIN
SetC(Scheme.Color[Counter]);
Prompt(IntToStr(Counter - 1));
SetC(7);
Prompt(' ');
END;
NL;
END;
FUNCTION CheckDriveSpace(S,Path: AStr; MinSpace: Integer): Boolean;
VAR
Drive: Char;
MinSpaceOk: Boolean;
BEGIN
MinSpaceOk := TRUE;
IF (DiskKBFree(Path) <= MinSpace) THEN
BEGIN
NL;
Star('Insufficient disk space.');
Drive := Chr(ExtractDriveNumber(Path) + 64);
IF (Drive = '@') THEN
SysOpLog('^8--->^3 '+S+' failure: Main BBS drive full.')
ELSE
SysOpLog('^8--->^3 '+S+' failure: '+Drive+' Drive full.');
MinSpaceOk := FALSE;
END;
CheckDriveSpace := MinSpaceOk;
END;
FUNCTION StripLeadSpace(S: STRING): STRING;
BEGIN
WHILE (S[1] = ' ') DO
Delete(S,1,1);
StripLeadSpace := S;
END;
FUNCTION StripTrailSpace(S: STRING): STRING;
BEGIN
WHILE (S[1] = ' ') DO
Delete(S,1,1);
StripTrailSpace := S;
END;
FUNCTION SemiCmd(S: AStr; B: Byte): STRING;
VAR
i,
p: Byte;
BEGIN
i := 1;
WHILE (i < B) AND (s <> '') DO
BEGIN
p := Pos(';',s);
IF (p <> 0) THEN
s := Copy(s,(p + 1),(Length(s) - p))
ELSE
s := '';
Inc(i);
END;
WHILE (Pos(';',s) <> 0) DO
s := Copy(s,1,(Pos(';',s) - 1));
SemiCmd := s;
END;
FUNCTION ExistDrive(Drive: Char): Boolean;
VAR
Found: Boolean;
BEGIN
ChDir(Drive+':');
IF (IOResult <> 0) THEN
Found := FALSE
ELSE
BEGIN
ChDir(StartDir);
Found := TRUE;
END;
ExistDrive := Found;
END;
PROCEDURE RenameFile(DisplayStr: AStr; OldFileName,NewFileName: AStr; VAR RenameOk: Boolean);
VAR
F: FILE;
BEGIN
Print(DisplayStr);
IF (NOT Exist(OldFileName)) THEN
BEGIN
NL;
Print('"'+OldFileName+'" does not exist, can not rename file.');
ReNameOk := FALSE;
END
ELSE IF (Exist(NewFileName)) THEN
BEGIN
NL;
Print('"'+NewFileName+'" exists, file can not be renamed to "'+OldFileName+'".');
ReNameOk := FALSE;
END
ELSE
BEGIN
Assign(F,OldFileName);
ReName(F,NewFileName);
LastError := IOResult;
IF (LastError <> 0) THEN
BEGIN
NL;
Print('Error renaming file '+OldFileName+'.');
ReNameOK := FALSE;
END;
END;
END;
FUNCTION GetFileSize(FileName: AStr): LongInt;
VAR
DirInfo1: SearchRec;
FSize: LongInt;
BEGIN
FindFirst(FileName,AnyFile - Directory - VolumeID - DOS.Hidden - SysFile,DirInfo1);
IF (DosError <> 0) THEN
FSize := -1
ELSE
FSize := DirInfo1.Size;
GetFileSize := FSize;
END;
PROCEDURE GetFileDateTime(CONST FileName: AStr; VAR FileTime: LongInt);
VAR
F: FILE;
BEGIN
FileTime := 0;
IF Exist(SQOutSp(FileName)) THEN
BEGIN
Assign(F,SQOutSp(FileName));
Reset(F);
GetFTime(F,FileTime);
Close(F);
LastError := IOResult;
END;
END;
PROCEDURE SetFileDateTime(CONST FileName: AStr; FileTime: LongInt);
VAR
F: FILE;
BEGIN
IF Exist(SQOutSp(FileName)) THEN
BEGIN
Assign(F,SQOutSp(FileName));
Reset(F);
SetFTime(F,FileTime);
Close(F);
LastError := IOResult;
END;
END;
FUNCTION PHours(CONST DisplayStr: AStr; LoTime,HiTime: Integer): AStr;
BEGIN
IF (LoTime <> HiTime) THEN
PHours := ZeroPad(IntToStr(LoTime DIV 60))+':'+ZeroPad(IntToStr(LoTime MOD 60))+'....'+
ZeroPad(IntToStr(HiTime DIV 60))+':'+ZeroPad(IntToStr(HiTime MOD 60))
ELSE
PHours := DisplayStr;
END;
FUNCTION RGSysCfgStr(StrNum: LongInt; PassValue: Boolean): AStr;
VAR
StrPointerFile: FILE OF StrPointerRec;
StrPointer: StrPointerRec;
RGStrFile: FILE;
S: STRING;
TotLoad: LongInt;
BEGIN
Assign(StrPointerFile,General.LMultPath+'RGSCFGPR.DAT');
Reset(StrPointerFile);
Seek(StrPointerFile,StrNum);
Read(StrPointerFile,StrPointer);
Close(StrPointerFile);
LastError := IOResult;
TotLoad := 0;
Assign(RGStrFile,General.LMultPath+'RGSCFGTX.DAT');
Reset(RGStrFile,1);
Seek(RGStrFile,(StrPointer.Pointer - 1));
REPEAT
BlockRead(RGStrFile,S[0],1);
BlockRead(RGStrFile,S[1],Ord(S[0]));
Inc(TotLoad,(Length(S) + 1));
IF (PassValue) THEN
BEGIN
IF (S[Length(s)] = '@') THEN
Dec(S[0]);
END
ELSE
BEGIN
IF (S[Length(S)] = '@') THEN
BEGIN
Dec(S[0]);
Prt(S);
END
ELSE
PrintACR(S);
END;
UNTIL (TotLoad >= StrPointer.TextSize) OR (Abort) OR (HangUp);
Close(RGStrFile);
LastError := IOResult;
RGSysCfgStr := S;
END;
FUNCTION RGNoteStr(StrNum: LongInt; PassValue: Boolean): AStr;
VAR
StrPointerFile: FILE OF StrPointerRec;
StrPointer: StrPointerRec;
RGStrFile: FILE;
S: STRING;
TotLoad: LongInt;
BEGIN
Assign(StrPointerFile,General.LMultPath+'RGNOTEPR.DAT');
Reset(StrPointerFile);
Seek(StrPointerFile,StrNum);
Read(StrPointerFile,StrPointer);
Close(StrPointerFile);
LastError := IOResult;
TotLoad := 0;
Assign(RGStrFile,General.LMultPath+'RGNOTETX.DAT');
Reset(RGStrFile,1);
Seek(RGStrFile,(StrPointer.Pointer - 1));
REPEAT
BlockRead(RGStrFile,S[0],1);
BlockRead(RGStrFile,S[1],Ord(S[0]));
Inc(TotLoad,(Length(S) + 1));
IF (PassValue) THEN
BEGIN
IF (S[Length(s)] = '@') THEN
Dec(S[0]);
END
ELSE
BEGIN
IF (S[Length(S)] = '@') THEN
BEGIN
Dec(S[0]);
Prt(S);
END
ELSE
PrintACR(S);
END;
UNTIL (TotLoad >= StrPointer.TextSize) OR (Abort) OR (HangUp);
Close(RGStrFile);
LastError := IOResult;
RGNoteStr := S;
END;
FUNCTION RGMainStr(StrNum: LongInt; PassValue: Boolean): AStr;
VAR
StrPointerFile: FILE OF StrPointerRec;
StrPointer: StrPointerRec;
RGStrFile: FILE;
S: STRING;
TotLoad: LongInt;
BEGIN
Assign(StrPointerFile,General.LMultPath+'RGMAINPR.DAT');
Reset(StrPointerFile);
Seek(StrPointerFile,StrNum);
Read(StrPointerFile,StrPointer);
Close(StrPointerFile);
LastError := IOResult;
TotLoad := 0;
Assign(RGStrFile,General.LMultPath+'RGMAINTX.DAT');
Reset(RGStrFile,1);
Seek(RGStrFile,(StrPointer.Pointer - 1));
REPEAT
BlockRead(RGStrFile,S[0],1);
BlockRead(RGStrFile,S[1],Ord(S[0]));
Inc(TotLoad,(Length(S) + 1));
IF (PassValue) THEN
BEGIN
IF (S[Length(s)] = '@') THEN
Dec(S[0]);
END
ELSE
BEGIN
IF (S[Length(S)] = '@') THEN
BEGIN
Dec(S[0]);
Prt(S);
END
ELSE
PrintACR(S);
END;
UNTIL (TotLoad >= StrPointer.TextSize) OR (Abort) OR (HangUp);
Close(RGStrFile);
LastError := IOResult;
RGMainStr := S;
END;
FUNCTION lRGLngStr(StrNum: LongInt; PassValue: Boolean): AStr;
VAR
StrPointerFile: FILE OF StrPointerRec;
StrPointer: StrPointerRec;
RGStrFile: FILE;
S: STRING;
TotLoad: LongInt;
BEGIN
Assign(StrPointerFile,General.LMultPath+'RGLNGPR.DAT');
Reset(StrPointerFile);
Seek(StrPointerFile,StrNum);
Read(StrPointerFile,StrPointer);
Close(StrPointerFile);
LastError := IOResult;
TotLoad := 0;
Assign(RGStrFile,General.LMultPath+'RGLNGTX.DAT');
Reset(RGStrFile,1);
Seek(RGStrFile,(StrPointer.Pointer - 1));
REPEAT
BlockRead(RGStrFile,S[0],1);
BlockRead(RGStrFile,S[1],Ord(S[0]));
Inc(TotLoad,(Length(S) + 1));
IF (PassValue) THEN
BEGIN
IF (S[Length(s)] = '@') THEN
Dec(S[0]);
END
ELSE
BEGIN
IF (S[Length(S)] = '@') THEN
BEGIN
Dec(S[0]);
Prt(S);
END
ELSE
PrintACR(S);
END;
UNTIL (TotLoad >= StrPointer.TextSize) OR (Abort) OR (HangUp);
Close(RGStrFile);
LastError := IOResult;
lRGLNGStr := S;
END;
PROCEDURE GetPassword(VAR PW: AStr; Len: Byte);
BEGIN
PW := '';
Echo := FALSE;
Input(PW,Len);
Echo := TRUE;
END;
PROCEDURE MakeDir(VAR Path: PathStr; AskMakeDir: Boolean);
VAR
CurDir: PathStr;
Counter: Byte;
BEGIN
IF (Path = '') THEN
BEGIN
NL;
Print('^7A valid path must be specified!^1');
END
ELSE IF (NOT (Path[1] IN ['A'..'Z'])) OR (Length(Path) < 3) OR
(NOT (Path[2] = ':')) OR (NOT (Path[3] = '\')) THEN
BEGIN
NL;
Print('^7Invalid drive specification: "'+Path+'"^1');
END
ELSE
BEGIN
GetDir(0,CurDir);
ChDir(Path[1]+':');
IF (IOResult <> 0) THEN
BEGIN
NL;
Print('^7Drive does not exist: "'+Path[1]+'"^1');
END
ELSE
ChDir(CurDir);
END;
Path := BSlash(Path,TRUE);
IF (Length(Path) > 3) AND (NOT ExistDir(Path)) THEN
BEGIN
NL;
IF (NOT AskMakeDir) OR PYNQ('Directory does not exist, create it? ',0,FALSE) THEN
BEGIN
Counter := 2;
WHILE (Counter <= Length(Path)) DO
BEGIN
IF (Path[Counter] = '\') THEN
BEGIN
IF (Path[Counter - 1] <> ':') THEN
BEGIN
IF (NOT ExistDir(Copy(Path,1,(Counter - 1)))) THEN
BEGIN
MkDir(Copy(Path,1,(Counter - 1)));
LastError := IOResult;
IF (LastError <> 0) THEN
BEGIN
NL;
Print('^7Error creating directory!^1');
SysOpLog('^7Error creating directory: '+Copy(Path,1,(Counter - 1)));
PauseScr(FALSE);
END;
END;
END;
END;
Inc(Counter);
END;
END;
END;
END;
PROCEDURE Messages(Msg,MaxRecs: Integer; AreaName: AStr);
VAR
MsgStr: AStr;
BEGIN
MsgStr := '';
NL;
CASE Msg OF
1 : MsgStr := '^7Invalid record number!^1';
2 : MsgStr := '^7You are at the first valid record!^1';
3 : MsgStr := '^7You are at the last valid record!^1';
4 : MsgStr := '^7No '+AreaName+' exist!^1';
5 : MsgStr := '^7No more then '+IntToStr(MaxRecs)+' '+AreaName+' can exist!^1';
6 : MsgStr := '^7No '+AreaName+' to position!^1';
7 : MsgStr := '^7Invalid drive!^1';
8 : MsgStr := '^7Invalid record number order!^1';
END;
PrintACR('^1'+MsgStr);
PauseScr(FALSE);
END;
FUNCTION ReadBuffer(FileName: AStr): Boolean;
VAR
BufferFile: FILE;
MCIBufferSize,
NumRead: Integer;
BEGIN
IF (MCIBuffer = NIL) THEN
New(MCIBuffer);
ReadBuffer := FALSE;
IF ((Pos('\',FileName) = 0) AND (Pos(':', FileName) = 0)) THEN
FileName := General.MiscPath+FileName;
IF (Pos('.',FileName) = 0) THEN
BEGIN
IF (OkRIP) AND Exist(FileName+'.RIP') THEN
FileName := FileName+'.RIP'
ELSE IF (OkAvatar) AND Exist(FileName+'.AVT') THEN
FileName := FileName+'.AVT'
ELSE IF (OkANSI) AND Exist(FileName+'.ANS') THEN
FileName := FileName+'.ANS'
ELSE IF (Exist(FileName+'.ASC')) THEN
FileName := FileName+'.ASC';
END;
IF (NOT Exist(FileName)) THEN
Exit;
Assign(BufferFile,FileName);
Reset(BufferFile,1);
IF (IOResult <> 0) THEN
Exit;
IF (FileSize(BufferFile) < MaxConfigurable) THEN
MCIBufferSize := FileSize(BufferFile)
ELSE
MCIBufferSize := MaxConfigurable;
FillChar(MCIBuffer^,SizeOf(MCIBuffer^),0);
BlockRead(BufferFile,MCIBuffer^,MCIBufferSize,NumRead);
IF (NumRead <> MCIBufferSize) THEN
Exit;
Close(BufferFile);
ReadBuffer := TRUE;
END;
PROCEDURE DisplayBuffer(MCIFunction: MCIFunctionType; Data1,Data2: Pointer);
VAR
TempStr: STRING;
cs: AStr;
Justify: Byte; {0=Right, 1=Left, 2=Center}
Counter,
X2: Integer;
BEGIN
Counter := 1;
WHILE (Counter <= MaxConfigurable) AND (MCIBuffer^[Counter] <> #0) DO
BEGIN
TempStr := '';
WHILE (Counter <= MaxConfigurable) AND (MCIBuffer^[Counter] <> #13) DO
IF (MCIBuffer^[Counter] = '~') AND (Counter + 2 <= MaxConfigurable) THEN
BEGIN
cs := MCIFunction(MCIBuffer^[Counter + 1] + MCIBuffer^[Counter + 2],Data1,Data2);
IF (cs = MCIBuffer^[Counter + 1] + MCIBuffer^[Counter + 2]) THEN
BEGIN
TempStr := TempStr + '~';
Inc(Counter);
Continue;
END;
Inc(Counter,3);
IF ((Counter + 1) <= MaxConfigurable) AND (MCIBuffer^[Counter] IN ['#','{','}']) THEN
BEGIN
IF (MCIBuffer^[Counter] = '}') THEN
Justify := 0
ELSE IF (MCIBuffer^[Counter] = '{') THEN
Justify := 1
ELSE
Justify := 2;
IF (MCIBuffer^[Counter + 1] IN ['0'..'9']) THEN
BEGIN
X2 := Ord(MCIBuffer^[Counter + 1]) - 48;
Inc(Counter, 2);
IF (MCIBuffer^[Counter] IN ['0'..'9']) THEN
BEGIN
X2 := X2 * 10 + Ord(MCIBuffer^[Counter]) - 48;
Inc(Counter,1);
END;
IF (X2 > 0) THEN
CASE Justify OF
0 : cs := PadRightStr(cs,X2);
1 : cs := PadLeftStr(cs,X2);
2 : WHILE (Length(cs) < X2) DO
BEGIN
cs := ' ' + cs;
IF (Length(cs) < X2) THEN
cs := cs + ' ';
END;
END;
END;
END;
IF ((Length(cs) + Length(TempStr)) <= 255) THEN
BEGIN
Move(cs[1],TempStr[Length(TempStr)+1],Length(cs));
Inc(TempStr[0],Length(cs));
END
ELSE
IF (Length(TempStr) < 255) THEN
BEGIN
Move(cs[1],TempStr[Length(TempStr) + 1],(255 - Length(TempStr)));
TempStr[0] := #255;
END;
END
ELSE
BEGIN
Inc(TempStr[0]);
TempStr[Length(TempStr)] := MCIBuffer^[Counter];
Inc(Counter);
END;
IF (Counter <= MaxConfigurable) AND (MCIBuffer^[Counter] = #13) THEN
Inc(Counter,2);
CROff := TRUE;
PrintACR(TempStr);
END;
END;
FUNCTION Chinkey: Char;
VAR
C: Char;
BEGIN
C := #0;
Chinkey := #0;
IF (KeyPressed) THEN
BEGIN
C := ReadKey;
IF (NOT WColor) THEN
UserColor(General.SysOpColor);
WColor := TRUE;
IF (C = #0) THEN
IF (KeyPressed) THEN
BEGIN
C := ReadKey;
SKey1(C);
IF (C = #31) OR (C = #46) THEN
C := #1
ELSE IF (Buf <> '') THEN
BEGIN
C := Buf[1];
Buf := Copy(Buf,2,(Length(Buf) - 1));
END
ELSE
C := #0
END;
Chinkey := C;
END
ELSE IF ((NOT Com_IsRecv_Empty) AND (InCom)) THEN
BEGIN
C := CInKey;
IF (WColor) THEN
UserColor(General.UserColor);
WColor := FALSE;
Chinkey := C;
END;
END;
FUNCTION FormatNumber(L: LongInt): STRING;
VAR
S: STRING;
StrLen,
Counter: Byte;
BEGIN
S := '';
Str(L,S);
StrLen := Length(S);
Counter := 0;
WHILE (StrLen > 1) DO
BEGIN
Inc(Counter);
IF (Counter = 3) THEN
BEGIN
Insert(',',S,StrLen);
Counter := 0;
END;
Dec(StrLen);
END;
FormatNumber := S;
END;
FUNCTION ConvertBytes(BytesToConvert: LongInt; OneChar: Boolean): STRING;
CONST
InByte = 1;
InKilo = 1024;
InMega = 1048576;
InGiga = 1073741824;
VAR
InSize,
InMod: LongInt;
InTypes: Str5;
BEGIN
InMod := 0;
InTypes := '';
IF (BytesToConvert < 0) THEN
Exit;
IF (BytesToConvert < InKilo) THEN {Bytes Convertion}
BEGIN
InSize := BytesToConvert;
InTypes := 'Bytes';
END
ELSE IF (BytesToConvert < InMega) THEN {Kilo Convertion}
BEGIN
InSize := (BytesToConvert DIV InKilo);
InMod := Trunc(((BytesToConvert Mod InKilo) / InKilo) * 10.0);
InTypes := 'KB';
END
ELSE IF (BytesToConvert < InGiga) THEN {Mega Convertion}
BEGIN
InSize := (BytesToConvert DIV InMega);
InMod := Trunc(((BytesToConvert Mod InMega) / InMega) * 10.0);
InTypes := 'MB';
END
ELSE IF ((BytesToConvert - 1) > InGiga) THEN {GigaByte Conversion}
BEGIN
InSize := (BytesToConvert DIV InGiga);
InMod := Trunc(((BytesToConvert Mod InGiga) / InGiga) * 10.0);
InTypes := 'GB';
END;
IF (InMod = 0) THEN
ConvertBytes := AOnOff(OneChar,IntToStr(InSize),FormatNumber(InSize)+' ')
+AOnOff(OneChar,Char(Ord(InTypes[1]) + 32),InTypes)
ELSE
ConvertBytes := AOnOff(OneChar,IntToStr(InSize),FormatNumber(InSize))+'.'
+AOnOff(OneChar,IntToStr(InMod),IntToStr(InMod)+' ')
+AOnOff(OneChar,Char(Ord(InTypes[1]) + 32),InTypes);
END;
FUNCTION ConvertKB(KBToConvert: LongInt; OneChar: Boolean): STRING;
CONST
InKilo = 1;
InMega = 1024;
InGiga = 1048576;
InTera = 1073741824;
VAR
InSize,
InMod: LongInt;
InTypes: Str5;
BEGIN
InMod := 0;
InTypes := '';
IF (KBToConvert < 0) THEN
Exit;
IF (KBToConvert < InMega) THEN {KILO Convertion}
BEGIN
InSize := KBToConvert;
InTypes := 'KB';
END
ELSE IF (KBToConvert < InGiga) THEN {MEGA Convertion}
BEGIN
InSize := (KBToConvert DIV InMega);
InMod := Trunc(((KBToConvert Mod InMega) / InMega) * 10.0);
InTypes := 'MB';
END
ELSE IF (KBToConvert < InTera) THEN {Giga Convertion}
BEGIN
InSize := (KBToConvert DIV InGiga);
InMod := Trunc(((KBToConvert Mod InGiga) / InGiga) * 10.0);
InTypes := 'GB';
END
ELSE IF ((KBToConvert - 1) > InTera) THEN {TeraByte Conversion}
BEGIN
InSize := (KBToConvert DIV InTera);
InMod := Trunc(((KBToConvert Mod InTera) / InTera) * 10.0);
InTypes := 'TB';
END;
IF (InMod = 0) THEN
ConvertKB := AOnOff(OneChar,IntToStr(InSize),FormatNumber(InSize)+' ')
+AOnOff(OneChar,Char(Ord(InTypes[1]) + 32),InTypes)
ELSE
ConvertKB := AOnOff(OneChar,IntToStr(InSize),FormatNumber(InSize))+'.'
+AOnOff(OneChar,IntToStr(InMod),IntToStr(InMod)+' ')
+AOnOff(OneChar,Char(Ord(InTypes[1]) + 32),InTypes);
END;
PROCEDURE WriteWFC(c: Char);
VAR
LastAttr: Byte;
BEGIN
IF (BlankMenuNow) THEN
Exit;
Window(23,11,78,15);
GotoXY(LastWFCX,LastWFCY);
LastAttr := TextAttr;
TextAttr := 7;
Write(c);
TextAttr := LastAttr;
LastWFCX := WhereX;
LastWFCY := WhereY;
Window(1,1,MaxDisplayCols,MaxDisplayRows);
END;
FUNCTION AccountBalance: LongInt;
BEGIN
AccountBalance := (ThisUser.lCredit - ThisUser.Debit);
END;
PROCEDURE AdjustBalance(Adjustment: LongInt);
BEGIN
IF (Adjustment > 0) THEN
Inc(ThisUser.Debit,Adjustment) { Add TO debits }
ELSE
Dec(ThisUser.lCredit,Adjustment); { Add TO credits }
END;
FUNCTION CRC32(S: AStr): LongInt;
BEGIN
CRC32 := NOT (UpdateCRC32($FFFFFFFF,S[1],Length(S)));
END;
PROCEDURE Kill(CONST FileName: AStr);
VAR
F: FILE;
BEGIN
Assign(F,FileName);
Erase(F);
LastError := IOResult;
END;
PROCEDURE BackSpace;
BEGIN
IF (OutCom) THEN
SerialOut(^H' '^H);
IF (WantOut) THEN
Write(^H' '^H);
END;
PROCEDURE DoBackSpace(Start,Finish: Byte);
VAR
Counter: Byte;
BEGIN
FOR Counter := Start TO Finish DO
BEGIN
IF (OutCom) THEN
SerialOut(^H' '^H);
IF (WantOut) THEN
Write(^H' '^H);
END;
END;
FUNCTION Substitute(Src: STRING; CONST old,New: STRING): STRING;
VAR
p,
Diff,
LastP: Integer;
BEGIN
IF (old <> New) THEN
BEGIN
LastP := 0;
Diff := Length(New) - Length(old);
REPEAT
p := Pos(old,Copy(Src,LastP,255));
IF (p > 0) THEN
BEGIN
IF (Diff <> 0) THEN
BEGIN
Move(Src[p + Length(old)],Src[p + Length(New)],(Length(Src) - p));
Inc(Src[0],Diff);
END;
Move(New[1],Src[p],Length(New));
LastP := p + Length(New);
END;
UNTIL (p = 0);
END;
Substitute := Src;
END;
PROCEDURE DOSANSI(CONST c:Char);
VAR
i:Word;
label Command;
BEGIN
IF (c = #27) AND (NextState IN [Waiting..In_Param]) THEN
BEGIN
NextState := Bracket;
Exit;
END;
IF (c = ^V) AND (NextState = Waiting) THEN
BEGIN
NextState := GetAvCmd;
Exit;
END;
IF (c = ^y) AND (NextState = Waiting) THEN
BEGIN
NextState := GetAvRLE1;
Exit;
END;
CASE NextState OF
Waiting : IF (c = #9) THEN
GotoXY((WhereX + 8),WhereY)
ELSE
Write(c);
GetAvRLE1:
BEGIN
ParamArr[1] := Ord(c);
NextState := GetAvRLE2;
END;
GetAvRLE2:
BEGIN
FOR i := 1 TO Ord(c) DO
Write(Chr(ParamArr[1]));
NextState := Waiting;
END;
GetAvAttr:
BEGIN
TextAttr := Ord(c) AND $7f;
NextState := Waiting;
END;
GetAvY:
BEGIN
ParamArr[1] := Ord(c);
NextState := GetAvX;
END;
GetAvX:
BEGIN
GotoXY(Ord(c),ParamArr[1]);
NextState := Waiting;
END;
GetAvCmd: CASE c OF
^A : NextState := GetAvAttr;
^B : BEGIN
TextAttr := TextAttr OR $80;
NextState := Waiting;
END;
^C : BEGIN
GotoXY(WhereX,(WhereY - 1));
NextState := Waiting;
END;
^d : BEGIN
GotoXY(WhereX,(WhereY + 1));
NextState := Waiting;
END;
^E : BEGIN
GotoXY((WhereX - 1),WhereY);
NextState := Waiting;
END;
^F :
BEGIN
GotoXY((WhereX + 1),WhereY);
NextState := Waiting;
END;
^G :
BEGIN
ClrEOL;
NextState := Waiting;
END;
^H : NextState := GetAvY;
ELSE
NextState := Waiting;
END;
Bracket :
BEGIN
IF c <> '[' THEN
BEGIN
NextState := Waiting;
Write(c);
END
ELSE
BEGIN
Params := 1;
FillChar(ParamArr,5,0);
NextState := Get_Args;
END;
END;
Get_Args,Get_Param,Eat_Semi :
BEGIN
IF (NextState = Eat_Semi) AND (c = ';') THEN
BEGIN
IF (Params < 5) THEN
Inc(Params);
NextState := Get_Param;
Exit;
END;
CASE c OF
'0'..'9' :
BEGIN
ParamArr[Params] := Ord(c) - 48;
NextState := In_Param;
END;
';' :
BEGIN
IF (Params < 5) THEN
Inc(Params);
NextState := Get_Param;
END;
ELSE
goto Command;
END {CASE c} ;
END;
In_Param : { last Char was a digit }
BEGIN
{ looking FOR more digits, a semicolon, OR a command Char }
CASE c OF
'0'..'9' :
BEGIN
ParamArr[Params] := ParamArr[Params] * 10 + Ord(c) - 48;
NextState := In_Param;
Exit;
END;
';' :
BEGIN
IF (Params < 5) THEN
Inc(Params);
NextState := Eat_Semi;
Exit;
END;
END {CASE c} ;
Command:
NextState := Waiting;
CASE c OF
{ Note: the order OF commands is optimized FOR execution speed }
'm' : {sgr}
BEGIN
FOR i := 1 TO Params DO
BEGIN
IF (Reverse) THEN
TextAttr := TextAttr SHR 4 + TextAttr SHL 4;
CASE ParamArr[i] OF
0 :
BEGIN
Reverse := FALSE;
TextAttr := 7;
END;
1 : TextAttr := TextAttr AND $FF OR $08;
2 : TextAttr := TextAttr AND $F7 OR $00;
4 : TextAttr := TextAttr AND $F8 OR $01;
5 : TextAttr := TextAttr OR $80;
7 : IF NOT Reverse THEN
BEGIN
{
TextAttr := TextAttr SHR 4 + TextAttr SHL 4;
}
Reverse := TRUE;
END;
22 : TextAttr := TextAttr AND $F7 OR $00;
24 : TextAttr := TextAttr AND $F8 OR $04;
25 : TextAttr := TextAttr AND $7F OR $00;
27 : IF Reverse THEN
BEGIN
Reverse := FALSE;
{
TextAttr := TextAttr SHR 4 + TextAttr SHL 4;
}
END;
30 : TextAttr := TextAttr AND $F8 OR $00;
31 : TextAttr := TextAttr AND $F8 OR $04;
32 : TextAttr := TextAttr AND $F8 OR $02;
33 : TextAttr := TextAttr AND $F8 OR $06;
34 : TextAttr := TextAttr AND $F8 OR $01;
35 : TextAttr := TextAttr AND $F8 OR $05;
36 : TextAttr := TextAttr AND $F8 OR $03;
37 : TextAttr := TextAttr AND $F8 OR $07;
40 : TextAttr := TextAttr AND $8F OR $00;
41 : TextAttr := TextAttr AND $8F OR $40;
42 : TextAttr := TextAttr AND $8F OR $20;
43 : TextAttr := TextAttr AND $8F OR $60;
44 : TextAttr := TextAttr AND $8F OR $10;
45 : TextAttr := TextAttr AND $8F OR $50;
46 : TextAttr := TextAttr AND $8F OR $30;
47 : TextAttr := TextAttr AND $8F OR $70;
END {CASE} ;
{ fixup FOR reverse }
IF (Reverse) THEN
TextAttr := TextAttr SHR 4 + TextAttr SHL 4;
END;
END;
'A' : {cuu}
BEGIN
IF (ParamArr[1] = 0) THEN
ParamArr[1] := 1;
{IF (WhereY - ParamArr[1] >= 1)
THEN} GotoXY(WhereX,(WhereY - ParamArr[1]))
{ELSE GotoXY(WhereX, 1);}
END;
'B' : {cud}
BEGIN
IF ParamArr[1] = 0 THEN ParamArr[1] := 1;
{IF (WhereY + ParamArr[1] <= Hi(WindMax) - Hi(WindMin) + 1)
THEN }GotoXY(WhereX, WhereY + ParamArr[1])
{ELSE GotoXY(WhereX, Hi(WindMax) - Hi(WindMin) + 1);}
END;
'C' : {cuf}
BEGIN
IF ParamArr[1] = 0 THEN ParamArr[1] := 1;
{IF (WhereX + ParamArr[1] <= Lo(WindMax) - Lo(WindMin) + 1)
THEN} GotoXY(WhereX + ParamArr[1], WhereY)
{ELSE GotoXY(Lo(WindMax) - Lo(WindMin) + 1, WhereY);}
END;
'D' : {cub}
BEGIN
IF (ParamArr[1] = 0) THEN ParamArr[1] := 1;
{IF (WhereX - ParamArr[1] >= 1)
THEN} GotoXY(WhereX - ParamArr[1], WhereY)
{ELSE GotoXY(1, WhereY);}
END;
'H', 'f' : {cup,hvp}
BEGIN
IF (ParamArr[1] = 0) THEN ParamArr[1] := 1;
IF (ParamArr[2] = 0) THEN ParamArr[2] := 1;
{IF (ParamArr[2] > Lo(WindMax) + 1)
THEN ParamArr[2] := Lo(WindMax) - Lo(WindMin) + 1;
IF (ParamArr[1] > Hi(WindMax) + 1)
THEN ParamArr[1] := Hi(WindMax) - Hi(WindMin) + 1;}
GotoXY(ParamArr[2], ParamArr[1]) ;
END;
'J' : IF (ParamArr[1] = 2) THEN ClrScr
ELSE
FOR i := WhereY TO 25 DO delline; { some terms use others! }
'K' : ClrEOL;
'L' : IF (ParamArr[1] = 0) THEN
insline
ELSE
FOR i := 1 TO ParamArr[1] DO insline; { must NOT Move cursor }
'M' : IF (ParamArr[1] = 0) THEN
delline
ELSE
FOR i := 1 TO ParamArr[1] DO delline; { must NOT Move cursor }
'P' : {dc }
BEGIN
END;
's' : {scp}
BEGIN
SaveX := WhereX;
SaveY := WhereY;
END;
'u' : {rcp} GotoXY(SaveX,SaveY);
'@':; { Some unknown code appears TO DO nothing }
ELSE
Write(c);
END {CASE c} ;
END;
END {CASE NextState} ;
END {AnsiWrite} ;
PROCEDURE ShellDos(MakeBatch: Boolean; CONST Command: AStr; VAR ResultCode: Integer);
VAR
BatFile: Text;
FName,
s: AStr;
BEGIN
IF (NOT MakeBatch) THEN
FName := Command
ELSE
BEGIN
FName := 'TEMP'+IntToStr(ThisNode)+'.BAT';
Assign(BatFile,FName);
ReWrite(BatFile);
WriteLn(BatFile,Command);
Close(BatFile);
LastError := IOResult;
END;
IF (FName <> '') THEN
FName := ' /c '+FName;
Com_Flush_Send;
Com_DeInstall;
CursorOn(TRUE);
SwapVectors;
{$IFDEF MSDOS}
IF (General.SwapShell) THEN
BEGIN
s := GetEnv('TEMP');
IF (s = '') THEN
s := StartDir;
Init_SpawNo(s,General.SwapTo,20,10);
ResultCode := Spawn(GetEnv('COMSPEC'),FName,0);
END;
{$ENDIF}
{$IFDEF WIN32}
ResultCode := -1;
{$ENDIF}
IF (NOT General.SwapShell) OR (ResultCode = -1) THEN
BEGIN
Exec(GetEnv('COMSPEC'),FName);
ResultCode := Lo(DOSExitCode);
LastError := IOResult;
END;
SwapVectors;
IF (MakeBatch) THEN
Kill(FName);
Com_Install;
IF (NOT LocalIOOnly) AND NOT (lockedport IN Liner.mflags) THEN
Com_Set_Speed(ComPortSpeed);
Update_Screen;
TextAttr := CurrentColor;
LastKeyHit := Timer;
END;
FUNCTION LennMCI(CONST InString: STRING): Integer;
VAR
TempStr: STRING;
Counter,
StrLen: Byte;
BEGIN
StrLen := Length(InString);
Counter := 0;
WHILE (Counter < Length(InString)) DO
BEGIN
Inc(Counter);
CASE InString[Counter] OF
^S : BEGIN
Dec(StrLen,2);
Inc(Counter);
END;
'^' : IF (Length(InString) > Counter) AND (InString[Counter + 1] IN ['0'..'9']) THEN
BEGIN
Dec(StrLen,2);
Inc(Counter);
END;
'|' : IF (Length(InString) > (Counter + 1)) AND (InString[Counter + 1] IN ['0'..'9']) AND
(Instring[Counter + 2] IN ['0'..'9']) THEN
BEGIN
Dec(StrLen,3);
Inc(Counter);
END;
'%' : IF (MCIAllowed) AND (Length(InString) > (Counter + 1)) THEN
BEGIN
TempStr := AllCaps(MCI('%' + InString[Counter + 1] + InString[Counter + 2]));
IF (Copy(TempStr,1,3) <> '%' + UpCase(InString[Counter + 1]) + UpCase(InString[Counter + 2])) THEN
Inc(StrLen,Length(TempStr) - 3);
END;
END;
END;
LennMCI := StrLen;
END;
{$V-}
PROCEDURE LCmds3(Len,c: Byte; c1,c2,c3: AStr);
VAR
s: AStr;
BEGIN
s := '';
s := s+'^1(^'+Chr(c + Ord('0'))+c1[1]+'^1)'+PadLeftStr(Copy(c1,2,LennMCI(c1)-1),Len-1);
IF (c2 <> '') THEN
s := s+'^1(^'+Chr(c + Ord('0')) + c2[1]+'^1)'+PadLeftStr(Copy(c2,2,LennMCI(c2)-1),Len-1);
IF (c3 <> '') THEN
s := s+'^1(^'+Chr(c + Ord('0')) + c3[1]+'^1)'+Copy(c3,2,LennMCI(c3)-1);
PrintACR(s);
END;
PROCEDURE LCmds(Len,c: Byte; c1,c2: AStr);
VAR
s: AStr;
BEGIN
s := Copy(c1,2,LennMCI(c1) - 1);
IF (c2 <> '') THEN
s := PadLeftStr(s,Len - 1);
Prompt('^1(^' + IntToStr(c) + c1[1] + '^1)' + s);
IF (c2 <> '') THEN
Prompt('^1(^' + IntToStr(c) + c2[1] + '^1)' + Copy(c2,2,LennMCI(c2) - 1));
NL;
END;
FUNCTION MsgSysOp: Boolean;
BEGIN
MsgSysOp := (CoSysOp) OR (AACS(General.MSOP)) OR (AACS(MemMsgArea.SysOpACS));
END;
FUNCTION FileSysOp: Boolean;
BEGIN
FileSysOp := ((CoSysOp) OR (AACS(General.FSOP)));
END;
FUNCTION CoSysOp: Boolean;
BEGIN
CoSysOp := ((SysOp) OR (AACS(General.CSOP)));
END;
FUNCTION SysOp: Boolean;
BEGIN
SysOp := (AACS(General.SOP));
END;
FUNCTION Timer: LongInt;
BEGIN
Timer := ((Ticks * 5) DIV 91); { 2.5 times faster than Ticks DIV 18.2 }
END;
FUNCTION OkVT100: Boolean;
BEGIN
OkVT100 := (VT100 IN ThisUser.Flags);
END;
FUNCTION OkANSI: Boolean;
BEGIN
OkANSI := (ANSI IN ThisUser.Flags);
END;
FUNCTION OkRIP: Boolean;
BEGIN
OkRIP := (RIP IN ThisUser.SFlags);
END;
FUNCTION OkAvatar: Boolean;
BEGIN
OkAvatar := (Avatar IN ThisUser.Flags);
END;
FUNCTION NSL: LongInt;
VAR
BeenOn: LongInt;
BEGIN
IF ((UserOn) OR (NOT InWFCMenu)) THEN
BEGIN
BeenOn := (GetPackDateTime - TimeOn);
NSL := ((LongInt(ThisUser.TLToday) * 60 + ExtraTime + FreeTime) - (BeenOn + ChopTime + CreditTime));
END
ELSE
NSL := 3600;
END;
FUNCTION StripColor(CONST InString: STRING): STRING;
VAR
TempStr: STRING;
Counter: Byte;
BEGIN
TempStr := '';
Counter := 0;
WHILE (Counter < Length(InString)) DO
BEGIN
Inc(Counter);
CASE InString[Counter] OF
^S : Inc(Counter);
'^' : IF (InString[Counter + 1] IN ['0'..'9']) THEN
Inc(Counter)
ELSE
TempStr := TempStr + '^';
'|' : IF (InString[Counter + 1] IN ['0'..'9']) AND (InString[Counter + 2] IN ['0'..'9']) THEN
Inc(Counter,2)
ELSE
TempStr := TempStr + '|';
ELSE
TempStr := TempStr + InString[Counter];
END;
END;
StripColor := TempStr;
END;
PROCEDURE sl1(s: AStr);
BEGIN
IF (SLogging) THEN
BEGIN
S := S + '^1';
IF (General.StripCLog) THEN
s := StripColor(s);
Append(SysOpLogFile);
IF (IOResult = 0) THEN
BEGIN
WriteLn(SysOpLogFile,s);
Close(SysOpLogFile);
LastError := IOResult;
END;
IF (SLogSeparate IN ThisUser.SFlags) THEN
BEGIN
Append(SysOpLogFile1);
IF (IOResult = 0) THEN
BEGIN
WriteLn(SysOpLogFile1,s);
Close(SysOpLogFile1);
LastError := IOResult;
END;
END;
END;
END;
PROCEDURE SysOpLog(s:AStr);
BEGIN
sl1(' '+s);
END;
FUNCTION StrToInt(S: Str11): LongInt;
VAR
I: Integer;
L: LongInt;
BEGIN
Val(S,L,I);
IF (I > 0) THEN
BEGIN
S[0] := Chr(I - 1);
Val(S,L,I)
END;
IF (S = '') THEN
StrToInt := 0
ELSE
StrToInt := L;
END;
FUNCTION RealToStr(R: Real; W,D: Byte): STRING;
VAR
S: STRING[11];
BEGIN
Str(R:W:D,S);
RealToStr := S;
END;
FUNCTION ValueR(S: AStr): REAL;
VAR
Code: Integer;
R: REAL;
BEGIN
Val(S,R,Code);
IF (Code <> 0) THEN
BEGIN
S := Copy(S,1,(Code - 1));
Val(S,R,Code)
END;
ValueR := R;
IF (S = '') THEN
ValueR := 0;
END;
FUNCTION AgeUser(CONST BirthDate: LongInt): Word;
VAR
DT1,
DT2: DateTime;
Year: Word;
BEGIN
PackToDate(DT1,BirthDate);
GetDateTime(DT2);
Year := (DT2.Year - DT1.Year);
IF (DT2.Month < DT1.Month) THEN
Dec(Year);
IF (DT2.Month = DT1.Month) AND (DT2.Day < DT1.Day) THEN
Dec(Year);
AgeUser := Year;
END;
FUNCTION AllCaps(InString: STRING): STRING;
VAR
Counter: Byte;
BEGIN
FOR Counter := 1 TO Length(InString) DO
IF (InString[Counter] IN ['a'..'z']) THEN
InString[Counter] := Chr(Ord(InString[Counter]) - Ord('a')+Ord('A'));
AllCaps := InString;
END;
FUNCTION Caps(Instring: STRING): STRING;
VAR
Counter: Integer; { must be Integer }
BEGIN
IF (InString[1] IN ['a'..'z']) THEN
Dec(InString[1],32);
FOR Counter := 2 TO Length(Instring) DO
IF (InString[Counter - 1] IN ['a'..'z','A'..'Z']) THEN
IF (InString[Counter] IN ['A'..'Z']) THEN
Inc(InString[Counter],32)
ELSE
ELSE
IF (InString[Counter] IN ['a'..'z']) THEN
Dec(InString[Counter],32);
Caps := InString;
END;
FUNCTION GetC(c: Byte): STRING;
CONST
xclr: ARRAY [0..7] OF Char = ('0','4','2','6','1','5','3','7');
VAR
s: STRING[10];
b: Boolean;
PROCEDURE adto(ss: str8);
BEGIN
IF (s[Length(s)] <> ';') AND (s[Length(s)] <> '[') THEN
s := s + ';';
s := s + ss;
b := TRUE;
END;
BEGIN
b := FALSE;
IF ((CurrentColor AND (NOT c)) AND $88) <> 0 THEN
BEGIN
s := #27+'[0';
CurrentColor := $07;
END
ELSE
s := #27+'[';
IF (c AND 7 <> CurrentColor AND 7) THEN
adto('3'+xclr[c AND 7]);
IF (c AND $70 <> CurrentColor AND $70) THEN
adto('4'+xclr[(c SHR 4) AND 7]);
IF (c AND 128 <> 0) THEN
adto('5');
IF (c AND 8 <> 0) THEN
adto('1');
IF (NOT b) THEN
adto('3'+xclr[c AND 7]);
s := s + 'm';
GetC := s;
END;
PROCEDURE SetC(C: Byte);
BEGIN
IF (NOT (OkANSI OR OkAvatar)) THEN
BEGIN
TextAttr := 7;
Exit;
END;
IF (C <> CurrentColor) THEN
BEGIN
IF (NOT (Color IN ThisUser.Flags)) THEN
IF ((C AND 8) = 8) THEN
C := 15
ELSE
C := 7;
IF (OutCom) THEN
IF (OkAvatar) THEN
SerialOut(^V^A+Chr(C AND $7f))
ELSE
SerialOut(GetC(C));
TextAttr := C;
CurrentColor := C;
END;
END;
PROCEDURE UserColor(Color: Byte);
BEGIN
IF (Color IN [0..9]) THEN
IF (OkANSI OR OkAvatar) THEN
SetC(Scheme.Color[Color + 1]);
END;
FUNCTION SQOutSp(InString: STRING): STRING;
BEGIN
WHILE (Pos(' ',InString) > 0) DO
Delete(InString,Pos(' ',InString),1);
SQOutSp := InString;
END;
FUNCTION ExtractDriveNumber(s: AStr): Byte;
BEGIN
s := FExpand(s);
ExtractDriveNumber := (Ord(s[1]) - 64);
END;
FUNCTION PadLeftStr(InString: STRING; MaxLen: Byte): STRING;
VAR
StrLen,
Counter: Byte;
BEGIN
StrLen := LennMCI(InString);
IF (StrLen > MaxLen) THEN
WHILE (StrLen > MaxLen) DO
BEGIN
InString[0] := Chr(MaxLen + (Length(InString) - StrLen));
StrLen := LennMCI(InString);
END
ELSE
FOR Counter := StrLen TO (MaxLen - 1) DO
InString := InString + ' ';
PadLeftStr := Instring;
END;
FUNCTION PadRightStr(InString: STRING; MaxLen: Byte): STRING;
VAR
StrLen,
Counter: Byte;
BEGIN
StrLen := LennMCI(InString);
FOR Counter := StrLen TO (MaxLen - 1) DO
InString := ' ' + InString;
IF (StrLen > MaxLen) THEN
InString[0] := Chr(MaxLen + (Length(InString) - StrLen));
PadRightStr := Instring;
END;
FUNCTION PadLeftInt(L: LongInt; MaxLen: Byte): STRING;
BEGIN
PadLeftInt := PadLeftStr(IntToStr(L),MaxLen);
END;
FUNCTION PadRightInt(L: LongInt; MaxLen: Byte): STRING;
BEGIN
PadRightInt := PadRightStr(IntToStr(L),MaxLen);
END;
PROCEDURE Prompt(CONST InString: STRING);
VAR
SaveAllowAbort: Boolean;
BEGIN
SaveAllowAbort := AllowAbort;
AllowAbort := FALSE;
PrintMain(InString);
AllowAbort := SaveAllowAbort;
END;
PROCEDURE Print(CONST Instring: STRING);
BEGIN
Prompt(InString+^M^J);
END;
PROCEDURE NL;
BEGIN
Prompt(^M^J);
END;
PROCEDURE Prt(CONST Instring: STRING);
BEGIN
UserColor(4);
Prompt(Instring);
UserColor(3);
END;
PROCEDURE MPL(MaxLen: Byte);
VAR
Counter,
SaveWhereX : Byte;
BEGIN
IF (OkANSI OR OkAvatar) THEN
BEGIN
UserColor(6);
SaveWhereX := WhereX;
IF (OutCom) THEN
FOR Counter := 1 TO MaxLen DO
Com_Send(' ');
IF (WantOut) THEN
FOR Counter := 1 TO MaxLen DO
Write(' ');
GotoXY(SaveWhereX,WhereY);
IF (OutCom) THEN
IF (OkAvatar) THEN
SerialOut(^y+^H+Chr(MaxLen))
ELSE
SerialOut(#27+'['+IntToStr(MaxLen)+'D');
END;
END;
FUNCTION InKey: Word;
VAR
c: Char;
l: LongInt;
BEGIN
c := #0;
InKey := 0;
CheckHangup;
IF (KeyPressed) THEN
BEGIN
c := ReadKey;
IF (c = #0) AND (KeyPressed) THEN
BEGIN
c := ReadKey;
SKey1(c);
IF (c = #31) OR (C = #46) THEN
c := #1
ELSE
BEGIN
InKey := (Ord(c) * 256); { Return scan code IN MSB }
Exit;
END;
END;
IF (Buf <> '') THEN
BEGIN
c := Buf[1];
Buf := Copy(Buf,2,255);
END;
InKey := Ord(c);
END
ELSE IF (InCom) THEN
BEGIN
c := CInKey;
IF (c = #27) THEN
BEGIN
IF (Empty) THEN
Delay(100);
IF (c = #27) AND (NOT Empty) THEN
BEGIN
c := CInKey;
IF (c = '[') OR (c = 'O') THEN
BEGIN
l := (Ticks + 4);
c := #0;
WHILE (l > Ticks) AND (c = #0) DO
c := CInKey;
END;
CASE Char(c) OF
'A' : InKey := F_UP; {UpArrow}
'B' : InKey := F_DOWN; {DownArrow}
'C' : InKey := F_RIGHT; {RightArrow}
'D' : InKey := F_LEFT; {LeftArrow}
'H' : InKey := F_HOME; {Home}
'K' : InKey := F_END; {END - PROCOMM+}
'R' : InKey := F_END; {END - GT}
'4' : BEGIN
InKey := F_END;
c := CInKey;
END;
'r' : InKey := F_PGUP; {PgUp}
'q' : InKey := F_PGDN; {PgDn}
'n' : InKey := F_INS; {Ins}
END;
Exit;
END;
END;
IF (c = #127) THEN
InKey := F_DEL
ELSE
InKey := Ord(c);
END;
END;
PROCEDURE OutTrap(c: Char);
BEGIN
IF (c <> ^G) THEN
Write(TrapFile,c);
IF (IOResult <> 0) THEN
BEGIN
SysOpLog('Error writing to trap file.');
Trapping := FALSE;
END;
END;
PROCEDURE OutKey(c: Char);
VAR
S: Str1;
BEGIN
IF (NOT Echo) THEN
IF (General.LocalSec) AND (c IN [#32..#255]) THEN
BEGIN
s := lRGLNGStr(1,TRUE); {FString.EchoC;}
c := s[1];
END;
IF (c IN [#27,^V,^y]) THEN
DOSANSIOn := TRUE;
IF (WantOut) AND (DOSANSIOn) AND (NextState <> Waiting) THEN
BEGIN
DOSANSI(c);
IF (OutCom) THEN
Com_Send(c);
Exit;
END
ELSE IF (c <> ^J) AND (c <> ^L) THEN
IF (WantOut) AND (NOT DOSANSIOn) AND NOT ((c = ^G) AND InCom) THEN
Write(c)
ELSE IF (WantOut) AND NOT ((c = ^G) AND InCom) THEN
DOSANSI(c);
IF (NOT Echo) AND (c IN [#32..#255]) THEN
BEGIN
S := lRGLNGStr(1,TRUE); {FString.EchoC;}
c := S[1];
END;
CASE c OF
^J : BEGIN
IF (NOT InChat) AND (NOT Write_Msg) AND (NOT CtrlJOff) AND (NOT DOSANSIOn) THEN
BEGIN
IF (((CurrentColor SHR 4) AND 7) > 0) OR (CurrentColor AND 128 = 128) THEN
SetC(Scheme.Color[1])
END
ELSE
LIL := 1;
IF (Trapping) THEN
OutTrap(c);
IF (WantOut) THEN
Write(^J);
IF (OutCom) THEN
Com_Send(^J);
Inc(LIL);
IF (LIL >= PageLength) THEN
BEGIN
LIL := 1;
IF (TempPause) THEN
PauseScr(TRUE);
END;
END;
^L : BEGIN
IF (WantOut) THEN
ClrScr;
IF (OutCom) THEN
Com_Send(^L);
LIL := 1;
END;
ELSE
BEGIN
IF (OutCom) THEN
Com_Send(c);
IF (Trapping) THEN
OutTrap(c);
END;
END;
END;
FUNCTION PageLength: Word;
BEGIN
IF (InCom) THEN
PageLength := ThisUser.PageLen
ELSE IF (General.WindowOn) AND NOT (InWFCMenu) THEN
PageLength := (MaxDisplayRows - 2)
ELSE
PageLength := MaxDisplayRows;
END;
PROCEDURE TeleConfCheck;
VAR
f: FILE;
s: STRING;
Counter: Byte;
SaveMCIAlllowed: Boolean;
{ Only check IF we're bored AND NOT slicing }
BEGIN
IF (MaxChatRec > NodeChatLastRec) THEN
BEGIN
FOR Counter := 1 TO (LennMCI(MLC) + 5) DO
BackSpace;
Assign(f,General.TempPath+'MSG'+IntToStr(ThisNode)+'.TMP');
Reset(f,1);
Seek(f,NodeChatLastRec);
WHILE NOT EOF(f) DO
BEGIN
BlockRead(f,s[0],1);
BlockRead(f,s[1],Ord(s[0]));
MultiNodeChat := FALSE; {avoid recursive calls during Pause!}
SaveMCIAlllowed := MCIAllowed;
MCIAllowed := FALSE;
Print(s);
MCIAllowed := SaveMCIAlllowed;
MultiNodeChat := TRUE;
END;
Close(f);
LastError := IOResult;
NodeChatLastRec := MaxChatRec;
Prompt('^3'+MLC);
END;
END;
FUNCTION GetKey: Word;
CONST
LastTimeSlice: LongInt = 0;
LastCheckTimeSlice: LongInt = 0;
VAR
{$IFDEF MSDOS}
Killme: Pointer ABSOLUTE $0040 :$F000;
{$ENDIF}
Tf: Boolean;
I: Integer;
C: Word;
TempTimer: LongInt;
BEGIN
IF (DieLater) THEN
{$IFDEF MSDOS}
ASM
Call Killme
END;
{$ENDIF}
{$IFDEF WIN32}
Halt;
{$ENDIF}
LIL := 1;
IF (Buf <> '') THEN
BEGIN
C := Ord(Buf[1]);
Buf := Copy(Buf,2,255);
END
ELSE
BEGIN
IF (NOT Empty) THEN
BEGIN
IF (InChat) THEN
C := Ord(Chinkey)
ELSE
C := InKey;
END
ELSE
BEGIN
Tf := FALSE;
LastKeyHit := Timer;
C := 0;
WHILE ((C = 0) AND (NOT HangUp)) DO
BEGIN
TempTimer := Timer;
IF (LastScreenSwap > 0) THEN
BEGIN
IF ((TempTimer - LastScreenSwap) < 0) THEN
LastScreenSwap := ((Timer - LastScreenSwap) + 86400);
IF ((TempTimer - LastScreenSwap) > 10) THEN
Update_Screen;
END;
IF (Alert IN ThisUser.Flags) OR ((NOT ShutUpChatCall) AND (General.ChatCall) AND (ChatReason <> '')) THEN
BEGIN
IF ((TempTimer - LastBeep) < 0) THEN
LastBeep := ((TempTimer - LastBeep) + 86400);
IF ((Alert IN ThisUser.Flags) AND ((TempTimer - LastBeep) >= General.Alertbeep)) OR
((ChatReason <> '') AND (SysOpAvailable) AND ((TempTimer - LastBeep) >= 5)) THEN
BEGIN
FOR I := 1 TO 100 DO
BEGIN
{$IFDEF MSDOS}
Sound(500 + (I * 10));
Delay(2);
Sound(100 + (I * 10));
Delay(2);
NoSound;
{$ENDIF}
{$IFDEF WIN32}
Sound(500, 200);
Sound(1500, 200);
{$ENDIF}
END;
LastBeep := TempTimer;
END;
END;
IF ((TempTimer - LastKeyHit) < 0) THEN
LastKeyHit := ((TempTimer - LastKeyHit) + 86400);
IF (General.TimeOut <> - 1) AND ((TempTimer - LastKeyHit) > (General.TimeOut * 60)) AND (NOT TimedOut)
AND (ComPortSpeed <> 0) THEN
BEGIN
TimedOut := TRUE;
PrintF('TIMEOUT');
IF (NoFile) THEN
Print(^M^J^M^J'Time out - disconnecting.'^M^J^M^J);
HangUp := TRUE;
SysOpLog('Inactivity timeout at '+TimeStr);
END;
IF (General.TimeOutBell <> - 1) AND ((TempTimer - LastKeyHit) > (General.TimeOutBell * 60)) AND
(NOT Tf) THEN
BEGIN
Tf := TRUE;
OutKey(^G);
Delay(100);
OutKey(^G);
END;
IF (Empty) THEN
BEGIN
IF (ABS((Ticks - LastTimeSlice)) >= General.Slicetimer) THEN
BEGIN
{$IFDEF MSDOS}
CASE Tasker OF
None : ASM
int 28h
END;
DV : ASM
Mov ax, 1000h
int 15h
END;
Win,Win32,DOS5N : ASM (* Added Win32 & DOS5N *)
Mov ax, 1680h
int 2Fh
END;
Os2 : ASM
Push dx
XOR dx, dx
Mov ax, 0
Sti
Hlt
Db 035h, 0Cah
Pop dx
END;
END;
{$ENDIF}
{$IFDEF WIN32}
Sleep(1);
{$ENDIF}
LastTimeSlice := Ticks;
END
ELSE IF (MultiNodeChat) AND (NOT InChat) AND (ABS(Ticks - LastCheckTimeSlice) > 9) THEN
BEGIN
LastCheckTimeSlice := Ticks;
TeleConfCheck;
LIL := 1;
END;
END;
IF (InChat) THEN
C := Ord(Chinkey)
ELSE
C := InKey;
END;
IF (UserOn) AND ((GetPackDateTime - CreditsLastUpdated) > 60) AND NOT (FNoCredits IN ThisUser.Flags) THEN
BEGIN
Inc(ThisUser.Debit,General.Creditminute * ((GetPackDateTime - CreditsLastUpdated) DIV 60));
CreditsLastUpdated := GetPackDateTime;
END;
END;
END;
GetKey := C;
END;
PROCEDURE CLS;
BEGIN
IF (OkANSI OR OkVT100) THEN
SerialOut(^[+'[1;1H'+^[+'[2J')
ELSE
OutKey(^L);
IF (WantOut) THEN
ClrScr;
IF (Trapping) THEN
OutTrap(^L);
UserColor(1);
LIL := 1;
END;
FUNCTION DisplayARFlags(AR: ARFlagSet; C1,C2: Char): AStr;
VAR
Flag: Char;
TempStr: AStr;
BEGIN
TempStr := '';
FOR Flag := 'A' TO 'Z' DO
IF Flag IN AR THEN
TempStr := TempStr + '^'+C1+Flag
ELSE
TempStr := TempStr + '^'+C2+'-';
DisplayArFlags := TempStr;
END;
PROCEDURE ToggleARFlag(Flag: Char; VAR AR: ARFlagSet; VAR Changed: Boolean);
VAR
SaveAR: ARFlagSet;
BEGIN
SaveAR := AR;
IF (Flag IN ['A'..'Z']) THEN
IF (Flag IN AR) THEN
Exclude(AR,Flag)
ELSE
Include(AR,Flag);
IF (SaveAR <> AR) THEN
Changed := TRUE;
END;
FUNCTION DisplayACFlags(Flags: FlagSet; C1,C2: Char): AStr;
VAR
Flag: FlagType;
TempS: AStr;
BEGIN
TempS := '';
FOR Flag := RLogon TO RMsg DO
IF (Flag IN Flags) THEN
TempS := TempS + '^'+C1+Copy('LCVUA*PEKM',(Ord(Flag) + 1),1)
ELSE
TempS := TempS + '^'+C2+'-';
TempS := TempS + '^'+C2+'/';
FOR Flag := FNoDLRatio TO FNoDeletion DO
IF (Flag IN Flags) THEN
TempS := TempS + '^'+C1+Copy('1234',(Ord(Flag) - 19),1)
ELSE
TempS := TempS + '^'+C2+'-';
DisplayACFlags := TempS;
END;
PROCEDURE ToggleACFlag(Flag: FlagType; VAR Flags: FlagSet);
BEGIN
IF (Flag IN Flags) THEN
Exclude(Flags,Flag)
ELSE
Include(Flags,Flag);
END;
PROCEDURE ToggleACFlags(Flag: Char; VAR Flags: FlagSet; VAR Changed: Boolean);
VAR
SaveFlags: FlagSet;
BEGIN
SaveFlags := Flags;
CASE Flag OF
'L' : ToggleACFlag(RLogon,Flags);
'C' : ToggleACFlag(RChat,Flags);
'V' : ToggleACFlag(RValidate,Flags);
'U' : ToggleACFlag(RUserList,Flags);
'A' : ToggleACFlag(RAMsg,Flags);
'*' : ToggleACFlag(RPostAn,Flags);
'P' : ToggleACFlag(RPost,Flags);
'E' : ToggleACFlag(REmail,Flags);
'K' : ToggleACFlag(RVoting,Flags);
'M' : ToggleACFlag(RMsg,Flags);
'1' : ToggleACFlag(FNoDLRatio,Flags);
'2' : ToggleACFlag(FNoPostRatio,Flags);
'3' : ToggleACFlag(FNoCredits,Flags);
'4' : ToggleACFlag(FNoDeletion,Flags);
END;
IF (SaveFlags <> Flags) THEN
Changed := TRUE;
END;
PROCEDURE ToggleStatusFlag(Flag: StatusFlagType; VAR SUFlags: StatusFlagSet);
BEGIN
IF (Flag IN SUFlags) THEN
Exclude(SUFlags,Flag)
ELSE
Include(SUFlags,Flag);
END;
PROCEDURE ToggleStatusFlags(Flag: Char; VAR SUFlags: StatusFlagSet);
BEGIN
CASE Flag OF
'A' : ToggleStatusFlag(LockedOut,SUFlags);
'B' : ToggleStatusFlag(Deleted,SUFlags);
'C' : ToggleStatusFlag(TrapActivity,SUFlags);
'D' : ToggleStatusFlag(TrapSeparate,SUFlags);
'E' : ToggleStatusFlag(ChatAuto,SUFlags);
'F' : ToggleStatusFlag(ChatSeparate,SUFlags);
'G' : ToggleStatusFlag(SLogSeparate,SUFlags);
'H' : ToggleStatusFlag(CLSMsg,SUFlags);
'I' : ToggleStatusFlag(RIP,SUFlags);
'J' : ToggleStatusFlag(FSEditor,SUFlags);
'K' : ToggleStatusFlag(AutoDetect,SUFlags);
END;
END;
FUNCTION TACCH(Flag: Char): FlagType;
BEGIN
CASE Flag OF
'L': TACCH := RLogon;
'C': TACCH := RChat;
'V': TACCH := RValidate;
'U': TACCH := RUserList;
'A': TACCH := RAMsg;
'*': TACCH := RPostAN;
'P': TACCH := RPost;
'E': TACCH := REmail;
'K': TACCH := RVoting;
'M': TACCH := RMsg;
'1': TACCH := FNoDLRatio;
'2': TACCH := FNoPostRatio;
'3': TACCH := FNoCredits;
'4': TACCH := FNoDeletion;
END;
END;
{$IFDEF MSDOS}
FUNCTION AOnOff(b: Boolean; CONST s1,s2:AStr): STRING; ASSEMBLER;
ASM
PUSH ds
Test b, 1
JZ @@1
LDS si, s1
JMP @@2
@@1: LDS si, s2
@@2: LES di, @Result
XOR Ch, Ch
MOV cl, Byte ptr ds:[si]
MOV Byte ptr es:[di], cl
Inc di
Inc si
CLD
REP MOVSB
POP ds
END;
{$ENDIF}
{$IFDEF WIN32}
FUNCTION AOnOff(b: Boolean; CONST s1,s2:AStr): STRING;
BEGIN
if (b) then
AOnOff := s1
else
AOnOff := s2;
END;
{$ENDIF}
FUNCTION ShowOnOff(b: Boolean): STRING;
BEGIN
IF (b) THEN
ShowOnOff := 'On '
ELSE
ShowOnOff := 'Off';
END;
FUNCTION ShowYesNo(b: Boolean): STRING;
BEGIN
IF (b) THEN
ShowYesNo := 'Yes'
ELSE
ShowYesNo := 'No ';
END;
FUNCTION YN(Len: Byte; DYNY: Boolean): Boolean;
VAR
Cmd: Char;
BEGIN
IF (NOT HangUp) THEN
BEGIN
UserColor(3);
Prompt(SQOutSp(ShowYesNo(DYNY)));
REPEAT
Cmd := UpCase(Char(GetKey));
UNTIL (Cmd IN ['Y','N',^M]) OR (HangUp);
IF (DYNY) AND (Cmd <> 'N') THEN
Cmd := 'Y';
IF (DYNY) AND (Cmd = 'N') THEN
Prompt(#8#8#8'^3No ')
ELSE IF (NOT DYNY) AND (Cmd = 'Y') THEN
Prompt(#8#8'^3Yes');
IF (Cmd = 'N') AND (Len <> 0) THEN
DoBackSpace(1,Len)
ELSE
NL;
UserColor(1);
YN := (Cmd = 'Y') AND (NOT HangUp);
END;
END;
FUNCTION PYNQ(CONST InString: AStr; MaxLen: Byte; DYNY: Boolean): Boolean;
BEGIN
UserColor(7);
Prompt(InString);
PYNQ := YN(MaxLen,DYNY);
END;
PROCEDURE OneK(VAR C: Char; ValidKeys: AStr; DisplayKey,LineFeed: Boolean);
BEGIN
MPL(1);
TempPause := (Pause IN ThisUser.Flags);
REPEAT
C := UpCase(Char(GetKey));
UNTIL (Pos(C,ValidKeys) > 0) OR (HangUp);
IF (HangUp) THEN
C := ValidKeys[1];
IF (DisplayKey) THEN
OutKey(C);
IF (Trapping) THEN
OutTrap(C);
UserColor(1);
IF (LineFeed) THEN
NL;
END;
PROCEDURE OneK1(VAR C: Char; ValidKeys: AStr; DisplayKey,LineFeed: Boolean);
BEGIN
MPL(1);
TempPause := (Pause IN ThisUser.Flags);
REPEAT
C := Char(GetKey);
IF (C = 'q') THEN
C := UpCase(C);
UNTIL (Pos(C,ValidKeys) > 0) OR (HangUp);
IF (HangUp) THEN
C := ValidKeys[1];
IF (DisplayKey) THEN
OutKey(C);
IF (Trapping) THEN
OutTrap(C);
UserColor(1);
IF (LineFeed) THEN
NL;
END;
PROCEDURE LOneK(DisplayStr: AStr; VAR C: Char; ValidKeys: AStr; DisplayKey,LineFeed: Boolean);
BEGIN
Prt(DisplayStr);
MPL(1);
TempPause := (Pause IN ThisUser.Flags);
REPEAT
C := UpCase(Char(GetKey));
UNTIL (Pos(C,ValidKeys) > 0) OR (HangUp);
IF (HangUp) THEN
C := ValidKeys[1];
IF (DisplayKey) THEN
OutKey(C);
IF (Trapping) THEN
OutTrap(C);
UserColor(1);
IF (LineFeed) THEN
NL;
END;
FUNCTION Centre(InString: AStr): STRING;
VAR
StrLen,
Counter: Integer;
BEGIN
StrLen := LennMCI(Instring);
IF (StrLen < ThisUser.LineLen) THEN
BEGIN
Counter := ((ThisUser.LineLen - StrLen) DIV 2);
Move(Instring[1],Instring[Counter + 1],Length(Instring));
Inc(Instring[0],Counter);
FillChar(InString[1],Counter,#32);
END;
Centre := InString;
END;
PROCEDURE WKey;
VAR
Cmd: Char;
BEGIN
IF (NOT AllowAbort) OR (Abort) OR (HangUp) OR (Empty) THEN
Exit;
Cmd := Char(GetKey);
IF (DisplayingMenu) AND (Pos(UpCase(Cmd),MenuKeys) > 0) THEN
BEGIN
MenuAborted := TRUE;
Abort := TRUE;
Buf := Buf + UpCase(Cmd);
END
ELSE
CASE UpCase(Cmd) OF
' ',^C,^X,^K :
Abort := TRUE;
'N',^N :
IF (Reading_A_Msg) THEN
BEGIN
Abort := TRUE;
Next := TRUE;
END;
'P',^S :
Cmd := Char(GetKey);
ELSE IF (Reading_A_Msg) OR (PrintingFile) THEN
IF (Cmd <> #0) THEN
Buf := Buf + Cmd;
END;
IF (Abort) THEN
BEGIN
Com_Purge_Send;
NL;
END;
END;
PROCEDURE PrintMain(CONST ss:STRING);
VAR
i,
X: Word;
X2: Byte;
c: Char;
cs: STRING;
s: STRING;
Justify: Byte;
BEGIN
IF (Abort) AND (AllowAbort) THEN
Exit;
IF (HangUp) THEN
BEGIN
Abort := TRUE;
Exit;
END;
IF (NOT MCIAllowed) THEN
s := ss
ELSE
BEGIN
s := '';
FOR i := 1 TO Length(ss) DO
IF (ss[i] = '%') AND (i + 2 <= Length(ss)) THEN
BEGIN
cs := MCI(Copy(ss,i,3)); { faster than adding }
IF (cs = Copy(ss,i,3)) THEN
BEGIN
s := s + '%';
Continue;
END;
Inc(i,2);
IF (Length(ss) >= i + 2) AND (ss[i + 1] IN ['#','{','}']) THEN
BEGIN
IF (ss[i + 1] = '}') THEN
Justify := 0
ELSE IF (ss[i + 1] = '{') THEN
Justify := 1
ELSE
Justify := 2;
IF (ss[i + 2] IN ['0'..'9']) THEN
BEGIN
X2 := Ord(ss[i + 2]) - 48;
Inc(i, 2);
IF (ss[i + 1] IN ['0'..'9']) THEN
BEGIN
X2 := X2 * 10 + Ord(ss[i + 1]) - 48;
Inc(i, 1);
END;
IF (X2 > 0) THEN
CASE Justify OF
0 : cs := PadRightStr(cs,X2);
1 : cs := PadLeftStr(cs,X2);
2 : WHILE (Length(cs) < X2) DO
BEGIN
cs := ' ' + cs;
IF (Length(cs) < X2) THEN
cs := cs + ' ';
END;
END;
END;
END;
{ s := s + cs; }
IF (Length(cs) + Length(s) <= 255) THEN
BEGIN
Move(cs[1],s[Length(s)+1],Length(cs));
Inc(s[0],Length(cs));
END
ELSE
IF (Length(s) < 255) THEN
BEGIN
Move(cs[1],s[Length(s)+1],(255 - Length(s)));
s[0] := #255;
END;
END
ELSE
IF (Length(s) < 255) THEN { s := s + ss[i]; }
BEGIN
Inc(s[0]);
s[Length(s)] := ss[i];
END;
END;
IF NOT (OkANSI OR OkAvatar) THEN
s := StripColor(s);
i := 1;
IF ((NOT Abort) OR (NOT AllowAbort)) AND (NOT HangUp) THEN { can't change IN loop }
WHILE (i <= Length(s)) DO
BEGIN
CASE s[i] OF
'%' : IF MCIAllowed AND (i + 1 < Length(s)) THEN
BEGIN
IF (UpCase(s[i + 1]) = 'P') AND (UpCase(s[i + 2]) = 'A') THEN { %PA Pause }
BEGIN
Inc(i,2);
PauseScr(FALSE)
END
ELSE IF (UpCase(s[i + 1]) = 'P') AND (UpCase(s[i + 2]) = 'E') THEN { %PE Null Pause }
BEGIN
Inc(i,2);
PauseIsNull := TRUE;
PauseScr(FALSE);
PauseIsNull := FALSE;
END
ELSE IF (UpCase(s[i + 1]) = 'D') THEN
IF (UpCase(s[i + 2]) = 'E') THEN { %DE Delay }
BEGIN
Inc(i,2);
OutKey(' '); OutKey(#8); { guard against +++ }
Delay(800);
END
ELSE IF ((UpCase(s[i + 2]) = 'F') AND (NOT PrintingFile)) THEN { %DF File Include }
BEGIN
cs := ''; Inc(i, 3);
WHILE (i < Length(s)) AND (s[i] <> '%') DO
BEGIN
cs := cs + s[i];
Inc(i);
END;
PrintF(StripName(cs));
END
ELSE
ELSE
OutKey('%');
END
ELSE
OutKey('%');
^S:IF (i < Length(s)) AND (NextState = Waiting) THEN BEGIN
IF (Ord(s[i + 1]) <= 200) THEN SetC(Scheme.Color[Ord(s[i + 1])]); Inc(i);
END
ELSE OutKey('');
'|':IF (ColorAllowed) AND (i + 1 < Length(s)) AND
(s[i + 1] IN ['0'..'9']) AND (s[i + 2] IN ['0'..'9'])
THEN
BEGIN
X := StrToInt(Copy(s,i + 1,2));
CASE X OF
0..15:SetC(CurrentColor - (CurrentColor MOD 16) + X);
16..23:SetC(((X - 16) * 16) + (CurrentColor MOD 16));
END;
Inc(i,2);
END
ELSE
OutKey('|');
#9:FOR X := 1 TO 5 DO
OutKey(' ');
'^':IF (ColorAllowed) AND (i < Length(s)) AND (s[i+1] IN ['0'..'9']) THEN
BEGIN
Inc(i);
UserColor(Ord(s[i]) - 48);
END
ELSE
OutKey('^');
ELSE
OutKey(s[i]);
END;
Inc(i);
X2 := i;
WHILE (X2 < Length(s)) AND
NOT (s[X2] IN [^S,'^','|','%',^G,^L,^V,^y,^J,^[])
DO
Inc(X2);
IF (X2 > i) THEN
BEGIN
cs[0] := Chr(X2 - i);
Move(s[i], cs[1], X2 - i); { twice as fast as Copy(s,i,x2-i); }
i := X2;
IF (Trapping) THEN
Write(TrapFile,cs);
IF (WantOut) THEN
IF (NOT DOSANSIOn) THEN
Write(cs)
ELSE
FOR X2 := 1 TO Length(cs) DO
DOSANSI(cs[X2]);
SerialOut(cs);
END;
END;
WKey;
END;
PROCEDURE PrintACR(InString: STRING);
VAR
TurnOff: Boolean;
BEGIN
IF (AllowAbort) AND (Abort) THEN
Exit;
Abort := FALSE;
TurnOff := (InString[Length(Instring)] = #29);
IF (TurnOff) THEN
Dec(InString[0]);
CheckHangup;
IF (NOT CROff) AND NOT (TurnOff) THEN
InString := InString + ^M^J;
PrintMain(InString);
IF (Abort) THEN
BEGIN
CurrentColor := (255 - CurrentColor);
UserColor(1);
END;
CROff := FALSE;
END;
PROCEDURE pfl(FN: AStr);
VAR
fil: Text;
ls: STRING[255];
ps: Byte;
c: Char;
SaveTempPause,
ToggleBack,
SaveAllowAbort: Boolean;
BEGIN
PrintingFile := TRUE;
SaveAllowAbort := AllowAbort;
AllowAbort := TRUE;
Abort := FALSE;
Next := FALSE;
ToggleBack := FALSE;
SaveTempPause := TempPause;
FN := AllCaps(FN);
IF (General.WindowOn) AND (Pos('.AN',FN) > 0) OR (Pos('.AV',FN) > 0) THEN
BEGIN
TempPause := FALSE;
ToggleBack := TRUE;
ToggleWindow(FALSE);
IF (OkRIP) THEN
SerialOut('!|*|');
END;
IF (Pos('.RI',FN) > 0) THEN
TempPause := FALSE;
IF (NOT HangUp) THEN
BEGIN
Assign(fil,SQOutSp(FN));
Reset(fil);
IF (IOResult <> 0) THEN
NoFile := TRUE
ELSE
BEGIN
Abort := FALSE;
Next := FALSE;
WHILE (NOT EOF(fil)) AND (NOT Abort) AND (NOT HangUp) DO
BEGIN
ps := 0;
REPEAT
Inc(ps);
Read(fil,ls[ps]);
IF EOF(fil) THEN {check again incase avatar parameter}
BEGIN
Inc(ps);
Read(fil,ls[ps]);
IF EOF(fil) THEN
Dec(ps);
END;
UNTIL ((ls[ps] = ^J) AND (NextState IN [Waiting..In_Param])) OR (ps = 255) OR EOF(fil);
ls[0] := Chr(ps);
CROff := TRUE;
CtrlJOff := ToggleBack;
PrintACR(ls);
END;
Close(fil);
END;
NoFile := FALSE;
END;
AllowAbort := SaveAllowAbort;
PrintingFile := FALSE;
CtrlJOff := FALSE;
IF (ToggleBack) THEN
ToggleWindow(TRUE);
RedrawForANSI;
IF (NOT TempPause) THEN
LIL := 0;
TempPause := SaveTempPause;
END;
FUNCTION BSlash(InString: AStr; b: Boolean): AStr;
BEGIN
IF (b) THEN
BEGIN
WHILE (Copy(InString,(Length(InString) - 1),2) = '\\') DO
InString := Copy(Instring,1,(Length(InString) - 2));
IF (Copy(InString,Length(InString),1) <> '\') THEN
InString := InString + '\';
END
ELSE
WHILE (InString[Length(InString)] = '\') DO
Dec(InString[0]);
BSlash := Instring;
END;
FUNCTION Exist(FileName: AStr): Boolean;
VAR
DirInfo1: SearchRec;
BEGIN
FindFirst(SQOutSp(FileName),AnyFile,DirInfo1);
Exist := (DOSError = 0);
END;
FUNCTION ExistDir(Path: PathStr): Boolean;
VAR
DirInfo1: SearchRec;
BEGIN
Path := AllCaps(BSlash(Path,FALSE));
FindFirst(Path,AnyFile,DirInfo1);
ExistDir := (DOSError = 0) AND (DirInfo1.Attr AND $10 = $10);
END;
PROCEDURE PrintFile(FileName: AStr);
VAR
s: AStr;
dayofweek: Byte;
i: Integer;
BEGIN
FileName := AllCaps(FileName);
s := FileName;
IF (Copy(FileName,Length(FileName) - 3,4) = '.ANS') THEN
BEGIN
IF (Exist(Copy(FileName,1,Length(FileName) - 4)+'.AN1')) THEN
REPEAT
i := Random(10);
IF (i = 0) THEN
FileName := Copy(FileName,1,Length(FileName) - 4)+'.ANS'
ELSE
FileName := Copy(FileName,1,Length(FileName) - 4)+'.AN'+IntToStr(i);
UNTIL (Exist(FileName));
END
ELSE IF (Copy(FileName,Length(FileName) - 3,4) = '.AVT') THEN
BEGIN
IF (Exist(Copy(FileName,1,Length(FileName) - 4)+'.AV1')) THEN
REPEAT
i := Random(10);
IF (i = 0) THEN
FileName := Copy(FileName,1,Length(FileName) - 4)+'.AVT'
ELSE
FileName := Copy(FileName,1,Length(FileName) - 4)+'.AV'+IntToStr(i);
UNTIL (Exist(FileName));
END
ELSE IF (Copy(FileName,Length(FileName) - 3,4) = '.RIP') THEN
BEGIN
IF (Exist(Copy(FileName,1,Length(FileName) - 4)+'.RI1')) THEN
REPEAT
i := Random(10);
IF (i = 0) THEN
FileName := Copy(FileName,1,Length(FileName) - 4)+'.RIP'
ELSE
FileName := Copy(FileName,1,Length(FileName) - 4)+'.RI'+IntToStr(i);
UNTIL (Exist(FileName));
END;
GetDayOfWeek(DayOfWeek);
s := FileName;
s[Length(s) - 1] := Chr(DayOfWeek + 48);
IF (Exist(s)) THEN
FileName := s;
pfl(FileName);
END;
PROCEDURE PrintF(FileName: AStr);
VAR
FFN,
Path: PathStr;
Name: NameStr;
Ext: ExtStr;
j: Integer; (* doesn't seem to do anything *)
BEGIN
NoFile := TRUE;
FileName := SQOutSp(FileName);
IF (FileName = '') THEN
Exit;
IF (Pos('\',FileName) <> 0) THEN (* ??? *)
j := 1
ELSE
BEGIN
j := 2;
FSplit(FExpand(FileName),Path,Name,Ext);
IF (NOT Exist(General.MiscPath+Name+'.*')) THEN
Exit;
END;
FFN := FileName;
IF ((Pos('\',FileName) = 0) AND (Pos(':',FileName) = 0)) THEN
FFN := General.MiscPath+FFN;
FFN := FExpand(FFN);
IF (Pos('.',FileName) <> 0) THEN
PrintFile(FFN)
ELSE
BEGIN
IF (OkRIP) AND Exist(FFN+'.RIP') THEN
PrintFile(FFN+'.RIP');
IF (NoFile) AND (OkAvatar) AND Exist(FFN+'.AVT') THEN
PrintFile(FFN+'.AVT');
IF (NoFile) AND (OkANSI) AND Exist(FFN+'.ANS') THEN
PrintFile(FFN+'.ANS');
IF (NoFile) AND (Exist(FFN+'.ASC')) THEN
PrintFile(FFN+'.ASC');
END;
END;
FUNCTION VerLine(B: Byte): STRING;
BEGIN
CASE B OF
1 : VerLine := '|09The |14Renegade Bulletin Board System|09, Version |15'+General.Version;
2 : VerLine := '|09Brought to you by |10The Renegade Development Team|09.';
3 : VerLine := '|09Copyright (c) |151991-2009|09';
END;
END;
FUNCTION AACS1(User: UserRecordType; UNum: Integer; s: ACString): Boolean;
VAR
s1,
s2: AStr;
c,
c1,
c2: Char;
i,
p1,
p2,
j: Integer;
b: Boolean;
PROCEDURE GetRest;
VAR
incre: Byte;
BEGIN
s1 := c;
p1 := i;
incre := 0;
IF ((i <> 1) AND (s[i - 1] = '!')) THEN
BEGIN
s1 := '!' + s1;
Dec(p1);
END;
IF (c IN ['N','C','E','F','G','I','J','M','O','R','V','Z']) THEN
BEGIN
s1 := s1 + s[i + 1];
Inc(i);
IF c IN ['N'] THEN
WHILE s[i + 1 + incre] IN ['0'..'9'] DO
BEGIN
Inc (incre);
s1 := s1 + s[i +1 +incre];
END;
END
ELSE
BEGIN
j := i + 1;
WHILE (j <= Length(s)) AND (s[j] IN ['0'..'9']) DO
BEGIN
s1 := s1 + s[j];
Inc(j);
END;
i := (j - 1);
END;
p2 := i;
END;
FUNCTION ArgStat(s: AStr): Boolean;
VAR
VS: AStr;
c: Char;
DayOfWeek: Byte;
RecNum1,
RecNum,
VSI: Integer;
Hour,
Minute,
Second,
Sec100: Word;
BoolState,
ACS: Boolean;
BEGIN
BoolState := (s[1] <> '!');
IF (NOT BoolState) THEN
s := Copy(s,2,(Length(s) - 1));
VS := Copy(s,2,(Length(s) - 1));
VSI := StrToInt(VS);
CASE s[1] OF
'A' : ACS := (AgeUser(User.BirthDate) >= VSI);
'B' : ACS := ((ActualSpeed >= (VSI * 100)) AND (VSI > 0)) OR (ComPortSpeed = 0);
'C' : BEGIN
ACS := (CurrentConf = VS);
C := VS[1];
IF (NOT ConfSystem) AND (C IN ConfKeys) THEN
BEGIN
IF FindConference(C,Conference) THEN
ACS := AACS1(ThisUser,UserNum,Conference.ACS)
ELSE
ACS := FALSE;
END;
END;
'D' : ACS := (User.DSL >= VSI) OR (TempSysOp);
'E' : CASE UpCase(VS[1]) OF
'A' : ACS := OkANSI;
'N' : ACS := NOT (OkANSI OR OkAvatar OR OkVT100);
'V' : ACS := OkAvatar;
'R' : ACS := OkRIP;
'1' : ACS := OkVT100;
END;
'F' : ACS := (UpCase(VS[1]) IN User.AR);
'G' : ACS := (User.Sex = UpCase(VS[1]));
'H' : BEGIN
GetTime(Hour,Minute,Second,Sec100);
ACS := (Hour = VSI);
END;
'I' : ACS := IsInvisible;
'J' : ACS := (Novice IN User.Flags);
'K' : ACS := (ReadMsgArea = VSI);
'L' : ACS := (ReadFileArea = VSI);
'M' : ACS := (UnVotedTopics = 0);
'N' : ACS := (ThisNode = VSI);
'O' : ACS := SysOpAvailable;
'P' : ACS := ((User.lCredit - User.Debit) >= VSI);
'R' : ACS := (TACCH(UpCase(VS[1])) IN User.Flags);
'S' : ACS := (User.SL >= VSI) OR (TempSysOp);
'T' : ACS := (NSL DIV 60 >= VSI);
'U' : ACS := (UNum = VSI);
'V' : BEGIN
Reset(ValidationFile);
RecNum1 := -1;
RecNum := 1;
WHILE (RecNum <= NumValKeys) AND (RecNum1 = -1) DO
BEGIN
Seek(ValidationFile,(RecNum - 1));
Read(ValidationFile,Validation);
IF (Validation.Key = '!') THEN
RecNum1 := RecNum;
Inc(RecNum);
END;
Close(ValidationFile);
ACS := (RecNum1 <> -1) AND (User.SL > Validation.NewSL);
END;
'W' : BEGIN
GetDayOfWeek(DayOfWeek);
ACS := (DayOfWeek = Ord(s[2]) - 48);
END;
'X' : ACS := (((User.Expiration DIV 86400) - (GetPackDateTime DIV 86400)) <= VSI) AND (User.Expiration > 0);
'Y' : ACS := (Timer DIV 60 >= VSI);
'Z' : IF (FNoPostRatio IN User.Flags) THEN
ACS := TRUE
ELSE IF (General.PostRatio[User.SL] > 0) AND (User.LoggedOn > 100 / General.PostRatio[User.SL]) THEN
ACS := ((User.MsgPost / User.LoggedOn * 100) >= General.PostRatio[User.SL])
ELSE
ACS := TRUE;
END;
IF (NOT BoolState) THEN
ACS := NOT ACS;
ArgStat := ACS;
END;
BEGIN
i := 0;
s := AllCaps(s);
WHILE (i < Length(s)) DO
BEGIN
Inc(i);
c := s[i];
IF (c IN ['A'..'Z']) AND (i <> Length(s)) THEN
BEGIN
GetRest;
b := ArgStat(s1);
Delete(s,p1,Length(s1));
IF (b) THEN
s2 := '^'
ELSE
s2 := '%';
Insert(s2,s,p1);
Dec(i,(Length(s1) - 1));
END;
END;
s := '(' + s + ')';
WHILE (Pos('&', s) <> 0) DO
Delete(s,Pos('&',s),1);
WHILE (Pos('^^', s) <> 0) DO
Delete(s,Pos('^^',s),1);
WHILE (Pos('(', s) <> 0) DO
BEGIN
i := 1;
WHILE ((s[i] <> ')') AND (i <= Length(s))) DO
BEGIN
IF (s[i] = '(') THEN
p1 := i;
Inc(i);
END;
p2 := i;
s1 := Copy(s,(p1 + 1),((p2 - p1) - 1));
WHILE (Pos('|',s1) <> 0) DO
BEGIN
i := Pos('|',s1);
c1 := s1[i - 1];
c2 := s1[i + 1];
s2 := '%';
IF ((c1 IN ['%','^']) AND (c2 IN ['%','^'])) THEN
BEGIN
IF ((c1 = '^') OR (c2 = '^')) THEN
s2 := '^';
Delete(s1,(i - 1),3);
Insert(s2,s1,(i - 1));
END
ELSE
Delete(s1,i,1);
END;
WHILE (Pos('%%',s1) <> 0) DO
Delete(s1,Pos('%%',s1),1); {leave only "%"}
WHILE (Pos('^^', s1) <> 0) DO
Delete(s1,Pos('^^',s1),1); {leave only "^"}
WHILE (Pos('%^', s1) <> 0) DO
Delete(s1,Pos('%^',s1)+1,1); {leave only "%"}
WHILE (Pos('^%', s1) <> 0) DO
Delete(s1,Pos('^%',s1),1); {leave only "%"}
Delete(s,p1,((p2 - p1) + 1));
Insert(s1,s,p1);
END;
AACS1 := (Pos('%',s) = 0);
END;
FUNCTION AACS(s: ACString): Boolean;
BEGIN
AACS := AACS1(ThisUser,UserNum,s);
END;
PROCEDURE LoadNode(NodeNumber: Byte);
BEGIN
IF (General.MultiNode) THEN
BEGIN
Reset(NodeFile);
IF (NodeNumber >= 1) AND (NodeNumber <= FileSize(NodeFile)) AND (IOResult = 0) THEN
BEGIN
Seek(NodeFile,(NodeNumber - 1));
Read(NodeFile,NodeR);
END;
Close(NodeFile);
LastError := IOResult;
END;
END;
PROCEDURE Update_Node(NActivityDesc: AStr; SaveVars: Boolean);
BEGIN
IF (General.MultiNode) THEN
BEGIN
LoadNode(ThisNode);
IF (SaveVars) THEN
BEGIN
SaveNDescription := NodeR.ActivityDesc;
NodeR.ActivityDesc := NActivityDesc
END
ELSE
NodeR.ActivityDesc := SaveNDescription;
(*
IF (UserOn) THEN
BEGIN
*)
NodeR.User := UserNum;
NodeR.UserName := ThisUser.Name;
NodeR.Sex := ThisUser.Sex;
NodeR.Age := AgeUser(ThisUser.BirthDate);
NodeR.CityState := ThisUser.CityState;
NodeR.LogonTime := TimeOn;
NodeR.Channel := ChatChannel;
(*
END;
*)
SaveNode(ThisNode);
END;
END;
FUNCTION MaxChatRec: LongInt;
VAR
DirInfo1: SearchRec;
BEGIN
FindFirst(General.TempPath+'MSG'+IntToStr(ThisNode)+'.TMP',AnyFile,DirInfo1);
IF (DOSError = 0) THEN
MaxChatRec := DirInfo1.Size
ELSE
MaxChatRec := 0;
END;
FUNCTION MaxNodes: Byte;
VAR
DirInfo1: SearchRec;
BEGIN
FindFirst(General.DataPath+'MULTNODE.DAT',AnyFile,DirInfo1);
IF (DOSError = 0) THEN
MaxNodes := (DirInfo1.Size DIV SizeOf(NodeRecordType))
ELSE
MaxNodes := 0;
END;
PROCEDURE SaveNode(NodeNumber: Byte);
BEGIN
IF (General.MultiNode) THEN
BEGIN
Reset(NodeFile);
IF (NodeNumber >= 1) AND (NodeNumber <= FileSize(NodeFile)) AND (IOResult = 0) THEN
BEGIN
Seek(NodeFile,(NodeNumber - 1));
Write(NodeFile,NodeR);
END;
Close(NodeFile);
LastError := IOResult;
END;
END;
PROCEDURE LoadURec(VAR User: UserRecordType; UserNumber: Integer);
VAR
FO: Boolean;
BEGIN
FO := (FileRec(UserFile).Mode <> FMClosed);
IF (NOT FO) THEN
BEGIN
Reset(UserFile);
IF (IOResult <> 0) THEN
BEGIN
SysOpLog('Error opening USERS.DAT.');
Exit;
END;
END;
IF (UserNumber <> UserNum) OR (NOT UserOn) THEN
BEGIN
Seek(UserFile,UserNumber);
Read(UserFile,User);
END
ELSE
User := ThisUser;
IF (NOT FO) THEN
Close(UserFile);
LastError := IOResult;
END;
PROCEDURE SaveURec(User: UserRecordType; UserNumber: Integer);
VAR
FO: Boolean;
NodeNumber: Byte;
BEGIN
FO := (FileRec(UserFile).Mode <> FMClosed);
IF (NOT FO) THEN
BEGIN
Reset(UserFile);
IF (IOResult <> 0) THEN
BEGIN
SysOpLog('Error opening USERS.DAT.');
Exit;
END;
END;
Seek(UserFile,UserNumber);
Write(UserFile,User);
IF (NOT FO) THEN
Close(UserFile);
IF (UserNumber = UserNum) THEN
ThisUser := User
ELSE
BEGIN
IF (General.MultiNode) THEN
BEGIN
NodeNumber := OnNode(UserNumber);
IF (NodeNumber > 0) THEN
BEGIN
LoadNode(NodeNumber);
Include(NodeR.Status,NUpdate);
SaveNode(NodeNumber);
END;
END;
END;
LastError := IOResult;
END;
FUNCTION MaxUsers: Integer;
VAR
DirInfo1: SearchRec;
BEGIN
FindFirst(General.DataPath+'USERS.DAT',AnyFile,DirInfo1);
IF (DOSError = 0) THEN
MaxUsers := (DirInfo1.Size DIV SizeOf(UserRecordType))
ELSE
MaxUsers := 0;
END;
FUNCTION MaxIDXRec: Integer;
VAR
DirInfo1: SearchRec;
BEGIN
FindFirst(General.DataPath+'USERS.IDX',AnyFile,DirInfo1);
IF (DOSError = 0) THEN
MaxIDXRec := (DirInfo1.Size DIV SizeOf(UserIDXRec))
ELSE
MaxIDXRec := 0;
IF (NOT UserOn) AND (DirInfo1.Size MOD SizeOf(UserIDXRec) <> 0) THEN
MaxIDXRec := -1; { UserOn is so it'll only show during boot up }
END;
FUNCTION HiMsg: Word;
VAR
DirInfo1: SearchRec;
BEGIN
FindFirst(General.MsgPath+MemMsgArea.FileName+'.HDR',AnyFile,DirInfo1);
IF (DOSError = 0) THEN
HiMsg := (DirInfo1.Size DIV SizeOf(MHeaderRec))
ELSE
HiMsg := 0;
END;
PROCEDURE ScanInput(VAR S: AStr; CONST Allowed: AStr);
VAR
SaveS: AStr;
c: Char;
Counter: Byte;
GotCmd: Boolean;
BEGIN
GotCmd := FALSE;
s := '';
REPEAT
c := UpCase(Char(GetKey));
SaveS := s;
IF ((Pos(c,Allowed) <> 0) AND (s = '')) THEN
BEGIN
GotCmd := TRUE;
s := c;
END
ELSE IF (Pos(c,'0123456789') > 0) OR (c = '-') THEN
BEGIN
IF ((Length(s) < 6) OR ((Pos('-',s) > 0) AND (Length(s) < 11))) THEN
s := s + c;
END
ELSE IF ((s <> '') AND (c = ^H)) THEN
Dec(s[0])
ELSE IF (c = ^X) THEN
BEGIN
FOR Counter := 1 TO Length(s) DO
BackSpace;
s := '';
SaveS := '';
END
ELSE IF (c = #13) THEN
GotCmd := TRUE;
IF (Length(s) < Length(SaveS)) THEN
BackSpace;
IF (Length(s) > Length(SaveS)) THEN
Prompt(s[Length(s)]);
UNTIL (GotCmd) OR (HangUp);
UserColor(1);
NL;
END;
PROCEDURE ScreenDump(CONST FileName: AStr);
VAR
ScreenFile: Text;
TempStr: AStr;
c: Char;
XPos,
YPos: Byte;
VidSeg: Word;
BEGIN
Assign(ScreenFile,FileName);
Append(ScreenFile);
IF (IOResult = 2) THEN
ReWrite(ScreenFile);
IF (MonitorType = 7) THEN
VidSeg := $B000
ELSE
VidSeg := $B800;
FOR YPos := 1 TO MaxDisplayRows DO
BEGIN
TempStr := '';
FOR XPos := 1 TO MaxDisplayCols DO
BEGIN
{$IFDEF MSDOS}
c := Chr(Mem[VidSeg:(160 * (YPos - 1) + 2 * (XPos - 1))]);
{$ENDIF}
{$IFDEF WIN32}
c := SysReadCharAt(XPos - 1, YPos - 1);
{$ENDIF}
IF (c = #0) THEN
c := #32;
IF ((XPos = WhereX) AND (YPos = WhereY)) THEN
c := #178;
TempStr := TempStr + c;
END;
WHILE (TempStr[Length(TempStr)] = ' ') DO
Dec(TempStr[0]);
WriteLn(ScreenFile,TempStr);
END;
Close(ScreenFile);
LastError := IOResult;
END;
PROCEDURE InputPath(CONST DisplayStr: AStr; VAR DirPath: Str40; CreateDir,AllowExit: Boolean; VAR Changed: Boolean);
VAR
TempDirPath: Str40;
CurDir: PathStr;
Counter: Byte;
BEGIN
REPEAT
TempDirPath := DirPath;
Changed := FALSE;
InputWN1(DisplayStr,TempDirPath,39,[UpperOnly,InterActiveEdit],Changed);
TempDirPath := SQOutSp(TempDirPath);
IF (Length(TempDirPath) = 1) THEN
TempDirPath := TempDirPath + ':\'
ELSE IF (Length(TempDirPath) = 2) AND (TempDirPath[2] = ':') THEN
TempDirPath := TempDirPath + '\';
IF (AllowExit) AND (TempDirPath = '') THEN
BEGIN
NL;
Print('Aborted!');
END
ELSE IF (TempDirPath = '') THEN
BEGIN
NL;
Print('^7A valid path must be specified!^1');
END
ELSE IF (NOT (TempDirPath[1] IN ['A'..'Z'])) OR (Length(TempDirPath) < 3) OR
(NOT (TempDirPath[2] = ':')) OR (NOT (TempDirPath[3] = '\')) THEN
BEGIN
NL;
Print('^7Invalid drive specification: "'+Copy(TempDirPath,1,3)+'"^1');
TempDirPath := '';
END
ELSE
BEGIN
GetDir(0,CurDir);
ChDir(TempDirPath[1]+':');
IF (IOResult <> 0) THEN
BEGIN
NL;
Print('^7Drive does not exist: "'+Copy(TempDirPath,1,3)+'"^1');
TempDirPath := '';
END
ELSE
BEGIN
ChDir(CurDir);
IF (CreateDir) THEN
BEGIN
TempDirPath := BSlash(TempDirPath,TRUE);
IF (Length(TempDirPath) > 3) AND (NOT ExistDir(TempDirPath)) THEN
BEGIN
NL;
IF PYNQ('Directory does not exist, create it? ',0,FALSE) THEN
BEGIN
Counter := 2;
WHILE (Counter <= Length(TempDirPath)) DO
BEGIN
IF (TempDirPath[Counter] = '\') THEN
BEGIN
IF (TempDirPath[Counter - 1] <> ':') THEN
BEGIN
IF (NOT ExistDir(Copy(TempDirPath,1,(Counter - 1)))) THEN
BEGIN
MkDir(Copy(TempDirPath,1,(Counter - 1)));
LastError := IOResult;
IF (LastError <> 0) THEN
BEGIN
NL;
Print('Error creating directory: '+Copy(TempDirPath,1,(Counter - 1)));
SysOpLog('^7Error creating directory: '+Copy(TempDirPath,1,(Counter - 1)));
TempDirPath := '';
END;
END;
END;
END;
Inc(Counter);
END;
END;
END;
END;
END;
END;
UNTIL (TempDirPath <> '') OR (AllowExit) OR (HangUp);
IF (TempDirPath <> '') THEN
TempDirPath := BSlash(TempDirPath,TRUE);
IF (TempDirPath <> DirPath) THEN
Changed := TRUE;
DirPath := TempDirPath;
END;
FUNCTION OnNode(UserNumber: Integer): Byte;
VAR
NodeNumber: Byte;
BEGIN
OnNode := 0;
IF (General.MultiNode) AND (UserNumber > 0) THEN
FOR NodeNumber := 1 TO MaxNodes DO
BEGIN
LoadNode(NodeNumber);
IF (NodeR.User = UserNumber) THEN
BEGIN
OnNode := NodeNumber;
Exit;
END;
END;
END;
PROCEDURE PurgeDir(s: AStr; SubDirs: Boolean);
VAR
(*
DirInfo1: SearchRec;
*)
odir: STRING[80];
BEGIN
s := FExpand(s);
WHILE (s[Length(s)] = '\') DO
Dec(s[0]);
GetDir(ExtractDriveNumber(s),odir);
ChDir(s);
IF (IOResult <> 0) THEN
BEGIN
ChDir(odir);
Exit;
END;
FindFirst('*.*',AnyFile - Directory - VolumeID,DirInfo); (* Directory & VolumnID added *)
WHILE (DOSError = 0) DO
BEGIN
Kill(FExpand(DirInfo.Name));
FindNext(DirInfo);
END;
ChDir(odir);
IF (SubDirs) THEN
RmDir(s);
LastError := IOResult;
ChDir(StartDir);
END;
FUNCTION StripName(InString: STRING): STRING;
VAR
StrLen: Byte;
BEGIN
StrLen := Length(InString);
WHILE (StrLen > 0) AND (Pos(InString[StrLen],':\/') = 0) DO
Dec(StrLen);
Delete(InString,1,StrLen);
StripName := InString;
END;
PROCEDURE Star(InString: AStr);
BEGIN
IF (OkANSI OR OkAvatar) THEN
Prompt('^4<> ')
ELSE
Prompt('* ');
IF (InString[Length(InString)] = #29) THEN
Dec(InString[0])
ELSE
InString := InString + ^M^J;
Prompt('^3'+InString+'^1');
END;
FUNCTION ctp(t,b: LongInt): STRING;
VAR
s: AStr;
n: LongInt;
BEGIN
IF ((t = 0) OR (b = 0)) THEN
n := 0
ELSE
n := (t * 100) DIV b;
Str(n:6,s);
ctp := s;
END;
FUNCTION CInKey: Char;
BEGIN
IF (NOT LocalIOOnly) AND (NOT Com_IsRecv_Empty) THEN
CInKey := Com_Recv
ELSE
CInKey := #0;
END;
PROCEDURE Com_Send_Str(CONST InString: AStr);
VAR
Counter: Byte;
BEGIN
FOR Counter := 1 TO Length(InString) DO
CASE InString[Counter] OF
'~' : Delay(250);
'|' : BEGIN
Com_Send(^M);
IF (InWFCMenu) THEN
WriteWFC(^M);
END;
'^' : BEGIN
DTR(FALSE);
Delay(250);
DTR(TRUE);
END;
ELSE
BEGIN
Com_Send(InString[Counter]);
Delay(2);
IF (InWFCMenu) THEN
WriteWFC(InString[Counter]);
END;
END;
END;
PROCEDURE DoTelnetHangUp(ShowIt: Boolean);
BEGIN
IF (NOT LocalIOOnly) THEN
BEGIN
IF (ShowIt) AND (NOT BlankMenuNow) THEN
BEGIN
TextColor(15);
TextBackGround(1);
GotoXY(32,17);
Prt('Hanging up node..');
END;
Com_Flush_Recv;
DTR(FALSE);
END;
IF (ShowIt) AND (SysOpOn) AND (NOT BlankMenuNow) THEN
BEGIN
TextColor(15);
TextBackGround(1);
GotoXY(1,17);
ClrEOL;
END;
END;
PROCEDURE dophoneHangup(ShowIt: Boolean);
VAR
c: Char;
Try: Integer;
SaveTimer: LongInt;
BEGIN
IF (NOT LocalIOOnly) THEN
BEGIN
IF (ShowIt) AND (NOT BlankMenuNow) THEN
BEGIN
TextColor(15);
TextBackGround(1);
GotoXY(32,17);
Write('Hanging up phone...');
END;
Try := 0;
WHILE (Try < 3) AND (NOT KeyPressed) DO
BEGIN
Com_Flush_Recv;
Com_Send_Str(Liner.HangUp);
SaveTimer := Timer;
WHILE (ABS(Timer - SaveTimer) <= 2) AND (Com_Carrier) DO
BEGIN
c := CInKey;
IF (c > #0) AND (InWFCMenu) THEN
WriteWFC(c);
END;
Inc(Try);
END;
END;
IF (ShowIt) AND (SysOpOn) AND (NOT BlankMenuNow) THEN
BEGIN
TextColor(15);
TextBackGround(1);
GotoXY(1,17);
ClrEOL;
END;
END;
PROCEDURE DoPhoneOffHook(ShowIt: Boolean);
VAR
TempStr: AStr;
c: Char;
Done: Boolean;
SaveTimer: LongInt;
BEGIN
IF (ShowIt) AND (NOT BlankMenuNow) AND (SysOpOn) THEN
BEGIN
TextColor(15);
TextBackGround(1);
GotoXY(33,17);
Write('Phone off hook');
END;
Com_Flush_Recv;
Com_Send_Str(Liner.OffHook);
SaveTimer := Timer;
REPEAT
c := CInKey;
IF (c > #0) THEN
BEGIN
IF (InWFCMenu) THEN
WriteWFC(c);
IF (Length(TempStr) >= 160) THEN
Delete(TempStr,1,120);
TempStr := TempStr + c;
IF (Pos(Liner.OK,TempStr) > 0) THEN
Done := TRUE;
END;
UNTIL (ABS(Timer - SaveTimer) > 2) OR (Done) OR (KeyPressed);
Com_Flush_Recv;
END;
PROCEDURE PauseScr(IsCont: Boolean);
VAR
Cmd: Char;
SaveCurCo,
Counter: Byte;
SaveMCIAllowed: Boolean;
BEGIN
SaveCurCo := CurrentColor;
SaveMCIAllowed := MCIAllowed;
MCIAllowed := TRUE;
{$IFDEF MSDOS}
NoSound;
{$ENDIF}
IF (NOT AllowContinue) AND NOT (PrintingFile AND AllowAbort) THEN
IsCont := FALSE;
IF (IsCont) THEN
{ Prompt(FString.Continue) }
lRGLngStr(44,FALSE)
ELSE
BEGIN
IF NOT (PauseIsNull) THEN
{ Prompt({FString.lPause); }
lRGLngStr(5,FALSE);
END;
LIL := 1;
IF (IsCont) THEN
BEGIN
REPEAT
Cmd := UpCase(Char(GetKey));
CASE Cmd OF
'C' : IF (IsCont) THEN
TempPause := FALSE;
'N' : Abort := TRUE;
END;
UNTIL (Cmd IN ['Y','N','Q','C',^M]) OR (HangUp);
END
ELSE
Cmd := Char(GetKey);
IF (IsCont) THEN
FOR Counter := 1 TO LennMCI(lRGLngStr(44,TRUE){FString.Continue}) DO
BackSpace
ELSE
FOR Counter := 1 TO LennMCI(lRGLNGStr(5,TRUE){FString.lPause}) DO
BackSpace;
IF (Abort) THEN
NL;
IF (NOT HangUp) THEN
SetC(SaveCurCo);
MCIAllowed := SaveMCIAllowed;
END;
FUNCTION SearchUser(Uname: Str36; RealNameOK: Boolean): Integer;
VAR
UserIDX: UserIDXRec;
Current: Integer;
Done: Boolean;
BEGIN
SearchUser := 0;
Reset(UserIDXFile);
IF (IOResult <> 0) THEN
BEGIN
SysOpLog('Error opening USERS.IDX.');
Exit;
END;
WHILE (Uname[Length(Uname)] = ' ') DO
Dec(Uname[0]);
Uname := AllCaps(Uname);
Current := 0;
Done := FALSE;
IF (FileSize(UserIDXFile) > 0) THEN
REPEAT
Seek(UserIDXFile,Current);
Read(UserIDXFile,UserIDX);
IF (Uname < UserIDX.Name) THEN
Current := UserIDX.Left
ELSE IF (Uname > UserIDX.Name) THEN
Current := UserIDX.Right
ELSE
Done := TRUE;
UNTIL (Current = -1) OR (Done);
Close(UserIDXFile);
IF (Done) AND (RealNameOK OR NOT UserIDX.RealName) AND (NOT UserIDX.Deleted) THEN
SearchUser := UserIDX.Number;
LastError := IOResult;
END;
FUNCTION Plural(InString: STRING; Number: Byte): STRING;
BEGIN
IF (Number <> 1) THEN
Plural := InString + 's'
ELSE
Plural := InString;
END;
FUNCTION FormattedTime(TimeUsed: LongInt): STRING;
VAR
s: AStr;
BEGIN
s := '';
IF (TimeUsed > 3600) THEN
BEGIN
s := IntToStr(TimeUsed DIV 3600)+' '+Plural('Hour',TimeUsed DIV 3600) + ' ';
TimeUsed := (TimeUsed MOD 3600);
END;
IF (TimeUsed > 60) THEN
BEGIN
s := s + IntToStr(TimeUsed DIV 60)+' '+Plural('Minute',TimeUsed DIV 60) + ' ';
TimeUsed := (TimeUsed MOD 60);
END;
IF (TimeUsed > 0) THEN
s := s + IntToStr(TimeUsed)+' '+Plural('Second',TimeUsed);
IF (s = '') THEN
s := 'no time';
WHILE (s[Length(s)] = ' ') DO
Dec(s[0]);
FormattedTime := s;
END;
FUNCTION FunctionalMCI(CONST S: AStr; FileName,InternalFileName: AStr): STRING;
VAR
Temp: STRING;
Add: AStr;
Index: Byte;
BEGIN
Temp := '';
FOR Index := 1 TO Length(S) DO
IF (S[Index] = '%') THEN
BEGIN
CASE UpCase(S[Index + 1]) OF
'A' : Add := AOnOff(LocalIOOnly,'0',IntToStr(ActualSpeed));
'B' : Add := IntToStr(ComPortSpeed);
'C' : Add := Liner.Address;
'D' : Add := FunctionalMCI(Protocol.DLFList,'','');
'E' : Add := Liner.IRQ;
'F' : Add := SQOutSp(FileName);
'G' : Add := AOnOff((OkAvatar OR OkANSI),'1','0');
'H' : Add := SockHandle;
'I' : BEGIN
IF (S[Index + 2] = 'P') THEN
BEGIN
Add := ThisUser.CallerID;
Inc(Index,1);
END
ELSE
BEGIN
Add := InternalFileName;
END;
END;
'K' : BEGIN
LoadFileArea(FileArea);
IF (FADirDLPath IN MemFileArea.FAFlags) THEN
Add := MemFileArea.DLPath+MemFileArea.FileName+'.DIR'
ELSE
Add := General.DataPath+MemFileArea.FileName+'.DIR';
END;
'L' : Add := FunctionalMCI(Protocol.TempLog,'','');
'M' : Add := StartDir;
'N' : Add := IntToStr(ThisNode);
'O' : Add := Liner.DoorPath;
'P' : Add := IntToStr(Liner.ComPort);
'R' : Add := ThisUser.RealName;
'T' : Add := IntToStr(NSL DIV 60);
'U' : Add := ThisUser.Name;
'#' : Add := IntToStr(UserNum);
'1' : Add := Copy(Caps(ThisUser.RealName),1,Pos(' ',ThisUser.RealName) - 1);
'2' : IF (Pos(' ', ThisUser.RealName) = 0) THEN
Add := Caps(ThisUser.RealName)
ELSE
Add := Copy(Caps(ThisUser.RealName),Pos(' ',ThisUser.RealName) + 1,255);
ELSE
Add := '%' + S[Index + 1];
END;
Temp := Temp + Add;
Inc(Index);
END
ELSE
Temp := Temp + S[Index];
FunctionalMCI := Temp;
END;
FUNCTION MCI(CONST S: STRING): STRING;
VAR
Temp: STRING;
Add: AStr;
Index: Byte;
I: Integer;
BEGIN
Temp := '';
FOR Index := 1 TO Length(S) DO
IF (S[Index] = '%') AND (Index + 1 < Length(S)) THEN
BEGIN
Add := '%' + S[Index + 1] + S[Index + 2];
WITH ThisUser DO
CASE UpCase(S[Index + 1]) OF
'A' : CASE UpCase(S[Index + 2]) OF
'1' : Add := IntToStr(LowFileArea);
'2' : Add := IntToStr(HighFileArea);
'3' : Add := IntToStr(LowMsgArea);
'4' : Add := IntToStr(HighMsgArea);
'B' : Add := FormatNumber(lCredit - Debit);
'C' : Add := Copy(Ph,1,3);
'D' : Add := Street;
'O' : BEGIN
IF (PrintingFile) OR (Reading_A_Msg) THEN
AllowAbort := FALSE;
Add := '';
END;
END;
'B' : CASE UpCase(S[Index + 2]) OF
'D' : Add := IntToStr(ActualSpeed);
'L' : Add := PHours('Always allowed',General.MinBaudLowTime,General.MinBaudHiTime);
'M' : Add := PHours('Always allowed',General.MinBaudDLLowTime,General.MinBaudDLHiTime);
'N' : Add := General.BBSName;
'P' : Add := General.BBSPhone;
END;
'C' : CASE UpCase(S[Index + 2]) OF
'A' : Add := FormatNumber(General.CallAllow[SL]);
'D' : Add := AOnOff(General.PerCall,'call','day ');
'L' : Add := ^L;
'M' : Add := IntToStr(Msg_On);
'N' : IF FindConference(CurrentConf,Conference) THEN
Add := Conference.Name
ELSE
Add:= '';
'R' : Add := FormatNumber(lCredit);
'S' : Add := PHours('Always allowed',General.lLowTime,General.HiTime);
'T' : Add := CurrentConf;
'+' : BEGIN
Add := '';
CursorOn(TRUE);
END;
'-' : BEGIN
Add := '';
CursorOn(FALSE);
END;
END;
'D' : CASE UpCase(S[Index + 2]) OF
'1'..'3' :
Add := UsrDefStr[Ord(S[Index + 2]) - 48];
'A' : Add := DateStr;
'B' : Add := FormatNumber(Debit);
'D' : Add := FormatNumber(General.DlOneDay[SL]);
'H' : Add := PHours('Always allowed',General.DLLowTime,General.DLHiTime);
'K' : Add := FormatNumber(DK);
'L' : Add := FormatNumber(Downloads);
'S' : Add := IntToStr(DSL);
'T' : BEGIN
IF (Timer > 64800) THEN
Add := 'evening'
ELSE IF (Timer > 43200) THEN
Add := 'afternoon'
ELSE
Add := 'morning'
END;
END;
'E' : CASE UpCase(S[Index + 2]) OF
'D' : Add := AOnOff((Expiration = 0),'Never',ToDate8(PD2Date(Expiration)));
'S' : Add := FormatNumber(EmailSent);
'T' : Add := IntToStr(General.EventWarningTime);
'W' : Add := FormatNumber(Waiting);
'X' : IF (Expiration > 0) THEN
Add := IntToStr((Expiration DIV 86400) - (GetPackDateTime DIV 86400))
ELSE
Add := 'Never';
END;
'F' : CASE UpCase(S[Index + 2]) OF
'#' : Add := IntToStr(CompFileArea(FileArea,0));
'B' : BEGIN
LoadFileArea(FileArea);
Add := MemFileArea.AreaName;
END;
'D' : Add := ToDate8(PD2Date(FirstOn));
'K' : Add := FormatNumber(DiskFree(ExtractDriveNumber(MemFileArea.ULPath)) DIV 1024);
'N' : Add := Copy(RealName,1,(Pos(' ', RealName) - 1));
'P' : Add := FormatNumber(FilePoints);
'S' : Add := AOnOff(NewScanFileArea,'','not ');
'T' : Add := IntToStr(NumFileAreas);
END;
'G' : CASE UpCase(S[Index + 2]) OF
'N' : AOnOff((Sex = 'M'),'Mr.','Ms.');
END;
'H' : CASE UpCase(S[Index + 2]) OF
'1' : Add := CTim(General.lLowTime); (* Verify All CTim *)
'2' : Add := CTim(General.HiTime);
'3' : Add := CTim(General.MinBaudLowTime);
'4' : Add := CTim(General.MinBaudHiTime);
'5' : Add := CTim(General.DLLowTime);
'6' : Add := CTim(General.DLHiTime);
'7' : Add := CTim(General.MinBaudDLLowTime);
'8' : add := CTim(General.MinBaudDLHiTime);
'M' : Add := IntToStr(HiMsg);
END;
'I' : CASE UpCase(S[Index + 2]) OF
'L' : Add := IntToStr(Illegal);
'P' : Add := ThisUser.CallerID;
END;
'K' : CASE UpCase(S[Index + 2]) OF
'D' : Add := FormatNumber(General.DLKOneday[SL]);
'R' : IF (DK > 0) THEN
Str((UK / DK):3:3,Add)
ELSE
Add := '0';
END;
'L' : CASE UpCase(S[Index + 2]) OF
'C' : Add := ToDate8(PD2Date(LastOn));
'F' : Add := ^M^J;
'N' : BEGIN
I := Length(RealName);
WHILE ((RealName[i] <> ' ') AND (i > 1)) DO
Dec(i);
Add := Copy(Caps(RealName),(i + 1),255);
END;
'O' : Add := CityState;
END;
'M' : CASE UpCase(S[Index + 2]) OF
'#' : Add := IntToStr(CompMsgArea(MsgArea,0));
'1' : Add := IntToStr(General.GlobalMenu);
'2' : Add := IntToStr(General.AllStartMenu);
'3' : Add := IntToStr(General.ShuttleLogonMenu);
'4' : Add := IntToStr(General.NewUserInformationMenu);
'5' : Add := IntToStr(General.MessageReadMenu);
'6' : Add := IntToStr(General.FileListingMenu);
'7' : Add := IntToStr(General.MinimumBaud);
'B' : BEGIN
i := ReadMsgArea;
IF (i <> MsgArea) THEN
LoadMsgArea(MsgArea);
Add := MemMsgArea.Name;
END;
'L' : Add := IntToStr(NSL DIV 60);
'N' : Add := ShowOnOff(General.MultiNode);
'O' : Add := IntToStr((GetPackDateTime - TimeOn) DIV 60);
'R' : Add := IntToStr(HiMsg - Msg_On);
'S' : Add := AOnOff(LastReadRecord.NewScan,'','not ');
'T' : Add := IntToStr(NumMsgAreas);
END;
'N' : CASE UpCase(S[Index + 2]) OF
'D' : Add := IntToStr(ThisNode);
'L' : Add := '';
'M' : Add := ShowOnOff(General.NetworkMode);
'R' : IF (Downloads > 0) THEN
Str((Uploads / Downloads):3:3,Add)
ELSE
Add := '0';
END;
'O' : CASE UpCase(S[Index + 2]) OF
'1' : IF (RIP IN SFlags) THEN
Add := 'RIP'
ELSE IF (Avatar IN Flags) THEN
Add := 'Avatar'
ELSE IF (ANSI IN Flags) THEN
Add := 'ANSI'
ELSE IF (VT100 IN Flags) THEN
Add := 'VT-100'
ELSE
Add := 'None';
'2' : Add := IntToStr(LineLen)+'x'+IntToStr(PageLen);
'3' : Add := ShowOnOff(ClsMsg IN SFlags);
'4' : Add := ShowOnOff(FSEditor IN SFlags);
'5' : Add := ShowOnOff(Pause IN Flags);
'6' : Add := ShowOnOff(HotKey IN Flags);
'7' : Add := ShowOnOff(NOT (Novice IN Flags));
'8' : IF (ForUsr > 0) THEN
Add := 'Forwarded - '+IntToStr(ForUsr)
ELSE IF (Nomail IN Flags) THEN
Add := 'Closed'
ELSE
Add := 'Open';
'9' : Add := ShowOnOff(Color IN Flags);
'S' : BEGIN
CASE Tasker OF
None : Add := 'DOS';
DV : Add := 'DV';
Win : Add := 'Windows';
OS2 : Add := 'OS/2';
Win32 : Add := 'Windows 32bit';
Dos5N : Add := 'DOS/N';
END;
END;
END;
'P' : CASE UpCase(S[Index + 2]) OF
'1' : Add := General.MsgPath;
'2' : Add := General.NodePath;
'3' : Add := General.LMultPath;
'4' : Add := General.SysOpPW;
'5' : Add := General.NewUserPW;
'6' : Add := General.MinBaudOverride;
'7' : Add := General.ArcsPath;
'B' : Add := General.BulletPrefix;
'C' : IF (LoggedOn > 0) THEN
Str((MsgPost / LoggedOn) * 100:3:2,Add)
ELSE
Add := '0';
'D' : Add := General.DataPath;
'F' : Add := General.FileAttachPath;
'L' : Add := General.LogsPath;
'M' : Add := General.MiscPath;
'N' : Add := Ph;
'O' : BEGIN
IF (PrintingFile) OR (Reading_A_Msg) THEN
TempPause := FALSE;
Add := '';
END;
'P' : Add := General.ProtPath;
'S' : Add := FormatNumber(MsgPost);
'T' : Add := General.TempPath;
END;
'Q' : CASE UpCase(S[Index + 2]) OF
'D' : Add := IntToStr(NumBatchDLFiles);
'U' : Add := IntToStr(NumBatchULFiles);
END;
'R' : CASE UpCase(S[Index + 2]) OF
'N' : Add := Caps(RealName);
END;
'S' : CASE UpCase(S[Index + 2]) OF
'1' : Add := lRGLngStr(41,TRUE); {FString.UserDefEd[Ord(S[Index + 2]) - 48]; }
'2' : Add := lRGLngStr(42,TRUE); {FString.UserDefEd[Ord(S[Index + 2]) - 48]; }
'3' : Add := lRGLngStr(43,TRUE); {FString.UserDefEd[Ord(S[Index + 2]) - 48]; }
'A' : Add := AOnOff((SysOpAvailable), 'available','unavailable' );
'C' : Add := FormatNumber(General.CallerNum);
'D' : Add := IntToStr(General.TotalDloads);
'L' : Add := IntToStr(SL);
'M' : Add := IntToStr(General.TotalUsage);
'N' : Add := General.SysopName;
'P' : Add := IntToStr(General.TotalPosts);
'U' : Add := IntToStr(General.TotalUloads);
'X' : Add := AOnOff((Sex = 'M'),'Male','Female');
END;
'T' : CASE UpCase(S[Index + 2]) OF
'1' : Add := FormatNumber(General.TimeAllow[SL]);
'A' : Add := FormatNumber(TimeBankAdd);
'B' : Add := FormatNumber(TimeBank);
'C' : Add := FormatNumber(LoggedOn);
'D' : Add := FormatNumber(DLToday);
'G' : Add := GetTagLine;
'I' : Add := TimeStr;
'K' : Add := ConvertBytes(DLKToday * 1024,FALSE);
'L' : Add := CTim(NSL);
'N' : Add := Liner.NodeTelnetURL;
'O' : Add := IntToStr(General.TimeAllow[SL] - TLToday);
'S' : BEGIN
Assign(HistoryFile, General.DataPath+'HISTORY.DAT');
{$I-} Reset(HistoryFile); {$I+}
IF (IOResult <> 0) THEN
BEGIN
Add := 'Error With HISTORY.DAT, Inform ' + General.SysOpName + '!';
END
ELSE
BEGIN
Seek(HistoryFile, (FileSize(HistoryFile)-1));
Read(HistoryFile, HistoryRec);
Add := IntToStr(HistoryRec.Callers);
Close(HistoryFile);
END;
END;
'T' : Add := FormatNumber(TTimeOn);
'U' : Add := IntToStr(General.NumUsers);
END;
'U' : CASE UpCase(S[Index + 2]) OF
'A' : Add := IntToStr(AgeUser(BirthDate));
'B' : Add := ToDate8(PD2Date(BirthDate));
'C' : Add := IntToStr(OnToday);
'F' : Add := FormatNumber(Feedback);
'K' : Add := FormatNumber(UK);
'L' : Add := FormatNumber(Uploads);
'M' : Add := IntToStr(MaxUsers - 1);
'N' : Add := Caps(Name);
'U' : Add := IntToStr(UserNum);
END;
'V' : CASE UpCase(S[Index + 2]) OF
'R' : Add := General.Version;
END;
'Z' : CASE UpCase(S[Index + 2]) OF
'P' : Add := ZipCode;
END;
END;
Temp := Temp + Add;
Inc(Index,2);
END
ELSE
Temp := Temp + S[Index];
MCI := Temp;
END;
PROCEDURE BackErase(Len: Byte);
VAR
Counter: Byte;
BEGIN
IF (OkANSI) OR (OkVT100) THEN
SerialOut(^[+'['+IntToStr(Len)+'D'+^[+'[K')
ELSE IF (OkAvatar) THEN
BEGIN
FOR Counter := 1 TO Len DO
Com_Send(^H);
SerialOut(^V^G);
END
ELSE
FOR Counter := 1 TO Len DO
BEGIN
Com_Send(^H);
Com_Send(' ');
Com_Send(^H);
END;
GotoXY((WhereX - Len),WhereY);
ClrEOL;
END;
FUNCTION DiskKBFree(DrivePath: AStr): LongInt;
VAR
F: TEXT;
{$IFDEF MSDOS}
Regs: Registers;
{$ENDIF}
S,
S1: STRING;
Counter: Integer;
C,
C1,
C2: Comp;
BEGIN
C2 := 0.0; (* RGCMD *)
SwapVectors;
Exec(GetEnv('RGCMD'),' /C DIR '+DrivePath[1]+': > FREE.TXT');
SwapVectors;
IF (EXIST('FREE.TXT')) THEN
BEGIN
Assign(F,'FREE.TXT');
Reset(F);
WHILE NOT EOF(F) DO
BEGIN
ReadLn(F,S);
IF (Pos('bytes free',s) <> 0) THEN
BEGIN
WHILE (S[1] = ' ') DO
Delete(S,1,1);
Delete(S,1,Pos(')',s));
WHILE (S[1] = ' ') DO
Delete(S,1,1);
S := COPY(S,1,Pos(' ',S) - 1);
S1 := '';
FOR Counter := 1 TO Length(S) DO
IF (S[Counter] <> ',') THEN
S1 := S1 + S[Counter];
END;
END;
Close(F);
Erase(F);
Val(S1,C2,Counter);
END
ELSE
BEGIN
{$IFDEF MSDOS}
FillChar(Regs,SizeOf(Regs),#0);
Regs.Ah := $36;
Regs.Dl := ExtractDriveNumber(DrivePath);
Intr($21,Regs);
C := (1.0 * Regs.Ax);
C1 := ((1.0 * Regs.Cx) * C);
C2 := ((1.0 * Regs.Bx) * C1);
{$ENDIF}
{$IFDEF WIN32}
C2 := DiskFree(ExtractDriveNumber(DrivePath));
{$ENDIF}
END;
DiskKBFree := Round(C2 / 1024.0);
END;
FUNCTION IntToStr(L: LongInt): STRING;
VAR
S: STRING[11];
BEGIN
Str(L,S);
IntToStr := S;
END;
PROCEDURE MyDelay(WaitFor: LongInt);
VAR
CheckMS: LongInt;
BEGIN
CheckMS := (Ticks + WaitFor);
REPEAT
UNTIL (Ticks > CheckMS);
END;
END.