fpcodtmp.pas 17 KB

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