UnixDirView.cpp 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118
  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. if (File1->IsDirectory && DirView->AlwaysSortDirectoriesByName)
  748. {
  749. // fallback
  750. }
  751. else
  752. {
  753. switch (DirView->SortColumn)
  754. {
  755. case uvName:
  756. // fallback
  757. break;
  758. case uvSize:
  759. Result = COMPARE_NUMBER(File1->Size, File2->Size);
  760. break;
  761. case uvChanged:
  762. Result = COMPARE_NUMBER(File1->Modification, File2->Modification);
  763. break;
  764. case uvRights:
  765. Result = AnsiCompareText(File1->RightsStr, File2->RightsStr);
  766. break;
  767. case uvOwner:
  768. Result = File1->Owner.Compare(File2->Owner);
  769. break;
  770. case uvGroup:
  771. Result = File1->Group.Compare(File2->Group);
  772. break;
  773. case uvExt:
  774. // Duplicated in uvType branch
  775. if (!File1->IsDirectory)
  776. {
  777. Result = CompareLogicalText(File1->Extension, File2->Extension, DirView->NaturalOrderNumericalSorting);
  778. }
  779. else
  780. {
  781. // fallback
  782. }
  783. break;
  784. case uvLinkTarget:
  785. Result = CompareLogicalText(File1->LinkTo, File2->LinkTo, DirView->NaturalOrderNumericalSorting);
  786. break;
  787. case uvType:
  788. Result = CompareLogicalText(File1->TypeName, File2->TypeName, DirView->NaturalOrderNumericalSorting);
  789. // fallback to uvExt
  790. if ((Result == 0) && !File1->IsDirectory)
  791. {
  792. Result = CompareLogicalText(File1->Extension, File2->Extension, DirView->NaturalOrderNumericalSorting);
  793. }
  794. break;
  795. default:
  796. DebugFail();
  797. }
  798. }
  799. if (Result == 0)
  800. {
  801. Result = CompareLogicalText(File1->FileName, File2->FileName, DirView->NaturalOrderNumericalSorting);
  802. }
  803. if (!DirView->UnixColProperties->SortAscending)
  804. {
  805. Result = -Result;
  806. }
  807. }
  808. return Result;
  809. }
  810. //---------------------------------------------------------------------------
  811. #undef COMPARE_NUMBER
  812. #endif
  813. //---------------------------------------------------------------------------
  814. void __fastcall TUnixDirView::SortItems()
  815. {
  816. #ifndef DESIGN_ONLY
  817. if (HandleAllocated())
  818. {
  819. CustomSortItems(CompareFile);
  820. }
  821. #endif
  822. }
  823. //---------------------------------------------------------------------------
  824. bool __fastcall TUnixDirView::GetActive()
  825. {
  826. #ifndef DESIGN_ONLY
  827. return ((Terminal != NULL) && Terminal->Active);
  828. #else
  829. return false;
  830. #endif
  831. }
  832. //---------------------------------------------------------------------------
  833. void __fastcall TUnixDirView::DDDragDetect(int grfKeyState,
  834. const TPoint &DetectStart, const TPoint &Point, TDragDetectStatus DragStatus)
  835. {
  836. if ((DragStatus == ddsDrag) && (!Loading) && (MarkedCount > 0))
  837. {
  838. TCustomUnixDirView::DDDragDetect(grfKeyState, DetectStart, Point, DragStatus);
  839. }
  840. }
  841. //---------------------------------------------------------------------------
  842. void __fastcall TUnixDirView::SetAddParentDir(bool Value)
  843. {
  844. if (Value != AddParentDir)
  845. {
  846. #ifndef DESIGN_ONLY
  847. if (Terminal) Terminal->Files->IncludeParentDirectory = Value;
  848. #endif
  849. TCustomUnixDirView::SetAddParentDir(Value);
  850. }
  851. }
  852. //---------------------------------------------------------------------------
  853. bool __fastcall TUnixDirView::TargetHasDropHandler(TListItem * /* Item */, int /* Effect */)
  854. {
  855. return false;
  856. }
  857. //---------------------------------------------------------------------------
  858. void __fastcall TUnixDirView::DDChooseEffect(int grfKeyState, int &dwEffect, int PreferredEffect)
  859. {
  860. if ((grfKeyState & (MK_CONTROL | MK_SHIFT)) == 0)
  861. {
  862. dwEffect = DROPEFFECT_COPY;
  863. }
  864. TCustomDirView::DDChooseEffect(grfKeyState, dwEffect, PreferredEffect);
  865. }
  866. //---------------------------------------------------------------------------
  867. TDropEffectSet __fastcall TUnixDirView::GetDragSourceEffects()
  868. {
  869. TDropEffectSet Result;
  870. Result << deCopy;
  871. if (DDAllowMove)
  872. {
  873. Result << deMove;
  874. }
  875. return Result;
  876. }
  877. //---------------------------------------------------------------------------
  878. void __fastcall TUnixDirView::ChangeDirectory(UnicodeString Path)
  879. {
  880. UnicodeString LastFile = L"";
  881. if (ItemFocused) LastFile = ItemFileName(ItemFocused);
  882. ClearItems();
  883. #ifndef DESIGN_ONLY
  884. try
  885. {
  886. FDirLoadedAfterChangeDir = false;
  887. if (Path == HOMEDIRECTORY)
  888. {
  889. Terminal->HomeDirectory();
  890. }
  891. else if (Path == ROOTDIRECTORY)
  892. {
  893. Terminal->CurrentDirectory = ROOTDIRECTORY;
  894. }
  895. else
  896. {
  897. Terminal->ChangeDirectory(Path);
  898. }
  899. }
  900. __finally
  901. {
  902. // changing directory failed, so we load again old directory
  903. if (!FDirLoadedAfterChangeDir)
  904. {
  905. FSelectFile = LastFile;
  906. Reload(false);
  907. };
  908. }
  909. #endif
  910. }
  911. //---------------------------------------------------------------------------
  912. bool __fastcall TUnixDirView::CanEdit(TListItem* Item)
  913. {
  914. #ifndef DESIGN_ONLY
  915. DebugAssert(Terminal);
  916. return TCustomUnixDirView::CanEdit(Item) && Terminal->IsCapable[fcRename];
  917. #else
  918. DebugUsedParam(Item);
  919. return false;
  920. #endif
  921. }
  922. //---------------------------------------------------------------------------
  923. void __fastcall TUnixDirView::InternalEdit(const tagLVITEMW & HItem)
  924. {
  925. #ifndef DESIGN_ONLY
  926. TListItem *Item = GetItemFromHItem(HItem);
  927. ASSERT_VALID_ITEM;
  928. LoadEnabled = true;
  929. if (ITEMFILE->FileName != HItem.pszText)
  930. {
  931. FSelectFile = HItem.pszText;
  932. Terminal->RenameFile(ITEMFILE, HItem.pszText);
  933. }
  934. #else
  935. DebugUsedParam(HItem);
  936. #endif
  937. }
  938. //---------------------------------------------------------------------------
  939. int __fastcall TUnixDirView::HiddenCount()
  940. {
  941. return FHiddenCount;
  942. }
  943. //---------------------------------------------------------------------------
  944. int __fastcall TUnixDirView::FilteredCount()
  945. {
  946. return FFilteredCount;
  947. }
  948. //---------------------------------------------------------------------------
  949. void __fastcall TUnixDirView::CreateDirectory(UnicodeString DirName)
  950. {
  951. CreateDirectoryEx(DirName, NULL);
  952. }
  953. //---------------------------------------------------------------------------
  954. void __fastcall TUnixDirView::CreateDirectoryEx(UnicodeString DirName, const TRemoteProperties * Properties)
  955. {
  956. #ifndef DESIGN_ONLY
  957. DebugAssert(Terminal);
  958. // if file would be created in current directory, select it after reload
  959. if (UnixExtractFileName(DirName) == DirName)
  960. {
  961. FSelectFile = DirName;
  962. }
  963. Terminal->CreateDirectory(DirName, Properties);
  964. #else
  965. DebugUsedParam(Properties);
  966. #endif
  967. }
  968. //---------------------------------------------------------------------------
  969. bool __fastcall TUnixDirView::GetIsRoot()
  970. {
  971. #ifndef DESIGN_ONLY
  972. return (PathName == ROOTDIRECTORY);
  973. #else
  974. return false;
  975. #endif
  976. }
  977. //---------------------------------------------------------------------------
  978. TColor __fastcall TUnixDirView::ItemColor(TListItem * Item)
  979. {
  980. DebugAssert(Item);
  981. #ifndef DESIGN_ONLY
  982. if (DimmHiddenFiles && !Item->Selected && ITEMFILE->IsHidden)
  983. {
  984. return clGrayText;
  985. }
  986. else
  987. #else
  988. DebugUsedParam(Item);
  989. #endif
  990. {
  991. return (TColor)clDefaultItemColor;
  992. }
  993. }
  994. //---------------------------------------------------------------------------
  995. TDateTime __fastcall TUnixDirView::ItemFileTime(TListItem * Item,
  996. TDateTimePrecision & Precision)
  997. {
  998. DebugAssert(Item);
  999. #ifndef DESIGN_ONLY
  1000. switch (ITEMFILE->ModificationFmt)
  1001. {
  1002. case mfNone:
  1003. Precision = tpNone;
  1004. break;
  1005. case mfMDHM:
  1006. case mfYMDHM:
  1007. Precision = tpMinute;
  1008. break;
  1009. case mfMDY:
  1010. Precision = tpDay;
  1011. break;
  1012. case mfFull:
  1013. default:
  1014. Precision = tpSecond;
  1015. break;
  1016. }
  1017. return ITEMFILE->Modification;
  1018. #else
  1019. DebugUsedParam(Item);
  1020. Precision = tpSecond;
  1021. return Now();
  1022. #endif
  1023. }
  1024. //---------------------------------------------------------------------------
  1025. TObject * __fastcall TUnixDirView::ItemData(TListItem * Item)
  1026. {
  1027. #ifndef DESIGN_ONLY
  1028. return ITEMFILE;
  1029. #else
  1030. DebugUsedParam(Item);
  1031. return NULL;
  1032. #endif
  1033. }
  1034. //---------------------------------------------------------------------------
  1035. void __fastcall TUnixDirView::SetShowInaccesibleDirectories(bool value)
  1036. {
  1037. if (FShowInaccesibleDirectories != value)
  1038. {
  1039. FShowInaccesibleDirectories = value;
  1040. if (DirOK) Reload(false);
  1041. }
  1042. }
  1043. //---------------------------------------------------------------------------
  1044. void __fastcall TUnixDirView::AddToDragFileList(TFileList * FileList,
  1045. TListItem * Item)
  1046. {
  1047. UnicodeString FileName = ItemFullFileName(Item);
  1048. #ifndef DESIGN_ONLY
  1049. if (OnDDDragFileName != NULL)
  1050. {
  1051. OnDDDragFileName(this, ITEMFILE, FileName);
  1052. }
  1053. #endif
  1054. FileList->AddItem(NULL, FileName);
  1055. }
  1056. //---------------------------------------------------------------------------
  1057. void __fastcall TUnixDirView::UpdatePathLabelCaption()
  1058. {
  1059. if (Terminal != NULL)
  1060. {
  1061. TCustomDirView::UpdatePathLabelCaption();
  1062. }
  1063. else
  1064. {
  1065. PathLabel->Caption = UnicodeString();
  1066. PathLabel->Mask = UnicodeString();
  1067. }
  1068. }
  1069. //---------------------------------------------------------------------------
  1070. void __fastcall TUnixDirView::SetItemCalculatedSize(TListItem * Item, __int64 Size)
  1071. {
  1072. __int64 OldSize;
  1073. #ifndef DESIGN_ONLY
  1074. OldSize = ITEMFILE->CalculatedSize;
  1075. ITEMFILE->CalculatedSize = Size;
  1076. #else
  1077. OldSize = -1;
  1078. #endif
  1079. ItemCalculatedSizeUpdated(Item, OldSize, Size);
  1080. }