📄 utils.pas
字号:
unit Utils;
{$O+,F+,S-,X+}
interface
uses Objects, Views, TDos, TVars;
type
TResourceName = string[31];
const
mfWarning = $0000;
mfError = $0001;
mfInformation = $0002;
mfAwarePoint = $0010;
mfYesButton = $0100;
mfNoButton = $0200;
mfOKButton = $0400;
mfCancelButton = $0800;
mfYesNoCancel = mfYesButton + mfNoButton + mfCancelButton;
mfOKCancel = mfOKButton + mfCancelButton;
function MessageBox(Msg: Integer; Params: Pointer; AOptions: Word): Word;
procedure OutOfMemory;
function ValidView(P: PView): PView;
function LoadWindow(Name: TResourceName): PWindow;
function ExecDialog(Name: TResourceName; Params: Pointer): Word;
function WaitEvent: Word;
function GetEditWord(MaxLen: Integer; CS: PCharSet): string;
function GetEditChar(I: Integer): Char;
function GetFreeWNum: Integer;
procedure ChangeSet(var T: TCommandSet; Command: Word; Enable: Boolean);
procedure SearchSysDir(var Name: PathStr);
function ValidFileName(var Name: PathStr): Boolean;
procedure ChangeExt(var Path: PathStr; NewExt: ExtStr; Force: Boolean);
procedure SetEgaLines(Enable: Boolean);
function DirExists(var Dir: DirStr): Boolean;
implementation
uses Drivers, Memory, Dialogs, App, TEdit, Editor, StrNames;
function MessageBox(Msg: Integer; Params: Pointer; AOptions: Word): Word;
const
ButtonName: array[0..3] of string[6] =
('YesBtn', 'NoBtn', 'OkBtn', 'CnlBtn');
var
I, X, ButtonCount: Integer;
Dialog: PDialog;
Control: PView;
R: TRect;
T: TRect;
ButtonList: array[0..3] of PView;
S: String;
P: TPoint absolute Params;
begin
R.Assign(0, 0, 40, 9);
R.Move((Application^.Size.X - R.B.X) div 2,
(Application^.Size.Y - R.B.Y) div 2);
if AOptions and mfAwarePoint <> 0 then
begin
Desktop^.MakeGlobal(R.A, T.A);
Desktop^.MakeGlobal(R.B, T.B);
Dec(T.A.Y);
Inc(T.B.Y);
if (P.Y >= T.A.Y) and (P.Y <= T.B.Y) then
begin
I := R.B.Y - R.A.Y;
if P.Y - I - 3 < 0 then
R.A.Y := P.Y + 1
else
R.A.Y := P.Y - I - 2;
R.B.Y := R.A.Y + I;
end;
end;
Dialog := New(PDialog, Init(R, Strings^.Get((AOptions and $3) + sMsgBase)));
with Dialog^ do
begin
R.Assign(3, 2, Size.X - 2, Size.Y - 3);
FormatStr(S, Strings^.Get(Msg), Params^);
Control := New(PStaticText, Init(R, S));
Insert(Control);
X := -2;
ButtonCount := 0;
for I := 0 to 3 do
if AOptions and ($0100 shl I) <> 0 then
begin
Control := PView(Resource.Get(ButtonName[I]));
Inc(X, Control^.Size.X + 2);
ButtonList[ButtonCount] := Control;
Inc(ButtonCount);
end;
X := (Size.X - X) shr 1;
for I := 0 to ButtonCount - 1 do
begin
Control := ButtonList[I];
Insert(Control);
Control^.MoveTo(X, Size.Y - 3);
Inc(X, Control^.Size.X + 2);
end;
SelectNext(False);
end;
MessageBox := Application^.ExecView(Dialog);
Dispose(Dialog, Done);
end;
procedure OutOfMemory;
begin
MessageBox(sOutOfMemory, nil, mfError + mfOkButton);
end;
function ValidView(P: PView): PView;
begin
ValidView := nil;
if P <> nil then
begin
if LowMemory then
begin
Dispose(P, Done);
OutOfMemory
end
else if not P^.Valid(cmValid) then
Dispose(P, Done)
else
ValidView := P;
end;
end;
function LoadWindow(Name: TResourceName): PWindow;
var
W: PWindow;
L: array[0..0] of Longint;
begin
W := PWindow(Resource.Get(Name));
if W = nil then
begin
L[0] := Longint(@Name);
MessageBox(sNoResource, @L, mfError + mfOkButton);
end;
LoadWindow:=PWindow(ValidView(W));
end;
function ExecDialog(Name: TResourceName; Params: Pointer): Word;
var
D: PDialog;
I: Word;
begin
ExecDialog := cmCancel;
D := PDialog(LoadWindow(Name));
I := 0;
if D <> nil then
begin
if Params <> nil then
D^.SetData(Params^)
else
D^.SetData(I);
I := Application^.ExecView(D);
if (I <> cmCancel) and (Params <> nil) then
D^.GetData(Params^);
Dispose(D, Done);
ExecDialog := I;
end;
end;
function WaitEvent: Word; assembler;
asm
@@1: CMP ButtonCount,0
JE @@2
MOV AX,3
INT 33H
XOR AX,AX
OR BL,BL
JNZ @@3
@@2: MOV AH,1
INT 16H
JZ @@1
MOV AH,0
INT 16H
OR AX,AX
JZ @@1
@@3:
end;
function GetEditChar(I: Integer): Char;
var
C, CC: Char;
P: PEditView;
T: TPoint;
begin
GetEditChar := #0;
P := FindEditor(nil);
if P <> nil then
begin
T := P^.Editor^.TempPos;
C := #0;
repeat
CC := C;
C := Char(P^.DoFunc(edGetOneChar));
if C < ' ' then
if C = #0 then
Exit
else
C := ' ';
if (C <> ' ') or (CC <> ' ') then
Dec(I);
until I = 0;
GetEditChar := C;
P^.Editor^.TempPos := T;
end;
end;
function GetEditWord(MaxLen: Integer; CS: PCharSet): string;
var
P: PEditView;
SaveCursorPos, SaveScreenPos, SaveTempPos: TPoint;
S: string;
C: Char;
begin
S := '';
P := FindEditor(nil);
if P <> nil then
with P^ do
begin
SaveCursorPos := Editor^.CursorPos;
SaveScreenPos.X := Editor^.ScreenPos.X;
SaveScreenPos.Y := Editor^.ScreenPos.Y;
if Editor^.CursorPos.X <> 1 then
begin
repeat
DoFunc(edCursorCharLeft);
DoFunc(edSetTempPos);
C := Char(DoFunc(edGetOneChar));
until (Editor^.CursorPos.X = 1) or not (C in CS^);
if not (C in CS^) then
DoFunc(edCursorCharRight);
end;
DoFunc(edSetTempPos);
SaveTempPos := Editor^.TempPos;
C := Char(DoFunc(edGetOneChar));
while (C in CS^) and (length(S) < MaxLen) do
begin
Inc(S[0]);
S[length(S)] := C;
C := Char(DoFunc(edGetOneChar));
end;
Editor^.CursorPos := SaveCursorPos;
Editor^.ScreenPos.X := SaveScreenPos.X;
Editor^.ScreenPos.Y := SaveScreenPos.Y;
Editor^.TempPos := SaveTempPos;
end;
GetEditWord := S;
end;
function GetFreeWNum: Integer;
var
I: Integer;
function DoFind(P: PWindow): Boolean; far;
begin
if (P^.Options and ofSelectable <> 0) and (P^.State and sfVisible <> 0) then
DoFind := P^.Number = I
else
DoFind := False;
end;
begin
I := 0;
repeat
Inc(I)
until Desktop^.FirstThat(@DoFind) = nil;
GetFreeWNum := I;
end;
procedure ChangeSet(var T: TCommandSet; Command: Word; Enable: Boolean);
begin
if Enable then
T := T + [Command]
else
T := T - [Command];
end;
procedure SearchSysDir(var Name: PathStr);
var
Dir: DirStr;
N: NameStr;
Ext: ExtStr;
begin
FSplit(TurboExe, Dir, N, Ext);
Name := FSearch(Name, Dir);
end;
function ValidFileName(var Name: PathStr): Boolean;
var
Dir: DirStr;
N: NameStr;
Ext: ExtStr;
function HasAny(S, S1: string): Boolean; near; assembler;
asm
PUSH DS
CLD
LDS SI,S
LES DI,S1
INC DI
MOV DX,DI
XOR AH,AH
LODSB
MOV BX,AX
OR BX,BX
JZ @@2
MOV AL,ES:[DI-1]
XCHG AX,CX
@@1: PUSH CX
MOV DI,DX
LODSB
REPNE SCASB
POP CX
JE @@3
DEC BX
JNZ @@1
@@2: XOR AL,AL
JMP @@4
@@3: MOV AL,1
@@4: POP DS
end;
begin
ValidFileName := True;
if FileExists(Name) then
Exit;
FSplit(Name, Dir, N, Ext);
if (Dir + N + Ext <> Name) or (Dir <> '') and not DirExists(Dir) or
HasAny(N, ';,=+<>|"[] \') or
HasAny(Copy(Ext, 2, 255), ';,=+<>|"[] \.') then
ValidFileName := False;
end;
procedure ChangeExt(var Path: PathStr; NewExt: ExtStr; Force: Boolean);
var
Dir: DirStr;
Name: NameStr;
Ext: ExtStr;
begin
FSplit(Path, Dir, Name, Ext);
if Force or (Ext = '') then
Path := Dir + Name + NewExt;
end;
procedure SetEgaLines(Enable: Boolean);
var
I: Word;
begin
if HiResScreen and (Lo(ScreenMode) <> smMono) then
begin
if Enable then
I := ScreenMode or smFont8x8
else
I := ScreenMode and not smFont8x8;
if I <> ScreenMode then
Application^.SetScreenMode(I);
end;
end;
function DirExists(var Dir: DirStr): Boolean;
var
S: PathStr;
begin
FExpand(Dir, S);
if Length(S) <= 3 then
DirExists := (Length(S) > 1) and DriveValid(S[1])
else
begin
if S[Length(S)] = '\' then Dec(S[0]);
DirExists := GetFileAttr(S) > 0;
end;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -