fpcodcmp.pas 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. unit FPCodCmp; { CodeComplete }
  2. interface
  3. uses Objects,Drivers,Dialogs,
  4. WUtils,WViews;
  5. type
  6. PCodeCompleteWordList = ^TCodeCompleteWordList;
  7. TCodeCompleteWordList = object(TTextCollection)
  8. end;
  9. PCodeCompleteDialog = ^TCodeCompleteDialog;
  10. TCodeCompleteDialog = object(TCenterDialog)
  11. constructor Init;
  12. function Execute: Word; virtual;
  13. procedure HandleEvent(var Event: TEvent); virtual;
  14. private
  15. CodeCompleteLB : PAdvancedListBox;
  16. RB : PRadioButtons;
  17. procedure Add;
  18. procedure Edit;
  19. procedure Delete;
  20. end;
  21. function FPCompleteCodeWord(const WordS: string; var Text: string): boolean;
  22. procedure InitCodeComplete;
  23. function LoadCodeComplete(var S: TStream): boolean;
  24. function StoreCodeComplete(var S: TStream): boolean;
  25. procedure DoneCodeComplete;
  26. const CodeCompleteWords : PCodeCompleteWordList = nil;
  27. type
  28. TCodeCompleteCase = (ccc_unchanged, ccc_lower, ccc_upper, ccc_mixed);
  29. const
  30. CodeCompleteCase : TCodeCompleteCase = ccc_unchanged;
  31. procedure RegisterCodeComplete;
  32. implementation
  33. uses Views,MsgBox,
  34. {$ifdef FVISION}
  35. FVConsts,
  36. {$else}
  37. Commands,
  38. {$endif}
  39. WEditor,
  40. FPConst,FPString,FPViews;
  41. {$ifndef NOOBJREG}
  42. const
  43. RCodeCompleteWordList: TStreamRec = (
  44. ObjType: 14401;
  45. VmtLink: Ofs(TypeOf(TCodeCompleteWordList)^);
  46. Load: @TCodeCompleteWordList.Load;
  47. Store: @TCodeCompleteWordList.Store
  48. );
  49. {$endif}
  50. function FPCompleteCodeWord(const WordS: string; var Text: string): boolean;
  51. var OK: boolean;
  52. Index: sw_integer;
  53. begin
  54. OK:=Assigned(CodeCompleteWords);
  55. if OK then
  56. begin
  57. Text:=CodeCompleteWords^.Lookup(WordS,Index);
  58. OK:=(Index<>-1) and (length(Text)<>length(WordS));
  59. end;
  60. if OK=false then Text:=''
  61. else case CodeCompleteCase of
  62. ccc_upper : Text:=UpcaseStr(Text);
  63. ccc_lower : Text:=LowcaseStr(Text);
  64. ccc_mixed : Text:=UpCase(Text[1])+LowCaseStr(Copy(Text,2,High(Text)));
  65. end;
  66. FPCompleteCodeWord:=OK;
  67. end;
  68. procedure InitCodeComplete;
  69. var I:integer;
  70. S: string;
  71. begin
  72. if Assigned(CodeCompleteWords) then Exit;
  73. New(CodeCompleteWords, Init(10,10));
  74. for I:=0 to GetReservedWordCount-1 do
  75. begin
  76. S:=LowCaseStr(GetReservedWord(I));
  77. if length(S)>=CodeCompleteMinLen then
  78. CodeCompleteWords^.Insert(NewStr(S));
  79. end;
  80. {
  81. there should be also a user front-end for customizing CodeComplete !
  82. any volunteers to implement? ;) - Gabor
  83. }
  84. end;
  85. function LoadCodeComplete(var S: TStream): boolean;
  86. var C: PCodeCompleteWordList;
  87. OK: boolean;
  88. begin
  89. New(C, Load(S));
  90. OK:=Assigned(C) and (S.Status=stOk);
  91. if OK then
  92. begin
  93. if Assigned(CodeCompleteWords) then Dispose(CodeCompleteWords, Done);
  94. CodeCompleteWords:=C;
  95. S.Read(CodeCompleteCase,Sizeof(TCodeCompleteCase));
  96. end
  97. else
  98. if Assigned(C) then
  99. Dispose(C, Done);
  100. LoadCodeComplete:=OK;
  101. end;
  102. function StoreCodeComplete(var S: TStream): boolean;
  103. var OK: boolean;
  104. begin
  105. OK:=Assigned(CodeCompleteWords);
  106. if OK then
  107. begin
  108. CodeCompleteWords^.Store(S);
  109. S.Write(CodeCompleteCase,Sizeof(TCodeCompleteCase));
  110. OK:=OK and (S.Status=stOK);
  111. end;
  112. StoreCodeComplete:=OK;
  113. end;
  114. procedure DoneCodeComplete;
  115. begin
  116. if Assigned(CodeCompleteWords) then Dispose(CodeCompleteWords, Done);
  117. CodeCompleteWords:=nil;
  118. end;
  119. constructor TCodeCompleteDialog.Init;
  120. var R,R2,R3: TRect;
  121. Items: PSItem;
  122. SB: PScrollBar;
  123. begin
  124. R.Assign(0,0,46,20);
  125. inherited Init(R,dialog_codecomplete);
  126. HelpCtx:=hcCodeCompleteOptions;
  127. GetExtent(R); R.Grow(-3,-2); Inc(R.A.Y); R3.Copy(R); Dec(R.B.X,12);
  128. Dec(R.B.Y,5);
  129. R2.Copy(R); R2.Move(1,0); R2.A.X:=R2.B.X-1;
  130. New(SB, Init(R2)); Insert(SB);
  131. New(CodeCompleteLB, Init(R,1,SB));
  132. Insert(CodeCompleteLB);
  133. R2.Copy(R); R2.Move(0,-1); R2.B.Y:=R2.A.Y+1; Dec(R2.A.X);
  134. Insert(New(PLabel, Init(R2, label_codecomplete_keywords, CodeCompleteLB)));
  135. R.Copy(R3); R.A.Y:=R.B.Y-4; Dec(R.B.X,14); Inc(R.A.X);
  136. Items:=NewSItem('Unc~h~anged',
  137. NewSItem('~L~ower',
  138. NewSItem('~U~pper',
  139. NewSItem('~M~ixed',nil))));
  140. RB:=New(PRadioButtons,Init(R,Items));
  141. RB^.SetData(ord(CodeCompleteCase));
  142. R2.Copy(R); R2.Move(0,-1); R2.B.Y:=R2.A.Y+1; Dec(R2.A.X);
  143. Insert(New(PLabel, Init(R2, 'Case handling', RB)));
  144. Insert(RB);
  145. R.Copy(R3); R.A.X:=R.B.X-10; R.B.Y:=R.A.Y+2;
  146. Insert(New(PButton, Init(R, button_OK, cmOK, bfNormal)));
  147. R.Move(0,2);
  148. Insert(New(PButton, Init(R, button_Edit, cmEditItem, bfDefault)));
  149. R.Move(0,2);
  150. Insert(New(PButton, Init(R, button_New, cmAddItem, bfNormal)));
  151. R.Move(0,2);
  152. Insert(New(PButton, Init(R, button_Delete, cmDeleteItem, bfNormal)));
  153. R.Move(0,2);
  154. Insert(New(PButton, Init(R, button_Cancel, cmCancel, bfNormal)));
  155. SelectNext(false);
  156. end;
  157. procedure TCodeCompleteDialog.HandleEvent(var Event: TEvent);
  158. var DontClear: boolean;
  159. begin
  160. case Event.What of
  161. evKeyDown :
  162. begin
  163. DontClear:=false;
  164. case Event.KeyCode of
  165. kbIns :
  166. Message(@Self,evCommand,cmAddItem,nil);
  167. kbDel :
  168. Message(@Self,evCommand,cmDeleteItem,nil);
  169. else DontClear:=true;
  170. end;
  171. if DontClear=false then ClearEvent(Event);
  172. end;
  173. evBroadcast :
  174. case Event.Command of
  175. cmListItemSelected :
  176. if Event.InfoPtr=pointer(CodeCompleteLB) then
  177. Message(@Self,evCommand,cmEditItem,nil);
  178. end;
  179. evCommand :
  180. begin
  181. DontClear:=false;
  182. case Event.Command of
  183. cmAddItem : Add;
  184. cmDeleteItem : Delete;
  185. cmEditItem : Edit;
  186. else DontClear:=true;
  187. end;
  188. if DontClear=false then ClearEvent(Event);
  189. end;
  190. end;
  191. inherited HandleEvent(Event);
  192. end;
  193. function TCodeCompleteDialog.Execute: Word;
  194. var R: word;
  195. C: PCodeCompleteWordList;
  196. I: integer;
  197. begin
  198. New(C, Init(10,20));
  199. if Assigned(CodeCompleteWords) then
  200. for I:=0 to CodeCompleteWords^.Count-1 do
  201. C^.Insert(NewStr(GetStr(CodeCompleteWords^.At(I))));
  202. CodeCompleteLB^.NewList(C);
  203. R:=inherited Execute;
  204. if R=cmOK then
  205. begin
  206. if Assigned(CodeCompleteWords) then Dispose(CodeCompleteWords, Done);
  207. CodeCompleteWords:=C;
  208. CodeCompleteCase:=TCodeCompleteCase(RB^.Value);
  209. end
  210. else
  211. Dispose(C, Done);
  212. Execute:=R;
  213. end;
  214. procedure TCodeCompleteDialog.Add;
  215. var IC: boolean;
  216. S: string;
  217. P: PString;
  218. Cmd: word;
  219. CanExit: boolean;
  220. I: sw_integer;
  221. begin
  222. IC:=CodeCompleteLB^.Range=0;
  223. if IC=false then
  224. S:=GetStr(CodeCompleteLB^.List^.At(CodeCompleteLB^.Focused))
  225. else
  226. S:='';
  227. repeat
  228. Cmd:=InputBox(dialog_codecomplete_add,label_codecomplete_add_keyword,S,255);
  229. CanExit:=Cmd<>cmOK;
  230. if CanExit=false then
  231. begin
  232. CanExit:=PCodeCompleteWordList(CodeCompleteLB^.List)^.Search(@S,I)=false;
  233. if CanExit=false then
  234. begin
  235. ClearFormatParams; AddFormatParamStr(S);
  236. ErrorBox(msg_codecomplete_alreadyinlist,@FormatParams);
  237. end;
  238. end;
  239. until CanExit;
  240. if Cmd=cmOK then
  241. begin
  242. P:=NewStr(S);
  243. with CodeCompleteLB^ do
  244. begin
  245. List^.Insert(P);
  246. SetRange(List^.Count);
  247. SetFocusedItem(P);
  248. end;
  249. ReDraw;
  250. end;
  251. end;
  252. procedure TCodeCompleteDialog.Edit;
  253. var S: string;
  254. I,T: sw_integer;
  255. Cmd: word;
  256. CanExit: boolean;
  257. P: PString;
  258. begin
  259. if CodeCompleteLB^.Range=0 then Exit;
  260. I:=CodeCompleteLB^.Focused;
  261. S:=GetStr(CodeCompleteLB^.List^.At(I));
  262. repeat
  263. Cmd:=InputBox(dialog_codecomplete_edit,label_codecomplete_edit_keyword,S,255);
  264. CanExit:=Cmd<>cmOK;
  265. if CanExit=false then
  266. begin
  267. CanExit:=PCodeCompleteWordList(CodeCompleteLB^.List)^.Search(@S,T)=false;
  268. CanExit:=CanExit or (T=I);
  269. if CanExit=false then
  270. begin
  271. ClearFormatParams; AddFormatParamStr(S);
  272. ErrorBox(msg_codecomplete_alreadyinlist,@FormatParams);
  273. end;
  274. end;
  275. until CanExit;
  276. if Cmd=cmOK then
  277. begin
  278. P:=NewStr(S);
  279. with CodeCompleteLB^ do
  280. begin
  281. List^.AtFree(I);
  282. List^.Insert(P);
  283. SetFocusedItem(P);
  284. end;
  285. ReDraw;
  286. end;
  287. end;
  288. procedure TCodeCompleteDialog.Delete;
  289. begin
  290. if CodeCompleteLB^.Range=0 then Exit;
  291. CodeCompleteLB^.List^.AtFree(CodeCompleteLB^.Focused);
  292. CodeCompleteLB^.SetRange(CodeCompleteLB^.List^.Count);
  293. ReDraw;
  294. end;
  295. procedure RegisterCodeComplete;
  296. begin
  297. {$ifndef NOOBJREG}
  298. RegisterType(RCodeCompleteWordList);
  299. {$endif}
  300. end;
  301. END.