+wxDEFINE_EVENT( wxEVT_DIRCTRL_SELECTIONCHANGED, wxTreeEvent );
+wxDEFINE_EVENT( wxEVT_DIRCTRL_FILEACTIVATED, wxTreeEvent );
+
+// ----------------------------------------------------------------------------
+// wxGetAvailableDrives, for WINDOWS, DOS, OS2, MAC, UNIX (returns "/")
+// ----------------------------------------------------------------------------
+
+size_t wxGetAvailableDrives(wxArrayString &paths, wxArrayString &names, wxArrayInt &icon_ids)
+{
+#ifdef wxHAS_FILESYSTEM_VOLUMES
+
+#ifdef __WXWINCE__
+ // No logical drives; return "\"
+ paths.Add(wxT("\\"));
+ names.Add(wxT("\\"));
+ icon_ids.Add(wxFileIconsTable::computer);
+#elif defined(__WIN32__) && wxUSE_FSVOLUME
+ // TODO: this code (using wxFSVolumeBase) should be used for all platforms
+ // but unfortunately wxFSVolumeBase is not implemented everywhere
+ const wxArrayString as = wxFSVolumeBase::GetVolumes();
+
+ for (size_t i = 0; i < as.GetCount(); i++)
+ {
+ wxString path = as[i];
+ wxFSVolume vol(path);
+ int imageId;
+ switch (vol.GetKind())
+ {
+ case wxFS_VOL_FLOPPY:
+ if ( (path == wxT("a:\\")) || (path == wxT("b:\\")) )
+ imageId = wxFileIconsTable::floppy;
+ else
+ imageId = wxFileIconsTable::removeable;
+ break;
+ case wxFS_VOL_DVDROM:
+ case wxFS_VOL_CDROM:
+ imageId = wxFileIconsTable::cdrom;
+ break;
+ case wxFS_VOL_NETWORK:
+ if (path[0] == wxT('\\'))
+ continue; // skip "\\computer\folder"
+ imageId = wxFileIconsTable::drive;
+ break;
+ case wxFS_VOL_DISK:
+ case wxFS_VOL_OTHER:
+ default:
+ imageId = wxFileIconsTable::drive;
+ break;
+ }
+ paths.Add(path);
+ names.Add(vol.GetDisplayName());
+ icon_ids.Add(imageId);
+ }
+#elif defined(__OS2__)
+ APIRET rc;
+ ULONG ulDriveNum = 0;
+ ULONG ulDriveMap = 0;
+ rc = ::DosQueryCurrentDisk(&ulDriveNum, &ulDriveMap);
+ if ( rc == 0)
+ {
+ size_t i = 0;
+ while (i < 26)
+ {
+ if (ulDriveMap & ( 1 << i ))
+ {
+ const wxString path = wxFileName::GetVolumeString(
+ 'A' + i, wxPATH_GET_SEPARATOR);
+ const wxString name = wxFileName::GetVolumeString(
+ 'A' + i, wxPATH_NO_SEPARATOR);
+
+ // Note: If _filesys is unsupported by some compilers,
+ // we can always replace it by DosQueryFSAttach
+ char filesysname[20];
+#ifdef __WATCOMC__
+ ULONG cbBuffer = sizeof(filesysname);
+ PFSQBUFFER2 pfsqBuffer = (PFSQBUFFER2)filesysname;
+ APIRET rc = ::DosQueryFSAttach(name.fn_str(),0,FSAIL_QUERYNAME,pfsqBuffer,&cbBuffer);
+ if (rc != NO_ERROR)
+ {
+ filesysname[0] = '\0';
+ }
+#else
+ _filesys(name.fn_str(), filesysname, sizeof(filesysname));
+#endif
+ /* FAT, LAN, HPFS, CDFS, NFS */
+ int imageId;
+ if (path == wxT("A:\\") || path == wxT("B:\\"))
+ imageId = wxFileIconsTable::floppy;
+ else if (!strcmp(filesysname, "CDFS"))
+ imageId = wxFileIconsTable::cdrom;
+ else if (!strcmp(filesysname, "LAN") ||
+ !strcmp(filesysname, "NFS"))
+ imageId = wxFileIconsTable::drive;
+ else
+ imageId = wxFileIconsTable::drive;
+ paths.Add(path);
+ names.Add(name);
+ icon_ids.Add(imageId);
+ }
+ i ++;
+ }
+ }
+#else // !__WIN32__, !__OS2__
+ /* If we can switch to the drive, it exists. */
+ for ( char drive = 'A'; drive <= 'Z'; drive++ )
+ {
+ const wxString
+ path = wxFileName::GetVolumeString(drive, wxPATH_GET_SEPARATOR);
+
+ if (wxIsDriveAvailable(path))
+ {
+ paths.Add(path);
+ names.Add(wxFileName::GetVolumeString(drive, wxPATH_NO_SEPARATOR));
+ icon_ids.Add(drive <= 2 ? wxFileIconsTable::floppy
+ : wxFileIconsTable::drive);
+ }
+ }
+#endif // __WIN32__/!__WIN32__
+
+#elif defined(__WXMAC__) && wxOSX_USE_COCOA_OR_CARBON
+
+ ItemCount volumeIndex = 1;
+ OSErr err = noErr ;
+
+ while( noErr == err )
+ {
+ HFSUniStr255 volumeName ;
+ FSRef fsRef ;
+ FSVolumeInfo volumeInfo ;
+ err = FSGetVolumeInfo(0, volumeIndex, NULL, kFSVolInfoFlags , &volumeInfo , &volumeName, &fsRef);
+ if( noErr == err )
+ {
+ wxString path = wxMacFSRefToPath( &fsRef ) ;
+ wxString name = wxMacHFSUniStrToString( &volumeName ) ;
+
+ if ( (volumeInfo.flags & kFSVolFlagSoftwareLockedMask) || (volumeInfo.flags & kFSVolFlagHardwareLockedMask) )
+ {
+ icon_ids.Add(wxFileIconsTable::cdrom);
+ }
+ else
+ {
+ icon_ids.Add(wxFileIconsTable::drive);
+ }
+ // todo other removable
+
+ paths.Add(path);
+ names.Add(name);
+ volumeIndex++ ;
+ }
+ }
+
+#elif defined(__UNIX__)
+ paths.Add(wxT("/"));
+ names.Add(wxT("/"));
+ icon_ids.Add(wxFileIconsTable::computer);
+#else
+ #error "Unsupported platform in wxGenericDirCtrl!"
+#endif
+ wxASSERT_MSG( (paths.GetCount() == names.GetCount()), wxT("The number of paths and their human readable names should be equal in number."));
+ wxASSERT_MSG( (paths.GetCount() == icon_ids.GetCount()), wxT("Wrong number of icons for available drives."));
+ return paths.GetCount();
+}
+
+// ----------------------------------------------------------------------------
+// wxIsDriveAvailable
+// ----------------------------------------------------------------------------
+
+#if defined(__DOS__)
+
+bool wxIsDriveAvailable(const wxString& dirName)
+{
+ // FIXME: this method leads to hang up under Watcom for some reason
+#ifdef __WATCOMC__
+ wxUnusedVar(dirName);
+#else
+ if ( dirName.length() == 3 && dirName[1u] == wxT(':') )
+ {
+ wxString dirNameLower(dirName.Lower());
+ // VS: always return true for removable media, since Win95 doesn't
+ // like it when MS-DOS app accesses empty floppy drive
+ return (dirNameLower[0u] == wxT('a') ||
+ dirNameLower[0u] == wxT('b') ||
+ wxDirExists(dirNameLower));
+ }
+ else
+#endif
+ return true;
+}
+
+#elif defined(__WINDOWS__) || defined(__OS2__)
+
+int setdrive(int WXUNUSED_IN_WINCE(drive))
+{
+#ifdef __WXWINCE__
+ return 0;
+#elif defined(__GNUWIN32__) && \
+ (defined(__MINGW32_MAJOR_VERSION) && __MINGW32_MAJOR_VERSION >= 1)
+ return _chdrive(drive);
+#else
+ wxChar newdrive[4];
+
+ if (drive < 1 || drive > 31)
+ return -1;
+ newdrive[0] = (wxChar)(wxT('A') + drive - 1);
+ newdrive[1] = wxT(':');
+#ifdef __OS2__
+ newdrive[2] = wxT('\\');
+ newdrive[3] = wxT('\0');
+#else
+ newdrive[2] = wxT('\0');
+#endif
+#if defined(__WINDOWS__)
+ if (::SetCurrentDirectory(newdrive))
+#else
+ // VA doesn't know what LPSTR is and has its own set
+ if (!DosSetCurrentDir((PSZ)newdrive))
+#endif
+ return 0;
+ else
+ return -1;
+#endif // !GNUWIN32
+}
+
+bool wxIsDriveAvailable(const wxString& WXUNUSED_IN_WINCE(dirName))
+{
+#ifdef __WXWINCE__
+ return false;
+#else
+#ifdef __WIN32__
+ UINT errorMode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
+#endif
+ bool success = true;
+
+ // Check if this is a root directory and if so,
+ // whether the drive is available.
+ if (dirName.length() == 3 && dirName[(size_t)1] == wxT(':'))
+ {
+ wxString dirNameLower(dirName.Lower());
+#if defined(__GNUWIN32__) && !(defined(__MINGW32_MAJOR_VERSION) && __MINGW32_MAJOR_VERSION >= 1)
+ success = wxDirExists(dirNameLower);
+#else
+ #if defined(__OS2__)
+ // Avoid changing to drive since no media may be inserted.
+ if (dirNameLower[(size_t)0] == 'a' || dirNameLower[(size_t)0] == 'b')
+ return success;
+ #endif
+ int currentDrive = _getdrive();
+ int thisDrive = (int) (dirNameLower[(size_t)0] - 'a' + 1) ;
+ int err = setdrive( thisDrive ) ;
+ setdrive( currentDrive );
+
+ if (err == -1)
+ {
+ success = false;
+ }
+#endif
+ }
+#ifdef __WIN32__
+ (void) SetErrorMode(errorMode);
+#endif
+
+ return success;
+#endif
+}
+#endif // __WINDOWS__ || __OS2__
+
+#endif // wxUSE_DIRDLG || wxUSE_FILEDLG
+
+
+
+#if wxUSE_DIRDLG
+
+// Function which is called by quick sort. We want to override the default wxArrayString behaviour,
+// and sort regardless of case.
+static int wxCMPFUNC_CONV wxDirCtrlStringCompareFunction(const wxString& strFirst, const wxString& strSecond)
+{
+ return strFirst.CmpNoCase(strSecond);
+}