CompletionForm.pas 18 KB

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