mysticbbs/mystic/bbs_general.pas

1748 lines
48 KiB
ObjectPascal

Unit bbs_General;
// ====================================================================
// Mystic BBS Software Copyright 1997-2013 By James Coyle
// ====================================================================
//
// This file is part of Mystic BBS.
//
// Mystic BBS is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Mystic BBS is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Mystic BBS. If not, see <http://www.gnu.org/licenses/>.
//
// ====================================================================
{$I M_OPS.PAS}
Interface
Uses
m_Strings,
m_DateTime,
{$IFNDEF UNIX}
Windows,
bbs_SysopChat,
{$ENDIF}
BBS_Records,
BBS_Common,
bbs_Edit_ANSI,
bbs_Edit_Line;
Function Editor (Var Lines: SmallInt; MaxLen, MaxLine: SmallInt; Forced: Boolean; Template: String; Var Subj: String) : Boolean;
Procedure Upgrade_User_Level (Now : Boolean; Var U : RecUser; Sec: Byte);
Procedure View_BBS_List (Long: Boolean; Data: String);
Procedure Add_BBS_List (Name : String);
Procedure AutoSig_Edit;
Procedure AutoSig_View;
Procedure ShowUserList (Data: String);
Procedure ShowLastCallers;
Procedure ShowBBSHistory (LastDays: Word);
Procedure ShowOneLiners (Data: String);
Procedure ShowRandomQuote;
Procedure Add_TimeBank;
Procedure Get_TimeBank;
Procedure Add_Booth;
Procedure Voting_Booth (Forced: Boolean; Num: Integer);
Procedure Voting_Result (Data: Integer);
Procedure Voting_Booth_New;
Procedure Voting_Booth_Delete;
Procedure View_Directory (Data: String; ViewType: Byte);
Procedure AnsiViewer (Bar: RecPercent; Data: String);
{$IFNDEF UNIX}
Procedure PageForSysopChat (Forced: Boolean);
{$ENDIF}
Implementation
Uses
DOS,
m_FileIO,
m_QuickSort,
bbs_Core,
BBS_DataBase,
bbs_MsgBase_Ansi,
bbs_NodeInfo;
Function AnsiEditor (Var Lines: SmallInt; WrapPos: Byte; MaxLines: SmallInt; Forced: Boolean; Template: String; Var Subj: String) : Boolean;
Var
Editor : TEditorANSI;
Count : LongInt;
Begin
Editor := TEditorANSI.Create(Pointer(Session), Template);
Editor.Forced := Forced;
Editor.Subject := Subj;
Editor.MaxMsgLines := MaxLines;
Editor.MaxMsgCols := WrapPos;
For Count := 1 to Lines Do
Editor.SetLineText (Count, Session.Msgs.MsgText[Count]);
Result := Editor.Edit;
Subj := Editor.Subject;
If Result Then Begin
For Count := 1 to Editor.LastLine Do
Session.Msgs.MsgText[Count] := Editor.GetLineText(Count);
Lines := Editor.LastLine;
End;
Editor.Free;
End;
Function Editor (Var Lines: SmallInt; MaxLen, MaxLine: SmallInt; Forced: Boolean; Template: String; Var Subj: String) : Boolean;
Begin
If (Session.io.Graphics > 0) and ((Session.User.ThisUser.EditType = 1) or ((Session.User.ThisUser.EditType = 2) and Session.io.GetYN(Session.GetPrompt(106), True))) Then
Editor := AnsiEditor(Lines, MaxLen, MaxLine, Forced, Template, Subj)
Else
Editor := LineEditor(Lines, MaxLen, MaxLine, False, Forced, Subj);
End;
Procedure Upgrade_User_Level (Now: Boolean; Var U: RecUser; Sec: Byte);
Var
Flags : Char;
TempSec : RecSecurity;
Begin
Assign (Session.User.SecurityFile, bbsCfg.DataPath + 'security.dat');
Reset (Session.User.SecurityFile);
Seek (Session.User.SecurityFile, Sec - 1);
Read (Session.User.SecurityFile, TempSec);
Close (Session.User.SecurityFile);
U.Security := Sec;
U.StartMenu := TempSec.StartMenu;
U.TimeLeft := TempSec.Time;
U.Expires := '00/00/00';
U.ExpiresTo := TempSec.ExpiresTo;
If TempSec.Expires > 0 Then
U.Expires := DateJulian2Str(CurDateJulian + TempSec.Expires, 1);
For Flags := 'A' to 'Z' Do
If Ord(Flags) - 64 in TempSec.AF1 Then
U.AF1 := U.AF1 + [Ord(Flags) - 64]
Else
If TempSec.Hard Then
U.AF1 := U.AF1 - [Ord(Flags) - 64];
For Flags := 'A' to 'Z' Do
If Ord(Flags) - 64 in TempSec.AF2 Then
U.AF2 := U.AF2 + [Ord(Flags) - 64]
Else
If TempSec.Hard Then
U.AF2 := U.AF2 - [Ord(Flags) - 64];
If Now Then Session.User.Security := TempSec;
End;
Procedure AutoSig_Edit;
Var
DF : File;
Lines : Integer;
Str : String;
Begin
If bbsCfg.MaxAutoSig = 0 Then Exit;
Assign (DF, bbsCfg.DataPath + 'autosig.dat');
If Session.User.ThisUser.SigLength > 0 Then Begin
Reset (DF, 1);
Seek (DF, Session.User.ThisUser.SigOffset);
For Lines := 1 to Session.User.ThisUser.SigLength Do Begin
BlockRead (DF, Session.Msgs.MsgText[Lines][0], 1);
BlockRead (DF, Session.Msgs.MsgText[Lines][1], Ord(Session.Msgs.MsgText[Lines][0]));
End;
Close (DF);
End Else
Lines := 0;
Str := 'Signature Editor'; {++lang}
If Editor (Lines, 78, bbsCfg.MaxAutoSig, False, fn_tplMsgEdit, Str) Then Begin
{$I-} Reset (DF, 1); {$I+}
If IoResult <> 0 Then ReWrite (DF, 1);
Session.User.ThisUser.SigLength := Lines;
Session.User.ThisUser.SigOffset := FileSize(DF);
Seek (DF, Session.User.ThisUser.SigOffset);
For Lines := 1 to Lines Do
BlockWrite (DF, Session.Msgs.MsgText[Lines][0], Length(Session.Msgs.MsgText[Lines]) + 1);
Close (DF);
End;
End;
Procedure AutoSig_View;
Var
DF : File;
A : Byte;
S : String[79];
Begin
If Session.User.ThisUser.SigLength > 0 Then Begin
Assign (DF, bbsCfg.DataPath + 'autosig.dat');
Reset (DF, 1);
Seek (DF, Session.User.ThisUser.SigOffset);
For A := 1 to Session.User.ThisUser.SigLength Do Begin
BlockRead (DF, S[0], 1);
BlockRead (DF, S[1], Ord(S[0]));
Session.io.OutFullLn (S);
End;
Close (DF);
End Else
Session.io.OutFull (Session.GetPrompt(336));
End;
Procedure ShowRandomQuote;
Var
TF : Text;
TxtBuf : Array[1..2048] of Char;
Total : Integer;
Count : Integer;
Str : String;
Begin
Assign (TF, bbsCfg.DataPath + 'quotes.dat');
SetTextBuf (TF, TxtBuf);
{$I-} Reset (TF); {$I+}
If IoResult <> 0 Then Exit;
Total := 0;
While Not Eof(TF) Do Begin
ReadLn (TF, Str);
If Str[1] = '*' Then Inc(Total);
End;
If Total = 0 Then Begin
Close (TF);
Exit;
End;
Count := Random(Total) + 1;
Total := 0;
Reset (TF);
While Total <> Count Do Begin
ReadLn (TF, Str);
If Str[1] = '*' Then Inc(Total);
End;
While Not Eof(TF) Do Begin
ReadLn (TF, Str);
If Str[1] = '*' Then Break Else Session.io.OutFullLn (Str);
End;
Close (TF);
End;
Function SearchBBS (Str: String; Temp: BBSListRec) : Boolean;
Begin
Str := strUpper(Str);
SearchBBS := Bool_Search(Str, Temp.BBSName) or
Bool_Search(Str, Temp.SysopName) or
Bool_Search(Str, Temp.Software) or
Bool_Search(Str, Temp.Telnet) or
Bool_Search(Str, Temp.Phone) or
Bool_Search(Str, Temp.Location);
End;
Procedure Add_BBS_List (Name : String);
Var
BBSFile : File of BBSListRec;
BBSList : BBSListRec;
Temp : BBSListRec;
Begin
If Name = '' Then Exit;
Session.io.OutFull (Session.GetPrompt(361));
Case Session.io.OneKey ('DTBQ', True) of
'D' : BBSList.cType := 0;
'T' : BBSList.cType := 1;
'B' : BBSList.cType := 2;
'Q' : Exit;
End;
Session.io.OutRawLn('');
If BBSList.cType in [0, 2] Then Begin
Session.io.OutFull (Session.GetPrompt(283));
BBSList.Phone := Session.io.GetInput(15, 15, 12, '');
If BBSList.Phone = '' Then Exit;
End Else
BBSList.Phone := 'None'; //++lang
If BBSList.cType in [1, 2] Then Begin
Session.io.OutFull (Session.GetPrompt(330));
BBSList.Telnet := Session.io.GetInput(40, 40, 11, '');
If BBSList.Telnet = '' Then Exit;
End Else
BBSList.Telnet := 'None'; //++lang
Assign (BBSFile, bbsCfg.DataPath + Name + '.bbi');
{$I-} Reset(BBSFile); {$I+}
If IoResult <> 0 Then ReWrite(BBSFile);
While Not Eof(BBSFile) Do Begin
Read (BBSFile, Temp);
If ((strUpper(BBSList.Phone) = strUpper(Temp.Phone)) and (Temp.Phone <> 'None')) or
((strUpper(BBSList.Telnet) = strUpper(Temp.Telnet)) and (Temp.Telnet <> 'None')) Then Begin
Session.io.OutFullLn(Session.GetPrompt(362));
Close (BBSFile);
Exit;
End;
End;
Close (BBSFile);
Session.io.OutFull (Session.GetPrompt(284));
BBSList.BBSName := Session.io.GetInput(30, 30, 11, '');
Session.io.OutFull (Session.GetPrompt(285));
BBSList.Location := Session.io.GetInput(25, 25, 18, '');
Session.io.OutFull (Session.GetPrompt(286));
BBSList.SysopName := Session.io.GetInput(30, 30, 11, '');
Session.io.OutFull (Session.GetPrompt(287));
BBSList.BaudRate := Session.io.GetInput(6, 6, 11, '');
Session.io.OutFull (Session.GetPrompt(288));
BBSList.Software := Session.io.GetInput(10, 10, 11, '');
If Session.io.GetYN(Session.GetPrompt(290), True) Then Begin
BBSList.Deleted := False;
BBSList.AddedBy := Session.User.ThisUser.Handle;
BBSList.Verified := CurDateDos;
Reset (BBSFile);
Seek (BBSFile, FileSize(BBSFile));
Write (BBSFile, BBSList);
Close (BBSFile);
End;
End;
Procedure View_BBS_List (Long : Boolean; Data : String);
Var
BBSFile : File of BBSListRec;
BBSList : BBSListRec;
Name : String[8];
Str : String;
Search : Boolean;
Begin
Search := False;
If Pos(';', Data) > 0 Then Begin
Name := Copy(Data, 1, Pos(';', Data) - 1);
Search := Pos(';SEARCH', strUpper(Data)) > 0;
End Else
Name := Data;
If Name = '' Then Exit;
FileMode := 66;
Assign (BBSFile, bbsCfg.DataPath + Name + '.bbi');
{$I-} Reset(BBSFile); {$I+}
If IoResult <> 0 Then Begin
Session.io.OutFullLn (Session.GetPrompt(291));
Exit;
End;
If Search Then Begin
Session.io.OutFull (Session.GetPrompt(292));
Str := Session.io.GetInput(30, 30, 11, '');
End;
Session.io.PausePtr := 1;
Session.io.AllowPause := True;
If Long Then
Session.io.OutFullLn (Session.GetPrompt(264))
Else
Session.io.OutFullLn (Session.GetPrompt(260));
While Not EOF(BBSFile) Do Begin
Read (BBSFile, BBSList);
If BBSList.Deleted Then Continue;
If (Search and SearchBBS(Str, BBSList)) or Not Search Then Begin
Session.io.PromptInfo[1] := BBSList.BBSName;
Case BBSList.cType of
0 : Begin
Session.io.PromptInfo[3] := BBSList.Phone;
Session.io.PromptInfo[2] := 'DIALUP'; //++lang
End;
1 : Begin
Session.io.PromptInfo[3] := BBSList.Telnet;
Session.io.PromptInfo[2] := 'TELNET'; //++lang
End;
2 : Begin
Session.io.PromptInfo[3] := BBSList.Telnet;
Session.io.PromptInfo[2] := 'DU/TEL'; //++lang
End;
End;
If (BBSList.cType = 0) and Long Then Session.io.PromptInfo[3] := BBSList.Telnet;
Session.io.PromptInfo[4] := BBSList.Software;
Session.io.PromptInfo[5] := BBSList.Location;
Session.io.PromptInfo[6] := BBSList.SysopName;
Session.io.PromptInfo[7] := BBSList.BaudRate;
Session.io.PromptInfo[8] := BBSList.AddedBy;
Session.io.PromptInfo[9] := BBSList.Phone;
Session.io.PromptInfo[10] := DateDos2Str(BBSList.Verified, Session.User.ThisUser.DateType);
If Long Then Begin
Session.io.OutFullLn (Session.GetPrompt(265));
Session.io.OutFull (Session.GetPrompt(267));
Case Session.io.OneKey('DQV'#13, True) of
'D' : If Session.User.Access(bbsCfg.AcsSysop) or (strUpper(BBSList.AddedBy) = strUpper(Session.User.ThisUser.Handle)) Then Begin
If Session.io.GetYN(Session.GetPrompt(294), False) Then Begin
BBSList.Deleted := True;
Seek (BBSFile, FilePos(BBSFile) - 1);
Write (BBSFile, BBSList);
End;
End Else
Session.io.OutFullLn (Session.GetPrompt(295));
'Q' : Break;
'V' : If Session.io.GetYN(Session.GetPrompt(266), False) Then Begin
BBSList.Verified := CurDateDos;
Seek (BBSFile, FilePos(BBSFile) - 1);
Write (BBSFile, BBSList);
End;
End;
End Else Begin
Session.io.OutFullLn (Session.GetPrompt(261));
If (Session.io.PausePtr >= Session.User.ThisUser.ScreenSize) and (Session.io.AllowPause) Then
Case Session.io.MorePrompt of
'N' : Break;
'C' : Session.io.AllowPause := False;
End;
End;
End;
End;
Close (BBSFile);
If Not Long Then
Session.io.OutFullLn (Session.GetPrompt(262));
End;
Procedure ShowUserList (Data: String);
Var
Total : Integer;
TempUser : RecUser;
Begin
If Data = 'SEARCH' Then Begin
Session.io.OutFull (Session.GetPrompt(32));
Data := Session.io.GetInput (30, 30, 12, '');
End;
Reset (Session.User.UserFile);
Session.io.PausePtr := 1;
Session.io.AllowPause := True;
Session.io.OutFullLn (Session.GetPrompt(29));
Total := 0;
While Not Eof(Session.User.UserFile) Do Begin
Read (Session.User.UserFile, TempUser);
If (TempUser.Flags AND UserDeleted <> 0) and
(TempUser.Flags AND UserQWKNetwork <> 0) Then Continue;
Session.io.PromptInfo[1] := TempUser.Handle;
Session.io.PromptInfo[2] := TempUser.City;
Session.io.PromptInfo[3] := DateDos2Str(TempUser.LastOn, Session.User.ThisUser.DateType);
Session.io.PromptInfo[4] := TempUser.Gender;
Session.io.PromptInfo[5] := strI2S(TempUser.Security);
Session.io.PromptInfo[6] := TempUser.Address;
Session.io.PromptInfo[7] := strI2S(DaysAgo(TempUser.Birthday, 1) DIV 365);
Session.io.PromptInfo[8] := TempUser.Email;
Session.io.PromptInfo[9] := TempUser.UserInfo;
Session.io.PromptInfo[10] := TempUser.OptionData[1];
Session.io.PromptInfo[11] := TempUser.OptionData[2];
Session.io.PromptInfo[12] := TempUser.OptionData[3];
If (Data = '') or (Pos(Data, strUpper(TempUser.Handle)) > 0) Then Begin
Session.io.OutFullLn (Session.GetPrompt(30));
Inc (Total);
If (Session.io.PausePtr >= Session.User.ThisUser.ScreenSize) and (Session.io.AllowPause) Then
Case Session.io.MorePrompt of
'N' : Break;
'C' : Session.io.AllowPause := False;
End;
End;
End;
Close (Session.User.UserFile);
Session.io.PromptInfo[1] := strI2S(Total);
Session.io.OutFull (Session.GetPrompt(31));
End;
Procedure ShowLastCallers;
Begin
Session.io.OutFullLn (Session.GetPrompt(141));
Reset (Session.LastOnFile);
While Not Eof(Session.LastOnFile) Do Begin
Read (Session.LastOnFile, Session.LastOn);
Session.io.PromptInfo[1] := Session.LastOn.Handle;
Session.io.PromptInfo[2] := strI2S(Session.LastOn.Node);
Session.io.PromptInfo[3] := Session.LastOn.City;
Session.io.PromptInfo[4] := DateDos2Str(Session.LastOn.DateTime, Session.User.ThisUser.DateType);
Session.io.PromptInfo[5] := TimeDos2Str(Session.LastOn.DateTime, 1);
Session.io.PromptInfo[7] := strI2S(Session.LastOn.CallNum);
Session.io.PromptInfo[8] := Session.LastOn.Address;
Session.io.PromptInfo[9] := Session.LastOn.UserInfo;
Session.io.PromptInfo[10] := Session.LastOn.EmailAddr;
Session.io.PromptInfo[11] := Session.LastOn.OptionData[1];
Session.io.PromptInfo[12] := Session.LastOn.OptionData[2];
Session.io.PromptInfo[13] := Session.LastOn.OptionData[3];
Session.io.OutFullLn (Session.GetPrompt(142));
End;
Close (Session.LastOnFile);
Session.io.OutFull (Session.GetPrompt(143));
End;
Procedure Add_TimeBank;
Var
A : Integer;
Begin
Session.io.OutFull (Session.GetPrompt(172));
A := strS2I(Session.io.GetInput(4, 4, 11, ''));
If A > 0 Then
If (A < Session.TimeLeft - 4) Then Begin
If (Session.User.Security.MaxTB > 0) and (Session.User.ThisUser.TimeBank + A > Session.User.Security.MaxTB) Then Begin
Session.io.OutFullLn (Session.GetPrompt(209));
Exit;
End;
Inc (Session.User.ThisUser.TimeBank, A);
Session.SetTimeLeft (Session.TimeLeft - A);
End Else
Session.io.OutFullLn (Session.GetPrompt(210));
End;
Procedure Get_TimeBank;
Var
A : Integer;
Begin
Session.io.OutFull (Session.GetPrompt(173));
A := strS2I(Session.io.GetInput(4, 4, 11, ''));
If (A > 0) and (A <= Session.User.ThisUser.TimeBank) Then Begin
Dec (Session.User.ThisUser.TimeBank, A);
Session.SetTimeLeft (Session.TimeLeft + A);
End;
End;
Procedure ShowOneLiners (Data : String);
Const
MaxLines : Byte = 9;
MaxLen : Byte = 75;
MaxField : Byte = 75;
Var
OneLineFile : File of OneLineRec;
OneLine : OneLineRec;
Str : String;
A : Byte;
Begin
A := Pos(';', Data);
If A > 0 Then Begin
MaxLines := strS2I(Copy(Data, 1, A - 1)) - 1;
Delete (Data, 1, A);
A := Pos(';', Data);
MaxLen := strS2I(Copy(Data, 1, A - 1));
MaxField := strS2I(Copy(Data, A + 1, Length(Data)));
End;
FileMode := 66;
Assign (OneLineFile, bbsCfg.DataPath + 'oneliner.dat');
{$I-} Reset (OneLineFile); {$I+}
If IoResult <> 0 Then ReWrite (OneLineFile);
Repeat
Reset (OneLineFile);
Session.io.OutFullLn (Session.GetPrompt(188));
While Not Eof(OneLineFile) Do Begin
Read (OneLineFile, OneLine);
Session.io.PromptInfo[1] := OneLine.Text;
Session.io.PromptInfo[2] := OneLine.From;
Session.io.PromptInfo[3] := OneLine.From[1];
If Pos(' ', OneLine.From) > 0 Then
Session.io.PromptInfo[3] := Session.io.PromptInfo[3] + OneLine.From[Pos(' ', OneLine.From) + 1];
Session.io.OutFullLn (Session.GetPrompt(337));
End;
If Session.io.GetYN(Session.GetPrompt(189), False) Then Begin
Session.io.OutFull (Session.GetPrompt(190));
Str := Session.io.GetInput (MaxField, MaxLen, 11, '');
If Str <> '' Then Begin
If FileSize(OneLineFile) > MaxLines Then
KillRecord (OneLineFile, 1, SizeOf(OneLineRec));
OneLine.Text := Str;
OneLine.From := Session.User.ThisUser.Handle;
Seek (OneLineFile, FileSize(OneLineFile));
Write (OneLineFile, OneLine);
End;
End Else
Break;
Until False;
Close (OneLineFile);
End;
Procedure Add_Booth;
Var
A : Byte;
Begin
If Not Session.io.GetYN (Session.GetPrompt(275), True) Then Exit;
Reset (Session.VoteFile);
If FileSize (Session.VoteFile) = mysMaxVoteQuestion Then Begin
Close (Session.VoteFile);
Session.io.OutFull (Session.GetPrompt(276));
Exit;
End;
Close (Session.VoteFile);
Session.io.OutFull (Session.GetPrompt(277));
Session.Vote.Question := Session.io.GetInput(78, 78, 11, '');
If Session.Vote.Question = '' Then Exit;
Session.io.OutFullLn (Session.GetPrompt(278));
A := 1;
While A <= 15 Do Begin
Session.io.PromptInfo[1] := strI2S(A);
Session.io.OutFull (Session.GetPrompt(279));
Session.Vote.Answer[A].Text := Session.io.GetInput(40, 40, 11, '');
If Session.Vote.Answer[A].Text = '' Then Begin
Dec (A);
Break;
End;
Session.Vote.Answer[A].Votes := 0;
Inc(A);
End;
If A = 0 Then Exit;
Session.Vote.AnsNum := A;
Session.Vote.Votes := 0;
Session.Vote.ACS := '';
Session.Vote.AddACS := 's999';
Session.Vote.ForceACS := 's999';
If Session.io.GetYN(Session.GetPrompt(280), True) Then Session.Vote.AddACS := '';
If Session.io.GetYN(Session.GetPrompt(281), True) Then Begin
Reset (Session.VoteFile);
Seek (Session.VoteFile, FileSize(Session.VoteFile));
Write (Session.VoteFile, Session.Vote);
Close (Session.VoteFile);
End;
End;
{ VOTING BOOTH SHIT }
Function Voting_List : Byte;
Var
Total : Byte;
Begin
Reset (Session.VoteFile);
Session.io.OutFullLn (Session.GetPrompt(241));
Total := 0;
While Not Eof(Session.VoteFile) Do Begin
Read (Session.VoteFile, Session.Vote);
If Session.User.Access(Session.Vote.ACS) Then Begin
Inc (Total);
Session.io.PromptInfo[1] := strI2S(Total);
Session.io.PromptInfo[2] := Session.Vote.Question;
If Session.User.ThisUser.Vote[FilePos(Session.VoteFile)] = 0 Then
Session.io.PromptInfo[3] := '*' //++lang
Else
Session.io.PromptInfo[3] := ' ';
Session.io.OutFullLn (Session.GetPrompt(242));
End;
End;
Close (Session.VoteFile);
If Total = 0 Then Session.io.OutFullLn (Session.GetPrompt(243));
Voting_List := Total;
End;
Procedure Voting_Result (Data : Integer);
Var
A : SmallInt;
P : SmallInt;
Begin
Reset (Session.VoteFile);
If (Data > 0) and (Data <= FileSize(Session.VoteFile)) Then Begin
Seek (Session.VoteFile, Data - 1);
Read (Session.VoteFile, Session.Vote);
Close (Session.VoteFile);
End Else Begin
A := Voting_List;
If A = 0 Then Exit;
Repeat
Session.io.PromptInfo[1] := strI2S(A);
Session.io.OutFull (Session.GetPrompt(263));
P := strS2I(Session.io.GetInput(2, 2, 12, ''));
If P = 0 Then Exit;
If P <= A Then Break;
Until False;
Reset (Session.VoteFile);
A := 0;
Repeat
Read (Session.VoteFile, Session.Vote);
If Session.User.Access(Session.Vote.ACS) Then Inc(A);
Until A = P;
Close (Session.VoteFile);
End;
Session.io.PromptInfo[1] := Session.Vote.Question;
Session.io.PromptInfo[2] := strI2S(Session.Vote.Votes);
Session.io.OutFullLn (Session.GetPrompt(249));
For A := 1 to Session.Vote.AnsNum Do Begin
Session.io.PromptInfo[1] := strI2S(A);
Session.io.PromptInfo[2] := Session.Vote.Answer[A].Text;
Session.io.PromptInfo[3] := strI2S(Session.Vote.Answer[A].Votes);
If Session.Vote.Votes = 0 Then Begin
Session.io.PromptInfo[4] := '0';
Session.io.PromptInfo[5] := '';
End Else Begin
Session.io.PromptInfo[5] := Session.io.DrawPercent(Session.Theme.VotingBar, Session.Vote.Answer[A].Votes, Session.Vote.Votes, P);
Session.io.PromptInfo[4] := strI2S(P);
End;
Session.io.OutFullLn (Session.GetPrompt(250));
End;
Session.io.OutFull (Session.GetPrompt(251));
End;
Procedure Voting_Booth_New;
Var
NewQues : Array[1..mysMaxVoteQuestion] of Boolean;
Pos : Byte;
Begin
Reset (Session.VoteFile);
While Not Eof(Session.VoteFile) Do Begin
Read (Session.VoteFile, Session.Vote);
If Session.User.Access(Session.Vote.ACS) Then
NewQues[FilePos(Session.VoteFile)] := (Session.User.ThisUser.Vote[FilePos(Session.VoteFile)] = 0)
Else
NewQues[FilePos(Session.VoteFile)] := False;
End;
Close (Session.VoteFile);
For Pos := 1 to mysMaxVoteQuestion Do
If NewQues[Pos] Then Voting_Booth (False, Pos);
End;
Procedure Voting_Booth (Forced: Boolean; Num: Integer);
Var
VPos : Byte;
Temp : Byte;
Total : Byte;
Str : String[40];
Begin
If Not Forced And (Num = 0) Then Begin
Total := Voting_List;
If Total = 0 Then Exit;
Repeat
Session.io.PromptInfo[1] := strI2S(Total);
Session.io.OutFull (Session.GetPrompt(244));
Temp := strS2I(Session.io.GetInput(2, 2, 12, ''));
If Temp = 0 Then Exit;
If Temp <= Total Then Break;
Until False;
Total := 0;
Reset (Session.VoteFile);
Repeat
Read (Session.VoteFile, Session.Vote);
If Session.User.Access(Session.Vote.ACS) Then Inc(Total);
Until Total = Temp;
End Else Begin
Reset (Session.VoteFile);
If Num > FileSize(Session.VoteFile) Then Begin
Close (Session.VoteFile);
Exit;
End;
Seek (Session.VoteFile, Num - 1);
Read (Session.VoteFile, Session.Vote);
End;
VPos := FilePos(Session.VoteFile);
Repeat
Session.io.PromptInfo[1] := Session.Vote.Question;
Session.io.OutFullLn (Session.GetPrompt(245));
For Temp := 1 to Session.Vote.AnsNum Do Begin
Session.io.PromptInfo[1] := strI2S(Temp);
Session.io.PromptInfo[2] := Session.Vote.Answer[Temp].Text;
If Session.User.ThisUser.Vote[VPos] = Temp Then
Session.io.PromptInfo[3] := '*' //++lang
Else
Session.io.PromptInfo[3] := ' ';
Session.io.OutFullLn (Session.GetPrompt(246));
End;
If Session.User.Access(Session.Vote.AddACS) and (Session.Vote.AnsNum < 15) Then Begin
Session.io.PromptInfo[1] := strI2S(Session.Vote.AnsNum + 1);
Session.io.PromptInfo[2] := Session.GetPrompt(252);
Session.io.PromptInfo[3] := ' ';
Session.io.OutFullLn (Session.GetPrompt(246));
End;
Session.io.OutFull (Session.GetPrompt(247));
Temp := strS2I(Session.io.GetInput(2, 2, 12, ''));
If (Session.Vote.AnsNum < 15) and Session.User.Access(Session.Vote.AddACS) and (Temp = Succ(Session.Vote.AnsNum)) Then Begin
Session.io.OutFull (Session.GetPrompt(253));
Str := Session.io.GetInput (40, 40, 11, '');
If Str <> '' Then Begin
Inc (Session.Vote.AnsNum);
Session.Vote.Answer[Session.Vote.AnsNum].Text := Str;
Session.Vote.Answer[Session.Vote.AnsNum].Votes := 0;
End;
End;
If (Temp > 0) and (Temp <= Session.Vote.AnsNum) Then Begin
If Session.User.ThisUser.Vote[VPos] <> 0 Then Begin
Dec (Session.Vote.Answer[Session.User.ThisUser.Vote[VPos]].Votes);
Dec (Session.Vote.Votes);
End;
Inc(Session.Vote.Answer[Temp].Votes);
Inc(Session.Vote.Votes);
Session.User.ThisUser.Vote[VPos] := Temp;
Seek (Session.VoteFile, VPos - 1);
Write (Session.VoteFile, Session.Vote);
Break;
End Else
If Forced Then Session.io.OutFull (Session.GetPrompt(254)) Else Break;
Until False;
Close (Session.VoteFile);
If Session.io.GetYN (Session.GetPrompt(248), True) Then Voting_Result(VPos);
End;
Procedure Voting_Booth_Delete;
Var
Max : LongInt;
A : LongInt;
C : LongInt;
Begin
Max := Voting_List;
Session.io.OutFull('|CR|09Delete which question? ');
A := strS2I(Session.io.GetInput(2, 2, 12, ''));
If (A > 0) and (A <= Max) Then Begin
Max := 0;
Reset (Session.VoteFile);
Repeat
Read (Session.VoteFile, Session.Vote);
If Session.User.Access(Session.Vote.ACS) Then Inc(Max);
Until Max = A;
A := FilePos(Session.VoteFile);
Session.io.OutFullLn ('|CR|12Deleting...');
KillRecord (Session.VoteFile, A, SizeOf(VoteRec));
Close (Session.VoteFile);
Reset (Session.User.UserFile);
While Not Eof(Session.User.UserFile) Do Begin
Read (Session.User.UserFile, Session.User.TempUser);
For C := A To 19 Do
Session.User.TempUser.Vote[C] := Session.User.TempUser.Vote[C+1];
Session.User.TempUser.Vote[20] := 0;
Seek (Session.User.UserFile, FilePos(Session.User.UserFile) - 1);
Write (Session.User.UserFile, Session.User.TempUser);
End;
Close (Session.User.UserFile);
For C := A to 19 Do
Session.User.ThisUser.Vote[C] := Session.User.ThisUser.Vote[C+1];
Session.User.ThisUser.Vote[20] := 0;
End;
End;
Procedure ShowBBSHistory (LastDays: Word);
Var
Temp : RecHistory;
Days : Word;
Begin
Assign (Session.HistoryFile, bbsCfg.DataPath + 'history.dat');
{$I-} Reset(Session.HistoryFile); {$I+}
If IoResult <> 0 Then
Session.io.OutFullLn (Session.GetPrompt(454))
Else Begin
If (LastDays > 0) And (FileSize(Session.HistoryFile) >= LastDays) Then
Seek (Session.HistoryFile, FileSize(Session.HistoryFile) - LastDays);
Session.io.AllowPause := True;
Session.io.PausePtr := 1;
Days := 0;
Session.io.OutFullLn (Session.GetPrompt(455));
While Not Eof(Session.HistoryFile) Do Begin
Read (Session.HistoryFile, Temp);
Session.io.PromptInfo[1] := DateDos2Str(Temp.Date, Session.User.ThisUser.DateType);
Session.io.PromptInfo[2] := strI2S(Temp.Calls);
Session.io.PromptInfo[3] := strI2S(Temp.NewUsers);
Session.io.PromptInfo[4] := strI2S(Temp.Posts);
Session.io.PromptInfo[5] := strI2S(Temp.Emails);
Session.io.PromptInfo[6] := strI2S(Temp.Downloads);
Session.io.PromptInfo[7] := strI2S(Temp.DownloadKB);
Session.io.PromptInfo[8] := strI2S(Temp.Uploads);
Session.io.PromptInfo[9] := strI2S(Temp.UploadKB);
Session.io.OutFullLn (Session.GetPrompt(456));
Inc (Days);
If (Session.io.PausePtr >= Session.User.ThisUser.ScreenSize) and (Session.io.AllowPause) Then
Case Session.io.MorePrompt of
'N' : Break;
'C' : Session.io.AllowPause := False;
End;
End;
Close (Session.HistoryFile);
Session.io.PromptInfo[1] := strI2S(Days);
Session.io.OutFullLn (Session.GetPrompt(457));
End;
End;
Function ReadSauceInfo (FN: String; Var Sauce: RecSauceInfo) : Boolean;
Var
DF : File;
Str : String;
Res : LongInt;
Begin
Result := False;
Assign (DF, FN);
{$I-} Reset (DF, 1); {$I+}
If IoResult <> 0 Then Exit;
{$I-} Seek (DF, FileSize(DF) - 130); {$I+}
If IoResult <> 0 Then Begin
Close (DF);
Exit;
End;
BlockRead (DF, Str[1], 130);
Str[0] := #130;
Close (DF);
Res := Pos('SAUCE', Copy(Str, 1, 7));
If Res > 0 Then Begin
Result := True;
Sauce.Title := strReplace(Copy(Str, 7 + Res, 35), #0, #32);
Sauce.Author := strReplace(Copy(Str, 42 + Res, 20), #0, #32);
Sauce.Group := strReplace(Copy(Str, 62 + Res, 20), #0, #32);
End;
End;
Procedure View_Directory (Data: String; ViewType: Byte);
Const
vtMaxList = 1000;
Type
DirRec = Record
Desc : String[160];
Size : LongInt;
Date : LongInt;
IsDir : Boolean;
Title : String[34];
Author : String[19];
Group : String[19];
End;
Var
WinTop : Byte;
WinBot : Byte;
WinSize : Byte;
DirList : Array[1..vtMaxList] of ^DirRec;
DirCount : LongInt = 0;
CurTop : LongInt = 1;
CurBot : LongInt = 1;
CurPos : LongInt = 1;
CurPath : String;
Root : String;
Procedure BuildDirectory (Path: String);
Var
SR : SearchRec;
Count : Word;
Sauce : RecSauceInfo;
Temp : String;
SortLoop : Word;
SortPos : Word;
Sort : TQuickSort;
Begin
For Count := DirCount Downto 1 Do
Dispose(DirList[Count]);
Sort := TQuickSort.Create;
Temp := Session.GetPrompt(473);
DirCount := 0;
For Count := 1 to 2 Do Begin
FindFirst (Path + '*', AnyFile, SR);
While (DosError = 0) And (DirCount < vtMaxList) Do Begin
If (SR.Name = '.') or ((Path = Root) And (SR.Name = '..')) Then Begin
FindNext (SR);
Continue;
End;
If ((Count = 1) And (SR.Attr And Directory = 0)) or
((Count = 2) And (SR.Attr And Directory <> 0)) Then Begin
FindNext(SR);
Continue;
End;
Inc (DirCount);
New (DirList[DirCount]);
DirList[DirCount]^.Desc := SR.Name;
DirList[DirCount]^.Size := SR.Size;
DirList[DirCount]^.Date := SR.Time;
If (SR.Attr And Directory) = 0 Then Begin
DirList[DirCount]^.IsDir := False;
If ReadSauceInfo(Path + SR.Name, Sauce) Then Begin
DirList[DirCount]^.Title := Sauce.Title;
DirList[DirCount]^.Author := Sauce.Author;
DirList[DirCount]^.Group := Sauce.Group;
End Else Begin
DirList[DirCount]^.Title := strWordGet(1, Temp, ';');
DirList[DirCount]^.Author := strWordGet(2, Temp, ';');
DirList[DirCount]^.Group := strWordGet(3, Temp, ';');
End;
End Else
DirList[DirCount]^.IsDir := True;
FindNext (SR);
End;
FindClose (SR);
Case Count of
1 : Begin
SortPos := DirCount;
For SortLoop := 1 to DirCount Do
Sort.Add(strUpper(DirList[SortLoop]^.Desc), LongInt(@DirList[SortLoop]^));
Sort.Sort(1, DirCount, qAscending);
For SortLoop := 1 to DirCount Do
DirList[SortLoop] := Pointer(Sort.Data[SortLoop]^.Ptr);
End;
2 : If SortPos <> DirCount Then Begin
Sort.Clear;
For SortLoop := Succ(SortPos) to DirCount Do
Sort.Add(strUpper(DirList[SortLoop]^.Desc), LongInt(@DirList[SortLoop]^));
Sort.Sort(1, DirCount - SortPos, qAscending);
For SortLoop := 1 to DirCount - SortPos Do
DirList[SortLoop + SortPos] := Pointer(Sort.Data[SortLoop]^.Ptr);
End;
End;
End;
Sort.Free;
End;
Procedure SetBarInfo (BarPos: Word);
Begin
Session.io.PromptInfo[1] := DirList[BarPos]^.Desc;
Session.io.PromptInfo[2] := strComma(DirList[BarPos]^.Size);
Session.io.PromptInfo[3] := DateDos2Str(DirList[BarPos]^.Date, Session.User.ThisUser.DateType);
Session.io.PromptInfo[7] := TimeDos2Str(DirList[BarPos]^.Date, 1);
If DirList[BarPos]^.IsDir Then Begin
Session.io.PromptInfo[4] := '';
Session.io.PromptInfo[5] := '';
Session.io.PromptInfo[6] := '';
End Else Begin
Session.io.PromptInfo[4] := DirList[BarPos]^.Author;
Session.io.PromptInfo[5] := DirList[BarPos]^.Title;
Session.io.PromptInfo[6] := DirList[BarPos]^.Group;
End;
End;
Procedure DrawPage;
Var
Count : SmallInt;
Start : Word;
Begin
Start := CurTop;
For Count := WinTop to WinBot Do Begin
Session.io.AnsiGotoXY(1, Count);
If Start <= DirCount Then Begin
SetBarInfo(Start);
Case DirList[Start]^.IsDir of
False : Session.io.OutFull(Session.GetPrompt(467));
True : Session.io.OutFull(Session.GetPrompt(469));
End;
End Else Begin
Session.io.PromptInfo[1] := '';
Session.io.PromptInfo[2] := '';
Session.io.PromptInfo[3] := '';
Session.io.PromptInfo[4] := '';
Session.io.PromptInfo[5] := '';
Session.io.PromptInfo[6] := '';
Session.io.PromptInfo[7] := '';
Session.io.OutFull(Session.GetPrompt(467));
End;
Inc (Start);
End;
CurBot := Start - 1;
If CurPos > CurBot Then CurPos := CurBot;
Session.io.PromptInfo[1] := Session.io.DrawPercent(Session.Theme.GalleryBar, CurBot, DirCount, Count);
Session.io.PromptInfo[2] := strI2S(Count);
Session.io.OutFull(Session.GetPrompt(472));
End;
Procedure DrawBar (Selected: Boolean);
Begin
SetBarInfo(CurPos);
Session.io.AnsiGotoXY (1, CurPos - CurTop + WinTop);
If Selected Then
Case DirList[CurPos]^.IsDir of
False : Session.io.OutFull(Session.GetPrompt(468));
True : Session.io.OutFull(Session.GetPrompt(470));
End
Else
Case DirList[CurPos]^.IsDir of
False : Session.io.OutFull(Session.GetPrompt(467));
True : Session.io.OutFull(Session.GetPrompt(469));
End;
End;
Procedure UpdatePath;
Var
Temp : String;
Begin
Temp := CurPath;
Delete (Temp, 1, Length(Root) - 1);
If Length(Temp) > 70 Then
Session.io.PromptInfo[1] := '..' + Copy(Temp, (Length(Temp) - 68), 255)
Else
Session.io.PromptInfo[1] := Temp;
Session.io.PromptInfo[2] := strComma(DirCount);
Session.io.OutFull(Session.GetPrompt(471));
End;
Procedure FullReDraw;
Begin
Session.io.OutFile('ansigal', False, 0);
WinTop := Session.io.ScreenInfo[1].Y;
WinBot := Session.io.ScreenInfo[2].Y;
WinSize := WinBot - WinTop + 1;
UpdatePath;
DrawPage;
DrawBar(True);
End;
Function FindCharacter (Ch: Char) : Byte;
Var
Loop : Boolean;
StartPos : Word;
EndPos : Word;
Count : Word;
Begin
Result := 0;
Loop := True;
StartPos := CurPos + 1;
EndPos := DirCount;
If StartPos > DirCount Then StartPos := 1;
Count := StartPos;
While (Count <= EndPos) Do Begin
If UpCase(DirList[Count]^.Desc[1]) = Ch Then Begin
Result := 1;
While Count <> CurPos Do Begin
If CurPos < Count Then Begin
If CurPos < DirCount Then Inc (CurPos);
If CurPos >= CurTop + WinSize Then Begin
Inc (CurTop);
Result := 2;
End;
End Else
If CurPos > Count Then Begin
If CurPos > 1 Then Dec (CurPos);
If CurPos < CurTop Then Begin
Dec (CurTop);
Result := 2;
End;
End;
End;
Break;
End;
If (Count = DirCount) and Loop Then Begin
Count := 0;
StartPos := 1;
EndPos := CurPos - 1;
Loop := False;
End;
Inc (Count);
End;
End;
Var
Ch : Char;
Count : Word;
Speed : Byte;
UseFull : Boolean;
Begin
If Session.io.Graphics = 0 Then Begin
Session.io.OutFullLn(Session.GetPrompt(466));
Exit;
End;
Session.io.AllowArrow := True;
Root := DirSlash(strWordGet(1, Data, ';'));
Speed := strS2I(strWordGet(2, Data, ';'));
UseFull := Not (strUpper(strWordGet(3, Data, ';')) = 'DISPLAY');
CurPath := Root;
If Not DirExists(Root) Then Exit;
BuildDirectory(CurPath);
FullReDraw;
Repeat
Ch := UpCase(Session.io.GetKey);
If Session.io.IsArrow Then Begin
Case Ch of
#71 : If CurPos > 1 Then Begin
CurPos := 1;
CurTop := 1;
DrawPage;
DrawBar(True);
End;
#72 : If CurPos > 1 Then Begin
If CurPos = CurTop Then Begin
Dec (CurTop);
Dec (CurPos);
DrawPage;
DrawBar(True);
End Else Begin
DrawBar(False);
Dec(CurPos);
DrawBar(True);
End;
End;
#73,
#75 : If CurTop - WinSize >= 1 Then Begin
Dec (CurTop, WinSize);
Dec (CurPos, WinSize);
DrawPage;
DrawBar(True);
End Else
If CurPos > 1 Then Begin
CurPos := 1;
CurTop := 1;
DrawPage;
DrawBar(True);
End;
#79 : If CurPos < DirCount Then Begin
CurPos := DirCount;
CurTop := DirCount - WinSize + 1;
If CurTop < 1 Then CurTop := 1;
DrawPage;
DrawBar(True);
End;
#80 : If CurPos < DirCount Then Begin
If CurPos = CurBot Then Begin
Inc (CurTop);
Inc (CurPos);
DrawPage;
DrawBar(True);
End Else Begin
DrawBar(False);
Inc(CurPos);
DrawBar(True);
End;
End;
#77,
#81 : If CurTop + WinSize <= DirCount - WinSize Then Begin
Inc (CurPos, WinSize);
Inc (CurTop, WinSize);
DrawPage;
DrawBar(True);
End Else
If CurPos < DirCount Then Begin
CurPos := DirCount;
CurTop := DirCount - WinSize + 1;
If CurTop < 1 Then CurTop := 1;
DrawPage;
DrawBar(True);
End;
End;
End Else
Case Ch of
#08 : If CurPath <> Root Then Begin
Delete (CurPath, Length(CurPath), 1);
While CurPath[Length(CurPath)] <> PathChar Do
Delete (CurPath, Length(CurPath), 1);
BuildDirectory(CurPath);
CurPos := 1;
CurTop := 1;
UpdatePath;
DrawPage;
DrawBar(True);
End;
#13 : If DirList[CurPos]^.IsDir Then Begin
If DirList[CurPos]^.Desc = '..' Then Begin
Delete (CurPath, Length(CurPath), 1);
While CurPath[Length(CurPath)] <> PathChar Do
Delete (CurPath, Length(CurPath), 1);
End Else
CurPath := CurPath + DirList[CurPos]^.Desc + PathChar;
BuildDirectory(CurPath);
CurPos := 1;
CurTop := 1;
UpdatePath;
DrawPage;
DrawBar(True);
End Else Begin
Session.io.AllowMCI := True;
Session.io.AnsiColor(7);
Session.io.AnsiClear;
If UseFull Then
AnsiViewer (Session.Theme.ViewerBar, 'ansigalv;ansigalh;' + strI2S(Speed) + ';' + CurPath + DirList[CurPos]^.Desc)
Else Begin
Session.io.OutFile (CurPath + DirList[CurPos]^.Desc, False, Speed);
Session.io.PauseScreen;
End;
FullReDraw;
End;
#27 : Break;
'?' : Begin
Session.io.OutFile('ansigalh', False, 0);
FullRedraw;
End;
'!' : If Not DirList[CurPos]^.IsDir Then Begin
Session.io.AnsiColor(7);
Session.io.AnsiGotoXY(1, Session.User.ThisUser.ScreenSize);
If Session.io.GetYN(Session.GetPrompt(474), False) Then
Session.FileBase.SendFile(CurPath + DirList[CurPos]^.Desc);
FullReDraw;
End;
Else
DrawBar(False);
Case FindCharacter(Ch) of
0,
1 : DrawBar(True);
2 : Begin
DrawPage;
DrawBar(True);
End;
End;
End;
Until Session.ShutDown;
Session.io.AnsiColor(7);
Session.io.AnsiGotoXY(1, 24);
For Count := DirCount DownTo 1 Do
Dispose (DirList[Count]);
End;
{$IFNDEF UNIX}
Procedure PageForSysopChat (Forced: Boolean);
Var
Temp : String;
Count : Integer;
Begin
If Forced or ((TimerMinutes DIV 60 >= bbsCfg.ChatStart) and (TimerMinutes DIV 60 <= bbsCfg.ChatEnd)) Then Begin
Session.io.OutFull (Session.GetPrompt(23));
Temp := Session.io.GetInput(50, 50, 11, '');
If Temp = '' Then Exit;
Session.SystemLog('Chat Page: ' + Temp);
UpdateStatusLine (0, ' ' + strPadR(Session.User.ThisUser.Handle, 17, ' ') + ' ' + strPadR(Temp, 40, ' ') + ' ALT+(S)plit (C)Line');
Session.io.OutFull(Session.GetPrompt(24));
For Count := 1 to 10 Do Begin
Session.io.OutFull(Session.GetPrompt(25));
Session.io.BufFlush;
MessageBeep(0);
If Keyboard.KeyPressed Then
If Keyboard.ReadKey = #0 Then Begin
Case Keyboard.ReadKey of
#31 : OpenChat(True);
#46 : OpenChat(False);
End;
Exit;
End;
WaitMS(1000);
End;
End;
UpdateStatusLine (Session.StatusPtr, '');
Session.io.OutFull (Session.GetPrompt(28));
If bbsCfg.ChatFeedback Then
If Session.io.GetYN(Session.GetPrompt(178), False) Then
Session.Msgs.PostMessage (True, '/TO:' + strReplace(bbsCfg.SysopName, ' ', '_') + ' /SUBJ:Chat_Feedback');
End;
{$ENDIF}
Procedure AnsiViewer (Bar: RecPercent; Data: String);
Var
Buf : Array[1..4096] of Char;
BufLen : LongInt;
TopLine : LongInt;
WinSize : LongInt;
Ansi : TMsgBaseAnsi;
AFile : File;
Ch : Char;
FN : String;
Template : String;
HelpFile : String;
Speed : Byte;
Str : String;
Sauce : RecSauceInfo;
Procedure Update;
Var
Per : SmallInt;
Begin
If Session.io.ScreenInfo[3].X <> 0 Then Begin
Session.io.AnsiGotoXY (Session.io.ScreenInfo[3].X, Session.io.ScreenInfo[4].Y);
Session.io.OutRaw (Session.io.DrawPercent(Bar, TopLine + WinSize - 1, Ansi.Lines, Per));
Session.io.AnsiGotoXY (Session.io.ScreenInfo[4].X, Session.io.ScreenInfo[4].Y);
Session.io.AnsiColor (Session.io.Screeninfo[4].A);
Session.io.OutRaw (strPadL(strI2S(Per), 3, ' '));
End;
Ansi.DrawPage (Session.io.ScreenInfo[1].Y, Session.io.ScreenInfo[2].Y, TopLine);
End;
Procedure ReDraw;
Begin
Session.io.AllowArrow := True;
Session.io.ScreenInfo[3].X := 0;
Session.io.OutFile(Template, False, 0);
WinSize := Session.io.ScreenInfo[2].Y - Session.io.ScreenInfo[1].Y + 1;
If strUpper(strWordGet(4, Data, ';')) = 'END' Then Begin
TopLine := Ansi.Lines - WinSize + 1;
If TopLine < 1 Then TopLine := 1;
End Else
TopLine := 1;
Update;
End;
Begin
Template := strWordGet(1, Data, ';');
HelpFile := strWordGet(2, Data, ';');
Speed := strS2I(strWordGet(3, Data, ';'));
FN := strWordGet(4, Data, ';');
If Pos(PathChar, FN) = 0 Then
FN := Session.Theme.TextPath + FN;
If Pos('.', FN) = 0 Then
FN := FN + '.ans';
If Not FileExist(FN) Then Exit;
If ReadSauceInfo(FN, Sauce) Then Begin
Session.io.PromptInfo[2] := Sauce.Title;
Session.io.PromptInfo[3] := Sauce.Author;
Session.io.PromptInfo[4] := Sauce.Group;
End Else Begin
Str := Session.GetPrompt(473);
Session.io.PromptInfo[2] := strWordGet(1, Str, ';');
Session.io.PromptInfo[3] := strWordGet(2, Str, ';');
Session.io.PromptInfo[4] := strWordGet(3, Str, ';');
End;
Session.io.PromptInfo[1] := JustFile(FN);
Ansi := TMsgBaseAnsi.Create(Session, False);
Assign (AFile, FN);
ioReset (AFile, 1, fmReadWrite + fmDenyNone);
While Not Eof(AFile) Do Begin
ioBlockRead (AFile, Buf, SizeOf(Buf), BufLen);
If Ansi.ProcessBuf (Buf, BufLen) Then Break;
End;
Close (AFile);
ReDraw;
While Not Session.ShutDown Do Begin
Ch := UpCase(Session.io.GetKey);
If Session.io.IsArrow Then Begin
Case Ch of
#71 : If TopLine > 1 Then Begin
TopLine := 1;
Update;
End;
#72 : If TopLine > 1 Then Begin
Dec (TopLine);
Update;
End;
#73,
#75 : If TopLine > 1 Then Begin
Dec (TopLine, WinSize);
If TopLine < 1 Then TopLine := 1;
Update;
End;
#79 : If TopLine + WinSize <= Ansi.Lines Then Begin
TopLine := Ansi.Lines - WinSize + 1;
Update;
End;
#80 : If TopLine + WinSize <= Ansi.Lines Then Begin
Inc (TopLine);
Update;
End;
#77,
#81 : If TopLine < Ansi.Lines - WinSize Then Begin
Inc (TopLine, WinSize);
If TopLine + WinSize > Ansi.Lines Then TopLine := Ansi.Lines - WinSize + 1;
Update;
End;
End;
End Else
Case Ch of
'?' : Begin
Session.io.OutFile(HelpFile, True, 0);
If Not Session.io.NoFile Then
ReDraw;
End;
#32 : Begin
Session.io.AnsiColor(7);
Session.io.AnsiClear;
Session.io.OutFile(FN, False, Speed);
Session.io.PauseScreen;
ReDraw;
End;
'P' : If TopLine < Ansi.Lines - WinSize Then Begin
Inc (TopLine, WinSize);
If TopLine + WinSize > Ansi.Lines Then TopLine := Ansi.Lines - WinSize + 1;
Update;
End;
'N',
#13 : If TopLine < Ansi.Lines - WinSize Then Begin
Inc (TopLine, WinSize);
If TopLine + WinSize > Ansi.Lines Then TopLine := Ansi.Lines - WinSize + 1;
Update;
End;
#27 : Break;
End;
End;
Ansi.Free;
Session.io.AnsiGotoXY (1, Session.User.ThisUser.ScreenSize);
End;
End.