dos_compilers/Borland Turbo Pascal v55/TCINPUT.PAS
2024-07-02 06:49:04 -07:00

334 lines
9.6 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{ Copyright (c) 1989 by Borland International, Inc. }
unit TCInput;
{ Turbo Pascal 5.5 object-oriented example input routines.
This unit is used by TCALC.PAS.
See TCALC.DOC for an more information about this example.
}
{$S-}
interface
uses Crt, TCUtil, TCScreen, TCLStr;
const
LeftInputArrow = #17;
RightInputArrow = #16;
YesNo = 'Y/N';
LegalYesNo = ['Y', 'N'];
AllUpper = True;
NotUpper = False;
ErrNumberError1 = 'You must enter a number from ';
ErrNumberError2 = ' to ';
ErrColumnError1 = 'You must enter a column from ';
ErrColumnError2 = ' to ';
ErrCellError = 'You must enter a legal cell';
type
InputField = object
StartCol : ScreenColRange;
StopCol : Integer;
InputRow : Integer;
MaxInputLen : Word;
Quit : Boolean;
InputData : LStringPtr;
UCase : Boolean;
InputArea : ScreenArea;
constructor Init(C1 : ScreenColRange; C2 : Integer; R : Integer;
InitMaxInputLen : Word; InitUCase : Boolean);
destructor Done;
function GetQuit : Boolean;
procedure Edit(StartCursor : Word);
procedure ClearInput;
end;
function ReadString(Prompt : String; Len : Word;
var ESCPressed : Boolean) : String;
function GetLegalChar(Prompt : String; Legal : CharSet;
var ESCPressed : Boolean) : Char;
function GetYesNo(Prompt : String; var ESCPressed : Boolean) : Boolean;
function GetNumber(Prompt : String; Low, High : Longint;
var Result : Boolean) : Longint;
implementation
constructor InputField.Init(C1 : ScreenColRange; C2 : Integer; R : Integer;
InitMaxInputLen : Word; InitUCase : Boolean);
{ Sets up an input field }
begin
InputData := New(LStringPtr, Init);
if InputData = nil then
Fail;
StartCol := C1;
StopCol := C2;
InputRow := R;
if InitMaxInputLen = 0 then
MaxInputLen := 65521 { Maximum area that a pointer can allocate }
else
MaxInputLen := InitMaxInputLen;
UCase := InitUCase;
Quit := False;
end; { InputField.Init }
destructor InputField.Done;
{ Remove memory used by an input field }
begin
Dispose(InputData, Done);
end; { InputField.Done }
function InputField.GetQuit : Boolean;
{ Check to see if an input field has been exited with ESC }
begin
GetQuit := Quit;
end; { InputField.GetQuit }
procedure InputField.Edit(StartCursor : Word);
{ Edits the input field }
var
CursorPos, Start, Cursor : Word;
Ch : Word;
Good, InsMode, Finished : Boolean;
R : ScreenRowRange;
SCol, ECol, EndCol : ScreenColRange;
begin
with InputData^ do
begin
Quit := False;
SCol := StartCol; { Figure out where the field starts and stops }
if StopCol <= 0 then
EndCol := Scr.CurrCols + StopCol
else
EndCol := StopCol;
if InputRow <= 0 then
R := Scr.CurrRows + InputRow
else
R := InputRow;
if (R = Scr.CurrRows) and (ECol = Scr.CurrCols) then
Dec(EndCol);
ECol := EndCol;
InputArea.Init(SCol, R, ECol, R, Colors.InputColor);
InputArea.Clear;
if StartCursor = 0 then
CursorPos := Succ(Length)
else
CursorPos := StartCursor;
Finished := False;
InsMode := True;
Cursor := Scr.InsCursor;
Start := Max(Longint(CursorPos) - ECol - SCol + 2, 1);
repeat
if CursorPos > Length then
ECol := EndCol;
if (CursorPos < Start) or (CursorPos > Start + ECol - SCol) then
Start := Max(Longint(CursorPos) - ECol + SCol, 1);
if (Start = 2) and (SCol <> StartCol) then
begin
SCol := StartCol;
Start := 1;
end;
if Start > 1 then
begin
if SCol = StartCol then
begin
Inc(Start);
SCol := Succ(StartCol); { Text is off left side of line }
end;
end
else
SCol := StartCol;
if Length > Start + ECol - SCol then
begin
if ECol = EndCol then
begin
if SCol <> StartCol then
Inc(Start);
ECol := Pred(EndCol); { Text is off right side of line }
end;
end
else
ECol := EndCol;
GotoXY(StartCol, R);
if SCol <> StartCol then { Text is off left side of line }
WriteColor(LeftInputArrow, Colors.InputArrowColor);
WriteColor(LeftJustStr(InputData^.Copy(Start, Succ(ECol - SCol)),
Succ(ECol - SCol)), Colors.InputColor);
if ECol <> EndCol then { Text is off right side of line }
WriteColor(RightInputArrow, Colors.InputArrowColor);
GotoXY(CursorPos - Start + SCol, R);
SetCursor(Cursor);
Ch := GetKey;
SetCursor(NoCursor);
case Ch of
Ord(' ')..Ord('~') : begin
if not (InsMode and (Length = MaxInputLen)) then
begin
if UCase then
Ch := Ord(UpCase(Chr(Ch)));
if InsMode or (CursorPos > Length) then
Good := Insert(Chr(Ch), CursorPos)
else begin
Good := True;
Change(Chr(Ch), CursorPos);
end;
if Good then
Inc(CursorPos);
end;
end;
HomeKey : CursorPos := 1;
EndKey : CursorPos := Succ(Length);
BS : begin
if CursorPos > 1 then
begin
Delete(Pred(CursorPos), 1);
Dec(CursorPos);
end;
end;
DelKey : begin
if CursorPos <= Length then
Delete(CursorPos, 1);
end;
LeftKey : begin
if CursorPos > 1 then
Dec(CursorPos);
end;
RightKey : begin
if CursorPos <= Length then
Inc(CursorPos);
end;
InsKey : begin
InsMode := not InsMode;
if InsMode then
Cursor := Scr.InsCursor
else
Cursor := Scr.OldCursor;
end;
CtrlLeftKey : begin { Move back one word }
if (CursorPos > 1) and (Data^[CursorPos] <> ' ') then
Dec(CursorPos);
while (CursorPos > 1) and (Data^[CursorPos] = ' ') do
Dec(CursorPos);
while (CursorPos > 1) and (Data^[Pred(CursorPos)] <> ' ') do
Dec(CursorPos);
end;
CtrlRightKey : begin { Move forward one word }
while (CursorPos <= Length) and (Data^[CursorPos] <> ' ') do
Inc(CursorPos);
while (CursorPos <= Length) and (Data^[CursorPos] = ' ') do
Inc(CursorPos);
end;
ESC : begin
ClearInput;
Quit := True;
Finished := True;
end;
CR : Finished := True;
end; { case }
until Finished;
end; { with }
end; { InputField.Edit }
procedure InputField.ClearInput;
{ Makes the input field data a null long string }
var
Good : Boolean;
begin
Good := InputData^.FromString('');
end; { InputField.ClearInput }
function ReadString(Prompt : String; Len : Word;
var ESCPressed : Boolean) : String;
{ Read a string from the input area }
var
I : InputField;
begin
with I do
begin
if not Init(Length(Prompt) + 3, 0, -1, Len, NotUpper) then
begin
ESCPressed := True;
ReadString := '';
end;
WriteXY(Prompt + ': ', 1, Pred(Scr.CurrRows), Colors.PromptColor);
Edit(0);
ReadString := InputData^.ToString;
ESCPressed := GetQuit;
Done;
end; { with }
ClrEOLXY(1, Pred(Scr.CurrRows), Colors.BlankColor);
end; { ReadString }
function GetLegalChar(Prompt : String; Legal : CharSet;
var ESCPressed : Boolean) : Char;
{ Read a chanracter from the input area, only reading certain ones }
var
Ch : Char;
begin
WriteXY(Prompt + ': ', 1, Pred(Scr.CurrRows), Colors.PromptColor);
Ch := GetKeyChar(Legal);
ClrEOLXY(1, Pred(Scr.CurrRows), Colors.BlankColor);
GetLegalChar := Ch;
end; { GetLegalChar }
function GetYesNo(Prompt : String; var ESCPressed : Boolean) : Boolean;
{ Prints a "Yes/No" prompt, allowing the user to type Y or N to answer the
question }
var
Ch : Char;
begin
WriteXY(Prompt + ' (' + YesNo + ')?', 1, Pred(Scr.CurrRows),
Colors.PromptColor);
Ch := GetKeyChar(LegalYesNo);
ESCPressed := Ch = Chr(ESC);
ClrEOLXY(1, Pred(Scr.CurrRows), Colors.BlankColor);
GetYesNo := Ch = 'Y';
end; { GetYesNo }
function GetNumber(Prompt : String; Low, High : Longint;
var Result : Boolean) : Longint;
{ Prompts for a numeric value within a certain range }
var
I : InputField;
S : String;
Error : Integer;
L : Longint;
begin
with I do
begin
if not Init(Length(Prompt) + 3, 0, -1,
Max(Length(NumToString(Low)),
Length(NumToString(High))), NotUpper) then
begin
Result := False;
GetNumber := 0;
Exit;
end;
WriteXY(Prompt + ': ', 1, Pred(Scr.CurrRows), Colors.PromptColor);
repeat
Edit(0);
S := InputData^.ToString;
if (not GetQuit) and (S <> '') then
begin
Val(S, L, Error);
Result := (Error = 0) and (L >= Low) and (L <= High);
if not Result then
Scr.PrintError(ErrNumberError1 + NumToString(Low) +
ErrNumberError2 + NumToString(High));
end
else begin
Result := False;
L := 0;
end;
until Result or (S = '');
Done;
end; { with }
ClrEOLXY(1, Pred(Scr.CurrRows), Colors.BlankColor);
GetNumber := L;
end; { GetNumber }
end.