fpc/ide/fpcodtmp.pas
fpc 790a4fe2d3 * log and id tags removed
git-svn-id: trunk@42 -
2005-05-21 09:42:41 +00:00

639 lines
17 KiB
ObjectPascal

{
This file is part of the Free Pascal Integrated Development Environment
Copyright (c) 1998 by Berczi Gabor
Code Template routines
See the file COPYING.FPC, included in this distribution,
for details about the copyright.
This program 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.
**********************************************************************}
unit FPCodTmp; { Code Templates }
interface
uses Objects,Drivers,Dialogs,
WUtils,WViews,WEditor,
FPViews;
type
PCodeTemplate = ^TCodeTemplate;
TCodeTemplate = object(TObject)
constructor Init(const AShortCut: string; AText: PUnsortedStringCollection);
function GetShortCut: string;
procedure GetText(AList: PUnsortedStringCollection);
procedure SetShortCut(const AShortCut: string);
procedure SetText(AList: PUnsortedStringCollection);
procedure GetParams(var AShortCut: string; Lines: PUnsortedStringCollection);
procedure SetParams(const AShortCut: string; Lines: PUnsortedStringCollection);
constructor Load(var S: TStream);
procedure Store(var S: TStream);
destructor Done; virtual;
private
ShortCut: PString;
Text: PUnsortedStringCollection;
end;
PCodeTemplateCollection = ^TCodeTemplateCollection;
TCodeTemplateCollection = object(TSortedCollection)
function Compare(Key1, Key2: Pointer): sw_Integer; virtual;
function SearchByShortCut(const ShortCut: string): PCodeTemplate; virtual;
function LookUp(const S: string; AcceptMulti: boolean; var Idx: sw_integer): string; virtual;
end;
PCodeTemplateListBox = ^TCodeTemplateListBox;
TCodeTemplateListBox = object(TAdvancedListBox)
function GetText(Item,MaxLen: Sw_Integer): String; virtual;
end;
PCodeTemplateDialog = ^TCodeTemplateDialog;
TCodeTemplateDialog = object(TCenterDialog)
constructor Init(const ATitle: string; ATemplate: PCodeTemplate);
function Execute: Word; virtual;
private
Template : PCodeTemplate;
ShortcutIL : PInputLine;
CodeMemo : PFPCodeMemo;
end;
PCodeTemplatesDialog = ^TCodeTemplatesDialog;
TCodeTemplatesDialog = object(TCenterDialog)
SelMode: boolean;
constructor Init(ASelMode: boolean;const AShortCut : string);
function Execute: Word; virtual;
procedure HandleEvent(var Event: TEvent); virtual;
function GetSelectedShortCut: string;
private
CodeTemplatesLB : PCodeTemplateListBox;
TemplateViewer : PFPCodeMemo;
StartIdx : sw_integer;
procedure Add;
procedure Edit;
procedure Delete;
procedure Update;
end;
const CodeTemplates : PCodeTemplateCollection = nil;
function FPTranslateCodeTemplate(var Shortcut: string; ALines: PUnsortedStringCollection): boolean;
procedure InitCodeTemplates;
function LoadCodeTemplates(var S: TStream): boolean;
function StoreCodeTemplates(var S: TStream): boolean;
procedure DoneCodeTemplates;
procedure RegisterCodeTemplates;
implementation
uses Views,App,Validate,
FVConsts,
FPConst,FPString;
{$ifndef NOOBJREG}
const
RCodeTemplate: TStreamRec = (
ObjType: 14501;
VmtLink: Ofs(TypeOf(TCodeTemplate)^);
Load: @TCodeTemplate.Load;
Store: @TCodeTemplate.Store
);
RCodeTemplateCollection: TStreamRec = (
ObjType: 14502;
VmtLink: Ofs(TypeOf(TCodeTemplateCollection)^);
Load: @TCodeTemplateCollection.Load;
Store: @TCodeTemplateCollection.Store
);
{$endif}
constructor TCodeTemplate.Init(const AShortCut: string; AText: PUnsortedStringCollection);
procedure CopyIt(P: PString); {$ifndef FPC}far;{$endif}
begin
Text^.Insert(NewStr(GetStr(P)));
end;
begin
inherited Init;
ShortCut:=NewStr(AShortCut);
SetText(AText);
end;
function TCodeTemplate.GetShortCut: string;
begin
GetShortCut:=GetStr(ShortCut);
end;
procedure TCodeTemplate.GetText(AList: PUnsortedStringCollection);
procedure CopyIt(P: PString); {$ifndef FPC}far;{$endif}
begin
AList^.Insert(NewStr(GetStr(P)));
end;
begin
if Assigned(AList) and Assigned(Text) then
Text^.ForEach(@CopyIt);
end;
procedure TCodeTemplate.SetShortCut(const AShortCut: string);
begin
if Assigned(ShortCut) then DisposeStr(ShortCut);
ShortCut:=NewStr(AShortCut);
end;
procedure TCodeTemplate.SetText(AList: PUnsortedStringCollection);
begin
if Assigned(Text) then Dispose(Text, Done);
New(Text, CreateFrom(AList));
end;
procedure TCodeTemplate.GetParams(var AShortCut: string; Lines: PUnsortedStringCollection);
begin
AShortCut:=GetShortCut;
GetText(Lines);
end;
procedure TCodeTemplate.SetParams(const AShortCut: string; Lines: PUnsortedStringCollection);
begin
SetShortCut(AShortCut);
SetText(Lines);
end;
constructor TCodeTemplate.Load(var S: TStream);
begin
ShortCut:=S.ReadStr;
New(Text, Load(S));
end;
procedure TCodeTemplate.Store(var S: TStream);
begin
S.WriteStr(ShortCut);
Text^.Store(S);
end;
destructor TCodeTemplate.Done;
begin
if Assigned(ShortCut) then DisposeStr(ShortCut); ShortCut:=nil;
if Assigned(Text) then Dispose(Text, Done); Text:=nil;
inherited Done;
end;
function TCodeTemplateCollection.Compare(Key1, Key2: Pointer): sw_Integer;
var K1: PCodeTemplate absolute Key1;
K2: PCodeTemplate absolute Key2;
R: Sw_integer;
S1,S2: string;
begin
S1:=UpCaseStr(K1^.GetShortCut);
S2:=UpCaseStr(K2^.GetShortCut);
if S1<S2 then R:=-1 else
if S1>S2 then R:=1 else
R:=0;
Compare:=R;
end;
function TCodeTemplateCollection.SearchByShortCut(const ShortCut: string): PCodeTemplate;
var T: TCodeTemplate;
Index: sw_integer;
P: PCodeTemplate;
begin
T.Init(ShortCut,nil);
if Search(@T,Index)=false then P:=nil else
P:=At(Index);
T.Done;
SearchByShortCut:=P;
end;
function TCodeTemplateCollection.LookUp(const S: string; AcceptMulti: boolean; var Idx: sw_integer): string;
var OLI,ORI,Left,Right,Mid: sw_integer;
MidP: PCodeTemplate;
MidS: string;
FoundS: string;
UpS : string;
begin
Idx:=-1; FoundS:='';
Left:=0; Right:=Count-1;
UpS:=UpCaseStr(S);
while Left<=Right do
begin
OLI:=Left; ORI:=Right;
Mid:=Left+(Right-Left) div 2;
MidP:=At(Mid);
MidS:=UpCaseStr(MidP^.GetShortCut);
if copy(MidS,1,length(UpS))=UpS then
begin
if (Idx<>-1) and (Idx<>Mid) and not AcceptMulti then
begin
{ several solutions possible, return nothing }
Idx:=-1;
FoundS:='';
break;
end
else if Idx=-1 then
begin
Idx:=Mid;
FoundS:=MidP^.GetShortCut;
end;
end;
if UpS<MidS then
Right:=Mid
else
Left:=Mid;
if (OLI=Left) and (ORI=Right) then
begin
if (Left<Right) then
Left:=Right
else
Break;
end;
end;
{ check if next also fits...
return '' in that case }
if (Idx<>-1) and (Idx<Count-1) and not AcceptMulti then
begin
MidP:=At(Idx+1);
MidS:=UpCaseStr(MidP^.GetShortCut);
if copy(MidS,1,length(UpS))=UpS then
begin
Idx:=-1;
FoundS:='';
end;
end;
LookUp:=FoundS;
end;
function FPTranslateCodeTemplate(var Shortcut: string; ALines: PUnsortedStringCollection): boolean;
var OK: boolean;
P: PCodeTemplate;
CompleteName: String;
Idx : sw_integer;
begin
OK:=Assigned(CodeTemplates);
if OK then
begin
P:=CodeTemplates^.SearchByShortCut(ShortCut);
if not assigned(P) then
begin
CompleteName:=CodeTemplates^.Lookup(ShortCut,false,Idx);
if Idx<>-1 then
begin
P:=CodeTemplates^.At(Idx);
ShortCut:=CompleteName;
end;
end;
OK:=Assigned(P);
if OK then
P^.GetText(ALines);
end;
FPTranslateCodeTemplate:=OK;
end;
procedure InitCodeTemplates;
begin
if Assigned(CodeTemplates) then Exit;
New(CodeTemplates, Init(10,10));
end;
function LoadCodeTemplates(var S: TStream): boolean;
var C: PCodeTemplateCollection;
OK: boolean;
begin
New(C, Load(S));
OK:=Assigned(C) and (S.Status=stOk);
if OK then
begin
if Assigned(CodeTemplates) then Dispose(CodeTemplates, Done);
CodeTemplates:=C;
end
else
if Assigned(C) then
Dispose(C, Done);
LoadCodeTemplates:=OK;
end;
function StoreCodeTemplates(var S: TStream): boolean;
var OK: boolean;
begin
OK:=Assigned(CodeTemplates);
if OK then
begin
CodeTemplates^.Store(S);
OK:=OK and (S.Status=stOK);
end;
StoreCodeTemplates:=OK;
end;
procedure DoneCodeTemplates;
begin
if Assigned(CodeTemplates) then Dispose(CodeTemplates, Done);
CodeTemplates:=nil;
end;
function TCodeTemplateListBox.GetText(Item,MaxLen: Sw_Integer): String;
var P: PCodeTemplate;
begin
P:=List^.At(Item);
GetText:=P^.GetShortCut;
end;
constructor TCodeTemplateDialog.Init(const ATitle: string; ATemplate: PCodeTemplate);
var R,R2,R3: TRect;
begin
R.Assign(0,0,52,15);
inherited Init(R,ATitle);
Template:=ATemplate;
GetExtent(R); R.Grow(-3,-2); R3.Copy(R);
Inc(R.A.Y); R.B.Y:=R.A.Y+1; R.B.X:=R.A.X+46;
New(ShortCutIL, Init(R, 128)); Insert(ShortcutIL);
ShortCutIL^.SetValidator(New(PFilterValidator,Init(NumberChars+AlphaChars)));
R2.Copy(R); R2.Move(-1,-1);
Insert(New(PLabel, Init(R2, label_codetemplate_shortcut, ShortcutIL)));
R.Move(0,3); R.B.Y:=R.A.Y+8;
New(CodeMemo, Init(R, nil,nil,nil{,4096 does not compile !! }));
Insert(CodeMemo);
R2.Copy(R); R2.Move(-1,-1); R2.B.Y:=R2.A.Y+1;
Insert(New(PLabel, Init(R2, label_codetemplate_content, CodeMemo)));
InsertButtons(@Self);
ShortcutIL^.Select;
end;
function TCodeTemplateDialog.Execute: Word;
var R: word;
S: string;
L: PUnsortedStringCollection;
begin
New(L, Init(10,10));
S:=Template^.GetShortCut;
Template^.GetText(L);
ShortcutIL^.SetData(S);
CodeMemo^.SetContent(L);
R:=inherited Execute;
if R=cmOK then
begin
L^.FreeAll;
ShortcutIL^.GetData(S);
CodeMemo^.GetContent(L);
Template^.SetShortcut(S);
Template^.SetText(L);
end;
Execute:=R;
end;
constructor TCodeTemplatesDialog.Init(ASelMode: boolean;const AShortCut : string);
function B2I(B: boolean; I1,I2: longint): longint;
begin
if B then B2I:=I1 else B2I:=I2;
end;
var R,R2,R3: TRect;
SB: PScrollBar;
begin
R.Assign(0,0,46,20);
inherited Init(R,'Code Templates');
HelpCtx:=hcCodeTemplateOptions;
SelMode:=ASelMode;
GetExtent(R); R.Grow(-3,-2); Inc(R.A.Y); R.B.Y:=R.A.Y+10;
R3.Copy(R); Dec(R.B.X,12);
R2.Copy(R); R2.Move(1,0); R2.A.X:=R2.B.X-1;
New(SB, Init(R2)); Insert(SB);
New(CodeTemplatesLB, Init(R,1,SB));
Insert(CodeTemplatesLB);
if AShortCut<>'' then
begin
If assigned(CodeTemplates) then
CodeTemplates^.Lookup(AShortCut,true,StartIdx)
else
StartIdx:=-1;
end
else
StartIdx:=-1;
R2.Copy(R); R2.Move(0,-1); R2.B.Y:=R2.A.Y+1; Dec(R2.A.X);
Insert(New(PLabel, Init(R2, label_codetemplate_templates, CodeTemplatesLB)));
GetExtent(R); R.Grow(-2,-2); Inc(R.A.Y,12);
R2.Copy(R); R2.Move(1,0); R2.A.X:=R2.B.X-1;
New(SB, Init(R2)); Insert(SB);
New(TemplateViewer, Init(R,nil,SB,nil{,4096 does not compile }));
with TemplateViewer^ do
begin
ReadOnly:=true;
AlwaysShowScrollBars:=true;
end;
Insert(TemplateViewer);
R.Copy(R3); R.A.X:=R.B.X-10; R.B.Y:=R.A.Y+2;
Insert(New(PButton, Init(R, button_OK, cmOK, B2I(SelMode,bfDefault,bfNormal))));
R.Move(0,2);
Insert(New(PButton, Init(R, button_Edit, cmEditItem, B2I(SelMode,bfNormal,bfDefault) )));
R.Move(0,2);
Insert(New(PButton, Init(R, button_New, cmAddItem, bfNormal)));
R.Move(0,2);
Insert(New(PButton, Init(R, button_Delete, cmDeleteItem, bfNormal)));
R.Move(0,2);
Insert(New(PButton, Init(R, button_Cancel, cmCancel, bfNormal)));
SelectNext(false);
end;
procedure TCodeTemplatesDialog.Update;
var C: PUnsortedStringCollection;
begin
if CodeTemplatesLB^.Range=0 then C:=nil else
C:=PCodeTemplate(CodeTemplatesLB^.GetFocusedItem)^.Text;
TemplateViewer^.SetContent(C);
ReDraw;
end;
function TCodeTemplatesDialog.GetSelectedShortCut: string;
var S: string;
begin
if CodeTemplatesLB^.Range=0 then S:='' else
S:=GetStr(PCodeTemplate(CodeTemplatesLB^.GetFocusedItem)^.ShortCut);
GetSelectedShortCut:=S;
end;
procedure TCodeTemplatesDialog.HandleEvent(var Event: TEvent);
var DontClear: boolean;
begin
case Event.What of
evKeyDown :
begin
DontClear:=false;
case Event.KeyCode of
kbIns :
Message(@Self,evCommand,cmAddItem,nil);
kbDel :
Message(@Self,evCommand,cmDeleteItem,nil);
else DontClear:=true;
end;
if DontClear=false then ClearEvent(Event);
end;
evBroadcast :
case Event.Command of
cmListItemSelected :
if Event.InfoPtr=pointer(CodeTemplatesLB) then
Message(@Self,evCommand,cmEditItem,nil);
cmListFocusChanged :
if Event.InfoPtr=pointer(CodeTemplatesLB) then
Message(@Self,evBroadcast,cmUpdate,nil);
cmUpdate :
Update;
end;
evCommand :
begin
DontClear:=false;
case Event.Command of
cmAddItem : Add;
cmDeleteItem : Delete;
cmEditItem : Edit;
else DontClear:=true;
end;
if DontClear=false then ClearEvent(Event);
end;
end;
inherited HandleEvent(Event);
end;
function TCodeTemplatesDialog.Execute: Word;
var R: word;
P: PCodeTemplate;
C: PCodeTemplateCollection;
L: PUnsortedStringCollection;
I: integer;
begin
New(C, Init(10,20));
if Assigned(CodeTemplates) then
for I:=0 to CodeTemplates^.Count-1 do
begin
P:=CodeTemplates^.At(I);
New(L, Init(10,50));
P^.GetText(L);
C^.Insert(New(PCodeTemplate, Init(P^.GetShortCut,L)));
Dispose(L, Done);
end;
CodeTemplatesLB^.NewList(C);
if StartIdx<>-1 then
CodeTemplatesLB^.SetFocusedItem(CodeTemplates^.At(StartIdx));
Update;
R:=inherited Execute;
if R=cmOK then
begin
if Assigned(CodeTemplates) then Dispose(CodeTemplates, Done);
CodeTemplates:=C;
end
else
Dispose(C, Done);
Execute:=R;
end;
procedure TCodeTemplatesDialog.Add;
var P,P2: PCodeTemplate;
IC: boolean;
S: string;
L: PUnsortedStringCollection;
Cmd: word;
CanExit: boolean;
begin
New(L, Init(10,10));
IC:=CodeTemplatesLB^.Range=0;
if IC=false then
begin
P:=CodeTemplatesLB^.List^.At(CodeTemplatesLB^.Focused);
P^.GetParams(S,L);
end
else
begin
S:='';
end;
New(P, Init(S,L));
repeat
Cmd:=Application^.ExecuteDialog(New(PCodeTemplateDialog, Init(dialog_newtemplate,P)), nil);
CanExit:=(Cmd<>cmOK);
if CanExit=false then
begin
P2:=PCodeTemplateCollection(CodeTemplatesLB^.List)^.SearchByShortCut(P^.GetShortCut);
CanExit:=(Assigned(P2)=false);
if CanExit=false then
begin
ClearFormatParams; AddFormatParamStr(P^.GetShortCut);
ErrorBox(msg_codetemplate_alreadyinlist,@FormatParams);
end;
end;
until CanExit;
if Cmd=cmOK then
begin
CodeTemplatesLB^.List^.Insert(P);
CodeTemplatesLB^.SetRange(CodeTemplatesLB^.List^.Count);
CodeTemplatesLB^.SetFocusedItem(P);
Update;
end
else
Dispose(P, Done);
Dispose(L, Done);
end;
procedure TCodeTemplatesDialog.Edit;
var P,O,P2: PCodeTemplate;
I: sw_integer;
S: string;
L: PUnsortedStringCollection;
Cmd: word;
CanExit: boolean;
begin
if CodeTemplatesLB^.Range=0 then Exit;
New(L, Init(10,10));
I:=CodeTemplatesLB^.Focused;
O:=CodeTemplatesLB^.List^.At(I);
O^.GetParams(S,L);
P:=New(PCodeTemplate, Init(S, L));
repeat
Cmd:=Application^.ExecuteDialog(New(PCodeTemplateDialog, Init(dialog_modifytemplate,P)), nil);
CanExit:=(Cmd<>cmOK);
if CanExit=false then
begin
P2:=PCodeTemplateCollection(CodeTemplatesLB^.List)^.SearchByShortCut(P^.GetShortCut);
CanExit:=(Assigned(P2)=false) or (CodeTemplatesLB^.List^.IndexOf(P2)=I);
if CanExit=false then
begin
ClearFormatParams; AddFormatParamStr(P^.GetShortCut);
ErrorBox(msg_codetemplate_alreadyinlist,@FormatParams);
end;
end;
until CanExit;
if Cmd=cmOK then
begin
with CodeTemplatesLB^ do
begin
List^.AtFree(I); O:=nil;
List^.Insert(P);
SetFocusedItem(P);
end;
Update;
end;
Dispose(L, Done);
end;
procedure TCodeTemplatesDialog.Delete;
begin
if CodeTemplatesLB^.Range=0 then Exit;
CodeTemplatesLB^.List^.AtFree(CodeTemplatesLB^.Focused);
CodeTemplatesLB^.SetRange(CodeTemplatesLB^.List^.Count);
Update;
end;
procedure RegisterCodeTemplates;
begin
{$ifndef NOOBJREG}
RegisterType(RCodeTemplate);
RegisterType(RCodeTemplateCollection);
{$endif}
end;
END.