fpcodtmp.pas 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  1. unit FPCodTmp; { Code Templates }
  2. interface
  3. uses Objects,Drivers,Dialogs,
  4. WUtils,WViews,WEditor,
  5. FPViews;
  6. type
  7. PCodeTemplate = ^TCodeTemplate;
  8. TCodeTemplate = object(TObject)
  9. constructor Init(const AShortCut: string; AText: PUnsortedStringCollection);
  10. function GetShortCut: string;
  11. procedure GetText(AList: PUnsortedStringCollection);
  12. procedure SetShortCut(const AShortCut: string);
  13. procedure SetText(AList: PUnsortedStringCollection);
  14. procedure GetParams(var AShortCut: string; Lines: PUnsortedStringCollection);
  15. procedure SetParams(const AShortCut: string; Lines: PUnsortedStringCollection);
  16. constructor Load(var S: TStream);
  17. procedure Store(var S: TStream);
  18. destructor Done; virtual;
  19. private
  20. ShortCut: PString;
  21. Text: PUnsortedStringCollection;
  22. end;
  23. PCodeTemplateCollection = ^TCodeTemplateCollection;
  24. TCodeTemplateCollection = object(TSortedCollection)
  25. function Compare(Key1, Key2: Pointer): sw_Integer; virtual;
  26. function SearchByShortCut(const ShortCut: string): PCodeTemplate; virtual;
  27. end;
  28. PCodeTemplateListBox = ^TCodeTemplateListBox;
  29. TCodeTemplateListBox = object(TAdvancedListBox)
  30. function GetText(Item,MaxLen: Sw_Integer): String; virtual;
  31. end;
  32. PCodeTemplateDialog = ^TCodeTemplateDialog;
  33. TCodeTemplateDialog = object(TCenterDialog)
  34. constructor Init(const ATitle: string; ATemplate: PCodeTemplate);
  35. function Execute: Word; virtual;
  36. private
  37. Template : PCodeTemplate;
  38. ShortcutIL : PInputLine;
  39. CodeMemo : PFPCodeMemo;
  40. end;
  41. PCodeTemplatesDialog = ^TCodeTemplatesDialog;
  42. TCodeTemplatesDialog = object(TCenterDialog)
  43. constructor Init;
  44. function Execute: Word; virtual;
  45. procedure HandleEvent(var Event: TEvent); virtual;
  46. private
  47. CodeTemplatesLB : PCodeTemplateListBox;
  48. TemplateViewer : PFPCodeMemo;
  49. procedure Add;
  50. procedure Edit;
  51. procedure Delete;
  52. procedure Update;
  53. end;
  54. const CodeTemplates : PCodeTemplateCollection = nil;
  55. function FPTranslateCodeTemplate(const Shortcut: string; ALines: PUnsortedStringCollection): boolean;
  56. procedure InitCodeTemplates;
  57. function LoadCodeTemplates(var S: TStream): boolean;
  58. function StoreCodeTemplates(var S: TStream): boolean;
  59. procedure DoneCodeTemplates;
  60. procedure RegisterCodeTemplates;
  61. implementation
  62. uses Commands,Views,MsgBox,App,
  63. FPConst,FPString;
  64. {$ifndef NOOBJREG}
  65. const
  66. RCodeTemplate: TStreamRec = (
  67. ObjType: 14501;
  68. VmtLink: Ofs(TypeOf(TCodeTemplate)^);
  69. Load: @TCodeTemplate.Load;
  70. Store: @TCodeTemplate.Store
  71. );
  72. RCodeTemplateCollection: TStreamRec = (
  73. ObjType: 14502;
  74. VmtLink: Ofs(TypeOf(TCodeTemplateCollection)^);
  75. Load: @TCodeTemplateCollection.Load;
  76. Store: @TCodeTemplateCollection.Store
  77. );
  78. {$endif}
  79. constructor TCodeTemplate.Init(const AShortCut: string; AText: PUnsortedStringCollection);
  80. procedure CopyIt(P: PString); {$ifndef FPC}far;{$endif}
  81. begin
  82. Text^.Insert(NewStr(GetStr(P)));
  83. end;
  84. begin
  85. inherited Init;
  86. ShortCut:=NewStr(AShortCut);
  87. SetText(AText);
  88. end;
  89. function TCodeTemplate.GetShortCut: string;
  90. begin
  91. GetShortCut:=GetStr(ShortCut);
  92. end;
  93. procedure TCodeTemplate.GetText(AList: PUnsortedStringCollection);
  94. procedure CopyIt(P: PString); {$ifndef FPC}far;{$endif}
  95. begin
  96. AList^.Insert(NewStr(GetStr(P)));
  97. end;
  98. begin
  99. if Assigned(AList) and Assigned(Text) then
  100. Text^.ForEach(@CopyIt);
  101. end;
  102. procedure TCodeTemplate.SetShortCut(const AShortCut: string);
  103. begin
  104. if Assigned(ShortCut) then DisposeStr(ShortCut);
  105. ShortCut:=NewStr(AShortCut);
  106. end;
  107. procedure TCodeTemplate.SetText(AList: PUnsortedStringCollection);
  108. begin
  109. if Assigned(Text) then Dispose(Text, Done);
  110. New(Text, CreateFrom(AList));
  111. end;
  112. procedure TCodeTemplate.GetParams(var AShortCut: string; Lines: PUnsortedStringCollection);
  113. begin
  114. AShortCut:=GetShortCut;
  115. GetText(Lines);
  116. end;
  117. procedure TCodeTemplate.SetParams(const AShortCut: string; Lines: PUnsortedStringCollection);
  118. begin
  119. SetShortCut(AShortCut);
  120. SetText(Lines);
  121. end;
  122. constructor TCodeTemplate.Load(var S: TStream);
  123. begin
  124. ShortCut:=S.ReadStr;
  125. New(Text, Load(S));
  126. end;
  127. procedure TCodeTemplate.Store(var S: TStream);
  128. begin
  129. S.WriteStr(ShortCut);
  130. Text^.Store(S);
  131. end;
  132. destructor TCodeTemplate.Done;
  133. begin
  134. if Assigned(ShortCut) then DisposeStr(ShortCut); ShortCut:=nil;
  135. if Assigned(Text) then Dispose(Text, Done); Text:=nil;
  136. inherited Done;
  137. end;
  138. function TCodeTemplateCollection.Compare(Key1, Key2: Pointer): sw_Integer;
  139. var K1: PCodeTemplate absolute Key1;
  140. K2: PCodeTemplate absolute Key2;
  141. R: Sw_integer;
  142. S1,S2: string;
  143. begin
  144. S1:=UpCaseStr(K1^.GetShortCut);
  145. S2:=UpCaseStr(K2^.GetShortCut);
  146. if S1<S2 then R:=-1 else
  147. if S1>S2 then R:=1 else
  148. R:=0;
  149. Compare:=R;
  150. end;
  151. function TCodeTemplateCollection.SearchByShortCut(const ShortCut: string): PCodeTemplate;
  152. var T: TCodeTemplate;
  153. Index: sw_integer;
  154. P: PCodeTemplate;
  155. begin
  156. T.Init(ShortCut,nil);
  157. if Search(@T,Index)=false then P:=nil else
  158. P:=At(Index);
  159. T.Done;
  160. SearchByShortCut:=P;
  161. end;
  162. function FPTranslateCodeTemplate(const Shortcut: string; ALines: PUnsortedStringCollection): boolean;
  163. var OK: boolean;
  164. P: PCodeTemplate;
  165. begin
  166. OK:=Assigned(CodeTemplates);
  167. if OK then
  168. begin
  169. P:=CodeTemplates^.SearchByShortCut(ShortCut);
  170. OK:=Assigned(P);
  171. if OK then
  172. P^.GetText(ALines);
  173. end;
  174. FPTranslateCodeTemplate:=OK;
  175. end;
  176. procedure InitCodeTemplates;
  177. begin
  178. if Assigned(CodeTemplates) then Exit;
  179. New(CodeTemplates, Init(10,10));
  180. end;
  181. function LoadCodeTemplates(var S: TStream): boolean;
  182. var C: PCodeTemplateCollection;
  183. OK: boolean;
  184. begin
  185. New(C, Load(S));
  186. OK:=Assigned(C) and (S.Status=stOk);
  187. if OK then
  188. begin
  189. if Assigned(CodeTemplates) then Dispose(CodeTemplates, Done);
  190. CodeTemplates:=C;
  191. end
  192. else
  193. if Assigned(C) then
  194. Dispose(C, Done);
  195. LoadCodeTemplates:=OK;
  196. end;
  197. function StoreCodeTemplates(var S: TStream): boolean;
  198. var OK: boolean;
  199. begin
  200. OK:=Assigned(CodeTemplates);
  201. if OK then
  202. begin
  203. CodeTemplates^.Store(S);
  204. OK:=OK and (S.Status=stOK);
  205. end;
  206. StoreCodeTemplates:=OK;
  207. end;
  208. procedure DoneCodeTemplates;
  209. begin
  210. if Assigned(CodeTemplates) then Dispose(CodeTemplates, Done);
  211. CodeTemplates:=nil;
  212. end;
  213. function TCodeTemplateListBox.GetText(Item,MaxLen: Sw_Integer): String;
  214. var P: PCodeTemplate;
  215. begin
  216. P:=List^.At(Item);
  217. GetText:=P^.GetShortCut;
  218. end;
  219. constructor TCodeTemplateDialog.Init(const ATitle: string; ATemplate: PCodeTemplate);
  220. var R,R2,R3: TRect;
  221. Items: PSItem;
  222. I,KeyCount: sw_integer;
  223. begin
  224. R.Assign(0,0,52,15);
  225. inherited Init(R,ATitle);
  226. Template:=ATemplate;
  227. GetExtent(R); R.Grow(-3,-2); R3.Copy(R);
  228. Inc(R.A.Y); R.B.Y:=R.A.Y+1; R.B.X:=R.A.X+46;
  229. New(ShortCutIL, Init(R, 128)); Insert(ShortcutIL);
  230. R2.Copy(R); R2.Move(-1,-1); Insert(New(PLabel, Init(R2, '~S~hortcut', ShortcutIL)));
  231. R.Move(0,3); R.B.Y:=R.A.Y+8;
  232. New(CodeMemo, Init(R, nil,nil,nil,4096)); Insert(CodeMemo);
  233. R2.Copy(R); R2.Move(-1,-1); R2.B.Y:=R2.A.Y+1; Insert(New(PLabel, Init(R2, '~T~emplate content', CodeMemo)));
  234. InsertButtons(@Self);
  235. ShortcutIL^.Select;
  236. end;
  237. function TCodeTemplateDialog.Execute: Word;
  238. var R: word;
  239. S: string;
  240. L: PUnsortedStringCollection;
  241. W: word;
  242. begin
  243. New(L, Init(10,10));
  244. S:=Template^.GetShortCut;
  245. Template^.GetText(L);
  246. ShortcutIL^.SetData(S);
  247. CodeMemo^.SetContent(L);
  248. R:=inherited Execute;
  249. if R=cmOK then
  250. begin
  251. L^.FreeAll;
  252. ShortcutIL^.GetData(S);
  253. CodeMemo^.GetContent(L);
  254. Template^.SetShortcut(S);
  255. Template^.SetText(L);
  256. end;
  257. Execute:=R;
  258. end;
  259. constructor TCodeTemplatesDialog.Init;
  260. var R,R2,R3: TRect;
  261. SB: PScrollBar;
  262. begin
  263. R.Assign(0,0,46,20);
  264. inherited Init(R,'CodeTemplates');
  265. GetExtent(R); R.Grow(-3,-2); Inc(R.A.Y); R.B.Y:=R.A.Y+10;
  266. R3.Copy(R); Dec(R.B.X,12);
  267. R2.Copy(R); R2.Move(1,0); R2.A.X:=R2.B.X-1;
  268. New(SB, Init(R2)); Insert(SB);
  269. New(CodeTemplatesLB, Init(R,1,SB));
  270. Insert(CodeTemplatesLB);
  271. R2.Copy(R); R2.Move(0,-1); R2.B.Y:=R2.A.Y+1; Dec(R2.A.X);
  272. Insert(New(PLabel, Init(R2, '~T~emplates', CodeTemplatesLB)));
  273. GetExtent(R); R.Grow(-2,-2); Inc(R.A.Y,12);
  274. R2.Copy(R); R2.Move(1,0); R2.A.X:=R2.B.X-1;
  275. New(SB, Init(R2)); Insert(SB);
  276. New(TemplateViewer, Init(R,nil,SB,nil,4096));
  277. with TemplateViewer^ do
  278. begin
  279. IsReadOnly:=true;
  280. AlwaysShowScrollBars:=true;
  281. end;
  282. Insert(TemplateViewer);
  283. R.Copy(R3); R.A.X:=R.B.X-10; R.B.Y:=R.A.Y+2;
  284. Insert(New(PButton, Init(R, 'O~K~', cmOK, bfNormal)));
  285. R.Move(0,2);
  286. Insert(New(PButton, Init(R, '~E~dit', cmEditItem, bfDefault)));
  287. R.Move(0,2);
  288. Insert(New(PButton, Init(R, '~N~ew', cmAddItem, bfNormal)));
  289. R.Move(0,2);
  290. Insert(New(PButton, Init(R, '~D~elete', cmDeleteItem, bfNormal)));
  291. R.Move(0,2);
  292. Insert(New(PButton, Init(R, 'Cancel', cmCancel, bfNormal)));
  293. SelectNext(false);
  294. end;
  295. procedure TCodeTemplatesDialog.Update;
  296. var C: PUnsortedStringCollection;
  297. begin
  298. if CodeTemplatesLB^.Range=0 then C:=nil else
  299. C:=PCodeTemplate(CodeTemplatesLB^.GetFocusedItem)^.Text;
  300. TemplateViewer^.SetContent(C);
  301. ReDraw;
  302. end;
  303. procedure TCodeTemplatesDialog.HandleEvent(var Event: TEvent);
  304. var DontClear: boolean;
  305. begin
  306. case Event.What of
  307. evKeyDown :
  308. begin
  309. DontClear:=false;
  310. case Event.KeyCode of
  311. kbIns :
  312. Message(@Self,evCommand,cmAddItem,nil);
  313. kbDel :
  314. Message(@Self,evCommand,cmDeleteItem,nil);
  315. else DontClear:=true;
  316. end;
  317. if DontClear=false then ClearEvent(Event);
  318. end;
  319. evBroadcast :
  320. case Event.Command of
  321. cmListItemSelected :
  322. if Event.InfoPtr=pointer(CodeTemplatesLB) then
  323. Message(@Self,evCommand,cmEditItem,nil);
  324. cmListFocusChanged :
  325. if Event.InfoPtr=pointer(CodeTemplatesLB) then
  326. Message(@Self,evBroadcast,cmUpdate,nil);
  327. cmUpdate :
  328. Update;
  329. end;
  330. evCommand :
  331. begin
  332. DontClear:=false;
  333. case Event.Command of
  334. cmAddItem : Add;
  335. cmDeleteItem : Delete;
  336. cmEditItem : Edit;
  337. else DontClear:=true;
  338. end;
  339. if DontClear=false then ClearEvent(Event);
  340. end;
  341. end;
  342. inherited HandleEvent(Event);
  343. end;
  344. function TCodeTemplatesDialog.Execute: Word;
  345. var R: word;
  346. P: PCodeTemplate;
  347. C: PCodeTemplateCollection;
  348. L: PUnsortedStringCollection;
  349. I: integer;
  350. S1,S2,S3: string;
  351. W: word;
  352. begin
  353. New(C, Init(10,20));
  354. if Assigned(CodeTemplates) then
  355. for I:=0 to CodeTemplates^.Count-1 do
  356. begin
  357. P:=CodeTemplates^.At(I);
  358. New(L, Init(10,50));
  359. P^.GetText(L);
  360. C^.Insert(New(PCodeTemplate, Init(P^.GetShortCut,L)));
  361. Dispose(L, Done);
  362. end;
  363. CodeTemplatesLB^.NewList(C);
  364. Update;
  365. R:=inherited Execute;
  366. if R=cmOK then
  367. begin
  368. if Assigned(CodeTemplates) then Dispose(CodeTemplates, Done);
  369. CodeTemplates:=C;
  370. end
  371. else
  372. Dispose(C, Done);
  373. Execute:=R;
  374. end;
  375. procedure TCodeTemplatesDialog.Add;
  376. var P,P2: PCodeTemplate;
  377. IC: boolean;
  378. S: string;
  379. L: PUnsortedStringCollection;
  380. I: sw_integer;
  381. W: word;
  382. Cmd: word;
  383. CanExit: boolean;
  384. begin
  385. New(L, Init(10,10));
  386. IC:=CodeTemplatesLB^.Range=0;
  387. if IC=false then
  388. begin
  389. P:=CodeTemplatesLB^.List^.At(CodeTemplatesLB^.Focused);
  390. P^.GetParams(S,L);
  391. end
  392. else
  393. begin
  394. S:='';
  395. end;
  396. New(P, Init(S,L));
  397. repeat
  398. Cmd:=Application^.ExecuteDialog(New(PCodeTemplateDialog, Init('New template',P)), nil);
  399. CanExit:=(Cmd<>cmOK);
  400. if CanExit=false then
  401. begin
  402. P2:=PCodeTemplateCollection(CodeTemplatesLB^.List)^.SearchByShortCut(P^.GetShortCut);
  403. CanExit:=(Assigned(P2)=false);
  404. if CanExit=false then
  405. ErrorBox('A template named "'+P^.GetShortCut+'" is already in the list',nil);
  406. end;
  407. until CanExit;
  408. if Cmd=cmOK then
  409. begin
  410. CodeTemplatesLB^.List^.Insert(P);
  411. CodeTemplatesLB^.SetRange(CodeTemplatesLB^.List^.Count);
  412. CodeTemplatesLB^.SetFocusedItem(P);
  413. Update;
  414. end
  415. else
  416. Dispose(P, Done);
  417. Dispose(L, Done);
  418. end;
  419. procedure TCodeTemplatesDialog.Edit;
  420. var P,O,P2: PCodeTemplate;
  421. I: sw_integer;
  422. S: string;
  423. L: PUnsortedStringCollection;
  424. Cmd: word;
  425. CanExit: boolean;
  426. begin
  427. if CodeTemplatesLB^.Range=0 then Exit;
  428. New(L, Init(10,10));
  429. I:=CodeTemplatesLB^.Focused;
  430. O:=CodeTemplatesLB^.List^.At(I);
  431. O^.GetParams(S,L);
  432. P:=New(PCodeTemplate, Init(S, L));
  433. repeat
  434. Cmd:=Application^.ExecuteDialog(New(PCodeTemplateDialog, Init('Modify template',P)), nil);
  435. CanExit:=(Cmd<>cmOK);
  436. if CanExit=false then
  437. begin
  438. P2:=PCodeTemplateCollection(CodeTemplatesLB^.List)^.SearchByShortCut(P^.GetShortCut);
  439. CanExit:=(Assigned(P2)=false) or (CodeTemplatesLB^.List^.IndexOf(P2)=I);
  440. if CanExit=false then
  441. ErrorBox('A template named "'+P^.GetShortCut+'" is already in the list',nil);
  442. end;
  443. until CanExit;
  444. if Cmd=cmOK then
  445. begin
  446. with CodeTemplatesLB^ do
  447. begin
  448. List^.AtFree(I); O:=nil;
  449. List^.Insert(P);
  450. SetFocusedItem(P);
  451. end;
  452. Update;
  453. end;
  454. Dispose(L, Done);
  455. end;
  456. procedure TCodeTemplatesDialog.Delete;
  457. begin
  458. if CodeTemplatesLB^.Range=0 then Exit;
  459. CodeTemplatesLB^.List^.AtFree(CodeTemplatesLB^.Focused);
  460. CodeTemplatesLB^.SetRange(CodeTemplatesLB^.List^.Count);
  461. Update;
  462. end;
  463. procedure RegisterCodeTemplates;
  464. begin
  465. {$ifndef NOOBJREG}
  466. RegisterType(RCodeTemplate);
  467. RegisterType(RCodeTemplateCollection);
  468. {$endif}
  469. end;
  470. END.