UPD: Terminal - better buffer overflow checking ADD: Terminal - erase screen left sequence

This commit is contained in:
Alexander Koblov 2022-01-24 18:52:22 +03:00
commit e51f4fa0df
2 changed files with 72 additions and 39 deletions

View file

@ -83,7 +83,8 @@ type
procedure ClearAllTabs;
procedure ScrollDown;
procedure ScrollUp;
procedure EraseScreen(Column, Row: Integer);
procedure EraseScreenLeft(Column, Row: Integer);
procedure EraseScreenRight(Column, Row: Integer);
procedure EraseLineLeft(Column, Row: Integer);
procedure EraseLineRight(Column, Row: Integer);
procedure EraseChar(Column, Row, Count: Integer);
@ -368,16 +369,15 @@ begin
end;
// put char in buffer
procedure TComTermBuffer.SetChar(Column, Row: Integer;
TermChar: TComTermChar);
procedure TComTermBuffer.SetChar(Column, Row: Integer; TermChar: TComTermChar);
var
Address: Integer;
begin
Address := (Row - 1) * FColumns + Column - 1;
Move(
TermChar,
(FBuffer + (SizeOf(TComTermChar) * Address))^,
SizeOf(TComTermChar));
if (Row > FRows) or (Column > FColumns) then
Exit;
Address := (Row - 1) * FColumns + (Column - 1);
PComTermChar(FBuffer + (Address * SizeOf(TComTermChar)))^:= TermChar;
end;
// get char from buffer
@ -385,11 +385,11 @@ function TComTermBuffer.GetChar(Column, Row: Integer): TComTermChar;
var
Address: Integer;
begin
Address := (Row - 1) * FColumns + Column - 1;
Move(
(FBuffer + (SizeOf(TComTermChar) * Address))^,
Result,
SizeOf(TComTermChar));
if (Row > FRows) or (Column > FColumns) then
Exit(Default(TComTermChar));
Address := (Row - 1) * FColumns + (Column - 1);
Result:= PComTermChar(FBuffer + (Address * SizeOf(TComTermChar)))^;
end;
// scroll down up line
@ -407,13 +407,13 @@ end;
procedure TComTermBuffer.EraseLineLeft(Column, Row: Integer);
var
Index: Integer;
Count: Integer;
B: PComTermChar;
begin
if (Row > FRows) or (Column > FColumns) then Exit;
// in memory
Count:= (Column + 1);
B:= PComTermChar(FBuffer) + ((Row - 1) * FColumns - 1);
for Index:= 0 to Count - 1 do
for Index:= 0 to Column - 1 do
begin
B[Index].Ch:= #32;
B[Index].BackColor:= FOwner.FTermAttr.BackColor;
@ -434,9 +434,11 @@ var
Count: Integer;
B: PComTermChar;
begin
if (Row > FRows) or (Column > FColumns) then Exit;
// in memory
Count:= (FColumns - Column + 1);
B:= PComTermChar(FBuffer) + ((Row - 1) * FColumns + Column - 1);
B:= PComTermChar(FBuffer) + ((Row - 1) * FColumns + (Column - 1));
for Index:= 0 to Count - 1 do
begin
B[Index].Ch:= #32;
@ -456,11 +458,11 @@ var
Index: Integer;
B: PComTermChar;
begin
if (Column + Count > FColumns) then
Count:= FColumns - Column;
if (Row > FRows) or (Column > FColumns) then Exit;
if (Column + Count > FColumns) then Count:= FColumns - Column;
// in memory
B:= PComTermChar(FBuffer) + ((Row - 1) * FColumns + Column - 1);
B:= PComTermChar(FBuffer) + ((Row - 1) * FColumns + (Column - 1));
for Index:= 0 to Count - 1 do
begin
B[Index].Ch:= #32;
@ -481,12 +483,12 @@ var
DstAddr: PComTermChar;
SrcAddr: PComTermChar;
begin
if (Column + Count > FColumns) then
Count:= FColumns - Column;
if (Row > FRows) or (Column > FColumns) then Exit;
if (Column + Count > FColumns) then Count:= FColumns - Column;
// in memory
DstAddr:= PComTermChar(FBuffer) + ((Row - 1) * FColumns + Column - 1);
SrcAddr:= PComTermChar(FBuffer) + ((Row - 1) * FColumns + Column + Count - 1);
DstAddr:= PComTermChar(FBuffer) + ((Row - 1) * FColumns + (Column - 1));
SrcAddr:= PComTermChar(FBuffer) + ((Row - 1) * FColumns + (Column - 1) + Count);
// Move characters
Count:= (FColumns - (Column + Count));
@ -588,15 +590,43 @@ begin
end;
// erase screen
procedure TComTermBuffer.EraseScreen(Column, Row: Integer);
procedure TComTermBuffer.EraseScreenLeft(Column, Row: Integer);
var
Index: Integer;
Count: Integer;
B: PComTermChar;
begin
if (Row > FRows) or (Column > FColumns) then Exit;
// in memory
B:= PComTermChar(FBuffer) + ((Row - 1) * FColumns + Column - 1);
Count:= (FColumns - Column + 1 + (FRows - Row) * FColumns);
B:= PComTermChar(FBuffer);
Count:= (Row * FColumns + Column);
for Index:= 0 to Count - 1 do
begin
B[Index].Ch:= #32;
B[Index].BackColor:= FOwner.FTermAttr.BackColor;
B[Index].FrontColor:= FOwner.FTermAttr.FrontColor;
end;
// on screen
if FOwner.DoubleBuffered then
FOwner.Invalidate
else
FOwner.InvalidatePortion(Classes.Rect(Column, Row, FColumns, FRows))
end;
// erase screen
procedure TComTermBuffer.EraseScreenRight(Column, Row: Integer);
var
Index: Integer;
Count: Integer;
B: PComTermChar;
begin
if (Row > FRows) or (Column > FColumns) then Exit;
// in memory
B:= PComTermChar(FBuffer) + ((Row - 1) * FColumns + (Column - 1));
Count:= ((FRows - Row) * FColumns + (FColumns - Column) + 1);
for Index:= 0 to Count - 1 do
begin
B[Index].Ch:= #32;
@ -1723,17 +1753,19 @@ begin
ecReverseLineFeed: AdvanceCaret(acReverseLineFeed);
ecEraseLineLeft: FBuffer.EraseLineLeft(FCaretPos.X, FCaretPos.Y);
ecEraseLineRight: FBuffer.EraseLineRight(FCaretPos.X, FCaretPos.Y);
ecEraseScreenFrom: FBuffer.EraseScreen(FCaretPos.X, FCaretPos.Y);
ecEraseScreen: begin FBuffer.EraseScreen(1, 1); MoveCaret(1, 1) end;
ecEraseLine:
begin
FBuffer.EraseLineRight(1, FCaretPos.Y);
MoveCaret(1, FCaretPos.Y)
end;
ecEraseChar:
begin
FBuffer.EraseChar(FCaretPos.X, FCaretPos.Y, GetParam(1, AParams));
end;
ecEraseScreenLeft: FBuffer.EraseScreenLeft(FCaretPos.X, FCaretPos.Y);
ecEraseScreenRight: FBuffer.EraseScreenRight(FCaretPos.X, FCaretPos.Y);
ecEraseScreen:
begin
FBuffer.EraseScreenRight(1, 1);
MoveCaret(1, 1)
end;
ecEraseChar: FBuffer.EraseChar(FCaretPos.X, FCaretPos.Y, GetParam(1, AParams));
ecDeleteChar: FBuffer.DeleteChar(FCaretPos.X, FCaretPos.Y, GetParam(1, AParams));
ecIdentify:
begin

View file

@ -33,7 +33,7 @@ type
ecReverseLineFeed, ecAppCursorLeft, ecAppCursorRight, ecAppCursorUp, ecAppCursorDown,
ecAppCursorHome, ecAppCursorEnd, ecCursorNextLine, ecCursorPrevLine, ecInsertKey,
ecDeleteKey, ecPageUpKey, ecPageDownKey,
ecMouseDown, ecMouseUp, ecEraseLineLeft, ecEraseLineRight, ecEraseScreenFrom,
ecMouseDown, ecMouseUp, ecEraseLineLeft, ecEraseLineRight, ecEraseScreenRight, ecEraseScreenLeft,
ecEraseLine, ecEraseScreen, ecEraseChar, ecDeleteChar, ecSetTab, ecClearTab, ecClearAllTabs,
ecIdentify, ecIdentResponse, ecQueryDevice, ecReportDeviceOK,
ecReportDeviceFailure, ecQueryCursorPos, ecReportCursorPos,
@ -162,7 +162,7 @@ begin
ecCursorLeft: Result := #27'D';
ecCursorHome: Result := #27'H';
ecReverseLineFeed: Result := #27'I';
ecEraseScreenFrom: Result := #27'J';
ecEraseScreenRight: Result := #27'J';
ecEraseLineRight: Result := #27'K';
ecIdentify: Result := #27'Z';
ecIdentResponse: Result := #27'/Z';
@ -184,7 +184,7 @@ begin
'D': Result := ecCursorLeft;
'H': Result := ecCursorMove;
'I': Result := ecReverseLineFeed;
'J': Result := ecEraseScreenFrom;
'J': Result := ecEraseScreenRight;
'K': Result := ecEraseLineRight;
'Z': Result := ecIdentify;
'/': begin
@ -282,7 +282,7 @@ begin
ecCursorHome: Result := #27'[H';
ecCursorEnd: Result := #27'[F';
ecCursorMove: Result := Format(#27'[%d;%df', [GetParam(1, AParams), GetParam(2, AParams)]);
ecEraseScreenFrom: Result := #27'[J';
ecEraseScreenRight: Result := #27'[J';
ecEraseLineRight: Result := #27'[K';
ecEraseScreen: Result := #27'[2J';
ecEraseLine: Result := #27'[2K';
@ -405,12 +405,13 @@ var
Str: string;
begin
if TempParams.Count = 0 then
Result := ecEraseScreenFrom
Result := ecEraseScreenRight
else
begin
Str := TempParams[0];
case Str[1] of
'0': Result := ecEraseScreenFrom;
'0': Result := ecEraseScreenRight;
'1': Result := ecEraseScreenLeft;
'2': Result := ecEraseScreen;
else
Result := ecUnknown;