477 lines
12 KiB
ObjectPascal
477 lines
12 KiB
ObjectPascal
{-----------------------------------------------------------------------------
|
|
The contents of this file are subject to the Mozilla Public License
|
|
Version 1.1 (the "License"); you may not use this file except in compliance
|
|
with the License. You may obtain a copy of the License at
|
|
http://www.mozilla.org/MPL/MPL-1.1.html
|
|
|
|
Software distributed under the License is distributed on an "AS IS" basis,
|
|
WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for
|
|
the specific language governing rights and limitations under the License.
|
|
|
|
The Original Code is: JvCmdEdit.PAS, released on 2002-05-26.
|
|
|
|
The Initial Developer of the Original Code is Peter Thörnqvist [peter3 att users dott sourceforge dott net]
|
|
Portions created by Peter Thörnqvist are Copyright (C) 2002 Peter Thörnqvist.
|
|
All Rights Reserved.
|
|
|
|
Contributor(s):
|
|
|
|
Last Modified: 2002-05-26
|
|
|
|
You may retrieve the latest version of this file at the Project JEDI's JVCL home page,
|
|
located at http://jvcl.sourceforge.net
|
|
|
|
Known Issues:
|
|
-----------------------------------------------------------------------------}
|
|
|
|
{$I JVCL.INC}
|
|
|
|
{A TEdit that displays and reacts to command input. }
|
|
|
|
unit JvCommandEdit;
|
|
|
|
interface
|
|
|
|
uses
|
|
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
|
|
StdCtrls, Menus,
|
|
JvEdit, JvComponent, JvTypes;
|
|
|
|
type
|
|
TJvCmdEvent = procedure(Sender: TObject; Cmd: Integer; Params: TStrings; var Handled: Boolean) of object;
|
|
|
|
TJvCustomCommandEdit = class(TJvCustomEdit)
|
|
private
|
|
FShift: TShiftState;
|
|
FKey: Word;
|
|
FSuppress: Boolean;
|
|
FCurrCmd: string;
|
|
FCurrCmdIndex: Integer;
|
|
FPrompt: string;
|
|
FOnCommand: TJvCmdEvent;
|
|
FExecuteKey: TShortCut;
|
|
FHistory: TStrings;
|
|
FCommands: TStrings;
|
|
FArrowKeys: Boolean;
|
|
procedure WMPaste(var Msg: TWMPaste); message WM_PASTE;
|
|
procedure WMCopy(var Msg: TWMCopy); message WM_COPY;
|
|
procedure WMCut(var Msg: TWMCut); message WM_CUT;
|
|
procedure SetCommands(const Value: TStrings);
|
|
procedure SetCurrCmd(const Value: string);
|
|
procedure SetExecuteKey(const Value: TShortCut);
|
|
procedure SetHistory(const Value: TStrings);
|
|
procedure SetPrompt(const Value: string);
|
|
procedure CheckLimits(var Key: Word);
|
|
procedure ResetHistory;
|
|
// procedure UpdateState;
|
|
function GetCurrCmd: string;
|
|
procedure SetArrowKeys(const Value: Boolean);
|
|
protected
|
|
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
|
|
procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
|
|
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
|
|
procedure KeyUp(var Key: Word; Shift: TShiftState); override;
|
|
procedure KeyPress(var Key: Char); override;
|
|
function DoCommand(Cmd: Integer; Params: TStrings): Boolean; virtual;
|
|
|
|
property CurrCmd: string read GetCurrCmd write SetCurrCmd;
|
|
property Prompt: string read FPrompt write SetPrompt;
|
|
property History: TStrings read FHistory write SetHistory;
|
|
property Commands: TStrings read FCommands write SetCommands;
|
|
property ExecuteKey: TShortCut read FExecuteKey write SetExecuteKey default VK_RETURN;
|
|
property OnCommand: TJvCmdEvent read FOnCommand write FOnCommand;
|
|
property ArrowKeys: Boolean read FArrowKeys write SetArrowKeys default True;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
function GotoCmd(Index: Integer; RelToCurr: Boolean): Boolean;
|
|
function Execute: Boolean;
|
|
function ExecuteCommand(const Cmd: string): Boolean;
|
|
end;
|
|
|
|
TJvCommandEdit = class(TJvCustomCommandEdit)
|
|
published
|
|
property CurrCmd;
|
|
property ClipboardCommands;
|
|
property Commands;
|
|
property ExecuteKey;
|
|
property History;
|
|
property Prompt;
|
|
property OnCommand;
|
|
|
|
property ArrowKeys;
|
|
property Align;
|
|
property AutoSelect;
|
|
property AutoSize;
|
|
property BorderStyle;
|
|
property CharCase;
|
|
property Color;
|
|
property Ctl3D;
|
|
property DragCursor;
|
|
property DragMode;
|
|
property Enabled;
|
|
property Font;
|
|
property HideSelection;
|
|
property ImeMode;
|
|
property ImeName;
|
|
property MaxLength;
|
|
property OEMConvert;
|
|
property ParentColor;
|
|
property ParentCtl3D;
|
|
property ParentFont;
|
|
property ParentShowHint;
|
|
property PopupMenu;
|
|
property ShowHint;
|
|
property TabOrder;
|
|
property TabStop;
|
|
property Visible;
|
|
property OnChange;
|
|
property OnClick;
|
|
property OnDblClick;
|
|
property OnDragDrop;
|
|
property OnDragOver;
|
|
property OnEndDrag;
|
|
property OnEnter;
|
|
property OnExit;
|
|
property OnKeyDown;
|
|
property OnKeyPress;
|
|
property OnKeyUp;
|
|
property OnMouseDown;
|
|
property OnMouseMove;
|
|
property OnMouseUp;
|
|
property OnStartDrag;
|
|
property Anchors;
|
|
property BiDiMode;
|
|
property Constraints;
|
|
property DragKind;
|
|
property ParentBiDiMode;
|
|
property OnEndDock;
|
|
property OnStartDock;
|
|
end;
|
|
|
|
implementation
|
|
|
|
// uses
|
|
// utilsString;
|
|
|
|
constructor TJvCustomCommandEdit.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FHistory := TStringList.Create;
|
|
FCommands := TStringList.Create;
|
|
FArrowKeys := True;
|
|
FExecuteKey := VK_RETURN;
|
|
ShortCutToKey(FExecuteKey, FKey, FShift);
|
|
FCurrCmd := '';
|
|
Prompt := ':';
|
|
end;
|
|
|
|
destructor TJvCustomCommandEdit.Destroy;
|
|
begin
|
|
FHistory.Free;
|
|
FCommands.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
{
|
|
procedure TJvCustomCommandEdit.UpdateState;
|
|
begin
|
|
Text := FPrompt;
|
|
FSuppress := False;
|
|
if CanFocus and HasParent then
|
|
SelStart := length(FPrompt);
|
|
end;
|
|
}
|
|
|
|
procedure TJvCustomCommandEdit.CheckLimits(var Key: Word);
|
|
var
|
|
P: TPoint;
|
|
begin
|
|
if SelStart < Length(FPrompt) then
|
|
begin
|
|
Key := 0;
|
|
P.X := SelStart + SelLength;
|
|
P.Y := Length(FPrompt);
|
|
SendMessage(Handle, EM_SETSEL, P.X, P.Y);
|
|
SendMessage(Handle, EM_SCROLLCARET, 0, 0);
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomCommandEdit.ResetHistory;
|
|
begin
|
|
FHistory.Clear;
|
|
FCurrCmdIndex := 0;
|
|
end;
|
|
|
|
{$IFOPT J-}
|
|
{$DEFINE RESETJ}
|
|
{$ENDIF}
|
|
{$J+}
|
|
|
|
function strtok(Search, Delim: string): string;
|
|
const
|
|
I: Integer = 1;
|
|
Len: Integer = 0;
|
|
PrvStr: string = '';
|
|
begin
|
|
Result := '';
|
|
if Search <> '' then
|
|
begin
|
|
I := 1;
|
|
PrvStr := Search;
|
|
Len := Length(PrvStr);
|
|
end;
|
|
if PrvStr = '' then
|
|
Exit;
|
|
while (I <= Len) and (Pos(PrvStr[I], Delim) > 0) do
|
|
Inc(I);
|
|
while (I <= Len) and (Pos(PrvStr[I], Delim) = 0) do
|
|
begin
|
|
Result := Result + PrvStr[I];
|
|
Inc(I);
|
|
end;
|
|
end;
|
|
|
|
{$IFDEF RESETJ}
|
|
{$UNDEF RESETJ}
|
|
{$J-}
|
|
{$ENDIF}
|
|
|
|
function TJvCustomCommandEdit.Execute: Boolean;
|
|
var
|
|
Params: TStringList;
|
|
Cmd: string;
|
|
begin
|
|
FCurrCmd := Copy(Text, Length(Prompt) + 1, MaxInt);
|
|
Cmd := FCurrCmd;
|
|
Cmd := strtok(Cmd, ' ');
|
|
Params := TStringList.Create;
|
|
try
|
|
while Cmd <> '' do
|
|
begin
|
|
Params.Add(Cmd);
|
|
Cmd := strtok('', ' ');
|
|
end;
|
|
if Params.Count > 0 then
|
|
begin
|
|
Cmd := Params[0];
|
|
Params.Delete(0);
|
|
end
|
|
else
|
|
Cmd := '';
|
|
Result := DoCommand(FCommands.IndexOf(Cmd), Params);
|
|
if Result then
|
|
begin
|
|
FHistory.Add(CurrCmd);
|
|
FCurrCmdIndex := FHistory.Count - 1;
|
|
end;
|
|
finally
|
|
Params.Free;
|
|
end;
|
|
// UpdateState;
|
|
end;
|
|
|
|
function TJvCustomCommandEdit.GotoCmd(Index: Integer;
|
|
RelToCurr: Boolean): Boolean;
|
|
begin
|
|
Result := False;
|
|
if RelToCurr then
|
|
Inc(FCurrCmdIndex, Index)
|
|
else
|
|
FCurrCmdIndex := Index;
|
|
if FCurrCmdIndex < 0 then
|
|
FCurrCmdIndex := 0;
|
|
if FCurrCmdIndex >= FHistory.Count then
|
|
FCurrCmdIndex := FHistory.Count - 1;
|
|
Index := FCurrCmdIndex;
|
|
if (Index > -1) and (Index < FHistory.Count) then
|
|
begin
|
|
CurrCmd := History[Index];
|
|
Result := True;
|
|
SelStart := Length(Text) + 1;
|
|
end
|
|
else
|
|
Beep;
|
|
end;
|
|
|
|
procedure TJvCustomCommandEdit.KeyPress(var Key: Char);
|
|
begin
|
|
if FSuppress {and (Key = Char(FKey))} then
|
|
Key := #0
|
|
else
|
|
begin
|
|
// CheckLimits(Char(Key));
|
|
ReadOnly := (SelStart < Length(Prompt)) or ((SelStart <= Length(Prompt)) and (Key = #8));
|
|
end;
|
|
inherited KeyPress(Key);
|
|
FSuppress := False;
|
|
end;
|
|
|
|
procedure TJvCustomCommandEdit.KeyDown(var Key: Word; Shift: TShiftState);
|
|
begin
|
|
CheckLimits(Key);
|
|
ReadOnly := (SelStart < Length(Prompt)) or ((SelStart <= Length(Prompt)) and (Key = VK_BACK));
|
|
if (FArrowKeys and (Shift = []) and (Key in [VK_UP, VK_DOWN, VK_F3, VK_ESCAPE])) or
|
|
((Key = FKey) and (FShift = Shift)) or ((Key = VK_LEFT) and (SelStart + SelLength <= Length(Prompt))) then
|
|
begin
|
|
// FSuppress := True;
|
|
Key := 0;
|
|
end;
|
|
inherited KeyDown(Key, Shift);
|
|
end;
|
|
|
|
procedure TJvCustomCommandEdit.KeyUp(var Key: Word; Shift: TShiftState);
|
|
var
|
|
K2: Word;
|
|
begin
|
|
CheckLimits(Key);
|
|
K2 := Key;
|
|
Key := 0;
|
|
ReadOnly := (SelStart + SelLength < Length(Prompt)) or ((SelStart + SelLength <= Length(Prompt)) and (Key = VK_BACK));
|
|
if (K2 = FKey) and (FShift = Shift) then
|
|
Execute
|
|
else
|
|
if FArrowKeys and (Shift = []) then
|
|
begin
|
|
FSuppress := True;
|
|
case K2 of
|
|
VK_UP:
|
|
GotoCmd(-1, True);
|
|
VK_DOWN:
|
|
GotoCmd(1, True);
|
|
VK_F3:
|
|
GotoCmd(FHistory.Count - 1, False);
|
|
VK_ESCAPE:
|
|
CurrCmd := '';
|
|
else
|
|
begin
|
|
Key := K2;
|
|
FSuppress := False;
|
|
inherited KeyUp(Key, Shift);
|
|
end
|
|
end
|
|
end
|
|
else
|
|
begin
|
|
FSuppress := False;
|
|
Key := K2;
|
|
inherited KeyUp(Key, Shift);
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomCommandEdit.SetCommands(const Value: TStrings);
|
|
begin
|
|
FCommands.Assign(Value);
|
|
ResetHistory;
|
|
end;
|
|
|
|
procedure TJvCustomCommandEdit.SetCurrCmd(const Value: string);
|
|
begin
|
|
FCurrCmd := Value;
|
|
Text := FPrompt + FCurrCmd;
|
|
if CanFocus and HasParent then
|
|
SelStart := Length(Prompt) + 1;
|
|
end;
|
|
|
|
procedure TJvCustomCommandEdit.SetExecuteKey(const Value: TShortCut);
|
|
begin
|
|
if FExecuteKey <> Value then
|
|
begin
|
|
FExecuteKey := Value;
|
|
ShortCutToKey(FExecuteKey, FKey, FShift);
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomCommandEdit.SetHistory(const Value: TStrings);
|
|
begin
|
|
FHistory.Assign(Value);
|
|
end;
|
|
|
|
procedure TJvCustomCommandEdit.SetPrompt(const Value: string);
|
|
begin
|
|
FPrompt := Value;
|
|
Text := FPrompt + CurrCmd;
|
|
end;
|
|
|
|
procedure TJvCustomCommandEdit.WMCopy(var Msg: TWMCopy);
|
|
var
|
|
Key: Word;
|
|
begin
|
|
if caCopy in ClipboardCommands then
|
|
begin
|
|
Key := 0;
|
|
CheckLimits(Key);
|
|
inherited;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomCommandEdit.WMCut(var Msg: TWMCut);
|
|
var
|
|
Key: Word;
|
|
begin
|
|
if caCut in ClipboardCommands then
|
|
begin
|
|
Key := 0;
|
|
CheckLimits(Key);
|
|
inherited;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomCommandEdit.WMPaste(var Msg: TWMPaste);
|
|
var
|
|
Key: Word;
|
|
begin
|
|
if caPaste in ClipboardCommands then
|
|
begin
|
|
Key := 0;
|
|
CheckLimits(Key);
|
|
inherited;
|
|
end;
|
|
end;
|
|
|
|
function TJvCustomCommandEdit.DoCommand(Cmd: Integer; Params: TStrings): Boolean;
|
|
begin
|
|
Result := True;
|
|
// FSuppress := True;
|
|
if Assigned(FOnCommand) then
|
|
FOnCommand(Self, Cmd, Params, Result);
|
|
end;
|
|
|
|
procedure TJvCustomCommandEdit.MouseDown(Button: TMouseButton;
|
|
Shift: TShiftState; X, Y: Integer);
|
|
var
|
|
Key: Word;
|
|
begin
|
|
inherited MouseDown(Button, Shift, X, y);
|
|
CheckLimits(Key);
|
|
end;
|
|
|
|
procedure TJvCustomCommandEdit.MouseUp(Button: TMouseButton; Shift: TShiftState;
|
|
X, Y: Integer);
|
|
var
|
|
Key: Word;
|
|
begin
|
|
inherited MouseUp(Button, Shift, X, Y);
|
|
CheckLimits(Key);
|
|
end;
|
|
|
|
function TJvCustomCommandEdit.GetCurrCmd: string;
|
|
begin
|
|
Result := Copy(Text, Length(FPrompt) + 1, MaxInt);
|
|
end;
|
|
|
|
procedure TJvCustomCommandEdit.SetArrowKeys(const Value: Boolean);
|
|
begin
|
|
if FArrowKeys <> Value then
|
|
FArrowKeys := Value;
|
|
end;
|
|
|
|
function TJvCustomCommandEdit.ExecuteCommand(const Cmd: string): Boolean;
|
|
begin
|
|
CurrCmd := Cmd;
|
|
Result := Execute;
|
|
end;
|
|
|
|
end.
|
|
|