UnixDirView.cpp 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099
  1. //---------------------------------------------------------------------------
  2. #include <vcl.h>
  3. #pragma hdrstop
  4. #include <Common.h>
  5. #include "UnixDirView.h"
  6. #include "UnixDriveView.h"
  7. #include <FileCtrl.hpp>
  8. #ifndef DESIGN_ONLY
  9. #include <CoreMain.h>
  10. #include <Terminal.h>
  11. #include <WinConfiguration.h>
  12. #include <VCLCommon.h>
  13. #endif
  14. #pragma package(smart_init)
  15. #ifndef DESIGN_ONLY
  16. #define ITEMFILE ((TRemoteFile *)(Item->Data))
  17. // noop, previously this tested that the file was in terminal's file listing,
  18. // but that cannot be safely checked now the terminal is used in multithreaded
  19. // environment
  20. #define ASSERT_VALID_ITEM
  21. #endif
  22. //---------------------------------------------------------------------------
  23. static inline void ValidCtrCheck(TUnixDirView *)
  24. {
  25. new TUnixDirView(NULL);
  26. }
  27. //---------------------------------------------------------------------------
  28. namespace Unixdirview
  29. {
  30. void __fastcall PACKAGE Register()
  31. {
  32. TComponentClass classes[1] = {__classid(TUnixDirView)};
  33. RegisterComponents(L"Scp", classes, 0);
  34. }
  35. }
  36. //---------------------------------------------------------------------------
  37. #define HOMEDIRECTORY L""
  38. //---------------------------------------------------------------------------
  39. __fastcall TUnixDirView::TUnixDirView(TComponent* Owner)
  40. : TCustomUnixDirView(Owner)
  41. {
  42. #ifndef DESIGN_ONLY
  43. FTerminal = NULL;
  44. #endif
  45. FCaseSensitive = true;
  46. FDDAllowMove = false;
  47. FShowInaccesibleDirectories = true;
  48. FFullLoad = false;
  49. FDriveView = NULL;
  50. FInvalidNameChars = L"/";
  51. FAnnouncedDriveViewState = NULL;
  52. DragDropFilesEx->PreferCopy = true;
  53. }
  54. //---------------------------------------------------------------------------
  55. __fastcall TUnixDirView::~TUnixDirView()
  56. {
  57. #ifndef DESIGN_ONLY
  58. Terminal = NULL;
  59. #endif
  60. }
  61. //---------------------------------------------------------------------------
  62. void __fastcall TUnixDirView::DisplayContextMenu(const TPoint &Where)
  63. {
  64. bool Handled = false;
  65. if (OnContextPopup)
  66. {
  67. OnContextPopup(this, ScreenToClient(Where), Handled);
  68. }
  69. if (!Handled)
  70. {
  71. if (PopupMenu && !PopupMenu->AutoPopup)
  72. {
  73. PopupMenu->Popup(Where.x, Where.y);
  74. }
  75. }
  76. }
  77. //---------------------------------------------------------------------------
  78. void __fastcall TUnixDirView::DisplayPropertiesMenu()
  79. {
  80. if (OnDisplayProperties) OnDisplayProperties(this);
  81. }
  82. //---------------------------------------------------------------------------
  83. bool __fastcall TUnixDirView::DoExecFile(TListItem * Item, bool ForceEnter)
  84. {
  85. bool Result;
  86. #ifndef DESIGN_ONLY
  87. ASSERT_VALID_ITEM;
  88. if (ForceEnter)
  89. {
  90. PathChanging(true);
  91. ChangeDirectory(ITEMFILE->FileName);
  92. Result = false;
  93. }
  94. else
  95. #endif
  96. {
  97. Result = TCustomDirView::DoExecFile(Item, ForceEnter);
  98. }
  99. return Result;
  100. }
  101. //---------------------------------------------------------------------------
  102. void __fastcall TUnixDirView::ExecuteFile(TListItem * Item)
  103. {
  104. #ifndef DESIGN_ONLY
  105. ASSERT_VALID_ITEM;
  106. if (ITEMFILE->IsDirectory ||
  107. (!Terminal->ResolvingSymlinks && !Terminal->IsEncryptingFiles()))
  108. {
  109. PathChanging(true);
  110. ChangeDirectory(ITEMFILE->FileName);
  111. }
  112. else
  113. {
  114. if (ItemFocused != Item) ItemFocused = Item;
  115. DisplayPropertiesMenu();
  116. }
  117. #else
  118. DebugUsedParam(Item);
  119. #endif
  120. }
  121. //---------------------------------------------------------------------------
  122. void __fastcall TUnixDirView::ExecuteParentDirectory()
  123. {
  124. PathChanging(true);
  125. #ifndef DESIGN_ONLY
  126. ChangeDirectory(PARENTDIRECTORY);
  127. #endif
  128. }
  129. //---------------------------------------------------------------------------
  130. void __fastcall TUnixDirView::ExecuteHomeDirectory()
  131. {
  132. #ifndef DESIGN_ONLY
  133. // don't select any directory
  134. PathChanging(false);
  135. UnicodeString APath = Terminal->SessionData->RemoteDirectory;
  136. if (WinConfiguration->DefaultDirIsHome && !APath.IsEmpty() &&
  137. !Terminal->SessionData->UpdateDirectories)
  138. {
  139. if (APath[1] != L'/')
  140. {
  141. Terminal->BeginTransaction();
  142. try
  143. {
  144. ChangeDirectory(HOMEDIRECTORY);
  145. ChangeDirectory(APath);
  146. }
  147. __finally
  148. {
  149. Terminal->EndTransaction();
  150. }
  151. }
  152. else
  153. {
  154. ChangeDirectory(APath);
  155. }
  156. }
  157. else
  158. {
  159. ChangeDirectory(HOMEDIRECTORY);
  160. }
  161. #endif
  162. }
  163. //---------------------------------------------------------------------------
  164. void __fastcall TUnixDirView::ReloadDirectory()
  165. {
  166. #ifndef DESIGN_ONLY
  167. FLastPath = L"";
  168. Terminal->ReloadDirectory();
  169. #endif
  170. }
  171. //---------------------------------------------------------------------------
  172. void __fastcall TUnixDirView::ExecuteRootDirectory()
  173. {
  174. #ifndef DESIGN_ONLY
  175. // We set LastPath to top directory, so it will be selected
  176. // after entering root directory
  177. // DISABLED: see PathChanged(): back moves to top directory, not to current
  178. PathChanging(false);
  179. ChangeDirectory(ROOTDIRECTORY);
  180. #endif
  181. }
  182. //---------------------------------------------------------------------------
  183. bool __fastcall TUnixDirView::ItemIsDirectory(TListItem * Item)
  184. {
  185. #ifndef DESIGN_ONLY
  186. ASSERT_VALID_ITEM;
  187. return ITEMFILE->IsDirectory;
  188. #else
  189. DebugUsedParam(Item);
  190. return false;
  191. #endif
  192. }
  193. //---------------------------------------------------------------------------
  194. bool __fastcall TUnixDirView::ItemIsFile(TListItem * Item)
  195. {
  196. #ifndef DESIGN_ONLY
  197. ASSERT_VALID_ITEM;
  198. return !(ITEMFILE->IsParentDirectory);
  199. #else
  200. DebugUsedParam(Item);
  201. return false;
  202. #endif
  203. }
  204. //---------------------------------------------------------------------------
  205. bool __fastcall TUnixDirView::ItemIsParentDirectory(TListItem * Item)
  206. {
  207. #ifndef DESIGN_ONLY
  208. ASSERT_VALID_ITEM;
  209. return ITEMFILE->IsParentDirectory;
  210. #else
  211. DebugUsedParam(Item);
  212. return false;
  213. #endif
  214. }
  215. //---------------------------------------------------------------------------
  216. UnicodeString __fastcall TUnixDirView::ItemFileName(TListItem * Item)
  217. {
  218. #ifndef DESIGN_ONLY
  219. ASSERT_VALID_ITEM;
  220. return ITEMFILE->FileName;
  221. #else
  222. DebugUsedParam(Item);
  223. return UnicodeString();
  224. #endif
  225. }
  226. //---------------------------------------------------------------------------
  227. __int64 __fastcall TUnixDirView::ItemFileSize(TListItem * Item)
  228. {
  229. #ifndef DESIGN_ONLY
  230. ASSERT_VALID_ITEM;
  231. return (ITEMFILE->CalculatedSize >= 0) ? ITEMFILE->CalculatedSize : ITEMFILE->Size;
  232. #else
  233. DebugUsedParam(Item);
  234. return 0;
  235. #endif
  236. }
  237. //---------------------------------------------------------------------------
  238. UnicodeString __fastcall TUnixDirView::ItemFullFileName(TListItem * Item)
  239. {
  240. #ifndef DESIGN_ONLY
  241. ASSERT_VALID_ITEM;
  242. return ITEMFILE->FullFileName;
  243. #else
  244. DebugUsedParam(Item);
  245. return UnicodeString();
  246. #endif
  247. }
  248. //---------------------------------------------------------------------------
  249. int __fastcall TUnixDirView::ItemImageIndex(TListItem * Item, bool /*Cache*/)
  250. {
  251. #ifndef DESIGN_ONLY
  252. ASSERT_VALID_ITEM;
  253. // TCustomDirView::ItemImageIndex is used for icon caching
  254. // so we don't need it here. But it's implemented anyway.
  255. return ITEMFILE->IconIndex;
  256. #else
  257. DebugUsedParam(Item);
  258. return 0;
  259. #endif
  260. }
  261. //---------------------------------------------------------------------------
  262. bool __fastcall TUnixDirView::ItemMatchesFilter(TListItem * Item,
  263. const TFileFilter &Filter)
  264. {
  265. #ifndef DESIGN_ONLY
  266. ASSERT_VALID_ITEM;
  267. TRemoteFile *File = ITEMFILE;
  268. return
  269. ((Filter.Masks.IsEmpty()) ||
  270. FileNameMatchesMasks(File->FileName, File->IsDirectory, File->Size, File->Modification, Filter.Masks, false) ||
  271. (File->IsDirectory && Filter.Directories &&
  272. FileNameMatchesMasks(File->FileName, false, File->Size, File->Modification, Filter.Masks, false)));
  273. #else
  274. DebugUsedParam(Item);
  275. DebugUsedParam(Filter);
  276. return false;
  277. #endif
  278. }
  279. //---------------------------------------------------------------------------
  280. Word __fastcall TUnixDirView::ItemOverlayIndexes(TListItem * Item)
  281. {
  282. #ifndef DESIGN_ONLY
  283. ASSERT_VALID_ITEM;
  284. Word Result = TCustomDirView::ItemOverlayIndexes(Item);
  285. if (ITEMFILE->IsParentDirectory)
  286. {
  287. Result |= oiDirUp;
  288. }
  289. if (ITEMFILE->IsSymLink)
  290. {
  291. Result |= ITEMFILE->BrokenLink ? oiBrokenLink : oiLink;
  292. }
  293. if (ITEMFILE->IsEncrypted)
  294. {
  295. Result |= oiEncrypted;
  296. }
  297. return Result;
  298. #else
  299. DebugUsedParam(Item);
  300. return 0;
  301. #endif
  302. }
  303. //---------------------------------------------------------------------------
  304. void __fastcall TUnixDirView::LoadFiles()
  305. {
  306. #ifndef DESIGN_ONLY
  307. DebugAssert(Terminal);
  308. if (DirOK)
  309. {
  310. // it's enough if we reach this point, we don't require that loading files into
  311. // list succeeded. FDirLoadedAfterChangeDir == false tells only that
  312. // loding file list from server failed, not loading into listview
  313. FDirLoadedAfterChangeDir = true;
  314. FFilesSize = 0;
  315. FHasParentDir = false;
  316. int VisibleFiles = 0;
  317. FHiddenCount = 0;
  318. FFilteredCount = 0;
  319. for (int Index = 0; Index < Terminal->Files->Count; Index++)
  320. {
  321. TRemoteFile *File = Terminal->Files->Files[Index];
  322. DebugAssert(File);
  323. if ((!ShowHiddenFiles && File->IsHidden) ||
  324. (!ShowInaccesibleDirectories && File->IsInaccesibleDirectory))
  325. {
  326. FHiddenCount++;
  327. }
  328. else if (!Mask.IsEmpty() &&
  329. IsRealFile(File->FileName) &&
  330. !FileNameMatchesMasks(File->FileName, File->IsDirectory, File->Size, File->Modification, Mask, true))
  331. {
  332. FFilteredCount++;
  333. }
  334. else
  335. {
  336. VisibleFiles++;
  337. FFilesSize += File->Size;
  338. if (File->IsParentDirectory) FHasParentDir = true;
  339. TListItem * Item = new TListItem(Items);
  340. Item->Data = File;
  341. // Need to add before assigning to .Caption and .OverlayIndex,
  342. // as the setters these call back to owning view.
  343. // Assignment is redundant
  344. Item = Items->AddItem(Item);
  345. Item->Caption = File->FileName;
  346. if (DebugAlwaysFalse(FFullLoad))
  347. {
  348. // this is out of date
  349. // (missing columns and does not update then file properties are loaded)
  350. Item->ImageIndex = File->IconIndex;
  351. Item->SubItems->Add(!File->IsDirectory ? FormatPanelBytes(File->Size, FormatSizeBytes) : UnicodeString());
  352. Item->SubItems->Add(File->UserModificationStr);
  353. Item->SubItems->Add(File->RightsStr);
  354. Item->SubItems->Add(File->Owner.DisplayText);
  355. Item->SubItems->Add(File->Group.DisplayText);
  356. Item->SubItems->Add(File->Extension);
  357. }
  358. }
  359. }
  360. if (OwnerData)
  361. {
  362. Items->Count = VisibleFiles;
  363. }
  364. }
  365. #endif
  366. }
  367. //---------------------------------------------------------------------------
  368. void __fastcall TUnixDirView::GetDisplayInfo(TListItem * Item, tagLVITEMW &DispInfo)
  369. {
  370. if (!FFullLoad)
  371. {
  372. #ifndef DESIGN_ONLY
  373. TRemoteFile * File = ITEMFILE;
  374. if (DispInfo.mask & LVIF_TEXT)
  375. {
  376. UnicodeString Value;
  377. switch (DispInfo.iSubItem) {
  378. case uvName: Value = File->FileName; break;
  379. case uvSize:
  380. {
  381. __int64 Size;
  382. if (!File->IsDirectory)
  383. {
  384. Size = File->Size;
  385. }
  386. else
  387. {
  388. Size = File->CalculatedSize;
  389. }
  390. if (Size >= 0)
  391. {
  392. Value = FormatPanelBytes(Size, FormatSizeBytes);
  393. }
  394. }
  395. break;
  396. case uvChanged: Value = File->UserModificationStr; break;
  397. case uvRights: Value = File->RightsStr; break;
  398. case uvOwner: Value = File->Owner.DisplayText; break;
  399. case uvGroup: Value = File->Group.DisplayText; break;
  400. case uvExt: Value = File->Extension; break;
  401. case uvLinkTarget: Value = File->LinkTo; break;
  402. case uvType: Value = File->TypeName; break;
  403. default: DebugFail();
  404. }
  405. StrPLCopy(DispInfo.pszText, Value, DispInfo.cchTextMax - 1);
  406. }
  407. if (DispInfo.iSubItem == 0 && DispInfo.mask & LVIF_IMAGE)
  408. {
  409. DispInfo.iImage = File->IconIndex;
  410. DispInfo.mask |= LVIF_DI_SETITEM;
  411. }
  412. #else
  413. DebugUsedParam(Item);
  414. DebugUsedParam(DispInfo);
  415. #endif
  416. }
  417. }
  418. //---------------------------------------------------------------------------
  419. bool __fastcall TUnixDirView::PasteFromClipBoard(UnicodeString TargetPath)
  420. {
  421. DragDropFilesEx->FileList->Clear();
  422. bool Result = false;
  423. if (CanPasteFromClipBoard() &&
  424. DragDropFilesEx->GetFromClipboard())
  425. {
  426. if (TargetPath.IsEmpty())
  427. {
  428. TargetPath = PathName;
  429. }
  430. PerformItemDragDropOperation(NULL, DROPEFFECT_COPY, true);
  431. if (OnDDExecuted != NULL)
  432. {
  433. OnDDExecuted(this, DROPEFFECT_COPY);
  434. }
  435. Result = true;
  436. }
  437. return Result;
  438. }
  439. //---------------------------------------------------------------------------
  440. void __fastcall TUnixDirView::PerformItemDragDropOperation(
  441. TListItem * Item, int Effect, bool Paste)
  442. {
  443. #ifndef DESIGN_ONLY
  444. if (OnDDFileOperation)
  445. {
  446. // Could be empty if the source application does not provide any files;
  447. // or if the IDataObject fails GetData, like Visual Studio Code 0.8.0.
  448. if (DragDropFilesEx->FileList->Count > 0)
  449. {
  450. UnicodeString SourceDirectory;
  451. UnicodeString TargetDirectory;
  452. SourceDirectory = ExtractFilePath(DragDropFilesEx->FileList->Items[0]->Name);
  453. if (Item)
  454. {
  455. DebugAssert(ITEMFILE->IsDirectory && (Terminal->Files->IndexOf(ITEMFILE) >= 0));
  456. TargetDirectory = ITEMFILE->FullFileName;
  457. }
  458. else
  459. {
  460. TargetDirectory = Path;
  461. }
  462. bool DoFileOperation = true;
  463. OnDDFileOperation(
  464. this, Effect, SourceDirectory, TargetDirectory, Paste, DoFileOperation);
  465. }
  466. }
  467. #else
  468. DebugUsedParam(Item);
  469. DebugUsedParam(Effect);
  470. DebugUsedParam(Paste);
  471. #endif
  472. }
  473. //---------------------------------------------------------------------------
  474. void __fastcall TUnixDirView::SetItemImageIndex(TListItem * /* Item */, int /* Index */)
  475. {
  476. // TCustomDirView::SetItemImageIndex is used for icon caching
  477. // so we don't need it here.
  478. }
  479. //---------------------------------------------------------------------------
  480. void __fastcall TUnixDirView::DDMenuDone(TObject* /* Sender */, HMENU /* AMenu */)
  481. {
  482. // TODO: Why I need to duplicate this method? (see TCustomDirView::DDMenuDone)
  483. }
  484. //---------------------------------------------------------------------------
  485. void __fastcall TUnixDirView::SetDriveView(TCustomUnixDriveView * Value)
  486. {
  487. if (Value != FDriveView)
  488. {
  489. if (FDriveView != NULL)
  490. {
  491. FDriveView->Terminal = NULL;
  492. }
  493. FDriveView = Value;
  494. if (FDriveView != NULL)
  495. {
  496. FDriveView->Terminal = Terminal;
  497. }
  498. }
  499. }
  500. //---------------------------------------------------------------------------
  501. #ifndef DESIGN_ONLY
  502. void __fastcall TUnixDirView::DoSetTerminal(TTerminal * value, bool Replace)
  503. {
  504. DebugUsedParam(Replace);
  505. if ((FTerminal != value) ||
  506. ((FTerminal != NULL) && !FTerminal->Active)) // Abused by TCustomScpExplorerForm::DisconnectSession
  507. {
  508. if (FTerminal)
  509. {
  510. DebugAssert((FTerminal->OnReadDirectory == DoReadDirectory) || Replace);
  511. if (FTerminal->OnReadDirectory == DoReadDirectory)
  512. {
  513. FTerminal->OnReadDirectory = NULL;
  514. }
  515. DebugAssert((FTerminal->OnStartReadDirectory == DoStartReadDirectory) || Replace);
  516. if (FTerminal->OnStartReadDirectory == DoStartReadDirectory)
  517. {
  518. FTerminal->OnStartReadDirectory = NULL;
  519. }
  520. if (!value || !value->Files->Loaded)
  521. {
  522. ClearItems();
  523. }
  524. }
  525. FTerminal = value;
  526. PathChanging(false);
  527. if (FDriveView != NULL)
  528. {
  529. FDriveView->Terminal = FTerminal;
  530. }
  531. if (FTerminal)
  532. {
  533. FTerminal->OnReadDirectory = DoReadDirectory;
  534. FTerminal->OnStartReadDirectory = DoStartReadDirectory;
  535. FTerminal->Files->IncludeParentDirectory = AddParentDir;
  536. if (FTerminal->Files->Loaded)
  537. {
  538. DoStartReadDirectory(FTerminal); // just for style and the assertions
  539. DoReadDirectoryImpl(FTerminal, false);
  540. }
  541. else
  542. {
  543. PathChanged(); // To clear path combo box
  544. }
  545. }
  546. UpdatePathLabel();
  547. }
  548. }
  549. //---------------------------------------------------------------------------
  550. void __fastcall TUnixDirView::SetTerminal(TTerminal * value)
  551. {
  552. DoSetTerminal(value, false);
  553. }
  554. //---------------------------------------------------------------------------
  555. void __fastcall TUnixDirView::ReplaceTerminal(TTerminal * value)
  556. {
  557. DoSetTerminal(value, true);
  558. }
  559. #endif
  560. //---------------------------------------------------------------------------
  561. class TUnixDirViewState : public TObject
  562. {
  563. public:
  564. std::unique_ptr<TObject> CustomDirViewState;
  565. std::unique_ptr<TObject> DriveViewState;
  566. };
  567. //---------------------------------------------------------------------------
  568. TObject * __fastcall TUnixDirView::SaveState()
  569. {
  570. TUnixDirViewState * State = new TUnixDirViewState();
  571. State->CustomDirViewState.reset(TCustomUnixDirView::SaveState());
  572. if (FDriveView != NULL)
  573. {
  574. State->DriveViewState.reset(FDriveView->SaveState());
  575. }
  576. return State;
  577. }
  578. //---------------------------------------------------------------------------
  579. void __fastcall TUnixDirView::AnnounceState(TObject * State)
  580. {
  581. TObject * CustomDirViewState = NULL;
  582. if (State != NULL)
  583. {
  584. TUnixDirViewState * UnixDirViewState = dynamic_cast<TUnixDirViewState *>(State);
  585. if (UnixDirViewState != NULL)
  586. {
  587. FAnnouncedDriveViewState = UnixDirViewState->DriveViewState.get();
  588. CustomDirViewState = UnixDirViewState->CustomDirViewState.get();
  589. }
  590. else
  591. {
  592. // It might be TCustomDirView state from CreateDirViewStateForFocusedItem.
  593. CustomDirViewState = State;
  594. }
  595. }
  596. TCustomDirView::AnnounceState(CustomDirViewState);
  597. }
  598. //---------------------------------------------------------------------------
  599. void __fastcall TUnixDirView::RestoreState(TObject * State)
  600. {
  601. TObject * CustomDirViewState = NULL;
  602. if (State != NULL)
  603. {
  604. TUnixDirViewState * UnixDirViewState = dynamic_cast<TUnixDirViewState *>(State);
  605. if (UnixDirViewState != NULL)
  606. {
  607. CustomDirViewState = UnixDirViewState->CustomDirViewState.get();
  608. }
  609. else
  610. {
  611. // See the comment in AnnounceState
  612. CustomDirViewState = State;
  613. }
  614. }
  615. TCustomDirView::RestoreState(CustomDirViewState);
  616. }
  617. //---------------------------------------------------------------------------
  618. void __fastcall TUnixDirView::DoStartReadDirectory(TObject * /*Sender*/)
  619. {
  620. DebugAssert(!FLoading);
  621. FLoading = true;
  622. }
  623. //---------------------------------------------------------------------------
  624. void __fastcall TUnixDirView::DoReadDirectory(TObject * Sender, bool ReloadOnly)
  625. {
  626. DoReadDirectoryImpl(Sender, ReloadOnly);
  627. if (FOnRead != NULL)
  628. {
  629. FOnRead(this);
  630. }
  631. }
  632. //---------------------------------------------------------------------------
  633. void __fastcall TUnixDirView::DoReadDirectoryImpl(TObject * /*Sender*/, bool ReloadOnly)
  634. {
  635. DebugAssert(FLoading);
  636. FLoading = false;
  637. #ifndef DESIGN_ONLY
  638. CancelEdit();
  639. if (Terminal->Active)
  640. {
  641. if (ReloadOnly)
  642. {
  643. Reload(false);
  644. }
  645. else
  646. {
  647. Load(true);
  648. PathChanged();
  649. }
  650. if ((FDriveView != NULL) && FDriveView->Visible)
  651. {
  652. FDriveView->LoadDirectory();
  653. }
  654. }
  655. else
  656. {
  657. // Make sure file list is cleared, to remove all references to invalid
  658. // file objects. LoadFiles check for disconnected terminal, so no reloading
  659. // actually occures.
  660. Load(true);
  661. }
  662. #else
  663. DebugUsedParam(ReloadOnly);
  664. #endif
  665. }
  666. //---------------------------------------------------------------------------
  667. bool __fastcall TUnixDirView::GetDirOK()
  668. {
  669. #ifndef DESIGN_ONLY
  670. return (Active && Terminal->Files->Loaded);
  671. #else
  672. return false;
  673. #endif
  674. }
  675. //---------------------------------------------------------------------------
  676. UnicodeString __fastcall TUnixDirView::GetPathName()
  677. {
  678. #ifndef DESIGN_ONLY
  679. if (DirOK) return Terminal->CurrentDirectory;
  680. else
  681. #endif
  682. return L"";
  683. }
  684. //---------------------------------------------------------------------------
  685. UnicodeString __fastcall TUnixDirView::GetPath()
  686. {
  687. #ifndef DESIGN_ONLY
  688. if (DirOK) return UnixIncludeTrailingBackslash(Terminal->CurrentDirectory);
  689. else
  690. #endif
  691. return L"";
  692. }
  693. //---------------------------------------------------------------------------
  694. void __fastcall TUnixDirView::SetPath(UnicodeString Value)
  695. {
  696. #ifndef DESIGN_ONLY
  697. Value = UnixExcludeTrailingBackslash(Value);
  698. if (Active && (Terminal->CurrentDirectory != Value))
  699. {
  700. PathChanging(true);
  701. Terminal->CurrentDirectory = Value;
  702. }
  703. #endif
  704. }
  705. //---------------------------------------------------------------------------
  706. #ifndef DESIGN_ONLY
  707. #define COMPARE_NUMBER(Num1, Num2) ( Num1 < Num2 ? -1 : ( Num1 > Num2 ? 1 : 0) )
  708. //---------------------------------------------------------------------------
  709. int __stdcall CompareFile(TListItem * Item1, TListItem * Item2, TUnixDirView * DirView)
  710. {
  711. DebugAssert((Item1 != NULL) && (Item2 != NULL));
  712. TRemoteFile * File1 = DebugNotNull((TRemoteFile *)(Item1->Data));
  713. TRemoteFile * File2 = DebugNotNull((TRemoteFile *)(Item2->Data));
  714. int Result;
  715. if (File1->IsParentDirectory && !File2->IsParentDirectory)
  716. {
  717. Result = -1;
  718. }
  719. else if (!File1->IsParentDirectory && File2->IsParentDirectory)
  720. {
  721. Result = 1;
  722. }
  723. else if (File1->IsDirectory && !File2->IsDirectory)
  724. {
  725. Result = -1;
  726. }
  727. else if (!File1->IsDirectory && File2->IsDirectory)
  728. {
  729. Result = 1;
  730. }
  731. else
  732. {
  733. Result = 0;
  734. switch (DirView->SortColumn)
  735. {
  736. case uvName:
  737. // fallback
  738. break;
  739. case uvSize:
  740. Result = COMPARE_NUMBER(File1->Size, File2->Size);
  741. break;
  742. case uvChanged:
  743. Result = COMPARE_NUMBER(File1->Modification, File2->Modification);
  744. break;
  745. case uvRights:
  746. Result = AnsiCompareText(File1->RightsStr, File2->RightsStr);
  747. break;
  748. case uvOwner:
  749. Result = File1->Owner.Compare(File2->Owner);
  750. break;
  751. case uvGroup:
  752. Result = File1->Group.Compare(File2->Group);
  753. break;
  754. case uvExt:
  755. // Duplicated in uvType branch
  756. if (!File1->IsDirectory)
  757. {
  758. Result = CompareLogicalText(File1->Extension, File2->Extension, DirView->NaturalOrderNumericalSorting);
  759. }
  760. else
  761. {
  762. // fallback
  763. }
  764. break;
  765. case uvLinkTarget:
  766. Result = CompareLogicalText(File1->LinkTo, File2->LinkTo, DirView->NaturalOrderNumericalSorting);
  767. break;
  768. case uvType:
  769. Result = CompareLogicalText(File1->TypeName, File2->TypeName, DirView->NaturalOrderNumericalSorting);
  770. // fallback to uvExt
  771. if ((Result == 0) && !File1->IsDirectory)
  772. {
  773. Result = CompareLogicalText(File1->Extension, File2->Extension, DirView->NaturalOrderNumericalSorting);
  774. }
  775. break;
  776. default:
  777. DebugFail();
  778. }
  779. if (Result == 0)
  780. {
  781. Result = CompareLogicalText(File1->FileName, File2->FileName, DirView->NaturalOrderNumericalSorting);
  782. }
  783. if (!DirView->UnixColProperties->SortAscending)
  784. {
  785. Result = -Result;
  786. }
  787. }
  788. return Result;
  789. }
  790. //---------------------------------------------------------------------------
  791. #undef COMPARE_NUMBER
  792. #endif
  793. //---------------------------------------------------------------------------
  794. void __fastcall TUnixDirView::SortItems()
  795. {
  796. #ifndef DESIGN_ONLY
  797. if (HandleAllocated())
  798. {
  799. CustomSortItems(CompareFile);
  800. }
  801. #endif
  802. }
  803. //---------------------------------------------------------------------------
  804. bool __fastcall TUnixDirView::GetActive()
  805. {
  806. #ifndef DESIGN_ONLY
  807. return ((Terminal != NULL) && Terminal->Active);
  808. #else
  809. return false;
  810. #endif
  811. }
  812. //---------------------------------------------------------------------------
  813. void __fastcall TUnixDirView::DDDragDetect(int grfKeyState,
  814. const TPoint &DetectStart, const TPoint &Point, TDragDetectStatus DragStatus)
  815. {
  816. if ((DragStatus == ddsDrag) && (!Loading) && (MarkedCount > 0))
  817. {
  818. TCustomUnixDirView::DDDragDetect(grfKeyState, DetectStart, Point, DragStatus);
  819. }
  820. }
  821. //---------------------------------------------------------------------------
  822. void __fastcall TUnixDirView::SetAddParentDir(bool Value)
  823. {
  824. if (Value != AddParentDir)
  825. {
  826. #ifndef DESIGN_ONLY
  827. if (Terminal) Terminal->Files->IncludeParentDirectory = Value;
  828. #endif
  829. TCustomUnixDirView::SetAddParentDir(Value);
  830. }
  831. }
  832. //---------------------------------------------------------------------------
  833. bool __fastcall TUnixDirView::TargetHasDropHandler(TListItem * /* Item */, int /* Effect */)
  834. {
  835. return false;
  836. }
  837. //---------------------------------------------------------------------------
  838. void __fastcall TUnixDirView::DDChooseEffect(int grfKeyState, int &dwEffect, int PreferredEffect)
  839. {
  840. if ((grfKeyState & (MK_CONTROL | MK_SHIFT)) == 0)
  841. {
  842. dwEffect = DROPEFFECT_COPY;
  843. }
  844. TCustomDirView::DDChooseEffect(grfKeyState, dwEffect, PreferredEffect);
  845. }
  846. //---------------------------------------------------------------------------
  847. TDropEffectSet __fastcall TUnixDirView::GetDragSourceEffects()
  848. {
  849. TDropEffectSet Result;
  850. Result << deCopy;
  851. if (DDAllowMove)
  852. {
  853. Result << deMove;
  854. }
  855. return Result;
  856. }
  857. //---------------------------------------------------------------------------
  858. void __fastcall TUnixDirView::ChangeDirectory(UnicodeString Path)
  859. {
  860. UnicodeString LastFile = L"";
  861. if (ItemFocused) LastFile = ItemFileName(ItemFocused);
  862. ClearItems();
  863. #ifndef DESIGN_ONLY
  864. try
  865. {
  866. FDirLoadedAfterChangeDir = false;
  867. if (Path == HOMEDIRECTORY)
  868. {
  869. Terminal->HomeDirectory();
  870. }
  871. else
  872. // this works even with LockInHome
  873. if (Path == ROOTDIRECTORY)
  874. {
  875. Terminal->CurrentDirectory = ROOTDIRECTORY;
  876. }
  877. else
  878. {
  879. Terminal->ChangeDirectory(Path);
  880. }
  881. }
  882. __finally
  883. {
  884. // changing directory failed, so we load again old directory
  885. if (!FDirLoadedAfterChangeDir)
  886. {
  887. FSelectFile = LastFile;
  888. Reload(false);
  889. };
  890. }
  891. #endif
  892. }
  893. //---------------------------------------------------------------------------
  894. bool __fastcall TUnixDirView::CanEdit(TListItem* Item)
  895. {
  896. #ifndef DESIGN_ONLY
  897. DebugAssert(Terminal);
  898. return TCustomUnixDirView::CanEdit(Item) && Terminal->IsCapable[fcRename];
  899. #else
  900. DebugUsedParam(Item);
  901. return false;
  902. #endif
  903. }
  904. //---------------------------------------------------------------------------
  905. void __fastcall TUnixDirView::InternalEdit(const tagLVITEMW & HItem)
  906. {
  907. #ifndef DESIGN_ONLY
  908. TListItem *Item = GetItemFromHItem(HItem);
  909. ASSERT_VALID_ITEM;
  910. LoadEnabled = true;
  911. if (ITEMFILE->FileName != HItem.pszText)
  912. {
  913. FSelectFile = HItem.pszText;
  914. Terminal->RenameFile(ITEMFILE, HItem.pszText, true);
  915. }
  916. #else
  917. DebugUsedParam(HItem);
  918. #endif
  919. }
  920. //---------------------------------------------------------------------------
  921. int __fastcall TUnixDirView::HiddenCount()
  922. {
  923. return FHiddenCount;
  924. }
  925. //---------------------------------------------------------------------------
  926. int __fastcall TUnixDirView::FilteredCount()
  927. {
  928. return FFilteredCount;
  929. }
  930. //---------------------------------------------------------------------------
  931. void __fastcall TUnixDirView::CreateDirectory(UnicodeString DirName)
  932. {
  933. CreateDirectoryEx(DirName, NULL);
  934. }
  935. //---------------------------------------------------------------------------
  936. void __fastcall TUnixDirView::CreateDirectoryEx(UnicodeString DirName, const TRemoteProperties * Properties)
  937. {
  938. #ifndef DESIGN_ONLY
  939. DebugAssert(Terminal);
  940. // if file would be created in current directory, select it after reload
  941. if (UnixExtractFileName(DirName) == DirName)
  942. {
  943. FSelectFile = DirName;
  944. }
  945. Terminal->CreateDirectory(DirName, Properties);
  946. #else
  947. DebugUsedParam(Properties);
  948. #endif
  949. }
  950. //---------------------------------------------------------------------------
  951. bool __fastcall TUnixDirView::GetIsRoot()
  952. {
  953. #ifndef DESIGN_ONLY
  954. return (PathName == ROOTDIRECTORY);
  955. #else
  956. return false;
  957. #endif
  958. }
  959. //---------------------------------------------------------------------------
  960. TColor __fastcall TUnixDirView::ItemColor(TListItem * Item)
  961. {
  962. DebugAssert(Item);
  963. #ifndef DESIGN_ONLY
  964. if (DimmHiddenFiles && !Item->Selected && ITEMFILE->IsHidden)
  965. {
  966. return clGrayText;
  967. }
  968. else
  969. #else
  970. DebugUsedParam(Item);
  971. #endif
  972. {
  973. return (TColor)clDefaultItemColor;
  974. }
  975. }
  976. //---------------------------------------------------------------------------
  977. TDateTime __fastcall TUnixDirView::ItemFileTime(TListItem * Item,
  978. TDateTimePrecision & Precision)
  979. {
  980. DebugAssert(Item);
  981. #ifndef DESIGN_ONLY
  982. switch (ITEMFILE->ModificationFmt)
  983. {
  984. case mfNone:
  985. Precision = tpNone;
  986. break;
  987. case mfMDHM:
  988. Precision = tpMinute;
  989. break;
  990. case mfMDY:
  991. Precision = tpDay;
  992. break;
  993. case mfFull:
  994. default:
  995. Precision = tpSecond;
  996. break;
  997. }
  998. return ITEMFILE->Modification;
  999. #else
  1000. DebugUsedParam(Item);
  1001. Precision = tpSecond;
  1002. return Now();
  1003. #endif
  1004. }
  1005. //---------------------------------------------------------------------------
  1006. TObject * __fastcall TUnixDirView::ItemData(TListItem * Item)
  1007. {
  1008. #ifndef DESIGN_ONLY
  1009. return ITEMFILE;
  1010. #else
  1011. DebugUsedParam(Item);
  1012. return NULL;
  1013. #endif
  1014. }
  1015. //---------------------------------------------------------------------------
  1016. void __fastcall TUnixDirView::SetShowInaccesibleDirectories(bool value)
  1017. {
  1018. if (FShowInaccesibleDirectories != value)
  1019. {
  1020. FShowInaccesibleDirectories = value;
  1021. if (DirOK) Reload(false);
  1022. }
  1023. }
  1024. //---------------------------------------------------------------------------
  1025. void __fastcall TUnixDirView::AddToDragFileList(TFileList * FileList,
  1026. TListItem * Item)
  1027. {
  1028. UnicodeString FileName = ItemFullFileName(Item);
  1029. #ifndef DESIGN_ONLY
  1030. if (OnDDDragFileName != NULL)
  1031. {
  1032. OnDDDragFileName(this, ITEMFILE, FileName);
  1033. }
  1034. #endif
  1035. FileList->AddItem(NULL, FileName);
  1036. }
  1037. //---------------------------------------------------------------------------
  1038. void __fastcall TUnixDirView::UpdatePathLabelCaption()
  1039. {
  1040. if (Terminal != NULL)
  1041. {
  1042. TCustomDirView::UpdatePathLabelCaption();
  1043. }
  1044. else
  1045. {
  1046. PathLabel->Caption = UnicodeString();
  1047. PathLabel->Mask = UnicodeString();
  1048. }
  1049. }
  1050. //---------------------------------------------------------------------------
  1051. void __fastcall TUnixDirView::SetItemCalculatedSize(TListItem * Item, __int64 Size)
  1052. {
  1053. __int64 OldSize;
  1054. #ifndef DESIGN_ONLY
  1055. OldSize = ITEMFILE->CalculatedSize;
  1056. ITEMFILE->CalculatedSize = Size;
  1057. #else
  1058. OldSize = -1;
  1059. #endif
  1060. ItemCalculatedSizeUpdated(Item, OldSize, Size);
  1061. }