From 8c335f488ec65a7fff5dd4b572993b30c9ed153c Mon Sep 17 00:00:00 2001 From: mysticbbs Date: Mon, 4 Mar 2013 10:53:06 -0500 Subject: [PATCH] A26 --- mystic/bbs_cfg_syscfg.pas | 9 +- mystic/bbs_edit_ansi.pas | 836 +++++++++++++++++++++++++++++++++++- mystic/bbs_edit_full.pas | 2 +- mystic/bbs_filebase.pas | 61 ++- mystic/bbs_io.pas | 17 +- mystic/bbs_msgbase.pas | 80 +++- mystic/bbs_msgbase_ansi.pas | 23 +- mystic/default.txt | 12 +- mystic/mbbsutil.pas | 45 +- mystic/mis_client_ftp.pas | 1 + mystic/mis_nodedata.pas | 4 +- mystic/mystic.pas | 24 ++ mystic/records.pas | 6 +- mystic/whatsnew.txt | 43 +- 14 files changed, 1078 insertions(+), 85 deletions(-) diff --git a/mystic/bbs_cfg_syscfg.pas b/mystic/bbs_cfg_syscfg.pas index 662642d..226357b 100644 --- a/mystic/bbs_cfg_syscfg.pas +++ b/mystic/bbs_cfg_syscfg.pas @@ -287,7 +287,7 @@ Begin Box.Open (5, 5, 76, 21); VerticalLine (26, 7, 19); - VerticalLine (58, 7, 14); + VerticalLine (58, 7, 15); Form.AddBol ('L', ' List Compression', 8, 7, 28, 7, 18, 3, @Config.FCompress, Topic + ''); Form.AddTog ('I', ' List Columns', 12, 8, 28, 8, 14, 1, 1, 2, '1 2', @Config.FColumns, Topic + ''); @@ -308,9 +308,10 @@ Begin Form.AddStr ('N', ' DL Unvalidated', 42, 9, 60, 9, 16, 15, mysMaxAcsSize, @Config.AcsDLUnvalid, Topic + 'ACS to download unvalidated files'); Form.AddStr ('F', ' See Failed', 46, 10, 60, 10, 12, 15, mysMaxAcsSize, @Config.AcsSeeFailed, Topic + 'ACS to see failed files'); Form.AddStr (#0, ' DL Failed', 47, 11, 60, 11, 11, 15, mysMaxAcsSize, @Config.AcsDLFailed, Topic + 'ACS to download failed files'); - Form.AddLong ('C', ' Min Upload Space', 40, 12, 60, 12, 18, 9, 0, 999999999, @Config.FreeUL, Topic + 'Min space to allow uploads (kb)'); - Form.AddLong ('-', ' Min CD-ROM Space', 40, 13, 60, 13, 18, 9, 0, 999999999, @Config.FreeCDROM, Topic + 'Min space for CD-ROM copy (kb)'); - Form.AddChar (#0, ' Default Protocol', 40, 14, 60, 14, 18, 32, 96, @Config.FProtocol, Topic + 'Default Protocol hotkey'); + Form.AddStr (#0, ' See Offline', 45, 12, 60, 12, 13, 15, mysMaxAcsSize, @Config.AcsSeeOffline, Topic + 'ACS to see offline files'); + Form.AddLong ('C', ' Min Upload Space', 40, 13, 60, 13, 18, 9, 0, 999999999, @Config.FreeUL, Topic + 'Min space to allow uploads (kb)'); + Form.AddLong ('-', ' Min CD-ROM Space', 40, 14, 60, 14, 18, 9, 0, 999999999, @Config.FreeCDROM, Topic + 'Min space for CD-ROM copy (kb)'); + Form.AddChar (#0, ' Default Protocol', 40, 15, 60, 15, 18, 32, 96, @Config.FProtocol, Topic + 'Default Protocol hotkey'); Form.Execute; diff --git a/mystic/bbs_edit_ansi.pas b/mystic/bbs_edit_ansi.pas index 84fc465..f8bf340 100644 --- a/mystic/bbs_edit_ansi.pas +++ b/mystic/bbs_edit_ansi.pas @@ -2,9 +2,839 @@ Unit bbs_Edit_Ansi; {$I M_OPS.PAS} -// online ansi editor WIP - Interface + +// Future online pipe/ansi editor and new full screen editor. +// Will be the most badass editor to ever exist. + +Uses + bbs_MsgBase_ANSI; + +Const + MaxLines = 1000; + +Type + TEditorANSI = Class + Owner : Pointer; + ANSI : TMsgBaseANSI; + WinY1 : Byte; + WinY2 : Byte; + WinX1 : Byte; + WinX2 : Byte; + WinSize : Byte; + RowSize : Byte; + CurX : Byte; + CurY : SmallInt; + CurAttr : Byte; + CurLength : Byte; + TopLine : LongInt; + CurLine : LongInt; + InsertMode : Boolean; + DrawMode : Boolean; + GlyphMode : Boolean; + WrapMode : Boolean; + ClearEOL : Boolean; + LastLine : LongInt; + + Constructor Create (Var O: Pointer); + Destructor Destroy; Override; + + Function IsAnsiLine (Line: LongInt) : Boolean; + Function IsBlankLine (Var Line; LineSize: Byte) : Boolean; + Function GetLineLength (Var Line; LineSize: Byte) : Byte; + Function GetWrapPos (Var Line; LineSize, WrapPos: Byte) : Byte; + Procedure TrimLine (Var Line; LineSize: Byte); + Procedure DeleteLine (Line: LongInt); + Procedure InsertLine (Line: LongInt); + Procedure FindLastLine; + Procedure Reformat; + Procedure LocateCursor; + Procedure ReDrawTemplate; + Procedure DrawPage (StartY, EndY: Byte; ExitEOF: Boolean); + Procedure ScrollUp; + Procedure ScrollDown; + Function LineUp : Boolean; + Function LineDown (Reset: Boolean) : Boolean; + Procedure PageUp; + Procedure PageDown; + Procedure DrawLine (Line: LongInt; XP, YP: Byte); + Procedure DoEnter; + Procedure DoBackSpace; + Procedure DoDelete; + Procedure DoChar (Ch: Char); + Function Edit : Boolean; + Procedure LoadANSI; + End; + Implementation -End. \ No newline at end of file +Uses + m_Strings, + bbs_Core, + bbs_Ansi_MenuBox; + +Constructor TEditorANSI.Create (Var O: Pointer); +Begin + Inherited Create; + + Owner := O; + ANSI := TMsgBaseANSI.Create(NIL, False); + WinX1 := 1; + WinX2 := 79; + WinY1 := 2; + WinY2 := 23; + WinSize := WinY2 - WinY1 + 1; + RowSize := WinX2 - WinX1 + 1; + CurX := 1; + CurY := 1; + CurLine := 1; + TopLine := 1; + CurAttr := 7; + InsertMode := True; + DrawMode := False; + GlyphMode := False; + WrapMode := True; + ClearEOL := RowSize >= 79; + LastLine := 1; +End; + +Destructor TEditorANSI.Destroy; +Begin + Inherited Destroy; + + ANSI.Free; +End; + +Procedure TEditorANSI.FindLastLine; +Var + Count : LongInt; +Begin + LastLine := MaxLines; + + While (LastLine > 1) And IsBlankLine(ANSI.Data[LastLine], 80) Do + Dec(LastLine); +End; + +Function TEditorANSI.IsAnsiLine (Line: LongInt) : Boolean; +Var + Count : Byte; +Begin + Result := False; + + If GetLineLength(ANSI.Data[Line], 80) >= Rowsize Then Begin + Result := True; + + Exit; + End; + + For Count := 1 to 80 Do + If (Ord(ANSI.Data[Line][Count].Ch) < 32) or (Ord(ANSI.Data[Line][Count].Ch) > 128) Then Begin + Result := True; + + Exit; + End; +End; + +Function TEditorANSI.IsBlankLine (Var Line; LineSize: Byte) : Boolean; +Var + EndPos : Byte; + Data : Array[1..255] of RecAnsiBufferChar absolute Line; +Begin + EndPos := LineSize; + + While (EndPos > 0) and (Data[EndPos].Ch = #0) Do + Dec (EndPos); + + Result := EndPos = 0; +End; + +Procedure TEditorANSI.TrimLine (Var Line; LineSize: Byte); +Var + Data : Array[1..255] of RecAnsiBufferChar absolute Line; + EndPos : Byte; +Begin + EndPos := 1; + + While (EndPos <= LineSize) and (Data[1].Ch = ' ') Do Begin + Move (Data[2], Data[1], SizeOf(RecAnsiBufferChar) * (LineSize - 1)); + + Data[LineSize].Ch := #0; + + Inc (EndPos); + End; + + EndPos := LineSize; + + While (EndPos > 0) and ((Data[EndPos].Ch = ' ') or (Data[EndPos].Ch = #0)) Do Begin + Data[EndPos].Ch := #0; + + Dec (EndPos); + End; +End; + +Procedure TEditorANSI.DeleteLine (Line: LongInt); +Var + Count : LongInt; +Begin + For Count := Line to MaxLines - 1 Do + ANSI.Data[Count] := ANSI.Data[Count + 1]; + + FillChar (ANSI.Data[MaxLines], SizeOf(RecAnsiBufferLine), #0); + + If LastLine > 1 Then Dec(LastLine); +End; + +Procedure TEditorANSI.InsertLine (Line: LongInt); +Var + Count : LongInt; +Begin + For Count := MaxLines DownTo Line + 1 Do + ANSI.Data[Count] := ANSI.Data[Count - 1]; + + FillChar(ANSI.Data[Line], SizeOf(RecAnsiBufferLine), #0); + + If LastLine < MaxLines Then Inc(LastLine); +End; + +Function TEditorANSI.GetWrapPos (Var Line; LineSize: Byte; WrapPos: Byte) : Byte; +Var + Data : Array[1..255] of RecAnsiBufferChar absolute Line; +Begin + If GetLineLength(Line, LineSize) < WrapPos Then Begin + Result := 0; + + Exit; + End; + + Result := LineSize; + + While (Result > 0) and ((Data[Result].Ch <> ' ') or (Result > WrapPos)) Do + Dec (Result); +End; + +Function TEditorANSI.GetLineLength (Var Line; LineSize: Byte) : Byte; +Var + Data : Array[1..255] of RecAnsiBufferChar absolute Line; +Begin + Result := LineSize; + + While (Result > 0) and (Data[Result].Ch = #0) Do + Dec (Result); +End; + +Procedure TEditorANSI.Reformat; +Var + WrapData : Array[1..255] of RecAnsiBufferChar; + TempStr : Array[1..255] of RecAnsiBufferChar; + NewLine : Array[1..255] of RecAnsiBufferChar; + Count : LongInt; + LineSize : Byte; + StartY : Byte; + StartLine : LongInt; + EndLine : LongInt; + First : Boolean = True; + + Procedure Update; + Var + NewY : LongInt; + Begin + NewY := StartY + EndLine - StartLine + 1; + + If NewY > WinSize Then NewY := WinSize; + + If CurY > WinSize Then + ScrollDown + Else + DrawPage (StartY, NewY, True); + End; + +Begin + FillChar (WrapData, SizeOf(WrapData), #0); + + Count := CurLine; + StartY := CurY; + StartLine := Count; + + While Count <= MaxLines Do Begin + If Count > LastLine Then LastLine := Count; + + FillChar (TempStr, SizeOf(TempStr), #0); + Move (Ansi.Data[Count], TempStr, SizeOf(Ansi.Data[Count])); + + If Not IsBlankLine(WrapData, 255) Then Begin + If IsBlankLine(TempStr, 255) Then Begin + If Count < LastLine Then Begin + InsertLine(Count); + EndLine := MaxLines; + End Else + EndLine := Count; + + Move (WrapData, ANSI.Data[Count], SizeOf(Ansi.Data[Count])); + + Update; + + Exit; + End; + + FillChar (NewLine, SizeOf(NewLine), #0); + + LineSize := GetLineLength(WrapData, 255); + + Move (WrapData, NewLine, LineSize * SizeOf(RecAnsiBufferChar)); + + NewLine[LineSize + 1].Ch := ' '; + NewLine[LineSize + 1].Attr := WrapData[LineSize].Attr; + + Move (TempStr, NewLine[LineSize + 2], GetLineLength(TempStr, 255) * SizeOf(RecAnsiBufferChar)); + Move (NewLine, TempStr, SizeOf(NewLine)); + End; + + FillChar (WrapData, SizeOf(WrapData), #0); + + LineSize := GetWrapPos(TempStr, 255, RowSize); + + If LineSize > 0 Then Begin + Move (TempStr[LineSize], WrapData, (GetLineLength(TempStr, 255) - LineSize + 1) * SizeOf(RecAnsiBufferChar)); + FillChar (TempStr[LineSize], (255 - LineSize) * SizeOf(RecAnsiBufferChar), #0); + + TrimLine (WrapData, 255); + + If First Then Begin + If CurX > LineSize Then Begin + CurX := CurX - LineSize; + + Inc (CurY); + Inc (CurLine); + End; + + First := False; + End; + End; + + FillChar (ANSI.Data[Count], SizeOf(ANSI.Data[Count]), #0); + Move (TempStr, ANSI.Data[Count], RowSize * SizeOf(RecAnsiBufferChar)); + + If LineSize = 0 Then Begin + If First Then Begin + CurX := 1; + + Inc (CurLine); + Inc (CurY); + + If CurLine > LastLine Then LastLine := CurLine; + + EndLine := Count + 1; + End Else + EndLine := Count; + + Update; + + Exit; + End; + + Inc (Count); + End; + +// Update; +End; + +Procedure TEditorANSI.ReDrawTemplate; +// temp stuff to be replaced by real template +Var + B : TAnsiMenuBox; +Begin + TBBSCore(Owner).io.AllowArrow := True; + + TBBSCore(Owner).io.AnsiColor(7); + TBBSCore(Owner).io.AnsiClear; + +(* + B := TAnsiMenuBox.Create; + + B.FrameType := 1; + + B.Open (5, 2, 75, 23); + B.Free; + + WinX1 := 6; + WinX2 := 74; + WinY1 := 3; + WinY2 := 22; +*) + + WinX1 := 1; + WinX2 := 79; + WinY1 := 2; + WinY2 := 23; + + WinSize := WinY2 - WinY1 + 1; + RowSize := WinX2 - WinX1 + 1; + CurX := 1; + CurY := 1; + ClearEOL := RowSize >= 79; + + LoadANSI; + FindLastLine; + + DrawPage(1, WinSize, False); +End; + +Procedure TEditorANSI.LocateCursor; +Begin + CurLength := GetLineLength(ANSI.Data[CurLine], RowSize); + + If CurX < 1 Then CurX := 1; + If CurX > CurLength Then CurX := CurLength + 1; + If CurY < 1 Then CurY := 1; + + While TopLine + CurY - 1 > LastLine Do + Dec (CurY); + + If Not DrawMode Then Begin + If (CurX > 1) and (CurX = CurLength + 1) Then + CurAttr := ANSI.Data[CurLine][CurX - 1].Attr + Else + CurAttr := ANSI.Data[CurLine][CurX].Attr; + + If CurAttr = 0 Then CurAttr := 7; + End; + + With TBBSCore(Owner).io Do Begin + + //AnsiGotoXY (1, 1); + //BufAddStr ('X:' + strI2S(CurX) + ' Y:' + strI2S(CurY) + ' CL:' + strI2S(CurLine) + ' TL:' + strI2S(TopLine) + ' Last:' + strI2S(LastLine) + ' Len:' + strI2S(GetLineLength(ANSI.Data[CurLine], 80)) + ' Row:' + strI2S(RowSize) + ' '); + + AnsiGotoXY (WinX1 + CurX - 1, WinY1 + CurY - 1); + AnsiColor (CurAttr); + + BufFlush; + End; +End; + +Procedure TEditorANSI.DrawPage (StartY, EndY: Byte; ExitEOF: Boolean); +Var + CountY : LongInt; + CountX : Byte; +Begin + For CountY := StartY to EndY Do Begin + If TopLine + CountY - 1 > LastLine + 1 Then Begin + TBBSCore(Owner).io.AnsiGotoXY (WinX1, WinY1 + CountY - 1); + TBBSCore(Owner).io.AnsiColor (7); + + If ClearEOL Then + TBBSCore(Owner).io.AnsiClrEOL + Else + TBBSCore(Owner).io.BufAddStr (strRep(' ', RowSize)); + End Else + If TopLine + CountY - 1 = LastLine + 1 Then Begin + TBBSCore(Owner).io.AnsiGotoXY (WinX1, WinY1 + CountY - 1); + TBBSCore(Owner).io.AnsiColor (12); + TBBSCore(Owner).io.BufAddStr (strPadC('-----END-----', RowSize, ' ')); + + If ExitEOF Then Break; + End Else + DrawLine (TopLine + CountY - 1, 1, CountY); + End; +End; + +Procedure TEditorANSI.ScrollUp; +Var + NewTop : LongInt; +Begin + NewTop := TopLine - (WinSize DIV 2) + 1; + + If NewTop < 1 Then NewTop := 1; + + CurY := CurLine - NewTop + 1; + TopLine := NewTop; + + DrawPage(1, WinSize, False); +End; + +Procedure TEditorANSI.ScrollDown; +Var + NewTop : LongInt; +Begin + NewTop := TopLine + (WinSize DIV 2) + 1; + + While NewTop >= MaxLines Do + Dec (NewTop, 2); + + CurY := CurLine - NewTop + 1; + TopLine := NewTop; + + DrawPage(1, WinSize, False); +End; + +Function TEditorANSI.LineUp : Boolean; +Begin + Result := False; + + If CurLine = 1 Then Exit; + + Dec (CurLine); + Dec (CurY); + + If CurX > GetLineLength(ANSI.Data[CurLine], 80) Then CurX := GetLineLength(ANSI.Data[CurLine], 80) + 1; + + If CurY < 1 Then Begin + ScrollUp; + + Result := True; + End; +End; + +Function TEditorANSI.LineDown (Reset: Boolean) : Boolean; +Begin + Result := False; + + If CurLine >= MaxLines Then Exit; + + Inc (CurLine); + Inc (CurY); + + If Reset Then CurX := 1; + + If CurX > GetLineLength(ANSI.Data[CurLine], 80) Then CurX := GetLineLength(ANSI.Data[CurLine], 80) + 1; + + If CurY > WinSize Then Begin + Result := True; + + ScrollDown; + End; +End; +(* +Procedure TEditorANSI.DrawLine (Line: LongInt; XP, YP: Byte); +Var + Count : Byte; +Begin + TBBSCore(Owner).io.AnsiGotoXY (WinX1 + XP - 1, WinY1 + YP - 1); + + For Count := XP to RowSize Do Begin + If ANSI.Data[Line][Count].Ch = #0 Then Begin + TBBSCore(Owner).io.AnsiColor (7); + TBBSCore(Owner).io.BufAddChar (' '); + End Else Begin + TBBSCore(Owner).io.AnsiColor (ANSI.Data[Line][Count].Attr); + TBBSCore(Owner).io.BufAddChar (ANSI.Data[Line][Count].Ch); + End; + End; +End; +*) + +Procedure TEditorANSI.DrawLine (Line: LongInt; XP, YP: Byte); +Var + Count : Byte; + LineLen : Byte; +Begin + TBBSCore(Owner).io.AnsiGotoXY (WinX1 + XP - 1, WinY1 + YP - 1); + + LineLen := GetLineLength(ANSI.Data[Line], RowSize); + + For Count := XP to LineLen Do Begin + If ANSI.Data[Line][Count].Ch = #0 Then Begin + TBBSCore(Owner).io.AnsiColor (7); + TBBSCore(Owner).io.BufAddChar (' '); + End Else Begin + TBBSCore(Owner).io.AnsiColor (ANSI.Data[Line][Count].Attr); + TBBSCore(Owner).io.BufAddChar (ANSI.Data[Line][Count].Ch); + End; + End; + + If LineLen < RowSize Then + If ClearEOL Then Begin + TBBSCore(Owner).io.AnsiColor (7); + TBBSCore(Owner).io.AnsiClrEOL; + End Else Begin + TBBSCore(Owner).io.AnsiColor (7); + TBBSCore(Owner).io.BufAddStr (strRep(' ', LineLen - RowSize)); + End; +End; + +Procedure TEditorANSI.DoDelete; +Var + JoinLen : Byte; + JoinPos : Byte; + JoinBuf : Array[1..255] of RecAnsiBufferChar; +Begin + If CurX <= CurLength Then Begin + Move (ANSI.Data[CurLine][CurX + 1], ANSI.Data[CurLine][CurX], (CurLength - 1) * SizeOf(RecAnsiBufferChar)); + + ANSI.Data[CurLine][CurLength].Ch := #0; + + DrawLine (CurLine, CurX, CurY); + End Else + If CurLine < LastLine Then + If (CurLength = 0) and (LastLine > 1) Then Begin + DeleteLine (CurLine); + DrawPage (CurY, WinSize, False); + End Else Begin + JoinLen := GetLineLength(ANSI.Data[CurLine + 1], RowSize); + + If CurLength + JoinLen <= RowSize Then Begin + Move (ANSI.Data[CurLine + 1], ANSI.Data[CurLine][CurX], SizeOf(RecAnsiBufferChar) * JoinLen); + DeleteLine (CurLine + 1); + DrawPage (CurY, WinSize, False); //optimize + End Else Begin + JoinPos := GetWrapPos(ANSI.Data[CurLine + 1], RowSize, RowSize - CurLength); + + If JoinPos > 0 Then Begin + Move (ANSI.Data[CurLine + 1], ANSI.Data[CurLine][CurX], SizeOf(RecAnsiBufferChar) * (JoinPos - 1)); + + FillChar (JoinBuf, SizeOf(JoinBuf), #0); + Move (ANSI.Data[CurLine + 1][JoinPos + 1], JoinBuf, (JoinLen - JoinPos + 1) * SizeOf(RecAnsiBufferChar)); + Move (JoinBuf, ANSI.Data[CurLine + 1], RowSize * SizeOf(RecAnsiBufferChar)); + + DrawPage (CurY, CurY + 1, True); + End; + End; + + End; +End; + +Procedure TEditorANSI.DoBackSpace; +Var + JoinPos : Byte; + JoinBuf : Array[1..255] of RecAnsiBufferChar; +Begin + If CurX > 1 Then Begin + Dec (CurX); + Move (ANSI.Data[CurLine][CurX + 1], ANSI.Data[CurLine][CurX], SizeOf(RecAnsiBufferChar) * (80 - CurX + 1)); + + ANSI.Data[CurLine][80].Ch := #0; + + If CurX > GetLineLength(ANSI.Data[CurLine], 80) Then + TBBSCore(Owner).io.OutBS(1, True) + Else + DrawLine (CurLine, CurX, CurY); + End Else + If CurLine > 1 Then Begin + If GetLineLength(ANSI.Data[CurLine - 1], 80) + CurLength <= RowSize Then Begin + CurX := GetLineLength(ANSI.Data[CurLine - 1], 80) + 1; + + Move (ANSI.Data[CurLine], ANSI.Data[CurLine - 1][CurX], SizeOf(RecAnsiBufferChar) * CurLength); + + DeleteLine (CurLine); + + If Not LineUp Then DrawPage (CurY, WinSize, False); //optimize + End Else Begin + JoinPos := GetWrapPos(ANSI.Data[CurLine], RowSize, RowSize - GetLineLength(ANSI.Data[CurLine - 1], RowSize)); + + If JoinPos > 0 Then Begin + CurX := GetLineLength(ANSI.Data[CurLine - 1], 80) + 1; + + Move (ANSI.Data[CurLine], ANSI.Data[CurLine - 1][CurX], SizeOf(RecAnsiBufferChar) * (JoinPos - 1)); + FillChar (JoinBuf, SizeOf(JoinBuf), #0); + Move (ANSI.Data[CurLine][JoinPos + 1], JoinBuf, (CurLength - JoinPos + 1) * SizeOf(RecAnsiBufferChar)); + Move (JoinBuf, ANSI.Data[CurLine], RowSize * SizeOf(RecAnsiBufferChar)); + + If Not LineUp Then DrawPage (CurY, WinSize, False); + End Else Begin + LineUp; + + CurX := CurLength + 1; + End; + End; + End; +End; + +Procedure TEditorANSI.DoChar (Ch: Char); +Begin + If InsertMode Then Begin + Move (ANSI.Data[CurLine][CurX], ANSI.Data[CurLine][CurX + 1], SizeOf(RecAnsiBufferChar) * (CurLength - CurX + 1)); + + ANSI.Data[CurLine][CurX].Ch := Ch; + ANSI.Data[CurLine][CurX].Attr := CurAttr; + + If CurLength < RowSize {-1} Then Begin + If CurX <= CurLength Then + DrawLine (CurLine, CurX, CurY) + Else Begin + TBBSCore(Owner).io.AnsiColor (CurAttr); + TBBSCore(Owner).io.BufAddChar (Ch); + End; + + Inc (CurX); + End Else Begin + Inc (CurX); + + Reformat; + End; + End Else + If CurX <= RowSize Then Begin + ANSI.Data[CurLine][CurX].Ch := Ch; + ANSI.Data[CurLine][CurX].Attr := CurAttr; + + TBBSCore(Owner).io.AnsiColor (CurAttr); + TBBSCore(Owner).io.BufAddChar (Ch); + + Inc (CurX); + End; +End; + +Procedure TEditorANSI.PageUp; +Var + NewTop : LongInt; +Begin + If CurLine = 1 Then Exit; + + If TopLine = 1 Then Begin + CurLine := 1; + CurY := 1; + CurX := 1; + + Exit; + End; + + Dec (CurLine, WinSize); + + If CurLine < 1 Then Begin + CurLine := 1; + NewTop := 1; + End Else Begin + NewTop := TopLine - WinSize; + + If NewTop < 1 Then NewTop := 1; + End; + + CurY := CurLine - NewTop + 1; + TopLine := NewTop; + + DrawPage(1, WinSize, False); +End; + +Procedure TEditorANSI.PageDown; +Var + NewTop : LongInt; +Begin + If CurLine = LastLine Then Exit; + + If (LastLine > TopLine) And (LastLine <= TopLine + WinSize - 1) Then Begin + CurLine := LastLine; + CurY := CurLine - TopLine + 1; + CurX := 1; + + Exit; + End; + + Inc (CurLine, WinSize); + + If CurLine > LastLine Then CurLine := LastLine; + + NewTop := TopLine + WinSize; + + While NewTop >= LastLine - (WinSize DIV 2) Do + Dec (NewTop); + + If NewTop < 1 Then NewTop := 1; + + CurY := CurLine - NewTop + 1; + TopLine := NewTop; + + DrawPage(1, WinSize, False); +End; + +Procedure TEditorANSI.LoadANSI; +Var + F : File; + B : Array[1..1024] of Char; + BR : LongInt; + A : LongInt; + C : LongINt; +Begin + Assign (F, '\code\mystic1\text\gj-glue1.ans'); + Reset (F, 1); + + While Not Eof(F) Do Begin + BlockRead (F, B, SizeOf(B), BR); + + If BR = 0 Then Break; + + ANSI.ProcessBuf(B, BR); + End; + + Close(F); + + For A := 1 to ANSI.Lines Do + For C := RowSize + 1 to 80 Do Begin + ANSI.Data[A][C].Ch := #0; + ANSI.Data[A][C].Attr := 0; + End; +End; + +Procedure TEditorANSI.DoEnter; +Var + TempLine : RecAnsiBufferLine; +Begin + If InsertMode and IsBlankLine(ANSI.Data[MaxLines], 80) Then Begin + If CurX > CurLength Then Begin + InsertLine (CurLine + 1); + + If Not LineDown(True) Then DrawPage(CurY, WinSize, True); + End Else Begin + TempLine := ANSI.Data[CurLine]; + + InsertLine (CurLine + 1); + + FillChar (ANSI.Data[CurLine][CurX], SizeOf(RecAnsiBufferChar) * (80 - CurX + 1), #0); + Move (TempLine[CurX], ANSI.Data[CurLine + 1][1], SizeOf(RecAnsiBufferChar) * (80 - CurX + 1)); + + If Not LineDown(True) Then + DrawPage (CurY - 1, WinSize, True); + End; + End Else + LineDown(True); +End; + +Function TEditorANSI.Edit : Boolean; +Var + Ch : Char; + Attr : Byte; +Begin + Result := False; + + ReDrawTemplate; + + While Not TBBSCore(Owner).ShutDown Do Begin + LocateCursor; + + Ch := TBBSCore(Owner).io.GetKey; + + If Session.io.IsArrow Then Begin + Case Ch of + #71 : CurX := 1; + #79 : CurX := CurLength + 1; + #72 : LineUp; + #80 : If CurLine < LastLine Then LineDown(False); + #75 : If CurX > 1 Then Dec(CurX); + #77 : If CurX <= RowSize Then Inc(CurX); + #73 : PageUp; + #81 : PageDown; + #83 : DoDelete; + End; + End Else + Case Ch of + ^V : InsertMode := Not InsertMode; //update on screen + ^Y : Begin + DeleteLine (CurLine); + + If CurLine > LastLine Then + InsertLine (CurLine); + + DrawPage (CurY, WinSize, False); + End; + ^Z : Break; + #08 : DoBackSpace; + #13 : DoEnter; + #32.. + #254 : If (CurLength >= RowSize) and (GetWrapPos(ANSI.Data[CurLine], RowSize, RowSize) = 0) Then Begin + If CurX = CurLength + 1 Then Begin + LineDown(True); + End; + End Else + DoChar(Ch); + End; + End; +End; + +End. diff --git a/mystic/bbs_edit_full.pas b/mystic/bbs_edit_full.pas index ab7321b..70e0538 100644 --- a/mystic/bbs_edit_full.pas +++ b/mystic/bbs_edit_full.pas @@ -984,4 +984,4 @@ Begin Dispose (CutText[A]); End; -End. +End. \ No newline at end of file diff --git a/mystic/bbs_filebase.pas b/mystic/bbs_filebase.pas index 528afd0..57aa37b 100644 --- a/mystic/bbs_filebase.pas +++ b/mystic/bbs_filebase.pas @@ -90,6 +90,7 @@ Type Function ExportFileList (NewFiles: Boolean; Qwk: Boolean) : Boolean; Function ArchiveView (FName : String) : Boolean; Procedure FileGroupChange (Ops: String; FirstBase, Intro : Boolean); + Procedure XferDisconnect; Procedure UploadFile; Procedure DownloadBatch; Procedure NewFileScan (Mode: Char); @@ -671,7 +672,7 @@ Begin Temp.NewScan := FBase.DefScan; Temp.LastNew := CurDateDos; - If Temp.NewScan = 2 Then Dec(Temp.NewScan); + If Temp.NewScan = 2 Then Dec (Temp.NewScan); Assign (FScanFile, Config.DataPath + FBase.FileName + '.scn'); {$I-} Reset (FScanFile); {$I+} @@ -1160,12 +1161,14 @@ Var If Session.User.Access(FBase.ListACS) Then Begin Inc (Total); + Session.io.PromptInfo[1] := strI2S(Total); Session.io.PromptInfo[2] := FBase.Name; GetFileScan; Session.io.PromptInfo[3] := Session.io.OutYN(FScan.NewScan > 0); + Session.io.OutFull (Session.GetPrompt(201)); If (Total MOD Config.FColumns = 0) And (Total > 0) Then Session.io.OutRawLn(''); @@ -1188,25 +1191,33 @@ Var B : Word; Begin B := 0; + Reset (FBaseFile); + Repeat Read (FBaseFile, FBase); + If Session.User.Access(FBase.ListACS) Then Inc(B); + If A = B Then Break; Until False; GetFileScan; + Session.io.PromptInfo[1] := FBase.Name; If FBase.DefScan = 2 Then Begin FScan.NewScan := 1; + Session.io.OutFullLn (Session.GetPrompt(289)); End Else If FScan.NewScan = 0 Then Begin FScan.NewScan := 1; + Session.io.OutFullLn (Session.GetPrompt(204)); End Else Begin FScan.NewScan := 0; + Session.io.OutFullLn (Session.GetPrompt(203)); End; @@ -2014,6 +2025,7 @@ Var OkFile := False; If (FDir.Flags And FDirDeleted <> 0) Then Exit; + If (FDir.Flags AND FDirOffline <> 0) And (Not Session.User.Access(Config.AcsSeeOffline)) Then Exit; If (FDir.Flags And FDirInvalid <> 0) And (Not Session.User.Access(Config.AcsSeeUnvalid)) Then Exit; If (FDir.Flags And FDirFailed <> 0) And (Not Session.User.Access(Config.AcsSeeFailed)) Then Exit; @@ -3213,10 +3225,11 @@ End; Procedure TFileBase.DownloadFile; Var - FName : String[70]; - Dir : String[40]; - Min : Integer; - Sec : Byte; + FName : String[70]; + Dir : String[40]; + Min : Integer; + Sec : Byte; + HangUp : Boolean; Begin If FBase.FileName = '' Then Begin Session.io.OutFullLn(Session.GetPrompt(38)); @@ -3267,6 +3280,8 @@ Begin Else Dir := FBase.Path; + HangUp := Session.io.GetYN(Session.GetPrompt(66), False); + If SendFile(Dir + FName) Then Begin Session.SystemLog ('Downloaded: ' + FDir.FileName); @@ -3284,6 +3299,8 @@ Begin Session.SystemLog ('Download of ' + FDir.FileName + ' FAILED'); FileErase(Session.TempPath + FName); + + If HangUp Then XferDisconnect; End; 1 : Session.io.OutFullLn (Session.GetPrompt(224)); 2 : Session.io.OutFullLn (Session.GetPrompt(58)); @@ -3300,14 +3317,32 @@ Begin Session.io.OutFullLn (Session.GetPrompt(51)); End; +Procedure TFileBase.XferDisconnect; +Var + Timer : LongInt; +Begin + Timer := TimerSet(1000); + + Session.io.OutFull(Session.GetPrompt(67)); + + While Not TimerUp(Timer) Do + If Session.io.InKey(1000) <> #255 Then Begin + Session.io.OutRawLn(''); + Exit; + End; + + Halt(0); +End; + Procedure TFileBase.DownloadBatch; Var - A : Byte; - K : LongInt; - M : Integer; - Dir : String[40]; - Old : RecFileBase; - FL : Text; + A : Byte; + K : LongInt; + M : Integer; + Dir : String[40]; + Old : RecFileBase; + FL : Text; + Hangup : Boolean; Begin K := 0; @@ -3324,6 +3359,8 @@ Begin If SelectProtocol(True, True) = 'Q' Then Exit; + HangUp := Session.io.GetYN(Session.GetPrompt(66), False); + Assign (FL, Session.TempPath + 'file.lst'); ReWrite (FL); @@ -3397,6 +3434,8 @@ Begin BatchNum := 0; DirClean (Session.TempPath, ''); + + If HangUp Then XferDisconnect; End; Procedure TFileBase.FileSearch; diff --git a/mystic/bbs_io.pas b/mystic/bbs_io.pas index db6facc..3b1b64c 100644 --- a/mystic/bbs_io.pas +++ b/mystic/bbs_io.pas @@ -474,9 +474,9 @@ Begin FmtString := False; Case FmtType of - 1 : Str := strPadR(Str, FmtLen, ' '); - 2 : Str := strPadL(Str, FmtLen, ' '); - 3 : Str := strPadC(Str, FmtLen, ' '); + 1 : Str := strPadR(Str, FmtLen, ' '); + 2 : Str := strPadL(Str, FmtLen, ' '); + 3 : Str := strPadC(Str, FmtLen, ' '); End; End; @@ -928,6 +928,7 @@ Begin BufAddStr (#27 + '[K'); End; +(* Function TBBSIO.Pipe2Ansi (Color: Byte) : String; Begin Result := ''; @@ -967,8 +968,8 @@ Begin 23: Result := Result + #27 + '[47m'; End; End; +*) -(* Function TBBSIO.Pipe2Ansi (Color: Byte) : String; Var CurFG : Byte; @@ -1033,7 +1034,6 @@ Begin End; End; End; -*) Function TBBSIO.Attr2Ansi (Attr: Byte) : String; Begin @@ -1055,6 +1055,8 @@ Procedure TBBSIO.AnsiGotoXY (X: Byte; Y: Byte); Begin If Graphics = 0 Then Exit; + If (X = Screen.CursorX) and (Y = Screen.CursorY) Then Exit; + If X = 0 Then X := Screen.CursorX; If Y = 0 Then Y := Screen.CursorY; @@ -1138,8 +1140,9 @@ Var End; Begin - Result := False; - NoFile := True; + Result := False; + NoFile := True; + FileMode := 66; If (Pos(PathSep, FName) > 0) Then Begin If Not FileExist(FName) Then diff --git a/mystic/bbs_msgbase.pas b/mystic/bbs_msgbase.pas index 7444886..a5cf03a 100644 --- a/mystic/bbs_msgbase.pas +++ b/mystic/bbs_msgbase.pas @@ -62,7 +62,7 @@ Type Procedure GlobalMessageSearch (Mode: Char); Procedure SetMessagePointers; Procedure ViewSentEmail; - Function ResolveOrigin (var mArea: RecMessageBase) : String; + Function ResolveOrigin (Var mArea: RecMessageBase) : String; // QWK and QWKE goodies Procedure DownloadQWK (Extended: Boolean; Data: String); Procedure UploadREP; @@ -366,7 +366,7 @@ Begin For A := 1 to Lines Do Msg^.DoStringLn(MsgText[A]); - If Session.User.ThisUser.SigUse and (Session.User.ThisUser.SigLength > 0) Then Begin + If (MBase.Flags AND MBAutoSigs <> 0) and Session.User.ThisUser.SigUse and (Session.User.ThisUser.SigLength > 0) Then Begin Assign (DF, Config.DataPath + 'autosig.dat'); Reset (DF, 1); @@ -1483,6 +1483,18 @@ Var Session.io.OutRawLn(''); End; + Procedure RemoveNewScan (PromptNumber: SmallInt); + Begin + GetMessageScan; + + If MScan.NewScan = 1 Then + If Session.io.GetYN(Session.GetPrompt(PromptNumber), False) Then Begin + MScan.NewScan := 0; + + SetMessageScan; + End; + End; + (**************************************************************************) (**************************************************************************) (**************************************************************************) @@ -1560,7 +1572,7 @@ Var MsgText[Lines] := MsgBase^.GetString(79); If MsgText[Lines][1] = #1 Then Begin - If Copy(MsgText[Lines], 1, 6) = #1 + 'MSGID' Then + If Copy(MsgText[Lines], 2, 5) = 'MSGID' Then ReplyID := Copy(MsgText[Lines], 9, Length(MsgText[Lines])); Dec (Lines); @@ -1667,6 +1679,9 @@ Var 'I' : Begin LastRead := MsgBase^.GetHighMsgNum; Ansi_View_Message := True; + + RemoveNewScan(495); + Exit; End; 'J' : Begin @@ -2077,6 +2092,9 @@ Var 'G' : Break; 'I' : Begin LastRead := MsgBase^.GetHighMsgNum; + + RemoveNewScan(495); + Break; End; '?' : Begin @@ -2158,7 +2176,7 @@ Var Str := MsgBase^.GetString(79); If Str[1] = #1 Then Begin - If Copy(Str, 1, 6) = #1 + 'MSGID' Then + If Copy(Str, 2, 5) = 'MSGID' Then ReplyID := Copy(Str, 9, Length(Str)); End Else Send_Msg_Text (Str); @@ -2220,6 +2238,9 @@ Var 'H' : LastRead := MsgBase^.GetMsgNum - 1; 'I' : Begin LastRead := MsgBase^.GetHighMsgNum; + + RemoveNewScan(494); + Exit; End; 'J' : Begin @@ -2485,33 +2506,43 @@ End; Procedure TMsgBase.PostMessage (Email: Boolean; Data: String); Var - MsgTo : String[30]; - MsgSubj : String[60]; - MsgAddr : String[20]; - TempStr : String; - DestAddr : RecEchoMailAddr; - A : Integer; - Lines : Integer; - Forced : Boolean; - Old : RecMessageBase; + MsgTo : String[30]; + MsgSubj : String[60]; + MsgAddr : String[20]; + TempStr : String; + DestAddr : RecEchoMailAddr; + A : Integer; + Lines : Integer; + Forced : Boolean; + Old : RecMessageBase; + SaveGroup : Boolean; Begin - Old := MBase; + Old := MBase; + SaveGroup := Session.User.IgnoreGroup; If Email Then Begin Reset (MBaseFile); Read (MBaseFile, MBase); Close (MBaseFile); + + Session.User.IgnoreGroup := True; End; If MBase.FileName = '' Then Begin Session.io.OutFullLn (Session.GetPrompt(110)); - MBase := Old; + + MBase := Old; + Session.User.IgnoreGroup := SaveGroup; + Exit; End; If Not Session.User.Access(MBase.PostACS) Then Begin Session.io.OutFullLn (Session.GetPrompt(105)); - MBase := Old; + + MBase := Old; + Session.User.IgnoreGroup := SaveGroup; + Exit; End; @@ -2582,7 +2613,9 @@ Begin End; If MsgTo = '' Then Begin - MBase := Old; + MBase := Old; + Session.User.IgnoreGroup := SaveGroup; + Exit; End; @@ -2596,7 +2629,9 @@ Begin If Forced Then Session.io.OutFull (Session.GetPrompt(307)) Else Begin - MBase := Old; + MBase := Old; + Session.User.IgnoreGroup := SaveGroup; + Exit; End; Until MsgSubj <> ''; @@ -2616,7 +2651,9 @@ Begin { also could be used in mass email rewrite and qwk .REP rewrite } If Not OpenCreateBase(MsgBase, MBase) Then Begin - MBase := Old; + MBase := Old; + Session.User.IgnoreGroup := SaveGroup; + Exit; End; @@ -2669,7 +2706,8 @@ Begin End Else Session.io.OutFullLn (Session.GetPrompt(109)); - MBase := Old; + MBase := Old; + Session.User.IgnoreGroup := SaveGroup; End; Procedure TMsgBase.CheckEMail; @@ -3411,7 +3449,7 @@ Var Pick : LongInt; Begin Result := ''; - Loc := Pos('@RANDOM=', mArea.Origin); + Loc := Pos('@RANDOM=', strUpper(mArea.Origin)); If Loc > 0 Then Begin FN := strStripB(Copy(mArea.Origin, Loc + 8, 255), ' '); diff --git a/mystic/bbs_msgbase_ansi.pas b/mystic/bbs_msgbase_ansi.pas index 3eaf4a9..bf0274c 100644 --- a/mystic/bbs_msgbase_ansi.pas +++ b/mystic/bbs_msgbase_ansi.pas @@ -9,21 +9,21 @@ Uses BBS_Common; Type - PtrMessageLine = ^RecMessageLine; - RecMessageLine = Array[1..80] of Record - Ch : Char; - Attr : Byte; - End; + RecAnsiBufferChar = Record + Ch : Char; + Attr : Byte; + End; - RecMessageAnsi = Array[1..mysMaxMsgLines] of RecMessageLine; - // make this a pointer? + RecAnsiBufferLine = Array[1..80] of RecAnsiBufferChar; + RecAnsiBuffer = Array[1..mysMaxMsgLines] of RecAnsiBufferLine; TMsgBaseAnsi = Class GotAnsi : Boolean; GotPipe : Boolean; + GotClear : Boolean; PipeCode : String[2]; Owner : Pointer; - Data : RecMessageAnsi; + Data : RecAnsiBuffer; Code : String; Lines : Word; CurY : Word; @@ -87,9 +87,10 @@ Begin Attr := 7; GotAnsi := False; GotPipe := False; + GotClear := False; PipeCode := ''; - FillChar (Data, SizeOf(Data), 0); + FillChar (Data, SizeOf(Data), #0); ResetControlCode; End; @@ -353,7 +354,7 @@ Begin Case Ch of #27 : Escape := 1; #9 : MoveXY (CurX + 8, CurY); - #12 : {Edit.ClearScreenData}; + #12 : GotClear := True; Else If Ch = '|' Then GotPipe := True @@ -488,4 +489,4 @@ Begin Dec (Lines); End; -End. +End. \ No newline at end of file diff --git a/mystic/default.txt b/mystic/default.txt index 866b035..4ac3475 100644 --- a/mystic/default.txt +++ b/mystic/default.txt @@ -151,8 +151,10 @@ 064 |01[|10þ|01] |09Search all file groups? |11 ; Start your file transfer now &1=selected protocol 065 |CR|12Start your |15|&1 |12transfer now... -066 UNUSED -067 UNUSED +; Disconnect after download? +066 |CR|12Disconnect after file transfer? |11 +; Disconneting in 10 seconds, press a key to abort +067 |CR|09Disconnecting in 10 seconds: Press a key to abort. 068 |CR|12You do not have access to upload here! 069 |CR|12Illegal filename.|DE|DE|DE 070 |CR|14Searching for duplicate files ... @@ -345,7 +347,7 @@ ; One Liner header 188 |CL|09Ú|$D77Ä|01¿|CR|09³|17 ± |15One Liners|$D64 |01|16³|CR|09À|01|$D77ÄÙ|CR ; One liner prompt -189 |CR |09|$D77Ä|CR |01[|10þ|01] |09Add to the one liners? +189 |CR |09|$D77Ä|CR |01[|10þ|01] |09Add to the one liners? |XX 190 |CR|01[|10þ|01] |09Enter your one liner:|CR 191 |CR|12Unable to view archive. ; Archive view header &1 = Filename @@ -966,3 +968,7 @@ 492 |CR|09Forward message to which base (|10?|09/|10List|09): |11 ; Sysop password prompt 493 |CR|09Sysop Password: |XX +; Normal msg reader: Remove from newscan? (after I command) +494 |CR|12Remove |15|MB |12from message newscan? |XX +; Lightbar msg reader: Remove from newscan (after I command) +495 |CR|12Remove |15|MB |12from message newscan? |XX \ No newline at end of file diff --git a/mystic/mbbsutil.pas b/mystic/mbbsutil.pas index 32e593a..f336311 100644 --- a/mystic/mbbsutil.pas +++ b/mystic/mbbsutil.pas @@ -64,6 +64,7 @@ Const TrashFile : String = ''; TempPath : String = ''; AreasFile : String = ''; + FCheckKill : Boolean = False; Var ConfigFile : File of RecConfig; @@ -119,7 +120,7 @@ Begin WriteLn ('-BKILL Delete BBSes which haven''t been verified in '); WriteLn ('-BPACK Pack all BBS lists'); WriteLn ('-BSORT Sorts and packs BBS list by '); - WriteLn ('-FCHECK Checks file entries for correct size and status'); + WriteLn ('-FCHECK Check filelist for correct size/status'); WriteLn ('-FIXINDEX Fix broken permanent index for msg/file bases'); WriteLn ('-FPACK Pack file bases'); WriteLn ('-FSORT Sort file base entries by filename'); @@ -281,7 +282,7 @@ Var FDirFile : File of RecFileList; FDir : RecFileList; TFDirFile : File of RecFileList; - DF : File of Byte; + DF : File; Begin Write ('Checking File Bases : '); @@ -305,24 +306,27 @@ Begin While Not Eof(FDirFile) Do Begin Read (FDirFile, FDir); - If FDir.Flags And FDirDeleted = 0 Then Begin - Assign (DF, FBase.Path + FDir.FileName); - {$I-} Reset (DF); {$I+} - If IoResult <> 0 Then - FDir.Flags := FDir.Flags AND FDirOffline - Else Begin - FDir.Size := FileSize(DF); + If FDir.Flags AND FDirDeleted <> 0 Then Continue; - If FDir.Size = 0 Then - FDir.Flags := FDir.Flags OR FDirOffline - Else - FDir.Flags := FDir.Flags AND NOT FDirOffline; + Assign (DF, FBase.Path + FDir.FileName); + {$I-} Reset (DF, 1); {$I+} - Close (DF); - End; + If IoResult <> 0 Then + FDir.Flags := FDir.Flags OR FDirOffline + Else Begin + FDir.Size := FileSize(DF); - Write (TFDirFile, FDir); + If FDir.Size = 0 Then + FDir.Flags := FDir.Flags OR FDirOffline + Else + FDir.Flags := FDir.Flags AND NOT FDirOffline; + + Close (DF); End; + + If (FDir.Flags AND FDirOffline <> 0) and FCheckKill Then Continue; + + Write (TFDirFile, FDir); End; Close (FDirFile); {delete backup file} @@ -1130,7 +1134,13 @@ Begin End Else BBSSort := True; End; - If Temp = '-FCHECK' Then FileCheck := True; + If Temp = '-FCHECK' Then Begin + FileCheck := True; + + FCheckKill := strUpper(ParamStr(A+1)) = 'KILL'; + + If FCheckKill Then Inc(A); + End; If Temp = '-FIXINDEX' Then FixIndex := True; If Temp = '-FPACK' Then FilePack := True; If Temp = '-FSORT' Then FileSort := True; @@ -1161,6 +1171,7 @@ Begin End; If Temp = '-UPACK' Then UserPack := True; + If Temp = '-NOCHECK' Then NodeCheck := False; Inc (A); End; diff --git a/mystic/mis_client_ftp.pas b/mystic/mis_client_ftp.pas index afd1149..cdc8e78 100644 --- a/mystic/mis_client_ftp.pas +++ b/mystic/mis_client_ftp.pas @@ -569,6 +569,7 @@ Begin DirFile.Read(Dir); If (Dir.Flags And FDirDeleted <> 0) Then Continue; + If (Dir.Flags and FDirOffline <> 0) And (Not CheckAccess(User, True, bbsConfig.AcsSeeOffline)) Then Continue; If (Dir.Flags And FDirInvalid <> 0) And (Not CheckAccess(User, True, bbsConfig.AcsSeeUnvalid)) Then Continue; If (Dir.Flags And FDirFailed <> 0) And (Not CheckAccess(User, True, bbsConfig.AcsSeeFailed)) Then Continue; diff --git a/mystic/mis_nodedata.pas b/mystic/mis_nodedata.pas index e8be36a..f7226ad 100644 --- a/mystic/mis_nodedata.pas +++ b/mystic/mis_nodedata.pas @@ -47,7 +47,7 @@ Var NI : TNodeInfoRec; Begin For Count := 1 to NodeTotal Do Begin - GetNodeInfo(Count, NI); + GetNodeInfo (Count, NI); Assign (ChatFile, bbsConfig.DataPath + 'chat' + strI2S(NI.Num) + '.dat'); @@ -61,7 +61,7 @@ Begin End Else NI.Busy := False; - SetNodeInfo(NI.Num, NI); + SetNodeInfo (NI.Num, NI); End; End; diff --git a/mystic/mystic.pas b/mystic/mystic.pas index 0100af1..457e41d 100644 --- a/mystic/mystic.pas +++ b/mystic/mystic.pas @@ -23,6 +23,8 @@ Program Mystic; {$I M_OPS.PAS} +{.$DEFINE EDITWORK} + Uses {$IFDEF DEBUG} HeapTrc, @@ -44,8 +46,23 @@ Uses bbs_Common, bbs_Core, bbs_NodeInfo, + {$IFDEF EDITWORK} + bbs_edit_ansi, + {$ENDIF} bbs_Cfg_Main; +{$IFDEF EDITWORK} +Procedure TestEditor; +Var + T : TEditorANSI; +Begin + T := TEditorANSI.Create(Pointer(Session)); + + T.Edit; + T.Free; +End; +{$ENDIF} + Procedure InitClasses; Begin Assign (ConfigFile, 'mystic.dat'); @@ -359,6 +376,8 @@ Begin DirChange(JustPath(ParamStr(0))); + //FileMode := 66; + InitClasses; Screen.TextAttr := 7; @@ -467,6 +486,11 @@ Begin Set_Node_Action (Session.GetPrompt(345)); + {$IFDEF EDITWORK} + TestEditor; + Halt(0); + {$ENDIF} + Session.User.UserLogon1 (UserName, Password, Script); If Session.TimeOffset > 0 Then diff --git a/mystic/records.pas b/mystic/records.pas index 452b593..7d3778d 100644 --- a/mystic/records.pas +++ b/mystic/records.pas @@ -59,7 +59,7 @@ Const mysMaxMenuCmds = 25; // Max menu commands per item mysMaxMenuInput = 12; mysMaxMenuStack = 8; - mysMaxThemeText = 493; // Total prompts in theme file + mysMaxThemeText = 495; // Total prompts in theme file fn_SemFileEcho = 'echomail.now'; fn_SemFileNews = 'newsmail.now'; @@ -325,14 +325,14 @@ Type inetTNHidden : Boolean; ThemeOnStart : Boolean; StartCodePage : Byte; - + AcsSeeOffline : String[mysMaxAcsSize]; //inetSMTPRelay : String[30]; //inetSMTPLogin : String[30]; //inetSMTPPW : String[30]; //EmailValidationLevel //AllowEmailPWReset - Reserved : Array[1..843] of Char; + Reserved : Array[1..812] of Char; End; Const diff --git a/mystic/whatsnew.txt b/mystic/whatsnew.txt index c27aad3..0e77e6e 100644 --- a/mystic/whatsnew.txt +++ b/mystic/whatsnew.txt @@ -2536,11 +2536,50 @@ ! According to a document I saw, the ANSI-BBS C function to move the cursor should hard stop at 80. Mystic's ANSI parser wraps to the next line which I think was added in a while back to increase ANSI compatibility. For - now I changed it back to follow what this standard document is claiming, - even if it is sort of against my better judgement. + now I changed it back to follow what this standard document is claiming. + If a message bases's data files actually exist, for but some reason the highest message number is 0 (ie everything has been deleted), Mystic will now display the "There are no messages in this base" prompt when reading. + + When downloading a file or a batch, Mystic will now ask the user if they + would like to disconnect after the transfer. Replace two prompts in your + language file: + + ; Disconnect after download? + 066 |CR|12Disconnect after file transfer? |11 + + ; Disconneting in 10 seconds, press a key to abort + 067 |CR|09Disconnecting in 10 seconds: Press a key to abort. + + ! Mystic wasn't properly checking the message base "auto signature" setting + before adding in the user's auto signature. + + + Mystic will now ignore the group membership contraints in the ACS string + when using the MW (write email) menu command. + + + Mystic now has an ACS setting to "see offline" files in the file bases. + This setting is found in System Config -> File Base Settings. + + + If you select the I (Ignore all messages) option while reading message + bases, Mystic will now ask you if you want to remove the base from your + new message scan. Two new prompts go along with this: + + ; Normal msg reader: Remove from newscan? (after I command) + 494 |CR|12Remove |15|MB |12from message newscan? |XX + + ; Lightbar msg reader: Remove from newscan (after I command) + 495 |CR|12Remove |15|MB |12from message newscan? |XX + + ! MBBSUTIL -NOCHECK option was not bypassing the online user check. + + ! MBBSUTIL -FCHECK was not properly marking some files OFFLINE when they + should have been. + + + MBBSUTIL -FCHECK now has an optional command after it which will cause + missing files to be removed from the file listing, instead of marked + offline. Add KILL after fcheck to enable this function: + + mbbsutil -fcheck kill +