{$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: Integer; 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: Integer; BDLFSize, BDLTime: LongInt; BDLFlags: TransferFlagSet; END; BatchULRecordType = RECORD BULFileName: Str12; BULUserNum, BULSection: Integer; BULDescription: Str50; BULVPointer: LongInt; BULVTextSize: Integer; 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 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 INTEGER; 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; 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 } Ticks: LongInt ABSOLUTE $0040:$006C; 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; { 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; 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: Word; InputFlags: InputFlagSet; LowNum,HighNum: Word; VAR Changed: Boolean); PROCEDURE InputWordWOC(S: AStr; VAR W: Word; InputFlags: InputFlagSet; LowNum,HighNum: Word); PROCEDURE InputIntegerWC(S: AStr; VAR I: Integer; InputFlags: InputFlagSet; LowNum,HighNum: Integer; VAR Changed: Boolean); PROCEDURE InputIntegerWOC(S: AStr; VAR I: Integer; 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, SpawnO, SysOp12, Vote; FUNCTION UpdateCRC32(CRC: LongInt; VAR Buffer; Len: Word): LongInt; EXTERNAL; {$L CRC32.OBJ } 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: Word; InputFlags: InputFlagSet; LowNum,HighNum: Word; VAR Changed: Boolean); BEGIN Common3.InputWordWC(S,W,InputFlags,LowNum,HighNum,Changed); END; PROCEDURE InputWordWOC(S: AStr; VAR W: Word; InputFlags: InputFlagSet; LowNum,HighNum: Word); BEGIN Common3.InputWordWOC(S,W,InputFlags,LowNum,HighNum); END; PROCEDURE InputIntegerWC(S: AStr; VAR I: Integer; InputFlags: InputFlagSet; LowNum,HighNum: Integer; VAR Changed: Boolean); BEGIN Common3.InputIntegerWC(S,I,InputFlags,LowNum,HighNum,Changed); END; PROCEDURE InputIntegerWOC(S: AStr; VAR I: Integer; 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; 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; 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 Killme: Pointer ABSOLUTE $0040 :$F000; Tf: Boolean; I: Integer; C: Word; TempTimer: LongInt; BEGIN IF (DieLater) THEN ASM Call Killme END; 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 Sound(500 + (I * 10)); Delay(2); Sound(100 + (I * 10)); Delay(2); NoSound; 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 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; 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; 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; 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 BEGIN Inc(i,2); PauseScr(FALSE) END ELSE IF (UpCase(s[i + 1]) = 'D') THEN IF (UpCase(s[i + 2]) = 'E') THEN BEGIN Inc(i,2); OutKey(' '); OutKey(#8); { guard against +++ } Delay(800); END ELSE IF ((UpCase(s[i + 2]) = 'F') AND (NOT PrintingFile)) THEN 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',0,DirInfo1); IF (DOSError = 0) THEN MaxChatRec := DirInfo1.Size ELSE MaxChatRec := 0; END; FUNCTION MaxNodes: Byte; VAR DirInfo1: SearchRec; BEGIN FindFirst(General.DataPath+'MULTNODE.DAT',0,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',0,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',0,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',0,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 c := Chr(Mem[VidSeg:(160 * (YPos - 1) + 2 * (XPos - 1))]); 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; NoSound; IF (NOT AllowContinue) AND NOT (PrintingFile AND AllowAbort) THEN IsCont := FALSE; IF (IsCont) THEN { Prompt(FString.Continue) } lRGLngStr(44,FALSE) ELSE { Prompt({FString.lPause); } lRGLngStr(5,FALSE); 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); '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 '); 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 '); END; 'N' : CASE UpCase(S[Index + 2]) OF 'D' : Add := IntToStr(ThisNode); '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); 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]; } 'C' : Add := FormatNumber(General.CallerNum); 'L' : Add := IntToStr(SL); 'N' : Add := General.SysopName; '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); 'I' : Add := TimeStr; 'K' : Add := ConvertBytes(DLKToday * 1024,FALSE); 'L' : Add := CTim(NSL); 'N' : Add := Liner.NodeTelnetURL; 'O' : Add := IntToStr(General.TimeAllow[SL] - TLToday); '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; Regs: Registers; 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 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); 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.