Authenticate.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736
  1. //---------------------------------------------------------------------------
  2. #include <FormsPCH.h>
  3. #pragma hdrstop
  4. #include "Authenticate.h"
  5. #include <Character.hpp>
  6. //---------------------------------------------------------------------------
  7. #pragma resource "*.dfm"
  8. //---------------------------------------------------------------------------
  9. __fastcall TAuthenticateForm::TAuthenticateForm(TComponent * Owner)
  10. : TForm(Owner), FSessionData(NULL), FTerminal(NULL)
  11. {
  12. }
  13. //---------------------------------------------------------------------------
  14. void __fastcall TAuthenticateForm::Init(TTerminal * Terminal)
  15. {
  16. FTerminal = Terminal;
  17. FSessionData = Terminal->SessionData;
  18. UseSystemSettings(this);
  19. FShowAsModalStorage = NULL;
  20. FFocusControl = NULL;
  21. UseDesktopFont(LogView);
  22. FAnimationPainted = false;
  23. FShowNoActivate = false;
  24. FPromptParent = InstructionsLabel->Parent;
  25. FPromptLeft = InstructionsLabel->Left;
  26. FPromptTop = InstructionsLabel->Top;
  27. FPromptRight = FPromptParent->ClientWidth - InstructionsLabel->Width - FPromptLeft;
  28. FPromptEditGap = PromptEdit1->Top - PromptLabel1->Top - PromptLabel1->Height;
  29. FPromptsGap = PromptLabel2->Top - PromptEdit1->Top - PromptEdit1->Height;
  30. ClientHeight = ScaleByTextHeight(this, 270);
  31. FHorizontalLogPadding = ScaleByTextHeight(this, 4);
  32. FVerticalLogPadding = ScaleByTextHeight(this, 3);
  33. FLogTextFormat << tfNoPrefix << tfWordBreak << tfVerticalCenter;
  34. FHintIndex = -1;
  35. }
  36. //---------------------------------------------------------------------------
  37. __fastcall TAuthenticateForm::~TAuthenticateForm()
  38. {
  39. Application->CancelHint();
  40. if (ReleaseAsModal(this, FShowAsModalStorage))
  41. {
  42. UnhookFormActivation(this);
  43. }
  44. }
  45. //---------------------------------------------------------------------------
  46. void __fastcall TAuthenticateForm::ShowAsModal()
  47. {
  48. if (IsApplicationMinimized())
  49. {
  50. FShowNoActivate = true;
  51. }
  52. // Do not call BringToFront when minimized, so that we do not have to use the same hack as in TMessageForm::SetZOrder
  53. ::ShowAsModal(this, FShowAsModalStorage, !FShowNoActivate, true);
  54. HookFormActivation(this);
  55. }
  56. //---------------------------------------------------------------------------
  57. void __fastcall TAuthenticateForm::CMShowingChanged(TMessage & Message)
  58. {
  59. if (Showing && FShowNoActivate)
  60. {
  61. ShowFormNoActivate(this);
  62. }
  63. else
  64. {
  65. TForm::Dispatch(&Message);
  66. }
  67. }
  68. //---------------------------------------------------------------------------
  69. void __fastcall TAuthenticateForm::WMNCCreate(TWMNCCreate & Message)
  70. {
  71. // bypass TForm::WMNCCreate to prevent disabling "resize"
  72. // (which is done for bsDialog, see comments in CreateParams)
  73. DefaultHandler(&Message);
  74. }
  75. //---------------------------------------------------------------------------
  76. void __fastcall TAuthenticateForm::DoCancel()
  77. {
  78. if (FOnCancel != NULL)
  79. {
  80. FOnCancel(this);
  81. }
  82. }
  83. //---------------------------------------------------------------------------
  84. void __fastcall TAuthenticateForm::Dispatch(void * AMessage)
  85. {
  86. TMessage & Message = *reinterpret_cast<TMessage *>(AMessage);
  87. if (Message.Msg == WM_NCCREATE)
  88. {
  89. WMNCCreate(*reinterpret_cast<TWMNCCreate *>(AMessage));
  90. }
  91. else if (Message.Msg == WM_CLOSE)
  92. {
  93. DoCancel();
  94. TForm::Dispatch(AMessage);
  95. }
  96. else if (Message.Msg == WM_MANAGES_CAPTION)
  97. {
  98. // caption managed in TAuthenticateForm::AdjustControls()
  99. Message.Result = 1;
  100. }
  101. else if (Message.Msg == CM_SHOWINGCHANGED)
  102. {
  103. CMShowingChanged(Message);
  104. }
  105. else
  106. {
  107. TForm::Dispatch(AMessage);
  108. }
  109. }
  110. //---------------------------------------------------------------------------
  111. void __fastcall TAuthenticateForm::CreateParams(TCreateParams & Params)
  112. {
  113. TForm::CreateParams(Params);
  114. // Allow resizing of the window, even if this is bsDialog.
  115. // This makes it more close to bsSizeable, but bsSizeable cannot for some
  116. // reason receive focus, if window is shown atop non-main window
  117. // (like editor)
  118. Params.Style = Params.Style | WS_THICKFRAME;
  119. }
  120. //---------------------------------------------------------------------------
  121. void __fastcall TAuthenticateForm::FormShow(TObject * /*Sender*/)
  122. {
  123. AdjustControls();
  124. if (FFocusControl != NULL)
  125. {
  126. ActiveControl = FFocusControl;
  127. }
  128. UnicodeString AnimationName = FSessionData->IsSecure() ? L"ConnectingSecure" : L"ConnectingInsecure";
  129. FFrameAnimation.Init(AnimationPaintBox, AnimationName);
  130. FFrameAnimation.Start();
  131. }
  132. //---------------------------------------------------------------------------
  133. void __fastcall TAuthenticateForm::Log(const UnicodeString & Message, const UnicodeString & Additional)
  134. {
  135. // HACK
  136. // The first call to Repaint from TFrameAnimation happens
  137. // even before the form is showing. After it is shown it takes sometime too long
  138. // before the animation is painted, so that the form is closed before the first frame even appers
  139. if (!FAnimationPainted && Showing)
  140. {
  141. AnimationPaintBox->Repaint();
  142. FAnimationPainted = true;
  143. }
  144. int Index = LogView->Items->Add(Message);
  145. FHints.push_back(Additional);
  146. MakeLogItemVisible(Index);
  147. LogView->Repaint();
  148. }
  149. //---------------------------------------------------------------------------
  150. void __fastcall TAuthenticateForm::MakeLogItemVisible(int Index)
  151. {
  152. if (Index < LogView->TopIndex)
  153. {
  154. LogView->TopIndex = Index;
  155. }
  156. else
  157. {
  158. int TotalHeight = 0;
  159. int Index2 = Index;
  160. while ((Index2 >= 0) && TotalHeight < LogView->ClientHeight)
  161. {
  162. TotalHeight += LogItemHeight(Index2);
  163. Index2--;
  164. }
  165. // Index2 is the last item above the first fully visible,
  166. // were the Index on the very bottom.
  167. if (LogView->TopIndex <= Index2 + 1)
  168. {
  169. LogView->TopIndex = Index2 + 2;
  170. }
  171. }
  172. }
  173. //---------------------------------------------------------------------------
  174. void __fastcall TAuthenticateForm::AdjustControls()
  175. {
  176. UnicodeString ACaption;
  177. if (FStatus.IsEmpty())
  178. {
  179. ACaption = FSessionData->SessionName;
  180. }
  181. else
  182. {
  183. ACaption = FStatus + TitleSeparator + FSessionData->SessionName;
  184. }
  185. Caption = FormatFormCaption(this, ACaption);
  186. }
  187. //---------------------------------------------------------------------------
  188. TLabel * __fastcall TAuthenticateForm::GenerateLabel(int Current, UnicodeString Caption)
  189. {
  190. TLabel * Result = CreateLabel(this);
  191. Result->Parent = FPromptParent;
  192. ApplyColorModeOnControl(Result); // noop
  193. Result->Anchors = TAnchors() << akLeft << akTop << akRight;
  194. Result->WordWrap = true;
  195. Result->AutoSize = false;
  196. Result->Top = Current;
  197. Result->Left = FPromptLeft;
  198. Result->Caption = Caption;
  199. int Width = FPromptParent->ClientWidth - FPromptLeft - FPromptRight;
  200. Result->Width = Width;
  201. Result->AutoSize = true;
  202. Result->AutoSize = false;
  203. Result->Width = Width;
  204. return Result;
  205. }
  206. //---------------------------------------------------------------------------
  207. TCustomEdit * __fastcall TAuthenticateForm::GenerateEdit(int Current, bool Echo)
  208. {
  209. TEdit * Result = CreateEdit(this);
  210. SetEditPasswordMode(Result, !Echo);
  211. Result->Parent = FPromptParent;
  212. ApplyColorModeOnControl(Result);
  213. Result->Anchors = TAnchors() << akLeft << akTop << akRight;
  214. Result->Top = Current;
  215. Result->Left = FPromptLeft;
  216. Result->Width = FPromptParent->ClientWidth - FPromptLeft - FPromptRight;
  217. return Result;
  218. }
  219. //---------------------------------------------------------------------------
  220. void TAuthenticateForm::ExternalLabel(TLabel * Label)
  221. {
  222. Label->OnContextPopup = LabelContextPopup;
  223. Label->PopupMenu = LabelPopupMenu;
  224. UnicodeString Url;
  225. if (ExtractUrl(Label->Caption, Url))
  226. {
  227. Label->Cursor = crHandPoint;
  228. Label->OnClick = LinkClick;
  229. }
  230. }
  231. //---------------------------------------------------------------------------
  232. TList * __fastcall TAuthenticateForm::GeneratePrompt(
  233. TPromptKind Kind, const UnicodeString & Instructions, TStrings * Prompts)
  234. {
  235. DeleteChildren(FPromptParent);
  236. TList * Result = new TList;
  237. int Current = FPromptTop;
  238. if (!Instructions.IsEmpty())
  239. {
  240. TLabel * Label = GenerateLabel(Current, Instructions);
  241. ExternalLabel(Label);
  242. Current += Label->Height + FPromptsGap;
  243. }
  244. for (int Index = 0; Index < Prompts->Count; Index++)
  245. {
  246. if (Index > 0)
  247. {
  248. Current += FPromptEditGap;
  249. }
  250. TLabel * Label = GenerateLabel(Current, Prompts->Strings[Index]);
  251. if (Kind == pkKeybInteractive)
  252. {
  253. ExternalLabel(Label);
  254. }
  255. Current += Label->Height + FPromptEditGap;
  256. bool Echo = FLAGSET(int(Prompts->Objects[Index]), pupEcho);
  257. TCustomEdit * Edit = GenerateEdit(Current, Echo);
  258. Result->Add(Edit);
  259. Label->FocusControl = Edit;
  260. Current += Edit->Height;
  261. }
  262. FPromptParent->ClientHeight = Current;
  263. return Result;
  264. }
  265. //---------------------------------------------------------------------------
  266. bool __fastcall TAuthenticateForm::PromptUser(TPromptKind Kind, UnicodeString Name,
  267. UnicodeString Instructions, TStrings * Prompts, TStrings * Results, bool ForceLog,
  268. bool StoredCredentialsTried)
  269. {
  270. bool Result;
  271. TList * Edits = GeneratePrompt(Kind, Instructions, Prompts);
  272. try
  273. {
  274. bool ShowSessionRememberPasswordPanel = false;
  275. bool ShowSavePasswordPanel = false;
  276. TSessionData * Data = NULL;
  277. if (IsPasswordPrompt(Kind, Prompts) && StoredCredentialsTried)
  278. {
  279. Data = StoredSessions->FindSame(FSessionData);
  280. ShowSavePasswordPanel = (Data != NULL) && !Data->Password.IsEmpty();
  281. }
  282. // do not offer to remember password,
  283. // if we are offering to save the password to stored site
  284. if (!ShowSavePasswordPanel &&
  285. (Prompts->Count == 1) &&
  286. FLAGSET(int(Prompts->Objects[0]), pupRemember) &&
  287. DebugAlwaysTrue(IsPasswordOrPassphrasePrompt(Kind, Prompts)))
  288. {
  289. ShowSessionRememberPasswordPanel = true;
  290. }
  291. SavePasswordCheck->Checked = false;
  292. SavePasswordPanel->Visible = ShowSavePasswordPanel;
  293. SessionRememberPasswordCheck->Checked = false;
  294. SessionRememberPasswordPanel->Visible = ShowSessionRememberPasswordPanel;
  295. if (PasswordPanel->AutoSize)
  296. {
  297. PasswordPanel->AutoSize = false;
  298. PasswordPanel->AutoSize = true;
  299. }
  300. PasswordPanel->Realign();
  301. DebugAssert(Results->Count == Edits->Count);
  302. for (int Index = 0; Index < Edits->Count; Index++)
  303. {
  304. TCustomEdit * Edit = reinterpret_cast<TCustomEdit *>(Edits->Items[Index]);
  305. Edit->Text = Results->Strings[Index];
  306. }
  307. Result = Execute(Name, PasswordPanel,
  308. ((Edits->Count > 0) ?
  309. reinterpret_cast<TWinControl *>(Edits->Items[0]) :
  310. static_cast<TWinControl *>(PasswordOKButton)),
  311. PasswordOKButton, PasswordCancelButton, true, false, ForceLog);
  312. if (Result)
  313. {
  314. for (int Index = 0; Index < Edits->Count; Index++)
  315. {
  316. TCustomEdit * Edit = reinterpret_cast<TCustomEdit *>(Edits->Items[Index]);
  317. Results->Strings[Index] = Edit->Text;
  318. Prompts->Objects[Index] = (TObject *)
  319. ((int(Prompts->Objects[Index]) & ~pupRemember) |
  320. FLAGMASK(((Index == 0) && SessionRememberPasswordCheck->Checked), pupRemember));
  321. }
  322. if (SavePasswordCheck->Checked)
  323. {
  324. DebugAssert(Data != NULL);
  325. DebugAssert(Results->Count >= 1);
  326. FSessionData->Password = Results->Strings[0];
  327. Data->Password = Results->Strings[0];
  328. // modified only, explicit
  329. StoredSessions->Save(false, true);
  330. }
  331. }
  332. }
  333. __finally
  334. {
  335. delete Edits;
  336. }
  337. return Result;
  338. }
  339. //---------------------------------------------------------------------------
  340. void __fastcall TAuthenticateForm::UpdateBannerFont()
  341. {
  342. if (BannerMonospacedFontAction->Checked)
  343. {
  344. BannerMemo->Font->Name = CustomWinConfiguration->DefaultFixedWidthFontName;
  345. BannerMemo->Font->Size = CustomWinConfiguration->DefaultFixedWidthFontSize;
  346. }
  347. else
  348. {
  349. BannerMemo->ParentFont = true;
  350. }
  351. }
  352. //---------------------------------------------------------------------------
  353. void __fastcall TAuthenticateForm::Banner(const UnicodeString & Banner,
  354. bool & NeverShowAgain, int Options, unsigned int & Params)
  355. {
  356. BannerMemo->Lines->Text = Banner;
  357. NeverShowAgainCheck->Visible = FLAGCLEAR(Options, boDisableNeverShowAgain);
  358. NeverShowAgainCheck->Checked = NeverShowAgain;
  359. BannerMonospacedFontAction->Checked = FLAGSET(Params, bpMonospacedFont);
  360. UpdateBannerFont();
  361. bool Result = Execute(LoadStr(AUTHENTICATION_BANNER), BannerPanel, BannerCloseButton,
  362. BannerCloseButton, BannerCloseButton, false, true, false);
  363. if (Result)
  364. {
  365. NeverShowAgain = NeverShowAgainCheck->Checked;
  366. Params =
  367. (Params & ~bpMonospacedFont) |
  368. FLAGMASK(BannerMonospacedFontAction->Checked, bpMonospacedFont);
  369. }
  370. }
  371. //---------------------------------------------------------------------------
  372. bool __fastcall TAuthenticateForm::Execute(UnicodeString Status, TPanel * Panel,
  373. TWinControl * FocusControl, TButton * DefaultButton, TButton * CancelButton,
  374. bool FixHeight, bool Zoom, bool ForceLog)
  375. {
  376. TModalResult DefaultButtonResult;
  377. TAlign Align = Panel->Align;
  378. try
  379. {
  380. // If not visible yet, the animation was not even initialized yet
  381. if (Visible)
  382. {
  383. FFrameAnimation.Stop();
  384. }
  385. DebugAssert(FStatus.IsEmpty());
  386. FStatus = Status;
  387. DefaultButton->Default = true;
  388. CancelButton->Cancel = true;
  389. DefaultButtonResult = DefaultResult(this);
  390. if (Zoom)
  391. {
  392. Panel->Align = alClient;
  393. }
  394. if (ForceLog || Visible)
  395. {
  396. if (ClientHeight < Panel->Height)
  397. {
  398. ClientHeight = Panel->Height;
  399. }
  400. // Panel being hidden gets not realigned automatically, even if it
  401. // has Align property set
  402. Panel->Top = ClientHeight - Panel->Height;
  403. Panel->Show();
  404. TCursor PrevCursor = Screen->Cursor;
  405. try
  406. {
  407. if (Zoom)
  408. {
  409. TopPanel->Hide();
  410. }
  411. else
  412. {
  413. if (LogView->Items->Count > 0)
  414. {
  415. // To avoid the scrolling effect when setting TopIndex
  416. LogView->Items->BeginUpdate();
  417. try
  418. {
  419. MakeLogItemVisible(LogView->Items->Count - 1);
  420. }
  421. __finally
  422. {
  423. LogView->Items->EndUpdate();
  424. RedrawLog();
  425. }
  426. }
  427. }
  428. Screen->Cursor = crDefault;
  429. if (!Visible)
  430. {
  431. DebugAssert(ForceLog);
  432. ShowAsModal();
  433. }
  434. ActiveControl = FocusControl;
  435. ModalResult = mrNone;
  436. AdjustControls();
  437. do
  438. {
  439. Application->HandleMessage();
  440. }
  441. while (!Application->Terminated && (ModalResult == mrNone));
  442. }
  443. __finally
  444. {
  445. Panel->Hide();
  446. Screen->Cursor = PrevCursor;
  447. if (Zoom)
  448. {
  449. TopPanel->Show();
  450. }
  451. Repaint();
  452. }
  453. }
  454. else
  455. {
  456. int PrevHeight = ClientHeight;
  457. int PrevMinHeight = Constraints->MinHeight;
  458. int PrevMaxHeight = Constraints->MaxHeight;
  459. try
  460. {
  461. Constraints->MinHeight = 0;
  462. ClientHeight = Panel->Height;
  463. if (FixHeight)
  464. {
  465. Constraints->MinHeight = Height;
  466. Constraints->MaxHeight = Height;
  467. }
  468. TopPanel->Hide();
  469. Panel->Show();
  470. FFocusControl = FocusControl;
  471. ShowModal();
  472. }
  473. __finally
  474. {
  475. FFocusControl = NULL;
  476. ClientHeight = PrevHeight;
  477. Constraints->MinHeight = PrevMinHeight;
  478. Constraints->MaxHeight = PrevMaxHeight;
  479. Panel->Hide();
  480. TopPanel->Show();
  481. }
  482. }
  483. }
  484. __finally
  485. {
  486. Panel->Align = Align;
  487. DefaultButton->Default = false;
  488. CancelButton->Cancel = false;
  489. FStatus = L"";
  490. AdjustControls();
  491. FFrameAnimation.Start();
  492. }
  493. bool Result = (ModalResult == DefaultButtonResult);
  494. if (!Result)
  495. {
  496. // This is not nice as it may ultimately route to
  497. // TTerminalThread::Cancel() and throw fatal exception,
  498. // what actually means that any PromptUser call during authentication never
  499. // return false and their fall back/alternative code never occurs.
  500. // It probably needs fixing.
  501. DoCancel();
  502. }
  503. return Result;
  504. }
  505. //---------------------------------------------------------------------------
  506. void __fastcall TAuthenticateForm::HelpButtonClick(TObject * /*Sender*/)
  507. {
  508. FormHelp(this);
  509. }
  510. //---------------------------------------------------------------------------
  511. int __fastcall TAuthenticateForm::LogItemHeight(int Index)
  512. {
  513. UnicodeString S = LogView->Items->Strings[Index];
  514. TRect TextRect(0, 0, LogView->ClientWidth - (2 * FHorizontalLogPadding), 0);
  515. LogView->Canvas->Font = LogView->Font;
  516. LogView->Canvas->TextRect(TextRect, S, FLogTextFormat + (TTextFormat() << tfCalcRect));
  517. int Result = TextRect.Height() + (2 * FVerticalLogPadding);
  518. return Result;
  519. }
  520. //---------------------------------------------------------------------------
  521. void __fastcall TAuthenticateForm::LogViewMeasureItem(TWinControl * /*Control*/, int Index,
  522. int & Height)
  523. {
  524. Height = LogItemHeight(Index);
  525. }
  526. //---------------------------------------------------------------------------
  527. void __fastcall TAuthenticateForm::LogViewDrawItem(TWinControl * /*Control*/, int Index,
  528. TRect & Rect, TOwnerDrawState /*State*/)
  529. {
  530. // Reset back to base colors. We do not want to render selection.
  531. // + At initial phases the canvas font will not yet reflect the desktop font.
  532. LogView->Canvas->Font = LogView->Font;
  533. LogView->Canvas->Brush->Color = LogView->Color;
  534. LogView->Canvas->FillRect(Rect);
  535. // tfVerticalCenter does not seem to center the text,
  536. // so we need to deflate the vertical size too
  537. Rect.Inflate(-FHorizontalLogPadding, -FVerticalLogPadding);
  538. UnicodeString S = LogView->Items->Strings[Index];
  539. LogView->Canvas->TextRect(Rect, S, FLogTextFormat);
  540. }
  541. //---------------------------------------------------------------------------
  542. void __fastcall TAuthenticateForm::RedrawLog()
  543. {
  544. // Redraw including the scrollbar (RDW_FRAME)
  545. RedrawWindow(LogView->Handle, NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW);
  546. }
  547. //---------------------------------------------------------------------------
  548. void __fastcall TAuthenticateForm::FormResize(TObject * /*Sender*/)
  549. {
  550. if (LogView->Showing)
  551. {
  552. // Mainly to avoid the scrolling effect when setting TopIndex
  553. LogView->Items->BeginUpdate();
  554. try
  555. {
  556. // Rebuild the list view to force Windows to resend WM_MEASUREITEM
  557. int ItemIndex = LogView->ItemIndex;
  558. int TopIndex = LogView->TopIndex;
  559. std::unique_ptr<TStringList> Items(new TStringList);
  560. Items->Assign(LogView->Items);
  561. LogView->Items->Assign(Items.get());
  562. LogView->ItemIndex = ItemIndex;
  563. LogView->TopIndex = TopIndex;
  564. }
  565. __finally
  566. {
  567. LogView->Items->EndUpdate();
  568. RedrawLog();
  569. }
  570. }
  571. }
  572. //---------------------------------------------------------------------------
  573. void __fastcall TAuthenticateForm::FormAfterMonitorDpiChanged(TObject *, int OldDPI, int NewDPI)
  574. {
  575. DebugUsedParam2(OldDPI, NewDPI);
  576. // Recreate the list to re-measure the items according to the new font
  577. if (LogView->HandleAllocated() &&
  578. (LogView->Items->Count > 0))
  579. {
  580. std::unique_ptr<TStrings> Items(new TStringList());
  581. Items->AddStrings(LogView->Items);
  582. LogView->Items->Clear();
  583. LogView->Items->AddStrings(Items.get());
  584. MakeLogItemVisible(LogView->Items->Count - 1);
  585. }
  586. }
  587. //---------------------------------------------------------------------------
  588. void __fastcall TAuthenticateForm::BannerMemoContextPopup(TObject * Sender, TPoint & MousePos, bool & Handled)
  589. {
  590. MenuPopup(Sender, MousePos, Handled);
  591. }
  592. //---------------------------------------------------------------------------
  593. void __fastcall TAuthenticateForm::BannerMonospacedFontActionExecute(TObject * /*Sender*/)
  594. {
  595. BannerMonospacedFontAction->Checked = !BannerMonospacedFontAction->Checked;
  596. UpdateBannerFont();
  597. }
  598. //---------------------------------------------------------------------------
  599. void __fastcall TAuthenticateForm::LogViewMouseMove(TObject *, TShiftState, int X, int Y)
  600. {
  601. int Index = LogView->ItemAtPos(TPoint(X, Y), true);
  602. if (FHintIndex != Index)
  603. {
  604. Application->CancelHint();
  605. FHintIndex = Index;
  606. if (Index >= 0)
  607. {
  608. LogView->Hint = FHints[Index];
  609. }
  610. }
  611. }
  612. //---------------------------------------------------------------------------
  613. bool TAuthenticateForm::ExtractUrl(const UnicodeString & Text, UnicodeString & Url)
  614. {
  615. bool Result = false;
  616. UnicodeString Prefix = HttpsProtocol + ProtocolSeparator;
  617. int P = Text.Pos(Prefix);
  618. if (P == 0)
  619. {
  620. Prefix = HttpProtocol + ProtocolSeparator;
  621. P = Text.Pos(Prefix);
  622. }
  623. if (P > 0)
  624. {
  625. Url = Text.SubString(P, Text.Length() - P + 1);
  626. P = 1;
  627. while (P <= Url.Length())
  628. {
  629. #pragma warn -dpr
  630. if (TCharacter::IsWhiteSpace(Url[P]))
  631. #pragma warn .dpr
  632. {
  633. Url.SetLength(P - 1);
  634. }
  635. P++;
  636. }
  637. // At least one letter/digit after the prefix
  638. if ((Url.Length() > Prefix.Length()) &&
  639. (::IsLetter(Url[Prefix.Length() + 1]) || ::IsDigit(Url[Prefix.Length() + 1])))
  640. {
  641. Result = true;
  642. }
  643. }
  644. return Result;
  645. }
  646. //---------------------------------------------------------------------------
  647. void __fastcall TAuthenticateForm::LabelContextPopup(TObject * Sender, const TPoint & MousePos, bool & Handled)
  648. {
  649. TLabel * Label = dynamic_cast<TLabel *>(Sender);
  650. UnicodeString Url;
  651. LabelOpenLinkAction2->Visible = ExtractUrl(Label->Caption, Url);
  652. FContextLabel = Label;
  653. MenuPopup(Sender, MousePos, Handled);
  654. }
  655. //---------------------------------------------------------------------------
  656. void __fastcall TAuthenticateForm::LabelCopyActionExecute(TObject *)
  657. {
  658. if (DebugAlwaysTrue(FContextLabel != NULL))
  659. {
  660. TInstantOperationVisualizer Visualizer;
  661. CopyToClipboard(FContextLabel->Caption);
  662. }
  663. }
  664. //---------------------------------------------------------------------------
  665. void TAuthenticateForm::LabelOpen(TLabel * Label)
  666. {
  667. UnicodeString Url;
  668. if (ExtractUrl(Label->Caption, Url))
  669. {
  670. OpenBrowser(Url);
  671. }
  672. }
  673. //---------------------------------------------------------------------------
  674. void __fastcall TAuthenticateForm::LabelOpenLinkAction2Execute(TObject *)
  675. {
  676. if (DebugAlwaysTrue(FContextLabel != NULL))
  677. {
  678. LabelOpen(FContextLabel);
  679. }
  680. }
  681. //---------------------------------------------------------------------------
  682. void __fastcall TAuthenticateForm::LinkClick(TObject * Sender)
  683. {
  684. LabelOpen(DebugNotNull(dynamic_cast<TLabel *>(Sender)));
  685. }
  686. //---------------------------------------------------------------------------
  687. void __fastcall TAuthenticateForm::CreateWnd()
  688. {
  689. TForm::CreateWnd();
  690. ApplyColorMode(this);
  691. }
  692. //---------------------------------------------------------------------------