CompletionForm.pas 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798
  1. {
  2. TIGCC IDE
  3. Copyright (C) 2004 Fréderic Bour
  4. Copyright (C) 2004 Sebastian Reichelt
  5. Copyright (C) 2006 Kevin Kofler
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2, or (at your option)
  9. any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software Foundation,
  16. Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  17. }
  18. unit CompletionForm;
  19. interface
  20. uses
  21. Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, MasterUnit,
  22. Dialogs, StdCtrls, ComCtrls, CodeCompletion, SourceFileUnit, UtilsDos, MemoComponentUnit,
  23. HtFormatting, Menus, ActnList;
  24. const
  25. SymbolFileNotFound = 'Symbol %s is declared in %s, but file can''t be found!';
  26. AddTemplatesMsg = 'To add templates, go to Preferences->Coding';
  27. type
  28. TCompForm = class(TForm)
  29. CompList: TListBox;
  30. CompStatus: TStatusBar;
  31. procedure FormCreate(Sender: TObject);
  32. procedure FormDestroy(Sender: TObject);
  33. procedure FormDeactivate(Sender: TObject);
  34. procedure CompListDrawItem(Control: TWinControl; Index: Integer;
  35. Rect: TRect; State: TOwnerDrawState);
  36. procedure CompListDblClick(Sender: TObject);
  37. procedure CompListKeyDown(Sender: TObject; var Key: Word;
  38. Shift: TShiftState);
  39. procedure CompListKeyUp(Sender: TObject; var Key: Word;
  40. Shift: TShiftState);
  41. procedure CompListKeyPress(Sender: TObject; var Key: Char);
  42. private
  43. procedure SetEditor(const Value: TMemoComponent);
  44. protected
  45. { Déclarations protégées }
  46. C: TCompletionList;
  47. CompRow: Integer;
  48. StopKey: Boolean;
  49. HintWindow: THtHintWindow;
  50. FSourceFile: TSourceFile;
  51. FEditor: TMemoComponent;
  52. procedure CreateParams(var Params: TCreateParams); override;
  53. function GetFileData(const F: string): string;
  54. procedure NeedFile(const FileName: string; out CCFData: string);
  55. protected
  56. // Be informed when active control change :)
  57. OldActiveControlChange: TNotifyEvent;
  58. procedure ActiveControlChange(Sender: TObject);
  59. public
  60. { Déclarations publiques }
  61. // Get & Replace word under caret
  62. procedure DelimitateWord(const Line: string; var StartPos: Integer; out EndPos: Integer);
  63. function GetWord(Full, RemoveSpace: Boolean): string;
  64. procedure SetWord(const Value: string);
  65. // Show Completion Windows
  66. property List: TCompletionList read C;
  67. procedure RebuildList;
  68. procedure ShowCompletion;
  69. procedure CloseCompletion;
  70. procedure ApplyCompletion;
  71. // Show an hint window about the symbol Symbol, or symbol under caret if ''
  72. function ShowSymbolInfo(Symbol: string = ''): Boolean;
  73. procedure CloseSymbolInfo;
  74. // Find symbol declaration
  75. procedure FindSymbolDecl;
  76. protected
  77. OldChange: TNotifyEvent;
  78. OldKeyDown: TKeyEvent;
  79. OldKeyPress: TKeyPressEvent;
  80. // Redirect Event from Editor
  81. procedure Editor_Enter(Sender: TMemoComponent);
  82. procedure Editor_Exit(Sender: TObject);
  83. procedure Editor_KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  84. procedure Editor_KeyPress(Sender: TObject; var Key: Char);
  85. procedure Editor_Change(Sender: TObject);
  86. public
  87. property Editor: TMemoComponent read FEditor write SetEditor;
  88. end;
  89. var
  90. CompForm: TCompForm;
  91. // TIGCC integration
  92. function SourceFileFromEditor(M: TMemoComponent): TSourceFile;
  93. procedure InsertAction(Owner: TComponent; After: TMenuItem; Action: TBasicAction);
  94. procedure InsertsAction(Owner: TComponent; const Afters: array of TMenuItem; Action: TBasicAction);
  95. implementation
  96. uses Types, StrUtils, Math, TmpltForm, MainUnit;
  97. {$R *.dfm}
  98. function SourceFileFromEditor(M: TMemoComponent): TSourceFile;
  99. var
  100. i: Integer;
  101. Lst: TSourceFiles;
  102. Src: TSourceFile;
  103. begin
  104. Lst := MainForm.SourceFiles;
  105. for i := 0 to Lst.Count - 1 do
  106. begin
  107. Src := TSourceFile(Lst.Items[i]);
  108. if Src.Editor = M then
  109. begin
  110. Result := Src;
  111. Exit;
  112. end;
  113. end;
  114. Result := nil;
  115. end;
  116. procedure InsertAction(Owner: TComponent; After: TMenuItem; Action: TBasicAction);
  117. var
  118. Item: TMenuItem;
  119. begin
  120. Item := TMenuItem.Create(Owner);
  121. Item.Action := Action;
  122. with After.Parent do
  123. Insert(IndexOf(After) + 1, Item);
  124. end;
  125. procedure InsertsAction(Owner: TComponent; const Afters: array of TMenuItem; Action: TBasicAction);
  126. var
  127. i: Integer;
  128. begin
  129. for i := Low(Afters) to High(Afters) do
  130. InsertAction(Owner, Afters[i], Action);
  131. end;
  132. // GUI Methods
  133. procedure TCompForm.FormCreate(Sender: TObject);
  134. begin
  135. C := TCompletionList.Create;
  136. C.OnNeedFile := NeedFile;
  137. HintWindow := THtHintWindow.Create(Self);
  138. OldActiveControlChange := Screen.OnActiveControlChange;
  139. Screen.OnActiveControlChange := ActiveControlChange;
  140. end;
  141. procedure TCompForm.FormDestroy(Sender: TObject);
  142. begin
  143. if Assigned(Screen.OnActiveControlChange) then
  144. Screen.OnActiveControlChange := OldActiveControlChange;
  145. HintWindow.Free;
  146. C.Free;
  147. end;
  148. procedure TCompForm.FormDeactivate(Sender: TObject);
  149. var
  150. M: TMemoComponent;
  151. begin
  152. M := Editor;
  153. if (M = nil) or (not M.Focused) then
  154. CloseCompletion;
  155. end;
  156. procedure TCompForm.CreateParams(var Params: TCreateParams);
  157. begin
  158. inherited;
  159. Params.Style := WS_POPUP or WS_SYSMENU or WS_THICKFRAME;
  160. end;
  161. procedure TCompForm.CompListDrawItem(Control: TWinControl; Index: Integer;
  162. Rect: TRect; State: TOwnerDrawState);
  163. const
  164. MinWidth = 62;
  165. var
  166. C: TCompletionItem;
  167. S: string;
  168. Cnv: TCanvas;
  169. Selected: Boolean;
  170. W: Integer;
  171. begin
  172. if (Index >= 0) and (Index < List.Count) then
  173. begin
  174. Cnv := CompList.Canvas;
  175. Selected := odSelected in State;
  176. C := List.Completion[Index];
  177. S := List[Index];
  178. if Assigned(C) then
  179. begin
  180. Cnv.Font.Style := [];
  181. DrawHtText(C.Left, Rect, Cnv, W, Selected);
  182. Inc(Rect.Left, W);
  183. end;
  184. if Rect.Left < MinWidth then
  185. Rect.Left := MinWidth;
  186. Inc(Rect.Left, 2);
  187. Cnv.Font.Style := [fsBold];
  188. DrawHtText(S, Rect, Cnv, W, Selected);
  189. Inc(Rect.Left, W + 2);
  190. if Assigned(C) then
  191. begin
  192. Cnv.Font.Style := [];
  193. DrawHtText(C.Right, Rect, CompList.Canvas, Rect.Left, Selected);
  194. if Selected then
  195. CompStatus.SimpleText := C.Description;
  196. end;
  197. end;
  198. end;
  199. procedure TCompForm.CompListDblClick(Sender: TObject);
  200. begin
  201. ApplyCompletion;
  202. end;
  203. // Completion Tools
  204. procedure TCompForm.RebuildList;
  205. var
  206. S: TSourceFile;
  207. begin
  208. List.Clear;
  209. S := SourceFileFromEditor(Editor);
  210. if Assigned(S) then
  211. begin
  212. if S is TCSourceFile then
  213. List.AddCompletion(MakeCCF_C(ExtractFileName(S.FileName), TCSourceFile(S)))
  214. else if S is THeaderSourceFile then
  215. List.AddCompletion(MakeCCF_H(ExtractFileName(S.FileName), THeaderSourceFile(S).SourceEditor.Lines));
  216. end;
  217. CompList.Count := List.Count;
  218. end;
  219. procedure TCompForm.ShowCompletion;
  220. var
  221. M: TMemoComponent;
  222. P: TPoint;
  223. i: Integer;
  224. begin
  225. M := Editor;
  226. CloseSymbolInfo;
  227. if Assigned(M) then
  228. begin
  229. RebuildList;
  230. CompRow := M.Selection.StartRowCol.Row;
  231. P := M.Selection.StartPoint;
  232. P := M.ClientToScreen(P);
  233. Left := P.X + 4;
  234. Top := P.Y + 20;
  235. List.Find(GetWord(True, False), i);
  236. CompList.ItemIndex := i;
  237. LockWindowUpdate(M.ParentWindow);
  238. Show;
  239. M.SetFocus;
  240. LockWindowUpdate(0);
  241. end;
  242. end;
  243. procedure TCompForm.CloseCompletion;
  244. begin
  245. Hide;
  246. end;
  247. function TCompForm.ShowSymbolInfo(Symbol: string = ''): Boolean;
  248. function Similarity(const A, B: string): Integer;
  249. var
  250. i, l: Integer;
  251. begin
  252. l := Min(Length(A), Length(B));
  253. i := 1;
  254. while (i <= l) and (UpCase(A[i]) = UpCase(B[i])) do
  255. Inc(i);
  256. Result := Abs(i - l);
  257. end;
  258. function Similar(const A, B: string): Boolean;
  259. var
  260. l: Integer;
  261. begin
  262. l := Min(Length(A), Length(B));
  263. Result := Similarity(A, B) < (l shr 1);
  264. end;
  265. var
  266. M: TMemoComponent;
  267. P: TPoint;
  268. R: TRect;
  269. i: Integer;
  270. C: TCompletionItem;
  271. T: string;
  272. begin
  273. CloseCompletion;
  274. Result := False;
  275. if Symbol = '' then
  276. Symbol := GetWord(False, True);
  277. if Symbol = '' then
  278. begin
  279. CloseSymbolInfo;
  280. Exit;
  281. end;
  282. M := Editor;
  283. if Assigned(M) then
  284. begin
  285. RebuildList;
  286. // Find Symbol
  287. if List.Find(Symbol, i) then
  288. T := ''
  289. else if (i >= 0) and (i < List.Count) then
  290. begin
  291. if i = 0 then
  292. begin
  293. if Similar(Symbol, List[i]) then
  294. T := List[i] + ' ?'#13#10
  295. else
  296. Exit;
  297. end
  298. else
  299. begin
  300. if Similarity(Symbol, List[i - 1]) < Similarity(Symbol, List[i]) then
  301. Dec(i);
  302. if Similar(Symbol, List[i]) then
  303. T := List[i] + ' ?'#13#10
  304. else
  305. Exit;
  306. end;
  307. end
  308. else
  309. Exit;
  310. // Show Symbol info
  311. C := List.Completion[i];
  312. if Assigned(C) then
  313. begin
  314. T := T + C.Left + ' ' + C.Right + #13#10 + C.Description;
  315. // Calc hint window position
  316. CompRow := M.Selection.StartRowCol.Row;
  317. P := M.ClientToScreen(M.Selection.StartPoint);
  318. R := HintWindow.CalcHintRect(Screen.Width, T, nil);
  319. Inc(R.Left, P.X + 4);
  320. Inc(R.Right, P.X + 4);
  321. Inc(R.Top, P.Y + 20);
  322. Inc(R.Bottom, P.Y + 20);
  323. LockWindowUpdate(M.ParentWindow);
  324. HintWindow.ActivateHint(R, T);
  325. Result := True;
  326. M.SetFocus;
  327. // Bug with TSourceFileForm ??!!
  328. if Assigned(M.Parent) and (M.Parent is TForm) then
  329. M.Parent.BringToFront;
  330. LockWindowUpdate(0);
  331. end;
  332. end;
  333. end;
  334. procedure TCompForm.CloseSymbolInfo;
  335. begin
  336. if IsWindowVisible(HintWindow.Handle) then
  337. ShowWindow(HintWindow.Handle, SW_HIDE);
  338. end;
  339. procedure TCompForm.ApplyCompletion;
  340. var
  341. i: Integer;
  342. begin
  343. i := CompList.ItemIndex;
  344. if (i >= 0) and (i < List.Count) then
  345. begin
  346. SetWord(List[i]);
  347. CloseCompletion;
  348. end;
  349. end;
  350. // Find Files
  351. function TCompForm.GetFileData(const F: string): string;
  352. var
  353. S: TSourceFile;
  354. Folder: string;
  355. begin
  356. S := MainForm.SourceFiles.FindFileNameOnly(F);
  357. Folder := WithBackslash(TIGCCFolder);
  358. if Assigned(S) and (S is TSourceTextSourceFile) then
  359. Result := TSourceTextSourceFile(S).Content
  360. else if FileExists(ExpandFileName(F)) then
  361. Result := FileToString(ExpandFileName(F))
  362. else if FileExists(Folder + CIncludeLocation + F) then
  363. Result := FileToString(Folder + CIncludeLocation + F)
  364. else if FileExists(Folder + ASMIncludeLocation + F) then
  365. Result := FileToString(Folder + ASMIncludeLocation + F)
  366. else
  367. Result := '';
  368. end;
  369. procedure TCompForm.NeedFile(const FileName: string; out CCFData: string);
  370. var
  371. CCFName: string;
  372. Lst: TStringList;
  373. begin
  374. // Search CCF file
  375. CCFName := WithBackslash(TIGCCFolder) + CompletionLocation + ChangeFileExt(FileName, '.ccf');
  376. if FileExists(CCFName) then
  377. CCFData := FileToString(CCFName)
  378. else
  379. begin
  380. // No CCF ? Generate info from header...
  381. if UpperCase(ExtractFileExt(FileName)) = '.H' then
  382. begin
  383. Lst := TStringList.Create;
  384. Lst.Text := GetFileData(FileName);
  385. if Lst.Count > 0 then
  386. CCFData := MakeCCF_H(FileName, Lst);
  387. Lst.Free;
  388. end;
  389. end;
  390. end;
  391. // Word manipulations
  392. procedure TCompForm.DelimitateWord(const Line: string; var StartPos: Integer; out EndPos: Integer);
  393. const
  394. ValidChars = ['A'..'Z', 'a'..'z', '0'..'9', '_', '$', '#'];
  395. var
  396. i, j, l: Integer;
  397. begin
  398. i := StartPos - 1;
  399. j := StartPos - 1;
  400. l := Length(Line);
  401. // Find start pos
  402. while (i > 0) and (i <= l) and (Line[i] in ValidChars) do
  403. Dec(i);
  404. // Find end pos
  405. while (j > 0) and (j <= l) and (Line[j] in ValidChars) do
  406. Inc(j);
  407. if j = StartPos - 1 then
  408. begin
  409. j := StartPos;
  410. while (j > 0) and (j <= l) and (Line[j] in ValidChars) do
  411. Inc(j);
  412. end;
  413. Dec(j);
  414. Inc(i);
  415. StartPos := i;
  416. EndPos := j;
  417. end;
  418. function TCompForm.GetWord(Full, RemoveSpace: Boolean): string;
  419. var
  420. M: TMemoComponent;
  421. S: string;
  422. T: TTextCell;
  423. StPos, EndPos, l: Integer;
  424. begin
  425. M := Editor;
  426. Result := '';
  427. if Assigned(M) then
  428. begin
  429. T := M.Selection.StartRowCol;
  430. if (T.Row > 0) and (T.Row <= M.LineCount) then
  431. begin
  432. S := M.Lines[T.Row - 1];
  433. StPos := T.Col;
  434. l := Length(S);
  435. if RemoveSpace and (StPos > 1) and (StPos <= l) then
  436. begin
  437. if S[StPos - 1] = ' ' then
  438. Dec(StPos);
  439. while (StPos > 1) and (S[StPos] in ['(', ' ']) do
  440. Dec(StPos);
  441. end;
  442. DelimitateWord(S, StPos, EndPos);
  443. if Full then
  444. Result := Trim(Copy(S, StPos, EndPos - StPos + 1))
  445. else
  446. Result := Trim(Copy(S, StPos, T.Col - StPos));
  447. end;
  448. end;
  449. end;
  450. procedure TCompForm.SetWord(const Value: string);
  451. var
  452. M: TMemoComponent;
  453. begin
  454. M := Editor;
  455. if Assigned(M) then
  456. begin
  457. with M.Selection do
  458. begin
  459. SelectWord;
  460. Text := Value;
  461. end;
  462. end;
  463. end;
  464. // Editor Events
  465. procedure TCompForm.Editor_KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  466. procedure Select(Direction, Page: Boolean);
  467. var
  468. HowMany, i, c: Integer;
  469. begin
  470. i := CompList.ItemIndex;
  471. c := List.Count;
  472. if Page then
  473. HowMany := CompList.Height div CompList.ItemHeight
  474. else
  475. HowMany := 1;
  476. if Direction then
  477. Inc(i, HowMany)
  478. else
  479. Dec(i, HowMany);
  480. if i <= 0 then
  481. CompList.ItemIndex := 0
  482. else if i >= c then
  483. CompList.ItemIndex := c - 1
  484. else
  485. CompList.ItemIndex := i;
  486. end;
  487. var
  488. NewKey: Word;
  489. begin
  490. if Assigned(OldKeyDown) then
  491. OldKeyDown(Sender, Key, Shift);
  492. if Visible then
  493. begin
  494. NewKey := 0;
  495. case Key of
  496. VK_ESCAPE: Close;
  497. VK_RETURN:
  498. begin
  499. ApplyCompletion;
  500. StopKey := True;
  501. end;
  502. VK_UP: Select(False, False);
  503. VK_DOWN: Select(True, False);
  504. VK_PRIOR: Select(False, True);
  505. VK_NEXT: Select(True, True);
  506. VK_HOME: CompList.ItemIndex := 0;
  507. VK_END: CompList.ItemIndex := List.Count - 1;
  508. VK_LEFT, VK_RIGHT:
  509. begin
  510. Editor_Change(Sender);
  511. NewKey := Key;
  512. end;
  513. else
  514. NewKey := Key;
  515. end;
  516. Key := NewKey;
  517. end
  518. else if (Shift = [ssCtrl]) and ((Key = VK_SPACE) or (Key = Ord('M'))) then
  519. begin
  520. Key := 0;
  521. StopKey := True;
  522. ShowCompletion;
  523. end
  524. else if (Shift = [ssCtrl]) and (Key = Ord('J')) then
  525. begin
  526. Key := 0;
  527. StopKey := True;
  528. if TemplateForm.Templates.Count > 0 then
  529. TemplateForm.Show
  530. else
  531. ShowMessage(AddTemplatesMsg);
  532. end
  533. else if (Key in [VK_BACK, VK_ESCAPE]) then // or not (Key in [Ord('A')..Ord('Z'), Ord('0')..Ord('9')
  534. CloseSymbolInfo;
  535. end;
  536. procedure TCompForm.Editor_KeyPress(Sender: TObject; var Key: Char);
  537. begin
  538. if Assigned(OldKeyPress) then
  539. OldKeyPress(Sender, Key);
  540. if StopKey then
  541. begin
  542. Key := #0;
  543. StopKey := False;
  544. end
  545. else
  546. begin
  547. case Key of
  548. '(': if Visible or not IsWindowVisible(HintWindow.Handle) then ShowSymbolInfo;
  549. ')': CloseSymbolInfo;
  550. end;
  551. end;
  552. end;
  553. procedure TCompForm.Editor_Change(Sender: TObject);
  554. var
  555. i: Integer;
  556. M: TMemoComponent;
  557. begin
  558. if Assigned(OldChange) then
  559. OldChange(Sender);
  560. M := Editor;
  561. if Visible then
  562. begin
  563. if Assigned(M) then
  564. begin
  565. if CompRow <> M.Selection.StartRowCol.Row then
  566. CloseCompletion
  567. else
  568. begin
  569. List.Find(GetWord(False, False), i);
  570. CompList.ItemIndex := i;
  571. end;
  572. end
  573. else
  574. CloseCompletion;
  575. end
  576. else if Assigned(M) and (CompRow <> M.Selection.StartRowCol.Row) then
  577. CloseSymbolInfo;
  578. end;
  579. procedure TCompForm.Editor_Enter(Sender: TMemoComponent);
  580. begin
  581. if Assigned(Sender) then
  582. begin
  583. FEditor := Sender;
  584. CloseCompletion;
  585. CloseSymbolInfo;
  586. OldKeyDown := Editor.OnKeyDown;
  587. OldKeyPress := Editor.OnKeyPress;
  588. OldChange := Editor.OnChange;
  589. Editor.OnKeyDown := Editor_KeyDown;
  590. Editor.OnKeyPress := Editor_KeyPress;
  591. Editor.OnChange := Editor_Change;
  592. Editor.OnSelectionChange := Editor_Change;
  593. end
  594. else
  595. begin
  596. FEditor := nil;
  597. OldKeyDown := nil;
  598. OldKeyPress := nil;
  599. OldChange := nil;
  600. end;
  601. end;
  602. procedure TCompForm.Editor_Exit(Sender: TObject);
  603. begin
  604. if Assigned(Editor) then
  605. begin
  606. Editor.OnKeyDown := OldKeyDown;
  607. Editor.OnKeyPress := OldKeyPress;
  608. Editor.OnChange := OldChange;
  609. Editor.OnSelectionChange := OldChange;
  610. end;
  611. CloseSymbolInfo;
  612. if not Focused then
  613. begin
  614. FEditor := nil;
  615. CloseCompletion;
  616. end;
  617. end;
  618. procedure TCompForm.CompListKeyDown(Sender: TObject; var Key: Word;
  619. Shift: TShiftState);
  620. var
  621. M: TMemoComponent;
  622. begin
  623. M := Editor;
  624. if Assigned(M) then
  625. begin
  626. M.HandleKeyDown(Key, Shift);
  627. M.SetFocus;
  628. Key := 0;
  629. end
  630. else
  631. CloseCompletion;
  632. end;
  633. procedure TCompForm.CompListKeyUp(Sender: TObject; var Key: Word;
  634. Shift: TShiftState);
  635. var
  636. M: TMemoComponent;
  637. begin
  638. M := Editor;
  639. if Assigned(M) then
  640. begin
  641. M.HandleKeyUp(Key, Shift);
  642. M.SetFocus;
  643. Key := 0;
  644. end
  645. else
  646. CloseCompletion;
  647. end;
  648. procedure TCompForm.CompListKeyPress(Sender: TObject; var Key: Char);
  649. var
  650. M: TMemoComponent;
  651. begin
  652. M := Editor;
  653. if Assigned(M) then
  654. begin
  655. M.HandleKeyPress(Key);
  656. M.SetFocus;
  657. end;
  658. end;
  659. procedure TCompForm.FindSymbolDecl;
  660. var
  661. i, p: Integer;
  662. Symbol, S: string;
  663. C: TCompletionItem;
  664. SourceFile: TSourceFile;
  665. begin
  666. RebuildList;
  667. Symbol := GetWord(True, True);
  668. if (Symbol <> '') and List.Find(Symbol, i) then
  669. begin
  670. C := List.Completion[i];
  671. if Assigned(C) and (C.SourceFileName <> '') then
  672. begin
  673. SourceFile := MainForm.SourceFiles.FindFileNameOnly(C.SourceFileName);
  674. if SourceFile = nil then
  675. begin
  676. if FileExists(ExpandFileName(C.SourceFileName)) then
  677. SourceFile := MainForm.AddSourceFile(ExpandFileName(C.SourceFileName), True)
  678. else if FileExists(WithBackslash(TIGCCFolder) + CIncludeLocation + C.SourceFileName) then
  679. SourceFile := MainForm.AddSourceFile(WithBackslash(TIGCCFolder) + CIncludeLocation + C.SourceFileName, True)
  680. else if FileExists(WithBackslash(TIGCCFolder) + ASMIncludeLocation + C.SourceFileName) then
  681. SourceFile := MainForm.AddSourceFile(WithBackslash(TIGCCFolder) + ASMIncludeLocation + C.SourceFileName, True)
  682. end;
  683. if Assigned(SourceFile) and (SourceFile is TTextSourceFile) then
  684. with TTextSourceFile(SourceFile).TextEditor do
  685. begin
  686. if (C.Line < Cardinal(Lines.Count)) then
  687. begin
  688. S := Lines[C.Line];
  689. p := Pos(Symbol, S);
  690. if p = 0 then
  691. p := 1;
  692. end
  693. else
  694. p := 1;
  695. Selection.StartRowCol := TextCell(C.Line + 1, p);
  696. Selection.RLength := 0;
  697. Selection.ScrollInView(4);
  698. end
  699. else
  700. ShowMessageFmt(SymbolFileNotFound, [Symbol, C.SourceFileName]);
  701. end;
  702. end;
  703. end;
  704. procedure TCompForm.ActiveControlChange(Sender: TObject);
  705. var
  706. W: TWinControl;
  707. begin
  708. W := Screen.ActiveControl;
  709. if (W = Editor) or (W = Self) or (W = CompList) or (W = TemplateForm) or (W = TemplateForm.TmpltList) then
  710. Exit;
  711. if Assigned(W) and (W is TMemoComponent) then
  712. Editor := TMemoComponent(W)
  713. else
  714. Editor := nil;
  715. if Assigned(OldActiveControlChange) then
  716. OldActiveControlChange(Sender);
  717. end;
  718. procedure TCompForm.SetEditor(const Value: TMemoComponent);
  719. begin
  720. if Value <> FEditor then
  721. begin
  722. Editor_Exit(Self);
  723. Editor_Enter(Value);
  724. FEditor := Value;
  725. end;
  726. end;
  727. end.