mysticbbs/mdl/m_output_windows.pas

881 lines
22 KiB
ObjectPascal

// ====================================================================
// 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/>.
//
// ====================================================================
Unit m_Output_Windows;
{$I M_OPS.PAS}
Interface
Uses
Windows,
m_Types;
Type
TOutputWindows = Class
Private
ConOut : THandle;
Cursor : TCoord;
Public
ScreenSize : Byte;
Active : Boolean;
TextAttr : Byte;
Buffer : TConsoleScreenRec;
LineBuf : TConsoleLineRec;
Window : TSmallRect;
Constructor Create (A: Boolean);
Destructor Destroy; Override;
Procedure ClearScreen; Virtual;
Procedure ClearScreenNoUpdate;
Procedure ScrollWindow; Virtual;
Procedure ClearEOL;
Procedure CursorXY (X, Y: Byte);
Function CursorX : Byte;
Function CursorY : Byte;
Procedure SetScreenSize (Mode: Byte);
Procedure SetWindowTitle (Title: String);
Procedure SetWindow (X1, Y1, X2, Y2: Byte; Home: Boolean);
Procedure GetScreenImage (X1, Y1, X2, Y2: Byte; Var Image: TConsoleImageRec);
Procedure PutScreenImage (Var Image: TConsoleImageRec);
Procedure LoadScreenImage (Var DataPtr; Len, Width, X, Y: Integer);
Procedure WriteXY (X, Y, A: Byte; Text: String);
Procedure WriteXYNoUpdate (X, Y, A: Byte; Text: String);
Procedure WriteXYPipe (X, Y, Attr, Pad: Integer; Text: String);
Procedure WriteLineRec (YPos: Integer; Line: TConsoleLineRec);
Function ReadCharXY (X, Y: Byte) : Char;
Function ReadAttrXY (X, Y: Byte) : Byte;
Procedure WriteChar (Ch: Char);
Procedure WriteLine (Str: String);
Procedure WriteStr (Str: String);
Procedure ShowBuffer;
Procedure BufFlush; // Linux compatibility only
// Property ScreenSize : Byte Read FScreenSize;
// Property TextAttr : Byte Read FTextAttr Write FTextAttr;
End;
Implementation
Uses
m_Strings;
Procedure TOutputWindows.WriteLineRec (YPos: Integer; Line: TConsoleLineRec);
Var
BufSize : TCoord;
BufCoord : TCoord;
Region : TSmallRect;
Begin
BufSize.X := 80;
BufSize.Y := 1;
BufCoord.X := 0;
BufCoord.Y := 0;
Region.Left := 0;
Region.Top := YPos - 1;
Region.Right := 79;
Region.Bottom := YPos - 1;
WriteConsoleOutput(ConOut, @Line, BufSize, BufCoord, Region);
Buffer[YPos] := Line;
End;
Procedure TOutputWindows.SetWindow (X1, Y1, X2, Y2 : Byte; Home: Boolean);
Begin
If (X1 > X2) or (X2 > 80) or
(Y1 > Y2) or (Y2 > ScreenSize) Then Exit;
Window.Left := X1 - 1;
Window.Top := Y1 - 1;
Window.Right := X2 - 1;
Window.Bottom := Y2 - 1;
If Home Then CursorXY (X1, Y1) Else CursorXY (Cursor.X + 1, Cursor.Y + 1);
End;
Constructor TOutputWindows.Create (A: Boolean);
Var
ScreenMode : TConsoleScreenBufferInfo;
CursorInfo : TConsoleCursorInfo;
Begin
Inherited Create;
Active := A;
ConOut := GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(ConOut, ScreenMode);
Case ScreenMode.dwSize.Y of
25 : ScreenSize := 25;
50 : ScreenSize := 50;
Else
SetScreenSize(25);
ScreenSize := 25;
End;
CursorInfo.bVisible := True;
CursorInfo.dwSize := 15;
SetConsoleCursorInfo(ConOut, CursorInfo);
Window.Top := 0;
Window.Left := 0;
Window.Right := 79;
Window.Bottom := ScreenSize - 1;
TextAttr := 7;
ClearScreen;
End;
Destructor TOutputWindows.Destroy;
Begin
Inherited Destroy;
End;
Procedure TOutputWindows.SetScreenSize (Mode: Byte);
Var
Size : TCoord;
Begin
If (Mode = ScreenSize) Or Not (Mode in [25, 50]) Then Exit;
Size.X := 80;
Size.Y := Mode;
Window.Top := 0;
Window.Left := 0;
Window.Right := Size.X - 1;
Window.Bottom := Size.Y - 1;
SetConsoleScreenBufferSize (ConOut, Size);
SetConsoleWindowInfo (ConOut, True, Window);
SetConsoleScreenBufferSize (ConOut, Size);
ScreenSize := Mode;
End;
Procedure TOutputWindows.CursorXY (X, Y: Byte);
Begin
// don't move to x/y coordinate outside of window
Cursor.X := X - 1;
Cursor.Y := Y - 1;
If Cursor.X < Window.Left Then Cursor.X := Window.Left Else
If Cursor.X > Window.Right Then Cursor.X := Window.Right;
If Cursor.Y < Window.Top Then Cursor.Y := Window.Top Else
If Cursor.Y > Window.Bottom Then Cursor.Y := Window.Bottom;
If Active Then
SetConsoleCursorPosition(ConOut, Cursor);
End;
Procedure TOutputWindows.ClearEOL;
Var
Count : Byte;
BufSize : TCoord;
BufCoord : TCoord;
Region : TSmallRect;
Begin
Count := Window.Right - Cursor.X + 1;
FillDWord (Buffer[Cursor.Y + 1][Cursor.X + 1], Count, (Word(TextAttr) SHL 16) OR Word($0020));
If Active Then Begin
BufSize.X := Count - 1;
BufSize.Y := 1;
BufCoord.X := 0;
BufCoord.Y := 0;
Region.Left := Cursor.X;
Region.Top := Cursor.Y;
Region.Right := Cursor.X + Count - 1;
Region.Bottom := Cursor.Y;
WriteConsoleOutput(ConOut, @Buffer[Cursor.Y + 1][Cursor.X + 1], BufSize, BufCoord, Region);
End;
End;
(*
Procedure TOutputWindows.ClearEOL;
Var
Count : Byte;
Res : LongInt;
Begin
Count := Window.Right - Cursor.X + 1;
FillDWord (Buffer[Cursor.Y + 1][Cursor.X + 1], Count, (Word(TextAttr) SHL 16) OR Word($0020));
If Active Then Begin
FillConsoleOutputCharacter (ConOut, ' ', Count, Cursor, @Res);
FillConsoleOutputAttribute (ConOut, TextAttr, Count, Cursor, @Res);
End;
End;
*)
Procedure TOutputWindows.ClearScreenNoUpdate;
Var
Res : ULong;
Count : Byte;
Size : Byte;
Cell : TCharInfo;
Begin
Size := Window.Right - Window.Left + 1;
Cursor.X := Window.Left;
Cell.Attributes := TextAttr;
Cell.UnicodeChar := ' ';
For Count := Window.Top To Window.Bottom Do Begin
Cursor.Y := Count;
FillConsoleOutputAttribute(ConOut, Cell.Attributes, Size, Cursor, Res);
FillConsoleOutputCharacter(ConOut, ' ', Size, Cursor, Res);
End;
End;
Procedure TOutputWindows.ClearScreen;
Var
Res : ULong;
Count : Byte;
Size : Byte;
Cell : TCharInfo;
Begin
Size := Window.Right - Window.Left + 1;
Cursor.X := Window.Left;
Cell.Attributes := TextAttr;
Cell.UnicodeChar := ' ';
If Active Then Begin
For Count := Window.Top To Window.Bottom Do Begin
Cursor.Y := Count;
FillConsoleOutputAttribute(ConOut, Cell.Attributes, Size, Cursor, Res);
FillConsoleOutputCharacter(ConOut, ' ', Size, Cursor, Res);
End;
End;
FillChar (Buffer, SizeOf(Buffer), 0);
CursorXY (Window.Left + 1, Window.Top + 1);
End;
Procedure TOutputWindows.SetWindowTitle (Title: String);
Begin
Title := Title + #0;
SetConsoleTitle(@Title[1]);
End;
Procedure TOutputWindows.WriteXY (X, Y, A: Byte; Text: String);
Var
Buf : Array[1..80] of TCharInfo;
BufSize : TCoord;
BufCoord : TCoord;
Region : TSmallRect;
Count : Byte;
Begin
Count := 1;
While Count <= Length(Text) Do Begin
Buf[Count].Attributes := A;
Buf[Count].UnicodeChar := Text[Count];
Inc (Count);
End;
Move (Buf[1], Buffer[Y][X], (Count - 1) * SizeOf(TCharInfo));
If Active Then Begin
BufSize.X := Count - 1;
BufSize.Y := 1;
BufCoord.X := 0;
BufCoord.Y := 0;
Region.Left := X - 1;
Region.Top := Y - 1;
Region.Right := X + Count - 1;
Region.Bottom := Y - 1;
If Region.Right > 79 Then Region.Right := 79;
WriteConsoleOutput(ConOut, @Buf, BufSize, BufCoord, Region);
End;
End;
Procedure TOutputWindows.WriteXYNoUpdate (X, Y, A: Byte; Text: String);
Var
Buf : Array[1..80] of TCharInfo;
BufSize : TCoord;
BufCoord : TCoord;
Region : TSmallRect;
Count : Byte;
Begin
Count := 1;
While Count <= Length(Text) Do Begin
Buf[Count].Attributes := A;
Buf[Count].UnicodeChar := Text[Count];
Inc (Count);
End;
BufSize.X := Count - 1;
BufSize.Y := 1;
BufCoord.X := 0;
BufCoord.Y := 0;
Region.Left := X - 1;
Region.Top := Y - 1;
Region.Right := X + Count - 1;
Region.Bottom := Y - 1;
If Region.Right > 79 Then Region.Right := 79;
WriteConsoleOutput(ConOut, @Buf, BufSize, BufCoord, Region);
End;
Procedure TOutputWindows.WriteXYPipe (X, Y, Attr, Pad: Integer; Text: String);
Var
Buf : Array[1..80] of TCharInfo;
BufPos : Byte;
Count : Byte;
Code : String[2];
CodeNum : Byte;
BufSize : TCoord;
BufCoord : TCoord;
Region : TSmallRect;
Procedure AddChar;
Begin
Inc (BufPos);
Buf[BufPos].Attributes := Attr;
Buf[BufPos].UnicodeChar := Text[Count];
End;
Begin
FillChar(Buf, SizeOf(Buf), #0);
Count := 1;
BufPos := 0;
While Count <= Length(Text) Do Begin
If Text[Count] = '|' Then Begin
Code := Copy(Text, Count + 1, 2);
CodeNum := strS2I(Code);
If (Code = '00') or ((CodeNum > 0) and (CodeNum < 24) and (Code[1] <> '$') and (Code[1] <> '&')) Then Begin
Inc (Count, 2);
If CodeNum in [00..15] Then
Attr := CodeNum + ((Attr SHR 4) AND 7) * 16
Else
Attr := (Attr AND $F) + (CodeNum - 16) * 16;
End Else
AddChar;
End Else
AddChar;
If BufPos = Pad Then Break;
Inc (Count);
End;
Text[1] := #32;
Count := 1;
While BufPos < Pad Do AddChar;
BufSize.X := Pad;
BufSize.Y := 1;
BufCoord.X := 0;
BufCoord.Y := 0;
Region.Left := X - 1;
Region.Top := Y - 1;
Region.Right := X + Pad;
Region.Bottom := Y - 1;
If Region.Right > 79 Then Region.Right := 79;
Move (Buf[1], Buffer[Y][X], BufSize.X * SizeOf(TCharInfo));
If Active Then
WriteConsoleOutput(ConOut, @Buf, BufSize, BufCoord, Region);
End;
Function TOutputWindows.CursorX : Byte;
Begin
CursorX := Cursor.X + 1;
End;
Function TOutputWindows.CursorY : Byte;
Begin
CursorY := Cursor.Y + 1;
End;
Procedure TOutputWindows.WriteChar (Ch: Char);
Var
BufferSize,
BufferCoord : TCoord;
WriteRegion : TSmallRect;
OneCell : TCharInfo;
// Res : LongInt;
Begin
Case Ch of
#08 : If Cursor.X > Window.Left Then Begin
Dec(Cursor.X);
If Active Then SetConsoleCursorPosition(ConOut, Cursor);
End;
#10 : Begin
If Cursor.Y = Window.Bottom Then
ScrollWindow
Else Begin
Inc (Cursor.Y);
Cursor.X := Window.Left;
End;
If Active Then SetConsoleCursorPosition(ConOut, Cursor);
End;
#13 : Cursor.X := Window.Left;
Else
If Active Then Begin
OneCell.UnicodeChar := Ch;
OneCell.Attributes := TextAttr;
BufferSize.X := 1;
BufferSize.Y := 1;
BufferCoord.X := 0;
BufferCoord.Y := 0;
WriteRegion.Left := Cursor.X;
WriteRegion.Top := Cursor.Y;
WriteRegion.Right := Cursor.X;
WriteRegion.Bottom := Cursor.Y;
// FillConsoleOutputCharacter (ConOut, Ch, 1, Cursor, @Res);
// FillConsoleOutputAttribute (ConOut, TextAttr, 1, Cursor, @Res);
WriteConsoleOutput (ConOut, @OneCell, BufferSize, BufferCoord, WriteRegion);
End;
Buffer[Cursor.Y + 1][Cursor.X + 1].UnicodeChar := Ch;
Buffer[Cursor.Y + 1][Cursor.X + 1].Attributes := TextAttr;
If Cursor.X < Window.Right Then
Inc (Cursor.X)
Else Begin
If (Cursor.X = Window.Right) And (Cursor.Y = Window.Bottom - 1) Then Begin
Inc (Cursor.X);
Exit;
End;
Cursor.X := Window.Left;
If Cursor.Y = Window.Bottom Then
ScrollWindow
Else
Inc (Cursor.Y);
End;
If Active Then SetConsoleCursorPosition(ConOut, Cursor);
End;
End;
(*
Procedure TOutputWindows.WriteChar (Ch: Char);
Var
BufferSize,
BufferCoord : TCoord;
WriteRegion : TSmallRect;
OneCell : TCharInfo;
Begin
Case Ch of
#08 : If Cursor.X > Window.Left Then Begin
Dec(Cursor.X);
If Active Then SetConsoleCursorPosition(ConOut, Cursor);
End;
#10 : Begin
If Cursor.Y = Window.Bottom Then
ScrollWindow
Else Begin
Inc (Cursor.Y);
Cursor.X := Window.Left;
End;
If Active Then SetConsoleCursorPosition(ConOut, Cursor);
End;
#13 : Cursor.X := Window.Left;
Else
If Active Then Begin
OneCell.UnicodeChar := Ch;
OneCell.Attributes := TextAttr;
BufferSize.X := 1;
BufferSize.Y := 1;
BufferCoord.X := 0;
BufferCoord.Y := 0;
WriteRegion.Left := Cursor.X;
WriteRegion.Top := Cursor.Y;
WriteRegion.Right := Cursor.X;
WriteRegion.Bottom := Cursor.Y;
WriteConsoleOutput (ConOut, @OneCell, BufferSize, BufferCoord, WriteRegion);
End;
Buffer[Cursor.Y + 1][Cursor.X + 1].UnicodeChar := Ch;
Buffer[Cursor.Y + 1][Cursor.X + 1].Attributes := TextAttr;
If Cursor.X < Window.Right Then
Inc (Cursor.X)
Else Begin
If (Cursor.X = Window.Right) And (Cursor.Y = Window.Bottom - 1) Then Begin
Inc (Cursor.X);
Exit;
End;
Cursor.X := Window.Left;
If Cursor.Y = Window.Bottom Then
ScrollWindow
Else
Inc (Cursor.Y);
End;
If Active Then SetConsoleCursorPosition(ConOut, Cursor);
End;
End;
*)
Procedure TOutputWindows.WriteLine (Str: String);
Var
Count : Byte;
Begin
Str := Str + #13#10;
For Count := 1 to Length(Str) Do WriteChar(Str[Count]);
End;
Procedure TOutputWindows.WriteStr (Str: String);
Var
Count : Byte;
Begin
For Count := 1 to Length(Str) Do WriteChar(Str[Count]);
End;
Procedure TOutputWindows.ScrollWindow;
Var
DestCoord : TCoord;
Fill : TCharInfo;
Begin
Fill.UnicodeChar := ' ';
Fill.Attributes := 7;
DestCoord.X := Window.Left;
DestCoord.Y := Window.Top - 1;
If Active Then
ScrollConsoleScreenBuffer(ConOut, Window, Window, DestCoord, Fill);
Move (Buffer[2][1], Buffer[1][1], SizeOf(TConsoleLineRec) * 49);
FillChar (Buffer[Window.Bottom + 1][1], SizeOf(TConsoleLineRec), #0);
End;
Procedure TOutputWindows.GetScreenImage (X1, Y1, X2, Y2: Byte; Var Image: TConsoleImageRec);
Var
CountY : Byte;
CountX : Byte;
BufPos : Integer;
NewBuf : Array[1..SizeOf(TConsoleScreenRec) DIV 2] of Word Absolute Image.Data;
Begin
Image.X1 := X1;
Image.X2 := X2;
Image.Y1 := Y1;
Image.Y2 := Y2;
Image.CursorX := CursorX;
Image.CursorY := CursorY;
Image.CursorA := TextAttr;
BufPos := 1;
For CountY := Y1 to Y2 Do Begin
For CountX := X1 to X2 Do Begin
NewBuf[BufPos] := Word(Buffer[CountY][CountX].UnicodeChar);
NewBuf[BufPos+1] := Buffer[CountY][CountX].Attributes;
Inc (BufPos, 2);
End;
End;
End;
(*
Procedure TOutputWindows.GetScreenImage (X1, Y1, X2, Y2: Byte; Var Image: TConsoleImageRec);
Var
BufSize : TCoord;
BufCoord : TCoord;
Region : TSmallRect;
// x,y,cx,cy:byte;
Begin
BufSize.X := X2 - X1 + 1;
BufSize.Y := Y2 - Y1 + 1;
BufCoord.X := 0;
BufCoord.Y := 0;
Region.Left := X1 - 1;
Region.Top := Y1 - 1;
Region.Right := X2 - 1;
Region.Bottom := Y2 - 1;
Image.X1 := X1;
Image.X2 := X2;
Image.Y1 := Y1;
Image.Y2 := Y2;
Image.CursorX := CursorX;
Image.CursorY := CursorY;
Image.CursorA := TextAttr;
If Active Then
ReadConsoleOutput (ConOut, @Image.Data[1][1], BufSize, BufCoord, Region)
Else
Image.Data := Buffer;
End;
*)
Procedure TOutputWindows.ShowBuffer;
Var
BufSize : TCoord;
BufCoord : TCoord;
Region : TSmallRect;
Begin
BufSize.X := 80;
BufSize.Y := ScreenSize;
BufCoord.X := 0;
BufCoord.Y := 0;
Region.Left := 0;
Region.Top := 0;
Region.Right := 79;
Region.Bottom := ScreenSize - 1;
WriteConsoleOutput (ConOut, @Buffer[1][1], BufSize, BufCoord, Region);
CursorXY (Cursor.X + 1, Cursor.Y + 1);
End;
Procedure TOutputWindows.PutScreenImage (Var Image: TConsoleImageRec);
Var
BufSize : TCoord;
BufCoord : TCoord;
Region : TSmallRect;
CountX : Byte;
CountY : Byte;
BufPos : Integer;
TempBuf : Array[1..SizeOf(TConsoleScreenRec) DIV 2] of LongInt Absolute Image.Data;
Begin
BufSize.X := Image.X2 - Image.X1 + 1;
BufSize.Y := Image.Y2 - Image.Y1 + 1;
BufCoord.X := 0;
BufCoord.Y := 0;
Region.Left := Image.X1 - 1;
Region.Top := Image.Y1 - 1;
Region.Right := Image.X2 - 1;
Region.Bottom := Image.Y2 - 1;
WriteConsoleOutput (ConOut, @Image.Data[1][1], BufSize, BufCoord, Region);
BufPos := 1;
For CountY := Image.Y1 to Image.Y2 Do
For CountX := Image.X1 to Image.X2 Do Begin
Buffer[CountY][CountX] := TCharInfo(TempBuf[BufPos]);
Inc(BufPos);
End;
CursorXY (Image.CursorX, Image.CursorY);
TextAttr := Image.CursorA;
End;
Procedure TOutputWindows.LoadScreenImage (Var DataPtr; Len, Width, X, Y: Integer);
Var
Image : TConsoleImageRec;
Data : Array[1..8000] of Byte Absolute DataPtr;
PosX : Word;
PosY : Byte;
Attrib : Byte;
Count : Word;
A : Byte;
B : Byte;
C : Byte;
Begin
PosX := 1;
PosY := 1;
Attrib := 7;
Count := 1;
FillChar(Image.Data, SizeOf(Image.Data), #0);
While (Count <= Len) Do Begin
Case Data[Count] of
00..
15 : Attrib := Data[Count] + ((Attrib SHR 4) and 7) * 16;
16..
23 : Attrib := (Attrib And $F) + (Data[Count] - 16) * 16;
24 : Begin
Inc (PosY);
PosX := 1;
End;
25 : Begin
Inc (Count);
For A := 0 to Data[Count] Do Begin
Image.Data[PosY][PosX].UnicodeChar := ' ';
Image.Data[PosY][PosX].Attributes := Attrib;
Inc (PosX);
End;
End;
26 : Begin
A := Data[Count + 1];
B := Data[Count + 2];
Inc (Count, 2);
For C := 0 to A Do Begin
Image.Data[PosY][PosX].UnicodeChar := Char(B);
Image.data[PosY][PosX].Attributes := Attrib;
Inc (PosX);
End;
End;
27..
31 : ;
Else
Image.Data[PosY][PosX].UnicodeChar := Char(Data[Count]);
Image.Data[PosY][PosX].Attributes := Attrib;
Inc (PosX);
End;
Inc (Count);
End;
Image.X1 := X;
Image.X2 := Width;
Image.Y1 := Y;
Image.Y2 := PosY;
Image.CursorX := PosX;
Image.CursorY := PosY;
Image.CursorA := Attrib;
PutScreenImage(Image);
End;
(*
Procedure TOutputWindows.LoadScreenImage (Var DataPtr; Len, Width, X, Y: Integer);
Var
Screen : TConsoleScreenRec;
Data : Array[1..8000] of Byte Absolute DataPtr;
PosX : Word;
PosY : Byte;
Attrib : Byte;
Count : Word;
A : Byte;
B : Byte;
C : Byte;
BufSize : TCoord;
BufCoord : TCoord;
Region : TSmallRect;
Begin
PosX := 1;
PosY := 1;
Attrib := 7;
Count := 1;
FillChar(Screen, SizeOf(Screen), #0);
While (Count <= Len) Do Begin
Case Data[Count] of
00..
15 : Attrib := Data[Count] + ((Attrib SHR 4) and 7) * 16;
16..
23 : Attrib := (Attrib And $F) + (Data[Count] - 16) * 16;
24 : Begin
Inc (PosY);
PosX := 1;
End;
25 : Begin
Inc (Count);
For A := 0 to Data[Count] Do Begin
Screen[PosY][PosX].UnicodeChar := ' ';
Screen[PosY][PosX].Attributes := Attrib;
Inc (PosX);
End;
End;
26 : Begin
A := Data[Count + 1];
B := Data[Count + 2];
Inc (Count, 2);
For C := 0 to A Do Begin
Screen[PosY][PosX].UnicodeChar := Char(B);
Screen[PosY][PosX].Attributes := Attrib;
Inc (PosX);
End;
End;
27..
31 : ;
Else
Screen[PosY][PosX].UnicodeChar := Char(Data[Count]);
Screen[PosY][PosX].Attributes := Attrib;
Inc (PosX);
End;
Inc (Count);
End;
BufSize.Y := PosY - (Y - 1);
BufSize.X := Width;
BufCoord.X := 0;
BufCoord.Y := 0;
Region.Left := X - 1;
Region.Top := Y - 1;
Region.Right := Width - 1;
Region.Bottom := PosY - 1;
WriteConsoleOutput (ConOut, @Screen[1][1], BufSize, BufCoord, Region);
CursorXY(PosX, PosY);
End;
*)
Function TOutputWindows.ReadCharXY (X, Y: Byte) : Char;
Begin
Result := Buffer[Y][X].UnicodeChar;
End;
Function TOutputWindows.ReadAttrXY (X, Y: Byte) : Byte;
Begin
Result := Buffer[Y][X].Attributes;
End;
Procedure TOutputWindows.BufFlush;
Begin
End;
End.