UnixDirView.cpp 32 KB

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