mysticbbs/mdl/m_term_ansi.pas

321 lines
7.0 KiB
ObjectPascal
Raw Normal View History

2012-02-13 15:45:09 -08:00
{$I M_OPS.PAS}
Unit m_Term_Ansi;
Interface
Uses
m_Output,
2012-08-11 11:58:12 -07:00
m_io_Base,
2012-02-13 15:45:09 -08:00
m_Strings;
Type
TTermAnsi = Class
Screen : TOutput;
WasValid : Boolean;
Private
2012-08-11 11:58:12 -07:00
Client : TIOBase;
2012-02-13 15:45:09 -08:00
State : Byte;
SavedX : Byte;
SavedY : Byte;
Options : String;
Procedure CheckCode (Ch: Char);
Function ParseNumber : Integer;
Procedure ResetState;
Procedure CursorUp;
Procedure CursorMove;
Procedure CursorDown;
Procedure CursorRight;
Procedure CursorLeft;
Public
Constructor Create (Var Con: TOutput);
Destructor Destroy; Override;
Procedure Process (Ch: Char);
Procedure ProcessBuf (Var Buf; BufLen : Word);
2012-08-11 11:58:12 -07:00
Procedure SetReplyClient (Var Cli: TIOBase);
2012-02-13 15:45:09 -08:00
End;
Implementation
Const
ColorTable : Array[30..47] of Byte = (0, 4, 2, 6, 1, 5, 3, 7, 0, 0, 0, 64, 32, 96, 16, 80, 48, 112);
Constructor TTermAnsi.Create (Var Con: TOutput);
Begin
Inherited Create;
Screen := Con;
Client := NIL;
WasValid := False;
ResetState;
End;
Destructor TTermAnsi.Destroy;
Begin
Inherited Destroy;
End;
2012-08-11 11:58:12 -07:00
Procedure TTermAnsi.SetReplyClient (Var Cli: TIOBase);
2012-02-13 15:45:09 -08:00
Begin
Client := Cli;
End;
Function TTermAnsi.ParseNumber : Integer;
Var
Res : LongInt;
Str : String;
Begin
Val (Options, Result, Res);
If Res = 0 Then
Options := ''
Else Begin
Str := Copy(Options, 1, Pred(Res));
Delete (Options, 1, Res);
Val (Str, Result, Res);
End;
End;
Procedure TTermAnsi.ResetState;
Begin
State := 0;
Options := '';
End;
Procedure TTermAnsi.CursorMove;
Var
X : Byte;
Y : Byte;
Begin
Y := ParseNumber;
2012-09-20 10:54:12 -07:00
2012-02-13 15:45:09 -08:00
If Y = 0 Then Y := 1;
2012-09-20 10:54:12 -07:00
2012-02-13 15:45:09 -08:00
X := ParseNumber;
2012-09-20 10:54:12 -07:00
2012-02-13 15:45:09 -08:00
If X = 0 Then X := 1;
2012-09-20 10:54:12 -07:00
2012-02-13 15:45:09 -08:00
Screen.CursorXY (X, Y);
2012-09-20 10:54:12 -07:00
2012-02-13 15:45:09 -08:00
ResetState;
End;
Procedure TTermAnsi.CursorUp;
Var
Y : Integer;
NewY : Integer;
Offset : Integer;
Begin
Offset := ParseNumber;
If Offset = 0 Then Offset := 1;
Y := Screen.CursorY;
If (Y - Offset) < 1 Then
NewY := 1
Else
NewY := Y - Offset;
Screen.CursorXY (Screen.CursorX, NewY);
ResetState;
End;
Procedure TTermAnsi.CursorDown;
Var
NewY : Byte;
Begin
NewY := ParseNumber;
If NewY = 0 Then NewY := 1;
NewY := NewY + Screen.CursorY;
Screen.CursorXY (Screen.CursorX, NewY);
ResetState;
End;
Procedure TTermAnsi.CursorRight;
Var
X : Integer;
Offset : Integer;
Begin
Offset := ParseNumber;
If Offset = 0 Then Offset := 1;
X := Screen.CursorX;
If (X + Offset) > 80 Then Begin
2013-02-27 01:41:10 -08:00
Screen.CursorXY (80, Screen.CursorY);
// Screen.WriteChar(#10); // force lf incase we have to scroll
// Screen.CursorXY(X + Offset - 80, Screen.CursorY);
2012-02-13 15:45:09 -08:00
End Else
Screen.CursorXY (x + offset, Screen.CursorY);
ResetState;
End;
Procedure TTermAnsi.CursorLeft;
Var
X : Integer;
NewX : Integer;
Offset : Integer;
Begin
Offset := ParseNumber;
If Offset = 0 Then offset := 1;
X := Screen.CursorX;
If (X - Offset) < 1 Then
NewX := 1
Else
NewX := X - Offset;
Screen.CursorXY (NewX, Screen.CursorY);
ResetState;
End;
Procedure TTermAnsi.CheckCode (Ch : Char);
Var
Temp : Byte;
Begin
Case Ch of
'h' : ResetState;
'0'..'9',
'?', ';' : Options := Options + Ch;
'H', 'f' : CursorMove;
'A' : CursorUp;
'B' : CursorDown;
'C' : CursorRight;
'D' : CursorLeft;
'J' : Begin
Screen.ClearScreen;
ResetState;
End;
'K' : Begin
Screen.ClearEOL;
ResetState;
End;
'm' : Begin
If Length(Options) = 0 Then Begin
Screen.TextAttr := 7;
2012-09-20 10:54:12 -07:00
2012-02-13 15:45:09 -08:00
ResetState;
End Else
While Length(Options) > 0 Do Begin
Temp := ParseNumber;
2012-09-20 10:54:12 -07:00
2012-02-13 15:45:09 -08:00
Case Temp of
0 : Screen.TextAttr := 7;
1 : Screen.TextAttr := Screen.TextAttr OR $08;
5 : Screen.TextAttr := Screen.TextAttr OR $80;
7 : Begin
Screen.TextAttr := Screen.TextAttr AND $F7;
Screen.TextAttr := (((Screen.TextAttr AND $70) SHR 4) + ((Screen.TextAttr AND $7) SHL 4) + Screen.TextAttr AND $80);
End;
30..
37: Screen.TextAttr := (Screen.TextAttr AND $F8 + ColorTable[Temp]);
40..
47: Screen.TextAttr := (Screen.TextAttr AND $F + ColorTable[Temp]);
End;
End;
2012-09-20 10:54:12 -07:00
2012-02-13 15:45:09 -08:00
ResetState;
End;
'n' : Begin
If Client <> NIL Then
Client.WriteStr(#27 + '[' + strI2S(Screen.CursorY) + ';' + strI2S(Screen.CursorX) + 'R');
2012-09-20 10:54:12 -07:00
2012-02-13 15:45:09 -08:00
ResetState;
End;
's' : Begin
SavedX := Screen.CursorX;
SavedY := Screen.CursorY;
2012-09-20 10:54:12 -07:00
2012-02-13 15:45:09 -08:00
ResetState;
End;
'u' : Begin
Screen.CursorXY (SavedX, SavedY);
2012-09-20 10:54:12 -07:00
2012-02-13 15:45:09 -08:00
ResetState;
End;
Else
ResetState;
End;
END;
Procedure TTermAnsi.Process (Ch : Char);
Begin
WasValid := False;
Case State of
0 : Begin
Case Ch of
#0 : ;
#27 : State := 1;
#9 : Screen.CursorXY (Screen.CursorX + 8, Screen.CursorY);
#12 : Screen.ClearScreen;
Else
Screen.WriteChar(Ch);
2012-09-20 10:54:12 -07:00
2012-02-13 15:45:09 -08:00
State := 0;
WasValid := True;
End;
End;
1 : If Ch = '[' Then Begin
State := 2;
Options := '';
End Else
State := 0;
2 : CheckCode(Ch);
Else
ResetState;
End;
End;
Procedure TTermAnsi.ProcessBuf (Var Buf; BufLen : Word);
Var
Count : Word;
Data : Array[1..16384] of Char Absolute Buf;
Begin
For Count := 1 to BufLen Do Begin
WasValid := False;
Case State of
0 : Begin
Case Data[Count] of
#0 : ;
#27 : State := 1;
#9 : Screen.CursorXY (Screen.CursorX + 8, Screen.CursorY);
#12 : Screen.ClearScreen;
Else
Screen.WriteChar(Data[Count]);
WasValid := True;
State := 0;
End;
End;
1 : If Data[Count] = '[' Then Begin
State := 2;
Options := '';
End Else
State := 0;
2 : CheckCode(Data[Count]);
Else
ResetState;
End;
End;
Screen.BufFlush;
End;
End.