UserInterface.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. //---------------------------------------------------------------------------
  2. #include <vcl.h>
  3. #pragma hdrstop
  4. #include "ScpCommander.h"
  5. #include "ScpExplorer.h"
  6. #include <CoreMain.h>
  7. #include <Common.h>
  8. #include <Exceptions.h>
  9. #include "ProgParams.h"
  10. #include "VCLCommon.h"
  11. #include "WinConfiguration.h"
  12. #include "TerminalManager.h"
  13. #include "TextsWin.h"
  14. #include "TBXThemes.hpp"
  15. #include "TBXOfficeXPTheme.hpp"
  16. #include "TBXOffice2003Theme.hpp"
  17. //---------------------------------------------------------------------------
  18. #pragma package(smart_init)
  19. //---------------------------------------------------------------------------
  20. const AnsiString AppName = "WinSCP";
  21. const AnsiString AppNameVersion = "WinSCP";
  22. //---------------------------------------------------------------------------
  23. TConfiguration * __fastcall CreateConfiguration()
  24. {
  25. TConfiguration * Configuration = new TWinConfiguration();
  26. TProgramParams * Params = TProgramParams::Instance();
  27. AnsiString IniFileName = Params->SwitchValue("ini");
  28. if (!IniFileName.IsEmpty())
  29. {
  30. IniFileName = ExpandFileName(ExpandEnvironmentVariables(IniFileName));
  31. Configuration->IniFileStorageName = IniFileName;
  32. }
  33. return Configuration;
  34. }
  35. //---------------------------------------------------------------------------
  36. TCustomScpExplorerForm * __fastcall CreateScpExplorer()
  37. {
  38. TCustomScpExplorerForm * ScpExplorer;
  39. if (WinConfiguration->Interface == ifExplorer)
  40. {
  41. ScpExplorer = SafeFormCreate<TScpExplorerForm>();
  42. }
  43. else
  44. {
  45. ScpExplorer = SafeFormCreate<TScpCommanderForm>();
  46. }
  47. ScpExplorer->Icon->Assign(Application->Icon);
  48. return ScpExplorer;
  49. }
  50. //---------------------------------------------------------------------------
  51. AnsiString __fastcall SshVersionString()
  52. {
  53. return FORMAT("WinSCP-release-%s", (Configuration->Version));
  54. }
  55. //---------------------------------------------------------------------------
  56. AnsiString __fastcall GetRegistryKey()
  57. {
  58. return "Software\\Martin Prikryl\\WinSCP 2";
  59. }
  60. //---------------------------------------------------------------------------
  61. static bool ForcedOnForeground = false;
  62. void __fastcall SetOnForeground(bool OnForeground)
  63. {
  64. ForcedOnForeground = OnForeground;
  65. }
  66. //---------------------------------------------------------------------------
  67. void __fastcall FlashOnBackground()
  68. {
  69. assert(Application);
  70. if (!ForcedOnForeground && !ForegroundTask())
  71. {
  72. FlashWindow(Application->Handle, true);
  73. }
  74. }
  75. //---------------------------------------------------------------------------
  76. void __fastcall ShowExtendedException(Exception * E)
  77. {
  78. ShowExtendedExceptionEx(NULL, E);
  79. }
  80. //---------------------------------------------------------------------------
  81. void __fastcall ShowExtendedExceptionEx(TTerminal * Terminal,
  82. Exception * E)
  83. {
  84. if (!E->Message.IsEmpty())
  85. {
  86. if (E->InheritsFrom(__classid(Exception)))
  87. {
  88. if (!E->InheritsFrom(__classid(EAbort)))
  89. {
  90. TTerminalManager * Manager = TTerminalManager::Instance(false);
  91. TQueryType Type;
  92. bool CloseOnCompletion = (dynamic_cast<ESshTerminate*>(E) != NULL);
  93. Type = CloseOnCompletion ? qtInformation : qtError;
  94. if (E->InheritsFrom(__classid(EFatal)) && (Terminal != NULL) &&
  95. (Manager != NULL) && (Manager->ActiveTerminal == Terminal))
  96. {
  97. if (CloseOnCompletion)
  98. {
  99. Manager->DisconnectActiveTerminal();
  100. }
  101. int Result;
  102. if (CloseOnCompletion)
  103. {
  104. if (WinConfiguration->ConfirmExitOnCompletion)
  105. {
  106. TMessageParams Params(mpNeverAskAgainCheck);
  107. Result = FatalExceptionMessageDialog(E, Type,
  108. Manager->Count > 1 ?
  109. FMTLOAD(DISCONNECT_ON_COMPLETION, (Manager->Count - 1)) :
  110. LoadStr(EXIT_ON_COMPLETION),
  111. qaYes | qaNo, HELP_NONE, &Params);
  112. if (Result == qaNeverAskAgain)
  113. {
  114. Result = qaYes;
  115. WinConfiguration->ConfirmExitOnCompletion = false;
  116. }
  117. }
  118. else
  119. {
  120. Result = qaYes;
  121. }
  122. }
  123. else
  124. {
  125. Result = FatalExceptionMessageDialog(E, Type);
  126. }
  127. if (Result == qaYes)
  128. {
  129. Application->Terminate();
  130. }
  131. else if (Result == qaRetry)
  132. {
  133. Manager->ReconnectActiveTerminal();
  134. }
  135. else
  136. {
  137. Manager->FreeActiveTerminal();
  138. }
  139. }
  140. else
  141. {
  142. if (CloseOnCompletion)
  143. {
  144. if (WinConfiguration->ConfirmExitOnCompletion)
  145. {
  146. TMessageParams Params(mpNeverAskAgainCheck);
  147. if (ExceptionMessageDialog(E, Type, "", qaOK, HELP_NONE, &Params) ==
  148. qaNeverAskAgain)
  149. {
  150. WinConfiguration->ConfirmExitOnCompletion = false;
  151. }
  152. }
  153. }
  154. else
  155. {
  156. ExceptionMessageDialog(E, Type);
  157. }
  158. }
  159. }
  160. }
  161. else
  162. {
  163. FlashOnBackground();
  164. ShowException(ExceptObject(), ExceptAddr());
  165. }
  166. }
  167. }
  168. //---------------------------------------------------------------------------
  169. void __fastcall ShowNotification(TTerminal * Terminal, const AnsiString & Str,
  170. TQueryType Type)
  171. {
  172. TTerminalManager * Manager = TTerminalManager::Instance(false);
  173. assert(Manager != NULL);
  174. Manager->ScpExplorer->PopupTrayBalloon(Terminal, Str, Type);
  175. }
  176. //---------------------------------------------------------------------------
  177. void __fastcall ConfigureInterface()
  178. {
  179. AnsiString S;
  180. S = LoadStr(MIDDLE_EAST);
  181. if (!S.IsEmpty())
  182. {
  183. SysLocale.MiddleEast = static_cast<bool>(StrToInt(S));
  184. }
  185. else
  186. {
  187. SysLocale.MiddleEast = false;
  188. }
  189. S = LoadStr(BIDI_MODE);
  190. if (!S.IsEmpty())
  191. {
  192. Application->BiDiMode = static_cast<TBiDiMode>(StrToInt(bdRightToLeft));
  193. }
  194. else
  195. {
  196. Application->BiDiMode = bdLeftToRight;
  197. }
  198. SetTBXSysParam(TSP_XPVISUALSTYLE, XPVS_AUTOMATIC);
  199. // Can be called during configuration creation.
  200. // Skip now, will be called again later.
  201. if (Configuration != NULL)
  202. {
  203. TBXSetTheme(WinConfiguration->Theme);
  204. }
  205. }
  206. //---------------------------------------------------------------------------
  207. // dummy function to force linking of TBXOfficeXPTheme.pas
  208. void __fastcall CreateThemes()
  209. {
  210. new TTBXOfficeXPTheme("OfficeXP");
  211. new TTBXOffice2003Theme("Office2003");
  212. }
  213. //---------------------------------------------------------------------------
  214. void __fastcall DoAboutDialog(TConfiguration *Configuration)
  215. {
  216. DoAboutDialog(Configuration, true, NULL);
  217. }
  218. //---------------------------------------------------------------------
  219. void __fastcall DoProductLicense()
  220. {
  221. DoLicenseDialog(lcWinScp);
  222. }
  223. //---------------------------------------------------------------------
  224. static inline void __fastcall GetToolbarKey(const AnsiString & ToolbarName,
  225. const AnsiString & Value, AnsiString & ToolbarKey)
  226. {
  227. int ToolbarNameLen;
  228. if ((ToolbarName.Length() > 7) &&
  229. (ToolbarName.SubString(ToolbarName.Length() - 7 + 1, 7) == "Toolbar"))
  230. {
  231. ToolbarNameLen = ToolbarName.Length() - 7;
  232. }
  233. else
  234. {
  235. ToolbarNameLen = ToolbarName.Length();
  236. }
  237. ToolbarKey = ToolbarName.SubString(1, ToolbarNameLen) + "_" + Value;
  238. }
  239. //---------------------------------------------------------------------------
  240. static int __fastcall ToolbarReadInt(const AnsiString ToolbarName,
  241. const AnsiString Value, const int Default, const void * ExtraData)
  242. {
  243. int Result;
  244. if (Value == "Rev")
  245. {
  246. Result = 2000;
  247. }
  248. else
  249. {
  250. TStrings * Storage = static_cast<TStrings *>(const_cast<void*>(ExtraData));
  251. AnsiString ToolbarKey;
  252. GetToolbarKey(ToolbarName, Value, ToolbarKey);
  253. if (Storage->IndexOfName(ToolbarKey) >= 0)
  254. {
  255. Result = StrToIntDef(Storage->Values[ToolbarKey], Default);
  256. }
  257. else
  258. {
  259. Result = Default;
  260. }
  261. }
  262. return Result;
  263. }
  264. //---------------------------------------------------------------------------
  265. static AnsiString __fastcall ToolbarReadString(const AnsiString ToolbarName,
  266. const AnsiString Value, const AnsiString Default, const void * ExtraData)
  267. {
  268. AnsiString Result;
  269. TStrings * Storage = static_cast<TStrings *>(const_cast<void*>(ExtraData));
  270. AnsiString ToolbarKey;
  271. GetToolbarKey(ToolbarName, Value, ToolbarKey);
  272. if (Storage->IndexOfName(ToolbarKey) >= 0)
  273. {
  274. Result = Storage->Values[ToolbarKey];
  275. }
  276. else
  277. {
  278. Result = Default;
  279. }
  280. return Result;
  281. }
  282. //---------------------------------------------------------------------------
  283. static void __fastcall ToolbarWriteInt(const AnsiString ToolbarName,
  284. const AnsiString Value, const int Data, const void * ExtraData)
  285. {
  286. if (Value != "Rev")
  287. {
  288. TStrings * Storage = static_cast<TStrings *>(const_cast<void*>(ExtraData));
  289. AnsiString ToolbarKey;
  290. GetToolbarKey(ToolbarName, Value, ToolbarKey);
  291. assert(Storage->IndexOfName(ToolbarKey) < 0);
  292. Storage->Values[ToolbarKey] = IntToStr(Data);
  293. }
  294. }
  295. //---------------------------------------------------------------------------
  296. static void __fastcall ToolbarWriteString(const AnsiString ToolbarName,
  297. const AnsiString Value, const AnsiString Data, const void * ExtraData)
  298. {
  299. TStrings * Storage = static_cast<TStrings *>(const_cast<void*>(ExtraData));
  300. AnsiString ToolbarKey;
  301. GetToolbarKey(ToolbarName, Value, ToolbarKey);
  302. assert(Storage->IndexOfName(ToolbarKey) < 0);
  303. Storage->Values[ToolbarKey] = Data;
  304. }
  305. //---------------------------------------------------------------------------
  306. AnsiString __fastcall GetToolbarsLayoutStr(const TComponent * OwnerComponent)
  307. {
  308. AnsiString Result;
  309. TStrings * Storage = new TStringList();
  310. try
  311. {
  312. TBCustomSavePositions(OwnerComponent, ToolbarWriteInt, ToolbarWriteString,
  313. Storage);
  314. Result = Storage->CommaText;
  315. }
  316. __finally
  317. {
  318. delete Storage;
  319. }
  320. return Result;
  321. }
  322. //---------------------------------------------------------------------------
  323. void __fastcall LoadToolbarsLayoutStr(const TComponent * OwnerComponent, AnsiString LayoutStr)
  324. {
  325. TStrings * Storage = new TStringList();
  326. try
  327. {
  328. Storage->CommaText = LayoutStr;
  329. TBCustomLoadPositions(OwnerComponent, ToolbarReadInt, ToolbarReadString,
  330. Storage);
  331. }
  332. __finally
  333. {
  334. delete Storage;
  335. }
  336. }
  337. //---------------------------------------------------------------------------
  338. void __fastcall AddMenuSeparator(TTBCustomItem * Menu)
  339. {
  340. TTBXSeparatorItem * Item = new TTBXSeparatorItem(Menu);
  341. Item->Caption = "-";
  342. Item->Hint = "E";
  343. Menu->Add(Item);
  344. }
  345. //---------------------------------------------------------------------------
  346. void __fastcall MenuPopup(TPopupMenu * AMenu, TPoint Point,
  347. TComponent * PopupComponent)
  348. {
  349. static TComponent * LastPopupComponent = NULL;
  350. static TDateTime LastCloseUp;
  351. // pressing the same button within 200ms after closing its popup menu
  352. // does nothing.
  353. // it is to immitate close-by-click behaviour. note that menu closes itself
  354. // before onclick handler of button occurs
  355. if ((PopupComponent == LastPopupComponent) &&
  356. (Now() - LastCloseUp < TDateTime(0, 0, 0, 200)))
  357. {
  358. LastPopupComponent = NULL;
  359. }
  360. else
  361. {
  362. TTBXPopupMenu * Menu = CreateTBXPopupMenu(AMenu->Owner);
  363. Menu->OnPopup = AMenu->OnPopup;
  364. Menu->Items->SubMenuImages = AMenu->Images;
  365. for (int Index = 0; Index < AMenu->Items->Count; Index++)
  366. {
  367. TMenuItem * AItem = AMenu->Items->Items[Index];
  368. TTBCustomItem * Item;
  369. // recurse not implemented yet
  370. assert(AItem->Count == 0);
  371. // see TB2DsgnConverter.pas DoConvert
  372. if (AItem->Caption == "-")
  373. {
  374. Item = new TTBXSeparatorItem(Menu);
  375. }
  376. else
  377. {
  378. Item = new TTBXItem(Menu);
  379. Item->Action = AItem->Action;
  380. Item->AutoCheck = AItem->AutoCheck;
  381. Item->Caption = AItem->Caption;
  382. Item->Checked = AItem->Checked;
  383. if (AItem->Default)
  384. {
  385. Item->Options = Item->Options << tboDefault;
  386. }
  387. Item->Enabled = AItem->Enabled;
  388. Item->GroupIndex = AItem->GroupIndex;
  389. Item->HelpContext = AItem->HelpContext;
  390. Item->ImageIndex = AItem->ImageIndex;
  391. Item->RadioItem = AItem->RadioItem;
  392. Item->ShortCut = AItem->ShortCut;
  393. Item->SubMenuImages = AItem->SubMenuImages;
  394. Item->OnClick = AItem->OnClick;
  395. }
  396. Item->Hint = AItem->Hint;
  397. Item->Tag = AItem->Tag;
  398. Item->Visible = AItem->Visible;
  399. Menu->Items->Add(Item);
  400. }
  401. Menu->PopupComponent = PopupComponent;
  402. Menu->Popup(Point.x, Point.y);
  403. LastPopupComponent = PopupComponent;
  404. LastCloseUp = Now();
  405. }
  406. }
  407. //---------------------------------------------------------------------------
  408. void __fastcall UpgradeSpeedButton(TSpeedButton * /*Button*/)
  409. {
  410. // no-op yet
  411. }
  412. //---------------------------------------------------------------------------
  413. struct TThreadParam
  414. {
  415. TThreadFunc ThreadFunc;
  416. void * Parameter;
  417. };
  418. //---------------------------------------------------------------------------
  419. static int __fastcall ThreadProc(void * AParam)
  420. {
  421. TThreadParam * Param = reinterpret_cast<TThreadParam *>(AParam);
  422. unsigned int Result = Param->ThreadFunc(Param->Parameter);
  423. delete Param;
  424. EndThread(Result);
  425. return Result;
  426. }
  427. //---------------------------------------------------------------------------
  428. int __fastcall StartThread(void * SecurityAttributes, unsigned StackSize,
  429. TThreadFunc ThreadFunc, void * Parameter, unsigned CreationFlags,
  430. unsigned & ThreadId)
  431. {
  432. TThreadParam * Param = new TThreadParam;
  433. Param->ThreadFunc = ThreadFunc;
  434. Param->Parameter = Parameter;
  435. return BeginThread(SecurityAttributes, StackSize, ThreadProc, Param,
  436. CreationFlags, ThreadId);
  437. }