mysticbbs/mystic/bbs_msgbase_ansi.pas

579 lines
12 KiB
ObjectPascal
Raw Permalink Normal View History

2012-02-13 16:50:48 -08:00
Unit BBS_MsgBase_Ansi;
// ====================================================================
// Mystic BBS Software Copyright 1997-2013 By James Coyle
// ====================================================================
//
// This file is part of Mystic BBS.
//
// Mystic BBS is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Mystic BBS is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Mystic BBS. If not, see <http://www.gnu.org/licenses/>.
//
// ====================================================================
2013-02-15 20:18:56 -08:00
{$I M_OPS.PAS}
2012-02-13 16:50:48 -08:00
Interface
Uses
m_Strings,
2013-08-29 03:04:20 -07:00
BBS_Records;
2012-02-13 16:50:48 -08:00
Type
2013-03-04 07:53:06 -08:00
RecAnsiBufferChar = Record
Ch : Char;
Attr : Byte;
End;
2012-02-13 16:50:48 -08:00
2013-03-04 07:53:06 -08:00
RecAnsiBufferLine = Array[1..80] of RecAnsiBufferChar;
RecAnsiBuffer = Array[1..mysMaxMsgLines] of RecAnsiBufferLine;
2012-02-13 16:50:48 -08:00
TMsgBaseAnsi = Class
GotAnsi : Boolean;
GotPipe : Boolean;
2013-03-04 07:53:06 -08:00
GotClear : Boolean;
2012-02-13 16:50:48 -08:00
PipeCode : String[2];
Owner : Pointer;
2013-03-04 07:53:06 -08:00
Data : RecAnsiBuffer;
2012-02-13 16:50:48 -08:00
Code : String;
Lines : Word;
CurY : Word;
Escape : Byte;
SavedX : Byte;
SavedY : Byte;
CurX : Byte;
Attr : Byte;
2013-03-13 20:56:42 -07:00
LastChar : Char;
2012-02-13 16:50:48 -08:00
Procedure SetFore (Color: Byte);
Procedure SetBack (Color: Byte);
Procedure ResetControlCode;
2013-03-13 20:56:42 -07:00
Function ParseNumber : Integer;
2012-02-13 16:50:48 -08:00
Function AddChar (Ch: Char) : Boolean;
Procedure MoveXY (X, Y: Word);
Procedure MoveUP;
Procedure MoveDOWN;
Procedure MoveLEFT;
Procedure MoveRIGHT;
Procedure MoveCursor;
Procedure CheckCode (Ch: Char);
Procedure ProcessChar (Ch: Char);
Constructor Create (O: Pointer; Msg: Boolean);
Destructor Destroy; Override;
2012-02-13 16:50:48 -08:00
Procedure Clear;
Function ProcessBuf (Var Buf; BufLen: Word) : Boolean;
Procedure WriteLine (Line: Word; Flush: Boolean);
Procedure DrawLine (Y, Line: Word; Flush: Boolean);
Procedure DrawPage (pStart, pEnd, pLine: Word);
2013-09-18 15:57:31 -07:00
Procedure SetLineColor (NewAttr, Line: Word);
Procedure RemoveLine (Line: Word);
2012-02-13 16:50:48 -08:00
End;
Implementation
Uses
BBS_Core;
Constructor TMsgBaseAnsi.Create (O: Pointer; Msg: Boolean);
Begin
Inherited Create;
Owner := O;
Clear;
End;
Destructor TMsgBaseAnsi.Destroy;
Begin
Inherited Destroy;
End;
Procedure TMsgBaseAnsi.Clear;
Begin
Lines := 1;
CurX := 1;
CurY := 1;
Attr := 7;
GotAnsi := False;
GotPipe := False;
2013-03-04 07:53:06 -08:00
GotClear := False;
2012-02-13 16:50:48 -08:00
PipeCode := '';
2013-03-04 07:53:06 -08:00
FillChar (Data, SizeOf(Data), #0);
2012-02-13 16:50:48 -08:00
ResetControlCode;
End;
Procedure TMsgBaseAnsi.ResetControlCode;
Begin
Escape := 0;
Code := '';
End;
Procedure TMsgBaseAnsi.SetFore (Color: Byte);
Begin
Attr := Color + ((Attr SHR 4) AND 7) * 16;
End;
Procedure TMsgBaseAnsi.SetBack (Color: Byte);
Begin
Attr := (Attr AND $F) + Color * 16;
End;
Function TMsgBaseAnsi.AddChar (Ch: Char) : Boolean;
Begin
AddChar := False;
Data[CurY][CurX].Ch := Ch;
Data[CurY][CurX].Attr := Attr;
If CurX < 80 Then
Inc (CurX)
Else Begin
If CurY = mysMaxMsgLines Then Begin
AddChar := True;
Exit;
End Else Begin
CurX := 1;
Inc (CurY);
End;
End;
End;
2013-03-13 20:56:42 -07:00
Function TMsgBaseAnsi.ParseNumber : Integer;
2012-02-13 16:50:48 -08:00
Var
2013-03-13 20:56:42 -07:00
Res : LongInt;
Str : String;
2012-02-13 16:50:48 -08:00
Begin
2013-03-13 20:56:42 -07:00
Val(Code, Result, Res);
2012-02-13 16:50:48 -08:00
2013-03-13 20:56:42 -07:00
If Res = 0 Then
Code := ''
2012-02-13 16:50:48 -08:00
Else Begin
2013-03-13 20:56:42 -07:00
Str := Copy(Code, 1, Pred(Res));
2012-02-13 16:50:48 -08:00
2013-03-13 20:56:42 -07:00
Delete (Code, 1, Res);
Val (Str, Result, Res);
2012-02-13 16:50:48 -08:00
End;
End;
Procedure TMsgBaseAnsi.MoveXY (X, Y: Word);
Begin
If X > 80 Then X := 80;
If Y > mysMaxMsgLines Then Y := mysMaxMsgLines;
CurX := X;
CurY := Y;
End;
Procedure TMsgBaseAnsi.MoveCursor;
Var
X : Byte;
Y : Byte;
Begin
2013-03-13 20:56:42 -07:00
Y := ParseNumber;
2012-02-13 16:50:48 -08:00
If Y = 0 Then Y := 1;
2013-03-13 20:56:42 -07:00
X := ParseNumber;
If X = 0 Then X := 1;
2012-02-13 16:50:48 -08:00
MoveXY (X, Y);
ResetControlCode;
End;
Procedure TMsgBaseAnsi.MoveUP;
Var
NewPos : Integer;
Offset : Integer;
Begin
2013-03-13 20:56:42 -07:00
Offset := ParseNumber;
2012-02-13 16:50:48 -08:00
If Offset = 0 Then Offset := 1;
If (CurY - Offset) < 1 Then
NewPos := 1
Else
NewPos := CurY - Offset;
MoveXY (CurX, NewPos);
ResetControlCode;
End;
Procedure TMsgBaseAnsi.MoveDOWN;
Var
NewPos : Byte;
Begin
2013-03-13 20:56:42 -07:00
NewPos := ParseNumber;
2012-02-13 16:50:48 -08:00
If NewPos = 0 Then NewPos := 1;
MoveXY (CurX, CurY + NewPos);
ResetControlCode;
End;
Procedure TMsgBaseAnsi.MoveLEFT;
Var
NewPos : Integer;
Offset : Integer;
Begin
2013-03-13 20:56:42 -07:00
Offset := ParseNumber;
2012-02-13 16:50:48 -08:00
If Offset = 0 Then Offset := 1;
If CurX - Offset < 1 Then
NewPos := 1
Else
NewPos := CurX - Offset;
MoveXY (NewPos, CurY);
ResetControlCode;
End;
Procedure TMsgBaseAnsi.MoveRIGHT;
Var
NewPos : Integer;
Offset : Integer;
Begin
2013-03-13 20:56:42 -07:00
Offset := ParseNumber;
2012-02-13 16:50:48 -08:00
If Offset = 0 Then Offset := 1;
If CurX + Offset > 80 Then Begin
2013-03-07 07:39:10 -08:00
NewPos := 80;
2012-02-13 16:50:48 -08:00
End Else
NewPos := CurX + Offset;
MoveXY (NewPos, CurY);
ResetControlCode;
End;
Procedure TMsgBaseAnsi.CheckCode (Ch: Char);
Var
Temp1 : Byte;
Temp2 : Byte;
Begin
Case Ch of
2012-02-21 14:43:02 -08:00
'0'..
'9',
';',
'?' : Code := Code + Ch;
'H',
'f' : MoveCursor;
'A' : MoveUP;
'B' : MoveDOWN;
'C' : MoveRIGHT;
'D' : MoveLEFT;
'J' : ResetControlCode;
'K' : Begin
Temp1 := CurX;
For Temp2 := CurX To 80 Do
AddChar(' ');
MoveXY (Temp1, CurY);
ResetControlCode;
End;
'h' : ResetControlCode;
'm' : Begin
While Length(Code) > 0 Do Begin
2013-03-13 20:56:42 -07:00
Case ParseNumber of
2012-02-21 14:43:02 -08:00
0 : Attr := 7;
1 : Attr := Attr OR $08;
5 : Attr := Attr OR $80;
7 : Begin
Attr := Attr AND $F7;
Attr := ((Attr AND $70) SHR 4) + ((Attr AND $7) SHL 4) + Attr AND $80;
2012-02-13 16:50:48 -08:00
End;
2012-02-21 14:43:02 -08:00
30: Attr := (Attr AND $F8) + 0;
31: Attr := (Attr AND $F8) + 4;
32: Attr := (Attr AND $F8) + 2;
33: Attr := (Attr AND $F8) + 6;
34: Attr := (Attr AND $F8) + 1;
35: Attr := (Attr AND $F8) + 5;
36: Attr := (Attr AND $F8) + 3;
37: Attr := (Attr AND $F8) + 7;
40: SetBack (0);
41: SetBack (4);
42: SetBack (2);
43: SetBack (6);
44: SetBack (1);
45: SetBack (5);
46: SetBack (3);
47: SetBack (7);
End;
End;
ResetControlCode;
End;
's' : Begin
SavedX := CurX;
SavedY := CurY;
ResetControlCode;
End;
'u' : Begin
MoveXY (SavedX, SavedY);
ResetControlCode;
End;
2012-02-13 16:50:48 -08:00
Else
ResetControlCode;
End;
End;
2013-03-14 11:14:46 -07:00
(*
2012-02-13 16:50:48 -08:00
Procedure TMsgBaseAnsi.ProcessChar (Ch: Char);
Begin
If GotPipe Then Begin
PipeCode := PipeCode + Ch;
If Length(PipeCode) = 2 Then Begin
2013-03-13 20:56:42 -07:00
If PipeCode = '00' Then
SetFore(0)
2012-02-13 16:50:48 -08:00
Else
2013-03-13 20:56:42 -07:00
Case strS2I(PipeCode) of
01..
15 : SetFore(strS2I(PipeCode));
16..
23 : SetBack(strS2I(PipeCode) - 16);
Else
AddChar('|');
AddChar(PipeCode[1]);
AddChar(PipeCode[2]);
2012-02-13 16:50:48 -08:00
End;
GotPipe := False;
PipeCode := '';
End;
Exit;
End;
Case Escape of
0 : Begin
Case Ch of
2013-03-13 20:56:42 -07:00
#0 : ;
2012-02-13 16:50:48 -08:00
#9 : MoveXY (CurX + 8, CurY);
2013-03-04 07:53:06 -08:00
#12 : GotClear := True;
2013-03-13 20:56:42 -07:00
#13 : CurX := 1;
#27 : Escape := 1;
2012-02-13 16:50:48 -08:00
Else
2013-03-14 11:14:46 -07:00
If Ch = '|' Then
GotPipe := True
Else
2012-02-13 16:50:48 -08:00
AddChar (Ch);
ResetControlCode;
End;
End;
1 : If Ch = '[' Then Begin
Escape := 2;
Code := '';
GotAnsi := True;
End Else
Escape := 0;
2012-02-13 16:50:48 -08:00
2 : CheckCode(Ch);
Else
ResetControlCode;
End;
2013-03-13 20:56:42 -07:00
LastChar := Ch;
2012-02-13 16:50:48 -08:00
End;
2013-03-14 11:14:46 -07:00
*)
Procedure TMsgBaseAnsi.ProcessChar (Ch: Char);
Procedure OneChar (C: Char);
Begin
Case Escape of
0 : Begin
Case C of
#0 : ;
#9 : MoveXY (CurX + 8, CurY);
#12 : GotClear := True;
#13 : CurX := 1;
#27 : Escape := 1;
Else
If C = '|' Then
GotPipe := True
Else
AddChar (C);
ResetControlCode;
End;
End;
1 : If C = '[' Then Begin
Escape := 2;
Code := '';
GotAnsi := True;
End Else
Escape := 0;
2 : CheckCode(C);
Else
ResetControlCode;
End;
LastChar := C;
End;
Begin
If GotPipe Then Begin
PipeCode := PipeCode + Ch;
If Length(PipeCode) = 2 Then Begin
2013-04-27 17:02:29 -07:00
If (PipeCode[1] in ['0'..'2']) and (PipeCode[2] in ['0'..'9']) Then Begin
If PipeCode = '00' Then
SetFore(0)
Else Begin
Case strS2I(PipeCode) of
01..
15 : SetFore(strS2I(PipeCode));
16..
23 : SetBack(strS2I(PipeCode) - 16);
Else
AddChar ('|');
OneChar (PipeCode[1]);
OneChar (PipeCode[2]);
End;
End;
End Else Begin
AddChar ('|');
OneChar (PipeCode[1]);
OneChar (PipeCode[2]);
2013-03-14 11:14:46 -07:00
End;
GotPipe := False;
PipeCode := '';
End;
Exit;
End;
OneChar (Ch);
End;
2012-02-13 16:50:48 -08:00
Function TMsgBaseAnsi.ProcessBuf (Var Buf; BufLen: Word) : Boolean;
Var
Count : Word;
Buffer : Array[1..4096] of Char Absolute Buf;
Begin
Result := False;
For Count := 1 to BufLen Do Begin
If CurY > Lines Then Lines := CurY;
2013-03-13 20:56:42 -07:00
2012-02-13 16:50:48 -08:00
Case Buffer[Count] of
#10 : If CurY = mysMaxMsgLines Then Begin
Result := True;
GotAnsi := False;
2013-03-13 20:56:42 -07:00
2012-02-13 16:50:48 -08:00
Break;
2013-03-13 20:56:42 -07:00
End Else Begin
2012-02-13 16:50:48 -08:00
Inc (CurY);
2013-03-13 20:56:42 -07:00
If LastChar <> #13 Then CurX := 1;
End;
2012-02-13 16:50:48 -08:00
#26 : Begin
Result := True;
Break;
End;
Else
ProcessChar(Buffer[Count]);
End;
End;
End;
Procedure TMsgBaseAnsi.WriteLine (Line: Word; Flush: Boolean);
Var
Count : Byte;
Begin
If Line > Lines Then Exit;
For Count := 1 to 79 Do Begin
Session.io.BufAddStr (Session.io.Attr2Ansi(Data[Line][Count].Attr));
2012-02-13 16:50:48 -08:00
If Data[Line][Count].Ch in [#0, #255] Then
Session.io.BufAddStr(' ')
Else
Session.io.BufAddStr (Data[Line][Count].Ch);
End;
Session.io.BufAddStr(#13#10);
If Flush Then Session.io.BufFlush;
Inc (Session.io.PausePtr);
End;
Procedure TMsgBaseAnsi.DrawLine (Y, Line: Word; Flush: Boolean);
Var
Count : Byte;
Begin
Session.io.AnsiGotoXY(1, Y);
If Line > Lines Then Begin
Session.io.BufAddStr(Session.io.Attr2Ansi(Session.io.ScreenInfo[1].A));
Session.io.AnsiClrEOL;
End Else
For Count := 1 to 80 Do Begin
Session.io.BufAddStr (Session.io.Attr2Ansi(Data[Line][Count].Attr));
If Data[Line][Count].Ch in [#0, #255] Then
Session.io.BufAddStr(' ')
Else
Session.io.BufAddStr (Data[Line][Count].Ch);
End;
If Flush Then Session.io.BufFlush;
End;
Procedure TMsgBaseAnsi.DrawPage (pStart, pEnd, pLine: Word);
Var
Count : Word;
Begin
For Count := pStart to pEnd Do Begin
DrawLine (Count, pLine, False);
Inc (pLine);
End;
Session.io.BufFlush;
End;
2013-09-18 15:57:31 -07:00
Procedure TMsgBaseAnsi.SetLineColor (NewAttr, Line: Word);
2012-02-13 16:50:48 -08:00
Var
Count : Word;
Begin
For Count := 1 to 80 Do
2013-09-18 15:57:31 -07:00
Data[Line][Count].Attr := NewAttr;
2012-02-13 16:50:48 -08:00
End;
Procedure TMsgBaseAnsi.RemoveLine (Line: Word);
Var
Count : Word;
Begin
For Count := Line to Lines - 1 Do
Data[Count] := Data[Count + 1];
Dec (Lines);
End;
2013-03-07 07:39:10 -08:00
End.