diff --git a/src/FileSystemView.cpp b/src/FileSystemView.cpp --- a/src/FileSystemView.cpp +++ b/src/FileSystemView.cpp @@ -1,1451 +1,1452 @@ #include "FtpApp.h" #include "lgi/common/Edit.h" #include "lgi/common/Combo.h" #include "lgi/common/Button.h" #include "lgi/common/Token.h" #include "lgi/common/ClipBoard.h" #include "lgi/common/ToolBar.h" #include "lgi/common/Menu.h" //////////////////////////////////////////////////////////////////////// CreateFolderDlg::CreateFolderDlg(LViewI *parent) { SetParent(parent); if (LoadFromResource(IDD_CREATE_FOLDER)) { MoveSameScreen(parent); LViewI *v; if (GetViewById(IDC_NAME, v)) v->Focus(true); LButton *b; if (GetViewById(IDC_CREATE_ENTER, b)) SetDefault(b); } } int CreateFolderDlg::OnNotify(LViewI *Ctrl, LNotification n) { switch (Ctrl->GetId()) { case IDC_CREATE_ENTER: case IDC_CREATE: case IDCANCEL: Name = GetCtrlName(IDC_NAME); EndModal(Ctrl->GetId()); break; } return 0; } //////////////////////////////////////////////////////////////////////// LFileSystemView::LFileSystemView(AppWnd *wnd, LImageList *ImageList, bool Local) { LocalView = Local; Wnd = wnd; Opposite = 0; Listing = true; Commands = NULL; Lst = 0; Dir = 0; Edit = 0; Lst = 0; SortCol = -1; SortAscend = true; Mount = 0; #ifdef WIN32 WndFlags |= WS_CLIPCHILDREN; #endif LRect r(0, 0, 100, 120); SetPos(r); int EditY = LSysFont->GetHeight() + 8; Children.Insert(Edit = new LEdit(M_FS_DIR, 0, 0, 100, EditY, "")); Children.Insert(Lst = new FtpList(wnd, M_FS_LIST, 0, EditY, 100, 100)); if (Lst) { Lst->View = this; Lst->Sunken(true); Lst->AddColumn(LLoadString(IDS_NAME), 240); Lst->AddColumn(LLoadString(IDS_TYPE), 60); Lst->AddColumn(LLoadString(IDS_SIZE), 70); Lst->AddColumn(LLoadString(IDS_DATE), 140); Lst->SetImageList(ImageList, false); } } LFileSystemView::~LFileSystemView() { // Delete this first as it points to the 'Entries' objects Lst->Empty(); // Delete all the entries... Entries.DeleteObjects(); } bool LFileSystemView::SetEntries(LArray a, bool Update) { if (Update) { // Set up map of existing entries... LHashTbl, IFtpEntry*> Map; for (auto i: Entries) { DirListItem *li = (DirListItem*)i->UserData; i->Deleted = false; i->Added = false; i->Updated = false; i->Unchanged = false; i->Selected = li ? li->Select() : false; Map.Add(i->Name, i); } // Scan input and matching against existing entries... for (unsigned idx=0; idxName); if (existing) { if ((existing->Size != i->Size) || (existing->Date != i->Date)) { existing->Size = i->Size; existing->Date = i->Date; existing->Updated = true; } else { existing->Unchanged = true; } Map.Delete(existing->Name); } else { // New item... Entries.Add(i); i->Added = true; i->Deleted = false; i->Updated = false; i->Unchanged = false; i->Selected = false; // Remove from CmdEntries a.DeleteAt(idx--); // reordering ok I guess? } } // Now remove missing existing entries... for (auto i: Map) { // These are deleted DirListItem *li = (DirListItem*)i.value->UserData; if (li) li->SetEntry(); Entries.Delete(i.value); DeleteObj(i.value); } a.DeleteObjects(); } else { if (Lst) Lst->Empty(); Entries.DeleteObjects(); Entries = a; for (auto i: Entries) { i->Deleted = false; i->Added = true; i->Updated = false; i->Unchanged = false; i->Selected = false; } } if (Lst) { // Update the UI UpdateList(); } return true; } bool LFileSystemView::UpdateList() { if (!Lst) return Wnd->OnError("No list (%s:%i).", _FL); bool ShowHidden = Wnd->ShowHiddenFiles(); // Get all current list items List All; List Ins; LArray Updated; if (Lst->GetAll(All)) { for (auto li: All) { IFtpEntry *e = li->GetEntry(); if (!e || !e->Name || e->Deleted) { // This can happen when someone deletes a local file... // The DirListItem is left with a NULL ptr to it's entry... // Just needs to be deleted. DeleteObj(li); } } } // Iterate over entries for (unsigned i=0; iUpdated) Updated.Add(e); DirListItem *li = (DirListItem*) e->UserData; // Check the filter... bool bVisible = true; if (Filter) bVisible = e->Name && stristr(e->Name, Filter) != 0; // Check the show hidden setting... if (e->IsHidden() && !ShowHidden) bVisible = false; if (bVisible) { if (li) { if (e->Updated) { li->Update(); e->Updated = false; } } else { // Add new item for insertion... Ins.Insert(new DirListItem(e, this)); } } else if (li) { li->SetEntry(); DeleteObj(li); } } // Add new items... Lst->Insert(Ins); // Sort the list items Lst->Sort(FtpItemCompare, (NativeInt)this); // Resize columns LVariant Resize = 0; if (Wnd->GetOptions()->GetValue(OPT_ResizeToContent, Resize) && Resize.CastInt32()) { Lst->ResizeColumnsToContent(); } Lst->Invalidate(); char p[MAX_PATH_LEN]; for (auto e: Updated) { LMakePath(p, sizeof(p), CurFolder, e->Name); Wnd->OnChange(IsLocal(), e->IsDir(), p, 0); } return true; } DirListItem *LFileSystemView::GetItem(char *Dir, char *Name) { // Check the folder hasn't changed.. LString Cwd = GetDir(); if (!Cwd.Equals(Dir)) { LgiTrace("%s:%i - Folder has changed from '%s' to '%s'\n", _FL, Dir, Cwd.Get()); return NULL; } // Update the UI with the new filename... List a; if (Lst->GetAll(a)) { // Find the old name in the list... for (auto i: a) { if (i->GetEntry() && i->GetEntry()->Name.Equals(Name)) { return i; } } } return NULL; } LMessage::Result LFileSystemView::OnEvent(LMessage *Msg) { switch (Msg->Msg()) { case M_FTPCMD_PROCESS: { LAutoPtr Cmd((FtpCmd*)Msg->A()); if (Cmd) { // auto Status = Msg->B(); switch (Cmd->Cmd) { case TASK_List: { if (Cmd->Str.Length()) Cd(Cmd->Str[LIST_REMOTE_PATH]); else RefreshList(); break; } case TASK_Folder: { const char *Path = Cmd->Str[FOLDER_PATH]; if (Cmd->Int[FOLDER_CREATE]) { if (!LDirExists(Path)) FileDev->CreateFolder(Path); } Cd(Path); break; } default: break; } } break; } case M_FTPCMD_RESPONSE: { LAutoPtr Cmd((FtpCmd*)Msg->A()); if (Cmd) { auto Status = Msg->B(); switch (Cmd->Cmd) { case TASK_ParentFolder: case TASK_List: { if (!Status) break; // Copy all the entry pointers to the local store... SetEntries(Cmd->SwapEntries(), false); // Set the current working directory. if (Cmd->Str.Length()> 0) { CurFolder = Cmd->Str[LIST_REMOTE_PATH]; Edit->Name(CurFolder); } break; } case TASK_Download: { // Only refresh local folder (it's next to free). // Uploads rely on putting a list command in the "OnSuccess" handler // of the command. if (IsLocal()) RefreshList(); break; } case TASK_Rename: { // Change the name of the list entry... DirListItem *i = GetItem( Cmd->Str[RENAME_DIR], Cmd->Str[RENAME_OLD]); if (i) { i->GetEntry()->Name = Cmd->Str[RENAME_NEW]; i->Update(); } break; } case TASK_Delete: { // Remove the old item from the list... if (Status) { DirListItem *i = GetItem( Cmd->Str[DELETE_DIR], Cmd->Str[DELETE_NAME]); if (i) { IFtpEntry *e = i->GetEntry(); Entries.Delete(e); DeleteObj(i); delete e; } } break; } /* I'm going to move this to the OnSuccess handler, This breaks the create folder and enter functionality: i.e. Request: Create "./aaa" Request: List "./aaa" Response: Create -> List "." Doesn't leave you in the new child folder. case TASK_CreateFolder: { RefreshList(); break; } */ default: break; } } break; } case M_ENABLE_CMDS: { EnableCommands(Msg->A() != 0); break; } } return LLayout::OnEvent(Msg); } bool LFileSystemView::PostCmd(LAutoPtr Cmd, LEventSinkI *Sink) { if (!Cmd) return false; if (!Cmd->IsValid()) { LAssert(!"Invalid cmd."); return false; } if (!Sink) Sink = Wnd->GetWorker(); if (Sink) return Sink->PostEvent(M_FTPCMD_PROCESS, (LMessage::Param)Cmd.Release()); // Else we aren't connected to a server currently... just ignore.. return false; } bool LFileSystemView::GetMap(EntryMap &Map) { for (auto &e : Entries) { Map.Add(e->Name, e); } return true; } void LFileSystemView::LItemMap::Create(LList *lst) { Empty(); if (lst) { List a; lst->GetAll(a); for (auto i: a) { Add(i->GetEntry()->Name, i); } } } void LFileSystemView::LEntryMap::Create(LArray *lst) { Empty(); if (lst) { for (auto &i : (*lst)) { Add(i->Name, i); } } } int FtpItemCompare(LListItem *a, LListItem *b, NativeInt Data) { DirListItem *A = (DirListItem*) a->_UserPtr; DirListItem *B = (DirListItem*) b->_UserPtr; LFileSystemView *View = (LFileSystemView*)Data; int Col = View->SortCol; int Status = 0; if (A && B) { NameCompare: switch (Col) { case -1: { if (A->GetEntry()->IsDir() && !B->GetEntry()->IsDir()) { return -1; } if (!A->GetEntry()->IsDir() && B->GetEntry()->IsDir()) { return 1; } return Stricmp(A->GetText(0), B->GetText(0)); break; } case 0: case 1: { Status = Stricmp(A->GetText(Col), B->GetText(Col)); break; } case 2: { int64 Diff = A->GetEntry()->Size - B->GetEntry()->Size; if (Diff > 0) Status = 1; else if (Diff < 0) Status = -1; else Status = 0; break; } case 3: { Status = A->GetEntry()->Date.Compare(&B->GetEntry()->Date); break; } default: { LAssert(0); break; } } if (Status == 0 && Col > 0) { Col = 0; goto NameCompare; } } return View->SortAscend ? Status : -Status; } void LFileSystemView::OnColumnClick(int Col, LMouse &m) { if (SortCol < 0) { SortCol = Col; SortAscend = true; } else if (Col == SortCol) { if (Col <= 0) { if (SortAscend) { SortAscend = false; } else if (!SortAscend) { SortCol = -1; SortAscend = true; } } else { SortAscend = !SortAscend; } } else { SortCol = Col; SortAscend = true; } Lst->Sort(FtpItemCompare, (NativeInt)this); for (int i=0; iGetColumns(); i++) { if (i == SortCol) { Lst->ColumnAt(i)->Mark(SortAscend ? GLI_MARK_DOWN_ARROW : GLI_MARK_UP_ARROW); } else { Lst->ColumnAt(i)->Mark(GLI_MARK_NONE); } } } bool LFileSystemView::Attach(LViewI *p) { bool Status = LView::Attach(p); if (Status) { Commands = LgiLoadToolbar(this, "_pane.png"); if (Commands) { Commands->SetId(IDC_FILES_TOOLBAR); Commands->Attach(this); Commands->Raised(false); Commands->TextLabels(true); Commands->GetCss(true)->BackgroundColor(LCss::ColorInherit); CmdCreateDir.ToolButton = Commands->AppendButton(LLoadString(IDS_CREATE_DIR), IDM_CREATE_DIR, TBT_PUSH, true, 0); CmdDelete.ToolButton = Commands->AppendButton(LLoadString(IDS_DELETE), IDM_DELETE, TBT_PUSH, true, 1); CmdRenameFile.ToolButton = Commands->AppendButton(LLoadString(IDS_RENAME), IDM_RENAME, TBT_PUSH, true, 2); CmdSetPerms.ToolButton = Commands->AppendButton(LLoadString(IDS_PERMS), IDM_SETPERMS, TBT_PUSH, true, 3); if (LocalView) { CmdExecute.ToolButton = Commands->AppendButton(LLoadString(IDS_EXECUTE_FILE), IDM_EXECUTE, TBT_PUSH, true, 4); CmdViewText.ToolButton = Commands->AppendButton(LLoadString(IDS_VIEW_TEXT), IDM_VIEW_TEXT, TBT_PUSH, true, 5); } Commands->AppendSeparator(); CmdTransfer.ToolButton = Commands->AppendButton(LLoadString(IDS_TRANSFER), IDM_UPLOAD, TBT_PUSH, true, 6); Commands->AppendSeparator(); CmdRefresh.ToolButton = Commands->AppendButton(LLoadString(IDS_LIST), IDM_LIST, TBT_PUSH, true, 7); CmdCdup.ToolButton = Commands->AppendButton(LLoadString(IDS_CDUP), IDM_UP, TBT_PUSH, true, 8); Commands->Customizable(Wnd->GetOptions(), IsLocal()?(char*)"LocalTools":(char*)"RemoteTools"); } AttachChildren(); } return Status; } void LFileSystemView::OnPosChange() { LRect c = GetClient(); LRegion r(c); if (Commands) { Commands->Pour(r); r.Subtract(&Commands->GetPos()); } int EditY = LSysFont->GetHeight() + 8; LRect *Rgn = FindLargest(r); if (Rgn) { LRect e(Rgn->x1, Rgn->y1, Rgn->x2, Rgn->y1 + EditY - 1); if (Mount) { LRect m = e; e.x1 += Mount->X(); m.x2 = e.x1 - 1; Mount->SetPos(m); r.Subtract(&m); } if (Dir) { LRect d = e; e.x2 -= Dir->X(); d.x1 = e.x2 + 1; Dir->SetPos(d); r.Subtract(&d); } if (Edit) { Edit->SetPos(e); r.Subtract(&e); } } Rgn = FindLargest(r); if (Rgn && Lst) { Lst->SetPos(*Rgn); r.Subtract(Rgn); } } void LFileSystemView::OnPaint(LSurface *pDC) { LRect a = GetPos(); a.Offset(-a.x1, -a.y1); LRegion r(a); for (auto c: Children) { r.Subtract(&c->GetPos()); } pDC->Colour(L_MED); for (LRect *b = r.First(); b; b = r.Next()) { pDC->Rectangle(b); } } void LFileSystemView::GetMenuCommands(IFtpEntry *e, LSubMenu *RClick) { if (!RClick) return; RClick->AppendItem(LLoadString(IDS_COPY_PATH), IDM_COPY_PATH, true); RClick->AppendItem("Copy", IDM_COPY, true); RClick->AppendItem("Paste", IDM_PASTE, Clip.Length() > 0); RClick->AppendItem(LLoadString(IDS_BROWSE), IDM_BROWSE, IsLocal()); RClick->AppendSeparator(); RClick->AppendItem(LLoadString(IDS_CHANGE_DIR), IDM_CD, e->IsDir() || TestFlag(e->Attributes, IFTP_SYM_LINK)); RClick->AppendItem(LLoadString(IDS_TRANSFER), IDM_TRANSFER, true); RClick->AppendItem(LLoadString(IDS_TRANSFER_MASK), IDM_TRANSFER_MASK, true); } void LFileSystemView::OnMenuCommand(IFtpEntry *e, int Cmd) { LString Mask; switch (Cmd) { case IDM_COPY: { Clip.Length(0); List Sel; if (Lst->GetSelection(Sel)) { char p[MAX_PATH_LEN]; const char *Dir = Edit->Name(); for (auto i: Sel) { if (Dir && _stricmp(Dir, "/")) sprintf_s(p, sizeof(p), "%s/%s", Dir, i->GetEntry()->Name.Get()); else sprintf_s(p, sizeof(p), "%s", i->GetEntry()->Name.Get()); Clip.New().Reset(NewStr(p)); } } break; } case IDM_PASTE: { char p[MAX_PATH_LEN]; const char *Dir = Edit->Name(); if (e->IsDir()) { // Paste into folder... if (IsLocal()) { LMakePath(p, sizeof(p), Dir, e->Name); } else { if (Dir && _stricmp(Dir, "/")) sprintf_s(p, sizeof(p), "%s/%s", Dir, e->Name.Get()); else sprintf_s(p, sizeof(p), "%s", e->Name.Get()); } } else { // Paste in current folder.. strcpy_s(p, sizeof(p), Dir); } for (int i=0; iMove(Src, Dst); } else { char *Leaf = strrchr(Src, '/'); sprintf_s(Dst, sizeof(Dst), "%s/%s", p, Leaf ? Leaf + 1 : Src); /* FIXME FtpCmd *Cmd = new FtpCmd(p); if (Cmd) { Cmd->Cmd = TASK_Rename; Cmd->View = this; strcpy_s(Cmd->Arg, sizeof(Cmd->Arg), Src); strcpy_s(Cmd->Arg2, sizeof(Cmd->Arg2), Dst); PostCmd(Cmd); } */ } } break; } case IDM_COPY_PATH: { if (!Edit || !e) break; LClipBoard Clip(this); char p[MAX_PATH_LEN]; if (IsLocal()) { LMakePath(p, sizeof(p), Edit->Name(), e->Name); Clip.Text(p); } else { /* FIXME LAutoString Host; int Port = 0; Wnd->GetFtp()->GetHost(&Host, &Port); GUri u; u.Protocol = NewStr("ftp"); sprintf_s(p, sizeof(p), "%s/%s", Edit->Name(), e->Name.Get()); u.Path = NewStr(p); u.Host = Host.Release(); u.Port = Port == FTP_PORT ? 0 : Port; LAutoString Uri = u.GetUri(); Clip.Text(Uri); */ } break; } case IDM_BROWSE: { if (!Edit || !e) break; char p[MAX_PATH_LEN]; LMakePath(p, sizeof(p), Edit->Name(), e->Name); LBrowseToFile(p); break; } case IDM_CD: { if (!Edit || !e) break; char p[MAX_PATH_LEN]; LMakePath(p, sizeof(p), Edit->Name(), e->Name); /* FIXME FtpCmd *Cmd = new FtpCmd(p); if (Cmd) { Cmd->Cmd = TASK_Cd; Cmd->Entry.Reset(new IFtpEntry(e)); Cmd->View = this; PostCmd(Cmd); } */ break; } case IDM_TRANSFER_MASK: { auto Dlg = new LInput(this, "", LLoadString(IDS_ENTER_MASKS), AppName); Dlg->DoModal([this, Dlg](auto dlg, auto code) { if (code == IDOK) { // Set mask and do transfer // Mask = Dlg->GetStr(); } delete dlg; }); break; } case IDM_TRANSFER: { List Sel; if (GetSelection(Sel) > 0) { /* FIXME FtpCmd *Cmd = 0; for (IFtpEntry *e = Sel.First(); e; e = Sel.Next()) { Cmd = new FtpCmd(Mask); if (Cmd) { Cmd->Int = true; Cmd->Cmd = TASK_Transfer; Cmd->Entry.Reset(new IFtpEntry(e)); Cmd->View = this; LAutoString a = (IsLocal() ? this : Opposite)->GetDir(); if (a) strcpy_s(Cmd->Arg2, sizeof(Cmd->Arg2), a); PostCmd(Cmd); } } Cmd = new FtpCmd; if (Cmd) { Cmd->Cmd = TASK_ListElements; Cmd->View = Opposite; Cmd->ForceRemote = !IsCmdLocal(TASK_ListElements); PostCmd(Cmd); } */ } break; } } } void LFileSystemView::OnClick(IFtpEntry *e, LMouse *m) { if (e && m->IsContextMenu()) { LSubMenu RClick; GetMenuCommands(e, &RClick); if (GetMouse(*m, true)) { int Cmd = RClick.Float(this, m->x, m->y, false); if (Cmd) { OnMenuCommand(e, Cmd); } } } ProcessClick(e, m, NULL); } void LFileSystemView::OnRename() { List Sel; if (Lst && Lst->GetSelection(Sel) && Sel.Length() == 1) { LListItem *i = Sel[0]; if (i) i->EditLabel(0); } } int LFileSystemView::OnNotify(LViewI *Ctrl, LNotification n) { switch (Ctrl->GetId()) { case IDC_FILES_TOOLBAR: { if (n.Type == LNotifyTableLayoutRefresh) OnPosChange(); break; } case IDC_DIR: { if (Edit) { LExecute(Edit->Name(), "", ""); } break; } case IDM_LIST: { RefreshList(); break; } case M_FS_DIR: { if (Edit && n.Type == LNotifyReturnKey) { const char *Path = Edit->Name(); if (Path) Cd(Path); } break; } case IDM_UPLOAD: { List Sel; if (GetSelection(Sel) > 0) { LString::Array Files; for (auto e: Sel) { Files.New() = e->Name; } Transfer(Files, 0); } break; } case IDM_UP: { Cd(); break; } case IDM_CREATE_DIR: { auto Inp = new CreateFolderDlg(this); Inp->DoModal([this, Inp](auto dlg, auto Cmd) { switch (Cmd) { case IDC_CREATE_ENTER: case IDC_CREATE: { if (CreateDir(Inp->Name)) { if (Cmd == IDC_CREATE_ENTER) { LString s = GetDir(Inp->Name); Cd(s); } else { RefreshList(); } } break; } } delete dlg; }); break; } case IDM_RENAME: { OnRename(); break; } case IDM_DELETE: { List Sel; if (GetSelection(Sel) > 0) { for (auto e: Sel) { Delete(e); } } UpdateList(); break; } case IDM_EXECUTE: { List Sel; if (GetSelection(Sel) > 0) { for (auto e: Sel) { if (e->IsDir()) { LExecute(e->Path); } else { ExecuteFile(e->Name); } } } break; } case IDM_VIEW_TEXT: { List Sel; if (GetSelection(Sel) > 0) { for (auto e: Sel) { if (!e->IsDir()) ViewTextFile(e->Path); } } break; } case IDM_SETPERMS: { - List Sel; - if (GetSelection(Sel) > 0) + List *Sel = new List; + if (GetSelection(*Sel) > 0) { #ifdef WIN32 bool Win32 = IsCmdLocal(IDM_SETPERMS); #else bool Win32 = false; #endif int64 Attributes[32] = {0}; int Flags = Win32 ? 6 : 12; - for (auto e: Sel) + for (auto e: *Sel) { for (int i=0; iPerms.u32 & f) Attributes[i]++; } } for (int i=0; i 0) { - if (Attributes[i] < (int64)Sel.Length()) + if (Attributes[i] < (int64)Sel->Length()) Attributes[i] = 2; else Attributes[i] = 1; } } - IFtpEntry *First = Sel[0]; - auto Dlg = new PermsDlg(this, Win32, Sel.Length() > 1, Attributes, First->User, First->Group); + IFtpEntry *First = (*Sel)[0]; + auto Dlg = new PermsDlg(this, Win32, Sel->Length() > 1, Attributes, First->User, First->Group); Dlg->DoModal([this,Dlg,Sel](auto dlg, auto code) { if (code == IDOK) { auto p = Dlg->GetPerms(); - for (unsigned i=0; iLength(); i++) + SetPerms((*Sel)[i], p); } + delete Sel; delete dlg; }); } break; } } return 0; } int LFileSystemView::GetSelection(List &Sel) { int Status = 0; if (Lst) { List Ls; if (Lst && Lst->GetSelection(Ls)) { for (auto item: Ls) { auto i = dynamic_cast(item); if (i->GetEntry()) { Sel.Insert(i->GetEntry()); Status++; } } } } return Status; } bool LFileSystemView::SetEdit(const char *Path) { return Edit ? Edit->Name(Path) : false; } LString LFileSystemView::GetDir(char *Append) { LString p; if (Edit) p = Edit->Name(); if (Append) { if (!strchr("/\\", p(-1))) p += !LocalView ? "/" : DIR_STR; p += Append; } return p; } void LFileSystemView::EnableViews(bool Enabled) { if (Lst) Lst->Enabled(Enabled); if (Edit) Edit->Enabled(Enabled); } IFtpEntry *LFileSystemView::HasDir(char *Name) { DirListItem *e = HasEntry(Name); if (e && e->GetEntry()->IsDir()) { return e->GetEntry(); } return 0; } DirListItem *LFileSystemView::HasEntry(char *Name) { if (Lst && Name) { List All; Lst->GetAll(All); for (auto i: All) { if (i->GetEntry() && i->GetEntry()->Name && stricmp(i->GetEntry()->Name, Name) == 0) { return i; } } } return 0; } bool LFileSystemView::TransferFilePattern(LString Pattern) { if (!Pattern) return false; LString::Array Files; List All; Lst->GetAll(All); for (auto i: All) { if (!i->GetEntry()->IsDir() && MatchStr(Pattern, i->GetEntry()->Name)) { Files.New() = i->GetEntry()->Name; } } return Transfer(Files, 0); } bool LFileSystemView::TransferDir(IFtpEntry *e, char *Mask) { bool Status = false; if (Lst && e && e->IsDir()) { LString OppPath = Opposite->GetDir(e->Name); IFtpEntry *d = Opposite->HasDir(e->Name); if (d) { // change to Status = Opposite->Cd(d->Path); } else { // create if ((Status = Opposite->CreateDir(e->Name))) { Status = Opposite->Cd(OppPath); if (!Status) { LgiTrace("%s:%i - Cd(%s) failed.\n", __FILE__, __LINE__, OppPath.Get()); } } else { LgiTrace("%s:%i - CreateDir(%s) failed.\n", __FILE__, __LINE__, e->Name.Get()); } } if (Status && (Status = Cd(e->Path))) { LToken T(Mask, " "); // For all items in directory List Local; { // copy all the items in the current directory into a temp // list, so that as we traverse the tree we don't lose items // in the list. List All; Lst->GetAll(All); for (auto i: All) { IFtpEntry *e = i->GetEntry(); if (e && e->Name && stricmp(e->Name, "..") != 0) { Local.Insert(new IFtpEntry(i->GetEntry())); } } } { // iterate the saved dir listing and process each item in turn for (IFtpEntry *i = Local[0]; Status && i; i = Local[0]) { if (i->IsDir()) { // Dir if (stricmp(i->Name, "..") != 0) { Status &= TransferDir(i, Mask); } } else { // File bool Transfer = Mask == 0; if (Mask) { for (int n=0; nName)) { Transfer = true; break; } } } if (Transfer) { /* FIXME if (IsCmdLocal(TASK_ListElements)) { // upload LString Path = GetDir(i->Name); Status &= Wnd->GetFtp()->UploadFile(Path, i->Name, Wnd->GetBinaryMode(i->Name)); // destination is remote, we can't waste time/bandwidth // updating the UI as we go... } else { // download LString Path = Opposite->GetDir(i->Name); Status &= Wnd->GetFtp()->DownloadFile(Path, i, Wnd->GetBinaryMode(i->Name)); // we can list the local contents as we go as the command // is local Opposite->ListElements(); } */ } } Local.Delete(i); DeleteObj(i); } } if (Status) { Status &= Cd(); Status &= Opposite->Cd(); } } } return Status; } bool LFileSystemView::DeleteDir(IFtpEntry *e) { bool Status = false; if (Lst && e && e->IsDir()) { if (IsLocal()) { Status = FileDev->RemoveFolder(e->Path, true); } else { // Save all current items... List Init; Lst->GetAll(Init); Lst->RemoveAll(); // Change to dir... if ((Status = Cd(e->Path))) { // For all items in directory List Local; Lst->GetAll(Local); Lst->RemoveAll(); for (auto i: Local) { if (i->GetEntry()) { char *n = i->GetEntry()->Name; if (stricmp(n, "..") != 0) { if (i->GetEntry()->IsDir()) { // Dir Status &= DeleteDir(i->GetEntry()); } else { // File Status &= Delete(i->GetEntry()); } } } Local.Delete(i); DeleteObj(i); } Status &= Cd(0, false); Status &= Delete(e); } // ReLoad all current items. for (auto i: Init) { if (i->GetEntry()->Path && strcmp(i->GetEntry()->Path, e->Path) == 0) { DeleteObj(i); } else { Lst->Insert(i); } } } } return Status; } diff --git a/src/PermsDlg.cpp b/src/PermsDlg.cpp --- a/src/PermsDlg.cpp +++ b/src/PermsDlg.cpp @@ -1,116 +1,116 @@ #include "lgi/common/Lgi.h" #include "lgi/common/CheckBox.h" #include "FtpApp.h" PermsDlg::PermsDlg( LViewI *parent, bool win32, int Three, int64 *Init, char *User, char *Group) { InitFlags = Init; Win32 = win32; SetParent(parent); ZeroObj(Chk); Ctrls = 0; if (Win32) { if (LoadFromResource(IDD_WIN32_PERMS)) { int Ids[] = { IDC_READ_ONLY, IDC_HIDDEN, IDC_SYSTEM, -1, -1/*folder*/, IDC_ARCHIVE }; Ctrls = CountOf(Ids); memcpy(CtrlId, Ids, sizeof(Ids)); } } else { if (LoadFromResource(IDD_UNIX_PERMS)) { int Ids[] = { IDC_GLOBAL_EX, IDC_GLOBAL_WR, IDC_GLOBAL_RD, -1, - IDC_GROUP_EX, IDC_GROUP_WR, IDC_GROUP_RD, -1, - IDC_OWNER_EX, IDC_OWNER_WR, IDC_OWNER_RD, + IDC_GROUP_EX, IDC_GROUP_WR, IDC_GROUP_RD, -1, + IDC_OWNER_EX, IDC_OWNER_WR, IDC_OWNER_RD, }; Ctrls = CountOf(Ids); memcpy(CtrlId, Ids, sizeof(Ids)); } /* for (int i=0; i(FindControl(Ctrl[i])); if (Chk[i]) { Chk[i]->ThreeState(Three != 0); Chk[i]->Value(Init[i]); } } if (Three) { SetCtrlName(IDC_USER, "..."); SetCtrlName(IDC_GROUP, "..."); } else { SetCtrlName(IDC_USER, User); SetCtrlName(IDC_GROUP, Group); } } */ } for (int i=0; i 0 && GetViewById(CtrlId[i], Chk[i])) { Chk[i]->ThreeState(Three != 0); Chk[i]->Value(Init[i]); } } MoveToCenter(); } LPermissions PermsDlg::GetPerms() { LPermissions p; p.IsWindows = Win32; p.u32 = 0; for (int i=0; iValue() != 0) p.u32 |= f; } return p; } int PermsDlg::OnNotify(LViewI *Ctrl, LNotification n) { switch (Ctrl->GetId()) { case IDOK: { for (int i=0; iValue(); } // fall thru } case IDCANCEL: { EndModal(Ctrl->GetId()); break; } } return 0; }