| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104 | //---------------------------------------------------------------------#include <vcl.h>#pragma hdrstop#include <CoreMain.h>#include <Configuration.h>#include <RemoteFiles.h>#include <VCLCommon.h>#include <TextsWin.h>#include <HelpWin.h>#include <Common.h>#include "LocationProfiles.h"#include "WinConfiguration.h"#include "Custom.h"#include <Math.hpp>#include <GUITools.h>//---------------------------------------------------------------------#pragma link "HistoryComboBox"#pragma link "PngImageList"#pragma resource "*.dfm"//---------------------------------------------------------------------bool __fastcall LocationProfilesDialog(TOpenDirectoryMode Mode,  TOperationSide Side, UnicodeString & LocalDirectory, UnicodeString & RemoteDirectory,  TStrings * LocalDirectories, TStrings * RemoteDirectories, TTerminal * Terminal){  bool Result;  TLocationProfilesDialog * Dialog = new TLocationProfilesDialog(Application);  try  {    Dialog->LocalDirectory = LocalDirectory;    Dialog->RemoteDirectory = RemoteDirectory;    Dialog->OperationSide = Side;    Dialog->Terminal = Terminal;    Dialog->RemoteDirectories = RemoteDirectories;    Dialog->LocalDirectories = LocalDirectories;    Dialog->Mode = Mode;    Result = Dialog->Execute();    if (Result)    {      LocalDirectory = Dialog->LocalDirectory;      RemoteDirectory = Dialog->RemoteDirectory;    }  }  __finally  {    delete Dialog;  }  return Result;}//---------------------------------------------------------------------------//---------------------------------------------------------------------------void __fastcall BookmarkNameValidateName(const UnicodeString Name){  if (Name.IsEmpty() || IsNumber(Name))  {    throw Exception(FMTLOAD(BOOKMARK_INVALID_NAME, (Name)));  }}//---------------------------------------------------------------------------void __fastcall BookmarkFolderValidateName(const UnicodeString Name,  bool AllowEmpty){  if ((!AllowEmpty && Name.IsEmpty()) || Name.Pos(L"\\"))  {    throw Exception(FMTLOAD(BOOKMARK_FOLDER_INVALID_NAME, (Name)));  }}//---------------------------------------------------------------------------//---------------------------------------------------------------------------class TBookmarkNameDialog : public TCustomDialog{public:  __fastcall TBookmarkNameDialog(TStrings * PeerBookmarks, bool AllowShared);  bool __fastcall Execute(UnicodeString & Name, bool & Shared);protected:  virtual void __fastcall DoValidate();private:  TComboBox * NameCombo;  TCheckBox * SharedCheck;};//---------------------------------------------------------------------__fastcall TBookmarkNameDialog::TBookmarkNameDialog(TStrings * PeerBookmarks,    bool AllowShared) :  TCustomDialog(HELP_LOCATION_PROFILE_ADD){  Caption = LoadStr(ADD_BOOKMARK_CAPTION);  NameCombo = new TComboBox(this);  NameCombo->AutoComplete = false;  NameCombo->DropDownCount = Max(NameCombo->DropDownCount, 16);  AddComboBox(NameCombo, CreateLabel(LoadStr(ADD_BOOKMARK_PROMPT)));  NameCombo->Items = PeerBookmarks;  if (AllowShared)  {    SharedCheck = new TCheckBox(this);    SharedCheck->Caption = LoadStr(ADD_BOOKMARK_SHARED);    AddButtonControl(SharedCheck);  }  else  {    SharedCheck = NULL;  }}//---------------------------------------------------------------------void __fastcall TBookmarkNameDialog::DoValidate(){  if (NameCombo->Text.IsEmpty() || IsNumber(NameCombo->Text))  {    throw Exception(FMTLOAD(BOOKMARK_INVALID_NAME, (NameCombo->Text)));  }  TCustomDialog::DoValidate();}//---------------------------------------------------------------------bool __fastcall TBookmarkNameDialog::Execute(UnicodeString & Name, bool & Shared){  NameCombo->Text = Name;  if (SharedCheck != NULL)  {    SharedCheck->Checked = Shared;  }  bool Result = TCustomDialog::Execute();  if (Result)  {    Name = NameCombo->Text;    if (SharedCheck != NULL)    {      Shared = SharedCheck->Checked;    }  }  return Result;}//---------------------------------------------------------------------------//---------------------------------------------------------------------------class TBookmarkFolderDialog : public TCustomDialog{public:  __fastcall TBookmarkFolderDialog(TStrings * Folders);  bool __fastcall Execute(UnicodeString & Name);protected:  virtual void __fastcall DoValidate();private:  TComboBox * NameCombo;};//---------------------------------------------------------------------__fastcall TBookmarkFolderDialog::TBookmarkFolderDialog(TStrings * Folders) :  TCustomDialog(HELP_LOCATION_PROFILE_MOVE){  Caption = LoadStr(MOVE_BOOKMARK_CAPTION);  NameCombo = new TComboBox(this);  NameCombo->AutoComplete = false;  AddComboBox(NameCombo, CreateLabel(LoadStr(MOVE_BOOKMARK_PROMPT)));  NameCombo->Items = Folders;}//---------------------------------------------------------------------void __fastcall TBookmarkFolderDialog::DoValidate(){  BookmarkFolderValidateName(NameCombo->Text, true);  TCustomDialog::DoValidate();}//---------------------------------------------------------------------bool __fastcall TBookmarkFolderDialog::Execute(UnicodeString & Name){  NameCombo->Text = Name;  bool Result = TCustomDialog::Execute();  if (Result)  {    Name = NameCombo->Text;  }  return Result;}//---------------------------------------------------------------------//---------------------------------------------------------------------__fastcall TLocationProfilesDialog::TLocationProfilesDialog(TComponent * AOwner):  TForm(AOwner){  FOperationSide = osLocal;  FBookmarkDragSource = NULL;  FTerminal = NULL;  FSessionBookmarkList = new TBookmarkList();  FSharedBookmarkList = new TBookmarkList();  FChanging = false;  FSessionFolders = CreateSortedStringList();  FSharedFolders = CreateSortedStringList();  FSessionScrollOnDragOver = new TTreeViewScrollOnDragOver(SessionProfilesView, true);  FSharedScrollOnDragOver = new TTreeViewScrollOnDragOver(SharedProfilesView, true);  UseSystemSettings(this);  SelectScaledImageList(BookmarkImageList);  LoadDialogImage(Image, L"Open folder");}//---------------------------------------------------------------------__fastcall TLocationProfilesDialog::~TLocationProfilesDialog(){  SAFE_DESTROY(FSharedScrollOnDragOver);  SAFE_DESTROY(FSessionScrollOnDragOver);  SAFE_DESTROY(FSharedBookmarkList);  SAFE_DESTROY(FSessionBookmarkList);  SAFE_DESTROY(FSharedFolders);  SAFE_DESTROY(FSessionFolders);}//---------------------------------------------------------------------------void __fastcall TLocationProfilesDialog::SetLocalDirectory(UnicodeString value){  if (LocalDirectory != value)  {    LocalDirectoryEdit->Text = value;    FindProfile();    UpdateControls();  }}//---------------------------------------------------------------------------UnicodeString __fastcall TLocationProfilesDialog::GetLocalDirectory(){  return ExcludeTrailingBackslash(LocalDirectoryEdit->Text);}//---------------------------------------------------------------------------void __fastcall TLocationProfilesDialog::SetRemoteDirectory(UnicodeString value){  if (RemoteDirectory != value)  {    RemoteDirectoryEdit->Text = value;    FindProfile();    UpdateControls();  }}//---------------------------------------------------------------------------UnicodeString __fastcall TLocationProfilesDialog::GetRemoteDirectory(){  return UnixExcludeTrailingBackslash(RemoteDirectoryEdit->Text);}//---------------------------------------------------------------------------void __fastcall TLocationProfilesDialog::SetRemoteDirectories(TStrings * value){  RemoteDirectoryEdit->Items = value;}//---------------------------------------------------------------------------TStrings * __fastcall TLocationProfilesDialog::GetRemoteDirectories(){  return RemoteDirectoryEdit->Items;}//---------------------------------------------------------------------------void __fastcall TLocationProfilesDialog::SetLocalDirectories(TStrings * value){  LocalDirectoryEdit->Items = value;}//---------------------------------------------------------------------------TStrings * __fastcall TLocationProfilesDialog::GetLocalDirectories(){  return LocalDirectoryEdit->Items;}//---------------------------------------------------------------------------bool __fastcall TLocationProfilesDialog::ProfileMatch(TTreeNode * Node){  bool Result = false;  if (Node->Data)  {    TBookmark * Bookmark = (TBookmark *)Node->Data;    Result =      (Bookmark->Local == LocalDirectory) &&      (Bookmark->Remote == RemoteDirectory);  }  return Result;}//---------------------------------------------------------------------------void __fastcall TLocationProfilesDialog::FindProfile(TTreeView * ProfilesView){  if ((ProfilesView->Selected == NULL) ||      !ProfileMatch(ProfilesView->Selected))  {    TTreeNode * Match = NULL;    for (int Index = 0; Index < ProfilesView->Items->Count; Index++)    {      TTreeNode * Node = ProfilesView->Items->Item[Index];      if (ProfileMatch(Node))      {        Match = Node;        break;      }    }    if (Match)    {      ProfilesView->Selected = Match;      Match->MakeVisible();    }    else    {      ProfilesView->Selected = NULL;    }  }}//---------------------------------------------------------------------------void __fastcall TLocationProfilesDialog::FindProfile(){  FindProfile(SessionProfilesView);  FindProfile(SharedProfilesView);}//---------------------------------------------------------------------------void __fastcall TLocationProfilesDialog::ControlChange(TObject * /*Sender*/){  UpdateControls();}//---------------------------------------------------------------------------void __fastcall TLocationProfilesDialog::UpdateProfilesControls(  TTreeView * ProfilesView,  TButton * AddBookmarkButton, TButton * RemoveBookmarkButton,  TButton * RenameBookmarkButton,  TButton * BookmarkMoveToButton,  TButton * ShortCutBookmarkButton,  TButton * UpBookmarkButton, TButton * DownBookmarkButton){  EnableControl(AddBookmarkButton,    !LocalDirectory.IsEmpty() || !RemoteDirectory.IsEmpty());  EnableControl(RemoveBookmarkButton, ProfilesView->Selected);  EnableControl(RenameBookmarkButton, ProfilesView->Selected);  EnableControl(BookmarkMoveToButton, ProfilesView->Selected && ProfilesView->Selected->Data);  if (ShortCutBookmarkButton != NULL)  {    EnableControl(ShortCutBookmarkButton, ProfilesView->Selected && ProfilesView->Selected->Data);  }  EnableControl(UpBookmarkButton, ProfilesView->Selected &&    ProfilesView->Selected->Data && ProfilesView->Selected->getPrevSibling() &&    ProfilesView->Selected->getPrevSibling()->Data);  EnableControl(DownBookmarkButton, ProfilesView->Selected &&    ProfilesView->Selected->Data && ProfilesView->Selected->getNextSibling() &&    ProfilesView->Selected->getNextSibling()->Data);}//---------------------------------------------------------------------------void __fastcall TLocationProfilesDialog::UpdateControls(){  EnableControl(OKBtn, !LocalDirectory.IsEmpty() || !RemoteDirectory.IsEmpty());  UpdateProfilesControls(SessionProfilesView,    AddSessionBookmarkButton, RemoveSessionBookmarkButton,    RenameSessionBookmarkButton,  SessionBookmarkMoveToButton, NULL,    UpSessionBookmarkButton, DownSessionBookmarkButton);  UpdateProfilesControls(SharedProfilesView,    AddSharedBookmarkButton, RemoveSharedBookmarkButton,    RenameSharedBookmarkButton, SharedBookmarkMoveToButton,    ShortCutSharedBookmarkButton,    UpSharedBookmarkButton, DownSharedBookmarkButton);}//---------------------------------------------------------------------------void __fastcall TLocationProfilesDialog::LoadBookmarks(  TTreeView * ProfilesView, TStringList * Folders, TBookmarkList * BookmarkList,  TBookmarkList * Source){  if (Source != NULL)  {    BookmarkList->Assign(Source);  }  else  {    BookmarkList->Clear();  }  Configuration->Usage->SetMax(L"MaxBookmarks", BookmarkList->Count);  DebugAssert(BookmarkList != NULL);  Folders->Clear();  for (int Index = 0; Index < BookmarkList->Count; Index++)  {    TBookmark * Bookmark = BookmarkList->Bookmarks[Index];    if (!Bookmark->Node.IsEmpty())    {      Folders->Add(Bookmark->Node);    }  }  // WORKAROUND  // TTreeNodes::Clear is noop, when tree does not have a handle yet.  // (what happens here for a tree view on an inactive page)  ProfilesView->HandleNeeded();  ProfilesView->Items->Clear();  for (int Index = 0; Index < Folders->Count; Index++)  {    Folders->Objects[Index] = ProfilesView->Items->Add(NULL, Folders->Strings[Index]);  }  for (int Index = 0; Index < BookmarkList->Count; Index++)  {    TBookmark * Bookmark = BookmarkList->Bookmarks[Index];    TTreeNode * Parent = NULL;    if (!Bookmark->Node.IsEmpty())    {      DebugAssert(Folders->IndexOf(Bookmark->Node) >= 0);      Parent = dynamic_cast<TTreeNode *>(Folders->Objects[Folders->IndexOf(Bookmark->Node)]);    }    ProfilesView->Items->AddChildObject(Parent, BookmarkText(Bookmark), Bookmark);    if ((Parent != NULL) && (Parent->Count == 1))    {      // only now, when folder node has its first child, we can eventually expand it      Parent->Expanded = BookmarkList->NodeOpened[Parent->Text];    }  }}//---------------------------------------------------------------------------bool __fastcall TLocationProfilesDialog::Execute(){  bool Result;  PageControl->ActivePage = GetProfilesSheet();  FBookmarkSelected = false;  Result = (ShowModal() == DefaultResult(this));  if (Terminal)  {    WinConfiguration->Bookmarks[FSessionKey] = FSessionBookmarkList;    WinConfiguration->SharedBookmarks = FSharedBookmarkList;    WinConfiguration->UseSharedBookmarks = (PageControl->ActivePage == SharedProfilesSheet);  }  if (Result)  {    if (FBookmarkSelected)    {      Configuration->Usage->Inc(L"OpenedBookmark");    }    else    {      Configuration->Usage->Inc(L"OpenedPath");    }  }  return Result;}//---------------------------------------------------------------------------TTabSheet * TLocationProfilesDialog::GetProfilesSheet(){  return WinConfiguration->UseSharedBookmarks ? SharedProfilesSheet : SessionProfilesSheet;}//---------------------------------------------------------------------------template<class T>typename T * GetProfilesObject(TObject * Sender, T * SessionObject, T * SharedObject){  TControl * Control = dynamic_cast<TControl *>(Sender);  DebugAssert(Control != NULL);  switch (abs(Control->Tag))  {    case 1: return SessionObject;    case 2: return SharedObject;    default: DebugFail(); return NULL;  }}//---------------------------------------------------------------------------TBookmarkList * TLocationProfilesDialog::GetBookmarkList(TObject * Sender){  return GetProfilesObject(Sender, FSessionBookmarkList, FSharedBookmarkList);}//---------------------------------------------------------------------------TStringList * TLocationProfilesDialog::GetFolders(TObject * Sender){  #ifdef _DEBUG  DebugAssert(FSessionProfilesViewHandle == SessionProfilesView->Handle);  DebugAssert(FSharedProfilesViewHandle == SharedProfilesView->Handle);  #endif  return GetProfilesObject(Sender, FSessionFolders, FSharedFolders);}//---------------------------------------------------------------------------TTreeView * TLocationProfilesDialog::GetProfilesView(TObject * Sender){  return GetProfilesObject(Sender, SessionProfilesView, SharedProfilesView);}//---------------------------------------------------------------------------TTreeViewScrollOnDragOver * TLocationProfilesDialog::GetScrollOnDragOver(TObject * Sender){  return GetProfilesObject(Sender, FSessionScrollOnDragOver, FSharedScrollOnDragOver);}//---------------------------------------------------------------------------bool __fastcall TLocationProfilesDialog::AddAsBookmark(TObject * Sender, bool Initial){  TBookmarkList * BookmarkList = GetBookmarkList(Sender);  TTreeView * ProfilesView = GetProfilesView(Sender);  DebugAssert(!LocalDirectory.IsEmpty() || !RemoteDirectory.IsEmpty());  bool Result;  UnicodeString BookmarkName;  if ((OperationSide == osLocal && !LocalDirectory.IsEmpty()) ||      RemoteDirectory.IsEmpty())  {    BookmarkName = LocalDirectory;  }  else  {    BookmarkName = RemoteDirectory;  }  TTreeNode * Selected = ProfilesView->Selected;  TBookmark * SelectedBookmark = NULL;  UnicodeString SelectedNode;  if (Selected != NULL)  {    DebugAssert(!Initial);    SelectedBookmark = (TBookmark *)Selected->Data;    if (SelectedBookmark != NULL)    {      SelectedNode = SelectedBookmark->Node;    }    else    {      SelectedNode = Selected->Text;    }  }  TStrings * PeerBookmarks = new TStringList();  try  {    for (int Index = 0; Index < BookmarkList->Count; Index++)    {      TBookmark * Bookmark = BookmarkList->Bookmarks[Index];      if (Bookmark->Node == SelectedNode)      {        PeerBookmarks->Add(Bookmark->Name);      }    }    TBookmarkNameDialog * Dialog = new TBookmarkNameDialog(PeerBookmarks, Initial);    try    {      bool Shared = WinConfiguration->UseSharedBookmarks;      Result = Dialog->Execute(BookmarkName, Shared);      if (Result)      {        if (Initial)        {          WinConfiguration->UseSharedBookmarks = Shared;          BookmarkList = GetBookmarkList(GetProfilesSheet());          ProfilesView = GetProfilesView(GetProfilesSheet());        }        TBookmark * Bookmark = BookmarkList->FindByName(SelectedNode, BookmarkName);        if (Bookmark != NULL)        {          Bookmark->Local = LocalDirectory;          Bookmark->Remote = RemoteDirectory;          for (int Index = 0; Index < ProfilesView->Items->Count; Index++)          {            TTreeNode * Node = ProfilesView->Items->Item[Index];            if (Node->Data == Bookmark)            {              Selected = Node;              break;            }          }        }        else        {          Bookmark = new TBookmark();          Bookmark->Name = BookmarkName;          Bookmark->Local = LocalDirectory;          Bookmark->Remote = RemoteDirectory;          if (SelectedBookmark != NULL)          {            Bookmark->Node = SelectedBookmark->Node;            BookmarkList->InsertBefore(SelectedBookmark, Bookmark);            Selected = ProfilesView->Items->InsertObject(Selected, BookmarkText(Bookmark), Bookmark);          }          else if ((Selected != NULL) && (SelectedBookmark == NULL))          {            // must be a folder            DebugAssert(!Selected->Parent); // more than one level of folders is not supported            Bookmark->Node = Selected->Text;            BookmarkList->Add(Bookmark);            Selected = ProfilesView->Items->AddChildObject(Selected, BookmarkText(Bookmark), Bookmark);          }          else          {            BookmarkList->Add(Bookmark);            Selected = ProfilesView->Items->AddObject(NULL, BookmarkText(Bookmark), Bookmark);          }        }        ProfilesView->Selected = Selected;      }    }    __finally    {      delete Dialog;    }  }  __finally  {    delete PeerBookmarks;  }  UpdateControls();  return Result;}//---------------------------------------------------------------------------void __fastcall TLocationProfilesDialog::AddBookmarkButtonClick(TObject * Sender){  AddAsBookmark(Sender, false);}//---------------------------------------------------------------------------void __fastcall TLocationProfilesDialog::RemoveBookmark(TObject * Sender){  TBookmarkList * BookmarkList = GetBookmarkList(Sender);  TTreeView * ProfilesView = GetProfilesView(Sender);  TStringList * Folders = GetFolders(Sender);  DebugAssert(ProfilesView->Selected);  TTreeNode * Node = ProfilesView->Selected;  if (Node->Data)  {    BookmarkList->Delete((TBookmark *)Node->Data);    TTreeNode * ParentNode = Node->Parent;    Node->Delete();    if (ParentNode && !ParentNode->Count)    {      DebugAssert(Folders->IndexOfObject(ParentNode) >= 0);      Folders->Delete(Folders->IndexOfObject(ParentNode));      ParentNode->Delete();    }  }  else  {    UnicodeString Message = MainInstructions(LoadStr(DELETE_BOOKMARK_FOLDER));    if (MessageDialog(Message, qtConfirmation,          qaYes | qaNo, HELP_LOCATION_PROFILE_DELETE) == qaYes)    {      DebugAssert(Node->Count);      for (int i = 0; i < Node->Count; i++)      {        BookmarkList->Delete((TBookmark *)Node->Item[i]->Data);      }      DebugAssert(Folders->IndexOfObject(Node) >= 0);      Folders->Delete(Folders->IndexOfObject(Node));      Node->Delete();    }  }  UpdateControls();}//---------------------------------------------------------------------------void __fastcall TLocationProfilesDialog::RemoveBookmarkButtonClick(TObject * Sender){  RemoveBookmark(Sender);}//---------------------------------------------------------------------------void __fastcall TLocationProfilesDialog::BookmarkMove(TObject * Sender,  TTreeNode * Source, TTreeNode * Dest){  TBookmarkList * BookmarkList = GetBookmarkList(Sender);  TTreeView * ProfilesView = GetProfilesView(Sender);  TStringList * Folders = GetFolders(Sender);  DebugAssert(Source && Source->Data);  TBookmark * Bookmark = (TBookmark *)Source->Data;  TTreeNode * PrevFolderNode = Source->Parent;  if (!Dest || !Dest->Data)  {    Bookmark->Node = Dest ? Dest->Text : UnicodeString();    BookmarkList->MoveTo(BookmarkList->Bookmarks[BookmarkList->Count - 1],      Bookmark, false);    ProfilesView->Selected->MoveTo(Dest, naAddChild);  }  else  {    TBookmark * DestBookmark = (TBookmark *)Dest->Data;    Bookmark->Node = DestBookmark->Node;    BookmarkList->MoveTo(DestBookmark, Bookmark,      Source->AbsoluteIndex > Dest->AbsoluteIndex);    if (Source->AbsoluteIndex > Dest->AbsoluteIndex)    {      Source->MoveTo(Dest, naInsert);    }    else if (Dest->getNextSibling() != NULL)    {      Source->MoveTo(Dest->getNextSibling(), naInsert);    }    else    {      Source->MoveTo(Dest, naAdd);    }  }  if (PrevFolderNode && !PrevFolderNode->Count)  {    DebugAssert(Folders->IndexOfObject(PrevFolderNode) >= 0);    Folders->Delete(Folders->IndexOfObject(PrevFolderNode));    PrevFolderNode->Delete();  }  Source->MakeVisible();  UpdateControls();}//---------------------------------------------------------------------------void __fastcall TLocationProfilesDialog::BookmarkButtonClick(TObject * Sender){  TControl * Control = dynamic_cast<TControl *>(Sender);  TTreeNode * Node = GetProfilesView(Sender)->Selected;  DebugAssert(Node);  DebugAssert(Node->Data);  TTreeNode * TargetNode;  if (Control->Tag < 0)  {    TargetNode = Node->getPrevSibling();    DebugAssert(TargetNode);  }  else  {    TargetNode = Node->getNextSibling();  }  BookmarkMove(Sender, Node, TargetNode ? TargetNode : Node->Parent);}//---------------------------------------------------------------------------void __fastcall TLocationProfilesDialog::ProfilesViewStartDrag(  TObject * Sender, TDragObject *& /*DragObject*/){  TTreeView * ProfilesView = GetProfilesView(Sender);  if (!ProfilesView->Selected->Data)  {    Abort();  }  FBookmarkDragSource = ProfilesView->Selected;  GetScrollOnDragOver(Sender)->StartDrag();}//---------------------------------------------------------------------------void __fastcall TLocationProfilesDialog::ProfilesViewDragOver(  TObject * Sender, TObject * Source, int X, int Y,  TDragState /*State*/, bool & Accept){  TTreeView * ProfilesView = GetProfilesView(Sender);  if (Source == ProfilesView)  {    Accept = (ProfilesView->DropTarget != NULL) &&      (FBookmarkDragSource != ProfilesView->DropTarget);    GetScrollOnDragOver(Sender)->DragOver(TPoint(X, Y));  }}//---------------------------------------------------------------------------void __fastcall TLocationProfilesDialog::ProfilesViewDragDrop(  TObject * Sender, TObject * Source, int /*X*/, int /*Y*/){  TTreeView * ProfilesView = GetProfilesView(Sender);  if ((Source == ProfilesView) && (ProfilesView->DropTarget != NULL) &&      (FBookmarkDragSource != ProfilesView->DropTarget))  {    DebugAssert(FBookmarkDragSource);    TTreeNode * Target = ProfilesView->DropTarget;    BookmarkMove(Sender, FBookmarkDragSource, Target);    FBookmarkDragSource = NULL;  }}//---------------------------------------------------------------------------void __fastcall TLocationProfilesDialog::ProfilesViewDblClick(TObject * Sender){  TTreeView * ProfilesView = GetProfilesView(Sender);  TPoint P = ProfilesView->ScreenToClient(Mouse->CursorPos);  TTreeNode * Node = ProfilesView->GetNodeAt(P.x, P.y);  if (OKBtn->Enabled && Node && Node->Data && Node->Selected)  {    ModalResult = DefaultResult(this);  }}//---------------------------------------------------------------------------void __fastcall TLocationProfilesDialog::FormShow(TObject * /*Sender*/){  if (DebugAlwaysTrue(Terminal != NULL))  {    // cache session key, in case terminal is closed while the window is open    FSessionKey = Terminal->SessionData->SessionKey;    // WORKAROUND    // Has to load this only now (not in Execute before ShowModal),    // when the trees are finally (re)created,    // otherwise the references in *Folders would be invalid already    LoadBookmarks(SessionProfilesView, FSessionFolders, FSessionBookmarkList, WinConfiguration->Bookmarks[FSessionKey]);    LoadBookmarks(SharedProfilesView, FSharedFolders, FSharedBookmarkList, WinConfiguration->SharedBookmarks);    #ifdef _DEBUG    FSessionProfilesViewHandle = SessionProfilesView->Handle;    FSharedProfilesViewHandle = SharedProfilesView->Handle;    #endif  }  if (Mode == odAddBookmark)  {    AddAsBookmark(GetProfilesSheet(), true);  }  InstallPathWordBreakProc(LocalDirectoryEdit);  InstallPathWordBreakProc(RemoteDirectoryEdit);  FindProfile();  if (OperationSide == osLocal)  {    ActiveControl = LocalDirectoryEdit;  }  else  {    ActiveControl = RemoteDirectoryEdit;  }  UpdateControls();}//---------------------------------------------------------------------------void __fastcall TLocationProfilesDialog::ProfilesViewKeyDown(TObject * Sender,  WORD & Key, TShiftState /*Shift*/){  TTreeView * ProfilesView = GetProfilesView(Sender);  if (!ProfilesView->IsEditing())  {    if ((ProfilesView->Selected != NULL) && (Key == VK_DELETE))    {      RemoveBookmark(Sender);      Key = 0;    }    else if ((ProfilesView->Selected != NULL) && (Key == VK_F2))    {      RenameBookmark(Sender);      Key = 0;    }  }}//---------------------------------------------------------------------------void __fastcall TLocationProfilesDialog::DirectoryEditChange(TObject * /*Sender*/){  if (!FChanging)  {    FindProfile();    UpdateControls();    FBookmarkSelected = false;  }}//---------------------------------------------------------------------------void __fastcall TLocationProfilesDialog::ProfilesViewChange(  TObject * /*Sender*/, TTreeNode * Node){  if (Node && Node->Data)  {    DebugAssert(!FChanging);    FChanging = true;    try    {      LocalDirectoryEdit->Text = ((TBookmark *)Node->Data)->Local;      RemoteDirectoryEdit->Text = ((TBookmark *)Node->Data)->Remote;    }    __finally    {      FChanging = false;    }    // try to locate the same profile in the other set    FindProfile();    FBookmarkSelected = true;  }  UpdateControls();}//---------------------------------------------------------------------------void __fastcall TLocationProfilesDialog::BookmarkMoveToButtonClick(TObject * Sender){  TTreeView * ProfilesView = GetProfilesView(Sender);  TStringList * Folders = GetFolders(Sender);  DebugAssert(ProfilesView->Selected->Data);  TBookmark * Bookmark = (TBookmark *)ProfilesView->Selected->Data;  TBookmarkFolderDialog * Dialog = new TBookmarkFolderDialog(Folders);  try  {    UnicodeString NodeName = Bookmark->Node;    if (Dialog->Execute(NodeName) &&        (NodeName != Bookmark->Node))    {      TTreeNode * FolderNode;      int I = Folders->IndexOf(NodeName);      if (NodeName.IsEmpty())      {        FolderNode = NULL;      }      else if (I >= 0)      {        FolderNode = dynamic_cast<TTreeNode *>(Folders->Objects[I]);        DebugAssert(FolderNode);      }      else      {        I = Folders->Add(NodeName);        TTreeNode * NextNode;        // duplicated in RenameButtonClick()        if (I < Folders->Count-1)        {          NextNode = dynamic_cast<TTreeNode *>(Folders->Objects[I+1]);          DebugAssert(NextNode);        }        else if (Folders->Count > 1)        {          NextNode = (dynamic_cast<TTreeNode *>(Folders->Objects[I-1]))->getNextSibling();        }        else        {          DebugAssert(ProfilesView->Items->Count);          NextNode = ProfilesView->Items->Item[0];        }        FolderNode = ProfilesView->Items->Insert(NextNode, NodeName);        DebugAssert(FolderNode);        Folders->Objects[I] = FolderNode;      }      BookmarkMove(Sender, ProfilesView->Selected, FolderNode);    }  }  __finally  {    delete Dialog;  }}//---------------------------------------------------------------------------void __fastcall TLocationProfilesDialog::RenameBookmark(TObject * Sender){  TTreeView * ProfilesView = GetProfilesView(Sender);  DebugAssert(ProfilesView->Selected != NULL);  if (ProfilesView->Selected != NULL)  {    ProfilesView->SetFocus();    ProfilesView->Selected->EditText();  }}//---------------------------------------------------------------------------void __fastcall TLocationProfilesDialog::RenameBookmarkButtonClick(TObject * Sender){  RenameBookmark(Sender);}//---------------------------------------------------------------------------void __fastcall TLocationProfilesDialog::ProfilesViewGetImageIndex(      TObject * /*Sender*/, TTreeNode * Node){  Node->ImageIndex = Node->Data ? 0 : (Node->Expanded ? 1 : 2);}//---------------------------------------------------------------------------void __fastcall TLocationProfilesDialog::ProfilesViewGetSelectedIndex(      TObject * /*Sender*/, TTreeNode * Node){  Node->SelectedIndex = Node->Data ? 0 : (Node->Expanded ? 1 : 2);}//---------------------------------------------------------------------------void __fastcall TLocationProfilesDialog::LocalDirectoryBrowseButtonClick(  TObject * /*Sender*/){  UnicodeString Directory = LocalDirectoryEdit->Text;  if (SelectDirectory(Directory, LoadStr(SELECT_LOCAL_DIRECTORY), true))  {    LocalDirectoryEdit->Text = Directory;    DirectoryEditChange(LocalDirectoryEdit);  }}//---------------------------------------------------------------------------void __fastcall TLocationProfilesDialog::SwitchButtonClick(TObject * /*Sender*/){  WinConfiguration->UseLocationProfiles = false;}//---------------------------------------------------------------------------void __fastcall TLocationProfilesDialog::HelpButtonClick(TObject * /*Sender*/){  FormHelp(this);}//---------------------------------------------------------------------------void __fastcall TLocationProfilesDialog::ProfilesViewCollapsed(  TObject * Sender, TTreeNode * Node){  DebugAssert(Node != NULL);  DebugAssert(Node->Data == NULL);  GetBookmarkList(Sender)->NodeOpened[Node->Text] = false;}//---------------------------------------------------------------------------void __fastcall TLocationProfilesDialog::ProfilesViewExpanded(  TObject * Sender, TTreeNode * Node){  DebugAssert(Node != NULL);  DebugAssert(Node->Data == NULL);  GetBookmarkList(Sender)->NodeOpened[Node->Text] = true;}//---------------------------------------------------------------------------void __fastcall TLocationProfilesDialog::ProfilesViewEdited(  TObject * Sender, TTreeNode * Node, UnicodeString & S){  TTreeView * ProfilesView = GetProfilesView(Sender);  TStringList * Folders = GetFolders(Sender);  if (Node->Data != NULL)  {    BookmarkNameValidateName(S);    // raises exception in case of duplicate name??    ((TBookmark *)Node->Data)->Name = S;  }  else  {    BookmarkFolderValidateName(S, false);    if (S.IsEmpty())    {      throw Exception(FMTLOAD(BOOKMARK_FOLDER_INVALID_NAME, (S)));    }    if ((Folders->IndexOf(S) >= 0) && AnsiCompareText(S, Node->Text))    {      throw Exception(FMTLOAD(DUPLICATE_BOOKMARK_FOLDER, (S)));    }    DebugAssert(Node->Count);    Folders->Delete(Folders->IndexOf(Node->Text));    int I = Folders->AddObject(S, Node);    TTreeNode * NextNode;    // duplicated in MoveToButtonClick()    if (I < Folders->Count-1)    {      NextNode = dynamic_cast<TTreeNode *>(Folders->Objects[I+1]);      DebugAssert(NextNode);    }    else if (Folders->Count > 1)    {      NextNode = (dynamic_cast<TTreeNode *>(Folders->Objects[I-1]))->getNextSibling();    }    else    {      DebugAssert(ProfilesView->Items->Count);      NextNode = ProfilesView->Items->Item[0];    }    if (NextNode != Node)    {      Node->MoveTo(NextNode, NextNode ? naInsert : naAddChild);    }    for (int i = 0; i < Node->Count; i++)    {      ((TBookmark *)Node->Item[i]->Data)->Node = S;    }    Node->MakeVisible();  }}//---------------------------------------------------------------------------void __fastcall TLocationProfilesDialog::ProfilesViewEditing(  TObject * /*Sender*/, TTreeNode * /*Node*/, bool & /*AllowEdit*/){  OKBtn->Default = false;  CancelBtn->Cancel = false;}//---------------------------------------------------------------------------void __fastcall TLocationProfilesDialog::UpdateActions(){  TForm::UpdateActions();  if ((!OKBtn->Default || !CancelBtn->Cancel) &&      !GetProfilesView(PageControl->ActivePage)->IsEditing())  {    OKBtn->Default = true;    CancelBtn->Cancel = true;  }}//---------------------------------------------------------------------------void __fastcall TLocationProfilesDialog::ProfilesViewEndDrag(  TObject * Sender, TObject * /*Target*/, int /*X*/, int /*Y*/){  GetScrollOnDragOver(Sender)->EndDrag();}//---------------------------------------------------------------------------void __fastcall TLocationProfilesDialog::ShortCutBookmarkButtonClick(  TObject * Sender){  TBookmarkList * BookmarkList = GetBookmarkList(Sender);  TTreeView * ProfilesView = GetProfilesView(Sender);  DebugAssert(ProfilesView->Selected != NULL);  TTreeNode * Node = ProfilesView->Selected;  DebugAssert(Node->Data != NULL);  TBookmark * Bookmark = static_cast<TBookmark *>(Node->Data);  TShortCuts ShortCuts;  WinConfiguration->CustomCommandShortCuts(ShortCuts);  BookmarkList->ShortCuts(ShortCuts);  TShortCut ShortCut = Bookmark->ShortCut;  if (DoShortCutDialog(ShortCut, ShortCuts, HelpKeyword))  {    Bookmark->ShortCut = ShortCut;    Node->Text = BookmarkText(Bookmark);    UpdateControls();  }}//---------------------------------------------------------------------------UnicodeString __fastcall TLocationProfilesDialog::BookmarkText(TBookmark * Bookmark){  UnicodeString Result = Bookmark->Name;  if (!Result.IsEmpty() && (Bookmark->ShortCut != 0))  {    Result = FORMAT(L"%s (%s)", (Result, ShortCutToText(Bookmark->ShortCut)));  }  return Result;}//---------------------------------------------------------------------------
 |