mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-05 08:38:14 +02:00
668 lines
19 KiB
ObjectPascal
668 lines
19 KiB
ObjectPascal
{
|
|
This file is part of the Free Pascal Integrated Development Environment
|
|
Copyright (c) 1998 by Berczi Gabor
|
|
|
|
Code Complete 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 FPCodCmp; { CodeComplete }
|
|
|
|
{$ifdef cpullvm}
|
|
{$modeswitch nestedprocvars}
|
|
{$endif}
|
|
{$H-}
|
|
|
|
interface
|
|
|
|
uses Objects,Drivers,Dialogs,
|
|
WEditor,WUtils,WViews;
|
|
|
|
type
|
|
PCodeCompleteWordList = ^TCodeCompleteWordList;
|
|
TCodeCompleteWordList = object(TTextCollection)
|
|
end;
|
|
|
|
PCodeCompleteDialog = ^TCodeCompleteDialog;
|
|
TCodeCompleteDialog = object(TCenterDialog)
|
|
constructor Init;
|
|
function Execute: Word; virtual;
|
|
procedure HandleEvent(var Event: TEvent); virtual;
|
|
private
|
|
CodeCompleteLB : PAdvancedListBox;
|
|
RB : PRadioButtons;
|
|
CB : PCheckBoxes;
|
|
MinInputL,InputL : PEditorInputLine;
|
|
procedure Add;
|
|
procedure Edit;
|
|
procedure Delete;
|
|
end;
|
|
|
|
function FPCompleteCodeWord(const WordS: string; var Text: string): boolean;
|
|
|
|
procedure InitCodeComplete;
|
|
function LoadCodeComplete(var S: TStream): boolean;
|
|
procedure AddStandardUnitsToCodeComplete;
|
|
procedure AddAvailableUnitsToCodeComplete(OnlyStandard : boolean);
|
|
function StoreCodeComplete(var S: TStream): boolean;
|
|
procedure DoneCodeComplete;
|
|
|
|
const CodeCompleteWords : PCodeCompleteWordList = nil;
|
|
type
|
|
TCodeCompleteCase = (ccc_unchanged, ccc_lower, ccc_upper, ccc_mixed);
|
|
const
|
|
CodeCompleteCase : TCodeCompleteCase = ccc_unchanged;
|
|
UnitsCodeCompleteWords : PCodeCompleteWordList = nil;
|
|
|
|
procedure RegisterCodeComplete;
|
|
|
|
implementation
|
|
|
|
uses App,Views,MsgBox,Validate,
|
|
FVConsts,
|
|
systems, BrowCol,
|
|
FPSwitch, FPCompil,
|
|
FPVars, FPSymbol,
|
|
FPConst,FPViews;
|
|
|
|
{$ifndef NOOBJREG}
|
|
const
|
|
RCodeCompleteWordList: TStreamRec = (
|
|
ObjType: 14401;
|
|
VmtLink: Ofs(TypeOf(TCodeCompleteWordList)^);
|
|
Load: @TCodeCompleteWordList.Load;
|
|
Store: @TCodeCompleteWordList.Store
|
|
);
|
|
{$endif}
|
|
|
|
{$ifdef useresstrings}
|
|
resourcestring
|
|
{$else}
|
|
const
|
|
{$endif}
|
|
{ CodeComplete dialog }
|
|
dialog_codecomplete = 'CodeComplete';
|
|
label_codecomplete_keywords = '~K~eywords';
|
|
|
|
dialog_codecomplete_add = 'Add new keyword';
|
|
label_codecomplete_add_keyword = 'Keyword';
|
|
|
|
dialog_codecomplete_edit = 'Edit keyword';
|
|
label_codecomplete_edit_keyword = 'Keyword';
|
|
|
|
msg_codecomplete_alreadyinlist = '"%s" is already in the list';
|
|
|
|
{ standard button texts }
|
|
button_OK = 'O~K~';
|
|
button_Cancel = 'Cancel';
|
|
button_New = '~N~ew';
|
|
button_Edit = '~E~dit';
|
|
button_Delete = '~D~elete';
|
|
|
|
function FPCompleteCodeWord(const WordS: string; var Text: string): boolean;
|
|
var OK: boolean;
|
|
CIndex, Index, i : sw_integer;
|
|
St, UpWordS : string;
|
|
begin
|
|
if ShowOnlyUnique then
|
|
UpWordS:=UpCaseStr(WordS);
|
|
OK:=Assigned(CodeCompleteWords);
|
|
if OK then
|
|
begin
|
|
Text:=CodeCompleteWords^.Lookup(WordS,CIndex);
|
|
OK:=(CIndex<>-1) and (length(Text)<>length(WordS));
|
|
Index:=-1;
|
|
if OK and ShowOnlyUnique and (CIndex<CodeCompleteWords^.Count-1) then
|
|
begin
|
|
St:=PString(CodeCompleteWords^.At(CIndex+1))^;
|
|
if (UpCaseStr(Copy(St,1,length(WordS)))=UpWordS) then
|
|
begin
|
|
{if UpCase(st[Length(UpWordS)+1])<>Upcase(Text[Length(UpWordS)+1]) then}
|
|
begin
|
|
Text:='';
|
|
FPCompleteCodeWord:=false;
|
|
exit;
|
|
(* end
|
|
else
|
|
{ only give the common part }
|
|
begin
|
|
i:=Length(UpWordS)+1;
|
|
while (i<=length(st)) and (i<=length(text)) and (UpCase(st[i])=Upcase(Text[i])) do
|
|
inc(i);
|
|
SetLength(Text,i-1); *)
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
if (ShowOnlyUnique or not OK) and Assigned(UnitsCodeCompleteWords) then
|
|
begin
|
|
Text:=UnitsCodeCompleteWords^.Lookup(WordS,Index);
|
|
OK:=(Index<>-1) and (length(Text)<>length(WordS));
|
|
if ShowOnlyUnique and (Index<UnitsCodeCompleteWords^.Count-1) then
|
|
begin
|
|
St:=PString(UnitsCodeCompleteWords^.At(Index+1))^;
|
|
if UpCaseStr(Copy(St,1,length(WordS)))=UpWordS then
|
|
begin
|
|
{if UpCase(st[Length(UpWordS)+1])<>Upcase(Text[Length(UpWordS)+1]) then}
|
|
begin
|
|
Text:='';
|
|
FPCompleteCodeWord:=false;
|
|
exit;
|
|
(* end
|
|
else
|
|
{ only give the common part }
|
|
begin
|
|
i:=Length(UpWordS)+1;
|
|
while (i<=length(st)) and (i<=length(text)) and (UpCase(st[i])=Upcase(Text[i])) do
|
|
inc(i);
|
|
SetLength(Text,i-1); *)
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
if ShowOnlyUnique and (Index<>-1) and (CIndex<>-1) then
|
|
begin
|
|
{St:=PString(CodeCompleteWords^.At(CIndex+1))^;
|
|
Was wrong, CIndex+1 could be above count => collection.error
|
|
generated RTE 213
|
|
if UpCase(st[Length(UpWordS)+1])<>Upcase(Text[Length(UpWordS)+1]) then}
|
|
begin
|
|
Text:='';
|
|
FPCompleteCodeWord:=false;
|
|
exit;
|
|
(* end
|
|
else
|
|
{ only give the common part }
|
|
begin
|
|
i:=Length(UpWordS)+1;
|
|
while (i<=length(st)) and (i<=length(text)) and (UpCase(st[i])=Upcase(Text[i])) do
|
|
inc(i);
|
|
SetLength(Text,i-1); *)
|
|
end;
|
|
end;
|
|
if OK=false then Text:=''
|
|
else case CodeCompleteCase of
|
|
ccc_upper : Text:=UpcaseStr(Text);
|
|
ccc_lower : Text:=LowcaseStr(Text);
|
|
ccc_mixed : Text:=UpCase(Text[1])+LowCaseStr(Copy(Text,2,High(Text)));
|
|
end;
|
|
FPCompleteCodeWord:=OK;
|
|
end;
|
|
|
|
procedure InitCodeComplete;
|
|
var I:integer;
|
|
S: string;
|
|
begin
|
|
if Assigned(CodeCompleteWords) then
|
|
Dispose(CodeCompleteWords, Done);
|
|
New(CodeCompleteWords, Init(10,10));
|
|
for I:=0 to GetReservedWordCount-1 do
|
|
begin
|
|
S:=LowCaseStr(GetReservedWord(I));
|
|
if length(S)>=CodeCompleteMinLen then
|
|
CodeCompleteWords^.Insert(NewStr(S));
|
|
end;
|
|
{
|
|
there should be also a user front-end for customizing CodeComplete !
|
|
any volunteers to implement? ;) - Gabor
|
|
}
|
|
end;
|
|
|
|
|
|
procedure AddAvailableUnitsToCodeComplete(OnlyStandard : boolean);
|
|
|
|
var
|
|
I : sw_integer;
|
|
Overflow: boolean;
|
|
Level : longint;
|
|
UpStandardUnits : string;
|
|
|
|
procedure InsertInS(P: PSymbol);
|
|
|
|
procedure InsertItemsInS(P: PSymbolCollection);
|
|
var I: Sw_integer;
|
|
begin
|
|
for I:=0 to P^.Count-1 do
|
|
InsertInS(P^.At(I));
|
|
end;
|
|
Var
|
|
st : string;
|
|
CIndex : sw_integer;
|
|
begin
|
|
Inc(level);
|
|
if UnitsCodeCompleteWords^.Count=MaxCollectionSize then
|
|
begin Overflow:=true; Exit; end;
|
|
st:=P^.GetName;
|
|
if Length(st)>=CodeCompleteMinLen then
|
|
if not ((level=1) and OnlyStandard and (st=UpCaseStr(CodeCompleteUnitName))) then
|
|
begin
|
|
st:=Lowcasestr(st);
|
|
UnitsCodeCompleteWords^.LookUp(st,CIndex);
|
|
if CIndex<>-1 then
|
|
UnitsCodeCompleteWords^.Insert(NewStr(st));
|
|
end;
|
|
{ this is wrong because it inserted args or locals of proc
|
|
in the globals list !! PM}
|
|
if (P^.Items<>nil) and (level=1) and
|
|
((not OnlyStandard or (Pos(P^.GetName+',',UpStandardUnits)>0) or
|
|
{ don't exclude system unit ... }
|
|
(Pos('SYS',P^.GetName)>0))) then
|
|
InsertItemsInS(P^.Items);
|
|
Dec(level);
|
|
end;
|
|
|
|
begin
|
|
if OnlyStandard then
|
|
UpStandardunits:=UpCaseStr(StandardUnits)+',';
|
|
if IsSymbolInfoAvailable then
|
|
begin
|
|
if Assigned(UnitsCodeCompleteWords) then
|
|
begin
|
|
Dispose(UnitsCodeCompleteWords,done);
|
|
UnitsCodeCompleteWords:=nil;
|
|
end;
|
|
|
|
New(UnitsCodeCompleteWords, Init(10,10));
|
|
level:=0;
|
|
Overflow:=false;
|
|
BrowCol.Modules^.ForEach(TCallbackProcParam(@InsertInS));
|
|
{ if Overflow then
|
|
WarningBox(msg_toomanysymbolscantdisplayall,nil); }
|
|
end;
|
|
end;
|
|
|
|
procedure AddStandardUnitsToCodeComplete;
|
|
var
|
|
HiddenSource : PSourceWindow;
|
|
R : TRect;
|
|
StoreBrowserSwitchesConfig : string;
|
|
begin
|
|
Desktop^.GetExtent(R);
|
|
New(HiddenSource,init(R,'*'));
|
|
HiddenSource^.NoNameCount:=0;
|
|
HiddenSource^.UpdateTitle;
|
|
HiddenSource^.Hide;
|
|
CompilingHiddenFile:=HiddenSource;
|
|
{ compile a dummy file to get symbol info }
|
|
with HiddenSource^.Editor^ do
|
|
begin
|
|
FileName:=CodeCompleteUnitName+'.pp';
|
|
Addline('unit '+CodeCompleteUnitName+';');
|
|
Addline('interface');
|
|
if StandardUnits<>'' then
|
|
begin
|
|
AddLine('uses');
|
|
Addline(StandardUnits);
|
|
Addline(' ;');
|
|
end;
|
|
Addline('implementation');
|
|
Addline('end.');
|
|
SetModified(true);
|
|
// SaveFile;
|
|
end;
|
|
StoreBrowserSwitchesConfig:=BrowserSwitches^.GetCurrSelParam;
|
|
BrowserSwitches^.ReadItemsCfg('+');
|
|
DoCompile(cCompile);
|
|
BrowserSwitches^.SetCurrSelParam(StoreBrowserSwitchesConfig);
|
|
AddAvailableUnitsToCodeComplete(true);
|
|
{ Now add the interface declarations to the Code Complete list }
|
|
CompilingHiddenFile:=nil;
|
|
Dispose(HiddenSource,Done);
|
|
end;
|
|
|
|
function LoadCodeComplete(var S: TStream): boolean;
|
|
var C: PCodeCompleteWordList;
|
|
OK: boolean;
|
|
NewCodeCompleteMinLen : byte;
|
|
NewUseStandardUnitsInCodeComplete,
|
|
NewUseAllUnitsInCodeComplete,
|
|
NewShowOnlyUnique : boolean;
|
|
NewCodeCompleteCase : TCodeCompleteCase;
|
|
StPtr : PString;
|
|
begin
|
|
New(C, Load(S));
|
|
OK:=Assigned(C) and (S.Status=stOk);
|
|
if OK then
|
|
begin
|
|
if Assigned(CodeCompleteWords) then Dispose(CodeCompleteWords, Done);
|
|
CodeCompleteWords:=C;
|
|
S.Read(NewCodeCompleteCase,Sizeof(TCodeCompleteCase));
|
|
OK:=(S.Status=stOk);
|
|
if OK then
|
|
CodeCompleteCase:=NewCodeCompleteCase;
|
|
{ Old version of Code complete, also OK PM }
|
|
if not OK or (S.getPos=S.getSize) then
|
|
begin
|
|
LoadCodeComplete:=OK;
|
|
exit;
|
|
end;
|
|
|
|
if S.Status=stOK then
|
|
S.Read(NewUseStandardUnitsInCodeComplete,Sizeof(UseStandardUnitsInCodeComplete));
|
|
if S.Status=stOK then
|
|
UseStandardUnitsInCodeComplete:=NewUseStandardUnitsInCodeComplete;
|
|
if S.Status=stOK then
|
|
S.Read(NewUseAllUnitsInCodeComplete,Sizeof(UseAllUnitsInCodeComplete));
|
|
if S.Status=stOK then
|
|
UseAllUnitsInCodeComplete:=NewUseAllUnitsInCodeComplete;
|
|
if S.Status=stOK then
|
|
S.Read(NewShowOnlyUnique,Sizeof(ShowOnlyUnique));
|
|
if S.Status=stOK then
|
|
ShowOnlyUnique:=NewShowOnlyUnique;
|
|
if S.Status=stOK then
|
|
S.Read(NewCodeCompleteMinLen,Sizeof(CodeCompleteMinLen));
|
|
if S.Status=stOK then
|
|
CodeCompleteMinLen:=NewCodeCompleteMinLen;
|
|
if S.Status=stOK then
|
|
StPtr:=S.ReadStr
|
|
else
|
|
StPtr:=nil;
|
|
if (S.Status=stOK) then
|
|
StandardUnits:=GetStr(StPtr);
|
|
if assigned(StPtr) then
|
|
FreeMem(StPtr,Length(StandardUnits)+1);
|
|
OK:=S.Status=stOK;
|
|
end
|
|
else
|
|
if Assigned(C) then
|
|
Dispose(C, Done);
|
|
LoadCodeComplete:=OK;
|
|
end;
|
|
|
|
function StoreCodeComplete(var S: TStream): boolean;
|
|
var OK: boolean;
|
|
begin
|
|
OK:=Assigned(CodeCompleteWords);
|
|
if OK then
|
|
begin
|
|
CodeCompleteWords^.Store(S);
|
|
S.Write(CodeCompleteCase,Sizeof(TCodeCompleteCase));
|
|
{ New fields added }
|
|
S.Write(UseStandardUnitsInCodeComplete,Sizeof(UseStandardUnitsInCodeComplete));
|
|
S.Write(UseAllUnitsInCodeComplete,Sizeof(UseAllUnitsInCodeComplete));
|
|
S.Write(ShowOnlyUnique,Sizeof(ShowOnlyUnique));
|
|
S.Write(CodeCompleteMinLen,Sizeof(CodeCompleteMinLen));
|
|
S.WriteStr(@StandardUnits);
|
|
OK:=OK and (S.Status=stOK);
|
|
end;
|
|
StoreCodeComplete:=OK;
|
|
end;
|
|
|
|
procedure DoneCodeComplete;
|
|
begin
|
|
if Assigned(CodeCompleteWords) then
|
|
begin
|
|
Dispose(CodeCompleteWords, Done);
|
|
CodeCompleteWords:=nil;
|
|
end;
|
|
if Assigned(UnitsCodeCompleteWords) then
|
|
begin
|
|
Dispose(UnitsCodeCompleteWords,done);
|
|
UnitsCodeCompleteWords:=nil;
|
|
end;
|
|
end;
|
|
|
|
constructor TCodeCompleteDialog.Init;
|
|
var R,R2,R3: TRect;
|
|
Items: PSItem;
|
|
SB: PScrollBar;
|
|
begin
|
|
R.Assign(0,0,50,22);
|
|
inherited Init(R,dialog_codecomplete);
|
|
HelpCtx:=hcCodeCompleteOptions;
|
|
|
|
{ name list dialog }
|
|
GetExtent(R); R.Grow(-3,-2); Inc(R.A.Y); R3.Copy(R); Dec(R.B.X,12);
|
|
Dec(R.B.Y,7);
|
|
R2.Copy(R); R2.Move(1,0); R2.A.X:=R2.B.X-1;
|
|
New(SB, Init(R2)); Insert(SB);
|
|
New(CodeCompleteLB, Init(R,1,SB));
|
|
Insert(CodeCompleteLB);
|
|
R2.Copy(R); R2.Move(0,-1); R2.B.Y:=R2.A.Y+1; Dec(R2.A.X);
|
|
Insert(New(PLabel, Init(R2, label_codecomplete_keywords, CodeCompleteLB)));
|
|
|
|
{ Case choice }
|
|
R.Copy(R3); Dec(R.B.Y,2); R.A.Y:=R.B.Y-4; Inc(R.A.X); R.B.X:=R.A.X+15;
|
|
Items:=NewSItem('Unc~h~anged',
|
|
NewSItem('~L~ower',
|
|
NewSItem('~U~pper',
|
|
NewSItem('~M~ixed',nil))));
|
|
RB:=New(PRadioButtons,Init(R,Items));
|
|
RB^.SetData(ord(CodeCompleteCase));
|
|
R2.Copy(R); R2.Move(0,-1); R2.B.Y:=R2.A.Y+1; Dec(R2.A.X);
|
|
Insert(New(PLabel, Init(R2, 'Case handling', RB)));
|
|
Insert(RB);
|
|
|
|
{ Mininum length inputline }
|
|
R.Copy(R3); R.A.Y:=R.B.Y-7;R.B.Y:=R.A.Y+1; Dec(R.B.X); R.A.X:=R.B.X -5;
|
|
New(MinInputL, Init(R,5));
|
|
MinInputL^.SetValidator(New(PRangeValidator, Init(1,255)));
|
|
Insert(MinInputL);
|
|
R2.Copy(R); R2.A.X:=20;Dec(R2.B.X,5);
|
|
Insert(New(PLabel, Init(R2, 'Min. length', MinInputL)));
|
|
|
|
{ Standard/all units booleans }
|
|
Items:=nil;
|
|
Items:=NewSItem('Add standard units', Items);
|
|
Items:=NewSItem('Add all units', Items);
|
|
Items:=NewSItem('Show only unique', Items);
|
|
R.Copy(R3); R.A.Y:=R.B.Y-5;R.B.Y:=R.A.Y+3; Inc(R.A.X,18); Dec(R.B.X);
|
|
New(CB, Init(R, Items));
|
|
Insert(CB);
|
|
R2.Copy(R); R2.Move(0,-1); R2.B.Y:=R2.A.Y+1; Dec(R2.A.X);
|
|
Insert(New(PLabel, Init(R2, 'Unit handling', CB)));
|
|
R2.Copy(R); R2.Move(0,-1); R2.B.Y:=R2.A.Y+1;
|
|
If ShowOnlyUnique then
|
|
CB^.Press(0);
|
|
If UseAllUnitsInCodeComplete then
|
|
CB^.Press(1);
|
|
If UseStandardUnitsInCodeComplete then
|
|
CB^.Press(2);
|
|
|
|
{ Standard unit name boolean }
|
|
R.Copy(R3); R.A.Y:=R.B.Y-1; Inc(R.A.X); Dec(R.B.X);
|
|
New(InputL,Init(R,255));
|
|
Insert(InputL);
|
|
InputL^.SetValidator(New(PFilterValidator,Init(NumberChars+AlphaChars+[','])));
|
|
R2.Copy(R); R2.Move(0,-1); R2.B.Y:=R2.A.Y+1; Dec(R2.A.X);R2.B.X:=R2.A.X+25;
|
|
Insert(New(PLabel, Init(R2, '~S~tandard unit list', InputL)));
|
|
|
|
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, bfNormal)));
|
|
R.Move(0,2);
|
|
Insert(New(PButton, Init(R, button_Edit, cmEditItem, 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 TCodeCompleteDialog.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(CodeCompleteLB) then
|
|
Message(@Self,evCommand,cmEditItem,nil);
|
|
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 TCodeCompleteDialog.Execute: Word;
|
|
var R: word;
|
|
C: PCodeCompleteWordList;
|
|
NewVal, I: integer;
|
|
NewValStr : string;
|
|
begin
|
|
New(C, Init(10,20));
|
|
if Assigned(CodeCompleteWords) then
|
|
for I:=0 to CodeCompleteWords^.Count-1 do
|
|
C^.Insert(NewStr(GetStr(CodeCompleteWords^.At(I))));
|
|
CodeCompleteLB^.NewList(C);
|
|
InputL^.SetData(StandardUnits);
|
|
NewValStr:=IntToStr(CodeCompleteMinLen);
|
|
MinInputL^.SetData(NewValStr);
|
|
R:=inherited Execute;
|
|
if R=cmOK then
|
|
begin
|
|
if Assigned(CodeCompleteWords) then Dispose(CodeCompleteWords, Done);
|
|
CodeCompleteWords:=C;
|
|
CodeCompleteCase:=TCodeCompleteCase(RB^.Value);
|
|
MinInputL^.GetData(NewValStr);
|
|
NewVal:=StrToInt(NewValStr);
|
|
if (NewVal>0) and (NewVal<>CodeCompleteMinLen) then
|
|
begin
|
|
CodeCompleteMinLen:=NewVal;
|
|
InitCodeComplete;
|
|
end;
|
|
ShowOnlyUnique:=CB^.Mark(0);
|
|
UseAllUnitsInCodeComplete:=CB^.Mark(1);
|
|
UseStandardUnitsInCodeComplete:=CB^.Mark(2);
|
|
if UseStandardUnitsInCodeComplete and (not UseAllUnitsInCodeComplete or not assigned(UnitsCodeCompleteWords)) and
|
|
((StandardUnits<>GetStr(InputL^.Data)) or not assigned(UnitsCodeCompleteWords)) then
|
|
begin
|
|
InputL^.GetData(StandardUnits);
|
|
AddStandardUnitsToCodeComplete;
|
|
end
|
|
else
|
|
InputL^.GetData(StandardUnits);
|
|
end
|
|
else
|
|
Dispose(C, Done);
|
|
Execute:=R;
|
|
end;
|
|
|
|
procedure TCodeCompleteDialog.Add;
|
|
var IC: boolean;
|
|
S: string;
|
|
P: PString;
|
|
Cmd: word;
|
|
CanExit: boolean;
|
|
I: sw_integer;
|
|
begin
|
|
IC:=CodeCompleteLB^.Range=0;
|
|
if IC=false then
|
|
S:=GetStr(CodeCompleteLB^.List^.At(CodeCompleteLB^.Focused))
|
|
else
|
|
S:='';
|
|
|
|
repeat
|
|
Cmd:=InputBox(dialog_codecomplete_add,label_codecomplete_add_keyword,S,255);
|
|
CanExit:=Cmd<>cmOK;
|
|
if CanExit=false then
|
|
begin
|
|
CanExit:=PCodeCompleteWordList(CodeCompleteLB^.List)^.Search(@S,I)=false;
|
|
if CanExit=false then
|
|
begin
|
|
ClearFormatParams; AddFormatParamStr(S);
|
|
ErrorBox(msg_codecomplete_alreadyinlist,@FormatParams);
|
|
end;
|
|
end;
|
|
until CanExit;
|
|
|
|
if Cmd=cmOK then
|
|
begin
|
|
P:=NewStr(S);
|
|
with CodeCompleteLB^ do
|
|
begin
|
|
List^.Insert(P);
|
|
SetRange(List^.Count);
|
|
SetFocusedItem(P);
|
|
end;
|
|
ReDraw;
|
|
end;
|
|
end;
|
|
|
|
procedure TCodeCompleteDialog.Edit;
|
|
var S: string;
|
|
I,T: sw_integer;
|
|
Cmd: word;
|
|
CanExit: boolean;
|
|
P: PString;
|
|
begin
|
|
if CodeCompleteLB^.Range=0 then Exit;
|
|
I:=CodeCompleteLB^.Focused;
|
|
S:=GetStr(CodeCompleteLB^.List^.At(I));
|
|
repeat
|
|
Cmd:=InputBox(dialog_codecomplete_edit,label_codecomplete_edit_keyword,S,255);
|
|
CanExit:=Cmd<>cmOK;
|
|
if CanExit=false then
|
|
begin
|
|
CanExit:=PCodeCompleteWordList(CodeCompleteLB^.List)^.Search(@S,T)=false;
|
|
CanExit:=CanExit or (T=I);
|
|
if CanExit=false then
|
|
begin
|
|
ClearFormatParams; AddFormatParamStr(S);
|
|
ErrorBox(msg_codecomplete_alreadyinlist,@FormatParams);
|
|
end;
|
|
end;
|
|
until CanExit;
|
|
|
|
if Cmd=cmOK then
|
|
begin
|
|
P:=NewStr(S);
|
|
with CodeCompleteLB^ do
|
|
begin
|
|
List^.AtFree(I);
|
|
List^.Insert(P);
|
|
SetFocusedItem(P);
|
|
end;
|
|
ReDraw;
|
|
end;
|
|
end;
|
|
|
|
procedure TCodeCompleteDialog.Delete;
|
|
begin
|
|
if CodeCompleteLB^.Range=0 then Exit;
|
|
CodeCompleteLB^.List^.AtFree(CodeCompleteLB^.Focused);
|
|
CodeCompleteLB^.SetRange(CodeCompleteLB^.List^.Count);
|
|
ReDraw;
|
|
end;
|
|
|
|
procedure RegisterCodeComplete;
|
|
begin
|
|
{$ifndef NOOBJREG}
|
|
RegisterType(RCodeCompleteWordList);
|
|
{$endif}
|
|
end;
|
|
|
|
END.
|