fpcodtmp.pas 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656
  1. {
  2. This file is part of the Free Pascal Integrated Development Environment
  3. Copyright (c) 1998 by Berczi Gabor
  4. Code Template 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 FPCodTmp; { Code Templates }
  12. {$ifdef cpullvm}
  13. {$modeswitch nestedprocvars}
  14. {$endif}
  15. interface
  16. uses Objects,Drivers,Dialogs,
  17. WUtils,WViews,WEditor,
  18. FPViews;
  19. type
  20. PCodeTemplate = ^TCodeTemplate;
  21. TCodeTemplate = object(TObject)
  22. constructor Init(const AShortCut: string; AText: PUnsortedStringCollection);
  23. function GetShortCut: string;
  24. procedure GetText(AList: PUnsortedStringCollection);
  25. procedure SetShortCut(const AShortCut: string);
  26. procedure SetText(AList: PUnsortedStringCollection);
  27. procedure GetParams(var AShortCut: string; Lines: PUnsortedStringCollection);
  28. procedure SetParams(const AShortCut: string; Lines: PUnsortedStringCollection);
  29. constructor Load(var S: TStream);
  30. procedure Store(var S: TStream);
  31. destructor Done; virtual;
  32. private
  33. ShortCut: PString;
  34. Text: PUnsortedStringCollection;
  35. end;
  36. PCodeTemplateCollection = ^TCodeTemplateCollection;
  37. TCodeTemplateCollection = object(TSortedCollection)
  38. function Compare(Key1, Key2: Pointer): sw_Integer; virtual;
  39. function SearchByShortCut(const ShortCut: string): PCodeTemplate; virtual;
  40. function LookUp(const S: string; AcceptMulti: boolean; var Idx: sw_integer): string; virtual;
  41. end;
  42. PCodeTemplateListBox = ^TCodeTemplateListBox;
  43. TCodeTemplateListBox = object(TAdvancedListBox)
  44. function GetText(Item,MaxLen: Sw_Integer): String; virtual;
  45. end;
  46. PCodeTemplateDialog = ^TCodeTemplateDialog;
  47. TCodeTemplateDialog = object(TCenterDialog)
  48. constructor Init(const ATitle: string; ATemplate: PCodeTemplate);
  49. function Execute: Word; virtual;
  50. private
  51. Template : PCodeTemplate;
  52. ShortcutIL : PInputLine;
  53. CodeMemo : PFPCodeMemo;
  54. end;
  55. PCodeTemplatesDialog = ^TCodeTemplatesDialog;
  56. TCodeTemplatesDialog = object(TCenterDialog)
  57. SelMode: boolean;
  58. constructor Init(ASelMode: boolean;const AShortCut : string);
  59. function Execute: Word; virtual;
  60. procedure HandleEvent(var Event: TEvent); virtual;
  61. function GetSelectedShortCut: string;
  62. private
  63. CodeTemplatesLB : PCodeTemplateListBox;
  64. TemplateViewer : PFPCodeMemo;
  65. StartIdx : sw_integer;
  66. procedure Add;
  67. procedure Edit;
  68. procedure Delete;
  69. procedure Update;
  70. end;
  71. const CodeTemplates : PCodeTemplateCollection = nil;
  72. function FPTranslateCodeTemplate(var Shortcut: string; ALines: PUnsortedStringCollection): boolean;
  73. procedure InitCodeTemplates;
  74. function LoadCodeTemplates(var S: TStream): boolean;
  75. function StoreCodeTemplates(var S: TStream): boolean;
  76. procedure DoneCodeTemplates;
  77. procedure RegisterCodeTemplates;
  78. implementation
  79. uses Views,App,Validate,
  80. FVConsts,
  81. FPConst;
  82. resourcestring label_codetemplate_shortcut = '~S~hortcut';
  83. label_codetemplate_content = '~T~emplate content';
  84. label_codetemplate_templates = '~T~emplates';
  85. msg_codetemplate_alreadyinlist = 'A template named "%s" is already in the list';
  86. dialog_modifytemplate = 'Modify template';
  87. dialog_newtemplate = 'New template';
  88. { standard button texts }
  89. button_OK = 'O~K~';
  90. button_Cancel = 'Cancel';
  91. button_New = '~N~ew';
  92. button_Edit = '~E~dit';
  93. button_Delete = '~D~elete';
  94. {$ifndef NOOBJREG}
  95. const
  96. RCodeTemplate: TStreamRec = (
  97. ObjType: 14501;
  98. VmtLink: Ofs(TypeOf(TCodeTemplate)^);
  99. Load: @TCodeTemplate.Load;
  100. Store: @TCodeTemplate.Store
  101. );
  102. RCodeTemplateCollection: TStreamRec = (
  103. ObjType: 14502;
  104. VmtLink: Ofs(TypeOf(TCodeTemplateCollection)^);
  105. Load: @TCodeTemplateCollection.Load;
  106. Store: @TCodeTemplateCollection.Store
  107. );
  108. {$endif}
  109. constructor TCodeTemplate.Init(const AShortCut: string; AText: PUnsortedStringCollection);
  110. procedure CopyIt(P: PString); {$ifndef FPC}far;{$endif}
  111. begin
  112. Text^.Insert(NewStr(GetStr(P)));
  113. end;
  114. begin
  115. inherited Init;
  116. ShortCut:=NewStr(AShortCut);
  117. SetText(AText);
  118. end;
  119. function TCodeTemplate.GetShortCut: string;
  120. begin
  121. GetShortCut:=GetStr(ShortCut);
  122. end;
  123. procedure TCodeTemplate.GetText(AList: PUnsortedStringCollection);
  124. procedure CopyIt(P: PString); {$ifndef FPC}far;{$endif}
  125. begin
  126. AList^.Insert(NewStr(GetStr(P)));
  127. end;
  128. begin
  129. if Assigned(AList) and Assigned(Text) then
  130. Text^.ForEach(TCallbackProcParam(@CopyIt));
  131. end;
  132. procedure TCodeTemplate.SetShortCut(const AShortCut: string);
  133. begin
  134. if Assigned(ShortCut) then DisposeStr(ShortCut);
  135. ShortCut:=NewStr(AShortCut);
  136. end;
  137. procedure TCodeTemplate.SetText(AList: PUnsortedStringCollection);
  138. begin
  139. if Assigned(Text) then Dispose(Text, Done);
  140. New(Text, CreateFrom(AList));
  141. end;
  142. procedure TCodeTemplate.GetParams(var AShortCut: string; Lines: PUnsortedStringCollection);
  143. begin
  144. AShortCut:=GetShortCut;
  145. GetText(Lines);
  146. end;
  147. procedure TCodeTemplate.SetParams(const AShortCut: string; Lines: PUnsortedStringCollection);
  148. begin
  149. SetShortCut(AShortCut);
  150. SetText(Lines);
  151. end;
  152. constructor TCodeTemplate.Load(var S: TStream);
  153. begin
  154. ShortCut:=S.ReadStr;
  155. New(Text, Load(S));
  156. end;
  157. procedure TCodeTemplate.Store(var S: TStream);
  158. begin
  159. S.WriteStr(ShortCut);
  160. Text^.Store(S);
  161. end;
  162. destructor TCodeTemplate.Done;
  163. begin
  164. if Assigned(ShortCut) then DisposeStr(ShortCut); ShortCut:=nil;
  165. if Assigned(Text) then Dispose(Text, Done); Text:=nil;
  166. inherited Done;
  167. end;
  168. function TCodeTemplateCollection.Compare(Key1, Key2: Pointer): sw_Integer;
  169. var K1: PCodeTemplate absolute Key1;
  170. K2: PCodeTemplate absolute Key2;
  171. R: Sw_integer;
  172. S1,S2: string;
  173. begin
  174. S1:=UpCaseStr(K1^.GetShortCut);
  175. S2:=UpCaseStr(K2^.GetShortCut);
  176. if S1<S2 then R:=-1 else
  177. if S1>S2 then R:=1 else
  178. R:=0;
  179. Compare:=R;
  180. end;
  181. function TCodeTemplateCollection.SearchByShortCut(const ShortCut: string): PCodeTemplate;
  182. var T: TCodeTemplate;
  183. Index: sw_integer;
  184. P: PCodeTemplate;
  185. begin
  186. T.Init(ShortCut,nil);
  187. if Search(@T,Index)=false then P:=nil else
  188. P:=At(Index);
  189. T.Done;
  190. SearchByShortCut:=P;
  191. end;
  192. function TCodeTemplateCollection.LookUp(const S: string; AcceptMulti: boolean; var Idx: sw_integer): string;
  193. var OLI,ORI,Left,Right,Mid: sw_integer;
  194. MidP: PCodeTemplate;
  195. MidS: string;
  196. FoundS: string;
  197. UpS : string;
  198. begin
  199. Idx:=-1; FoundS:='';
  200. Left:=0; Right:=Count-1;
  201. UpS:=UpCaseStr(S);
  202. while Left<=Right do
  203. begin
  204. OLI:=Left; ORI:=Right;
  205. Mid:=Left+(Right-Left) div 2;
  206. MidP:=At(Mid);
  207. MidS:=UpCaseStr(MidP^.GetShortCut);
  208. if copy(MidS,1,length(UpS))=UpS then
  209. begin
  210. if (Idx<>-1) and (Idx<>Mid) and not AcceptMulti then
  211. begin
  212. { several solutions possible, return nothing }
  213. Idx:=-1;
  214. FoundS:='';
  215. break;
  216. end
  217. else if Idx=-1 then
  218. begin
  219. Idx:=Mid;
  220. FoundS:=MidP^.GetShortCut;
  221. end;
  222. end;
  223. if UpS<MidS then
  224. Right:=Mid
  225. else
  226. Left:=Mid;
  227. if (OLI=Left) and (ORI=Right) then
  228. begin
  229. if (Left<Right) then
  230. Left:=Right
  231. else
  232. Break;
  233. end;
  234. end;
  235. { check if next also fits...
  236. return '' in that case }
  237. if (Idx<>-1) and (Idx<Count-1) and not AcceptMulti then
  238. begin
  239. MidP:=At(Idx+1);
  240. MidS:=UpCaseStr(MidP^.GetShortCut);
  241. if copy(MidS,1,length(UpS))=UpS then
  242. begin
  243. Idx:=-1;
  244. FoundS:='';
  245. end;
  246. end;
  247. LookUp:=FoundS;
  248. end;
  249. function FPTranslateCodeTemplate(var Shortcut: string; ALines: PUnsortedStringCollection): boolean;
  250. var OK: boolean;
  251. P: PCodeTemplate;
  252. CompleteName: String;
  253. Idx : sw_integer;
  254. begin
  255. OK:=Assigned(CodeTemplates);
  256. if OK then
  257. begin
  258. P:=CodeTemplates^.SearchByShortCut(ShortCut);
  259. if not assigned(P) then
  260. begin
  261. CompleteName:=CodeTemplates^.Lookup(ShortCut,false,Idx);
  262. if Idx<>-1 then
  263. begin
  264. P:=CodeTemplates^.At(Idx);
  265. ShortCut:=CompleteName;
  266. end;
  267. end;
  268. OK:=Assigned(P);
  269. if OK then
  270. P^.GetText(ALines);
  271. end;
  272. FPTranslateCodeTemplate:=OK;
  273. end;
  274. procedure InitCodeTemplates;
  275. begin
  276. if Assigned(CodeTemplates) then Exit;
  277. New(CodeTemplates, Init(10,10));
  278. end;
  279. function LoadCodeTemplates(var S: TStream): boolean;
  280. var C: PCodeTemplateCollection;
  281. OK: boolean;
  282. begin
  283. New(C, Load(S));
  284. OK:=Assigned(C) and (S.Status=stOk);
  285. if OK then
  286. begin
  287. if Assigned(CodeTemplates) then Dispose(CodeTemplates, Done);
  288. CodeTemplates:=C;
  289. end
  290. else
  291. if Assigned(C) then
  292. Dispose(C, Done);
  293. LoadCodeTemplates:=OK;
  294. end;
  295. function StoreCodeTemplates(var S: TStream): boolean;
  296. var OK: boolean;
  297. begin
  298. OK:=Assigned(CodeTemplates);
  299. if OK then
  300. begin
  301. CodeTemplates^.Store(S);
  302. OK:=OK and (S.Status=stOK);
  303. end;
  304. StoreCodeTemplates:=OK;
  305. end;
  306. procedure DoneCodeTemplates;
  307. begin
  308. if Assigned(CodeTemplates) then Dispose(CodeTemplates, Done);
  309. CodeTemplates:=nil;
  310. end;
  311. function TCodeTemplateListBox.GetText(Item,MaxLen: Sw_Integer): String;
  312. var P: PCodeTemplate;
  313. begin
  314. P:=List^.At(Item);
  315. GetText:=P^.GetShortCut;
  316. end;
  317. constructor TCodeTemplateDialog.Init(const ATitle: string; ATemplate: PCodeTemplate);
  318. var R,R2,R3: TRect;
  319. begin
  320. R.Assign(0,0,52,15);
  321. inherited Init(R,ATitle);
  322. Template:=ATemplate;
  323. GetExtent(R); R.Grow(-3,-2); R3.Copy(R);
  324. Inc(R.A.Y); R.B.Y:=R.A.Y+1; R.B.X:=R.A.X+46;
  325. New(ShortCutIL, Init(R, 128)); Insert(ShortcutIL);
  326. ShortCutIL^.SetValidator(New(PFilterValidator,Init(NumberChars+AlphaChars)));
  327. R2.Copy(R); R2.Move(-1,-1);
  328. Insert(New(PLabel, Init(R2, label_codetemplate_shortcut, ShortcutIL)));
  329. R.Move(0,3); R.B.Y:=R.A.Y+8;
  330. New(CodeMemo, Init(R, nil,nil,nil{,4096 does not compile !! }));
  331. Insert(CodeMemo);
  332. R2.Copy(R); R2.Move(-1,-1); R2.B.Y:=R2.A.Y+1;
  333. Insert(New(PLabel, Init(R2, label_codetemplate_content, CodeMemo)));
  334. InsertButtons(@Self);
  335. ShortcutIL^.Select;
  336. end;
  337. function TCodeTemplateDialog.Execute: Word;
  338. var R: word;
  339. S: string;
  340. L: PUnsortedStringCollection;
  341. begin
  342. New(L, Init(10,10));
  343. S:=Template^.GetShortCut;
  344. Template^.GetText(L);
  345. ShortcutIL^.SetData(S);
  346. CodeMemo^.SetContent(L);
  347. R:=inherited Execute;
  348. if R=cmOK then
  349. begin
  350. L^.FreeAll;
  351. ShortcutIL^.GetData(S);
  352. CodeMemo^.GetContent(L);
  353. Template^.SetShortcut(S);
  354. Template^.SetText(L);
  355. end;
  356. Execute:=R;
  357. end;
  358. constructor TCodeTemplatesDialog.Init(ASelMode: boolean;const AShortCut : string);
  359. function B2I(B: boolean; I1,I2: longint): longint;
  360. begin
  361. if B then B2I:=I1 else B2I:=I2;
  362. end;
  363. var R,R2,R3: TRect;
  364. SB: PScrollBar;
  365. begin
  366. R.Assign(0,0,46,20);
  367. inherited Init(R,'Code Templates');
  368. HelpCtx:=hcCodeTemplateOptions;
  369. SelMode:=ASelMode;
  370. GetExtent(R); R.Grow(-3,-2); Inc(R.A.Y); R.B.Y:=R.A.Y+10;
  371. R3.Copy(R); Dec(R.B.X,12);
  372. R2.Copy(R); R2.Move(1,0); R2.A.X:=R2.B.X-1;
  373. New(SB, Init(R2)); Insert(SB);
  374. New(CodeTemplatesLB, Init(R,1,SB));
  375. Insert(CodeTemplatesLB);
  376. if AShortCut<>'' then
  377. begin
  378. If assigned(CodeTemplates) then
  379. CodeTemplates^.Lookup(AShortCut,true,StartIdx)
  380. else
  381. StartIdx:=-1;
  382. end
  383. else
  384. StartIdx:=-1;
  385. R2.Copy(R); R2.Move(0,-1); R2.B.Y:=R2.A.Y+1; Dec(R2.A.X);
  386. Insert(New(PLabel, Init(R2, label_codetemplate_templates, CodeTemplatesLB)));
  387. GetExtent(R); R.Grow(-2,-2); Inc(R.A.Y,12);
  388. R2.Copy(R); R2.Move(1,0); R2.A.X:=R2.B.X-1;
  389. New(SB, Init(R2)); Insert(SB);
  390. New(TemplateViewer, Init(R,nil,SB,nil{,4096 does not compile }));
  391. with TemplateViewer^ do
  392. begin
  393. ReadOnly:=true;
  394. AlwaysShowScrollBars:=true;
  395. end;
  396. Insert(TemplateViewer);
  397. R.Copy(R3); R.A.X:=R.B.X-10; R.B.Y:=R.A.Y+2;
  398. Insert(New(PButton, Init(R, button_OK, cmOK, B2I(SelMode,bfDefault,bfNormal))));
  399. R.Move(0,2);
  400. Insert(New(PButton, Init(R, button_Edit, cmEditItem, B2I(SelMode,bfNormal,bfDefault) )));
  401. R.Move(0,2);
  402. Insert(New(PButton, Init(R, button_New, cmAddItem, bfNormal)));
  403. R.Move(0,2);
  404. Insert(New(PButton, Init(R, button_Delete, cmDeleteItem, bfNormal)));
  405. R.Move(0,2);
  406. Insert(New(PButton, Init(R, button_Cancel, cmCancel, bfNormal)));
  407. SelectNext(false);
  408. end;
  409. procedure TCodeTemplatesDialog.Update;
  410. var C: PUnsortedStringCollection;
  411. begin
  412. if CodeTemplatesLB^.Range=0 then C:=nil else
  413. C:=PCodeTemplate(CodeTemplatesLB^.GetFocusedItem)^.Text;
  414. TemplateViewer^.SetContent(C);
  415. ReDraw;
  416. end;
  417. function TCodeTemplatesDialog.GetSelectedShortCut: string;
  418. var S: string;
  419. begin
  420. if CodeTemplatesLB^.Range=0 then S:='' else
  421. S:=GetStr(PCodeTemplate(CodeTemplatesLB^.GetFocusedItem)^.ShortCut);
  422. GetSelectedShortCut:=S;
  423. end;
  424. procedure TCodeTemplatesDialog.HandleEvent(var Event: TEvent);
  425. var DontClear: boolean;
  426. begin
  427. case Event.What of
  428. evKeyDown :
  429. begin
  430. DontClear:=false;
  431. case Event.KeyCode of
  432. kbIns :
  433. Message(@Self,evCommand,cmAddItem,nil);
  434. kbDel :
  435. Message(@Self,evCommand,cmDeleteItem,nil);
  436. else DontClear:=true;
  437. end;
  438. if DontClear=false then ClearEvent(Event);
  439. end;
  440. evBroadcast :
  441. case Event.Command of
  442. cmListItemSelected :
  443. if Event.InfoPtr=pointer(CodeTemplatesLB) then
  444. Message(@Self,evCommand,cmEditItem,nil);
  445. cmListFocusChanged :
  446. if Event.InfoPtr=pointer(CodeTemplatesLB) then
  447. Message(@Self,evBroadcast,cmUpdate,nil);
  448. cmUpdate :
  449. Update;
  450. end;
  451. evCommand :
  452. begin
  453. DontClear:=false;
  454. case Event.Command of
  455. cmAddItem : Add;
  456. cmDeleteItem : Delete;
  457. cmEditItem : Edit;
  458. else DontClear:=true;
  459. end;
  460. if DontClear=false then ClearEvent(Event);
  461. end;
  462. end;
  463. inherited HandleEvent(Event);
  464. end;
  465. function TCodeTemplatesDialog.Execute: Word;
  466. var R: word;
  467. P: PCodeTemplate;
  468. C: PCodeTemplateCollection;
  469. L: PUnsortedStringCollection;
  470. I: integer;
  471. begin
  472. New(C, Init(10,20));
  473. if Assigned(CodeTemplates) then
  474. for I:=0 to CodeTemplates^.Count-1 do
  475. begin
  476. P:=CodeTemplates^.At(I);
  477. New(L, Init(10,50));
  478. P^.GetText(L);
  479. C^.Insert(New(PCodeTemplate, Init(P^.GetShortCut,L)));
  480. Dispose(L, Done);
  481. end;
  482. CodeTemplatesLB^.NewList(C);
  483. if StartIdx<>-1 then
  484. CodeTemplatesLB^.SetFocusedItem(CodeTemplates^.At(StartIdx));
  485. Update;
  486. R:=inherited Execute;
  487. if R=cmOK then
  488. begin
  489. if Assigned(CodeTemplates) then Dispose(CodeTemplates, Done);
  490. CodeTemplates:=C;
  491. end
  492. else
  493. Dispose(C, Done);
  494. Execute:=R;
  495. end;
  496. procedure TCodeTemplatesDialog.Add;
  497. var P,P2: PCodeTemplate;
  498. IC: boolean;
  499. S: string;
  500. L: PUnsortedStringCollection;
  501. Cmd: word;
  502. CanExit: boolean;
  503. begin
  504. New(L, Init(10,10));
  505. IC:=CodeTemplatesLB^.Range=0;
  506. if IC=false then
  507. begin
  508. P:=CodeTemplatesLB^.List^.At(CodeTemplatesLB^.Focused);
  509. P^.GetParams(S,L);
  510. end
  511. else
  512. begin
  513. S:='';
  514. end;
  515. New(P, Init(S,L));
  516. repeat
  517. Cmd:=Application^.ExecuteDialog(New(PCodeTemplateDialog, Init(dialog_newtemplate,P)), nil);
  518. CanExit:=(Cmd<>cmOK);
  519. if CanExit=false then
  520. begin
  521. P2:=PCodeTemplateCollection(CodeTemplatesLB^.List)^.SearchByShortCut(P^.GetShortCut);
  522. CanExit:=(Assigned(P2)=false);
  523. if CanExit=false then
  524. begin
  525. ClearFormatParams; AddFormatParamStr(P^.GetShortCut);
  526. ErrorBox(msg_codetemplate_alreadyinlist,@FormatParams);
  527. end;
  528. end;
  529. until CanExit;
  530. if Cmd=cmOK then
  531. begin
  532. CodeTemplatesLB^.List^.Insert(P);
  533. CodeTemplatesLB^.SetRange(CodeTemplatesLB^.List^.Count);
  534. CodeTemplatesLB^.SetFocusedItem(P);
  535. Update;
  536. end
  537. else
  538. Dispose(P, Done);
  539. Dispose(L, Done);
  540. end;
  541. procedure TCodeTemplatesDialog.Edit;
  542. var P,O,P2: PCodeTemplate;
  543. I: sw_integer;
  544. S: string;
  545. L: PUnsortedStringCollection;
  546. Cmd: word;
  547. CanExit: boolean;
  548. begin
  549. if CodeTemplatesLB^.Range=0 then Exit;
  550. New(L, Init(10,10));
  551. I:=CodeTemplatesLB^.Focused;
  552. O:=CodeTemplatesLB^.List^.At(I);
  553. O^.GetParams(S,L);
  554. P:=New(PCodeTemplate, Init(S, L));
  555. repeat
  556. Cmd:=Application^.ExecuteDialog(New(PCodeTemplateDialog, Init(dialog_modifytemplate,P)), nil);
  557. CanExit:=(Cmd<>cmOK);
  558. if CanExit=false then
  559. begin
  560. P2:=PCodeTemplateCollection(CodeTemplatesLB^.List)^.SearchByShortCut(P^.GetShortCut);
  561. CanExit:=(Assigned(P2)=false) or (CodeTemplatesLB^.List^.IndexOf(P2)=I);
  562. if CanExit=false then
  563. begin
  564. ClearFormatParams; AddFormatParamStr(P^.GetShortCut);
  565. ErrorBox(msg_codetemplate_alreadyinlist,@FormatParams);
  566. end;
  567. end;
  568. until CanExit;
  569. if Cmd=cmOK then
  570. begin
  571. with CodeTemplatesLB^ do
  572. begin
  573. List^.AtFree(I); O:=nil;
  574. List^.Insert(P);
  575. SetFocusedItem(P);
  576. end;
  577. Update;
  578. end;
  579. Dispose(L, Done);
  580. end;
  581. procedure TCodeTemplatesDialog.Delete;
  582. begin
  583. if CodeTemplatesLB^.Range=0 then Exit;
  584. CodeTemplatesLB^.List^.AtFree(CodeTemplatesLB^.Focused);
  585. CodeTemplatesLB^.SetRange(CodeTemplatesLB^.List^.Count);
  586. Update;
  587. end;
  588. procedure RegisterCodeTemplates;
  589. begin
  590. {$ifndef NOOBJREG}
  591. RegisterType(RCodeTemplate);
  592. RegisterType(RCodeTemplateCollection);
  593. {$endif}
  594. end;
  595. END.