UnixDirView.cpp 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085
  1. //---------------------------------------------------------------------------
  2. #include <vcl.h>
  3. #pragma hdrstop
  4. #include "UnixDirView.h"
  5. #include <FileCtrl.hpp>
  6. #ifndef DESIGN_ONLY
  7. #include <Interface.h>
  8. #include <ScpMain.h>
  9. #endif
  10. #include <Common.h>
  11. #pragma package(smart_init)
  12. #ifndef DESIGN_ONLY
  13. #define ITEMFILE ((TRemoteFile *)(Item->Data))
  14. #define ASSERT_VALID_ITEM assert(Item && Item->Data && Terminal); assert(Terminal->Files->IndexOf(ITEMFILE) >= 0)
  15. #endif
  16. //---------------------------------------------------------------------------
  17. static inline void ValidCtrCheck(TUnixDirView *)
  18. {
  19. new TUnixDirView(NULL);
  20. }
  21. //---------------------------------------------------------------------------
  22. namespace Unixdirview
  23. {
  24. void __fastcall PACKAGE Register()
  25. {
  26. TComponentClass classes[1] = {__classid(TUnixDirView)};
  27. RegisterComponents("Scp", classes, 0);
  28. }
  29. }
  30. //---------------------------------------------------------------------------
  31. #ifndef DESIGN_ONLY
  32. #define RFILE(N) ((TRemoteFile *)(Item ## N->Data))
  33. int __stdcall CompareDirectories(TListItem *Item1, TListItem *Item2, TUnixDirView *DirView)
  34. {
  35. // Because CompareDirectories is called from each other compare functions
  36. // it's sufficient to check pointers only here (see below)
  37. assert(DirView && Item1 && RFILE(1) && Item2 && RFILE(2));
  38. if (RFILE(1)->IsParentDirectory && !RFILE(2)->IsParentDirectory) return -1;
  39. else
  40. if (!RFILE(1)->IsParentDirectory && RFILE(2)->IsParentDirectory) return 1;
  41. else
  42. if (DirView->DirsOnTop &&
  43. RFILE(1)->IsDirectory && !RFILE(2)->IsDirectory) return -1;
  44. else
  45. if (DirView->DirsOnTop &&
  46. !RFILE(1)->IsDirectory && RFILE(2)->IsDirectory) return 1;
  47. else
  48. return 0;
  49. }
  50. //---------------------------------------------------------------------------
  51. #define DEFINE_COMPARE_FUNC(Property, CompareFunc) \
  52. int __stdcall Compare ## Property(TListItem *Item1, TListItem *Item2, TUnixDirView *DirView) \
  53. { int Result = CompareDirectories(Item1, Item2, DirView); \
  54. if (!Result) { Result = CompareFunc(RFILE(1)->Property, RFILE(2)->Property); \
  55. if (!DirView->UnixColProperties->SortAscending) Result = -Result; }\
  56. return Result; }
  57. #define COMPARE_NUMBER(Num1, Num2) ( Num1 < Num2 ? -1 : ( Num1 > Num2 ? 1 : 0) )
  58. //---------------------------------------------------------------------------
  59. DEFINE_COMPARE_FUNC(FileName, AnsiCompareText);
  60. DEFINE_COMPARE_FUNC(Size, COMPARE_NUMBER);
  61. DEFINE_COMPARE_FUNC(Modification, COMPARE_NUMBER);
  62. DEFINE_COMPARE_FUNC(RightsStr, AnsiCompareText);
  63. DEFINE_COMPARE_FUNC(Owner, AnsiCompareText);
  64. DEFINE_COMPARE_FUNC(Group, AnsiCompareText);
  65. DEFINE_COMPARE_FUNC(Extension, AnsiCompareText);
  66. //---------------------------------------------------------------------------
  67. #undef DEFINE_COMPARE_FUNC
  68. #undef COMPARE_NUMBER
  69. #undef RFILE
  70. #endif
  71. //---------------------------------------------------------------------------
  72. AnsiString __fastcall UniqTempDir(const AnsiString BaseDir)
  73. {
  74. AnsiString TempDir;
  75. #ifndef DESIGN_ONLY
  76. if (BaseDir.IsEmpty()) TempDir = SystemTemporaryDirectory();
  77. else
  78. #endif
  79. TempDir = BaseDir;
  80. TempDir = IncludeTrailingBackslash(IncludeTrailingBackslash(TempDir) + "scp" +
  81. FormatDateTime("nnzzz", Now()));
  82. return TempDir;
  83. }
  84. //---------------------------------------------------------------------------
  85. __fastcall TUnixDirView::TUnixDirView(TComponent* Owner)
  86. : TCustomUnixDirView(Owner)
  87. {
  88. #ifndef DESIGN_ONLY
  89. FTerminal = NULL;
  90. #endif
  91. FUniqTempDir = "";
  92. FDDDeleteDelay = DefaultDDDeleteDelay;
  93. FCaseSensitive = true;
  94. DDAllowMove = false;
  95. FShowInaccesibleDirectories = true;
  96. FOnWarnLackOfTempSpace = NULL;
  97. FDDTotalSize = -1;
  98. FDelayedDeletionTimer = NULL;
  99. FFullLoad = false;
  100. FDDFileList = NULL;
  101. FDelayedDeletionList = new TStringList();
  102. }
  103. //---------------------------------------------------------------------------
  104. __fastcall TUnixDirView::~TUnixDirView()
  105. {
  106. #ifndef DESIGN_ONLY
  107. Terminal = NULL;
  108. #endif
  109. if (FDelayedDeletionTimer)
  110. {
  111. DoDelayedDeletion(NULL);
  112. delete FDelayedDeletionTimer;
  113. }
  114. delete FDelayedDeletionList;
  115. }
  116. //---------------------------------------------------------------------------
  117. void __fastcall TUnixDirView::DisplayContextMenu(const TPoint &Where)
  118. {
  119. bool Handled = false;
  120. if (OnContextPopup) OnContextPopup(this, ScreenToClient(Where), Handled);
  121. if (!Handled)
  122. {
  123. if (PopupMenu && !PopupMenu->AutoPopup)
  124. PopupMenu->Popup(Where.x, Where.y);
  125. }
  126. }
  127. //---------------------------------------------------------------------------
  128. void __fastcall TUnixDirView::AddDelayedDirectoryDeletion(
  129. const AnsiString TempDir, int SecDelay)
  130. {
  131. TDateTime Alarm = Now() + (double)SecDelay*(double(1)/24/60/60);
  132. AnsiString xx = Alarm.TimeString();
  133. FDelayedDeletionList->AddObject(TempDir, (TObject*)Alarm.FileDate());
  134. if (!FDelayedDeletionTimer)
  135. {
  136. assert(HandleAllocated());
  137. FDelayedDeletionTimer = new TTimer(this);
  138. FDelayedDeletionTimer->Interval = 10000;
  139. FDelayedDeletionTimer->Enabled = true;
  140. FDelayedDeletionTimer->OnTimer = DoDelayedDeletion;
  141. }
  142. }
  143. //---------------------------------------------------------------------------
  144. bool DeleteCurrentFile(const AnsiString FileName)
  145. {
  146. if (FileName == "." || FileName == "..")
  147. {
  148. return true;
  149. }
  150. else
  151. {
  152. return DeleteFile(FileName);
  153. }
  154. }
  155. //---------------------------------------------------------------------------
  156. bool DeleteDirectory(const AnsiString DirName)
  157. {
  158. TSearchRec sr;
  159. bool retval = true;
  160. if (FindFirst(DirName + "\\*", faAnyFile, sr) == 0) // VCL Function
  161. {
  162. if (sr.Attr == faDirectory)
  163. {
  164. if (sr.Name != "." && sr.Name != "..")
  165. retval = DeleteDirectory(DirName + "\\" + sr.Name);
  166. }
  167. else
  168. {
  169. retval = DeleteCurrentFile(DirName + "\\" + sr.Name);
  170. }
  171. if (retval)
  172. {
  173. while (FindNext(sr) == 0)
  174. { // VCL Function
  175. if (sr.Attr == faDirectory)
  176. {
  177. if (sr.Name != "." && sr.Name != "..")
  178. retval = DeleteDirectory(DirName + "\\" + sr.Name);
  179. }
  180. else
  181. {
  182. retval = DeleteCurrentFile(DirName + "\\" + sr.Name);
  183. }
  184. if (!retval) break;
  185. }
  186. }
  187. }
  188. FindClose(sr);
  189. if (retval) retval = RemoveDir(DirName); // VCL function
  190. return retval;
  191. }
  192. //---------------------------------------------------------------------------
  193. void __fastcall TUnixDirView::DoDelayedDeletion(TObject * Sender)
  194. {
  195. assert(FDelayedDeletionList);
  196. TDateTime N = Now();
  197. TDateTime Alert;
  198. AnsiString Directory;
  199. for (int Index = FDelayedDeletionList->Count-1; Index >= 0; Index--)
  200. {
  201. Alert = FileDateToDateTime((int)FDelayedDeletionList->Objects[Index]);
  202. if (N >= Alert || !Sender)
  203. {
  204. Directory = FDelayedDeletionList->Strings[Index];
  205. if (DeleteDirectory(ExcludeTrailingBackslash(Directory)))
  206. {
  207. FDelayedDeletionList->Delete(Index);
  208. }
  209. }
  210. }
  211. if (FDelayedDeletionList->Count == 0)
  212. {
  213. FDelayedDeletionTimer->Enabled = false;
  214. }
  215. }
  216. //---------------------------------------------------------------------------
  217. void __fastcall TUnixDirView::DisplayPropertiesMenu()
  218. {
  219. if (OnDisplayProperties) OnDisplayProperties(this);
  220. }
  221. //---------------------------------------------------------------------------
  222. void __fastcall TUnixDirView::ExecuteFile(TListItem * Item)
  223. {
  224. #ifndef DESIGN_ONLY
  225. ASSERT_VALID_ITEM;
  226. if (ITEMFILE->IsDirectory)
  227. {
  228. FLastPath = PathName;
  229. ChangeDirectory(ITEMFILE->FileName);
  230. }
  231. else
  232. {
  233. if (ItemFocused != Item) ItemFocused = Item;
  234. DisplayPropertiesMenu();
  235. }
  236. #endif
  237. }
  238. //---------------------------------------------------------------------------
  239. void __fastcall TUnixDirView::ExecuteParentDirectory()
  240. {
  241. // We need to remember this to select directory being leaved in parent directory
  242. FLastPath = PathName;
  243. #ifndef DESIGN_ONLY
  244. ChangeDirectory(PARENTDIRECTORY);
  245. #endif
  246. }
  247. //---------------------------------------------------------------------------
  248. void __fastcall TUnixDirView::ExecuteHomeDirectory()
  249. {
  250. #ifndef DESIGN_ONLY
  251. // don't select any directory
  252. FLastPath = "";
  253. AnsiString APath = Terminal->SessionData->RemoteDirectory;
  254. if (Configuration->DefaultDirIsHome && !APath.IsEmpty() &&
  255. !Terminal->SessionData->UpdateDirectories)
  256. {
  257. if (APath[1] != '/')
  258. {
  259. Terminal->BeginTransaction();
  260. try
  261. {
  262. ChangeDirectory(HOMEDIRECTORY);
  263. ChangeDirectory(APath);
  264. }
  265. __finally
  266. {
  267. Terminal->EndTransaction();
  268. }
  269. }
  270. else
  271. {
  272. ChangeDirectory(APath);
  273. }
  274. }
  275. else
  276. {
  277. ChangeDirectory(HOMEDIRECTORY);
  278. }
  279. #endif
  280. }
  281. //---------------------------------------------------------------------------
  282. void __fastcall TUnixDirView::ReloadDirectory()
  283. {
  284. #ifndef DESIGN_ONLY
  285. FLastPath = "";
  286. DoAnimation(true);
  287. Terminal->ReloadDirectory();
  288. #endif
  289. }
  290. //---------------------------------------------------------------------------
  291. void __fastcall TUnixDirView::ExecuteRootDirectory()
  292. {
  293. #ifndef DESIGN_ONLY
  294. // We set LastPath to top directory, so it will be selected
  295. // after entering root directory
  296. // DISABLED: see PathChanged(): back moves to top directory, not to current
  297. FLastPath = PathName;
  298. ChangeDirectory(ROOTDIRECTORY);
  299. #endif
  300. }
  301. //---------------------------------------------------------------------------
  302. bool __fastcall TUnixDirView::ItemIsDirectory(TListItem * Item)
  303. {
  304. #ifndef DESIGN_ONLY
  305. ASSERT_VALID_ITEM;
  306. return ITEMFILE->IsDirectory;
  307. #else
  308. return false;
  309. #endif
  310. }
  311. //---------------------------------------------------------------------------
  312. bool __fastcall TUnixDirView::ItemIsFile(TListItem * Item)
  313. {
  314. #ifndef DESIGN_ONLY
  315. ASSERT_VALID_ITEM;
  316. return !(ITEMFILE->IsParentDirectory);
  317. #else
  318. return false;
  319. #endif
  320. }
  321. //---------------------------------------------------------------------------
  322. bool __fastcall TUnixDirView::ItemIsParentDirectory(TListItem * Item)
  323. {
  324. #ifndef DESIGN_ONLY
  325. ASSERT_VALID_ITEM;
  326. return ITEMFILE->IsParentDirectory;
  327. #else
  328. return false;
  329. #endif
  330. }
  331. //---------------------------------------------------------------------------
  332. AnsiString __fastcall TUnixDirView::ItemFileName(TListItem * Item)
  333. {
  334. #ifndef DESIGN_ONLY
  335. ASSERT_VALID_ITEM;
  336. return ITEMFILE->FileName;
  337. #else
  338. return AnsiString();
  339. #endif
  340. }
  341. //---------------------------------------------------------------------------
  342. __int64 __fastcall TUnixDirView::ItemFileSize(TListItem * Item)
  343. {
  344. #ifndef DESIGN_ONLY
  345. ASSERT_VALID_ITEM;
  346. return ITEMFILE->IsDirectory ? 0 : ITEMFILE->Size;
  347. #else
  348. return 0;
  349. #endif
  350. }
  351. //---------------------------------------------------------------------------
  352. AnsiString __fastcall TUnixDirView::ItemDragFileName(TListItem * Item)
  353. {
  354. #ifndef DESIGN_ONLY
  355. assert(Item && Item->Data && Terminal && (Terminal->Files->IndexOf(ITEMFILE) >= 0) && !FUniqTempDir.IsEmpty());
  356. return FUniqTempDir + Configuration->CopyParam.ValidLocalFileName(ITEMFILE->FileName);
  357. #else
  358. return 0;
  359. #endif
  360. }
  361. //---------------------------------------------------------------------------
  362. AnsiString __fastcall TUnixDirView::ItemFullFileName(TListItem * Item)
  363. {
  364. #ifndef DESIGN_ONLY
  365. ASSERT_VALID_ITEM;
  366. return ITEMFILE->FullFileName;
  367. #else
  368. return AnsiString();
  369. #endif
  370. }
  371. //---------------------------------------------------------------------------
  372. int __fastcall TUnixDirView::ItemImageIndex(TListItem * Item, bool /*Cache*/)
  373. {
  374. #ifndef DESIGN_ONLY
  375. ASSERT_VALID_ITEM;
  376. // TCustomDirView::ItemImageIndex is used for icon caching
  377. // so we don't need it here. But it's implemented anyway.
  378. return ITEMFILE->IconIndex;
  379. #else
  380. return 0;
  381. #endif
  382. }
  383. //---------------------------------------------------------------------------
  384. bool __fastcall TUnixDirView::ItemMatchesFilter(TListItem * Item,
  385. const TFileFilter &Filter)
  386. {
  387. #ifndef DESIGN_ONLY
  388. ASSERT_VALID_ITEM;
  389. TRemoteFile *File = ITEMFILE;
  390. int Attr = File->Attr;
  391. return
  392. ((Attr & Filter.IncludeAttr) == Filter.IncludeAttr) &&
  393. ((Attr & Filter.ExcludeAttr) == 0) &&
  394. ((!File->IsDirectory) || Filter.Directories) &&
  395. ((Filter.FileSizeFrom == 0) || (File->Size >= Filter.FileSizeFrom)) &&
  396. ((Filter.FileSizeTo == 0) || (File->Size <= Filter.FileSizeTo)) &&
  397. ((!(int)Filter.ModificationFrom) || (File->Modification >= Filter.ModificationFrom)) &&
  398. ((!(int)Filter.ModificationTo) || (File->Modification <= Filter.ModificationTo)) &&
  399. ((Filter.Masks.IsEmpty()) ||
  400. FileNameMatchesMasks(File->FileName, Filter.Masks));
  401. #else
  402. return false;
  403. #endif
  404. }
  405. //---------------------------------------------------------------------------
  406. Word __fastcall TUnixDirView::ItemOverlayIndexes(TListItem * Item)
  407. {
  408. #ifndef DESIGN_ONLY
  409. ASSERT_VALID_ITEM;
  410. Word Result = oiNoOverlay;
  411. if (ITEMFILE->IsParentDirectory)
  412. {
  413. Result |= oiDirUp;
  414. }
  415. if (ITEMFILE->IsSymLink)
  416. {
  417. Result |= ITEMFILE->BrokenLink ? oiBrokenLink : oiLink;
  418. }
  419. return Result;
  420. #else
  421. return 0;
  422. #endif
  423. }
  424. //---------------------------------------------------------------------------
  425. void __fastcall TUnixDirView::LoadFiles()
  426. {
  427. #ifndef DESIGN_ONLY
  428. assert(Terminal);
  429. if (DirOK)
  430. {
  431. // it's enough if we reach this point, we don't require that loading files into
  432. // list succeeded. FDirLoadedAfterChangeDir == false tells only that
  433. // loding file list from server failed, not loading into listview
  434. FDirLoadedAfterChangeDir = true;
  435. FFilesSize = 0;
  436. FHasParentDir = false;
  437. int VisibleFiles = 0;
  438. for (int Index = 0; Index < Terminal->Files->Count; Index++)
  439. {
  440. TRemoteFile *File = Terminal->Files->Files[Index];
  441. assert(File);
  442. TListItem *Item;
  443. if ((ShowHiddenFiles || !File->IsHidden) &&
  444. (ShowInaccesibleDirectories || !File->IsInaccesibleDirectory))
  445. {
  446. VisibleFiles++;
  447. if (!File->IsDirectory) FFilesSize += File->Size;
  448. if (File->IsParentDirectory) FHasParentDir = true;
  449. Item = Items->Add();
  450. Item->Data = File;
  451. Item->Caption = File->FileName;
  452. if (FFullLoad)
  453. {
  454. Item->ImageIndex = File->IconIndex;
  455. Item->SubItems->Add((!File->IsDirectory ? FormatFloat("#,##0", File->Size) : AnsiString()));
  456. Item->SubItems->Add(File->UserModificationStr);
  457. Item->SubItems->Add(File->RightsStr);
  458. Item->SubItems->Add(File->Owner);
  459. Item->SubItems->Add(File->Group);
  460. Item->SubItems->Add(File->Extension);
  461. }
  462. }
  463. }
  464. if (OwnerData)
  465. {
  466. Items->Count = VisibleFiles;
  467. }
  468. }
  469. #endif
  470. }
  471. //---------------------------------------------------------------------------
  472. void __fastcall TUnixDirView::GetDisplayInfo(TListItem * Item, tagLVITEMA &DispInfo)
  473. {
  474. if (!FFullLoad)
  475. {
  476. #ifndef DESIGN_ONLY
  477. TRemoteFile * File = ITEMFILE;
  478. if (DispInfo.mask & LVIF_TEXT)
  479. {
  480. AnsiString Value;
  481. switch (DispInfo.iSubItem) {
  482. case uvName: Value = File->FileName; break;
  483. case uvSize: Value = (!File->IsDirectory ? FormatFloat("#,##0", File->Size) : AnsiString()); break;
  484. case uvChanged: Value = File->UserModificationStr; break;
  485. case uvRights: Value = File->RightsStr; break;
  486. case uvOwner: Value = File->Owner; break;
  487. case uvGroup: Value = File->Group; break;
  488. case uvExt: Value = File->Extension; break;
  489. default: assert(false);
  490. }
  491. StrPLCopy(DispInfo.pszText, Value, DispInfo.cchTextMax);
  492. }
  493. if (DispInfo.iSubItem == 0 && DispInfo.mask & LVIF_IMAGE)
  494. {
  495. DispInfo.iImage = File->IconIndex;
  496. DispInfo.mask |= LVIF_DI_SETITEM;
  497. }
  498. #endif
  499. }
  500. }
  501. //---------------------------------------------------------------------------
  502. void __fastcall TUnixDirView::PerformItemDragDropOperation(TListItem * Item, int Effect)
  503. {
  504. #ifndef DESIGN_ONLY
  505. assert(DragDropFilesEx);
  506. TTransferType Type;
  507. TCopyParamType CopyParams = Configuration->CopyParam;
  508. TStrings *FileList = NULL;
  509. AnsiString Directory;
  510. switch (Effect) {
  511. case DROPEFFECT_COPY: Type = ttCopy; break;
  512. case DROPEFFECT_MOVE: Type = ttMove; break;
  513. // occures on WinXP (reported by user)
  514. default: Type = ttCopy; //assert(false);
  515. };
  516. FileList = new TStringList();
  517. try
  518. {
  519. for (int Index = 0; Index < DragDropFilesEx->FileList->Count; Index++)
  520. {
  521. FileList->Add(DragDropFilesEx->FileList->Items[Index]->Name);
  522. }
  523. if (Item)
  524. {
  525. assert(ITEMFILE->IsDirectory && (Terminal->Files->IndexOf(ITEMFILE) >= 0));
  526. Directory = ITEMFILE->FullFileName;
  527. }
  528. else
  529. {
  530. Directory = Path;
  531. }
  532. if (OnGetCopyParam)
  533. {
  534. OnGetCopyParam(this, tdToRemote, Type, Directory, FileList, CopyParams);
  535. }
  536. assert(Terminal);
  537. int Params = cpDragDrop;
  538. if (Type == ttMove) Params |= cpDelete;
  539. Terminal->CopyToRemote(FileList, Directory, &CopyParams, Params);
  540. // If target is current directory, we try to focus first dropped file
  541. if (!Item)
  542. {
  543. int RemoteIndex, DragIndex;
  544. for (RemoteIndex = 0; RemoteIndex < Items->Count; RemoteIndex++)
  545. {
  546. for (DragIndex = 0; DragIndex < FileList->Count; DragIndex++)
  547. {
  548. if (ItemFileName(Items->Item[RemoteIndex]) ==
  549. ExtractFileName(FileList->Strings[DragIndex]))
  550. {
  551. ItemFocused = Items->Item[RemoteIndex];
  552. // We need to break both FOR cycles
  553. RemoteIndex = Items->Count-1;
  554. break;
  555. }
  556. }
  557. }
  558. }
  559. }
  560. __finally
  561. {
  562. delete FileList;
  563. }
  564. #endif
  565. }
  566. //---------------------------------------------------------------------------
  567. void __fastcall TUnixDirView::SetItemImageIndex(TListItem * /* Item */, int /* Index */)
  568. {
  569. // TCustomDirView::SetItemImageIndex is used for icon caching
  570. // so we don't need it here.
  571. }
  572. //---------------------------------------------------------------------------
  573. void __fastcall TUnixDirView::DDMenuDone(TObject* /* Sender */, HMENU /* AMenu */)
  574. {
  575. // TODO: Why I need to duplicate this method? (see TCustomDirView::DDMenuDone)
  576. }
  577. //---------------------------------------------------------------------------
  578. #ifndef DESIGN_ONLY
  579. void __fastcall TUnixDirView::SetTerminal(TTerminal *value)
  580. {
  581. if (FTerminal != value)
  582. {
  583. if (FTerminal)
  584. {
  585. assert(FTerminal->OnReadDirectory == DoReadDirectory);
  586. Terminal->OnReadDirectory = NULL;
  587. assert(FTerminal->OnChangeDirectory == DoChangeDirectory);
  588. FTerminal->OnChangeDirectory = NULL;
  589. if (!value || !value->Files->Loaded)
  590. {
  591. ClearItems();
  592. }
  593. }
  594. FTerminal = value;
  595. if (FTerminal)
  596. {
  597. FTerminal->OnReadDirectory = DoReadDirectory;
  598. FTerminal->OnChangeDirectory = DoChangeDirectory;
  599. FTerminal->Files->IncludeParentDirectory = AddParentDir;
  600. if (FTerminal->Files->Loaded)
  601. {
  602. DoChangeDirectory(FTerminal);
  603. DoReadDirectory(FTerminal, false);
  604. }
  605. }
  606. }
  607. }
  608. #endif
  609. //---------------------------------------------------------------------------
  610. void __fastcall TUnixDirView::DoReadDirectory(TObject * /*Sender*/, bool ReloadOnly)
  611. {
  612. #ifndef DESIGN_ONLY
  613. if (Terminal->Active)
  614. {
  615. if (ReloadOnly)
  616. {
  617. Reload(false);
  618. }
  619. else
  620. {
  621. Load();
  622. PathChanged();
  623. }
  624. }
  625. #endif
  626. }
  627. //---------------------------------------------------------------------------
  628. void __fastcall TUnixDirView::DoChangeDirectory(TObject * /*Sender*/)
  629. {
  630. #ifndef DESIGN_ONLY
  631. // Reload(false);
  632. #endif
  633. }
  634. //---------------------------------------------------------------------------
  635. bool __fastcall TUnixDirView::GetDirOK()
  636. {
  637. #ifndef DESIGN_ONLY
  638. return (Active && Terminal->Files->Loaded);
  639. #else
  640. return false;
  641. #endif
  642. }
  643. //---------------------------------------------------------------------------
  644. AnsiString __fastcall TUnixDirView::GetPathName()
  645. {
  646. #ifndef DESIGN_ONLY
  647. if (DirOK) return Terminal->CurrentDirectory;
  648. else
  649. #endif
  650. return "";
  651. }
  652. //---------------------------------------------------------------------------
  653. AnsiString __fastcall TUnixDirView::GetPath()
  654. {
  655. #ifndef DESIGN_ONLY
  656. if (DirOK) return UnixIncludeTrailingBackslash(Terminal->CurrentDirectory);
  657. else
  658. #endif
  659. return "";
  660. }
  661. //---------------------------------------------------------------------------
  662. void __fastcall TUnixDirView::SetPath(AnsiString Value)
  663. {
  664. #ifndef DESIGN_ONLY
  665. Value = UnixExcludeTrailingBackslash(
  666. StringReplace(Value, '\\', '/', TReplaceFlags() << rfReplaceAll));
  667. if (Active && (Terminal->CurrentDirectory != Value))
  668. {
  669. FLastPath = PathName;
  670. Terminal->CurrentDirectory = Value;
  671. }
  672. #endif
  673. }
  674. //---------------------------------------------------------------------------
  675. void __fastcall TUnixDirView::SortItems()
  676. {
  677. #ifndef DESIGN_ONLY
  678. assert(Terminal);
  679. if (HandleAllocated())
  680. {
  681. PFNLVCOMPARE SortProc;
  682. switch (SortColumn) {
  683. case uvName: SortProc = (PFNLVCOMPARE)CompareFileName; break;
  684. case uvSize: SortProc = (PFNLVCOMPARE)CompareSize; break;
  685. case uvChanged: SortProc = (PFNLVCOMPARE)CompareModification; break;
  686. case uvRights: SortProc = (PFNLVCOMPARE)CompareRightsStr; break;
  687. case uvOwner: SortProc = (PFNLVCOMPARE)CompareOwner; break;
  688. case uvGroup: SortProc = (PFNLVCOMPARE)CompareGroup; break;
  689. case uvExt: SortProc = (PFNLVCOMPARE)CompareExtension; break;
  690. default: assert(false);
  691. }
  692. CustomSortItems(SortProc);
  693. }
  694. #endif
  695. }
  696. //---------------------------------------------------------------------------
  697. bool __fastcall TUnixDirView::GetActive()
  698. {
  699. #ifndef DESIGN_ONLY
  700. return ((Terminal != NULL) && Terminal->Active);
  701. #else
  702. return false;
  703. #endif
  704. }
  705. //---------------------------------------------------------------------------
  706. AnsiString __fastcall TUnixDirView::GetUniqTempDir()
  707. {
  708. return UniqTempDir(DDTemporaryDirectory);
  709. }
  710. //---------------------------------------------------------------------------
  711. void __fastcall TUnixDirView::DDDragDetect(int grfKeyState,
  712. const TPoint &DetectStart, const TPoint &Point, TDragDetectStatus DragStatus)
  713. {
  714. if ((DragStatus == ddsDrag) && (!Loading) && (MarkedCount > 0))
  715. {
  716. assert(FDragDropSshTerminate.IsEmpty());
  717. FDragDropSshTerminate = "";
  718. assert(!FDDFileList);
  719. FDDFileList = NULL;
  720. try
  721. {
  722. FDDFileList = new TStringList();
  723. FUniqTempDir = GetUniqTempDir();
  724. TCustomUnixDirView::DDDragDetect(grfKeyState, DetectStart, Point, DragStatus);
  725. #ifndef DESIGN_ONLY
  726. if (!FDragDropSshTerminate.IsEmpty())
  727. {
  728. throw ESshTerminate(NULL, FDragDropSshTerminate);
  729. }
  730. #endif
  731. }
  732. __finally
  733. {
  734. FDragDropSshTerminate = "";
  735. SAFE_DESTROY(FDDFileList);
  736. }
  737. }
  738. }
  739. //---------------------------------------------------------------------------
  740. void __fastcall TUnixDirView::SetAddParentDir(bool Value)
  741. {
  742. if (Value != AddParentDir)
  743. {
  744. #ifndef DESIGN_ONLY
  745. if (Terminal) Terminal->Files->IncludeParentDirectory = Value;
  746. #endif
  747. TCustomUnixDirView::SetAddParentDir(Value);
  748. }
  749. }
  750. //---------------------------------------------------------------------------
  751. void __fastcall TUnixDirView::SetDDDeleteDelay(int value)
  752. {
  753. if (value < 0) value = -1;
  754. if (FDDDeleteDelay != value)
  755. {
  756. FDDDeleteDelay = value;
  757. }
  758. }
  759. //---------------------------------------------------------------------------
  760. bool __fastcall TUnixDirView::TargetHasDropHandler(TListItem * /* Item */, int /* Effect */)
  761. {
  762. return false;
  763. }
  764. //---------------------------------------------------------------------------
  765. void __fastcall TUnixDirView::DDGiveFeedback(int dwEffect, HRESULT & Result)
  766. {
  767. // Remember drop effect so we know (when user dropes files), if we copy or move
  768. FLastDropEffect = dwEffect;
  769. TCustomUnixDirView::DDGiveFeedback(dwEffect, Result);
  770. }
  771. //---------------------------------------------------------------------------
  772. void __fastcall TUnixDirView::DDQueryContinueDrag(BOOL FEscapePressed,
  773. int grfKeyState, HRESULT & Result)
  774. {
  775. #ifndef DESIGN_ONLY
  776. TCustomUnixDirView::DDQueryContinueDrag(FEscapePressed, grfKeyState, Result);
  777. if (Result == DRAGDROP_S_DROP)
  778. {
  779. try
  780. {
  781. GlobalDragImageList->HideDragImage();
  782. DDTargetDrop();
  783. }
  784. catch (Exception &E)
  785. {
  786. // If downloading fails we need to cancel drag&drop, othwerwise
  787. // Explorer shows error
  788. // But by the way exception probably never reach this point as
  789. // it's catched on way
  790. Result = DRAGDROP_S_CANCEL;
  791. ShowExtendedException(&E);
  792. }
  793. }
  794. #endif
  795. }
  796. //---------------------------------------------------------------------------
  797. void __fastcall TUnixDirView::DDTargetDrop()
  798. {
  799. #ifndef DESIGN_ONLY
  800. assert(!FUniqTempDir.IsEmpty());
  801. TTransferType Type;
  802. AnsiString TempDir = FUniqTempDir;
  803. // We clear FUniqTempDir before calling
  804. // just in case it fail (raises exception)
  805. FUniqTempDir = "";
  806. Type = (FLastDropEffect & DROPEFFECT_MOVE ? ttMove : Type = ttCopy);
  807. try
  808. {
  809. TStrings * FileList = new TStringList();
  810. try
  811. {
  812. assert(DragDropFilesEx);
  813. assert(FDDFileList);
  814. TRemoteFile * File;
  815. int FileIndex;
  816. for (int Index = 0; Index < DragDropFilesEx->FileList->Count; Index++)
  817. {
  818. FileIndex = FDDFileList->IndexOf(DragDropFilesEx->FileList->Items[Index]->Name);
  819. assert(FileIndex >= 0);
  820. File = dynamic_cast<TRemoteFile *>(FDDFileList->Objects[FileIndex]);
  821. assert(File);
  822. FileList->AddObject(File->FileName, File);
  823. }
  824. TCopyParamType CopyParams = Configuration->CopyParam;
  825. AnsiString TargetDir = "";
  826. bool UseTempDir;
  827. if (OnGetCopyParam)
  828. {
  829. OnGetCopyParam(this, tdToLocal, Type,
  830. TargetDir /* empty directory parameter means temp directory -> don't display it! */,
  831. FileList, CopyParams);
  832. }
  833. UseTempDir = TargetDir.IsEmpty();
  834. bool Continue = true;
  835. if (UseTempDir)
  836. {
  837. DoWarnLackOfTempSpace(TempDir, FDDTotalSize, Continue);
  838. TargetDir = TempDir;
  839. }
  840. if (Continue)
  841. {
  842. if (ForceDirectories(TargetDir))
  843. {
  844. assert(Terminal && !TargetDir.IsEmpty());
  845. try
  846. {
  847. Terminal->CopyToLocal(FileList, TargetDir, &CopyParams,
  848. (UseTempDir ? cpDragDrop : 0) | (Type == ttMove ? cpDelete : 0));
  849. if (!UseTempDir)
  850. {
  851. // abort drag&drop, files are already at their place
  852. Abort();
  853. }
  854. }
  855. __finally
  856. {
  857. if (UseTempDir)
  858. {
  859. AddDelayedDirectoryDeletion(TempDir, DDDeleteDelay);
  860. }
  861. }
  862. }
  863. else
  864. {
  865. DragDropDirException(TempDir);
  866. }
  867. }
  868. else
  869. {
  870. Abort();
  871. }
  872. }
  873. __finally
  874. {
  875. delete FileList;
  876. }
  877. }
  878. catch(ESshTerminate & E)
  879. {
  880. assert(!E.MoreMessages); // not supported
  881. assert(!E.Message.IsEmpty());
  882. FDragDropSshTerminate = E.Message;
  883. }
  884. #endif
  885. }
  886. //---------------------------------------------------------------------------
  887. void __fastcall TUnixDirView::SetDDAllowMove(bool value)
  888. {
  889. if (DDAllowMove != value)
  890. {
  891. assert(DragDropFilesEx);
  892. FDDAllowMove = value;
  893. DragDropFilesEx->SourceEffects = DragSourceEffects;
  894. }
  895. }
  896. //---------------------------------------------------------------------------
  897. TDropEffectSet __fastcall TUnixDirView::GetDragSourceEffects()
  898. {
  899. TDropEffectSet Result;
  900. Result << deCopy;
  901. if (DDAllowMove) Result << deMove;
  902. return Result;
  903. }
  904. //---------------------------------------------------------------------------
  905. void __fastcall TUnixDirView::ChangeDirectory(AnsiString Path)
  906. {
  907. AnsiString LastFile = "";
  908. if (ItemFocused) LastFile = ItemFileName(ItemFocused);
  909. ClearItems();
  910. DoAnimation(true);
  911. #ifndef DESIGN_ONLY
  912. try
  913. {
  914. FDirLoadedAfterChangeDir = false;
  915. if (Path == HOMEDIRECTORY)
  916. {
  917. Terminal->HomeDirectory();
  918. }
  919. else
  920. // this works even with LockInHome
  921. if (Path == ROOTDIRECTORY)
  922. {
  923. Terminal->CurrentDirectory = ROOTDIRECTORY;
  924. }
  925. else
  926. {
  927. Terminal->ChangeDirectory(Path);
  928. }
  929. }
  930. __finally
  931. {
  932. // changing directory failed, so we load again old directory
  933. if (!FDirLoadedAfterChangeDir)
  934. {
  935. FSelectFile = LastFile;
  936. Reload(false);
  937. };
  938. }
  939. #endif
  940. }
  941. //---------------------------------------------------------------------------
  942. bool __fastcall TUnixDirView::CanEdit(TListItem* Item)
  943. {
  944. #ifndef DESIGN_ONLY
  945. assert(Terminal);
  946. return TCustomUnixDirView::CanEdit(Item) && Terminal->IsCapable[fcRename];
  947. #else
  948. return false;
  949. #endif
  950. }
  951. //---------------------------------------------------------------------------
  952. void __fastcall TUnixDirView::InternalEdit(const tagLVITEMA & HItem)
  953. {
  954. #ifndef DESIGN_ONLY
  955. TListItem *Item = GetItemFromHItem(HItem);
  956. ASSERT_VALID_ITEM;
  957. FSelectFile = HItem.pszText;
  958. Terminal->RenameFile(ITEMFILE, HItem.pszText, true);
  959. #endif
  960. }
  961. //---------------------------------------------------------------------------
  962. void __fastcall TUnixDirView::CreateDirectory(AnsiString DirName)
  963. {
  964. #ifndef DESIGN_ONLY
  965. assert(Terminal);
  966. // if file would be created in current directory, select it after reload
  967. if (UnixExtractFileName(DirName) == DirName)
  968. {
  969. FSelectFile = DirName;
  970. }
  971. Terminal->CreateDirectory(DirName);
  972. #endif
  973. }
  974. //---------------------------------------------------------------------------
  975. AnsiString __fastcall TUnixDirView::MinimizePath(AnsiString Path, int Length)
  976. {
  977. return StringReplace(MinimizeName(
  978. StringReplace(Path, '/', '\\', TReplaceFlags() << rfReplaceAll),
  979. Canvas, Length), '\\', '/', TReplaceFlags() << rfReplaceAll);
  980. }
  981. //---------------------------------------------------------------------------
  982. bool __fastcall TUnixDirView::GetIsRoot()
  983. {
  984. #ifndef DESIGN_ONLY
  985. return (PathName == ROOTDIRECTORY);
  986. #else
  987. return false;
  988. #endif
  989. }
  990. //---------------------------------------------------------------------------
  991. TColor __fastcall TUnixDirView::ItemColor(TListItem * Item)
  992. {
  993. assert(Item);
  994. #ifndef DESIGN_ONLY
  995. if (DimmHiddenFiles && !Item->Selected && ITEMFILE->IsHidden)
  996. {
  997. return clGrayText;
  998. }
  999. else
  1000. #endif
  1001. {
  1002. return (TColor)clDefaultItemColor;
  1003. }
  1004. }
  1005. //---------------------------------------------------------------------------
  1006. TDateTime __fastcall TUnixDirView::ItemFileTime(TListItem * Item)
  1007. {
  1008. assert(Item);
  1009. #ifndef DESIGN_ONLY
  1010. return ITEMFILE->Modification;
  1011. #else
  1012. return Now();
  1013. #endif
  1014. }
  1015. //---------------------------------------------------------------------------
  1016. void __fastcall TUnixDirView::SetShowInaccesibleDirectories(bool value)
  1017. {
  1018. if (FShowInaccesibleDirectories != value)
  1019. {
  1020. FShowInaccesibleDirectories = value;
  1021. if (DirOK) Reload(false);
  1022. }
  1023. }
  1024. //---------------------------------------------------------------------------
  1025. void __fastcall TUnixDirView::DoWarnLackOfTempSpace(const AnsiString Path,
  1026. __int64 RequiredSpace, bool & Continue)
  1027. {
  1028. if (FOnWarnLackOfTempSpace)
  1029. {
  1030. FOnWarnLackOfTempSpace(this, Path, RequiredSpace, Continue);
  1031. }
  1032. }
  1033. //---------------------------------------------------------------------------
  1034. void __fastcall TUnixDirView::AddToDragFileList(TFileList* FileList, TListItem* Item)
  1035. {
  1036. #ifndef DESIGN_ONLY
  1037. if (FileList->Count == 0) FDDTotalSize = 0;
  1038. if (FDDTotalSize >= 0)
  1039. {
  1040. if (ItemIsDirectory(Item))
  1041. {
  1042. FDDTotalSize = -1;
  1043. }
  1044. else
  1045. {
  1046. FDDTotalSize += ItemFileSize(Item);
  1047. }
  1048. }
  1049. FDDFileList->AddObject(ItemDragFileName(Item), ITEMFILE);
  1050. TCustomUnixDirView::AddToDragFileList(FileList, Item);
  1051. #endif
  1052. }