1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/generic/dirctrlg.cpp 
   3 // Purpose:     wxGenericDirCtrl 
   4 // Author:      Harm van der Heijden, Robert Roebling, Julian Smart 
   8 // Copyright:   (c) Harm van der Heijden, Robert Roebling and Julian Smart 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // For compilers that support precompilation, includes "wx.h". 
  13 #include "wx/wxprec.h" 
  19 #if wxUSE_DIRDLG || wxUSE_FILEDLG 
  21 #include "wx/generic/dirctrlg.h" 
  28     #include "wx/button.h" 
  30     #include "wx/settings.h" 
  31     #include "wx/msgdlg.h" 
  32     #include "wx/cmndata.h" 
  33     #include "wx/choice.h" 
  34     #include "wx/textctrl.h" 
  35     #include "wx/layout.h" 
  37     #include "wx/textdlg.h" 
  38     #include "wx/gdicmn.h" 
  40     #include "wx/module.h" 
  43 #include "wx/filename.h" 
  44 #include "wx/filefn.h" 
  45 #include "wx/imaglist.h" 
  46 #include "wx/tokenzr.h" 
  48 #include "wx/artprov.h" 
  49 #include "wx/mimetype.h" 
  52     #include "wx/statline.h" 
  55 #if defined(__WXMAC__) 
  56     #include  "wx/osx/private.h"  // includes mac headers 
  61 #include "wx/msw/winundef.h" 
  62 #include "wx/volume.h" 
  64 // FIXME - Mingw32 1.0 has both _getdrive() and _chdrive(). For now, let's assume 
  65 //         older releases don't, but it should be verified and the checks modified 
  67 #if !defined(__GNUWIN32__) || (defined(__MINGW32_MAJOR_VERSION) && __MINGW32_MAJOR_VERSION >= 1) 
  68 #if !defined(__WXWINCE__) 
  77 #if defined(__OS2__) || defined(__DOS__) 
  89 #if defined(__WXMAC__) 
  90 //    #include "MoreFilesX.h" 
  97 extern WXDLLEXPORT_DATA(const char) wxFileSelectorDefaultWildcardStr
[]; 
  99 // If compiled under Windows, this macro can cause problems 
 104 bool wxIsDriveAvailable(const wxString
& dirName
); 
 106 // ---------------------------------------------------------------------------- 
 107 // wxGetAvailableDrives, for WINDOWS, DOS, OS2, MAC, UNIX (returns "/") 
 108 // ---------------------------------------------------------------------------- 
 110 size_t wxGetAvailableDrives(wxArrayString 
&paths
, wxArrayString 
&names
, wxArrayInt 
&icon_ids
) 
 112 #ifdef wxHAS_FILESYSTEM_VOLUMES 
 115     // No logical drives; return "\" 
 116     paths
.Add(wxT("\\")); 
 117     names
.Add(wxT("\\")); 
 118     icon_ids
.Add(wxFileIconsTable::computer
); 
 119 #elif defined(__WIN32__) && wxUSE_FSVOLUME 
 120     // TODO: this code (using wxFSVolumeBase) should be used for all platforms 
 121     //       but unfortunately wxFSVolumeBase is not implemented everywhere 
 122     const wxArrayString as 
= wxFSVolumeBase::GetVolumes(); 
 124     for (size_t i 
= 0; i 
< as
.GetCount(); i
++) 
 126         wxString path 
= as
[i
]; 
 127         wxFSVolume 
vol(path
); 
 129         switch (vol
.GetKind()) 
 131             case wxFS_VOL_FLOPPY
: 
 132                 if ( (path 
== wxT("a:\\")) || (path 
== wxT("b:\\")) ) 
 133                     imageId 
= wxFileIconsTable::floppy
; 
 135                     imageId 
= wxFileIconsTable::removeable
; 
 137             case wxFS_VOL_DVDROM
: 
 139                 imageId 
= wxFileIconsTable::cdrom
; 
 141             case wxFS_VOL_NETWORK
: 
 142                 if (path
[0] == wxT('\\')) 
 143                     continue; // skip "\\computer\folder" 
 144                 imageId 
= wxFileIconsTable::drive
; 
 149                 imageId 
= wxFileIconsTable::drive
; 
 153         names
.Add(vol
.GetDisplayName()); 
 154         icon_ids
.Add(imageId
); 
 156 #elif defined(__OS2__) 
 158     ULONG ulDriveNum 
= 0; 
 159     ULONG ulDriveMap 
= 0; 
 160     rc 
= ::DosQueryCurrentDisk(&ulDriveNum
, &ulDriveMap
); 
 166             if (ulDriveMap 
& ( 1 << i 
)) 
 168                 const wxString path 
= wxFileName::GetVolumeString( 
 169                                         'A' + i
, wxPATH_GET_SEPARATOR
); 
 170                 const wxString name 
= wxFileName::GetVolumeString( 
 171                                         'A' + i
, wxPATH_NO_SEPARATOR
); 
 173                 // Note: If _filesys is unsupported by some compilers, 
 174                 //       we can always replace it by DosQueryFSAttach 
 175                 char filesysname
[20]; 
 177                 ULONG cbBuffer 
= sizeof(filesysname
); 
 178                 PFSQBUFFER2 pfsqBuffer 
= (PFSQBUFFER2
)filesysname
; 
 179                 APIRET rc 
= ::DosQueryFSAttach(name
.fn_str(),0,FSAIL_QUERYNAME
,pfsqBuffer
,&cbBuffer
); 
 182                     filesysname
[0] = '\0'; 
 185                 _filesys(name
.fn_str(), filesysname
, sizeof(filesysname
)); 
 187                 /* FAT, LAN, HPFS, CDFS, NFS */ 
 189                 if (path 
== wxT("A:\\") || path 
== wxT("B:\\")) 
 190                     imageId 
= wxFileIconsTable::floppy
; 
 191                 else if (!strcmp(filesysname
, "CDFS")) 
 192                     imageId 
= wxFileIconsTable::cdrom
; 
 193                 else if (!strcmp(filesysname
, "LAN") || 
 194                          !strcmp(filesysname
, "NFS")) 
 195                     imageId 
= wxFileIconsTable::drive
; 
 197                     imageId 
= wxFileIconsTable::drive
; 
 200                 icon_ids
.Add(imageId
); 
 205 #else // !__WIN32__, !__OS2__ 
 206     /* If we can switch to the drive, it exists. */ 
 207     for ( char drive 
= 'A'; drive 
<= 'Z'; drive
++ ) 
 210             path 
= wxFileName::GetVolumeString(drive
, wxPATH_GET_SEPARATOR
); 
 212         if (wxIsDriveAvailable(path
)) 
 215             names
.Add(wxFileName::GetVolumeString(drive
, wxPATH_NO_SEPARATOR
)); 
 216             icon_ids
.Add(drive 
<= 2 ? wxFileIconsTable::floppy
 
 217                                     : wxFileIconsTable::drive
); 
 220 #endif // __WIN32__/!__WIN32__ 
 222 #elif defined(__WXMAC__) && wxOSX_USE_COCOA_OR_CARBON 
 224     ItemCount volumeIndex 
= 1; 
 227     while( noErr 
== err 
) 
 229         HFSUniStr255 volumeName 
; 
 231         FSVolumeInfo volumeInfo 
; 
 232         err 
= FSGetVolumeInfo(0, volumeIndex
, NULL
, kFSVolInfoFlags 
, &volumeInfo 
, &volumeName
, &fsRef
); 
 235             wxString path 
= wxMacFSRefToPath( &fsRef 
) ; 
 236             wxString name 
= wxMacHFSUniStrToString( &volumeName 
) ; 
 238             if ( (volumeInfo
.flags 
& kFSVolFlagSoftwareLockedMask
) || (volumeInfo
.flags 
& kFSVolFlagHardwareLockedMask
) ) 
 240                 icon_ids
.Add(wxFileIconsTable::cdrom
); 
 244                 icon_ids
.Add(wxFileIconsTable::drive
); 
 246             // todo other removable 
 254 #elif defined(__UNIX__) || defined(__WXPALMOS__) 
 257     icon_ids
.Add(wxFileIconsTable::computer
); 
 259     #error "Unsupported platform in wxGenericDirCtrl!" 
 261     wxASSERT_MSG( (paths
.GetCount() == names
.GetCount()), wxT("The number of paths and their human readable names should be equal in number.")); 
 262     wxASSERT_MSG( (paths
.GetCount() == icon_ids
.GetCount()), wxT("Wrong number of icons for available drives.")); 
 263     return paths
.GetCount(); 
 266 // ---------------------------------------------------------------------------- 
 267 // wxIsDriveAvailable 
 268 // ---------------------------------------------------------------------------- 
 272 bool wxIsDriveAvailable(const wxString
& dirName
) 
 274     // FIXME_MGL - this method leads to hang up under Watcom for some reason 
 276     wxUnusedVar(dirName
); 
 278     if ( dirName
.length() == 3 && dirName
[1u] == wxT(':') ) 
 280         wxString 
dirNameLower(dirName
.Lower()); 
 281         // VS: always return true for removable media, since Win95 doesn't 
 282         //     like it when MS-DOS app accesses empty floppy drive 
 283         return (dirNameLower
[0u] == wxT('a') || 
 284                 dirNameLower
[0u] == wxT('b') || 
 285                 wxDirExists(dirNameLower
)); 
 292 #elif defined(__WINDOWS__) || defined(__OS2__) 
 294 int setdrive(int WXUNUSED_IN_WINCE(drive
)) 
 298 #elif defined(__GNUWIN32__) && \ 
 299     (defined(__MINGW32_MAJOR_VERSION) && __MINGW32_MAJOR_VERSION >= 1) 
 300     return _chdrive(drive
); 
 304     if (drive 
< 1 || drive 
> 31) 
 306     newdrive
[0] = (wxChar
)(wxT('A') + drive 
- 1); 
 307     newdrive
[1] = wxT(':'); 
 309     newdrive
[2] = wxT('\\'); 
 310     newdrive
[3] = wxT('\0'); 
 312     newdrive
[2] = wxT('\0'); 
 314 #if defined(__WXMSW__) 
 315     if (::SetCurrentDirectory(newdrive
)) 
 317     // VA doesn't know what LPSTR is and has its own set 
 318     if (!DosSetCurrentDir((PSZ
)newdrive
)) 
 326 bool wxIsDriveAvailable(const wxString
& WXUNUSED_IN_WINCE(dirName
)) 
 332     UINT errorMode 
= SetErrorMode(SEM_FAILCRITICALERRORS 
| SEM_NOOPENFILEERRORBOX
); 
 336     // Check if this is a root directory and if so, 
 337     // whether the drive is available. 
 338     if (dirName
.length() == 3 && dirName
[(size_t)1] == wxT(':')) 
 340         wxString 
dirNameLower(dirName
.Lower()); 
 341 #if defined(__GNUWIN32__) && !(defined(__MINGW32_MAJOR_VERSION) && __MINGW32_MAJOR_VERSION >= 1) 
 342         success 
= wxDirExists(dirNameLower
); 
 345         // Avoid changing to drive since no media may be inserted. 
 346         if (dirNameLower
[(size_t)0] == 'a' || dirNameLower
[(size_t)0] == 'b') 
 349         int currentDrive 
= _getdrive(); 
 350         int thisDrive 
= (int) (dirNameLower
[(size_t)0] - 'a' + 1) ; 
 351         int err 
= setdrive( thisDrive 
) ; 
 352         setdrive( currentDrive 
); 
 361     (void) SetErrorMode(errorMode
); 
 367 #endif // __WINDOWS__ || __OS2__ 
 369 #endif // wxUSE_DIRDLG || wxUSE_FILEDLG 
 375 // Function which is called by quick sort. We want to override the default wxArrayString behaviour, 
 376 // and sort regardless of case. 
 377 static int wxCMPFUNC_CONV 
wxDirCtrlStringCompareFunction(const wxString
& strFirst
, const wxString
& strSecond
) 
 379     return strFirst
.CmpNoCase(strSecond
); 
 382 //----------------------------------------------------------------------------- 
 384 //----------------------------------------------------------------------------- 
 386 wxDirItemData::wxDirItemData(const wxString
& path
, const wxString
& name
, 
 391     /* Insert logic to detect hidden files here 
 392      * In UnixLand we just check whether the first char is a dot 
 393      * For FileNameFromPath read LastDirNameInThisPath ;-) */ 
 394     // m_isHidden = (bool)(wxFileNameFromPath(*m_path)[0] == '.'); 
 396     m_isExpanded 
= false; 
 400 void wxDirItemData::SetNewDirName(const wxString
& path
) 
 403     m_name 
= wxFileNameFromPath(path
); 
 406 bool wxDirItemData::HasSubDirs() const 
 414         if ( !dir
.Open(m_path
) ) 
 418     return dir
.HasSubDirs(); 
 421 bool wxDirItemData::HasFiles(const wxString
& WXUNUSED(spec
)) const 
 429         if ( !dir
.Open(m_path
) ) 
 433     return dir
.HasFiles(); 
 436 //----------------------------------------------------------------------------- 
 438 //----------------------------------------------------------------------------- 
 441 #if wxUSE_EXTENDED_RTTI 
 442 WX_DEFINE_FLAGS( wxGenericDirCtrlStyle 
) 
 444 wxBEGIN_FLAGS( wxGenericDirCtrlStyle 
) 
 445     // new style border flags, we put them first to 
 446     // use them for streaming out 
 447     wxFLAGS_MEMBER(wxBORDER_SIMPLE
) 
 448     wxFLAGS_MEMBER(wxBORDER_SUNKEN
) 
 449     wxFLAGS_MEMBER(wxBORDER_DOUBLE
) 
 450     wxFLAGS_MEMBER(wxBORDER_RAISED
) 
 451     wxFLAGS_MEMBER(wxBORDER_STATIC
) 
 452     wxFLAGS_MEMBER(wxBORDER_NONE
) 
 454     // old style border flags 
 455     wxFLAGS_MEMBER(wxSIMPLE_BORDER
) 
 456     wxFLAGS_MEMBER(wxSUNKEN_BORDER
) 
 457     wxFLAGS_MEMBER(wxDOUBLE_BORDER
) 
 458     wxFLAGS_MEMBER(wxRAISED_BORDER
) 
 459     wxFLAGS_MEMBER(wxSTATIC_BORDER
) 
 460     wxFLAGS_MEMBER(wxBORDER
) 
 462     // standard window styles 
 463     wxFLAGS_MEMBER(wxTAB_TRAVERSAL
) 
 464     wxFLAGS_MEMBER(wxCLIP_CHILDREN
) 
 465     wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW
) 
 466     wxFLAGS_MEMBER(wxWANTS_CHARS
) 
 467     wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE
) 
 468     wxFLAGS_MEMBER(wxALWAYS_SHOW_SB 
) 
 469     wxFLAGS_MEMBER(wxVSCROLL
) 
 470     wxFLAGS_MEMBER(wxHSCROLL
) 
 472     wxFLAGS_MEMBER(wxDIRCTRL_DIR_ONLY
) 
 473     wxFLAGS_MEMBER(wxDIRCTRL_3D_INTERNAL
) 
 474     wxFLAGS_MEMBER(wxDIRCTRL_SELECT_FIRST
) 
 475     wxFLAGS_MEMBER(wxDIRCTRL_MULTIPLE
) 
 477 wxEND_FLAGS( wxGenericDirCtrlStyle 
) 
 479 IMPLEMENT_DYNAMIC_CLASS_XTI(wxGenericDirCtrl
, wxControl
,"wx/dirctrl.h") 
 481 wxBEGIN_PROPERTIES_TABLE(wxGenericDirCtrl
) 
 482     wxHIDE_PROPERTY( Children 
) 
 483     wxPROPERTY( DefaultPath 
, wxString 
, SetDefaultPath 
, GetDefaultPath  
, EMPTY_MACROVALUE 
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) 
 484     wxPROPERTY( Filter 
, wxString 
, SetFilter 
, GetFilter  
, EMPTY_MACROVALUE 
, 0 /*flags*/ , wxT("Helpstring") , wxT("group") ) 
 485     wxPROPERTY( DefaultFilter 
, int , SetFilterIndex
, GetFilterIndex
, EMPTY_MACROVALUE 
, 0 /*flags*/ , wxT("Helpstring") , wxT("group") ) 
 486     wxPROPERTY_FLAGS( WindowStyle
, wxGenericDirCtrlStyle
, long, SetWindowStyleFlag
, GetWindowStyleFlag
, EMPTY_MACROVALUE 
, 0, wxT("Helpstring"), wxT("group") ) 
 487 wxEND_PROPERTIES_TABLE() 
 489 wxBEGIN_HANDLERS_TABLE(wxGenericDirCtrl
) 
 490 wxEND_HANDLERS_TABLE() 
 492 wxCONSTRUCTOR_8( wxGenericDirCtrl 
, wxWindow
* , Parent 
, wxWindowID 
, Id 
, wxString 
, DefaultPath 
, 
 493                  wxPoint 
, Position 
, wxSize 
, Size 
, long , WindowStyle 
, wxString 
, Filter 
, int , DefaultFilter 
) 
 495 IMPLEMENT_DYNAMIC_CLASS(wxGenericDirCtrl
, wxControl
) 
 498 BEGIN_EVENT_TABLE(wxGenericDirCtrl
, wxControl
) 
 499   EVT_TREE_ITEM_EXPANDING     (wxID_TREECTRL
, wxGenericDirCtrl::OnExpandItem
) 
 500   EVT_TREE_ITEM_COLLAPSED     (wxID_TREECTRL
, wxGenericDirCtrl::OnCollapseItem
) 
 501   EVT_TREE_BEGIN_LABEL_EDIT   (wxID_TREECTRL
, wxGenericDirCtrl::OnBeginEditItem
) 
 502   EVT_TREE_END_LABEL_EDIT     (wxID_TREECTRL
, wxGenericDirCtrl::OnEndEditItem
) 
 503   EVT_SIZE                    (wxGenericDirCtrl::OnSize
) 
 506 wxGenericDirCtrl::wxGenericDirCtrl(void) 
 511 void wxGenericDirCtrl::ExpandRoot() 
 513     ExpandDir(m_rootId
); // automatically expand first level 
 515     // Expand and select the default path 
 516     if (!m_defaultPath
.empty()) 
 518         ExpandPath(m_defaultPath
); 
 523         // On Unix, there's only one node under the (hidden) root node. It 
 524         // represents the / path, so the user would always have to expand it; 
 525         // let's do it ourselves 
 526         ExpandPath( wxT("/") ); 
 531 bool wxGenericDirCtrl::Create(wxWindow 
*parent
, 
 537                               const wxString
& filter
, 
 539                               const wxString
& name
) 
 541     if (!wxControl::Create(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
)) 
 544     SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
)); 
 545     SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT
)); 
 549     long treeStyle 
= wxTR_HAS_BUTTONS
; 
 551     // On Windows CE, if you hide the root, you get a crash when 
 552     // attempting to access data for children of the root item. 
 554     treeStyle 
|= wxTR_HIDE_ROOT
; 
 558     treeStyle 
|= wxTR_NO_LINES
; 
 561     if (style 
& wxDIRCTRL_EDIT_LABELS
) 
 562         treeStyle 
|= wxTR_EDIT_LABELS
; 
 564     if (style 
& wxDIRCTRL_MULTIPLE
) 
 565         treeStyle 
|= wxTR_MULTIPLE
; 
 567     if ((style 
& wxDIRCTRL_3D_INTERNAL
) == 0) 
 568         treeStyle 
|= wxNO_BORDER
; 
 570     m_treeCtrl 
= CreateTreeCtrl(this, wxID_TREECTRL
, 
 571                                 wxPoint(0,0), GetClientSize(), treeStyle
); 
 574         m_filterListCtrl 
= new wxDirFilterListCtrl(this, wxID_FILTERLISTCTRL
); 
 579     if (m_filter
.empty()) 
 580         m_filter 
= wxFileSelectorDefaultWildcardStr
; 
 582     SetFilterIndex(defaultFilter
); 
 584     if (m_filterListCtrl
) 
 585         m_filterListCtrl
->FillFilterList(filter
, defaultFilter
); 
 587     m_treeCtrl
->SetImageList(wxTheFileIconsTable
->GetSmallImageList()); 
 589     m_showHidden 
= false; 
 590     wxDirItemData
* rootData 
= new wxDirItemData(wxEmptyString
, wxEmptyString
, true); 
 594 #if defined(__WINDOWS__) || defined(__OS2__) || defined(__DOS__) 
 595     rootName 
= _("Computer"); 
 597     rootName 
= _("Sections"); 
 600     m_rootId 
= m_treeCtrl
->AddRoot( rootName
, 3, -1, rootData
); 
 601     m_treeCtrl
->SetItemHasChildren(m_rootId
); 
 605     SetInitialSize(size
); 
 611 wxGenericDirCtrl::~wxGenericDirCtrl() 
 615 void wxGenericDirCtrl::Init() 
 617     m_showHidden 
= false; 
 619     m_currentFilterStr 
= wxEmptyString
; // Default: any file 
 621     m_filterListCtrl 
= NULL
; 
 624 wxTreeCtrl
* wxGenericDirCtrl::CreateTreeCtrl(wxWindow 
*parent
, wxWindowID id
, const wxPoint
& pos
, const wxSize
& size
, long treeStyle
) 
 626     return new wxTreeCtrl(parent
, id
, pos
, size
, treeStyle
); 
 629 void wxGenericDirCtrl::ShowHidden( bool show 
) 
 631     if ( m_showHidden 
== show 
) 
 636     if ( HasFlag(wxDIRCTRL_MULTIPLE
) ) 
 641         for ( unsigned n 
= 0; n 
< paths
.size(); n
++ ) 
 643             ExpandPath(paths
[n
]); 
 648         wxString path 
= GetPath(); 
 655 wxGenericDirCtrl::AddSection(const wxString
& path
, const wxString
& name
, int imageId
) 
 657     wxDirItemData 
*dir_item 
= new wxDirItemData(path
,name
,true); 
 659     wxTreeItemId id 
= AppendItem( m_rootId
, name
, imageId
, -1, dir_item
); 
 661     m_treeCtrl
->SetItemHasChildren(id
); 
 666 void wxGenericDirCtrl::SetupSections() 
 668     wxArrayString paths
, names
; 
 671     size_t n
, count 
= wxGetAvailableDrives(paths
, names
, icons
); 
 674     wxString home 
= wxGetHomeDir(); 
 675     AddSection( home
, _("Home directory"), 1); 
 676     home 
+= wxT("/Desktop"); 
 677     AddSection( home
, _("Desktop"), 1); 
 680     for (n 
= 0; n 
< count
; n
++) 
 681         AddSection(paths
[n
], names
[n
], icons
[n
]); 
 684 void wxGenericDirCtrl::SetFocus() 
 686     // we don't need focus ourselves, give it to the tree so that the user 
 689         m_treeCtrl
->SetFocus(); 
 692 void wxGenericDirCtrl::OnBeginEditItem(wxTreeEvent 
&event
) 
 694     // don't rename the main entry "Sections" 
 695     if (event
.GetItem() == m_rootId
) 
 701     // don't rename the individual sections 
 702     if (m_treeCtrl
->GetItemParent( event
.GetItem() ) == m_rootId
) 
 709 void wxGenericDirCtrl::OnEndEditItem(wxTreeEvent 
&event
) 
 711     if (event
.IsEditCancelled()) 
 714     if ((event
.GetLabel().empty()) || 
 715         (event
.GetLabel() == wxT(".")) || 
 716         (event
.GetLabel() == wxT("..")) || 
 717         (event
.GetLabel().Find(wxT('/')) != wxNOT_FOUND
) || 
 718         (event
.GetLabel().Find(wxT('\\')) != wxNOT_FOUND
) || 
 719         (event
.GetLabel().Find(wxT('|')) != wxNOT_FOUND
)) 
 721         wxMessageDialog 
dialog(this, _("Illegal directory name."), _("Error"), wxOK 
| wxICON_ERROR 
); 
 727     wxTreeItemId id 
= event
.GetItem(); 
 728     wxDirItemData 
*data 
= (wxDirItemData
*)m_treeCtrl
->GetItemData( id 
); 
 731     wxString 
new_name( wxPathOnly( data
->m_path 
) ); 
 732     new_name 
+= wxString(wxFILE_SEP_PATH
); 
 733     new_name 
+= event
.GetLabel(); 
 737     if (wxFileExists(new_name
)) 
 739         wxMessageDialog 
dialog(this, _("File name exists already."), _("Error"), wxOK 
| wxICON_ERROR 
); 
 744     if (wxRenameFile(data
->m_path
,new_name
)) 
 746         data
->SetNewDirName( new_name 
); 
 750         wxMessageDialog 
dialog(this, _("Operation not permitted."), _("Error"), wxOK 
| wxICON_ERROR 
); 
 756 void wxGenericDirCtrl::OnExpandItem(wxTreeEvent 
&event
) 
 758     wxTreeItemId parentId 
= event
.GetItem(); 
 760     // VS: this is needed because the event handler is called from wxTreeCtrl 
 761     //     ctor when wxTR_HIDE_ROOT was specified 
 763     if (!m_rootId
.IsOk()) 
 765         m_rootId 
= m_treeCtrl
->GetRootItem(); 
 768     if ( m_treeCtrl
->GetChildrenCount(parentId
, false) == 0 ) 
 770         m_treeCtrl
->SetItemHasChildren(parentId
, false); 
 774 void wxGenericDirCtrl::OnCollapseItem(wxTreeEvent 
&event 
) 
 776     CollapseDir(event
.GetItem()); 
 779 void wxGenericDirCtrl::CollapseDir(wxTreeItemId parentId
) 
 783     wxDirItemData 
*data 
= (wxDirItemData 
*) m_treeCtrl
->GetItemData(parentId
); 
 784     if (!data
->m_isExpanded
) 
 787     data
->m_isExpanded 
= false; 
 789     m_treeCtrl
->Freeze(); 
 790     if (parentId 
!= m_treeCtrl
->GetRootItem()) 
 791         m_treeCtrl
->CollapseAndReset(parentId
); 
 792     m_treeCtrl
->DeleteChildren(parentId
); 
 796 void wxGenericDirCtrl::ExpandDir(wxTreeItemId parentId
) 
 798     wxDirItemData 
*data 
= (wxDirItemData 
*) m_treeCtrl
->GetItemData(parentId
); 
 800     if (data
->m_isExpanded
) 
 803     data
->m_isExpanded 
= true; 
 805     if (parentId 
== m_treeCtrl
->GetRootItem()) 
 813     wxString search
,path
,filename
; 
 815     wxString 
dirName(data
->m_path
); 
 817 #if (defined(__WINDOWS__) && !defined(__WXWINCE__)) || defined(__DOS__) || defined(__OS2__) 
 818     // Check if this is a root directory and if so, 
 819     // whether the drive is avaiable. 
 820     if (!wxIsDriveAvailable(dirName
)) 
 822         data
->m_isExpanded 
= false; 
 823         //wxMessageBox(wxT("Sorry, this drive is not available.")); 
 828     // This may take a longish time. Go to busy cursor 
 831 #if defined(__WINDOWS__) || defined(__DOS__) || defined(__OS2__) 
 832     if (dirName
.Last() == ':') 
 833         dirName 
+= wxString(wxFILE_SEP_PATH
); 
 837     wxArrayString filenames
; 
 840     wxString eachFilename
; 
 847         int style 
= wxDIR_DIRS
; 
 848         if (m_showHidden
) style 
|= wxDIR_HIDDEN
; 
 849         if (d
.GetFirst(& eachFilename
, wxEmptyString
, style
)) 
 853                 if ((eachFilename 
!= wxT(".")) && (eachFilename 
!= wxT(".."))) 
 855                     dirs
.Add(eachFilename
); 
 858             while (d
.GetNext(&eachFilename
)); 
 861     dirs
.Sort(wxDirCtrlStringCompareFunction
); 
 863     // Now do the filenames -- but only if we're allowed to 
 864     if (!HasFlag(wxDIRCTRL_DIR_ONLY
)) 
 870             int style 
= wxDIR_FILES
; 
 871             if (m_showHidden
) style 
|= wxDIR_HIDDEN
; 
 872             // Process each filter (ex: "JPEG Files (*.jpg;*.jpeg)|*.jpg;*.jpeg") 
 873             wxStringTokenizer strTok
; 
 875             strTok
.SetString(m_currentFilterStr
,wxT(";")); 
 876             while(strTok
.HasMoreTokens()) 
 878                 curFilter 
= strTok
.GetNextToken(); 
 879                 if (d
.GetFirst(& eachFilename
, curFilter
, style
)) 
 883                         if ((eachFilename 
!= wxT(".")) && (eachFilename 
!= wxT(".."))) 
 885                             filenames
.Add(eachFilename
); 
 888                     while (d
.GetNext(& eachFilename
)); 
 892         filenames
.Sort(wxDirCtrlStringCompareFunction
); 
 895     // Add the sorted dirs 
 897     for (i 
= 0; i 
< dirs
.GetCount(); i
++) 
 899         eachFilename 
= dirs
[i
]; 
 901         if (!wxEndsWithPathSeparator(path
)) 
 902             path 
+= wxString(wxFILE_SEP_PATH
); 
 903         path 
+= eachFilename
; 
 905         wxDirItemData 
*dir_item 
= new wxDirItemData(path
,eachFilename
,true); 
 906         wxTreeItemId id 
= AppendItem( parentId
, eachFilename
, 
 907                                       wxFileIconsTable::folder
, -1, dir_item
); 
 908         m_treeCtrl
->SetItemImage( id
, wxFileIconsTable::folder_open
, 
 909                                   wxTreeItemIcon_Expanded 
); 
 911         // assume that it does have children by default as it can take a long 
 912         // time to really check for this (think remote drives...) 
 914         // and if we're wrong, we'll correct it later in OnExpandItem() if 
 915         // the user really tries to open this item 
 916         m_treeCtrl
->SetItemHasChildren(id
); 
 919     // Add the sorted filenames 
 920     if (!HasFlag(wxDIRCTRL_DIR_ONLY
)) 
 922         for (i 
= 0; i 
< filenames
.GetCount(); i
++) 
 924             eachFilename 
= filenames
[i
]; 
 926             if (!wxEndsWithPathSeparator(path
)) 
 927                 path 
+= wxString(wxFILE_SEP_PATH
); 
 928             path 
+= eachFilename
; 
 929             //path = dirName + wxString(wxT("/")) + eachFilename; 
 930             wxDirItemData 
*dir_item 
= new wxDirItemData(path
,eachFilename
,false); 
 931             int image_id 
= wxFileIconsTable::file
; 
 932             if (eachFilename
.Find(wxT('.')) != wxNOT_FOUND
) 
 933                 image_id 
= wxTheFileIconsTable
->GetIconID(eachFilename
.AfterLast(wxT('.'))); 
 934             (void) AppendItem( parentId
, eachFilename
, image_id
, -1, dir_item
); 
 939 void wxGenericDirCtrl::ReCreateTree() 
 941     CollapseDir(m_treeCtrl
->GetRootItem()); 
 945 void wxGenericDirCtrl::CollapseTree() 
 947     wxTreeItemIdValue cookie
; 
 948     wxTreeItemId child 
= m_treeCtrl
->GetFirstChild(m_rootId
, cookie
); 
 952         child 
= m_treeCtrl
->GetNextChild(m_rootId
, cookie
); 
 956 // Find the child that matches the first part of 'path'. 
 957 // E.g. if a child path is "/usr" and 'path' is "/usr/include" 
 958 // then the child for /usr is returned. 
 959 wxTreeItemId 
wxGenericDirCtrl::FindChild(wxTreeItemId parentId
, const wxString
& path
, bool& done
) 
 961     wxString 
path2(path
); 
 963     // Make sure all separators are as per the current platform 
 964     path2
.Replace(wxT("\\"), wxString(wxFILE_SEP_PATH
)); 
 965     path2
.Replace(wxT("/"), wxString(wxFILE_SEP_PATH
)); 
 967     // Append a separator to foil bogus substring matching 
 968     path2 
+= wxString(wxFILE_SEP_PATH
); 
 970     // In MSW or PM, case is not significant 
 971 #if defined(__WINDOWS__) || defined(__DOS__) || defined(__OS2__) 
 975     wxTreeItemIdValue cookie
; 
 976     wxTreeItemId childId 
= m_treeCtrl
->GetFirstChild(parentId
, cookie
); 
 977     while (childId
.IsOk()) 
 979         wxDirItemData
* data 
= (wxDirItemData
*) m_treeCtrl
->GetItemData(childId
); 
 981         if (data 
&& !data
->m_path
.empty()) 
 983             wxString 
childPath(data
->m_path
); 
 984             if (!wxEndsWithPathSeparator(childPath
)) 
 985                 childPath 
+= wxString(wxFILE_SEP_PATH
); 
 987             // In MSW and PM, case is not significant 
 988 #if defined(__WINDOWS__) || defined(__DOS__) || defined(__OS2__) 
 989             childPath
.MakeLower(); 
 992             if (childPath
.length() <= path2
.length()) 
 994                 wxString path3 
= path2
.Mid(0, childPath
.length()); 
 995                 if (childPath 
== path3
) 
 997                     if (path3
.length() == path2
.length()) 
1006         childId 
= m_treeCtrl
->GetNextChild(parentId
, cookie
); 
1008     wxTreeItemId invalid
; 
1012 // Try to expand as much of the given path as possible, 
1013 // and select the given tree item. 
1014 bool wxGenericDirCtrl::ExpandPath(const wxString
& path
) 
1017     wxTreeItemId id 
= FindChild(m_rootId
, path
, done
); 
1018     wxTreeItemId lastId 
= id
; // The last non-zero id 
1019     while (id
.IsOk() && !done
) 
1023         id 
= FindChild(id
, path
, done
); 
1030     wxDirItemData 
*data 
= (wxDirItemData 
*) m_treeCtrl
->GetItemData(lastId
); 
1033         m_treeCtrl
->Expand(lastId
); 
1035     if (HasFlag(wxDIRCTRL_SELECT_FIRST
) && data
->m_isDir
) 
1037         // Find the first file in this directory 
1038         wxTreeItemIdValue cookie
; 
1039         wxTreeItemId childId 
= m_treeCtrl
->GetFirstChild(lastId
, cookie
); 
1040         bool selectedChild 
= false; 
1041         while (childId
.IsOk()) 
1043             data 
= (wxDirItemData
*) m_treeCtrl
->GetItemData(childId
); 
1045             if (data 
&& data
->m_path 
!= wxEmptyString 
&& !data
->m_isDir
) 
1047                 m_treeCtrl
->SelectItem(childId
); 
1048                 m_treeCtrl
->EnsureVisible(childId
); 
1049                 selectedChild 
= true; 
1052             childId 
= m_treeCtrl
->GetNextChild(lastId
, cookie
); 
1056             m_treeCtrl
->SelectItem(lastId
); 
1057             m_treeCtrl
->EnsureVisible(lastId
); 
1062         m_treeCtrl
->SelectItem(lastId
); 
1063         m_treeCtrl
->EnsureVisible(lastId
); 
1070 bool wxGenericDirCtrl::CollapsePath(const wxString
& path
) 
1073     wxTreeItemId id     
= FindChild(m_rootId
, path
, done
); 
1074     wxTreeItemId lastId 
= id
; // The last non-zero id 
1076     while ( id
.IsOk() && !done 
) 
1080         id 
= FindChild(id
, path
, done
); 
1086     if ( !lastId
.IsOk() ) 
1089     m_treeCtrl
->SelectItem(lastId
); 
1090     m_treeCtrl
->EnsureVisible(lastId
); 
1096 wxString 
wxGenericDirCtrl::GetPath() const 
1098     // Allow calling GetPath() in multiple selection from OnSelFilter 
1099     if (m_treeCtrl
->HasFlag(wxTR_MULTIPLE
)) 
1101         wxArrayTreeItemIds items
; 
1102         m_treeCtrl
->GetSelections(items
); 
1103         if (items
.size() > 0) 
1105             // return first string only 
1106             wxTreeItemId id 
= items
[0]; 
1107             wxDirItemData
* data 
= (wxDirItemData
*) m_treeCtrl
->GetItemData(id
); 
1108             return data
->m_path
; 
1111         return wxEmptyString
; 
1114     wxTreeItemId id 
= m_treeCtrl
->GetSelection(); 
1117         wxDirItemData
* data 
= (wxDirItemData
*) m_treeCtrl
->GetItemData(id
); 
1118         return data
->m_path
; 
1121         return wxEmptyString
; 
1124 void wxGenericDirCtrl::GetPaths(wxArrayString
& paths
) const 
1128     wxArrayTreeItemIds items
; 
1129     m_treeCtrl
->GetSelections(items
); 
1130     for ( unsigned n 
= 0; n 
< items
.size(); n
++ ) 
1132         wxTreeItemId id 
= items
[n
]; 
1133         wxDirItemData
* data 
= (wxDirItemData
*) m_treeCtrl
->GetItemData(id
); 
1134         paths
.Add(data
->m_path
); 
1138 wxString 
wxGenericDirCtrl::GetFilePath() const 
1140     wxTreeItemId id 
= m_treeCtrl
->GetSelection(); 
1143         wxDirItemData
* data 
= (wxDirItemData
*) m_treeCtrl
->GetItemData(id
); 
1145             return wxEmptyString
; 
1147             return data
->m_path
; 
1150         return wxEmptyString
; 
1153 void wxGenericDirCtrl::GetFilePaths(wxArrayString
& paths
) const 
1157     wxArrayTreeItemIds items
; 
1158     m_treeCtrl
->GetSelections(items
); 
1159     for ( unsigned n 
= 0; n 
< items
.size(); n
++ ) 
1161         wxTreeItemId id 
= items
[n
]; 
1162         wxDirItemData
* data 
= (wxDirItemData
*) m_treeCtrl
->GetItemData(id
); 
1163         if ( !data
->m_isDir 
) 
1164             paths
.Add(data
->m_path
); 
1168 void wxGenericDirCtrl::SetPath(const wxString
& path
) 
1170     m_defaultPath 
= path
; 
1175 void wxGenericDirCtrl::SelectPath(const wxString
& path
, bool select
) 
1178     wxTreeItemId id 
= FindChild(m_rootId
, path
, done
); 
1179     wxTreeItemId lastId 
= id
; // The last non-zero id 
1180     while ( id
.IsOk() && !done 
) 
1182         id 
= FindChild(id
, path
, done
); 
1186     if ( !lastId
.IsOk() ) 
1191         m_treeCtrl
->SelectItem(id
, select
); 
1195 void wxGenericDirCtrl::SelectPaths(const wxArrayString
& paths
) 
1197     if ( HasFlag(wxDIRCTRL_MULTIPLE
) ) 
1200         for ( unsigned n 
= 0; n 
< paths
.size(); n
++ ) 
1202             SelectPath(paths
[n
]); 
1207 void wxGenericDirCtrl::UnselectAll() 
1209     m_treeCtrl
->UnselectAll(); 
1214 void wxGenericDirCtrl::FindChildFiles(wxTreeItemId id
, int dirFlags
, wxArrayString
& filenames
) 
1216     wxDirItemData 
*data 
= (wxDirItemData 
*) m_treeCtrl
->GetItemData(id
); 
1218     // This may take a longish time. Go to busy cursor 
1223     wxString search
,path
,filename
; 
1225     wxString 
dirName(data
->m_path
); 
1227 #if defined(__WXMSW__) || defined(__OS2__) 
1228     if (dirName
.Last() == ':') 
1229         dirName 
+= wxString(wxFILE_SEP_PATH
); 
1233     wxString eachFilename
; 
1240         if (d
.GetFirst(& eachFilename
, m_currentFilterStr
, dirFlags
)) 
1244                 if ((eachFilename 
!= wxT(".")) && (eachFilename 
!= wxT(".."))) 
1246                     filenames
.Add(eachFilename
); 
1249             while (d
.GetNext(& eachFilename
)) ; 
1255 void wxGenericDirCtrl::SetFilterIndex(int n
) 
1257     m_currentFilter 
= n
; 
1260     if (ExtractWildcard(m_filter
, n
, f
, d
)) 
1261         m_currentFilterStr 
= f
; 
1264         m_currentFilterStr 
= wxT("*"); 
1266         m_currentFilterStr 
= wxT("*.*"); 
1270 void wxGenericDirCtrl::SetFilter(const wxString
& filter
) 
1274     if (!filter
.empty() && !m_filterListCtrl
) 
1275         m_filterListCtrl 
= new wxDirFilterListCtrl(this, wxID_FILTERLISTCTRL
); 
1276     else if (filter
.empty() && m_filterListCtrl
) 
1278         m_filterListCtrl
->Destroy(); 
1279         m_filterListCtrl 
= NULL
; 
1283     if (ExtractWildcard(m_filter
, m_currentFilter
, f
, d
)) 
1284         m_currentFilterStr 
= f
; 
1287         m_currentFilterStr 
= wxT("*"); 
1289         m_currentFilterStr 
= wxT("*.*"); 
1291     // current filter index is meaningless after filter change, set it to zero 
1293     if (m_filterListCtrl
) 
1294         m_filterListCtrl
->FillFilterList(m_filter
, 0); 
1297 // Extract description and actual filter from overall filter string 
1298 bool wxGenericDirCtrl::ExtractWildcard(const wxString
& filterStr
, int n
, wxString
& filter
, wxString
& description
) 
1300     wxArrayString filters
, descriptions
; 
1301     int count 
= wxParseCommonDialogsFilter(filterStr
, descriptions
, filters
); 
1302     if (count 
> 0 && n 
< count
) 
1304         filter 
= filters
[n
]; 
1305         description 
= descriptions
[n
]; 
1313 void wxGenericDirCtrl::DoResize() 
1315     wxSize sz 
= GetClientSize(); 
1316     int verticalSpacing 
= 3; 
1320         if (m_filterListCtrl
) 
1322             filterSz 
= m_filterListCtrl
->GetSize(); 
1323             sz
.y 
-= (filterSz
.y 
+ verticalSpacing
); 
1325         m_treeCtrl
->SetSize(0, 0, sz
.x
, sz
.y
); 
1326         if (m_filterListCtrl
) 
1328             m_filterListCtrl
->SetSize(0, sz
.y 
+ verticalSpacing
, sz
.x
, filterSz
.y
); 
1329             // Don't know why, but this needs refreshing after a resize (wxMSW) 
1330             m_filterListCtrl
->Refresh(); 
1336 void wxGenericDirCtrl::OnSize(wxSizeEvent
& WXUNUSED(event
)) 
1341 wxTreeItemId 
wxGenericDirCtrl::AppendItem (const wxTreeItemId 
& parent
, 
1342                                            const wxString 
& text
, 
1343                                            int image
, int selectedImage
, 
1344                                            wxTreeItemData 
* data
) 
1346   wxTreeCtrl 
*treeCtrl 
= GetTreeCtrl (); 
1348   wxASSERT (treeCtrl
); 
1352     return treeCtrl
->AppendItem (parent
, text
, image
, selectedImage
, data
); 
1356     return wxTreeItemId(); 
1361 //----------------------------------------------------------------------------- 
1362 // wxDirFilterListCtrl 
1363 //----------------------------------------------------------------------------- 
1365 IMPLEMENT_CLASS(wxDirFilterListCtrl
, wxChoice
) 
1367 BEGIN_EVENT_TABLE(wxDirFilterListCtrl
, wxChoice
) 
1368     EVT_CHOICE(wxID_ANY
, wxDirFilterListCtrl::OnSelFilter
) 
1371 bool wxDirFilterListCtrl::Create(wxGenericDirCtrl
* parent
, 
1372                                  const wxWindowID id
, 
1379     // by default our border style is determined by the style of our parent 
1380     if ( !(style 
& wxBORDER_MASK
) ) 
1382         style 
|= parent
->HasFlag(wxDIRCTRL_3D_INTERNAL
) ? wxBORDER_SUNKEN
 
1386     return wxChoice::Create(parent
, id
, pos
, size
, 0, NULL
, style
); 
1389 void wxDirFilterListCtrl::Init() 
1394 void wxDirFilterListCtrl::OnSelFilter(wxCommandEvent
& WXUNUSED(event
)) 
1396     int sel 
= GetSelection(); 
1398     if (m_dirCtrl
->HasFlag(wxDIRCTRL_MULTIPLE
)) 
1400         wxArrayString paths
; 
1401         m_dirCtrl
->GetPaths(paths
); 
1403         m_dirCtrl
->SetFilterIndex(sel
); 
1405         // If the filter has changed, the view is out of date, so 
1406         // collapse the tree. 
1407         m_dirCtrl
->ReCreateTree(); 
1409         // Expand and select the previously selected paths 
1410         for (unsigned int i 
= 0; i 
< paths
.GetCount(); i
++) 
1412             m_dirCtrl
->ExpandPath(paths
.Item(i
)); 
1417         wxString currentPath 
= m_dirCtrl
->GetPath(); 
1419         m_dirCtrl
->SetFilterIndex(sel
); 
1420         m_dirCtrl
->ReCreateTree(); 
1422         // Try to restore the selection, or at least the directory 
1423         m_dirCtrl
->ExpandPath(currentPath
); 
1427 void wxDirFilterListCtrl::FillFilterList(const wxString
& filter
, int defaultFilter
) 
1430     wxArrayString descriptions
, filters
; 
1431     size_t n 
= (size_t) wxParseCommonDialogsFilter(filter
, descriptions
, filters
); 
1433     if (n 
> 0 && defaultFilter 
< (int) n
) 
1435         for (size_t i 
= 0; i 
< n
; i
++) 
1436             Append(descriptions
[i
]); 
1437         SetSelection(defaultFilter
); 
1440 #endif // wxUSE_DIRDLG 
1442 #if wxUSE_DIRDLG || wxUSE_FILEDLG 
1444 // ---------------------------------------------------------------------------- 
1445 // wxFileIconsTable icons 
1446 // ---------------------------------------------------------------------------- 
1449 /* Computer (c) Julian Smart */ 
1450 static const char* const file_icons_tbl_computer_xpm
[] = { 
1451 /* columns rows colors chars-per-pixel */ 
1515 // ---------------------------------------------------------------------------- 
1516 // wxFileIconsTable & friends 
1517 // ---------------------------------------------------------------------------- 
1519 // global instance of a wxFileIconsTable 
1520 wxFileIconsTable
* wxTheFileIconsTable 
= NULL
; 
1522 // A module to allow icons table cleanup 
1524 class wxFileIconsTableModule
: public wxModule
 
1526 DECLARE_DYNAMIC_CLASS(wxFileIconsTableModule
) 
1528     wxFileIconsTableModule() {} 
1529     bool OnInit() { wxTheFileIconsTable 
= new wxFileIconsTable
; return true; } 
1532         wxDELETE(wxTheFileIconsTable
); 
1536 IMPLEMENT_DYNAMIC_CLASS(wxFileIconsTableModule
, wxModule
) 
1538 class wxFileIconEntry 
: public wxObject
 
1541     wxFileIconEntry(int i
) { id 
= i
; } 
1546 wxFileIconsTable::wxFileIconsTable() 
1549     m_smallImageList 
= NULL
; 
1552 wxFileIconsTable::~wxFileIconsTable() 
1556         WX_CLEAR_HASH_TABLE(*m_HashTable
); 
1559     if (m_smallImageList
) delete m_smallImageList
; 
1562 // delayed initialization - wait until first use (wxArtProv not created yet) 
1563 void wxFileIconsTable::Create() 
1565     wxCHECK_RET(!m_smallImageList 
&& !m_HashTable
, wxT("creating icons twice")); 
1566     m_HashTable 
= new wxHashTable(wxKEY_STRING
); 
1567     m_smallImageList 
= new wxImageList(16, 16); 
1570     m_smallImageList
->Add(wxArtProvider::GetBitmap(wxART_FOLDER
, 
1574     m_smallImageList
->Add(wxArtProvider::GetBitmap(wxART_FOLDER_OPEN
, 
1579     // GTK24 uses this icon in the file open dialog 
1580     m_smallImageList
->Add(wxArtProvider::GetBitmap(wxART_HARDDISK
, 
1584     m_smallImageList
->Add(wxIcon(file_icons_tbl_computer_xpm
)); 
1587     m_smallImageList
->Add(wxArtProvider::GetBitmap(wxART_HARDDISK
, 
1591     m_smallImageList
->Add(wxArtProvider::GetBitmap(wxART_CDROM
, 
1595     m_smallImageList
->Add(wxArtProvider::GetBitmap(wxART_FLOPPY
, 
1599     m_smallImageList
->Add(wxArtProvider::GetBitmap(wxART_REMOVABLE
, 
1603     m_smallImageList
->Add(wxArtProvider::GetBitmap(wxART_NORMAL_FILE
, 
1607     if (GetIconID(wxEmptyString
, wxT("application/x-executable")) == file
) 
1609         m_smallImageList
->Add(wxArtProvider::GetBitmap(wxART_EXECUTABLE_FILE
, 
1612         delete m_HashTable
->Get(wxT("exe")); 
1613         m_HashTable
->Delete(wxT("exe")); 
1614         m_HashTable
->Put(wxT("exe"), new wxFileIconEntry(executable
)); 
1616     /* else put into list by GetIconID 
1617        (KDE defines application/x-executable for *.exe and has nice icon) 
1621 wxImageList 
*wxFileIconsTable::GetSmallImageList() 
1623     if (!m_smallImageList
) 
1626     return m_smallImageList
; 
1629 #if wxUSE_MIMETYPE && wxUSE_IMAGE && (!defined(__WXMSW__) || wxUSE_WXDIB) 
1630 // VS: we don't need this function w/o wxMimeTypesManager because we'll only have 
1631 //     one icon and we won't resize it 
1633 static wxBitmap 
CreateAntialiasedBitmap(const wxImage
& img
) 
1635     const unsigned int size 
= 16; 
1637     wxImage 
smallimg (size
, size
); 
1638     unsigned char *p1
, *p2
, *ps
; 
1639     unsigned char mr 
= img
.GetMaskRed(), 
1640                   mg 
= img
.GetMaskGreen(), 
1641                   mb 
= img
.GetMaskBlue(); 
1644     unsigned sr
, sg
, sb
, smask
; 
1646     p1 
= img
.GetData(), p2 
= img
.GetData() + 3 * size
*2, ps 
= smallimg
.GetData(); 
1647     smallimg
.SetMaskColour(mr
, mr
, mr
); 
1649     for (y 
= 0; y 
< size
; y
++) 
1651         for (x 
= 0; x 
< size
; x
++) 
1653             sr 
= sg 
= sb 
= smask 
= 0; 
1654             if (p1
[0] != mr 
|| p1
[1] != mg 
|| p1
[2] != mb
) 
1655                 sr 
+= p1
[0], sg 
+= p1
[1], sb 
+= p1
[2]; 
1658             if (p1
[0] != mr 
|| p1
[1] != mg 
|| p1
[2] != mb
) 
1659                 sr 
+= p1
[0], sg 
+= p1
[1], sb 
+= p1
[2]; 
1662             if (p2
[0] != mr 
|| p2
[1] != mg 
|| p2
[2] != mb
) 
1663                 sr 
+= p2
[0], sg 
+= p2
[1], sb 
+= p2
[2]; 
1666             if (p2
[0] != mr 
|| p2
[1] != mg 
|| p2
[2] != mb
) 
1667                 sr 
+= p2
[0], sg 
+= p2
[1], sb 
+= p2
[2]; 
1672                 ps
[0] = ps
[1] = ps
[2] = mr
; 
1675                 ps
[0] = (unsigned char)(sr 
>> 2); 
1676                 ps
[1] = (unsigned char)(sg 
>> 2); 
1677                 ps
[2] = (unsigned char)(sb 
>> 2); 
1681         p1 
+= size
*2 * 3, p2 
+= size
*2 * 3; 
1684     return wxBitmap(smallimg
); 
1687 // This function is currently not unused anymore 
1689 // finds empty borders and return non-empty area of image: 
1690 static wxImage 
CutEmptyBorders(const wxImage
& img
) 
1692     unsigned char mr 
= img
.GetMaskRed(), 
1693                   mg 
= img
.GetMaskGreen(), 
1694                   mb 
= img
.GetMaskBlue(); 
1695     unsigned char *dt 
= img
.GetData(), *dttmp
; 
1696     unsigned w 
= img
.GetWidth(), h 
= img
.GetHeight(); 
1698     unsigned top
, bottom
, left
, right
, i
; 
1701 #define MK_DTTMP(x,y)      dttmp = dt + ((x + y * w) * 3) 
1702 #define NOEMPTY_PIX(empt)  if (dttmp[0] != mr || dttmp[1] != mg || dttmp[2] != mb) {empt = false; break;} 
1704     for (empt 
= true, top 
= 0; empt 
&& top 
< h
; top
++) 
1707         for (i 
= 0; i 
< w
; i
++, dttmp
+=3) 
1710     for (empt 
= true, bottom 
= h
-1; empt 
&& bottom 
> top
; bottom
--) 
1712         MK_DTTMP(0, bottom
); 
1713         for (i 
= 0; i 
< w
; i
++, dttmp
+=3) 
1716     for (empt 
= true, left 
= 0; empt 
&& left 
< w
; left
++) 
1719         for (i 
= 0; i 
< h
; i
++, dttmp
+=3*w
) 
1722     for (empt 
= true, right 
= w
-1; empt 
&& right 
> left
; right
--) 
1725         for (i 
= 0; i 
< h
; i
++, dttmp
+=3*w
) 
1728     top
--, left
--, bottom
++, right
++; 
1730     return img
.GetSubImage(wxRect(left
, top
, right 
- left 
+ 1, bottom 
- top 
+ 1)); 
1734 #endif // wxUSE_MIMETYPE 
1736 int wxFileIconsTable::GetIconID(const wxString
& extension
, const wxString
& mime
) 
1738     if (!m_smallImageList
) 
1742     if (!extension
.empty()) 
1744         wxFileIconEntry 
*entry 
= (wxFileIconEntry
*) m_HashTable
->Get(extension
); 
1745         if (entry
) return (entry 
-> id
); 
1748     wxFileType 
*ft 
= (mime
.empty()) ? 
1749                    wxTheMimeTypesManager 
-> GetFileTypeFromExtension(extension
) : 
1750                    wxTheMimeTypesManager 
-> GetFileTypeFromMimeType(mime
); 
1752     wxIconLocation iconLoc
; 
1757         if ( ft 
&& ft
->GetIcon(&iconLoc
) ) 
1759             ic 
= wxIcon( iconLoc 
); 
1768         m_HashTable
->Put(extension
, new wxFileIconEntry(newid
)); 
1773     bmp
.CopyFromIcon(ic
); 
1778         m_HashTable
->Put(extension
, new wxFileIconEntry(newid
)); 
1782     const unsigned int size 
= 16; 
1784     int id 
= m_smallImageList
->GetImageCount(); 
1785     if ((bmp
.GetWidth() == (int) size
) && (bmp
.GetHeight() == (int) size
)) 
1787         m_smallImageList
->Add(bmp
); 
1789 #if wxUSE_IMAGE && (!defined(__WXMSW__) || wxUSE_WXDIB) 
1792         wxImage img 
= bmp
.ConvertToImage(); 
1794         if ((img
.GetWidth() != size
*2) || (img
.GetHeight() != size
*2)) 
1795 //            m_smallImageList->Add(CreateAntialiasedBitmap(CutEmptyBorders(img).Rescale(size*2, size*2))); 
1796             m_smallImageList
->Add(CreateAntialiasedBitmap(img
.Rescale(size
*2, size
*2))); 
1798             m_smallImageList
->Add(CreateAntialiasedBitmap(img
)); 
1800 #endif // wxUSE_IMAGE 
1802     m_HashTable
->Put(extension
, new wxFileIconEntry(id
)); 
1805 #else // !wxUSE_MIMETYPE 
1808     if (extension 
== wxT("exe")) 
1812 #endif // wxUSE_MIMETYPE/!wxUSE_MIMETYPE 
1815 #endif // wxUSE_DIRDLG || wxUSE_FILEDLG