CompletionForm.pas 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805
  1. {
  2. TIGCC IDE
  3. Copyright (C) 2004 Fréderic Bour
  4. Copyright (C) 2004 Sebastian Reichelt
  5. Copyright (C) 2006-2007 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 SimilarityDistance(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 := l + 1 - i;
  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 := SimilarityDistance(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 (List.Count > 0) and (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 if i = List.Count then
  299. begin
  300. if Similar(Symbol, List[i - 1]) then
  301. T := List[i - 1] + ' ?'#13#10
  302. else
  303. Exit;
  304. end
  305. else
  306. begin
  307. if SimilarityDistance(Symbol, List[i - 1]) < SimilarityDistance(Symbol, List[i]) then
  308. Dec(i);
  309. if Similar(Symbol, List[i]) then
  310. T := List[i] + ' ?'#13#10
  311. else
  312. Exit;
  313. end;
  314. end
  315. else
  316. Exit;
  317. // Show Symbol info
  318. C := List.Completion[i];
  319. if Assigned(C) then
  320. begin
  321. T := T + C.Left + ' ' + C.Right + #13#10 + C.Description;
  322. // Calc hint window position
  323. CompRow := M.Selection.StartRowCol.Row;
  324. P := M.ClientToScreen(M.Selection.StartPoint);
  325. R := HintWindow.CalcHintRect(Screen.Width, T, nil);
  326. Inc(R.Left, P.X + 4);
  327. Inc(R.Right, P.X + 4);
  328. Inc(R.Top, P.Y + 20);
  329. Inc(R.Bottom, P.Y + 20);
  330. LockWindowUpdate(M.ParentWindow);
  331. HintWindow.ActivateHint(R, T);
  332. Result := True;
  333. M.SetFocus;
  334. // Bug with TSourceFileForm ??!!
  335. if Assigned(M.Parent) and (M.Parent is TForm) then
  336. M.Parent.BringToFront;
  337. LockWindowUpdate(0);
  338. end;
  339. end;
  340. end;
  341. procedure TCompForm.CloseSymbolInfo;
  342. begin
  343. if IsWindowVisible(HintWindow.Handle) then
  344. ShowWindow(HintWindow.Handle, SW_HIDE);
  345. end;
  346. procedure TCompForm.ApplyCompletion;
  347. var
  348. i: Integer;
  349. begin
  350. i := CompList.ItemIndex;
  351. if (i >= 0) and (i < List.Count) then
  352. begin
  353. SetWord(List[i]);
  354. CloseCompletion;
  355. end;
  356. end;
  357. // Find Files
  358. function TCompForm.GetFileData(const F: string): string;
  359. var
  360. S: TSourceFile;
  361. Folder: string;
  362. begin
  363. S := MainForm.SourceFiles.FindFileNameOnly(F);
  364. Folder := WithBackslash(TIGCCFolder);
  365. if Assigned(S) and (S is TSourceTextSourceFile) then
  366. Result := TSourceTextSourceFile(S).Content
  367. else if FileExists(ExpandFileName(F)) then
  368. Result := FileToString(ExpandFileName(F))
  369. else if FileExists(Folder + CIncludeLocation + F) then
  370. Result := FileToString(Folder + CIncludeLocation + F)
  371. else if FileExists(Folder + ASMIncludeLocation + F) then
  372. Result := FileToString(Folder + ASMIncludeLocation + F)
  373. else
  374. Result := '';
  375. end;
  376. procedure TCompForm.NeedFile(const FileName: string; out CCFData: string);
  377. var
  378. CCFName: string;
  379. Lst: TStringList;
  380. begin
  381. // Search CCF file
  382. CCFName := WithBackslash(TIGCCFolder) + CompletionLocation + ChangeFileExt(FileName, '.ccf');
  383. if FileExists(CCFName) then
  384. CCFData := FileToString(CCFName)
  385. else
  386. begin
  387. // No CCF ? Generate info from header...
  388. if UpperCase(ExtractFileExt(FileName)) = '.H' then
  389. begin
  390. Lst := TStringList.Create;
  391. Lst.Text := GetFileData(FileName);
  392. if Lst.Count > 0 then
  393. CCFData := MakeCCF_H(FileName, Lst);
  394. Lst.Free;
  395. end;
  396. end;
  397. end;
  398. // Word manipulations
  399. procedure TCompForm.DelimitateWord(const Line: string; var StartPos: Integer; out EndPos: Integer);
  400. const
  401. ValidChars = ['A'..'Z', 'a'..'z', '0'..'9', '_', '$', '#'];
  402. var
  403. i, j, l: Integer;
  404. begin
  405. i := StartPos - 1;
  406. j := StartPos - 1;
  407. l := Length(Line);
  408. // Find start pos
  409. while (i > 0) and (i <= l) and (Line[i] in ValidChars) do
  410. Dec(i);
  411. // Find end pos
  412. while (j > 0) and (j <= l) and (Line[j] in ValidChars) do
  413. Inc(j);
  414. if j = StartPos - 1 then
  415. begin
  416. j := StartPos;
  417. while (j > 0) and (j <= l) and (Line[j] in ValidChars) do
  418. Inc(j);
  419. end;
  420. Dec(j);
  421. Inc(i);
  422. StartPos := i;
  423. EndPos := j;
  424. end;
  425. function TCompForm.GetWord(Full, RemoveSpace: Boolean): string;
  426. var
  427. M: TMemoComponent;
  428. S: string;
  429. T: TTextCell;
  430. StPos, EndPos, l: Integer;
  431. begin
  432. M := Editor;
  433. Result := '';
  434. if Assigned(M) then
  435. begin
  436. T := M.Selection.StartRowCol;
  437. if (T.Row > 0) and (T.Row <= M.LineCount) then
  438. begin
  439. S := M.Lines[T.Row - 1];
  440. StPos := T.Col;
  441. l := Length(S);
  442. if RemoveSpace and (StPos > 1) and (StPos <= l) then
  443. begin
  444. if S[StPos - 1] = ' ' then
  445. Dec(StPos);
  446. while (StPos > 1) and (S[StPos] in ['(', ' ']) do
  447. Dec(StPos);
  448. end;
  449. DelimitateWord(S, StPos, EndPos);
  450. if Full then
  451. Result := Trim(Copy(S, StPos, EndPos - StPos + 1))
  452. else
  453. Result := Trim(Copy(S, StPos, T.Col - StPos));
  454. end;
  455. end;
  456. end;
  457. procedure TCompForm.SetWord(const Value: string);
  458. var
  459. M: TMemoComponent;
  460. begin
  461. M := Editor;
  462. if Assigned(M) then
  463. begin
  464. with M.Selection do
  465. begin
  466. SelectWord;
  467. Text := Value;
  468. end;
  469. end;
  470. end;
  471. // Editor Events
  472. procedure TCompForm.Editor_KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  473. procedure Select(Direction, Page: Boolean);
  474. var
  475. HowMany, i, c: Integer;
  476. begin
  477. i := CompList.ItemIndex;
  478. c := List.Count;
  479. if Page then
  480. HowMany := CompList.Height div CompList.ItemHeight
  481. else
  482. HowMany := 1;
  483. if Direction then
  484. Inc(i, HowMany)
  485. else
  486. Dec(i, HowMany);
  487. if i <= 0 then
  488. CompList.ItemIndex := 0
  489. else if i >= c then
  490. CompList.ItemIndex := c - 1
  491. else
  492. CompList.ItemIndex := i;
  493. end;
  494. var
  495. NewKey: Word;
  496. begin
  497. if Assigned(OldKeyDown) then
  498. OldKeyDown(Sender, Key, Shift);
  499. if Visible then
  500. begin
  501. NewKey := 0;
  502. case Key of
  503. VK_ESCAPE: Close;
  504. VK_RETURN:
  505. begin
  506. ApplyCompletion;
  507. StopKey := True;
  508. end;
  509. VK_UP: Select(False, False);
  510. VK_DOWN: Select(True, False);
  511. VK_PRIOR: Select(False, True);
  512. VK_NEXT: Select(True, True);
  513. VK_HOME: CompList.ItemIndex := 0;
  514. VK_END: CompList.ItemIndex := List.Count - 1;
  515. VK_LEFT, VK_RIGHT:
  516. begin
  517. Editor_Change(Sender);
  518. NewKey := Key;
  519. end;
  520. else
  521. NewKey := Key;
  522. end;
  523. Key := NewKey;
  524. end
  525. else if (Shift = [ssCtrl]) and ((Key = VK_SPACE) or (Key = Ord('M'))) then
  526. begin
  527. Key := 0;
  528. StopKey := True;
  529. ShowCompletion;
  530. end
  531. else if (Shift = [ssCtrl]) and (Key = Ord('J')) then
  532. begin
  533. Key := 0;
  534. StopKey := True;
  535. if TemplateForm.Templates.Count > 0 then
  536. TemplateForm.Show
  537. else
  538. ShowMessage(AddTemplatesMsg);
  539. end
  540. else if (Key in [VK_BACK, VK_ESCAPE]) then // or not (Key in [Ord('A')..Ord('Z'), Ord('0')..Ord('9')
  541. CloseSymbolInfo;
  542. end;
  543. procedure TCompForm.Editor_KeyPress(Sender: TObject; var Key: Char);
  544. begin
  545. if Assigned(OldKeyPress) then
  546. OldKeyPress(Sender, Key);
  547. if StopKey then
  548. begin
  549. Key := #0;
  550. StopKey := False;
  551. end
  552. else
  553. begin
  554. case Key of
  555. '(': if Visible or not IsWindowVisible(HintWindow.Handle) then ShowSymbolInfo;
  556. ')': CloseSymbolInfo;
  557. end;
  558. end;
  559. end;
  560. procedure TCompForm.Editor_Change(Sender: TObject);
  561. var
  562. i: Integer;
  563. M: TMemoComponent;
  564. begin
  565. if Assigned(OldChange) then
  566. OldChange(Sender);
  567. M := Editor;
  568. if Visible then
  569. begin
  570. if Assigned(M) then
  571. begin
  572. if CompRow <> M.Selection.StartRowCol.Row then
  573. CloseCompletion
  574. else
  575. begin
  576. List.Find(GetWord(False, False), i);
  577. CompList.ItemIndex := i;
  578. end;
  579. end
  580. else
  581. CloseCompletion;
  582. end
  583. else if Assigned(M) and (CompRow <> M.Selection.StartRowCol.Row) then
  584. CloseSymbolInfo;
  585. end;
  586. procedure TCompForm.Editor_Enter(Sender: TMemoComponent);
  587. begin
  588. if Assigned(Sender) then
  589. begin
  590. FEditor := Sender;
  591. CloseCompletion;
  592. CloseSymbolInfo;
  593. OldKeyDown := Editor.OnKeyDown;
  594. OldKeyPress := Editor.OnKeyPress;
  595. OldChange := Editor.OnChange;
  596. Editor.OnKeyDown := Editor_KeyDown;
  597. Editor.OnKeyPress := Editor_KeyPress;
  598. Editor.OnChange := Editor_Change;
  599. Editor.OnSelectionChange := Editor_Change;
  600. end
  601. else
  602. begin
  603. FEditor := nil;
  604. OldKeyDown := nil;
  605. OldKeyPress := nil;
  606. OldChange := nil;
  607. end;
  608. end;
  609. procedure TCompForm.Editor_Exit(Sender: TObject);
  610. begin
  611. if Assigned(Editor) then
  612. begin
  613. Editor.OnKeyDown := OldKeyDown;
  614. Editor.OnKeyPress := OldKeyPress;
  615. Editor.OnChange := OldChange;
  616. Editor.OnSelectionChange := OldChange;
  617. end;
  618. CloseSymbolInfo;
  619. if not Focused then
  620. begin
  621. FEditor := nil;
  622. CloseCompletion;
  623. end;
  624. end;
  625. procedure TCompForm.CompListKeyDown(Sender: TObject; var Key: Word;
  626. Shift: TShiftState);
  627. var
  628. M: TMemoComponent;
  629. begin
  630. M := Editor;
  631. if Assigned(M) then
  632. begin
  633. M.HandleKeyDown(Key, Shift);
  634. M.SetFocus;
  635. Key := 0;
  636. end
  637. else
  638. CloseCompletion;
  639. end;
  640. procedure TCompForm.CompListKeyUp(Sender: TObject; var Key: Word;
  641. Shift: TShiftState);
  642. var
  643. M: TMemoComponent;
  644. begin
  645. M := Editor;
  646. if Assigned(M) then
  647. begin
  648. M.HandleKeyUp(Key, Shift);
  649. M.SetFocus;
  650. Key := 0;
  651. end
  652. else
  653. CloseCompletion;
  654. end;
  655. procedure TCompForm.CompListKeyPress(Sender: TObject; var Key: Char);
  656. var
  657. M: TMemoComponent;
  658. begin
  659. M := Editor;
  660. if Assigned(M) then
  661. begin
  662. M.HandleKeyPress(Key);
  663. M.SetFocus;
  664. end;
  665. end;
  666. procedure TCompForm.FindSymbolDecl;
  667. var
  668. i, p: Integer;
  669. Symbol, S: string;
  670. C: TCompletionItem;
  671. SourceFile: TSourceFile;
  672. begin
  673. RebuildList;
  674. Symbol := GetWord(True, True);
  675. if (Symbol <> '') and List.Find(Symbol, i) then
  676. begin
  677. C := List.Completion[i];
  678. if Assigned(C) and (C.SourceFileName <> '') then
  679. begin
  680. SourceFile := MainForm.SourceFiles.FindFileNameOnly(C.SourceFileName);
  681. if SourceFile = nil then
  682. begin
  683. if FileExists(ExpandFileName(C.SourceFileName)) then
  684. SourceFile := MainForm.AddSourceFile(ExpandFileName(C.SourceFileName), True)
  685. else if FileExists(WithBackslash(TIGCCFolder) + CIncludeLocation + C.SourceFileName) then
  686. SourceFile := MainForm.AddSourceFile(WithBackslash(TIGCCFolder) + CIncludeLocation + C.SourceFileName, True)
  687. else if FileExists(WithBackslash(TIGCCFolder) + ASMIncludeLocation + C.SourceFileName) then
  688. SourceFile := MainForm.AddSourceFile(WithBackslash(TIGCCFolder) + ASMIncludeLocation + C.SourceFileName, True)
  689. end;
  690. if Assigned(SourceFile) and (SourceFile is TTextSourceFile) then
  691. with TTextSourceFile(SourceFile).TextEditor do
  692. begin
  693. if (C.Line < Cardinal(Lines.Count)) then
  694. begin
  695. S := Lines[C.Line];
  696. p := Pos(Symbol, S);
  697. if p = 0 then
  698. p := 1;
  699. end
  700. else
  701. p := 1;
  702. Selection.StartRowCol := TextCell(C.Line + 1, p);
  703. Selection.RLength := 0;
  704. Selection.ScrollInView(4);
  705. end
  706. else
  707. ShowMessageFmt(SymbolFileNotFound, [Symbol, C.SourceFileName]);
  708. end;
  709. end;
  710. end;
  711. procedure TCompForm.ActiveControlChange(Sender: TObject);
  712. var
  713. W: TWinControl;
  714. begin
  715. W := Screen.ActiveControl;
  716. if (W = Editor) or (W = Self) or (W = CompList) or (W = TemplateForm) or (W = TemplateForm.TmpltList) then
  717. Exit;
  718. if Assigned(W) and (W is TMemoComponent) then
  719. Editor := TMemoComponent(W)
  720. else
  721. Editor := nil;
  722. if Assigned(OldActiveControlChange) then
  723. OldActiveControlChange(Sender);
  724. end;
  725. procedure TCompForm.SetEditor(const Value: TMemoComponent);
  726. begin
  727. if Value <> FEditor then
  728. begin
  729. Editor_Exit(Self);
  730. Editor_Enter(Value);
  731. FEditor := Value;
  732. end;
  733. end;
  734. end.