UnixDirView.cpp 31 KB

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