fpcodcmp.pas 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  1. {
  2. This file is part of the Free Pascal Integrated Development Environment
  3. Copyright (c) 1998 by Berczi Gabor
  4. Code Complete routines
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. unit FPCodCmp; { CodeComplete }
  12. interface
  13. uses Objects,Drivers,Dialogs,
  14. WEditor,WUtils,WViews;
  15. type
  16. PCodeCompleteWordList = ^TCodeCompleteWordList;
  17. TCodeCompleteWordList = object(TTextCollection)
  18. end;
  19. PCodeCompleteDialog = ^TCodeCompleteDialog;
  20. TCodeCompleteDialog = object(TCenterDialog)
  21. constructor Init;
  22. function Execute: Word; virtual;
  23. procedure HandleEvent(var Event: TEvent); virtual;
  24. private
  25. CodeCompleteLB : PAdvancedListBox;
  26. RB : PRadioButtons;
  27. CB : PCheckBoxes;
  28. MinInputL,InputL : PEditorInputLine;
  29. procedure Add;
  30. procedure Edit;
  31. procedure Delete;
  32. end;
  33. function FPCompleteCodeWord(const WordS: string; var Text: string): boolean;
  34. procedure InitCodeComplete;
  35. function LoadCodeComplete(var S: TStream): boolean;
  36. procedure AddStandardUnitsToCodeComplete;
  37. procedure AddAvailableUnitsToCodeComplete(OnlyStandard : boolean);
  38. function StoreCodeComplete(var S: TStream): boolean;
  39. procedure DoneCodeComplete;
  40. const CodeCompleteWords : PCodeCompleteWordList = nil;
  41. type
  42. TCodeCompleteCase = (ccc_unchanged, ccc_lower, ccc_upper, ccc_mixed);
  43. const
  44. CodeCompleteCase : TCodeCompleteCase = ccc_unchanged;
  45. UnitsCodeCompleteWords : PCodeCompleteWordList = nil;
  46. procedure RegisterCodeComplete;
  47. implementation
  48. uses App,Views,MsgBox,Validate,
  49. FVConsts,
  50. systems, BrowCol,
  51. FPSwitch, FPCompil,
  52. FPVars, FPSymbol,
  53. FPConst,FPString,FPViews;
  54. {$ifndef NOOBJREG}
  55. const
  56. RCodeCompleteWordList: TStreamRec = (
  57. ObjType: 14401;
  58. VmtLink: Ofs(TypeOf(TCodeCompleteWordList)^);
  59. Load: @TCodeCompleteWordList.Load;
  60. Store: @TCodeCompleteWordList.Store
  61. );
  62. {$endif}
  63. function FPCompleteCodeWord(const WordS: string; var Text: string): boolean;
  64. var OK: boolean;
  65. CIndex, Index, i : sw_integer;
  66. St, UpWordS : string;
  67. begin
  68. if ShowOnlyUnique then
  69. UpWordS:=UpCaseStr(WordS);
  70. OK:=Assigned(CodeCompleteWords);
  71. if OK then
  72. begin
  73. Text:=CodeCompleteWords^.Lookup(WordS,CIndex);
  74. OK:=(CIndex<>-1) and (length(Text)<>length(WordS));
  75. Index:=-1;
  76. if OK and ShowOnlyUnique and (CIndex<CodeCompleteWords^.Count-1) then
  77. begin
  78. St:=PString(CodeCompleteWords^.At(CIndex+1))^;
  79. if (UpCaseStr(Copy(St,1,length(WordS)))=UpWordS) then
  80. begin
  81. {if UpCase(st[Length(UpWordS)+1])<>Upcase(Text[Length(UpWordS)+1]) then}
  82. begin
  83. Text:='';
  84. FPCompleteCodeWord:=false;
  85. exit;
  86. (* end
  87. else
  88. { only give the common part }
  89. begin
  90. i:=Length(UpWordS)+1;
  91. while (i<=length(st)) and (i<=length(text)) and (UpCase(st[i])=Upcase(Text[i])) do
  92. inc(i);
  93. SetLength(Text,i-1); *)
  94. end;
  95. end;
  96. end;
  97. end;
  98. if (ShowOnlyUnique or not OK) and Assigned(UnitsCodeCompleteWords) then
  99. begin
  100. Text:=UnitsCodeCompleteWords^.Lookup(WordS,Index);
  101. OK:=(Index<>-1) and (length(Text)<>length(WordS));
  102. if ShowOnlyUnique and (Index<UnitsCodeCompleteWords^.Count-1) then
  103. begin
  104. St:=PString(UnitsCodeCompleteWords^.At(Index+1))^;
  105. if UpCaseStr(Copy(St,1,length(WordS)))=UpWordS then
  106. begin
  107. {if UpCase(st[Length(UpWordS)+1])<>Upcase(Text[Length(UpWordS)+1]) then}
  108. begin
  109. Text:='';
  110. FPCompleteCodeWord:=false;
  111. exit;
  112. (* end
  113. else
  114. { only give the common part }
  115. begin
  116. i:=Length(UpWordS)+1;
  117. while (i<=length(st)) and (i<=length(text)) and (UpCase(st[i])=Upcase(Text[i])) do
  118. inc(i);
  119. SetLength(Text,i-1); *)
  120. end;
  121. end;
  122. end;
  123. end;
  124. if ShowOnlyUnique and (Index<>-1) and (CIndex<>-1) then
  125. begin
  126. {St:=PString(CodeCompleteWords^.At(CIndex+1))^;
  127. Was wrong, CIndex+1 could be above count => collection.error
  128. generated RTE 213
  129. if UpCase(st[Length(UpWordS)+1])<>Upcase(Text[Length(UpWordS)+1]) then}
  130. begin
  131. Text:='';
  132. FPCompleteCodeWord:=false;
  133. exit;
  134. (* end
  135. else
  136. { only give the common part }
  137. begin
  138. i:=Length(UpWordS)+1;
  139. while (i<=length(st)) and (i<=length(text)) and (UpCase(st[i])=Upcase(Text[i])) do
  140. inc(i);
  141. SetLength(Text,i-1); *)
  142. end;
  143. end;
  144. if OK=false then Text:=''
  145. else case CodeCompleteCase of
  146. ccc_upper : Text:=UpcaseStr(Text);
  147. ccc_lower : Text:=LowcaseStr(Text);
  148. ccc_mixed : Text:=UpCase(Text[1])+LowCaseStr(Copy(Text,2,High(Text)));
  149. end;
  150. FPCompleteCodeWord:=OK;
  151. end;
  152. procedure InitCodeComplete;
  153. var I:integer;
  154. S: string;
  155. begin
  156. if Assigned(CodeCompleteWords) then
  157. Dispose(CodeCompleteWords, Done);
  158. New(CodeCompleteWords, Init(10,10));
  159. for I:=0 to GetReservedWordCount-1 do
  160. begin
  161. S:=LowCaseStr(GetReservedWord(I));
  162. if length(S)>=CodeCompleteMinLen then
  163. CodeCompleteWords^.Insert(NewStr(S));
  164. end;
  165. {
  166. there should be also a user front-end for customizing CodeComplete !
  167. any volunteers to implement? ;) - Gabor
  168. }
  169. end;
  170. procedure AddAvailableUnitsToCodeComplete(OnlyStandard : boolean);
  171. var
  172. I : sw_integer;
  173. Overflow: boolean;
  174. Level : longint;
  175. UpStandardUnits : string;
  176. procedure InsertInS(P: PSymbol); {$ifndef FPC}far;{$endif}
  177. procedure InsertItemsInS(P: PSymbolCollection);
  178. var I: Sw_integer;
  179. begin
  180. for I:=0 to P^.Count-1 do
  181. InsertInS(P^.At(I));
  182. end;
  183. Var
  184. st : string;
  185. begin
  186. Inc(level);
  187. if UnitsCodeCompleteWords^.Count=MaxCollectionSize then
  188. begin Overflow:=true; Exit; end;
  189. st:=P^.GetName;
  190. if Length(st)>=CodeCompleteMinLen then
  191. if not ((level=1) and OnlyStandard and (st=UpCaseStr(CodeCompleteUnitName))) then
  192. UnitsCodeCompleteWords^.Insert(NewStr(Lowcasestr(st)));
  193. { this is wrong because it inserted args or locals of proc
  194. in the globals list !! PM}
  195. if (P^.Items<>nil) and (level=1) and
  196. ((not OnlyStandard or (Pos(P^.GetName+',',UpStandardUnits)>0) or
  197. { don't exclude system unit ... }
  198. (Pos('SYS',P^.GetName)>0))) then
  199. InsertItemsInS(P^.Items);
  200. Dec(level);
  201. end;
  202. begin
  203. if OnlyStandard then
  204. UpStandardunits:=UpCaseStr(StandardUnits)+',';
  205. if IsSymbolInfoAvailable then
  206. begin
  207. if Assigned(UnitsCodeCompleteWords) then
  208. begin
  209. Dispose(UnitsCodeCompleteWords,done);
  210. UnitsCodeCompleteWords:=nil;
  211. end;
  212. New(UnitsCodeCompleteWords, Init(10,10));
  213. level:=0;
  214. Overflow:=false;
  215. BrowCol.Modules^.ForEach(@InsertInS);
  216. { if Overflow then
  217. WarningBox(msg_toomanysymbolscantdisplayall,nil); }
  218. end;
  219. end;
  220. procedure AddStandardUnitsToCodeComplete;
  221. var
  222. HiddenSource : PSourceWindow;
  223. R : TRect;
  224. StoreBrowserSwitchesConfig : string;
  225. begin
  226. Desktop^.GetExtent(R);
  227. New(HiddenSource,init(R,'*'));
  228. HiddenSource^.NoNameCount:=0;
  229. HiddenSource^.UpdateTitle;
  230. HiddenSource^.Hide;
  231. CompilingHiddenFile:=HiddenSource;
  232. { compile a dummy file to get symbol info }
  233. with HiddenSource^.Editor^ do
  234. begin
  235. FileName:=CodeCompleteUnitName+'.pp';
  236. Addline('unit '+CodeCompleteUnitName+';');
  237. Addline('interface');
  238. if StandardUnits<>'' then
  239. begin
  240. AddLine('uses');
  241. Addline(StandardUnits);
  242. Addline(' ;');
  243. end;
  244. Addline('implementation');
  245. Addline('end.');
  246. SetModified(true);
  247. // SaveFile;
  248. end;
  249. StoreBrowserSwitchesConfig:=BrowserSwitches^.GetCurrSelParam;
  250. BrowserSwitches^.ReadItemsCfg('+');
  251. DoCompile(cCompile);
  252. BrowserSwitches^.SetCurrSelParam(StoreBrowserSwitchesConfig);
  253. AddAvailableUnitsToCodeComplete(true);
  254. { Now add the interface declarations to the Code Complete list }
  255. CompilingHiddenFile:=nil;
  256. Dispose(HiddenSource,Done);
  257. end;
  258. function LoadCodeComplete(var S: TStream): boolean;
  259. var C: PCodeCompleteWordList;
  260. OK: boolean;
  261. NewCodeCompleteMinLen : byte;
  262. NewUseStandardUnitsInCodeComplete,
  263. NewUseAllUnitsInCodeComplete,
  264. NewShowOnlyUnique : boolean;
  265. NewCodeCompleteCase : TCodeCompleteCase;
  266. StPtr : PString;
  267. begin
  268. New(C, Load(S));
  269. OK:=Assigned(C) and (S.Status=stOk);
  270. if OK then
  271. begin
  272. if Assigned(CodeCompleteWords) then Dispose(CodeCompleteWords, Done);
  273. CodeCompleteWords:=C;
  274. S.Read(NewCodeCompleteCase,Sizeof(TCodeCompleteCase));
  275. OK:=(S.Status=stOk);
  276. if OK then
  277. CodeCompleteCase:=NewCodeCompleteCase;
  278. { Old version of Code complete, also OK PM }
  279. if not OK or (S.getPos=S.getSize) then
  280. begin
  281. LoadCodeComplete:=OK;
  282. exit;
  283. end;
  284. if S.Status=stOK then
  285. S.Read(NewUseStandardUnitsInCodeComplete,Sizeof(UseStandardUnitsInCodeComplete));
  286. if S.Status=stOK then
  287. UseStandardUnitsInCodeComplete:=NewUseStandardUnitsInCodeComplete;
  288. if S.Status=stOK then
  289. S.Read(NewUseAllUnitsInCodeComplete,Sizeof(UseAllUnitsInCodeComplete));
  290. if S.Status=stOK then
  291. UseAllUnitsInCodeComplete:=NewUseAllUnitsInCodeComplete;
  292. if S.Status=stOK then
  293. S.Read(NewShowOnlyUnique,Sizeof(ShowOnlyUnique));
  294. if S.Status=stOK then
  295. ShowOnlyUnique:=NewShowOnlyUnique;
  296. if S.Status=stOK then
  297. S.Read(NewCodeCompleteMinLen,Sizeof(CodeCompleteMinLen));
  298. if S.Status=stOK then
  299. CodeCompleteMinLen:=NewCodeCompleteMinLen;
  300. if S.Status=stOK then
  301. StPtr:=S.ReadStr
  302. else
  303. StPtr:=nil;
  304. if (S.Status=stOK) then
  305. StandardUnits:=GetStr(StPtr);
  306. if assigned(StPtr) then
  307. FreeMem(StPtr,Length(StandardUnits)+1);
  308. OK:=S.Status=stOK;
  309. end
  310. else
  311. if Assigned(C) then
  312. Dispose(C, Done);
  313. LoadCodeComplete:=OK;
  314. end;
  315. function StoreCodeComplete(var S: TStream): boolean;
  316. var OK: boolean;
  317. begin
  318. OK:=Assigned(CodeCompleteWords);
  319. if OK then
  320. begin
  321. CodeCompleteWords^.Store(S);
  322. S.Write(CodeCompleteCase,Sizeof(TCodeCompleteCase));
  323. { New fields added }
  324. S.Write(UseStandardUnitsInCodeComplete,Sizeof(UseStandardUnitsInCodeComplete));
  325. S.Write(UseAllUnitsInCodeComplete,Sizeof(UseAllUnitsInCodeComplete));
  326. S.Write(ShowOnlyUnique,Sizeof(ShowOnlyUnique));
  327. S.Write(CodeCompleteMinLen,Sizeof(CodeCompleteMinLen));
  328. S.WriteStr(@StandardUnits);
  329. OK:=OK and (S.Status=stOK);
  330. end;
  331. StoreCodeComplete:=OK;
  332. end;
  333. procedure DoneCodeComplete;
  334. begin
  335. if Assigned(CodeCompleteWords) then
  336. begin
  337. Dispose(CodeCompleteWords, Done);
  338. CodeCompleteWords:=nil;
  339. end;
  340. if Assigned(UnitsCodeCompleteWords) then
  341. begin
  342. Dispose(UnitsCodeCompleteWords,done);
  343. UnitsCodeCompleteWords:=nil;
  344. end;
  345. end;
  346. constructor TCodeCompleteDialog.Init;
  347. var R,R2,R3: TRect;
  348. Items: PSItem;
  349. SB: PScrollBar;
  350. begin
  351. R.Assign(0,0,50,22);
  352. inherited Init(R,dialog_codecomplete);
  353. HelpCtx:=hcCodeCompleteOptions;
  354. { name list dialog }
  355. GetExtent(R); R.Grow(-3,-2); Inc(R.A.Y); R3.Copy(R); Dec(R.B.X,12);
  356. Dec(R.B.Y,7);
  357. R2.Copy(R); R2.Move(1,0); R2.A.X:=R2.B.X-1;
  358. New(SB, Init(R2)); Insert(SB);
  359. New(CodeCompleteLB, Init(R,1,SB));
  360. Insert(CodeCompleteLB);
  361. R2.Copy(R); R2.Move(0,-1); R2.B.Y:=R2.A.Y+1; Dec(R2.A.X);
  362. Insert(New(PLabel, Init(R2, label_codecomplete_keywords, CodeCompleteLB)));
  363. { Case choice }
  364. 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;
  365. Items:=NewSItem('Unc~h~anged',
  366. NewSItem('~L~ower',
  367. NewSItem('~U~pper',
  368. NewSItem('~M~ixed',nil))));
  369. RB:=New(PRadioButtons,Init(R,Items));
  370. RB^.SetData(ord(CodeCompleteCase));
  371. R2.Copy(R); R2.Move(0,-1); R2.B.Y:=R2.A.Y+1; Dec(R2.A.X);
  372. Insert(New(PLabel, Init(R2, 'Case handling', RB)));
  373. Insert(RB);
  374. { Mininum length inputline }
  375. 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;
  376. New(MinInputL, Init(R,5));
  377. MinInputL^.SetValidator(New(PRangeValidator, Init(1,255)));
  378. Insert(MinInputL);
  379. R2.Copy(R); R2.A.X:=20;Dec(R2.B.X,5);
  380. Insert(New(PLabel, Init(R2, 'Min. length', MinInputL)));
  381. { Standard/all units booleans }
  382. Items:=nil;
  383. Items:=NewSItem('Add standard units', Items);
  384. Items:=NewSItem('Add all units', Items);
  385. Items:=NewSItem('Show only unique', Items);
  386. 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);
  387. New(CB, Init(R, Items));
  388. Insert(CB);
  389. R2.Copy(R); R2.Move(0,-1); R2.B.Y:=R2.A.Y+1; Dec(R2.A.X);
  390. Insert(New(PLabel, Init(R2, 'Unit handling', CB)));
  391. R2.Copy(R); R2.Move(0,-1); R2.B.Y:=R2.A.Y+1;
  392. If ShowOnlyUnique then
  393. CB^.Press(0);
  394. If UseAllUnitsInCodeComplete then
  395. CB^.Press(1);
  396. If UseStandardUnitsInCodeComplete then
  397. CB^.Press(2);
  398. { Standard unit name boolean }
  399. R.Copy(R3); R.A.Y:=R.B.Y-1; Inc(R.A.X); Dec(R.B.X);
  400. New(InputL,Init(R,255));
  401. Insert(InputL);
  402. InputL^.SetValidator(New(PFilterValidator,Init(NumberChars+AlphaChars+[','])));
  403. 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;
  404. Insert(New(PLabel, Init(R2, '~S~tandard unit list', InputL)));
  405. R.Copy(R3); R.A.X:=R.B.X-10; R.B.Y:=R.A.Y+2;
  406. Insert(New(PButton, Init(R, button_OK, cmOK, bfNormal)));
  407. R.Move(0,2);
  408. Insert(New(PButton, Init(R, button_Edit, cmEditItem, bfDefault)));
  409. R.Move(0,2);
  410. Insert(New(PButton, Init(R, button_New, cmAddItem, bfNormal)));
  411. R.Move(0,2);
  412. Insert(New(PButton, Init(R, button_Delete, cmDeleteItem, bfNormal)));
  413. R.Move(0,2);
  414. Insert(New(PButton, Init(R, button_Cancel, cmCancel, bfNormal)));
  415. SelectNext(false);
  416. end;
  417. procedure TCodeCompleteDialog.HandleEvent(var Event: TEvent);
  418. var DontClear: boolean;
  419. begin
  420. case Event.What of
  421. evKeyDown :
  422. begin
  423. DontClear:=false;
  424. case Event.KeyCode of
  425. kbIns :
  426. Message(@Self,evCommand,cmAddItem,nil);
  427. kbDel :
  428. Message(@Self,evCommand,cmDeleteItem,nil);
  429. else DontClear:=true;
  430. end;
  431. if DontClear=false then ClearEvent(Event);
  432. end;
  433. evBroadcast :
  434. case Event.Command of
  435. cmListItemSelected :
  436. if Event.InfoPtr=pointer(CodeCompleteLB) then
  437. Message(@Self,evCommand,cmEditItem,nil);
  438. end;
  439. evCommand :
  440. begin
  441. DontClear:=false;
  442. case Event.Command of
  443. cmAddItem : Add;
  444. cmDeleteItem : Delete;
  445. cmEditItem : Edit;
  446. else DontClear:=true;
  447. end;
  448. if DontClear=false then ClearEvent(Event);
  449. end;
  450. end;
  451. inherited HandleEvent(Event);
  452. end;
  453. function TCodeCompleteDialog.Execute: Word;
  454. var R: word;
  455. C: PCodeCompleteWordList;
  456. NewVal, I: integer;
  457. NewValStr : string;
  458. begin
  459. New(C, Init(10,20));
  460. if Assigned(CodeCompleteWords) then
  461. for I:=0 to CodeCompleteWords^.Count-1 do
  462. C^.Insert(NewStr(GetStr(CodeCompleteWords^.At(I))));
  463. CodeCompleteLB^.NewList(C);
  464. InputL^.SetData(StandardUnits);
  465. NewValStr:=IntToStr(CodeCompleteMinLen);
  466. MinInputL^.SetData(NewValStr);
  467. R:=inherited Execute;
  468. if R=cmOK then
  469. begin
  470. if Assigned(CodeCompleteWords) then Dispose(CodeCompleteWords, Done);
  471. CodeCompleteWords:=C;
  472. CodeCompleteCase:=TCodeCompleteCase(RB^.Value);
  473. MinInputL^.GetData(NewValStr);
  474. NewVal:=StrToInt(NewValStr);
  475. if (NewVal>0) and (NewVal<>CodeCompleteMinLen) then
  476. begin
  477. CodeCompleteMinLen:=NewVal;
  478. InitCodeComplete;
  479. end;
  480. ShowOnlyUnique:=CB^.Mark(0);
  481. UseAllUnitsInCodeComplete:=CB^.Mark(1);
  482. UseStandardUnitsInCodeComplete:=CB^.Mark(2);
  483. if UseStandardUnitsInCodeComplete and (not UseAllUnitsInCodeComplete or not assigned(UnitsCodeCompleteWords)) and
  484. ((StandardUnits<>GetStr(InputL^.Data)) or not assigned(UnitsCodeCompleteWords)) then
  485. begin
  486. InputL^.GetData(StandardUnits);
  487. AddStandardUnitsToCodeComplete;
  488. end
  489. else
  490. InputL^.GetData(StandardUnits);
  491. end
  492. else
  493. Dispose(C, Done);
  494. Execute:=R;
  495. end;
  496. procedure TCodeCompleteDialog.Add;
  497. var IC: boolean;
  498. S: string;
  499. P: PString;
  500. Cmd: word;
  501. CanExit: boolean;
  502. I: sw_integer;
  503. begin
  504. IC:=CodeCompleteLB^.Range=0;
  505. if IC=false then
  506. S:=GetStr(CodeCompleteLB^.List^.At(CodeCompleteLB^.Focused))
  507. else
  508. S:='';
  509. repeat
  510. Cmd:=InputBox(dialog_codecomplete_add,label_codecomplete_add_keyword,S,255);
  511. CanExit:=Cmd<>cmOK;
  512. if CanExit=false then
  513. begin
  514. CanExit:=PCodeCompleteWordList(CodeCompleteLB^.List)^.Search(@S,I)=false;
  515. if CanExit=false then
  516. begin
  517. ClearFormatParams; AddFormatParamStr(S);
  518. ErrorBox(msg_codecomplete_alreadyinlist,@FormatParams);
  519. end;
  520. end;
  521. until CanExit;
  522. if Cmd=cmOK then
  523. begin
  524. P:=NewStr(S);
  525. with CodeCompleteLB^ do
  526. begin
  527. List^.Insert(P);
  528. SetRange(List^.Count);
  529. SetFocusedItem(P);
  530. end;
  531. ReDraw;
  532. end;
  533. end;
  534. procedure TCodeCompleteDialog.Edit;
  535. var S: string;
  536. I,T: sw_integer;
  537. Cmd: word;
  538. CanExit: boolean;
  539. P: PString;
  540. begin
  541. if CodeCompleteLB^.Range=0 then Exit;
  542. I:=CodeCompleteLB^.Focused;
  543. S:=GetStr(CodeCompleteLB^.List^.At(I));
  544. repeat
  545. Cmd:=InputBox(dialog_codecomplete_edit,label_codecomplete_edit_keyword,S,255);
  546. CanExit:=Cmd<>cmOK;
  547. if CanExit=false then
  548. begin
  549. CanExit:=PCodeCompleteWordList(CodeCompleteLB^.List)^.Search(@S,T)=false;
  550. CanExit:=CanExit or (T=I);
  551. if CanExit=false then
  552. begin
  553. ClearFormatParams; AddFormatParamStr(S);
  554. ErrorBox(msg_codecomplete_alreadyinlist,@FormatParams);
  555. end;
  556. end;
  557. until CanExit;
  558. if Cmd=cmOK then
  559. begin
  560. P:=NewStr(S);
  561. with CodeCompleteLB^ do
  562. begin
  563. List^.AtFree(I);
  564. List^.Insert(P);
  565. SetFocusedItem(P);
  566. end;
  567. ReDraw;
  568. end;
  569. end;
  570. procedure TCodeCompleteDialog.Delete;
  571. begin
  572. if CodeCompleteLB^.Range=0 then Exit;
  573. CodeCompleteLB^.List^.AtFree(CodeCompleteLB^.Focused);
  574. CodeCompleteLB^.SetRange(CodeCompleteLB^.List^.Count);
  575. ReDraw;
  576. end;
  577. procedure RegisterCodeComplete;
  578. begin
  579. {$ifndef NOOBJREG}
  580. RegisterType(RCodeCompleteWordList);
  581. {$endif}
  582. end;
  583. END.