From f8a6bd6cb4a19d52c1893631b925faa745657147 Mon Sep 17 00:00:00 2001 From: mysticbbs Date: Wed, 13 Mar 2013 23:56:42 -0400 Subject: [PATCH] Updates --- mystic/bbs_ansi_menuform.pas | 16 +- mystic/bbs_cfg_menuedit.pas | 3 +- mystic/bbs_cfg_theme.pas | 5 +- mystic/bbs_cfg_useredit.pas | 2 + mystic/bbs_common.pas | 72 +++-- mystic/bbs_core.pas | 104 ++++---- mystic/bbs_edit_ansi.pas | 2 +- mystic/bbs_edit_full.pas | 1 + mystic/bbs_edit_line.pas | 19 +- mystic/bbs_general.pas | 77 ++++-- mystic/bbs_io.pas | 39 +-- mystic/bbs_menus.pas | 5 +- mystic/bbs_msgbase.pas | 477 ++++++++++++++++++++-------------- mystic/bbs_msgbase_abs.pas | 9 +- mystic/bbs_msgbase_ansi.pas | 86 +++--- mystic/bbs_msgbase_jam.pas | 61 ++--- mystic/bbs_msgbase_squish.pas | 9 +- mystic/bbs_nodelist.pas | 6 +- mystic/bbs_user.pas | 26 +- mystic/default.txt | 40 ++- mystic/mis.pas | 6 + mystic/mis_client_nntp.pas | 203 ++++++++++++++- mystic/mis_client_pop3.pas | 69 +++-- mystic/mis_client_smtp.pas | 7 +- mystic/mis_common.pas | 1 + mystic/mpl_common.pas | 4 +- mystic/mpl_execute.pas | 9 +- mystic/mpl_types.pas | 2 +- mystic/mutil.ini | 10 +- mystic/mutil_msgpack.pas | 6 +- mystic/mystic.pas | 14 +- mystic/records.pas | 9 +- mystic/todo.pas | 4 + mystic/whatsnew.txt | 206 ++++++++++++++- 34 files changed, 1094 insertions(+), 515 deletions(-) diff --git a/mystic/bbs_ansi_menuform.pas b/mystic/bbs_ansi_menuform.pas index 13740ea..06d7d29 100644 --- a/mystic/bbs_ansi_menuform.pas +++ b/mystic/bbs_ansi_menuform.pas @@ -70,7 +70,6 @@ Type Private Procedure EditPercentBar (Var Bar: RecPercent); Function GetColorAttr (C: Byte) : Byte; - Function DrawAccessFlags (Var Flags: TMenuFormFlagsRec) : String; Procedure EditAccessFlags (Var Flags: TMenuFormFlagsRec); Procedure AddBasic (HK: Char; D: String; X, Y, FX, FY, DS, FS, MS: Byte; I: FormItemType; P: Pointer; H: String); Procedure BarON; @@ -221,19 +220,6 @@ Begin Box.Free; End; -Function TAnsiMenuForm.DrawAccessFlags (Var Flags: TMenuFormFlagsRec) : String; -Var - Str : String; - Ch : Char; -Begin - Str := ''; - - For Ch := 'A' to 'Z' Do - If Ord(Ch) - 64 in Flags Then Str := Str + Ch Else Str := Str + '-'; - - Result := Str; -End; - Procedure TAnsiMenuForm.EditAccessFlags (Var Flags: TMenuFormFlagsRec); Var Box : TAnsiMenuBox; @@ -552,7 +538,7 @@ Begin ItemByte : WriteXY (FieldX, FieldY, cData, strPadR(strI2S(B^), FieldSize, ' ')); ItemWord : WriteXY (FieldX, FieldY, cData, strPadR(strI2S(W^), FieldSize, ' ')); ItemLong : WriteXY (FieldX, FieldY, cData, strPadR(strI2S(L^), FieldSize, ' ')); - ItemToggle : WriteXY (FieldX, FieldY, cData, StrPadR(strWordGet(B^ + 1 - MinNum, Toggle, ' '), FieldSize, ' ')); + ItemToggle : WriteXY (FieldX, FieldY, cData, StrPadR(strReplace(strWordGet(B^ + 1 - MinNum, Toggle, ' '), '_', ' '), FieldSize, ' ')); ItemChar : WriteXY (FieldX, FieldY, cData, C^); ItemAttr : WriteXY (FieldX, FieldY, B^, ' Sample '); ItemFlags : WriteXY (FieldX, FieldY, cData, DrawAccessFlags(F^)); diff --git a/mystic/bbs_cfg_menuedit.pas b/mystic/bbs_cfg_menuedit.pas index 7cd1c0c..2c1eb35 100644 --- a/mystic/bbs_cfg_menuedit.pas +++ b/mystic/bbs_cfg_menuedit.pas @@ -30,7 +30,7 @@ Type End; Const - Num_Cmds = 101; + Num_Cmds = 102; MenuCmds : Array[1..Num_Cmds] of CmdRec = ( // AUTOSIG MENU COMMANDS ( Name: 'AE'; Desc: 'Autosig editor' ), @@ -145,6 +145,7 @@ Const ( Name: '-N'; Desc: 'Ask Yes/No (default No)' ), ( Name: '-P'; Desc: 'Prompt for a password' ), ( Name: '-S'; Desc: 'Add text to Sysop log' ), + ( Name: '-R'; Desc: 'Reset OK ACS flags' ), ( Name: '-Y'; Desc: 'Ask Yes/No (default Yes)' ), // SYSOP/EDITORS MENU COMMANDS diff --git a/mystic/bbs_cfg_theme.pas b/mystic/bbs_cfg_theme.pas index 04541bc..d23fce4 100644 --- a/mystic/bbs_cfg_theme.pas +++ b/mystic/bbs_cfg_theme.pas @@ -691,11 +691,11 @@ Begin Box := TAnsiMenuBox.Create; Form := TAnsiMenuForm.Create; - Box.Open (5, 5, 75, 17); + Box.Open (5, 5, 75, 18); Box.Header := ' Theme Edit '; - VerticalLine (23, 7, 15); + VerticalLine (23, 7, 16); Form.AddStr ('F', ' File Name' , 12, 7, 25, 7, 11, 20, 20, @Theme.FileName, Topic + 'Root theme filename'); Form.AddStr ('D', ' Description' , 10, 8, 25, 8, 13, 30, 40, @Theme.Desc, Topic + 'Theme description'); @@ -706,6 +706,7 @@ Begin Form.AddBits ('F', ' Allow Fallback' , 7, 13, 25, 13, 16, ThmFallback, @Theme.Flags, Topic + 'Allow fallback to default paths?'); Form.AddBits ('C', ' Allow ASCII' , 10, 14, 25, 14, 13, ThmAllowASCII, @Theme.Flags, Topic + 'Allow ASCII users to use this theme?'); Form.AddBits ('N', ' Allow ANSI' , 11, 15, 25, 15, 12, ThmAllowANSI, @Theme.Flags, Topic + 'Allow ANSI users to use this theme?'); + Form.AddTog ('O', ' Column Size' , 10, 16, 25, 16, 13, 9, 0, 1, '80_Column 40_Column', @Theme.ColumnSize, Topic + 'Column size of this theme'); Form.AddNone ('1', ' 1: Prompts' , 57, 7, 57, 7, 17, Topic + 'Edit prompts for this theme'); Form.AddNone ('2', ' 2: Options' , 57, 8, 57, 8, 17, Topic + 'Edit general options for this theme'); diff --git a/mystic/bbs_cfg_useredit.pas b/mystic/bbs_cfg_useredit.pas index db939ed..28ca143 100644 --- a/mystic/bbs_cfg_useredit.pas +++ b/mystic/bbs_cfg_useredit.pas @@ -335,6 +335,8 @@ Begin Configuration_EditUser (Session.User.ThisUser); + Screen.WriteXY (1, 24, 7, strRep(' ', 80)); + Session.InUserEdit := False; Session.LocalMode := SavedLocal; diff --git a/mystic/bbs_common.pas b/mystic/bbs_common.pas index 41e003c..bb6cdf8 100644 --- a/mystic/bbs_common.pas +++ b/mystic/bbs_common.pas @@ -27,7 +27,7 @@ Uses Const WinConsoleTitle = mysSoftwareID + ' Node '; - CopyID = 'Copyright (C) ' + mysCopyYear + ' By James Coyle. All Rights Reserved.'; + CopyID = 'Copyright (C) ' + mysCopyYear + ' By James Coyle'; DateTypeStr : Array[1..4] of String[8] = ('MM/DD/YY', 'DD/MM/YY', 'YY/DD/MM', 'Ask '); Var @@ -44,6 +44,7 @@ Var Config : RecConfig; StatusPtr : Byte = 1; +Function DrawAccessFlags (Var Flags: AccessFlagType) : String; Procedure KillRecord (Var dFile; RecNum: LongInt; RecSize: Word); Procedure AddRecord (var dFile; RecNum: LongInt; RecSize: Word); Function Bool_Search (Mask: String; Str: String) : Boolean; @@ -68,6 +69,19 @@ Uses bbs_General, MPL_Execute; +Function DrawAccessFlags (Var Flags: AccessFlagType) : String; +Var + Ch : Char; +Begin + Result := ''; + + For Ch := 'A' to 'Z' Do + If Ord(Ch) - 64 in Flags Then + Result := Result + Ch + Else + Result := Result + '-'; +End; + Procedure AddRecord (var dFile; RecNum: LongInt; RecSize: Word); Var F : File Absolute dFile; @@ -239,58 +253,36 @@ End; {$IFNDEF UNIX} Procedure UpdateStatusLine (Mode: Byte; Str: String); - - Function DrawAccessFlags (Var Flags : AccessFlagType) : String; - Var - S : String; - Ch : Char; - Begin - S := ''; - - For Ch := 'A' to 'Z' Do - If Ord(Ch) - 64 in Flags Then S := S + Ch Else S := S + '-'; - - Result := S; - End; - Begin If Not Config.UseStatusBar Then Exit; Screen.SetWindow (1, 1, 80, 25, False); Case Mode of - 0 : Screen.WriteXY (1, 25, 120, strPadC(Str, 80, ' ')); + 0 : Screen.WriteXY (1, 25, Config.StatusColor3, strPadC(Str, 80, ' ')); 1 : Begin - Screen.WriteXY ( 1, 25, 112, ' [Alias] [Baud] [Sec] [Time] '); - Screen.WriteXY (10, 25, 112, Session.User.ThisUser.Handle); - Screen.WriteXY (48, 25, 112, strI2S(Session.Baud)); - Screen.WriteXY (63, 25, 112, strI2S(Session.User.ThisUser.Security)); - Screen.WriteXY (76, 25, 112, strI2S(Session.TimeLeft)); + Screen.WriteXY ( 1, 25, Config.StatusColor1, ' Alias ' + strRep(' ', 35) + 'Age SecLevel TimeLeft '); + Screen.WriteXY ( 8, 25, Config.StatusColor2, Session.User.ThisUser.Handle); + Screen.WriteXY (47, 25, Config.StatusColor2, Session.User.ThisUser.Gender + '/' + strI2S(DaysAgo(Session.User.ThisUser.Birthday, 1) DIV 365)); + Screen.WriteXY (62, 25, Config.StatusColor2, strI2S(Session.User.ThisUser.Security)); + Screen.WriteXY (76, 25, Config.StatusColor2, strI2S(Session.TimeLeft)); End; 2 : Begin - Screen.WriteXY ( 1, 25, 112, ' [Name] [Flag1] '); - Screen.WriteXY ( 9, 25, 112, Session.User.ThisUser.RealName); - Screen.WriteXY (48, 25, 112, DrawAccessFlags(Session.User.ThisUser.AF1)); + Screen.WriteXY ( 1, 25, Config.StatusColor1, ' Email ' + strRep(' ', 35) + ' Location ' + strRep(' ', 27) + ' '); + Screen.WriteXY ( 8, 25, Config.StatusColor2, strPadR(Session.User.ThisUser.Email, 36, ' ')); + Screen.WriteXY (53, 25, Config.StatusColor2, strPadR(Session.User.ThisUser.City, 27, ' ')); End; 3 : Begin - Screen.WriteXY ( 1, 25, 112, ' [Address] '); - Screen.WriteXY (12, 25, 112, Session.User.ThisUser.Address); - Screen.WriteXY (43, 25, 112, Session.User.ThisUser.City); - Screen.WriteXY (69, 25, 112, Session.User.ThisUser.ZipCode); + Screen.WriteXY ( 1, 25, Config.StatusColor1, ' IP ' + strRep(' ', 19) + ' Host ' + strRep(' ', 49) + ' '); + Screen.WriteXY ( 5, 25, Config.StatusColor2, Session.UserIPInfo); + Screen.WriteXY (31, 25, Config.StatusColor2, strPadR(Session.UserHostInfo, 49, ' ')); End; 4 : Begin - Screen.WriteXY ( 1, 25, 112, ' [BDay] [Sex] [Home PH] [Data PH] '); - Screen.WriteXY ( 9, 25, 112, DateDos2Str(Session.User.ThisUser.Birthday, Session.User.ThisUser.DateType)); - Screen.WriteXY (25, 25, 112, Session.User.ThisUser.Gender); - Screen.WriteXY (39, 25, 112, Session.User.ThisUser.HomePhone); - Screen.WriteXY (65, 25, 112, Session.User.ThisUser.DataPhone); + Screen.WriteXY ( 1, 25, Config.StatusColor1, ' Flags 1 ' + strRep(' ', 35) + ' Flags 2 '); + Screen.WriteXY (10, 25, Config.StatusColor2, DrawAccessFlags(Session.User.ThisUser.AF1)); + Screen.WriteXY (54, 25, Config.StatusColor2, DrawAccessFlags(Session.User.ThisUser.AF2)); End; - 5 : Begin - Screen.WriteXY ( 1, 25, 112, ' [Email] [Flag2] '); - Screen.WriteXY (10, 25, 112, Session.User.ThisUser.Email); - Screen.WriteXY (54, 25, 112, DrawAccessFlags(Session.User.ThisUser.AF2)); - End; - 6 : Screen.WriteXY ( 1, 25, 112, ' ALT (C)hat (S)plit (E)dit (H)angup (J) DOS (U)pgrade (B) Status Bar '); + 5 : Screen.WriteXY (1, 25, Config.StatusColor3, ' ALTS/C Chat ALTE Edit ALTH Hangup ALT+/- Time ALTB Info ALTT Bar ALTV Screen '); End; Screen.SetWindow (1, 1, 80, 24, False); @@ -323,7 +315,7 @@ Begin Else Session.io.LocalScreenEnable; {B} #48 : Begin - If StatusPtr < 6 Then + If StatusPtr < 5 Then Inc (StatusPtr) Else StatusPtr := 1; diff --git a/mystic/bbs_core.pas b/mystic/bbs_core.pas index 73e83d4..3123730 100644 --- a/mystic/bbs_core.pas +++ b/mystic/bbs_core.pas @@ -29,55 +29,59 @@ Type {$IFNDEF UNIX} Client : TIOBase; {$ENDIF} - User : TBBSUser; - Msgs : TMsgBase; - FileBase : TFileBase; - Menu : TMenuEngine; - IO : TBBSIO; - Pipe : TPipe; - EventFile : File of EventRec; - ThemeFile : File of RecTheme; - VoteFile : File of VoteRec; - Vote : VoteRec; - CommHandle : LongInt; - ShutDown : Boolean; - TempPath : String; - Event : EventRec; - NextEvent : EventRec; - Theme : RecTheme; - LocalMode : Boolean; - Baud : LongInt; - ExitLevel : Byte; - EventWarn : Boolean; - EventExit : Boolean; - EventRunAfter : Boolean; - NodeNum : Byte; - TimerStart : Integer; - TimerEnd : Integer; - LastTimeLeft : Integer; - TimeOut : LongInt; - UserHostInfo : String[50]; - UserIPInfo : String[15]; - CheckTimeOut : Boolean; - TimeOffset : Word; - TimeSaved : Word; - TimerOn : Boolean; - TimeChecked : Boolean; - ConfigMode : Boolean; - InUserEdit : Boolean; - AllowMessages : Boolean; - InMessage : Boolean; - MessageCheck : Byte; - HistoryFile : File of RecHistory; - HistoryEmails : Word; - HistoryPosts : Word; - HistoryDLs : Word; - HistoryDLKB : LongInt; - HistoryULs : Word; - HistoryULKB : LongInt; - HistoryHour : SmallInt; - PromptFile : File of RecPrompt; - Prompt : RecPrompt; + User : TBBSUser; + Msgs : TMsgBase; + FileBase : TFileBase; + Menu : TMenuEngine; + IO : TBBSIO; + Pipe : TPipe; + EventFile : File of EventRec; + ThemeFile : File of RecTheme; + VoteFile : File of VoteRec; + Vote : VoteRec; + CommHandle : LongInt; + ShutDown : Boolean; + TempPath : String; + Event : EventRec; + NextEvent : EventRec; + Theme : RecTheme; + LocalMode : Boolean; + Baud : LongInt; + ExitLevel : Byte; + EventWarn : Boolean; + EventExit : Boolean; + EventRunAfter : Boolean; + NodeNum : Byte; + TimerStart : Integer; + TimerEnd : Integer; + LastTimeLeft : Integer; + TimeOut : LongInt; + UserLoginName : String[30]; + UserLoginPW : String[15]; + UserHostInfo : String[50]; + UserIPInfo : String[15]; + CheckTimeOut : Boolean; + TimeOffset : Word; + TimeSaved : Word; + TimerOn : Boolean; + TimeChecked : Boolean; + ConfigMode : Boolean; + InUserEdit : Boolean; + AllowMessages : Boolean; + InMessage : Boolean; + MessageCheck : Byte; + HistoryFile : File of RecHistory; + HistoryEmails : Word; + HistoryPosts : Word; + HistoryDLs : Word; + HistoryDLKB : LongInt; + HistoryULs : Word; + HistoryULKB : LongInt; + HistoryHour : SmallInt; + PromptFile : File of RecPrompt; + Prompt : RecPrompt; + LastScanHadNew : Boolean; + LastScanHadYou : Boolean; Constructor Create; Destructor Destroy; Override; @@ -118,6 +122,8 @@ Begin EventExit := False; EventRunAfter := False; NodeNum := 0; + UserLoginName := ''; + UserLoginPW := ''; UserHostInfo := ''; UserIPInfo := ''; CheckTimeOut := True; diff --git a/mystic/bbs_edit_ansi.pas b/mystic/bbs_edit_ansi.pas index 1a89fd9..263fcc1 100644 --- a/mystic/bbs_edit_ansi.pas +++ b/mystic/bbs_edit_ansi.pas @@ -834,7 +834,7 @@ Begin #77 : If CurX <= RowSize Then Inc(CurX); #73 : PageUp; #81 : PageDown; - #83 : DoDelete; + #83 : DoDelete; End; End Else Case Ch of diff --git a/mystic/bbs_edit_full.pas b/mystic/bbs_edit_full.pas index 7ee31b7..45c20ee 100644 --- a/mystic/bbs_edit_full.pas +++ b/mystic/bbs_edit_full.pas @@ -475,6 +475,7 @@ Begin Start := strS2I(Session.io.GetInput(3, 3, 11, '')); Session.io.OutFull (Session.GetPrompt(160)); + Finish := strS2I(Session.io.GetInput(3, 3, 11, '')); If (Start > 0) and (Start <= NumLines) and (Finish <= NumLines) Then Begin diff --git a/mystic/bbs_edit_line.pas b/mystic/bbs_edit_line.pas index 05ad8df..151476f 100644 --- a/mystic/bbs_edit_line.pas +++ b/mystic/bbs_edit_line.pas @@ -87,9 +87,12 @@ Function LineEditor (Var Lines : Integer; MaxLen: Byte; MaxLine: Integer; TEdit, Begin Done := False; Save := False; + Repeat Session.io.OutFull (Session.GetPrompt(166)); + Ch := Session.io.OneKey ('?ACQRSU', True); + Case Ch of '?' : Session.io.OutFullLn (Session.GetPrompt(167)); 'A' : If Forced Then Begin @@ -144,9 +147,13 @@ Function LineEditor (Var Lines : Integer; MaxLen: Byte; MaxLine: Integer; TEdit, Dec(Session.Msgs.MsgText[CurLine][0]); End Else If CurLine > 1 Then Begin Dec(CurLine); + Session.io.PromptInfo[1] := strI2S(CurLine); + Session.io.OutFullLn (Session.GetPrompt(165)); + Session.io.OutRaw (Session.Msgs.MsgText[CurLine]); + If Session.Msgs.MsgText[CurLine] <> '' Then Begin Session.io.OutBS(1, True); Dec(Session.Msgs.MsgText[CurLine][0]); @@ -155,6 +162,7 @@ Function LineEditor (Var Lines : Integer; MaxLen: Byte; MaxLine: Integer; TEdit, #13 : Begin If CurLine < MaxLine Then Begin Inc(CurLine); + Session.io.OutRaw (#13#10); End; End; @@ -163,15 +171,18 @@ Function LineEditor (Var Lines : Integer; MaxLen: Byte; MaxLine: Integer; TEdit, Commands; If (Not Save) and (Not Done) Then FullReDraw; End Else - If Ch in [#32..#254] Then Begin + If Ch in [#32..#254] Then Begin If Length(Session.Msgs.MsgText[Curline]) < MaxLen Then Begin Session.Msgs.MsgText[CurLine] := Session.Msgs.MsgText[CurLine] + Ch; + Session.io.BufAddChar (Ch); End; If (Length(Session.Msgs.MsgText[CurLine]) > MaxLen-1) and (CurLine < MaxLine) Then Begin strWrap (Session.Msgs.MsgText[CurLine], Session.Msgs.MsgText[Succ(CurLine)], MaxLen); - Inc(CurLine); - Session.io.OutBS (Length(Session.Msgs.MsgText[CurLine]), True); + + Inc (CurLine); + + Session.io.OutBS (Length(Session.Msgs.MsgText[CurLine]), True); Session.io.OutRawLn (''); Session.io.OutRaw (Session.Msgs.MsgText[CurLine]); End; @@ -196,7 +207,7 @@ Begin GetText; If Save Then Begin - Lines := CurLine - 1; + Lines := CurLine - 1; LineEditor := True; End Else LineEditor := False; diff --git a/mystic/bbs_general.pas b/mystic/bbs_general.pas index 674daea..fa96d5a 100644 --- a/mystic/bbs_general.pas +++ b/mystic/bbs_general.pas @@ -637,11 +637,13 @@ 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)); @@ -657,11 +659,14 @@ 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; @@ -697,10 +702,13 @@ Begin 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 @@ -708,9 +716,11 @@ Begin 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; @@ -727,6 +737,7 @@ Begin Close (Session.VoteFile); End Else Begin A := Voting_List; + If A = 0 Then Exit; Repeat @@ -748,11 +759,14 @@ Begin 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] := ''; @@ -760,8 +774,10 @@ 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; @@ -771,6 +787,7 @@ Var 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 @@ -778,6 +795,7 @@ Begin Else NewQues[FilePos(Session.VoteFile)] := False; End; + Close (Session.VoteFile); For Pos := 1 to mysMaxVoteQuestion Do @@ -794,6 +812,7 @@ Begin If Not Forced And (Num = 0) Then Begin Total := Voting_List; + If Total = 0 Then Exit; Repeat @@ -1258,6 +1277,8 @@ Begin UseFull := Not (strUpper(strWordGet(3, Data, ';')) = 'DISPLAY'); CurPath := Root; + If Not DirExists(Root) Then Exit; + BuildDirectory(CurPath); FullReDraw; @@ -1381,7 +1402,7 @@ Begin Session.io.AnsiClear; If UseFull Then - AnsiViewer (Session.Theme.ViewerBar, 'ansigalv;dummy;' + CurPath + DirList[CurPos]^.Desc) + 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; @@ -1485,6 +1506,7 @@ Var FN : String; Template : String; HelpFile : String; + Speed : Byte; Str : String; Sauce : RecSauceInfo; @@ -1503,10 +1525,30 @@ Var 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, ';'); - FN := strWordGet(3, Data, ';'); + Speed := strS2I(strWordGet(3, Data, ';')); + FN := strWordGet(4, Data, ';'); If Pos(PathChar, FN) = 0 Then FN := Session.Theme.TextPath + FN; @@ -1542,21 +1584,7 @@ Begin Close (AFile); - 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; + ReDraw; While Not Session.ShutDown Do Begin Ch := UpCase(Session.io.GetKey); @@ -1594,7 +1622,20 @@ Begin End; End Else Case Ch of - #32, + '?' : 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; #13 : If TopLine < Ansi.Lines - WinSize Then Begin Inc (TopLine, WinSize); diff --git a/mystic/bbs_io.pas b/mystic/bbs_io.pas index 3b1b64c..79b3587 100644 --- a/mystic/bbs_io.pas +++ b/mystic/bbs_io.pas @@ -72,30 +72,30 @@ Type Procedure BufAddChar (Ch: Char); Procedure BufAddStr (Str: String); Procedure BufFlush; - Function ParseMCI (Display : Boolean; Code: String) : Boolean; + Function ParseMCI (Display: Boolean; Code: String) : Boolean; Function StrMci (Str: String) : String; Function Attr2Ansi (Attr: Byte) : String; - Function Pipe2Ansi (Color : Byte) : String; - Procedure AnsiGotoXY (X : Byte; Y:Byte); - Procedure AnsiMoveX (X : Byte); - Procedure AnsiMoveY (Y : Byte); - Procedure AnsiColor (A : Byte); + Function Pipe2Ansi (Color: Byte) : String; + Procedure AnsiGotoXY (X: Byte; Y:Byte); + Procedure AnsiMoveX (X: Byte); + Procedure AnsiMoveY (Y: Byte); + Procedure AnsiColor (A: Byte); Procedure AnsiClear; Procedure AnsiClrEOL; Procedure OutPipe (Str: String); Procedure OutPipeLn (Str: String); - Procedure OutRaw (Str : String); + Procedure OutRaw (Str: String); Procedure OutRawLn (Str: String); - Procedure OutBS (Num : Byte; Del: Boolean); - Procedure OutFull (Str : String); - Procedure OutFullLn (Str : String); - Function OutFile (FName : String; DoPause: Boolean; Speed: Byte) : Boolean; - Function OutYN (Y : Boolean) : String; - Function OutON (O : Boolean) : String; + Procedure OutBS (Num: Byte; Del: Boolean); + Procedure OutFull (Str: String); + Procedure OutFullLn (Str: String); + Function OutFile (FName: String; DoPause: Boolean; Speed: Byte) : Boolean; + Function OutYN (Y: Boolean) : String; + Function OutON (O: Boolean) : String; Procedure PauseScreen; Function MorePrompt : Char; - Function DrawPercent (Bar : RecPercent; Part, Whole : SmallInt; Var Percent : SmallInt) : String; - Function GetInput (Field, Max, Mode: Byte; Default : String) : String; + Function DrawPercent (Bar: RecPercent; Part, Whole: SmallInt; Var Percent : SmallInt) : String; + Function GetInput (Field, Max, Mode: Byte; Default: String) : String; Function InXY (X, Y, Field, Max, Mode: Byte; Default: String) : String; Function InKey (Wait: LongInt) : Char; Function GetYNL (Str: String; Yes: Boolean) : Boolean; @@ -1821,12 +1821,13 @@ Var Begin If UseInLimit Then Begin - Field := InLimit; + Field := InLimit; UseInLimit := False; End; If UseInSize Then Begin UseInSize := False; + If InSize <= Max Then Max := InSize; End; @@ -1880,6 +1881,7 @@ Begin Ch := GetKey; If IsArrow Then Begin + Case Ch of #71 : If StrPos > 1 Then Begin StrPos := 1; @@ -1939,6 +1941,7 @@ Begin End; End; End Else + Case Ch of #02 : ReDraw; #08 : If StrPos > 1 Then Begin @@ -2058,7 +2061,7 @@ Var Begin Attr := Screen.TextAttr; - Screen.TextAttr := 0; // kludge to force it to return full ansi codes +// Screen.TextAttr := 0; // kludge to force it to return full ansi codes If Part > Whole Then Part := Whole; @@ -2072,7 +2075,7 @@ Begin Result := Attr2Ansi(Bar.HiAttr) + strRep(Bar.HiChar, FillSize) + Attr2Ansi(Bar.LoAttr) + strRep(Bar.LoChar, Bar.BarLength - FillSize) + - Attr2Ansi(Attr); + Pipe2Ansi(16) + Attr2Ansi(Attr); End; {$IFDEF UNIX} diff --git a/mystic/bbs_menus.pas b/mystic/bbs_menus.pas index 6adf64b..6da82b7 100644 --- a/mystic/bbs_menus.pas +++ b/mystic/bbs_menus.pas @@ -145,6 +145,7 @@ Begin 'N' : Session.User.AcsOkFlag := Session.io.GetYN(CmdData, False); 'P' : Session.User.AcsOkFlag := Session.io.GetPW(Copy(CmdData, 1, Pos(';', CmdData) - 1), Session.GetPrompt(417), strUpper(Copy(CmdData, Pos(';', CmdData) + 1, Length(CmdData)))); + 'R' : Session.User.AcsOkFlag := Boolean(Ord(strS2I(CmdData))); 'S' : Session.SystemLog(CmdData); 'Y' : Session.User.AcsOkFlag := Session.io.GetYN(CmdData, True); End; @@ -255,7 +256,7 @@ Begin End; 'M' : Case Cmd[2] of 'A' : Session.Msgs.ChangeArea(CmdData); - 'C' : Session.Msgs.CheckEMail; + 'C' : Session.Msgs.CheckEMail(CmdData); 'D' : Session.Msgs.SetMessagePointers; 'G' : Session.Msgs.MessageGroupChange (CmdData, True, True); 'L' : Session.Msgs.NetMailLookup (True, '', ''); @@ -266,7 +267,7 @@ Begin 'R' : Begin If CmdData = '' Then CmdData := ' '; - Session.Msgs.ReadMessages(UpCase(CmdData[1]), ''); + Session.Msgs.ReadMessages(UpCase(CmdData[1]), Copy(CmdData, 3, 255), ''); End; 'S' : Session.Msgs.GlobalMessageSearch(UpCase(CmdData[1])); 'V' : Session.Msgs.ViewSentEmail; diff --git a/mystic/bbs_msgbase.pas b/mystic/bbs_msgbase.pas index 6abab6c..5ce7490 100644 --- a/mystic/bbs_msgbase.pas +++ b/mystic/bbs_msgbase.pas @@ -35,11 +35,11 @@ Type Function IsQuotedText (Str: String) : Boolean; Function OpenCreateBase (Var Msg: PMsgBaseABS; Var Area: RecMessageBase) : Boolean; Procedure AppendMessageText (Var Msg: PMsgBaseABS; Lines: Integer; ReplyID: String); - Procedure AssignMessageData (Var Msg: PMsgBaseABS); + Procedure AssignMessageData (Var Msg: PMsgBaseABS; Var TempBase: RecMessageBase); Function GetBaseByNum (Num: LongInt; Var TempBase: RecMessageBase) : Boolean; Function GetBaseCompressed (Num: LongInt; Var TempBase: RecMessageBase) : Boolean; Function GetBaseByIndex (Num: LongInt; Var TempBase: RecMessageBase) : Boolean; - Procedure GetMessageStats (Var TempBase: RecMessageBase; Var Total, New, Yours: LongInt); + Procedure GetMessageStats (List, ShowPrompt, ShowYou: Boolean; Var ListPtr: LongInt; Var TempBase: RecMessageBase; NoFrom, NoRead: Boolean; Var Total, New, Yours: LongInt); Function GetTotalBases (Compressed: Boolean) : LongInt; Function GetTotalMessages (Var TempBase: RecMessageBase) : LongInt; Procedure PostTextFile (Data: String; AllowCodes: Boolean); @@ -53,11 +53,11 @@ Type Procedure MessageUpload (Var CurLine: SmallInt); Procedure ReplyMessage (Email: Boolean; ListMode: Byte; ReplyID: String); Procedure EditMessage; - Function ReadMessages (Mode : Char; SearchStr: String) : Boolean; + Function ReadMessages (Mode: Char; CmdData, SearchStr: String) : Boolean; Procedure ToggleNewScan (QWK: Boolean; Data: String); Procedure MessageGroupChange (Ops: String; FirstBase, Intro : Boolean); Procedure PostMessage (Email: Boolean; Data: String); - Procedure CheckEMail; + Procedure CheckEMail (CmdData: String); Procedure MessageNewScan (Data: String); Procedure MessageQuickScan (Data: String); Procedure GlobalMessageSearch (Mode: Char); @@ -215,7 +215,6 @@ Begin While NodeList.FindNext(NodeData) Do Begin Case ListType of - 0 : ;//If NodeData.Keyword <> '' Then Continue; 1 : If NodeData.Keyword <> 'ZONE' Then Continue; 2 : If (NodeData.Keyword <> 'ZONE') and (NodeData.Keyword <> 'REGION') and (NodeData.Keyword <> 'HOST') Then Continue; End; @@ -405,10 +404,9 @@ Begin End; End; -Procedure TMsgBase.GetMessageStats (Var TempBase: RecMessageBase; Var Total, New, Yours: LongInt); +Procedure TMsgBase.GetMessageStats (List, ShowPrompt, ShowYou: Boolean; Var ListPtr: LongInt; Var TempBase: RecMessageBase; NoFrom, NoRead: Boolean; Var Total, New, Yours: LongInt); Var TempMsg : PMsgBaseABS; - MsgTo : String[40]; Begin Total := 0; New := 0; @@ -422,13 +420,53 @@ Begin TempMsg^.SeekFirst(TempMsg^.GetLastRead(Session.User.UserNum) + 1); While TempMsg^.SeekFound Do Begin - Inc (New); - TempMsg^.MsgStartUp; - MsgTo := strUpper(TempMsg^.GetTo); + If NoFrom And Session.User.IsThisUser(TempMsg^.GetFrom) Then Begin + TempMsg^.SeekNext; - If (MsgTo = strUpper(Session.User.ThisUser.Handle)) or (MsgTo = strUpper(Session.User.ThisUser.RealName)) Then + Continue; + End; + + If NoRead And Session.User.IsThisUser(TempMsg^.GetTo) And TempMsg^.IsRcvd Then Begin + TempMsg^.SeekNext; + + Continue; + End; + + If List Then Begin + If (ShowYou And Not Session.User.IsThisUser(TempMsg^.GetTo)) Then Begin + TempMsg^.SeekNext; + + Continue; + End; + + If ShowPrompt Then + Session.io.OutBS(Screen.CursorX, True); + + Inc (ListPtr); + + Session.io.PromptInfo[1] := strI2S(ListPtr); + Session.io.PromptInfo[2] := TempBase.Name; + Session.io.PromptInfo[3] := TempMsg^.GetFrom; + Session.io.PromptInfo[4] := TempMsg^.GetTo; + Session.io.PromptInfo[5] := TempMsg^.GetSubj; + Session.io.PromptInfo[6] := DateDos2Str(DateStr2Dos(TempMsg^.GetDate), Session.User.ThisUser.DateType); + + If ListPtr = 1 Then + Session.io.OutFullLn(Session.GetPrompt(506)); + + Session.io.OutFullLn(Session.GetPrompt(507)); + + If ShowPrompt Then + Session.io.OutFull(Session.GetPrompt(487)); + + Session.io.BufFlush; + End; + + Inc (New); + + If Session.User.IsThisUser(TempMsg^.GetTo) Then Inc(Yours); TempMsg^.SeekNext; @@ -470,6 +508,8 @@ Begin MScan.NewScan := MBase.DefNScan; MScan.QwkScan := MBase.DefQScan; + FileMode := 66; + Assign (MScanFile, MBase.Path + MBase.FileName + '.scn'); {$I-} Reset (MScanFile); {$I+} @@ -527,31 +567,31 @@ Begin End; End; -Procedure TMsgBase.AssignMessageData (Var Msg: PMsgBaseABS); +Procedure TMsgBase.AssignMessageData (Var Msg: PMsgBaseABS; Var TempBase: RecMessageBase); Var Addr : RecEchoMailAddr; SemFile : Text; Begin Msg^.StartNewMsg; - If MBase.Flags And MBRealNames <> 0 Then + If TempBase.Flags And MBRealNames <> 0 Then Msg^.SetFrom(Session.User.ThisUser.RealName) Else Msg^.SetFrom(Session.User.ThisUser.Handle); Msg^.SetLocal (True); - If MBase.NetType > 0 Then Begin - If MBase.NetType = 3 Then + If TempBase.NetType > 0 Then Begin + If TempBase.NetType = 3 Then Msg^.SetMailType(mmtNetMail) Else Msg^.SetMailType(mmtEchoMail); - Addr := Config.NetAddress[MBase.NetAddr]; + Addr := Config.NetAddress[TempBase.NetAddr]; Msg^.SetOrig(Addr); - Case MBase.NetType of + Case TempBase.NetType of 1 : Begin Assign (SemFile, Config.SemaPath + fn_SemFileEcho); If Session.ExitLevel > 5 Then Session.ExitLevel := 7 Else Session.ExitLevel := 5; @@ -572,7 +612,7 @@ Begin End Else Msg^.SetMailType(mmtNormal); - Msg^.SetPriv (MBase.Flags and MBPrivate <> 0); + Msg^.SetPriv (TempBase.Flags and MBPrivate <> 0); Msg^.SetDate (DateDos2Str(CurDateDos, 1)); Msg^.SetTime (TimeDos2Str(CurDateDos, False)); End; @@ -647,62 +687,6 @@ Begin End; End; -(* -Procedure TMsgBase.ToggleNewScan (QWK: Boolean; Data: String); - - Procedure NewScanListBases; - Begin - Session.io.PausePtr := 1; - Session.io.AllowPause := True; - - If QWK Then - Session.io.OutFullLn (Session.GetPrompt(90)) - Else - Session.io.OutFullLn (Session.GetPrompt(91)); - - Session.io.OutFullLn (Session.GetPrompt(92)); - - Total := 0; - - Reset (MBaseFile); - - While Not Eof(MBaseFile) Do Begin - Read (MBaseFile, MBase); - - If Session.User.Access(MBase.ListACS) Then Begin - Inc (Total); - - Session.io.PromptInfo[1] := strI2S(Total); - Session.io.PromptInfo[2] := MBase.Name; - - GetMessageScan; - - If ((MScan.NewScan > 0) And Not QWK) or ((MScan.QwkScan > 0) And QWK) Then - Session.io.PromptInfo[3] := 'Yes' {++lang++} - Else - Session.io.PromptInfo[3] := 'No'; {++lang++} - - Session.io.OutFull (Session.GetPrompt(93)); - - If (Total MOD Config.MColumns = 0) And (Total > 0) Then Session.io.OutRawLn(''); - End; - - If EOF(MBaseFile) and (Total MOD Config.MColumns <> 0) Then Session.io.OutRawLn(''); - - 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; - - Session.io.OutFull (Session.GetPrompt(430)); - End; - -Begin -End; -*) - Procedure TMsgBase.ToggleNewScan (QWK: Boolean; Data: String); Var Total: LongInt; @@ -769,7 +753,8 @@ Var Repeat Read (MBaseFile, MBase); - If Session.User.Access(MBase.ListACS) Then Inc(B); + If Session.User.Access(MBase.ListACS) Then + Inc(B); If A = B Then Break; Until False; @@ -1192,13 +1177,12 @@ Begin Session.io.PromptInfo[1] := ToWho; - If Editor(Lines, 78, mysMaxMsgLines, False, fn_tplMsgEdit, Subj) Then Begin - + If Editor(Lines, ColumnValue[Session.Theme.ColumnSize] - 2, mysMaxMsgLines, False, fn_tplMsgEdit, Subj) Then Begin Session.io.OutFull (Session.GetPrompt(107)); If Not OpenCreateBase(MsgNew, MBase) Then Exit; - AssignMessageData(MsgNew); + AssignMessageData(MsgNew, MBase); Case MBase.NetType of 2 : MsgNew^.SetTo('All'); @@ -1321,7 +1305,7 @@ Begin '!' : Begin Temp1 := MsgBase^.GetSubj; - If Editor(Lines, 78, mysMaxMsgLines, False, fn_tplMsgEdit, Temp1) Then + If Editor(Lines, ColumnValue[Session.Theme.ColumnSize] - 2, mysMaxMsgLines, False, fn_tplMsgEdit, Temp1) Then MsgBase^.SetSubj(Temp1) Else ReadText; @@ -1393,9 +1377,11 @@ Begin Session.io.PromptInfo[2] := T2; End; -Function TMsgBase.ReadMessages (Mode : Char; SearchStr : String) : Boolean; +Function TMsgBase.ReadMessages (Mode: Char; CmdData, SearchStr: String) : Boolean; Var ReadRes : Boolean; + NoFrom : Boolean; + NoRead : Boolean; ScanMode : Byte; ValidKeys : String; HelpFile : String[8]; @@ -1404,7 +1390,7 @@ Var ReplyID : String[31]; TempStr : String; - Procedure Set_Message_Security; + Procedure SetMessageSecurity; Begin If Mode = 'E' Then Begin ValidKeys := 'ADJLNPQRX?'#13; @@ -1504,7 +1490,7 @@ Var Session.User.IgnoreGroup := False; End; - Procedure Export_Message; + Procedure ExportMessage; Var FN : String; Temp : String; @@ -1602,6 +1588,12 @@ Var 4 : Res := Session.User.IsThisUser(MsgBase^.GetFrom); End; + If NoFrom And Session.User.IsThisUser(MsgBase^.GetFrom) Then + Res := False; + + If NoRead And Session.User.IsThisUser(MsgBase^.GetTo) And MsgBase^.IsRcvd Then + Res := False; + If Not Res Then If Back Then MsgBase^.SeekPrior @@ -1617,7 +1609,7 @@ Var SeekNextMsg := Res; End; - Procedure Assign_Header_Info; + Procedure AssignHeaderInfo; Var NetAddr : RecEchoMailAddr; Begin @@ -1646,10 +1638,12 @@ Var TempStr := Session.GetPrompt(490); - If MsgBase^.IsLocal Then Session.io.PromptInfo[9] := strWordGet(1, TempStr, ' ') Else Session.io.PromptInfo[9] := strWordGet(2, TempStr, ' '); - If MsgBase^.IsPriv Then Session.io.PromptInfo[9] := Session.io.PromptInfo[9] + ' ' + strWordGet(3, TempStr, ' '); - If MsgBase^.IsSent Then Session.io.PromptInfo[9] := Session.io.PromptInfo[9] + ' ' + strWordGet(4, TempStr, ' '); - If MsgBase^.IsDeleted Then Session.io.PromptInfo[9] := Session.io.PromptInfo[9] + ' ' + strWordGet(5, TempStr, ' '); + If MsgBase^.IsLocal Then Session.io.PromptInfo[9] := strWordGet(1, TempStr, ','); + If MsgBase^.IsEchoed Then Session.io.PromptInfo[9] := Session.io.PromptInfo[9] + ' ' + strWordGet(2, TempStr, ','); + If MsgBase^.IsPriv Then Session.io.PromptInfo[9] := Session.io.PromptInfo[9] + ' ' + strWordGet(3, TempStr, ','); + If MsgBase^.IsSent Then Session.io.PromptInfo[9] := Session.io.PromptInfo[9] + ' ' + strWordGet(4, TempStr, ','); + If MsgBase^.IsRcvd Then Session.io.PromptInfo[9] := Session.io.PromptInfo[9] + ' ' + strWordGet(6, TempStr, ','); + If MsgBase^.IsDeleted Then Session.io.PromptInfo[9] := Session.io.PromptInfo[9] + ' ' + strWordGet(5, TempStr, ','); End; Procedure Send_Msg_Text (Str : String); @@ -1748,10 +1742,15 @@ Var Repeat Set_Node_Action (Session.GetPrompt(348)); - Set_Message_Security; + SetMessageSecurity; If MsgBase^.GetMsgNum > LastRead Then LastRead := MsgBase^.GetMsgNum; + If Session.User.IsThisUser(MsgBase^.GetTo) And Not MsgBase^.IsRcvd Then Begin + MsgBase^.SetRcvd(True); + MsgBase^.ReWriteHDR; + End; + CurMsg := MsgBase^.GetMsgNum; Lines := 0; PageStart := 1; @@ -1773,7 +1772,7 @@ Var End; End; - Assign_Header_Info; + AssignHeaderInfo; Session.io.ScreenInfo[4].Y := 0; Session.io.ScreenInfo[5].Y := 0; @@ -1869,6 +1868,8 @@ Var End; 'H' : Begin LastRead := CurMsg - 1; + + Session.io.OutFullLn(Session.GetPrompt(504)); End; 'I' : Begin LastRead := MsgBase^.GetHighMsgNum; @@ -1972,7 +1973,7 @@ Var Break; End; 'X' : Begin - Export_Message; + ExportMessage; Break; End; @@ -2357,8 +2358,13 @@ Var If MsgBase^.GetMsgNum > LastRead Then LastRead := MsgBase^.GetMsgNum; - Set_Message_Security; - Assign_Header_Info; + If Session.User.IsThisUser(MsgBase^.GetTo) And Not MsgBase^.IsRcvd Then Begin + MsgBase^.SetRcvd(True); + MsgBase^.ReWriteHDR; + End; + + SetMessageSecurity; + AssignHeaderInfo; Display_Header; MsgBase^.MsgTxtStartUp; @@ -2429,7 +2435,13 @@ Var Break; End; 'G' : Exit; - 'H' : LastRead := MsgBase^.GetMsgNum - 1; + 'H' : Begin + LastRead := MsgBase^.GetMsgNum - 1; + + Session.io.OutFullLn(Session.GetPrompt(505)); + + Break; + End; 'I' : Begin LastRead := MsgBase^.GetHighMsgNum; @@ -2449,6 +2461,7 @@ Var If Not SeekNextMsg(True, False) Then Begin MsgBase^.SeekFirst(B); + SeekNextMsg(True, False); End; End; @@ -2463,7 +2476,7 @@ Var Session.io.OutFullLn(Session.GetPrompt(411)); While SeekNextMsg(False, False) Do Begin - Assign_Header_Info; + AssignHeaderInfo; Session.io.OutFullLn (Session.GetPrompt(412)); @@ -2531,7 +2544,7 @@ Var SetMessageScan; End; - 'X' : Export_Message; + 'X' : ExportMessage; '?' : Session.io.OutFile(HelpFile, True, 0); '[' : If MsgBase^.GetRefer > 0 Then Begin MsgBase^.SeekFirst(MsgBase^.GetRefer); @@ -2560,12 +2573,16 @@ Var P = Global personal scan B = By You T = Global text search } Var - MsgNum : LongInt; + MsgNum : LongInt; + NoLastRead : Boolean; Begin ReadMessages := True; ReadRes := True; WereMsgs := False; ReplyID := ''; + NoLastRead := Pos('/NOLR', strUpper(CmdData)) > 0; + NoFrom := Pos('/NOFROM', strUpper(CmdData)) > 0; + NoRead := Pos('/NOREAD', strUpper(CmdData)) > 0; If MBase.FileName = '' Then Begin Session.io.OutFullLn (Session.GetPrompt(110)); @@ -2595,6 +2612,8 @@ Begin End; End; +{ start here opencreate... } + Case MBase.BaseType of 0 : MsgBase := New(PMsgBaseJAM, Init); 1 : MsgBase := New(PMsgbaseSquish, Init); @@ -2614,6 +2633,8 @@ Begin Exit; End; + {end here } + If Mode = 'E' Then ScanMode := 1 Else @@ -2657,7 +2678,7 @@ Begin Else MsgBase^.SeekFirst(LastRead + 1); - Set_Message_Security; + SetMessageSecurity; Reading := True; @@ -2669,9 +2690,11 @@ Begin Ascii_Read_Messages; End; - If Not (Mode in ['E', 'S', 'T']) Then MsgBase^.SetLastRead (Session.User.UserNum, LastRead); + If Not (Mode in ['E', 'S', 'T']) And Not NoLastRead Then + MsgBase^.SetLastRead (Session.User.UserNum, LastRead); MsgBase^.CloseMsgBase; + Dispose (MsgBase, Done); Reading := False; @@ -2834,7 +2857,7 @@ Begin Session.io.PromptInfo[1] := MsgTo; // Session.io.PromptInfo[2] := MsgSubj; - If Editor(Lines, 78, mysMaxMsgLines, Forced, fn_tplMsgEdit, MsgSubj) Then Begin + If Editor(Lines, ColumnValue[Session.Theme.ColumnSize] - 2, mysMaxMsgLines, Forced, fn_tplMsgEdit, MsgSubj) Then Begin Session.io.OutFull (Session.GetPrompt(107)); { all of this below should be replaced with a SaveMessage function } @@ -2850,7 +2873,7 @@ Begin Exit; End; - AssignMessageData(MsgBase); + AssignMessageData(MsgBase, MBase); MsgBase^.SetTo (MsgTo); MsgBase^.SetSubj (MsgSubj); @@ -2903,78 +2926,70 @@ Begin Session.User.IgnoreGroup := SaveGroup; End; -Procedure TMsgBase.CheckEMail; +Procedure TMsgBase.CheckEMail (CmdData: String); Var - Old : RecMessageBase; - Total : Integer; + MsgBase : PMsgBaseABS; + TempBase : RecMessageBase; + Total : Integer; + UnRead : Integer; Begin + TempBase := MBase; + Total := 0; + UnRead := 0; + FileMode := 66; + Session.io.OutFull (Session.GetPrompt(123)); - Session.io.BufFlush; - Old := MBase; - Reset (MBaseFile); Read (MBaseFile, MBase); Close (MBaseFile); - Case MBase.BaseType of - 0 : MsgBase := New(PMsgBaseJAM, Init); - 1 : MsgBase := New(PMsgBaseSquish, Init); - End; + If OpenCreateBase (MsgBase, MBase) Then Begin + MsgBase^.SeekFirst (1); - MsgBase^.SetMsgPath (MBase.Path + MBase.FileName); - - If Not MsgBase^.OpenMsgBase Then Begin - Session.io.OutFullLn (Session.GetPrompt(124)); - Dispose (MsgBase, Done); - MBase := Old; - Exit; - End; - - Total := 0; - - MsgBase^.YoursFirst(Session.User.ThisUser.RealName, Session.User.ThisUser.Handle); - - If MsgBase^.YoursFound Then Begin - Session.io.OutFullLn (Session.GetPrompt(125)); - - Total := 0; - - While MsgBase^.YoursFound Do Begin + While MsgBase^.SeekFound Do Begin MsgBase^.MsgStartUp; - Inc (Total); + If Session.User.IsThisUser(MsgBase^.GetTo) Then Begin + Inc (Total); - Session.io.PromptInfo[1] := strI2S(Total); - Session.io.PromptInfo[2] := MsgBase^.GetFrom; - Session.io.PromptInfo[3] := MsgBase^.GetSubj; - Session.io.PromptInfo[4] := MsgBase^.GetDate; + If Not MsgBase^.IsRcvd Then Inc (UnRead); - Session.io.OutFullLn (Session.GetPrompt(126)); + If Total = 1 Then + Session.io.OutFullLn (Session.GetPrompt(125)); - MsgBase^.YoursNext; + Session.io.PromptInfo[1] := strI2S(Total); + Session.io.PromptInfo[2] := MsgBase^.GetFrom; + Session.io.PromptInfo[3] := MsgBase^.GetSubj; + Session.io.PromptInfo[4] := MsgBase^.GetDate; + + Session.io.OutFullLn (Session.GetPrompt(126)); + End; + + MsgBase^.SeekNext; End; - If Session.io.GetYN (Session.GetPrompt(127), True) Then Begin - MsgBase^.CloseMsgBase; - Dispose (MsgBase, Done); + MsgBase^.CloseMsgBase; - ReadMessages('E', ''); + Dispose (MsgBase, Done); + End; + + Session.LastScanHadNew := UnRead > 0; + + If Total = 0 Then + Session.io.OutFullLn (Session.GetPrompt(124)) + Else Begin + Session.io.PromptInfo[1] := strI2S(Total); + Session.io.PromptInfo[2] := strI2S(UnRead); + + If Session.io.GetYN (Session.GetPrompt(127), UnRead > 0) Then Begin + ReadMessages('E', '', ''); Session.io.OutFullLn (Session.GetPrompt(118)); - - MBase := Old; - Exit; End; - End Else - Session.io.OutFullLn (Session.GetPrompt(124)); - - MsgBase^.CloseMsgBase; - - Dispose (MsgBase, Done); - - MBase := Old; + End; + MBase := TempBase; End; Procedure TMsgBase.SetMessagePointers; @@ -2999,6 +3014,7 @@ Var While MsgBase^.SeekFound Do Begin MsgBase^.MsgStartUp; + If DateStr2Dos(MsgBase^.GetDate) >= NewDate Then Begin MsgBase^.SetLastRead(Session.User.UserNum, MsgBase^.GetMsgNum - 1); Found := True; @@ -3047,12 +3063,14 @@ Procedure TMsgBase.MessageNewScan (Data: String); { /M : scan only mandatory bases } { /G : scan all bases in all groups } Var - Old : RecMessageBase; - Mode : Char; - Mand : Boolean; + Old : RecMessageBase; + Mode : Char; + Mand : Boolean; + CmdData : String; Begin - Old := MBase; - Mand := False; + Old := MBase; + Mand := False; + FileMode := 66; Reset (MBaseFile); @@ -3072,6 +3090,12 @@ Begin Session.User.IgnoreGroup := Pos('/G', Data) > 0; WereMsgs := False; + CmdData := ''; + + If Pos('/NOLR', Data) > 0 Then CmdData := '/NOLR'; + If Pos('/NOFROM', Data) > 0 Then CmdData := CmdData + '/NOFROM'; + If Pos('/NOREAD', Data) > 0 Then CmdData := CmdData + '/NOREAD'; + Session.io.OutRawLn (''); While Not Eof(MBaseFile) Do Begin @@ -3085,7 +3109,7 @@ Begin Session.io.OutFull (Session.GetPrompt(130)); Session.io.BufFlush; - If Not ReadMessages(Mode, '') Then Begin + If Not ReadMessages(Mode, CmdData, '') Then Begin Session.io.OutRawLn(''); Break; End; @@ -3126,12 +3150,12 @@ Begin Session.User.IgnoreGroup := Mode = 'A'; If Mode = 'C' Then - ReadMessages('S', SearchStr) + ReadMessages('S', '', SearchStr) Else Begin Session.io.OutRawLn (''); Reset (MBaseFile); - Read (MBaseFile, MBase); {skip email base} + Read (MBaseFile, MBase); While Not Eof(MBaseFile) Do Begin Read (MBaseFile, MBase); @@ -3140,7 +3164,7 @@ Begin GetMessageScan; If MScan.NewScan > 0 Then Begin - If Not ReadMessages('T', SearchStr) Then Begin + If Not ReadMessages('T', '', SearchStr) Then Begin Session.io.OutRawLn(''); Break; End; @@ -3151,6 +3175,7 @@ Begin End; Session.io.OutFull (Session.GetPrompt(311)); + Close (MBaseFile); End; @@ -3177,7 +3202,7 @@ Var Begin Session.SystemLog ('Sending mass mail to ' + MsgTo); - AssignMessageData(MsgBase); + AssignMessageData (MsgBase, MBase); MsgBase^.SetFrom (MsgFrom); MsgBase^.SetTo (MsgTo); @@ -3277,7 +3302,7 @@ Begin Lines := 0; - If Editor(Lines, 78, mysMaxMsgLines, False, fn_tplMsgEdit, MsgSubj) Then Begin + If Editor(Lines, ColumnValue[Session.Theme.ColumnSize] - 2, mysMaxMsgLines, False, fn_tplMsgEdit, MsgSubj) Then Begin Session.io.OutFullLn (Session.GetPrompt(394)); OLD := MBase; @@ -3350,32 +3375,38 @@ Begin Read (MBaseFile, MBase); Close (MBaseFile); - ReadMessages('B', ''); + ReadMessages('B', '', ''); MBase := Old; End; Procedure TMsgBase.MessageQuickScan (Data: String); -// defaults to ALL groups/bases +// Defaults to ALL groups/bases // /CURRENT = scan only current message base // /GROUP = scan only current group bases -// options: -// /NOSCAN = do not show "scanning" prompt -// /NOFOOT = do not show "end of scan" prompt -// /NOHEAD = do not show "starting quickscan" prompt -// Only scans bases that they have selected in Newscan, of course -Const - Global_CurBase : LongInt = 1; - Global_TotalBases : LongInt = 1; - Global_TotalMsgs : LongInt = 0; - Global_NewMsgs : LongInt = 0; - Global_YourMsgs : LongInt = 0; - ShowIfNew : Boolean = False; - ShowIfYou : Boolean = False; - ShowScanPrompt : Boolean = True; - ShowHeadPrompt : Boolean = True; - ShowFootPrompt : Boolean = True; - Mode : Char = 'A'; +// other options: +// /LIST = List messages +// /NEW = only show/list if base has new or msg is new +// /YOU = only show/list if base has your msgs or is your msg +// /NOFOOT = dont show footer prompt +// /NOSCAN = do not show "scanning" prompt +// /NOFROM = bypass messages posted FROM the user +// /NOREAD = bypass messages addressed to, and read by, the user +Var + NoFrom : Boolean; + NoRead : Boolean; + ShowIfNew : Boolean; + ShowIfYou : Boolean; + ShowScanPrompt : Boolean; + ShowFootPrompt : Boolean; + ShowMessage : Boolean; + ShowMessagePTR : LongInt; + Global_CurBase : LongInt; + Global_TotalBases : LongInt; + Global_TotalMsgs : LongInt; + Global_NewMsgs : LongInt; + Global_YourMsgs : LongInt; + Mode : Char; Procedure ScanBase; Var @@ -3393,10 +3424,11 @@ Const If ShowScanPrompt Then Begin Session.io.OutFull(Session.GetPrompt(487)); + Session.io.BufFlush; End; - GetMessageStats(MBase, TotalMsgs, NewMsgs, YourMsgs); + GetMessageStats(ShowMessage, ShowScanPrompt, ShowIfYou, ShowMessagePTR, MBase, NoFrom, NoRead, TotalMsgs, NewMsgs, YourMsgs); Inc (Global_TotalMsgs, TotalMsgs); Inc (Global_NewMsgs, NewMsgs); @@ -3412,6 +3444,7 @@ Const If ShowScanPrompt Then Session.io.OutBS(Screen.CursorX, True); + If Not ShowMessage Then If (ShowIfNew And (NewMsgs > 0)) or (ShowIfYou And (YourMsgs > 0)) or (Not ShowIfNew And Not ShowIfYou) Then Begin Session.io.OutFullLn(Session.GetPrompt(488)); Session.io.BufFlush; @@ -3421,26 +3454,39 @@ Const Var Old : RecMessageBase; Begin + Session.LastScanHadNew := False; + Session.LastScanHadYou := False; + + Global_CurBase := 1; + Global_TotalBases := 1; + Global_TotalMsgs := 0; + Global_NewMsgs := 0; + Global_YourMsgs := 0; + ShowMessagePTR := 0; + Mode := 'A'; + FillChar(Session.io.PromptInfo, SizeOf(Session.io.PromptInfo), 0); If Pos('/GROUP', Data) > 0 Then Mode := 'G'; If Pos('/CURRENT', Data) > 0 Then Mode := 'C'; - ShowScanPrompt := Pos('/NOSCAN', Data) = 0; - ShowHeadPrompt := Pos('/NOHEAD', Data) = 0; + ShowMessage := Pos('/LIST', Data) > 0; ShowFootPrompt := Pos('/NOFOOT', Data) = 0; + ShowScanPrompt := Pos('/NOSCAN', Data) = 0; + ShowIfNew := Pos('/NEW', Data) > 0; + ShowIfYou := Pos('/YOU', Data) > 0; + NoFrom := Pos('/NOFROM', Data) > 0; + NoRead := Pos('/NOREAD', Data) > 0; Old := MBase; Session.User.IgnoreGroup := Mode = 'A'; - If ShowHeadPrompt Then - Session.io.OutFullLn (Session.GetPrompt(486)); + FileMode := 66; If Mode = 'C' Then ScanBase Else Begin Reset (MBaseFile); - Read (MBaseFile, MBase); {skip email base} Global_TotalBases := FileSize(MBaseFile); @@ -3459,6 +3505,16 @@ Begin Close (MBaseFile); End; + Session.LastScanHadNew := Global_NewMsgs > 0; + Session.LastScanHadYou := Global_YourMsgs > 0; + + Session.io.PromptInfo[1] := strComma(Global_TotalMsgs); + Session.io.PromptInfo[2] := strComma(Global_NewMsgs); + Session.io.PromptInfo[3] := strComma(Global_YourMsgs); + + If ShowMessagePTR > 0 Then + Session.io.OutFull(Session.GetPrompt(508)); + If ShowFootPrompt Then Session.io.OutFullLn(Session.GetPrompt(489)); @@ -3724,11 +3780,44 @@ Const CRLF = #13#10; Var tFile : Text; + Flags : String; Begin Assign (tFile, Session.TempPath + 'toreader.ext'); ReWrite (tFile); + Write (tFile, 'ALIAS ' + Session.User.ThisUser.Handle + CRLF); - Write (tFile, 'ALIAS ' + Session.User.ThisUser.Handle + CRLF); + Reset (MBaseFile); + + While Not Eof(MBaseFile) Do Begin + Read (MBaseFile, MBase); + + If Session.User.Access(MBase.ReadACS) Then Begin + Flags := ' '; + + If MBase.Flags AND MBPrivate = 0 Then + Flags := Flags + 'aO' + Else + Flags := Flags + 'pP'; + + If MBase.Flags AND MBRealNames = 0 Then + Flags := Flags + 'H'; + + If Not Session.User.Access(MBase.PostACS) Then + Flags := Flags + 'BRZ'; + + Case MBase.NetType of + 0 : Flags := Flags + 'L'; + 1 : Flags := Flags + 'E'; + 2 : Flags := Flags + 'U'; + 3 : Flags := Flags + 'N'; + End; + + If MBase.DefQScan = 2 Then + Flags := Flags + 'F'; + + Write (tFile, 'AREA ' + strI2S(MBase.Index) + Flags, CRLF); + End; + End; Close (tFile); End; @@ -3853,11 +3942,11 @@ Begin MsgBase^.MsgStartUp; - If MsgBase^.IsPriv Then - If Not ((MsgBase^.GetTo = Session.User.ThisUser.RealName) or (MsgBase^.GetTo = Session.User.ThisUser.Handle)) Then Begin - MsgBase^.SeekNext; - Continue; - End; + If MsgBase^.IsPriv And Not Session.User.IsThisUser(MsgBase^.GetTo) Then Begin + MsgBase^.SeekNext; + + Continue; + End; Inc (MsgAdded); Inc (TotalMsgs); @@ -4171,7 +4260,7 @@ Begin If OpenCreateBase(MsgBase, TempBase) Then Begin - AssignMessageData(MsgBase); + AssignMessageData(MsgBase, TempBase); QwkBlock[0] := #25; Move (QwkHeader.UpTo, QwkBlock[1], 25); diff --git a/mystic/bbs_msgbase_abs.pas b/mystic/bbs_msgbase_abs.pas index cd509a4..ba79bbe 100644 --- a/mystic/bbs_msgbase_abs.pas +++ b/mystic/bbs_msgbase_abs.pas @@ -98,9 +98,9 @@ Type Procedure SeekNext; Virtual; {Find next matching msg} Procedure SeekPrior; Virtual; {Prior msg} Function SeekFound: Boolean; Virtual; {Msg was found} - Procedure YoursFirst(Name: String; Handle: String); Virtual; {Seek your mail} - Procedure YoursNext; Virtual; {Seek next your mail} - Function YoursFound: Boolean; Virtual; {Message found} +// Procedure YoursFirst(Name: String; Handle: String); Virtual; {Seek your mail} +// Procedure YoursNext; Virtual; {Seek next your mail} +// Function YoursFound: Boolean; Virtual; {Message found} Function GetHighMsgNum: LongInt; Virtual; {Get highest msg number} Procedure SetMailType(MT: MsgMailType); Virtual; {Set message base type} // Function GetSubArea: Word; Virtual; {Get sub area number} @@ -496,6 +496,7 @@ Procedure TMsgBaseABS.MsgTxtStartUp; Begin End; +(* Procedure TMsgBaseABS.YoursFirst(Name: String; Handle: String); Begin End; @@ -507,7 +508,7 @@ End; Function TMsgBaseABS.YoursFound: Boolean; Begin End; - +*) Function TMsgBaseABS.CreateMsgBase(MaxMsg: Word; MaxDays: Word): Boolean; Begin End; diff --git a/mystic/bbs_msgbase_ansi.pas b/mystic/bbs_msgbase_ansi.pas index dd42ab4..20ac0ac 100644 --- a/mystic/bbs_msgbase_ansi.pas +++ b/mystic/bbs_msgbase_ansi.pas @@ -32,11 +32,12 @@ Type SavedY : Byte; CurX : Byte; Attr : Byte; + LastChar : Char; Procedure SetFore (Color: Byte); Procedure SetBack (Color: Byte); Procedure ResetControlCode; - Function ParseNumber (Var Line: String) : Integer; + Function ParseNumber : Integer; Function AddChar (Ch: Char) : Boolean; Procedure MoveXY (X, Y: Word); Procedure MoveUP; @@ -130,28 +131,21 @@ Begin End; End; -Function TMsgBaseAnsi.ParseNumber (Var Line: String) : Integer; +Function TMsgBaseAnsi.ParseNumber : Integer; Var - A : Integer; - B : LongInt; - Str1 : String; - Str2 : String; + Res : LongInt; + Str : String; Begin - Str1 := Line; + Val(Code, Result, Res); - Val(Str1, A, B); - - If B = 0 Then - Str1 := '' + If Res = 0 Then + Code := '' Else Begin - Str2 := Copy(Str1, 1, B - 1); + Str := Copy(Code, 1, Pred(Res)); - Delete (Str1, 1, B); - Val (Str2, A, B); + Delete (Code, 1, Res); + Val (Str, Result, Res); End; - - Line := Str1; - ParseNumber := A; End; Procedure TMsgBaseAnsi.MoveXY (X, Y: Word); @@ -168,11 +162,13 @@ Var X : Byte; Y : Byte; Begin - X := ParseNumber(Code); - Y := ParseNumber(Code); + Y := ParseNumber; + + If Y = 0 Then Y := 1; + + X := ParseNumber; If X = 0 Then X := 1; - If Y = 0 Then Y := 1; MoveXY (X, Y); @@ -184,7 +180,7 @@ Var NewPos : Integer; Offset : Integer; Begin - Offset := ParseNumber (Code); + Offset := ParseNumber; If Offset = 0 Then Offset := 1; @@ -202,7 +198,7 @@ Procedure TMsgBaseAnsi.MoveDOWN; Var NewPos : Byte; Begin - NewPos := ParseNumber (Code); + NewPos := ParseNumber; If NewPos = 0 Then NewPos := 1; @@ -216,7 +212,7 @@ Var NewPos : Integer; Offset : Integer; Begin - Offset := ParseNumber (Code); + Offset := ParseNumber; If Offset = 0 Then Offset := 1; @@ -235,7 +231,7 @@ Var NewPos : Integer; Offset : Integer; Begin - Offset := ParseNumber(Code); + Offset := ParseNumber; If Offset = 0 Then Offset := 1; @@ -278,7 +274,7 @@ Begin 'h' : ResetControlCode; 'm' : Begin While Length(Code) > 0 Do Begin - Case ParseNumber(Code) of + Case ParseNumber of 0 : Attr := 7; 1 : Attr := Attr OR $08; 5 : Attr := Attr OR $80; @@ -327,16 +323,18 @@ Begin PipeCode := PipeCode + Ch; If Length(PipeCode) = 2 Then Begin - - Case strS2I(PipeCode) of - 00.. - 15 : SetFore(strS2I(PipeCode)); - 16.. - 23 : SetBack(strS2I(PipeCode) - 16); + If PipeCode = '00' Then + SetFore(0) Else - AddChar('|'); - AddChar(PipeCode[1]); - AddChar(PipeCode[2]); + Case strS2I(PipeCode) of + 01.. + 15 : SetFore(strS2I(PipeCode)); + 16.. + 23 : SetBack(strS2I(PipeCode) - 16); + Else + AddChar('|'); + AddChar(PipeCode[1]); + AddChar(PipeCode[2]); End; GotPipe := False; @@ -349,13 +347,15 @@ Begin Case Escape of 0 : Begin Case Ch of - #27 : Escape := 1; + #0 : ; #9 : MoveXY (CurX + 8, CurY); #12 : GotClear := True; + #13 : CurX := 1; + #27 : Escape := 1; Else - If Ch = '|' Then - GotPipe := True - Else +// If Ch = '|' Then +// GotPipe := True +// Else AddChar (Ch); ResetControlCode; @@ -372,6 +372,8 @@ Begin Else ResetControlCode; End; + + LastChar := Ch; End; Function TMsgBaseAnsi.ProcessBuf (Var Buf; BufLen: Word) : Boolean; @@ -383,14 +385,18 @@ Begin For Count := 1 to BufLen Do Begin If CurY > Lines Then Lines := CurY; + Case Buffer[Count] of #10 : If CurY = mysMaxMsgLines Then Begin Result := True; GotAnsi := False; + Break; - End Else + End Else Begin Inc (CurY); - #13 : CurX := 1; + + If LastChar <> #13 Then CurX := 1; + End; #26 : Begin Result := True; Break; diff --git a/mystic/bbs_msgbase_jam.pas b/mystic/bbs_msgbase_jam.pas index 4d81e35..18ca1bc 100644 --- a/mystic/bbs_msgbase_jam.pas +++ b/mystic/bbs_msgbase_jam.pas @@ -219,9 +219,9 @@ Type // Function IsEchoed : Boolean; Virtual; {Msg should be echoed} Function GetMsgLoc : LongInt; Virtual; {Msg location} Procedure SetMsgLoc (ML: LongInt); Virtual; {Msg location} - Procedure YoursFirst (Name: String; Handle: String); Virtual; {Seek your mail} - Procedure YoursNext; Virtual; {Seek next your mail} - Function YoursFound : Boolean; Virtual; {Message found} +// Procedure YoursFirst (Name: String; Handle: String); Virtual; {Seek your mail} +// Procedure YoursNext; Virtual; {Seek next your mail} +// Function YoursFound : Boolean; Virtual; {Message found} Procedure StartNewMsg; Virtual; Function OpenMsgBase : Boolean; Virtual; Procedure CloseMsgBase; Virtual; @@ -246,7 +246,7 @@ Type Function ReReadIdx (Var IdxLoc : LongInt) : Word; End; -Function JamStrCrc(St: String): LongInt; +Function JamStrCrc (St: String): LongInt; Implementation @@ -298,7 +298,7 @@ Begin If TxtBuf <> Nil Then Dispose(TxtBuf); End; -Function JamStrCrc(St: String): LongInt; +Function JamStrCrc (St: String): LongInt; Var i: Word; crc: LongInt; @@ -311,7 +311,7 @@ Begin JamStrCrc := Crc; End; -Procedure TMsgBaseJAM.SetMsgPath(St: String); +Procedure TMsgBaseJAM.SetMsgPath (St: String); Begin JM^.MsgPath := Copy(St, 1, 124); End; @@ -326,52 +326,52 @@ Begin JM^.Dest := Addr; End; -Procedure TMsgBaseJAM.SetOrig(Addr: RecEchoMailAddr); +Procedure TMsgBaseJAM.SetOrig (Addr: RecEchoMailAddr); Begin JM^.Orig := Addr; End; -Procedure TMsgBaseJAM.SetFrom(Name: String); +Procedure TMsgBaseJAM.SetFrom (Name: String); Begin JM^.MsgFrom := Name; End; -Procedure TMsgBaseJAM.SetTo(Name: String); +Procedure TMsgBaseJAM.SetTo (Name: String); Begin JM^.MsgTo := Name; End; -Procedure TMsgBaseJAM.SetSubj(Str: String); +Procedure TMsgBaseJAM.SetSubj (Str: String); Begin JM^.MsgSubj := Str; End; -Procedure TMsgBaseJAM.SetCost(SCost: Word); +Procedure TMsgBaseJAM.SetCost (SCost: Word); Begin MsgHdr^.JamHdr.Cost := SCost; End; -Procedure TMsgBaseJAM.SetRefer(SRefer: LongInt); +Procedure TMsgBaseJAM.SetRefer (SRefer: LongInt); Begin MsgHdr^.JamHdr.ReplyTo := SRefer; End; -Procedure TMsgBaseJAM.SetSeeAlso(SAlso: LongInt); +Procedure TMsgBaseJAM.SetSeeAlso (SAlso: LongInt); Begin MsgHdr^.JamHdr.ReplyFirst := SAlso; End; -Procedure TMsgBaseJAM.SetDate(SDate: String); +Procedure TMsgBaseJAM.SetDate (SDate: String); Begin JM^.MsgDate := SDate; End; -Procedure TMsgBaseJAM.SetTime(STime: String); +Procedure TMsgBaseJAM.SetTime (STime: String); Begin JM^.MsgTime := STime; End; -Procedure TMsgBaseJAM.SetAttr1(Mask: LongInt; St: Boolean); +Procedure TMsgBaseJAM.SetAttr1 (Mask: LongInt; St: Boolean); Begin If St Then MsgHdr^.JamHdr.Attr1 := MsgHdr^.JamHdr.Attr1 Or Mask @@ -379,67 +379,67 @@ Procedure TMsgBaseJAM.SetAttr1(Mask: LongInt; St: Boolean); MsgHdr^.JamHdr.Attr1 := MsgHdr^.JamHdr.Attr1 And (Not Mask); End; -Procedure TMsgBaseJAM.SetLocal(LS: Boolean); +Procedure TMsgBaseJAM.SetLocal (LS: Boolean); Begin SetAttr1(Jam_Local, LS); End; -Procedure TMsgBaseJAM.SetRcvd(RS: Boolean); +Procedure TMsgBaseJAM.SetRcvd (RS: Boolean); Begin SetAttr1(Jam_Rcvd, RS); End; -Procedure TMsgBaseJAM.SetPriv(PS: Boolean); +Procedure TMsgBaseJAM.SetPriv (PS: Boolean); Begin SetAttr1(Jam_Priv, PS); End; -Procedure TMsgBaseJAM.SetHold(SS: Boolean); +Procedure TMsgBaseJAM.SetHold (SS: Boolean); Begin SetAttr1 (Jam_Hold, SS); End; -Procedure TMsgBaseJAM.SetCrash(SS: Boolean); +Procedure TMsgBaseJAM.SetCrash (SS: Boolean); Begin SetAttr1(Jam_Crash, SS); End; -Procedure TMsgBaseJAM.SetKillSent(SS: Boolean); +Procedure TMsgBaseJAM.SetKillSent (SS: Boolean); Begin SetAttr1(Jam_KillSent, SS); End; -Procedure TMsgBaseJAM.SetSent(SS: Boolean); +Procedure TMsgBaseJAM.SetSent (SS: Boolean); Begin SetAttr1(Jam_Sent, SS); End; -Procedure TMsgBaseJAM.SetFAttach(SS: Boolean); +Procedure TMsgBaseJAM.SetFAttach (SS: Boolean); Begin SetAttr1(Jam_FAttch, SS); End; -Procedure TMsgBaseJAM.SetReqRct(SS: Boolean); +Procedure TMsgBaseJAM.SetReqRct (SS: Boolean); Begin SetAttr1(Jam_RcptReq, SS); End; -Procedure TMsgBaseJAM.SetReqAud(SS: Boolean); +Procedure TMsgBaseJAM.SetReqAud (SS: Boolean); Begin SetAttr1(Jam_ConfmReq, SS); End; -Procedure TMsgBaseJAM.SetRetRct(SS: Boolean); +Procedure TMsgBaseJAM.SetRetRct (SS: Boolean); Begin End; -Procedure TMsgBaseJAM.SetFileReq(SS: Boolean); +Procedure TMsgBaseJAM.SetFileReq (SS: Boolean); Begin SetAttr1(Jam_Freq, SS); End; -Procedure TMsgBaseJAM.DoString(Str: String); +Procedure TMsgBaseJAM.DoString (Str: String); Var i: Word; Begin @@ -1354,7 +1354,7 @@ Procedure TMsgBaseJAM.SetMsgLoc(ML: LongInt); {Msg location} Begin JM^.CurrMsgNum := ML; End; - +(* Procedure TMsgBaseJAM.YoursFirst (Name: String; Handle: String); Begin JM^.YourName := Name; @@ -1422,6 +1422,7 @@ Function TMsgBaseJAM.YoursFound: Boolean; Begin YoursFound := ((JM^.CurrMsgNum >= JM^.BaseHdr.BaseMsgNum) and (JM^.CurrMsgNum <= GetHighMsgNum)); End; +*) Procedure TMsgBaseJAM.StartNewMsg; Begin diff --git a/mystic/bbs_msgbase_squish.pas b/mystic/bbs_msgbase_squish.pas index cd4c39d..f90a05c 100644 --- a/mystic/bbs_msgbase_squish.pas +++ b/mystic/bbs_msgbase_squish.pas @@ -262,9 +262,9 @@ Type Function GetMsgLoc: LongInt; Virtual; {To allow reseeking to message} Procedure SetMsgLoc(ML: LongInt); Virtual; {Reseek to message} Function IdxHighest: LongInt; Virtual; { *** } - Procedure YoursFirst(Name: String; Handle: String); Virtual; {Seek your mail} - Procedure YoursNext; Virtual; {Seek next your mail} - Function YoursFound: Boolean; Virtual; {Message found} +// Procedure YoursFirst(Name: String; Handle: String); Virtual; {Seek your mail} +// Procedure YoursNext; Virtual; {Seek next your mail} +// Function YoursFound: Boolean; Virtual; {Message found} Function GetMsgDisplayNum: LongInt; Virtual; {Get msg number to display} Function GetTxtPos: LongInt; Virtual; {Get indicator of msg text position} Procedure SetTxtPos(TP: LongInt); Virtual; {Set text position} @@ -1513,6 +1513,7 @@ Begin SeekFirst(ML); End; +(* Procedure TMsgBaseSquish.YoursFirst (Name: String; Handle: String); Begin SqInfo^.CurrIdx := 0; @@ -1554,7 +1555,7 @@ Function TMsgBaseSquish.YoursFound: Boolean; Begin YoursFound := SqInfo^.CurrIdx <= SqInfo^.SqBase.NumMsg; End; - +*) Function TMsgBaseSquish.GetMsgDisplayNum: LongInt; Begin GetMsgDisplayNum := SqInfo^.CurrIdx; diff --git a/mystic/bbs_nodelist.pas b/mystic/bbs_nodelist.pas index 66d75c6..1dab87a 100644 --- a/mystic/bbs_nodelist.pas +++ b/mystic/bbs_nodelist.pas @@ -74,7 +74,11 @@ Begin A := Pos(':', SearchStr); B := Pos('/', SearchStr); - AddrSearch := Not (A = 0) or (B <= A); + If (A = 0) or (B <= A) Then + AddrSearch := False + Else + AddrSearch := True; +// AddrSearch := Not (A = 0) or (B <= A); If AddrSearch Then Begin SearchZone := Copy(SearchStr, 1, A - 1); diff --git a/mystic/bbs_user.pas b/mystic/bbs_user.pas index cb5680f..b7f79e0 100644 --- a/mystic/bbs_user.pas +++ b/mystic/bbs_user.pas @@ -62,7 +62,7 @@ Type Procedure GetOption2 (Edit: Boolean); Procedure GetOption3 (Edit: Boolean); Procedure GetTheme; - Procedure UserLogon1 (Var UN, PW, MPE : String); + Procedure UserLogon1 (Var MPE : String); Procedure UserLogon2; Procedure UserLogon3; Procedure CreateNewUser (DefName: String); @@ -163,6 +163,7 @@ Var 'A' : Res := Chat.Available; 'I' : Res := Chat.Invisible; 'K' : Res := AcsOkFlag; + 'N' : Res := Session.LastScanHadNew; 'M' : Begin Res := Access(Session.Msgs.MBase.SysopACS); @@ -175,6 +176,7 @@ Var Res := (Temp2 >= Temp1); End Else Res := True; + 'Y' : Res := Session.LastScanHadYou; End; 'S' : Res := ThisUser.Security >= strS2I(Data); 'T' : Res := Session.TimeLeft > strS2I(Data); @@ -1171,7 +1173,7 @@ Begin {$ENDIF} End; -Procedure TBBSUser.UserLogon1 (Var UN, PW, MPE : String); +Procedure TBBSUser.UserLogon1 (Var MPE: String); Var A : Integer; Count : Byte; @@ -1182,7 +1184,7 @@ Begin Session.io.Graphics := 0; - Session.systemLog ('-'); + Session.SystemLog ('-'); Session.SystemLog ('Connect from ' + Session.UserIPInfo + ' (' + Session.UserHostInfo + ')'); Session.HistoryHour := strS2I(Copy(TimeDos2Str(CurDateDos, False), 1, 2)); @@ -1194,11 +1196,7 @@ Begin Halt(0); End; - //Session.io.OutFullLn('|CL|CR' + strPadC(mysSoftwareID + ' BBS Version ' + mysVersion + ' for ' + OSID, 79, ' ')); - //Session.io.OutFullLn(strPadC(CopyID, 79, ' ')); - //Session.io.OutFullLn('|CR' + strPadC(mysWebSite, 79, ' ')); - - Session.io.OutFullLn ('|CL' + mysSoftwareID + ' BBS Version ' + mysVersion + ' for ' + OSID + ' : Node |ND'); + Session.io.OutFullLn ('|CL' + mysSoftwareID + ' BBS v' + mysVersion + ' for ' + OSID + ' Node |ND'); Session.io.OutFullLn (CopyID); If Config.DefTermMode = 0 Then @@ -1213,9 +1211,6 @@ Begin If Config.ThemeOnStart Then GetTheme; - If FileExist(Config.ScriptPath + 'startup.mpx') Then - ExecuteMPL(NIL, 'startup'); - If (Session.Theme.Flags AND ThmAllowASCII = 0) and (Session.io.Graphics = 0) Then Begin Session.io.OutFullLn (Session.GetPrompt(321)); Session.SystemLog ('ASCII login disabled'); @@ -1227,11 +1222,14 @@ Begin Halt(0); End; - If UN <> '' Then Begin - If Not FindUser(UN, True) Then + If FileExist(Config.ScriptPath + 'startup.mpx') Then + ExecuteMPL(NIL, 'startup'); + + If Session.UserLoginName <> '' Then Begin + If Not FindUser(Session.UserLoginName, True) Then Halt; - If strUpper(PW) <> TempUser.Password Then Begin + If strUpper(Session.UserLoginPW) <> TempUser.Password Then Begin UserNum := -1; Halt; End; diff --git a/mystic/default.txt b/mystic/default.txt index a3d12ce..e5d46c1 100644 --- a/mystic/default.txt +++ b/mystic/default.txt @@ -196,7 +196,7 @@ ; &1 = base number &2 = base name &3 = scan base? (Yes or No) 093 |07|$R04|&1|15|$R03|&3 |07|$R29|&2 094 |CR|12There are no available message bases! -095 |09|$D77Ä|CR |09Selection |01[|10##|01]|09, |01[|10##|01-|10##|01]|09, |01[|10?|01/|10List|01]|09, or |01[|10Q|01]|09uit: |XX +095 |09Selection |01[|10##|01]|09, |01[|10##|01-|10##|01]|09, |01[|10?|01/|10List|01]|09, or |01[|10Q|01]|09uit: |XX ; For strings 096 - 099: &1 = message base name 096 |CR |11|&1 will NOT be scanned in QWK packets!|CR 097 |CR |11|&1 will be scanned in QWK packets!|CR @@ -223,7 +223,7 @@ ; E-mail reader prompt 115 |CR|09(A)gain, (P)revious, (N)ext, (R)eply, (D)elete, (J)ump, (Q)uit? |11 ; Message read prompt. &1 = Current Msg # &2 = Total Messages -116 |CR (|&1 of |&2) Reading Messages (?/Help): |XX +116 |CR|01[|09|&1 of |&2|01] |09Reading Messages (|10?|09/|10Help|09): |11 117 |CR|12Delete this mail? |11 118 |CR|15End of messages. ; Post message TO: @@ -241,7 +241,8 @@ ; &1 = email number &2 = email from ; &3 = email subject &4 = email date 126 |07|$R05|&1|15|$R32|&2|10|$R32|&3|11|&4 -127 |01|$D77Ä |CR |01[|10þ|01] |09Read waiting mail? |11 +; Read new email? &1 = total &2 = unread +127 |01|$D77Ä |CR |01[|10þ|01] |09You have |11|&1 |09messages (|11|&2 |09unread|09). Read them now? |11 ; First message in thread prompt 128 |CR|11This is the first message in the thread. ; User lockout message. @@ -372,7 +373,7 @@ ; &1 = File base number &2 = File base name &3 = Scan? (Yes or No) 201 |07|$R04|&1|15|$R03|&3 |07|$R29|&2 ; Select scanned file bases prompt -202 |09|$D77Ä|CR |09Selection |01[|10##|01]|09, |01[|10##|01-|10##|01]|09, |01[|10?|01/|10List|01]|09, or |01[|10Q|01]|09uit: |XX +202 |09Selection |01[|10##|01]|09, |01[|10##|01-|10##|01]|09, |01[|10?|01/|10List|01]|09, or |01[|10Q|01]|09uit: |XX ; &1 = File base name 203 |CR |11|&1 will NOT be scanned in new file scan!|CR ; &1 = File base name @@ -395,7 +396,7 @@ ; Lightbar file list: Access to file denied. 212 |12File is not available.|PN ; Read Message personal prompt. &1 = Current Msg # &2 = Total Messages -213 |CR|09[|&1 of |&2] Reading Messages (?/Help): |XX +213 |CR|01[|09|&1 of |&2|01] |09Reading Messages (|10?|09/|10Help|09): |11 ; File group list header 214 |CL|CR|$D13 |09Ú|$D54Ä|01¿|CR|$D13 |09³|17 ± |15File Groups|$D40 |16|01³|CR|$D13 |09À|01|$D54ÄÙ|CR|$D14 |10#|02# |10F|02ile |10G|02roup |10N|02ame|07|$D29 |02A|10reas|CR|$D14 |09|$D54Ä ; File group list format @@ -772,7 +773,7 @@ ; Ansi msg read: delete msg 402 |CR|12Delete this mail? |11 ; Ansi msg read: jump to msg: &1 = cur msg num &2 = high msg num -403 |CR|09Jump to which message? (1-|&2): |XX +403 |CR|09Jump to which message? (|101|09-|10|&2|09): |11 ; Ansi msg read: scan toggle &1 = message base name 404 |CR|11|&1 will NOT be scanned in new message scan! 405 |CR|11|&1 will be scanned in new message scan! @@ -820,7 +821,7 @@ ; new user: use lightbar message index? 429 |CR|12Use lightbar message index? |11 ; msg scan setting footer -430 +430 |09|$D77Ä|CR ; Lightbar file list: #/filename: ; &1 = filenum, &2 = filename, &3 = tag char &4 = size &5 = date &6 = DLs 431 |07|&1|12|&3|15|$R57|&2 |09|$L07|&4 |&5 @@ -860,7 +861,7 @@ ; info edit: option 3 448 |CR|09Enter optional field 3: |XX ; file new scan setting footer -449 +449 |09|$D77Ä|CR ; private post (email) TO: 450 |CR|09To: |XX ; reply msg SUBJ @@ -947,11 +948,11 @@ 484 |16|CL|09|17 ° |15Chat mode end.|$X79 |16|DE|DE ; User2User accept chat page request? &1=user &2=Node 485 |16|CL|15|&1 is requesting private user chat. Accept? |11 -; MsgBase quickscan header prompt -486 |CR|12Starting Quick Scan|CR +; +486 UNUSED ; MsgBase quickscan Scanning prompt ; &1=basename &2=current base# &3=total bases# -487 Scanning |&1 [|&2 of |&3]... +487 |03Scanning |11|&1 |03[|11|&2 |03of |11|&3|03]|08... ; MsgBase quickscan base list prompt ; &4=msgs in base &5=new messages &6=your messages &7=global total msg ; &8=global new msgs &9=global your msgs @@ -959,9 +960,9 @@ ; MsgBase quickscan footer prompt ; &7=global total msg &8=global new msgs &9=global your msgs 489 |CRQuick Scan complete. |CR|CR|PA -; Msg header flags text one word each separated by a space -; 1=Local 2=Echo 3=Private 4=Sent 5=Delete -490 Local Echo Private Sent Deleted +; Msg header flags text one word each separated by a comma +; 1=Local 2=Echo 3=Private 4=Sent 5=Delete, 6=Received +490 Local,Echo,Priv,Sent,Del,Read ; File base filesize flags one word separated by a space ; 1=offline 2=failed 3=unvalidated 4=GB 5=MB 6=KB 7=B 491 OFFLINE FAILED UNVALID GB MB KB B @@ -992,3 +993,14 @@ ; QWK .REP complete/results prompt ; &1=msgs imported &2=msgs failed &3=bases added to scan &4=bases removed 503 |10SUCCESS|01.|CR|CR|11- |03Posted |11|&1 |03new messages (|11|&2 |03failed)|CR|11- |03Added |11|&3 |03bases to new scan (|11|&4 |03removed).|CR|CR|PA +; Standard message reader: Lastread pointer set &1 = msg number +504 |CR|11Last read pointer has been set to message number |&1.|CR|CR|PA +; Lightbar reader: Lastread pointer set &1 = msg number +505 |CR|11Last read pointer has been set to message number |&1.|CR|CR|PA +; QuickScan message list header &2=basename +506 |15From Base Subject|CR|09=============== ==================== ========================================== +; QuickScan message list middle +; &1=msg# &2=basename &3=from &4=to &5=subject &6=date +507 |10|$R15|&3 |09|$R20|&2 |11|$R42|&5 +; QuicScan message list footer +508 |09|$D79=|CR diff --git a/mystic/mis.pas b/mystic/mis.pas index d4136c2..49e3164 100644 --- a/mystic/mis.pas +++ b/mystic/mis.pas @@ -109,6 +109,12 @@ Begin Halt(1); End; + TempPath := bbsConfig.SystemPath + 'temp0' + PathChar; + + {$I-} MkDir (TempPath); {$I+} + + If IoResult <> 0 Then; + DirChange(bbsConfig.SystemPath); End; diff --git a/mystic/mis_client_nntp.pas b/mystic/mis_client_nntp.pas index 763a9c7..d189916 100644 --- a/mystic/mis_client_nntp.pas +++ b/mystic/mis_client_nntp.pas @@ -184,7 +184,8 @@ Begin 1 : MsgBase := New(PMsgBaseSquish, Init); End; - MsgBase^.SetMsgPath (TempBase.Path + TempBase.FileName); + MsgBase^.SetMsgPath (TempBase.Path + TempBase.FileName); + MsgBase^.SetTempFile (TempPath + 'msgbuf.'); If MsgBase^.OpenMsgBase Then Begin Low := 1; @@ -264,7 +265,8 @@ Begin 1 : MsgBase := New(PMsgBaseSquish, Init); End; - MsgBase^.SetMsgPath (TempBase.Path + TempBase.FileName); + MsgBase^.SetMsgPath (TempBase.Path + TempBase.FileName); + MsgBase^.SetTempFile (TempPath + 'msgbuf.'); If MsgBase^.OpenMsgBase Then Begin LowMessage := 1; @@ -283,6 +285,7 @@ Begin ClientWriteLine('.'); End; +(* Procedure TNNTPServer.cmd_POST; Var MsgBase : PMsgBaseABS; @@ -408,6 +411,196 @@ Begin End; MsgBase^.SetMsgPath (TempBase.Path + TempBase.FileName); + // set tmpbuf + + If Not MsgBase^.OpenMsgBase Then + If Not MsgBase^.CreateMsgBase (TempBase.MaxMsgs, TempBase.MaxAge) Then Begin + Dispose(MsgBase, Done); + MsgText.Free; + Client.WriteLine('441 Cannot save'); + Exit; + End Else + If Not MsgBase^.OpenMsgBase Then Begin + Dispose(MsgBase, Done); + MsgText.Free; + Client.WriteLine('411 Cannot save'); + Exit; + End; + + MsgBase^.StartNewMsg; + + MsgBase^.SetLocal (True); + MsgBase^.SetDate (FormatDateTime('mm/dd/yy', Now)); + MsgBase^.SetTime (FormatDateTime('hh:nn', Now)); + MsgBase^.SetTo ('All'); + MsgBase^.SetSubj (Subject); + + If TempBase.Flags And MBRealNames <> 0 Then + MsgBase^.SetFrom(User.RealName) + Else + MsgBase^.SetFrom(User.Handle); + + If TempBase.NetType > 0 Then Begin + MsgBase^.SetMailType(mmtEchoMail); + + Case TempBase.NetType of + 1 : Assign (SemFile, bbsConfig.SemaPath + fn_SemFileEcho); + 2 : Assign (SemFile, bbsConfig.SemaPath + fn_SemFileNews); + End; + + ReWrite (SemFile); + Close (SemFile); + End Else + MsgBase^.SetMailType(mmtNormal); + + MsgBase^.SetPriv (TempBase.Flags and MBPrivate <> 0); + + For Count := 1 to MsgText.Count Do Begin + InData := MsgText.Strings[Count - 1]; + + If Length(InData) > 79 Then InData[0] := #79; + + MsgBase^.DoStringLn(InData); + End; + + MsgBase^.WriteMsg; + MsgBase^.CloseMsgBase; + + Dispose (MsgBase, Done); + + MsgText.Free; + + ClientWriteLine ('240 Article posted ok'); +End; +*) + +Procedure TNNTPServer.cmd_POST; +Var + MsgBase : PMsgBaseABS; + MBaseFile : File of RecMessageBase; + TempBase : RecMessageBase; + MsgText : TStringList; + Subject : String; + Newsgroup : String; + InData : String; + HackCount : LongInt; + Count : LongInt; + GotStart : Boolean; + Found : Boolean; + SemFile : File; +Begin + If Not LoggedIn Then Begin + ClientWriteLine(re_AuthReq); + Exit; + End; + + ClientWriteLine('340 Send article to be posted. End with .'); + + Subject := ''; + Newsgroup := ''; + GotStart := False; + MsgText := TStringList.Create; + + Repeat + Client.ReadLine(InData); + + If InData = '.' Then Break; + + If Not GotStart And (Pos('Newsgroups:', InData) > 0) Then Begin + Newsgroup := Copy(InData, 13, 255); + + Continue; + End; + + If Not GotStart And (Pos('Subject:', InData) > 0) Then Begin + Subject := Copy(InData, 10, 255); + + Continue; + End; + + If (InData = '') And Not GotStart Then Begin + GotStart := True; + Continue; + End; + + If MsgText.Count >= mysMaxMsgLines Then Begin + HackCount := 0; + + While Not Terminated And (InData <> '.') Do Begin + Client.ReadLine(InData); + + Inc (HackCount); + + If HackCount >= HackThreshold Then Begin + EndSession := True; // someone is being a douchebag + + Server.Status('Flood attempt from ' + Client.PeerIP + '. Goodbye'); + + MsgText.Free; + + Exit; + End; + End; + + Break; + End; + + If GotStart Then MsgText.Add(InData); + Until Terminated; + + If Terminated Then Exit; + + If (Subject = '') Then Begin + MsgText.Free; + + ClientWriteLine('441 No subject; message not posted'); + + Exit; + End; + + Found := False; + + Assign (MBaseFile, bbsConfig.DataPath + 'mbases.dat'); + + If ioReset(MBaseFile, SizeOf(RecMessageBase), fmRWDN) Then Begin + ioRead (MBaseFile, TempBase); + + While Not EOF(MBaseFile) Do Begin + ioRead (MBaseFile, TempBase); + + If TempBase.NewsName = Newsgroup Then Begin + Found := True; + + Break; + End; + End; + End; + + Close (MBaseFile); + + If Not Found or (Newsgroup = '') Then Begin + MsgText.Free; + + ClientWriteLine('441 No newsgroup selected'); + + Exit; + End; + + If Not CheckAccess(User, True, TempBase.PostACS) or (TempBase.NetType = 3) Then Begin + MsgText.Free; + + ClientWriteLine('441 No post access'); + + Exit; + End; + + Case TempBase.BaseType of + 0 : MsgBase := New(PMsgBaseJAM, Init); + 1 : MsgBase := New(PMsgBaseSquish, Init); + End; + + MsgBase^.SetMsgPath (TempBase.Path + TempBase.FileName); + MsgBase^.SetTempFile (TempPath + 'msgbuf.'); If Not MsgBase^.OpenMsgBase Then If Not MsgBase^.CreateMsgBase (TempBase.MaxMsgs, TempBase.MaxAge) Then Begin @@ -493,7 +686,8 @@ Begin 1 : MsgBase := New(PMsgBaseSquish, Init); End; - MsgBase^.SetMsgPath (MBase.Path + MBase.FileName); + MsgBase^.SetMsgPath (MBase.Path + MBase.FileName); + MsgBase^.SetTempFile (TempPath + 'msgbuf.'); If Not MsgBase^.OpenMsgBase Then Begin ClientWriteLine('423 No such article'); @@ -577,7 +771,8 @@ Begin 1 : MsgBase := New(PMsgBaseSquish, Init); End; - MsgBase^.SetMsgPath (MBase.Path + MBase.FileName); + MsgBase^.SetMsgPath (MBase.Path + MBase.FileName); + MsgBase^.SetTempFile (TempPath + 'msgbuf.'); If Not MsgBase^.OpenMsgBase Then Begin ClientWriteLine('420 No article(s) selected'); diff --git a/mystic/mis_client_pop3.pas b/mystic/mis_client_pop3.pas index 134acef..62ec066 100644 --- a/mystic/mis_client_pop3.pas +++ b/mystic/mis_client_pop3.pas @@ -55,6 +55,7 @@ Type Procedure Execute; Override; Destructor Destroy; Override; + Function IsUser (Str: String) : Boolean; Procedure ResetSession; Procedure CreateMailBoxData; Procedure DeleteMessages; @@ -105,6 +106,12 @@ Begin MailSize := 0; End; +Function TPOP3Server.IsUser (Str: String) : Boolean; +Begin + Str := strUpper(Str); + Result := LoggedIn and ((strUpper(User.RealName) = Str) or (strUpper(User.Handle) = Str)); +End; + Procedure TPOP3Server.ResetSession; Var Count : LongInt; @@ -185,41 +192,45 @@ Begin 1 : MsgBase := New(PMsgBaseSquish, Init); End; - MsgBase^.SetMsgPath (MBase.Path + MBase.FileName); + MsgBase^.SetMsgPath (MBase.Path + MBase.FileName); + MsgBase^.SetTempFile (TempPath + 'msgbuf.'); If Not MsgBase^.OpenMsgBase Then Begin Dispose (MsgBase, Done); Exit; End; - MsgBase^.YoursFirst(User.RealName, User.Handle); + MsgBase^.SeekFirst(1); - While MsgBase^.YoursFound Do Begin + While MsgBase^.SeekFound Do Begin MsgBase^.MsgStartup; - MsgBase^.MsgTxtStartup; - Inc (MailSize); + if IsUser(MsgBase^.GetTo) Then Begin + MsgBase^.MsgTxtStartup; - New (MailInfo[MailSize]); + Inc (MailSize); - MailInfo[MailSize].Text := TStringList.Create; + New (MailInfo[MailSize]); - AddLine ('Date: ' + ParseDateTime(MsgBase^.GetDate, MsgBase^.GetTime)); - AddLine ('From: ' + MsgBase^.GetFrom + ' <' + strReplace(MsgBase^.GetFrom, ' ', '_') + '@' + bbsConfig.inetDomain + '>'); - AddLine ('X-Mailer: Mystic BBS ' + mysVersion); - AddLine ('To: ' + MsgBase^.GetTo + ' <' + strReplace(MsgBase^.GetTo, ' ', '_') + '@' + bbsConfig.inetDomain + '>'); - AddLine ('Subject: ' + MsgBase^.GetSubj); - AddLine ('Content-Type: text/plain; charset=us-ascii'); - AddLine (''); + MailInfo[MailSize].Text := TStringList.Create; - While Not MsgBase^.EOM Do - AddLine(MsgBase^.GetString(79)); + AddLine ('Date: ' + ParseDateTime(MsgBase^.GetDate, MsgBase^.GetTime)); + AddLine ('From: ' + MsgBase^.GetFrom + ' <' + strReplace(MsgBase^.GetFrom, ' ', '_') + '@' + bbsConfig.inetDomain + '>'); + AddLine ('X-Mailer: Mystic BBS ' + mysVersion); + AddLine ('To: ' + MsgBase^.GetTo + ' <' + strReplace(MsgBase^.GetTo, ' ', '_') + '@' + bbsConfig.inetDomain + '>'); + AddLine ('Subject: ' + MsgBase^.GetSubj); + AddLine ('Content-Type: text/plain; charset=us-ascii'); + AddLine (''); - MailInfo[MailSize].MD5 := GetMessageUID(MsgBase); - MailInfo[MailSize].GotRETR := False; - MailInfo[MailSize].Deleted := False; + While Not MsgBase^.EOM Do + AddLine(MsgBase^.GetString(79)); - MsgBase^.YoursNext; + MailInfo[MailSize].MD5 := GetMessageUID(MsgBase); + MailInfo[MailSize].GotRETR := False; + MailInfo[MailSize].Deleted := False; + End; + + MsgBase^.SeekNext; End; MsgBase^.CloseMsgBase; @@ -246,7 +257,8 @@ Begin 1 : MsgBase := New(PMsgBaseSquish, Init); End; - MsgBase^.SetMsgPath (MBase.Path + MBase.FileName); + MsgBase^.SetMsgPath (MBase.Path + MBase.FileName); + MsgBase^.SetTempFile (TempPath + 'msgbuf.'); If Not MsgBase^.OpenMsgBase Then Begin Dispose (MsgBase, Done); @@ -255,17 +267,18 @@ Begin For Count := 1 to MailSize Do Begin If MailInfo[Count].Deleted or (MailInfo[Count].GotRETR and bbsConfig.inetPOP3Delete) Then Begin - MsgBase^.YoursFirst(User.RealName, User.Handle); + MsgBase^.SeekFirst(1); - While MsgBase^.YoursFound Do Begin + While MsgBase^.SeekFound Do Begin MsgBase^.MsgStartUp; - If GetMessageUID(MsgBase) = MailInfo[Count].MD5 Then Begin - MsgBase^.DeleteMsg; - Break; - End; + If IsUser(MsgBase^.GetTo) Then + If GetMessageUID(MsgBase) = MailInfo[Count].MD5 Then Begin + MsgBase^.DeleteMsg; + Break; + End; - MsgBase^.YoursNext; + MsgBase^.SeekNext; End; End; End; diff --git a/mystic/mis_client_smtp.pas b/mystic/mis_client_smtp.pas index 7ff13db..a2b942f 100644 --- a/mystic/mis_client_smtp.pas +++ b/mystic/mis_client_smtp.pas @@ -188,12 +188,16 @@ Begin // todo: what happens if they never send an EOL... could still flood Client.ReadLine(InData); + Inc (HackCount); If HackCount >= SMTPHackThresh Then Begin EndSession := True; // someone is being a douchebag + Server.Status('Flood attempt from ' + FromName + ' (' + Client.PeerIP + '); Goodbye'); + MsgText.Free; + Exit; End; End; @@ -214,7 +218,8 @@ Begin 1 : MsgBase := New(PMsgBaseSquish, Init); End; - MsgBase^.SetMsgPath (MBase.Path + MBase.FileName); + MsgBase^.SetMsgPath (MBase.Path + MBase.FileName); + MsgBase^.SetTempFile (TempPath + 'msgbuf.'); If Not MsgBase^.OpenMsgBase Then If Not MsgBase^.CreateMsgBase (MBase.MaxMsgs, MBase.MaxAge) Then Begin diff --git a/mystic/mis_common.pas b/mystic/mis_common.pas index 5e44837..58813e4 100644 --- a/mystic/mis_common.pas +++ b/mystic/mis_common.pas @@ -12,6 +12,7 @@ Uses Var bbsConfig : RecConfig; + TempPath : String; Console : TOutput; Term : TTermAnsi; diff --git a/mystic/mpl_common.pas b/mystic/mpl_common.pas index d43433b..1b2274b 100644 --- a/mystic/mpl_common.pas +++ b/mystic/mpl_common.pas @@ -291,7 +291,7 @@ Begin AddProc ({$IFDEF MPLPARSER} 'putthisuser', {$ENDIF} '', iNone); // 538 AddProc ({$IFDEF MPLPARSER} 'putuser', {$ENDIF} 'l', iNone); // 539 AddProc ({$IFDEF MPLPARSER} 'isuser', {$ENDIF} 's', iBool); // 540 - AddProc ({$IFDEF MPLPARSER} 'getmbasestats', {$ENDIF} 'lLLL', iBool); // 541 + AddProc ({$IFDEF MPLPARSER} 'getmbstats', {$ENDIF} 'looLLL', iBool); // 541 AddProc ({$IFDEF MPLPARSER} 'writexy', {$ENDIF} 'bbbs', iNone); // 542 AddProc ({$IFDEF MPLPARSER} 'writexypipe', {$ENDIF} 'bbbis', iNone); // 543 AddProc ({$IFDEF MPLPARSER} 'msgeditor', {$ENDIF} 'iIiiosS', iBool); // 544 @@ -312,6 +312,8 @@ Begin AddPointer ({$IFDEF MPLPARSER} 'ignoregroups', {$ENDIF} iBool, 1, {$IFNDEF MPLPARSER} @Session.User.IgnoreGroup {$ELSE} NIL {$ENDIF}); AddPointer ({$IFDEF MPLPARSER} 'pausepos', {$ENDIF} iByte, 1, {$IFNDEF MPLPARSER} @Session.io.PausePtr {$ELSE} NIL {$ENDIF}); AddPointer ({$IFDEF MPLPARSER} 'allowmci', {$ENDIF} iBool, 1, {$IFNDEF MPLPARSER} @Session.io.PausePtr {$ELSE} NIL {$ENDIF}); + AddPointer ({$IFDEF MPLPARSER} 'userloginname',{$ENDIF} iString, 31, {$IFNDEF MPLPARSER} @Session.UserLoginName {$ELSE} NIL {$ENDIF}); + AddPointer ({$IFDEF MPLPARSER} 'userloginpw', {$ENDIF} iString, 16, {$IFNDEF MPLPARSER} @Session.UserLoginPW {$ELSE} NIL {$ENDIF}); {$IFNDEF MPLPARSER} TInterpEngine(S).IdxVarDir := X + 1; {$ENDIF} diff --git a/mystic/mpl_execute.pas b/mystic/mpl_execute.pas index 984ae94..5ceeb61 100644 --- a/mystic/mpl_execute.pas +++ b/mystic/mpl_execute.pas @@ -92,7 +92,7 @@ Type Procedure GetMBaseVars (Var M: RecMessageBase); Function GetMBaseRecord (Num: LongInt) : Boolean; - Function GetMBaseStats (Num: LongInt; Var Total, New, Yours: LongInt) : Boolean; + Function GetMBaseStats (Num: LongInt; SkipFrom, SkipRead: Boolean; Var Total, New, Yours: LongInt) : Boolean; Procedure GetMGroupVars (Var G: RecGroup); Function GetMGroupRecord (Num: LongInt) : Boolean; @@ -244,14 +244,15 @@ Begin Move (M.SysopACS, VarData[IdxVarMBase + 5 ]^.Data^, SizeOf(M.SysopACS)); End; -Function TInterpEngine.GetMBaseStats (Num: LongInt; Var Total, New, Yours: LongInt) : Boolean; +Function TInterpEngine.GetMBaseStats (Num: LongInt; SkipFrom, SkipRead: Boolean; Var Total, New, Yours: LongInt) : Boolean; Var M : RecMessageBase; + T : LongInt; Begin Result := Session.Msgs.GetBaseByNum(Num, M); If Result Then - Session.Msgs.GetMessageStats(M, Total, New, Yours); + Session.Msgs.GetMessageStats(False, False, False, T, M, SkipFrom, SkipRead, Total, New, Yours); End; Function TInterpEngine.GetMBaseRecord (Num: LongInt) : Boolean; @@ -1903,7 +1904,7 @@ Begin Store (TempBool, 1); End; 541 : Begin - TempBool := GetMBaseStats(Param[1].L, LongInt(Pointer(Param[2].vData)^), LongInt(Pointer(Param[3].vData)^), LongInt(Pointer(Param[4].vData)^)); + TempBool := GetMBaseStats(Param[1].L, Param[2].O, Param[3].O, LongInt(Pointer(Param[3].vData)^), LongInt(Pointer(Param[4].vData)^), LongInt(Pointer(Param[5].vData)^)); Store (TempBool, 1); End; 542 : WriteXY (Param[1].B, Param[2].B, Param[3].B, Param[4].S); diff --git a/mystic/mpl_types.pas b/mystic/mpl_types.pas index 8e2e2ce..e603ace 100644 --- a/mystic/mpl_types.pas +++ b/mystic/mpl_types.pas @@ -77,7 +77,7 @@ Type ); Const - mplVer = '11E'; + mplVer = '11G'; mplVersion = '[MPX ' + mplVer +']' + #26; mplVerLength = 10; mplExtSource = '.mps'; diff --git a/mystic/mutil.ini b/mystic/mutil.ini index 664fa2b..e4c3926 100644 --- a/mystic/mutil.ini +++ b/mystic/mutil.ini @@ -57,7 +57,7 @@ ; list of functions to perform on startup Import_FIDONET.NA = true - Import_MessageBase = true + Import_MessageBase = true Import_FILEBONE.NA = true Import_FILES.BBS = true MassUpload = true @@ -333,8 +333,8 @@ [ImportMessageBase] - ; This option scans the message base directory, and creates any messages - ; bases inside of Mystic that have data files in the directory. + ; This option scans the message base directory, and creates any messages + ; bases inside of Mystic that have data files in the directory. ; The following options define the "default" values used when creating ; new message bases. netaddress must match an exiting network @@ -353,9 +353,9 @@ max_msgs = 500 max_msgs_age = 365 - ; network type (0=local, 1=echomail, 2=newsgroup 3=netmail) + ; network type (0=local, 1=echomail, 2=newsgroup 3=netmail) - net_type = 1 + net_type = 1 ; true/false type values 0=false 1=true (newscan 2=forced) diff --git a/mystic/mutil_msgpack.pas b/mystic/mutil_msgpack.pas index 04bc2ec..4126502 100644 --- a/mystic/mutil_msgpack.pas +++ b/mystic/mutil_msgpack.pas @@ -65,7 +65,7 @@ Var Count : Cardinal; Addr : RecEchoMailAddr; Begin - FileMode := 66; + FileMode := 66; BaseKills := 0; Inc (BaseTotal); @@ -150,8 +150,8 @@ Var 3 : NewData^.SetMailType(mmtNetMail); End; - NewData^.SetOrig(MsgData^.GetOrigAddr); - NewData^.SetDest(MsgData^.GetDestAddr); + NewData^.SetOrig (MsgData^.GetOrigAddr); + NewData^.SetDest (MsgData^.GetDestAddr); MsgData^.MsgTxtStartUp; diff --git a/mystic/mystic.pas b/mystic/mystic.pas index 49d203a..ed63e69 100644 --- a/mystic/mystic.pas +++ b/mystic/mystic.pas @@ -362,11 +362,9 @@ Begin End; Var - Count : Byte; - Temp : String[120]; - UserName : String[30]; - Password : String[15]; - Script : String[120]; + Count : Byte; + Temp : String[120]; + Script : String[120]; Begin {$IFDEF DEBUG} SetHeapTraceOutput('mystic.mem'); @@ -411,10 +409,10 @@ Begin Session.UserHostInfo := Copy(ParamStr(Count), 6, Length(Temp)) Else If Copy(Temp, 1, 2) = '-U' Then - UserName := strReplace(Copy(Temp, 3, Length(Temp)), '_', ' ') + Session.UserLoginName := strReplace(Copy(Temp, 3, Length(Temp)), '_', ' ') Else If Copy(Temp, 1, 2) = '-P' Then - Password := Copy(Temp, 3, Length(Temp)) + Session.UserLoginPW := Copy(Temp, 3, Length(Temp)) Else If Copy(Temp, 1, 2) = '-X' Then Script := strReplace(Copy(ParamStr(Count), 3, Length(Temp)), '_', ' ') @@ -489,7 +487,7 @@ Begin //Halt(0); {$ENDIF} - Session.User.UserLogon1 (UserName, Password, Script); + Session.User.UserLogon1 (Script); If Session.TimeOffset > 0 Then Session.TimeSaved := Session.User.ThisUser.TimeLeft; diff --git a/mystic/records.pas b/mystic/records.pas index 2a2eb4e..1b69e5b 100644 --- a/mystic/records.pas +++ b/mystic/records.pas @@ -23,7 +23,7 @@ Const mysSoftwareID = 'Mystic'; // no idea mysCopyYear = '1997-2013'; // its been a long time! - mysVersion = '1.10 A27'; // current version + mysVersion = '1.10 A29'; // current version mysDataChanged = '1.10 A11'; // version of last records change {$IFDEF WIN32} @@ -59,7 +59,7 @@ Const mysMaxMenuCmds = 25; // Max menu commands per item mysMaxMenuInput = 12; mysMaxMenuStack = 8; - mysMaxThemeText = 503; // Total prompts in theme file + mysMaxThemeText = 508; fn_SemFileEcho = 'echomail.now'; fn_SemFileNews = 'newsmail.now'; @@ -67,6 +67,8 @@ Const fn_tplMsgEdit = 'ansiedit'; fn_tplTextEdit = 'ansitext'; + ColumnValue : Array[0..1] of Byte = (80, 40); + Type SmallWord = System.Word; Integer = SmallInt; @@ -706,7 +708,8 @@ Type MGroupBar : RecPercent; MAreaList : RecPercent; Colors : Array[0..9] of Byte; - Reserved : Array[1..199] of Byte; + ColumnSize : Byte; + Reserved : Array[1..198] of Byte; End; BBSListRec = Record diff --git a/mystic/todo.pas b/mystic/todo.pas index cd782c0..9389a8f 100644 --- a/mystic/todo.pas +++ b/mystic/todo.pas @@ -8,6 +8,7 @@ design elements/issues. BUGS AND POSSIBLE ISSUES ======================== +! Posting echomail via NNTP is not setting ECHO flag ! LBP menus arent scrolling correctly in Linux ! MUTIL FILESBBS import is not skipping FILES.BBS? ! Make sure MIS in Linux works with DOSEMU @@ -28,6 +29,9 @@ BUGS AND POSSIBLE ISSUES FUTURE / IDEAS / WORK IN PROGRESS / NOTES ========================================= +- MUTIL create FILES.BBS in the file base directory +- MUTILs new DIR import of msg bases could have optional config to reference + a series of .NA files to get the name/description of bases. - New Scan/Read message should have option to not update last read when reading personal messages. - Option for QuickScan that only prints a base if it has new messages. diff --git a/mystic/whatsnew.txt b/mystic/whatsnew.txt index 902763b..bcf9695 100644 --- a/mystic/whatsnew.txt +++ b/mystic/whatsnew.txt @@ -1754,12 +1754,14 @@ mentioning it just in case. + New MPL function: GetMBaseStats. This can be used as a function or a - procedure (returning true if successful). It takes 4 parameters. + procedure (returning true if successful). It takes 6 parameters. #1: Message base number - #2: Total messages (this is a VAR parameter) - #3: New messages (this is a VAR parameter) - #4: New messages to you (this is a VAR parameter) + #2: Exclude messages FROM the current user in stats + #3: Exclude messages TO the current user that have already been read + #4: Total messages (this is a VAR parameter) + #5: New messages (this is a VAR parameter) + #6: New messages to you (this is a VAR parameter) Example: @@ -1771,7 +1773,7 @@ count := 1; //start @1 to skip email base while getmbase(count) do begin - getmbasestats(count, total, new, yours); + getmbstats(count, true, true, total, new, yours); writeln('base : ' + mbasename); writeln('total msgs : ' + int2str(total)); @@ -2671,4 +2673,196 @@ + E-mail messages are now included in QWK packets. - + + Added additional support for the QWKE packets. Mystic will now generate + the appropriate QWKE data to tell the reader if the message base is + public or private, if reading is forced, if real names or handles should + be used, and whether or not they have access to post/reply to the area. + + + Rewrote the status bar on the local console (in Windows) to use the color + values set in the configuration. + + + Message QuickScan (MQ) menu command now has two new options: + + /YOU - Only show base if it has messages address to you + /NEW - Only show base if it has new messages + + ! Fixed a bug which caused the nodelist text search to not work. + + + The "startup" MPL program that is executed if it exists after ANSI + detection and theme assignment can now set the user login and password + to bypass the internal login functions. You must set to two variables: + + UserLoginName + UserLoginPW + + So for example if I had a startup.mpx that simply did this: + + Begin + UserLoginName := 'g00r00'; + UserLoginPW := 'mypassword'; + End; + + It would automatically log in as g00r00 and bypass the normal login/pw + stuff. This combined with newuserapp.mpx allows you to completely + rewrite login and newuser functions in MPL if you'd like to. + + + The Read Messages menu command (MR) now has the option to pass /NOLR + in the optional data. If this is found, Mystic will not update the + users last read pointers after reading. + + You MUST still supply the read type as the first character. So for + example: + + Command: MR + Optional data: Y /NOLR + + Would read all messages addressed specifically to that user, but would + not set their last read pointers. + + + The Message New Scan (MN) now has the option to supply /NOLR which will + cause the users last read pointers to NOT get updated during this + message scan. + + + New Menu Command -R will set the value of the "OK" acs flag. The + optional data of 0 will set the OK flag to return false, or 1 will set + it to return true. + + + New ACS function: ON. This returns true if the last performed message + "Quick scan" found new messages or if the last performed Email check + found unread emails. + + + New ACS function: OY. This returns true if the last performed message + "Quick scan" found new messages addressed to the user. + + + The Message New Scan (MN) now has the option to supply /NOFROM which + will skip over any messages FROM the user. This works in ALL reading + modes. + + + The Read Messages (MR) now has the option to supply /NOFROM which + will skip over any messages FROM the user. This works in ALL reading + modes. + + + The Message Quick Scan (MQ) command now has the option to supply + /NOFROM which will not count any messages FROM the user in the scan. + + + Added a new menu "personalscan.mnu" into the default install menu + directory which demonstrates many of the new message reading/scanning + functions. + + - MPL GetMBaseStats has changed in a few ways. First, it has been renamed + to "getmbstats" and now has two additional parameters: + + #1: Message base number + #2: Exclude messages FROM the current user in stats? T/F + #3: Exclude personal messages that have already been read? T/F + #4: Total messages (this is a VAR parameter) + #5: New messages (this is a VAR parameter) + #6: New messages to you (this is a VAR parameter) + + + Mystic now tracks if ANY message (public or private) has been read by + the user the message is addressed to. You MUST replace your old + message header flags prompt with the new one to include the received + flag at the end: + + ; Msg header flags text one word each separated by a space + ; 1=Local 2=Echo 3=Private 4=Sent 5=Delete 6=Received + 490 Local Echo Private Sent Deleted Rcvd + + ! Fixed a bug that could cause private messages to not be marked as private + when uploading a QWKE REP packet. + + + Two new prompt info codes added to prompt #127 (read email? prompt): + + &1 = number of emails + &2 = number of unread emails + + In addition, the Yes/No prompt defaults to NO if they do not have any + unread emails, or YES if they do. + + + The Read Messages command (RM) now allows for the option /NOREAD which + will skip over any message marked as received. A received message is + classified as a message addressed to the current user that has already + been read. + + + The Message New Scan (MN) command now allows for the /NOREAD option. + + + The QuickScan command (MQ) now allows for the /NOREAD option. + + - Removed QuickScan header prompt and /NOHEAD option. It was pointless and + could easily be done in a menu if yo someone wanted it. + + + Added prompts that will be displayed when setting the last read pointer + within the message readers. The two new prompts are: + + ; Standard message reader: Lastread pointer set &1 = msg number + 504 |CR|11Last read pointer has been set to message number |&1.|CR|CR|PA + + ; Lightbar reader: Lastread pointer set &1 = msg number + 505 |CR|11Last read pointer has been set to message number |&1.|CR|CR|PA + + + Added a /LIST option to the QuickScan which will list out messages based + on the options presented. The following new prompts need to be added: + + ; QuickScan message list header &2=basename + 506 |15From Base Subject|CR|09=============== ==================== ========================================== + + ; QuickScan message list middle + ; &1=msg# &2=basename &3=from &4=to &5=subject &6=date + + 507 |10|$R15|&3 |09|$R20|&2 |11|$R42|&5 + ; QuicScan message list footer + + 508 |09|$D79=|CR + + + + + Prompt #490 has been changed to separate message header flags by comma + instead of space. This allows the ability to completely exclude certain + flags (ie if you never want a Local flag you can just remove it and leave + the comma) + + ; Msg header flags text one word each separated by a comma + ; 1=Local 2=Echo 3=Private 4=Sent 5=Delete, 6=Received + 490 Local,Echo,Priv,Sent,Del,Read + + ! Echo flag was not displaying correctly in the message headers. + + ! Fixed a bug in the ANSI file viewer which was causing garbled ANSIs + in the gallery and the viewer. + + + Pressing the SPACE bar in the ANSI viewer now displays the file + "normally" with a screenpause at the end. + + + The ansi viewer now has a help file option. The format of the optional + data has changed for the GV menu command so you will need to change it + if you are using it. + +