UnixDriveView.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777
  1. //---------------------------------------------------------------------------
  2. #include <vcl.h>
  3. #pragma hdrstop
  4. #include <Common.h>
  5. #include "UnixDriveView.h"
  6. #ifndef DESIGN_ONLY
  7. #include <Terminal.h>
  8. #include <RemoteFiles.h>
  9. #endif
  10. #pragma package(smart_init)
  11. //---------------------------------------------------------------------------
  12. static inline void ValidCtrCheck(TUnixDriveView *)
  13. {
  14. new TUnixDriveView(NULL);
  15. }
  16. //---------------------------------------------------------------------------
  17. namespace Unixdriveview
  18. {
  19. void __fastcall PACKAGE Register()
  20. {
  21. TComponentClass classes[1] = {__classid(TUnixDriveView)};
  22. RegisterComponents("Scp", classes, 0);
  23. }
  24. }
  25. //---------------------------------------------------------------------------
  26. __fastcall TUnixDriveView::TUnixDriveView(TComponent * Owner) :
  27. TCustomUnixDriveView(Owner)
  28. {
  29. }
  30. //---------------------------------------------------------------------------
  31. struct TNodeData
  32. {
  33. TRemoteFileList * FileList;
  34. TRemoteFile * File;
  35. AnsiString Directory;
  36. };
  37. //---------------------------------------------------------------------------
  38. __fastcall TCustomUnixDriveView::TCustomUnixDriveView(TComponent* Owner) :
  39. TCustomDriveView(Owner)
  40. {
  41. FTerminal = NULL;
  42. FRootName = Customunixdirview_SUnixDefaultRootName;
  43. FIgnoreChange = false;
  44. FPrevSelected = NULL;
  45. DDAllowMove = false;
  46. FShowInaccesibleDirectories = true;
  47. FDummyDragFile = NULL;
  48. }
  49. //---------------------------------------------------------------------------
  50. __fastcall TCustomUnixDriveView::~TCustomUnixDriveView()
  51. {
  52. Terminal = NULL;
  53. if (FDummyDragFile != NULL)
  54. {
  55. #ifndef DESIGN_ONLY
  56. SAFE_DESTROY(FDummyDragFile);
  57. #endif
  58. }
  59. }
  60. //---------------------------------------------------------------------------
  61. void __fastcall TCustomUnixDriveView::CreateWnd()
  62. {
  63. TCustomDriveView::CreateWnd();
  64. FDragDropFilesEx->TargetEffects = TDropEffectSet() << deCopy << deMove;
  65. }
  66. //---------------------------------------------------------------------------
  67. void __fastcall TCustomUnixDriveView::SetTerminal(TTerminal * value)
  68. {
  69. if (FTerminal != value)
  70. {
  71. FTerminal = value;
  72. Items->Clear();
  73. #ifndef DESIGN_ONLY
  74. if (FTerminal != NULL)
  75. {
  76. TStrings * FixedPaths = FTerminal->FixedPaths;
  77. if (FixedPaths != NULL)
  78. {
  79. for (int i = 0; i < FixedPaths->Count; i++)
  80. {
  81. LoadPath(FixedPaths->Strings[i]);
  82. }
  83. }
  84. }
  85. #endif
  86. }
  87. }
  88. //---------------------------------------------------------------------------
  89. void __fastcall TCustomUnixDriveView::SetDirView(TUnixDirView * Value)
  90. {
  91. if (FDirView != Value)
  92. {
  93. if (FDirView != NULL)
  94. {
  95. FDirView->DriveView = NULL;
  96. }
  97. FDirView = Value;
  98. if (FDirView != NULL)
  99. {
  100. FDirView->DriveView = this;
  101. }
  102. }
  103. }
  104. //---------------------------------------------------------------------------
  105. TCustomDirView * __fastcall TCustomUnixDriveView::GetCustomDirView()
  106. {
  107. return FDirView;
  108. }
  109. //---------------------------------------------------------------------------
  110. void __fastcall TCustomUnixDriveView::SetCustomDirView(TCustomDirView * Value)
  111. {
  112. SetDirView(dynamic_cast<TUnixDirView *>(Value));
  113. }
  114. //---------------------------------------------------------------------------
  115. bool __fastcall TCustomUnixDriveView::IsRootNameStored()
  116. {
  117. return (FRootName != Customunixdirview_SUnixDefaultRootName);
  118. }
  119. //---------------------------------------------------------------------------
  120. bool __fastcall TCustomUnixDriveView::NodeIsHidden(const TTreeNode * Node)
  121. {
  122. #ifndef DESIGN_ONLY
  123. TNodeData * Data = NodeData(Node);
  124. TRemoteFile * File = Data->File;
  125. return
  126. ((File != NULL) && File->IsHidden) ||
  127. ((File == NULL) && IsUnixHiddenFile(UnixExtractFileName(Data->Directory)));
  128. #else
  129. return false;
  130. #endif
  131. }
  132. //---------------------------------------------------------------------------
  133. bool __fastcall TCustomUnixDriveView::NodeCanDelete(TTreeNode * Node)
  134. {
  135. return (Selected == NULL) ||
  136. ((Selected != Node) && !Selected->HasAsParent(Node));
  137. }
  138. //---------------------------------------------------------------------------
  139. void __fastcall TCustomUnixDriveView::UpdatePath(TTreeNode * Node, bool Force,
  140. bool CanLoad)
  141. {
  142. #ifndef DESIGN_ONLY
  143. TNodeData * Data = NodeData(Node);
  144. AnsiString Path = Data->Directory;
  145. if (FTerminal->DirectoryFileList(Path, Data->FileList, CanLoad) ||
  146. ((Data->FileList != NULL) && Force))
  147. {
  148. TStringList * ChildrenDirs = new TStringList();
  149. try
  150. {
  151. ChildrenDirs->Duplicates = dupAccept;
  152. ChildrenDirs->CaseSensitive = true;
  153. TTreeNode * ChildNode = Node->getFirstChild();
  154. while (ChildNode != NULL)
  155. {
  156. TNodeData * ChildData = NodeData(ChildNode);
  157. ChildData->File = NULL;
  158. ChildrenDirs->AddObject(UnixExtractFileName(ChildData->Directory),
  159. ChildNode);
  160. ChildNode = Node->GetNextChild(ChildNode);
  161. }
  162. // sort only after adding all items.
  163. // should be faster then keeping the list sorted since beginning
  164. ChildrenDirs->Sorted = true;
  165. for (int i = 0; i < Data->FileList->Count; i++)
  166. {
  167. TRemoteFile * File = Data->FileList->Files[i];
  168. if (File->IsDirectory && !File->IsParentDirectory && !File->IsThisDirectory &&
  169. (ShowHiddenDirs || !File->IsHidden) &&
  170. (ShowInaccesibleDirectories || !File->IsInaccesibleDirectory))
  171. {
  172. int ChildIndex = ChildrenDirs->IndexOf(File->FileName);
  173. if (ChildIndex >= 0)
  174. {
  175. TTreeNode * ChildNode =
  176. dynamic_cast<TTreeNode *>(ChildrenDirs->Objects[ChildIndex]);
  177. TNodeData * ChildData = NodeData(ChildNode);
  178. ChildData->File = File;
  179. UpdatePath(ChildNode, Force);
  180. }
  181. else
  182. {
  183. AnsiString ChildPath = UnixIncludeTrailingBackslash(Path) + File->FileName;
  184. assert(!IsUnixRootPath(ChildPath));
  185. LoadPathEasy(Node, ChildPath, File);
  186. }
  187. }
  188. }
  189. for (int i = 0; i < ChildrenDirs->Count; i++)
  190. {
  191. TTreeNode * ChildNode = dynamic_cast<TTreeNode *>(ChildrenDirs->Objects[i]);
  192. TNodeData * ChildData = NodeData(ChildNode);
  193. if ((ChildData->File == NULL) && NodeCanDelete(ChildNode))
  194. {
  195. ChildNode->Delete();
  196. }
  197. }
  198. Node->AlphaSort(false);
  199. }
  200. __finally
  201. {
  202. delete ChildrenDirs;
  203. }
  204. }
  205. else if (Force)
  206. {
  207. TTreeNode * ChildNode = Node->GetLastChild();
  208. while (ChildNode != NULL)
  209. {
  210. TTreeNode * PrevChildNode = Node->GetPrevChild(ChildNode);
  211. TRemoteFile * File = NodeFile(ChildNode);
  212. if (!NodeCanDelete(ChildNode) ||
  213. ((ShowHiddenDirs || !NodeIsHidden(ChildNode)) &&
  214. (ShowInaccesibleDirectories || (File == NULL) || !File->IsInaccesibleDirectory)))
  215. {
  216. UpdatePath(ChildNode, true);
  217. }
  218. else
  219. {
  220. ChildNode->Delete();
  221. }
  222. ChildNode = PrevChildNode;
  223. }
  224. }
  225. #endif
  226. }
  227. //---------------------------------------------------------------------------
  228. TTreeNode * __fastcall TCustomUnixDriveView::LoadPathEasy(TTreeNode * Parent,
  229. AnsiString Path, TRemoteFile * File)
  230. {
  231. #ifndef DESIGN_ONLY
  232. assert(Path == UnixExcludeTrailingBackslash(Path));
  233. AnsiString DirName;
  234. if (IsUnixRootPath(Path))
  235. {
  236. DirName = RootName;
  237. }
  238. else
  239. {
  240. DirName = UnixExtractFileName(Path);
  241. }
  242. TTreeNode * Node = Items->AddChild(Parent, DirName);
  243. TNodeData * Data = new TNodeData();
  244. Node->Data = Data;
  245. Data->Directory = Path;
  246. Data->File = File;
  247. Data->FileList = NULL;
  248. UpdatePath(Node, true);
  249. return Node;
  250. #else
  251. return NULL;
  252. #endif
  253. }
  254. //---------------------------------------------------------------------------
  255. TTreeNode * __fastcall TCustomUnixDriveView::LoadPath(AnsiString Path)
  256. {
  257. #ifndef DESIGN_ONLY
  258. if (Path.IsEmpty())
  259. {
  260. Path = ROOTDIRECTORY;
  261. }
  262. TTreeNode * Node = FindNodeToPath(Path);
  263. if (Node == NULL)
  264. {
  265. Path = UnixExcludeTrailingBackslash(Path);
  266. TTreeNode * Parent = NULL;
  267. TRemoteFile * File = NULL;
  268. if (!IsUnixRootPath(Path))
  269. {
  270. Parent = LoadPath(UnixExtractFileDir(Path));
  271. }
  272. Node = FindNodeToPath(Path);
  273. if (Node == NULL)
  274. {
  275. // node still does not exist, this should happen only when
  276. // if the parent directory is not in cache
  277. if (Parent != NULL)
  278. {
  279. TRemoteFileList * ParentFileList = NodeFileList(Parent);
  280. if (ParentFileList != NULL)
  281. {
  282. File = ParentFileList->FindFile(UnixExtractFileName(Path));
  283. }
  284. }
  285. Node = LoadPathEasy(Parent, Path, File);
  286. if (Parent != NULL)
  287. {
  288. Parent->AlphaSort(false);
  289. }
  290. }
  291. else
  292. {
  293. UpdatePath(Node, false);
  294. }
  295. }
  296. else
  297. {
  298. UpdatePath(Node, false);
  299. }
  300. return Node;
  301. #else
  302. return NULL;
  303. #endif
  304. }
  305. //---------------------------------------------------------------------------
  306. void __fastcall TCustomUnixDriveView::LoadDirectory()
  307. {
  308. #ifndef DESIGN_ONLY
  309. assert(!FIgnoreChange);
  310. FIgnoreChange = true;
  311. try
  312. {
  313. Selected = LoadPath(FTerminal->Files->Directory);
  314. assert(Selected != NULL);
  315. FPrevSelected = Selected;
  316. }
  317. __finally
  318. {
  319. FIgnoreChange = false;
  320. FDirectoryLoaded = true;
  321. }
  322. #endif
  323. }
  324. //---------------------------------------------------------------------------
  325. TNodeData * __fastcall TCustomUnixDriveView::NodeData(const TTreeNode * Node)
  326. {
  327. assert(Node->Data != NULL);
  328. return static_cast<TNodeData*>(Node->Data);
  329. }
  330. //---------------------------------------------------------------------------
  331. TRemoteFileList * __fastcall TCustomUnixDriveView::NodeFileList(const TTreeNode * Node)
  332. {
  333. assert(Node->Data != NULL);
  334. return static_cast<TNodeData*>(Node->Data)->FileList;
  335. }
  336. //---------------------------------------------------------------------------
  337. TRemoteFile * __fastcall TCustomUnixDriveView::NodeFile(const TTreeNode * Node)
  338. {
  339. assert(Node->Data != NULL);
  340. return static_cast<TNodeData*>(Node->Data)->File;
  341. }
  342. //---------------------------------------------------------------------------
  343. TRemoteFile * __fastcall TCustomUnixDriveView::NodeFileForce(TTreeNode * Node)
  344. {
  345. TRemoteFile * File = NodeFile(Node);
  346. if (File == NULL)
  347. {
  348. #ifndef DESIGN_ONLY
  349. SAFE_DESTROY(FDummyDragFile);
  350. FDummyDragFile = new TRemoteDirectoryFile();
  351. FDummyDragFile->FileName = Node->Text;
  352. FDummyDragFile->FullFileName = NodePathName(Node);
  353. File = FDummyDragFile;
  354. #endif
  355. }
  356. return File;
  357. }
  358. //---------------------------------------------------------------------------
  359. void __fastcall TCustomUnixDriveView::Delete(TTreeNode * Node)
  360. {
  361. if (Node == FPrevSelected)
  362. {
  363. FPrevSelected = NULL;
  364. }
  365. TNodeData * Data = NULL;
  366. if (Node != NULL)
  367. {
  368. Data = NodeData(Node);
  369. }
  370. TCustomDriveView::Delete(Node);
  371. // delete file list at last, when we are sure that no child nodes exist
  372. if (Data != NULL)
  373. {
  374. #ifndef DESIGN_ONLY
  375. delete Data->FileList;
  376. #endif
  377. delete Data;
  378. }
  379. }
  380. //---------------------------------------------------------------------------
  381. void __fastcall TCustomUnixDriveView::Change(TTreeNode * Node)
  382. {
  383. #ifndef DESIGN_ONLY
  384. // During D&D Selected is set to NULL and then back to previous selection,
  385. // prevent actually changing directory in such case
  386. if (FIgnoreChange || (Node == NULL) || (Node == FPrevSelected))
  387. {
  388. TCustomDriveView::Change(Node);
  389. }
  390. else
  391. {
  392. if (FDirView != NULL)
  393. {
  394. // remember current directory, so it gets selected if we move to parent
  395. // directory
  396. FDirView->ContinueSession(true);
  397. }
  398. // if previous node is child to newly selected one, do not expand it.
  399. // it is either already expanded and it is even being collapsed.
  400. bool Expand = (FPrevSelected == NULL) || !FPrevSelected->HasAsParent(Node);
  401. FDirectoryLoaded = false;
  402. try
  403. {
  404. Terminal->ChangeDirectory(NodePathName(Node));
  405. TCustomDriveView::Change(Node);
  406. }
  407. __finally
  408. {
  409. if (FDirectoryLoaded)
  410. {
  411. FPrevSelected = Selected;
  412. if (Expand)
  413. {
  414. Selected->Expand(false);
  415. }
  416. }
  417. else
  418. {
  419. assert(!FIgnoreChange);
  420. FIgnoreChange = true;
  421. try
  422. {
  423. Selected = FPrevSelected;
  424. }
  425. __finally
  426. {
  427. FIgnoreChange = false;
  428. }
  429. }
  430. }
  431. }
  432. #else
  433. TCustomDriveView::Change(Node);
  434. #endif
  435. }
  436. //---------------------------------------------------------------------------
  437. void __fastcall TCustomUnixDriveView::PerformDragDropFileOperation(
  438. TTreeNode * Node, int Effect)
  439. {
  440. if (OnDDFileOperation)
  441. {
  442. assert(DragDropFilesEx->FileList->Count > 0);
  443. assert(Node != NULL);
  444. AnsiString SourceDirectory;
  445. AnsiString TargetDirectory;
  446. SourceDirectory = ExtractFilePath(DragDropFilesEx->FileList->Items[0]->Name);
  447. TargetDirectory = NodeData(Node)->Directory;
  448. bool DoFileOperation = true;
  449. OnDDFileOperation(this, Effect, SourceDirectory, TargetDirectory,
  450. DoFileOperation);
  451. }
  452. }
  453. //---------------------------------------------------------------------------
  454. void __fastcall TCustomUnixDriveView::DDChooseEffect(int KeyState, int & Effect)
  455. {
  456. // if any drop effect is allowed at all (e.g. no drop to self and drop to parent)
  457. if (Effect != DROPEFFECT_None)
  458. {
  459. if (DropTarget != NULL)
  460. {
  461. if ((KeyState & (MK_CONTROL | MK_SHIFT)) == 0)
  462. {
  463. Effect = DROPEFFECT_Copy;
  464. }
  465. }
  466. else
  467. {
  468. Effect = DROPEFFECT_None;
  469. }
  470. }
  471. TCustomDriveView::DDChooseEffect(KeyState, Effect);
  472. }
  473. //---------------------------------------------------------------------------
  474. void __fastcall TCustomUnixDriveView::UpdateDropTarget()
  475. {
  476. // should never be NULL
  477. if (DropTarget != NULL)
  478. {
  479. UpdatePath(DropTarget, false, true);
  480. }
  481. }
  482. //---------------------------------------------------------------------------
  483. void __fastcall TCustomUnixDriveView::UpdateDropSource()
  484. {
  485. // DragNode may be NULL if its parent directory was reloaded as result
  486. // of D&D operation and thus all child nodes are recreated
  487. if ((DragNode != NULL) && (DragNode->Parent != NULL))
  488. {
  489. UpdatePath(DragNode->Parent, false, true);
  490. }
  491. }
  492. //---------------------------------------------------------------------------
  493. TStrings * __fastcall TCustomUnixDriveView::DragFileList()
  494. {
  495. assert(DragNode != NULL);
  496. TStrings * FileList = new TStringList();
  497. try
  498. {
  499. #ifndef DESIGN_ONLY
  500. FileList->AddObject(ExcludeTrailingBackslash(NodePathName(DragNode)),
  501. NodeFileForce(DragNode));
  502. #endif
  503. }
  504. catch(...)
  505. {
  506. delete FileList;
  507. throw;
  508. }
  509. return FileList;
  510. }
  511. //---------------------------------------------------------------------------
  512. bool __fastcall TCustomUnixDriveView::DragCompleteFileList()
  513. {
  514. return true;
  515. }
  516. //---------------------------------------------------------------------------
  517. TDropEffectSet __fastcall TCustomUnixDriveView::DDSourceEffects()
  518. {
  519. TDropEffectSet Result;
  520. Result << deCopy;
  521. if (DDAllowMove)
  522. {
  523. Result << deMove;
  524. }
  525. return Result;
  526. }
  527. //---------------------------------------------------------------------------
  528. AnsiString __fastcall TCustomUnixDriveView::NodePathName(TTreeNode * Node)
  529. {
  530. // same as NodePath
  531. return NodeData(Node)->Directory;
  532. }
  533. //---------------------------------------------------------------------------
  534. void __fastcall TCustomUnixDriveView::ClearDragFileList(TFileList * FileList)
  535. {
  536. #ifndef DESIGN_ONLY
  537. if (FDummyDragFile != NULL)
  538. {
  539. SAFE_DESTROY(FDummyDragFile);
  540. }
  541. #endif
  542. TCustomDriveView::ClearDragFileList(FileList);
  543. }
  544. //---------------------------------------------------------------------------
  545. void __fastcall TCustomUnixDriveView::AddToDragFileList(TFileList * FileList,
  546. TTreeNode * Node)
  547. {
  548. AnsiString FileName = NodePathName(Node);
  549. TRemoteFile * File = NodeFileForce(Node);
  550. if (OnDDDragFileName != NULL)
  551. {
  552. OnDDDragFileName(this, File, FileName);
  553. }
  554. FileList->AddItem(NULL, FileName);
  555. }
  556. //---------------------------------------------------------------------------
  557. AnsiString __fastcall TCustomUnixDriveView::NodePath(TTreeNode * Node)
  558. {
  559. // same as NodePathName
  560. return NodeData(Node)->Directory;
  561. }
  562. //---------------------------------------------------------------------------
  563. bool __fastcall TCustomUnixDriveView::NodeIsRecycleBin(TTreeNode * /*Node*/)
  564. {
  565. return false;
  566. }
  567. //---------------------------------------------------------------------------
  568. bool __fastcall TCustomUnixDriveView::NodePathExists(TTreeNode * /*Node*/)
  569. {
  570. return true;
  571. }
  572. //---------------------------------------------------------------------------
  573. TColor __fastcall TCustomUnixDriveView::NodeColor(TTreeNode * Node)
  574. {
  575. assert(Node != NULL);
  576. TColor Result = static_cast<TColor>(clDefaultItemColor);
  577. #ifndef DESIGN_ONLY
  578. if (FDimmHiddenDirs && !Node->Selected)
  579. {
  580. if (NodeIsHidden(Node))
  581. {
  582. Result = clGrayText;
  583. }
  584. }
  585. #endif
  586. return Result;
  587. }
  588. //---------------------------------------------------------------------------
  589. Word __fastcall TCustomUnixDriveView::NodeOverlayIndexes(TTreeNode * Node)
  590. {
  591. #ifndef DESIGN_ONLY
  592. Word Result = oiNoOverlay;
  593. // Cannot query root node for file
  594. if (Node->Parent != NULL)
  595. {
  596. TRemoteFile * File = NodeFile(Node);
  597. if ((File != NULL) && (File->IsSymLink))
  598. {
  599. // broken link cannot probably happen anyway
  600. // as broken links are treated as files
  601. Result |= File->BrokenLink ? oiBrokenLink : oiLink;
  602. }
  603. }
  604. return Result;
  605. #else
  606. return 0;
  607. #endif
  608. }
  609. //---------------------------------------------------------------------------
  610. void __fastcall TCustomUnixDriveView::GetImageIndex(TTreeNode * Node)
  611. {
  612. TCustomDriveView::GetImageIndex(Node);
  613. Node->ImageIndex = StdDirIcon;
  614. Node->SelectedIndex = StdDirSelIcon;
  615. }
  616. //---------------------------------------------------------------------------
  617. TTreeNode * __fastcall TCustomUnixDriveView::FindNodeToPath(AnsiString Path)
  618. {
  619. TTreeNode * Result;
  620. #ifndef DESIGN_ONLY
  621. if (IsUnixRootPath(Path))
  622. {
  623. Result = Items->GetFirstNode();
  624. }
  625. else
  626. {
  627. Result = NULL;
  628. Path = UnixExcludeTrailingBackslash(Path);
  629. TTreeNode * Parent = NULL;
  630. if (!IsUnixRootPath(Path))
  631. {
  632. Parent = FindNodeToPath(UnixExtractFileDir(Path));
  633. }
  634. if ((Parent != NULL) && (Parent->getFirstChild() != NULL))
  635. {
  636. AnsiString DirName = UnixExtractFileName(Path);
  637. int StartIndex = 0;
  638. int EndIndex = Parent->Count - 1;
  639. while (true)
  640. {
  641. int Index = (StartIndex + EndIndex) / 2;
  642. AnsiString NodeDir = Parent->Item[Index]->Text;
  643. // lstrcmp is used by AlphaSort()
  644. int C = lstrcmp(DirName.c_str(), NodeDir.c_str());
  645. if (C == 0)
  646. {
  647. Result = Parent->Item[Index];
  648. break;
  649. }
  650. else if (C < 0)
  651. {
  652. if (Index == StartIndex)
  653. {
  654. break;
  655. }
  656. EndIndex = Index - 1;
  657. }
  658. else
  659. {
  660. if (Index == EndIndex)
  661. {
  662. break;
  663. }
  664. StartIndex = Index + 1;
  665. }
  666. }
  667. }
  668. }
  669. #else
  670. Result = NULL
  671. #endif
  672. return Result;
  673. }
  674. //---------------------------------------------------------------------------
  675. TTreeNode * __fastcall TCustomUnixDriveView::FindPathNode(AnsiString Path)
  676. {
  677. TTreeNode * Result = NULL;
  678. #ifndef DESIGN_ONLY
  679. if (Items->GetFirstNode() != NULL)
  680. {
  681. do
  682. {
  683. Result = FindNodeToPath(Path);
  684. if (Result == NULL)
  685. {
  686. assert(!IsUnixRootPath(Path));
  687. Path = UnixExtractFileDir(UnixExcludeTrailingBackslash(Path));
  688. }
  689. }
  690. while (Result == NULL);
  691. }
  692. #endif
  693. return Result;
  694. }
  695. //---------------------------------------------------------------------------
  696. void __fastcall TCustomUnixDriveView::ValidateDirectoryEx(TTreeNode * /*Node*/,
  697. TRecursiveScan /*Recurse*/, bool /*NewDirs*/)
  698. {
  699. // nothing
  700. }
  701. //---------------------------------------------------------------------------
  702. void __fastcall TCustomUnixDriveView::RebuildTree()
  703. {
  704. TTreeNode * First = Items->GetFirstNode();
  705. if (First != NULL)
  706. {
  707. UpdatePath(First, true);
  708. }
  709. }
  710. //---------------------------------------------------------------------------
  711. void __fastcall TCustomUnixDriveView::SetShowInaccesibleDirectories(bool value)
  712. {
  713. if (FShowInaccesibleDirectories != value)
  714. {
  715. FShowInaccesibleDirectories = value;
  716. RebuildTree();
  717. }
  718. }
  719. //---------------------------------------------------------------------------
  720. void __fastcall TCustomUnixDriveView::CMShowingChanged(TMessage & Message)
  721. {
  722. TCustomDriveView::Dispatch(&Message);
  723. if (Showing && (Terminal != NULL))
  724. {
  725. LoadDirectory();
  726. }
  727. }
  728. //---------------------------------------------------------------------------
  729. void __fastcall TCustomUnixDriveView::DisplayContextMenu(TTreeNode * /*Node*/,
  730. const TPoint & /*ScreenPos*/)
  731. {
  732. // TODO
  733. }
  734. //---------------------------------------------------------------------------
  735. void __fastcall TCustomUnixDriveView::DisplayPropertiesMenu(TTreeNode * /*Node*/)
  736. {
  737. // TODO
  738. }