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" 
  41 #include "wx/module.h" 
  42 #include "wx/filefn.h" 
  43 #include "wx/imaglist.h" 
  44 #include "wx/tokenzr.h" 
  46 #include "wx/artprov.h" 
  47 #include "wx/mimetype.h" 
  51     #include "wx/statline.h" 
  54 #if defined(__WXMAC__) 
  55     #include  "wx/mac/private.h"  // includes mac headers 
  60 #include "wx/msw/winundef.h" 
  62 // FIXME - Mingw32 1.0 has both _getdrive() and _chdrive(). For now, let's assume 
  63 //         older releases don't, but it should be verified and the checks modified 
  65 #if !defined(__GNUWIN32__) || (defined(__MINGW32_MAJOR_VERSION) && __MINGW32_MAJOR_VERSION >= 1) 
  66 #if !defined(__WXWINCE__) 
  75 #if defined(__OS2__) || defined(__DOS__) 
  85     extern bool wxIsDriveAvailable(const wxString
& dirName
); 
  88 #if defined(__WXMAC__) 
  89     #include "MoreFilesX.h" 
  96 // If compiled under Windows, this macro can cause problems 
 101 // ---------------------------------------------------------------------------- 
 102 // wxGetAvailableDrives, for WINDOWS, DOS, OS2, MAC, UNIX (returns "/") 
 103 // ---------------------------------------------------------------------------- 
 105 size_t wxGetAvailableDrives(wxArrayString 
&paths
, wxArrayString 
&names
, wxArrayInt 
&icon_ids
) 
 107 #if defined(__WINDOWS__) || defined(__DOS__) || defined(__OS2__) 
 110     // No logical drives; return "\" 
 111     paths
.Add(wxT("\\")); 
 112     names
.Add(wxT("\\")); 
 113     icon_ids
.Add(wxFileIconsTable::computer
); 
 114 #elif defined(__WIN32__) 
 115     wxChar driveBuffer
[256]; 
 116     size_t n 
= (size_t) GetLogicalDriveStrings(255, driveBuffer
); 
 121         path
.Printf(wxT("%c:\\"), driveBuffer
[i
]); 
 122         name
.Printf(wxT("%c:"), driveBuffer
[i
]); 
 124 #if !defined(__WXWINCE__) 
 125         wxChar pname
[52]; // FIXME: why 52 and not MAX_PATH or whatever? 
 126         if ( GetVolumeInformation(path
, pname
, WXSIZEOF(pname
), 
 127                                   NULL
, NULL
, NULL
, NULL
, 0) ) 
 129             name 
<< _T(' ') << pname
; 
 131 #endif // __WXWINCE__ 
 134         int driveType 
= ::GetDriveType(path
); 
 137             case DRIVE_REMOVABLE
: 
 138                 if (path 
== wxT("a:\\") || path 
== wxT("b:\\")) 
 139                     imageId 
= wxFileIconsTable::floppy
; 
 141                     imageId 
= wxFileIconsTable::removeable
; 
 144                 imageId 
= wxFileIconsTable::cdrom
; 
 149                 imageId 
= wxFileIconsTable::drive
; 
 155         icon_ids
.Add(imageId
); 
 157         while (driveBuffer
[i
] != wxT('\0')) 
 160         if (driveBuffer
[i
] == wxT('\0')) 
 163 #elif defined(__OS2__) 
 165     ULONG ulDriveNum 
= 0; 
 166     ULONG ulDriveMap 
= 0; 
 167     rc 
= ::DosQueryCurrentDisk(&ulDriveNum
, &ulDriveMap
); 
 173             if (ulDriveMap 
& ( 1 << i 
)) 
 176                 path
.Printf(wxT("%c:\\"), 'A' + i
); 
 177                 name
.Printf(wxT("%c:"), 'A' + i
); 
 179                 // Note: If _filesys is unsupported by some compilers, 
 180                 //       we can always replace it by DosQueryFSAttach 
 181                 char filesysname
[20]; 
 183                 ULONG cbBuffer 
= sizeof(filesysname
); 
 184                 PFSQBUFFER2 pfsqBuffer 
= (PFSQBUFFER2
)filesysname
; 
 185                 APIRET rc 
= ::DosQueryFSAttach(name
.fn_str(),0,FSAIL_QUERYNAME
,pfsqBuffer
,&cbBuffer
); 
 188                     filesysname
[0] = '\0'; 
 191                 _filesys(name
.fn_str(), filesysname
, sizeof(filesysname
)); 
 193                 /* FAT, LAN, HPFS, CDFS, NFS */ 
 195                 if (path 
== wxT("A:\\") || path 
== wxT("B:\\")) 
 196                     imageId 
= wxFileIconsTable::floppy
; 
 197                 else if (!strcmp(filesysname
, "CDFS")) 
 198                     imageId 
= wxFileIconsTable::cdrom
; 
 199                 else if (!strcmp(filesysname
, "LAN") || 
 200                          !strcmp(filesysname
, "NFS")) 
 201                     imageId 
= wxFileIconsTable::drive
; 
 203                     imageId 
= wxFileIconsTable::drive
; 
 206                 icon_ids
.Add(imageId
); 
 211 #else // !__WIN32__, !__OS2__ 
 214     /* If we can switch to the drive, it exists. */ 
 215     for( drive 
= 1; drive 
<= 26; drive
++ ) 
 218         path
.Printf(wxT("%c:\\"), (char) (drive 
+ 'a' - 1)); 
 219         name
.Printf(wxT("%c:"), (char) (drive 
+ 'A' - 1)); 
 221         if (wxIsDriveAvailable(path
)) 
 225             icon_ids
.Add((drive 
<= 2) ? wxFileIconsTable::floppy 
: wxFileIconsTable::drive
); 
 228 #endif // __WIN32__/!__WIN32__ 
 230 #elif defined(__WXMAC__) 
 232     ItemCount volumeIndex 
= 1; 
 235     while( noErr 
== err 
) 
 237         HFSUniStr255 volumeName 
; 
 239         FSVolumeInfo volumeInfo 
; 
 240         err 
= FSGetVolumeInfo(0, volumeIndex
, NULL
, kFSVolInfoFlags 
, &volumeInfo 
, &volumeName
, &fsRef
); 
 243             wxString path 
= wxMacFSRefToPath( &fsRef 
) ; 
 244             wxString name 
= wxMacHFSUniStrToString( &volumeName 
) ; 
 246             if ( (volumeInfo
.flags 
& kFSVolFlagSoftwareLockedMask
) || (volumeInfo
.flags 
& kFSVolFlagHardwareLockedMask
) ) 
 248                 icon_ids
.Add(wxFileIconsTable::cdrom
); 
 252                 icon_ids
.Add(wxFileIconsTable::drive
); 
 254             // todo other removable 
 262 #elif defined(__UNIX__) 
 265     icon_ids
.Add(wxFileIconsTable::computer
); 
 267     #error "Unsupported platform in wxGenericDirCtrl!" 
 269     wxASSERT_MSG( (paths
.GetCount() == names
.GetCount()), wxT("The number of paths and their human readable names should be equal in number.")); 
 270     wxASSERT_MSG( (paths
.GetCount() == icon_ids
.GetCount()), wxT("Wrong number of icons for available drives.")); 
 271     return paths
.GetCount(); 
 274 // ---------------------------------------------------------------------------- 
 275 // wxIsDriveAvailable 
 276 // ---------------------------------------------------------------------------- 
 280 bool wxIsDriveAvailable(const wxString
& dirName
) 
 282     // FIXME_MGL - this method leads to hang up under Watcom for some reason 
 284     wxUnusedVar(dirName
); 
 286     if ( dirName
.length() == 3 && dirName
[1u] == wxT(':') ) 
 288         wxString 
dirNameLower(dirName
.Lower()); 
 289         // VS: always return true for removable media, since Win95 doesn't 
 290         //     like it when MS-DOS app accesses empty floppy drive 
 291         return (dirNameLower
[0u] == wxT('a') || 
 292                 dirNameLower
[0u] == wxT('b') || 
 293                 wxDirExists(dirNameLower
)); 
 300 #elif defined(__WINDOWS__) || defined(__OS2__) 
 302 int setdrive(int WXUNUSED_IN_WINCE(drive
)) 
 306 #elif defined(__GNUWIN32__) && \ 
 307     (defined(__MINGW32_MAJOR_VERSION) && __MINGW32_MAJOR_VERSION >= 1) 
 308     return _chdrive(drive
); 
 312     if (drive 
< 1 || drive 
> 31) 
 314     newdrive
[0] = (wxChar
)(wxT('A') + drive 
- 1); 
 315     newdrive
[1] = wxT(':'); 
 317     newdrive
[2] = wxT('\\'); 
 318     newdrive
[3] = wxT('\0'); 
 320     newdrive
[2] = wxT('\0'); 
 322 #if defined(__WXMSW__) 
 323     if (::SetCurrentDirectory(newdrive
)) 
 325     // VA doesn't know what LPSTR is and has its own set 
 326     if (!DosSetCurrentDir((PSZ
)newdrive
)) 
 334 bool wxIsDriveAvailable(const wxString
& WXUNUSED_IN_WINCE(dirName
)) 
 340     UINT errorMode 
= SetErrorMode(SEM_FAILCRITICALERRORS 
| SEM_NOOPENFILEERRORBOX
); 
 344     // Check if this is a root directory and if so, 
 345     // whether the drive is available. 
 346     if (dirName
.length() == 3 && dirName
[(size_t)1] == wxT(':')) 
 348         wxString 
dirNameLower(dirName
.Lower()); 
 349 #if defined(__GNUWIN32__) && !(defined(__MINGW32_MAJOR_VERSION) && __MINGW32_MAJOR_VERSION >= 1) 
 350         success 
= wxDirExists(dirNameLower
); 
 353         // Avoid changing to drive since no media may be inserted. 
 354         if (dirNameLower
[(size_t)0] == 'a' || dirNameLower
[(size_t)0] == 'b') 
 357         int currentDrive 
= _getdrive(); 
 358         int thisDrive 
= (int) (dirNameLower
[(size_t)0] - 'a' + 1) ; 
 359         int err 
= setdrive( thisDrive 
) ; 
 360         setdrive( currentDrive 
); 
 369     (void) SetErrorMode(errorMode
); 
 375 #endif // __WINDOWS__ || __OS2__ 
 377 #endif // wxUSE_DIRDLG || wxUSE_FILEDLG 
 383 // Function which is called by quick sort. We want to override the default wxArrayString behaviour, 
 384 // and sort regardless of case. 
 385 static int wxCMPFUNC_CONV 
wxDirCtrlStringCompareFunction(const wxString
& strFirst
, const wxString
& strSecond
) 
 387     return strFirst
.CmpNoCase(strSecond
); 
 390 //----------------------------------------------------------------------------- 
 392 //----------------------------------------------------------------------------- 
 394 wxDirItemData::wxDirItemData(const wxString
& path
, const wxString
& name
, 
 399     /* Insert logic to detect hidden files here 
 400      * In UnixLand we just check whether the first char is a dot 
 401      * For FileNameFromPath read LastDirNameInThisPath ;-) */ 
 402     // m_isHidden = (bool)(wxFileNameFromPath(*m_path)[0] == '.'); 
 404     m_isExpanded 
= false; 
 408 void wxDirItemData::SetNewDirName(const wxString
& path
) 
 411     m_name 
= wxFileNameFromPath(path
); 
 414 bool wxDirItemData::HasSubDirs() const 
 422         if ( !dir
.Open(m_path
) ) 
 426     return dir
.HasSubDirs(); 
 429 bool wxDirItemData::HasFiles(const wxString
& WXUNUSED(spec
)) const 
 437         if ( !dir
.Open(m_path
) ) 
 441     return dir
.HasFiles(); 
 444 //----------------------------------------------------------------------------- 
 446 //----------------------------------------------------------------------------- 
 449 #if wxUSE_EXTENDED_RTTI 
 450 WX_DEFINE_FLAGS( wxGenericDirCtrlStyle 
) 
 452 wxBEGIN_FLAGS( wxGenericDirCtrlStyle 
) 
 453     // new style border flags, we put them first to 
 454     // use them for streaming out 
 455     wxFLAGS_MEMBER(wxBORDER_SIMPLE
) 
 456     wxFLAGS_MEMBER(wxBORDER_SUNKEN
) 
 457     wxFLAGS_MEMBER(wxBORDER_DOUBLE
) 
 458     wxFLAGS_MEMBER(wxBORDER_RAISED
) 
 459     wxFLAGS_MEMBER(wxBORDER_STATIC
) 
 460     wxFLAGS_MEMBER(wxBORDER_NONE
) 
 462     // old style border flags 
 463     wxFLAGS_MEMBER(wxSIMPLE_BORDER
) 
 464     wxFLAGS_MEMBER(wxSUNKEN_BORDER
) 
 465     wxFLAGS_MEMBER(wxDOUBLE_BORDER
) 
 466     wxFLAGS_MEMBER(wxRAISED_BORDER
) 
 467     wxFLAGS_MEMBER(wxSTATIC_BORDER
) 
 468     wxFLAGS_MEMBER(wxBORDER
) 
 470     // standard window styles 
 471     wxFLAGS_MEMBER(wxTAB_TRAVERSAL
) 
 472     wxFLAGS_MEMBER(wxCLIP_CHILDREN
) 
 473     wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW
) 
 474     wxFLAGS_MEMBER(wxWANTS_CHARS
) 
 475     wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE
) 
 476     wxFLAGS_MEMBER(wxALWAYS_SHOW_SB 
) 
 477     wxFLAGS_MEMBER(wxVSCROLL
) 
 478     wxFLAGS_MEMBER(wxHSCROLL
) 
 480     wxFLAGS_MEMBER(wxDIRCTRL_DIR_ONLY
) 
 481     wxFLAGS_MEMBER(wxDIRCTRL_3D_INTERNAL
) 
 482     wxFLAGS_MEMBER(wxDIRCTRL_SELECT_FIRST
) 
 483     wxFLAGS_MEMBER(wxDIRCTRL_SHOW_FILTERS
) 
 485 wxEND_FLAGS( wxGenericDirCtrlStyle 
) 
 487 IMPLEMENT_DYNAMIC_CLASS_XTI(wxGenericDirCtrl
, wxControl
,"wx/dirctrl.h") 
 489 wxBEGIN_PROPERTIES_TABLE(wxGenericDirCtrl
) 
 490     wxHIDE_PROPERTY( Children 
) 
 491     wxPROPERTY( DefaultPath 
, wxString 
, SetDefaultPath 
, GetDefaultPath  
, EMPTY_MACROVALUE 
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) 
 492     wxPROPERTY( Filter 
, wxString 
, SetFilter 
, GetFilter  
, EMPTY_MACROVALUE 
, 0 /*flags*/ , wxT("Helpstring") , wxT("group") ) 
 493     wxPROPERTY( DefaultFilter 
, int , SetFilterIndex
, GetFilterIndex
, EMPTY_MACROVALUE 
, 0 /*flags*/ , wxT("Helpstring") , wxT("group") ) 
 494     wxPROPERTY_FLAGS( WindowStyle
, wxGenericDirCtrlStyle
, long, SetWindowStyleFlag
, GetWindowStyleFlag
, EMPTY_MACROVALUE 
, 0, wxT("Helpstring"), wxT("group") ) 
 495 wxEND_PROPERTIES_TABLE() 
 497 wxBEGIN_HANDLERS_TABLE(wxGenericDirCtrl
) 
 498 wxEND_HANDLERS_TABLE() 
 500 wxCONSTRUCTOR_8( wxGenericDirCtrl 
, wxWindow
* , Parent 
, wxWindowID 
, Id 
, wxString 
, DefaultPath 
, 
 501                  wxPoint 
, Position 
, wxSize 
, Size 
, long , WindowStyle 
, wxString 
, Filter 
, int , DefaultFilter 
) 
 503 IMPLEMENT_DYNAMIC_CLASS(wxGenericDirCtrl
, wxControl
) 
 506 BEGIN_EVENT_TABLE(wxGenericDirCtrl
, wxControl
) 
 507   EVT_TREE_ITEM_EXPANDING     (wxID_TREECTRL
, wxGenericDirCtrl::OnExpandItem
) 
 508   EVT_TREE_ITEM_COLLAPSED     (wxID_TREECTRL
, wxGenericDirCtrl::OnCollapseItem
) 
 509   EVT_TREE_BEGIN_LABEL_EDIT   (wxID_TREECTRL
, wxGenericDirCtrl::OnBeginEditItem
) 
 510   EVT_TREE_END_LABEL_EDIT     (wxID_TREECTRL
, wxGenericDirCtrl::OnEndEditItem
) 
 511   EVT_SIZE                    (wxGenericDirCtrl::OnSize
) 
 514 wxGenericDirCtrl::wxGenericDirCtrl(void) 
 519 void wxGenericDirCtrl::ExpandRoot() 
 521     ExpandDir(m_rootId
); // automatically expand first level 
 523     // Expand and select the default path 
 524     if (!m_defaultPath
.empty()) 
 526         ExpandPath(m_defaultPath
); 
 531         // On Unix, there's only one node under the (hidden) root node. It 
 532         // represents the / path, so the user would always have to expand it; 
 533         // let's do it ourselves 
 534         ExpandPath( wxT("/") ); 
 539 bool wxGenericDirCtrl::Create(wxWindow 
*parent
, 
 545                               const wxString
& filter
, 
 547                               const wxString
& name
) 
 549     if (!wxControl::Create(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
)) 
 552     SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
)); 
 556     long treeStyle 
= wxTR_HAS_BUTTONS
; 
 558     // On Windows CE, if you hide the root, you get a crash when 
 559     // attempting to access data for children of the root item. 
 561     treeStyle 
|= wxTR_HIDE_ROOT
; 
 565     treeStyle 
|= wxTR_NO_LINES
; 
 568     if (style 
& wxDIRCTRL_EDIT_LABELS
) 
 569         treeStyle 
|= wxTR_EDIT_LABELS
; 
 571     if ((style 
& wxDIRCTRL_3D_INTERNAL
) == 0) 
 572         treeStyle 
|= wxNO_BORDER
; 
 574         treeStyle 
|= wxBORDER_SUNKEN
; 
 576     long filterStyle 
= 0; 
 577     if ((style 
& wxDIRCTRL_3D_INTERNAL
) == 0) 
 578         filterStyle 
|= wxNO_BORDER
; 
 580         filterStyle 
|= wxBORDER_SUNKEN
; 
 582     m_treeCtrl 
= CreateTreeCtrl(this, wxID_TREECTRL
, 
 583                                 wxPoint(0,0), GetClientSize(), treeStyle
); 
 585     if (!filter
.empty() && (style 
& wxDIRCTRL_SHOW_FILTERS
)) 
 586         m_filterListCtrl 
= new wxDirFilterListCtrl(this, wxID_FILTERLISTCTRL
, wxDefaultPosition
, wxDefaultSize
, filterStyle
); 
 591     if (m_filter
.empty()) 
 595         m_filter 
= wxT("*.*"); 
 598     SetFilterIndex(defaultFilter
); 
 600     if (m_filterListCtrl
) 
 601         m_filterListCtrl
->FillFilterList(filter
, defaultFilter
); 
 603     m_treeCtrl
->SetImageList(wxTheFileIconsTable
->GetSmallImageList()); 
 605     m_showHidden 
= false; 
 606     wxDirItemData
* rootData 
= new wxDirItemData(wxEmptyString
, wxEmptyString
, true); 
 610 #if defined(__WINDOWS__) || defined(__OS2__) || defined(__DOS__) 
 611     rootName 
= _("Computer"); 
 613     rootName 
= _("Sections"); 
 616     m_rootId 
= m_treeCtrl
->AddRoot( rootName
, 3, -1, rootData
); 
 617     m_treeCtrl
->SetItemHasChildren(m_rootId
); 
 627 wxGenericDirCtrl::~wxGenericDirCtrl() 
 631 void wxGenericDirCtrl::Init() 
 633     m_showHidden 
= false; 
 635     m_currentFilterStr 
= wxEmptyString
; // Default: any file 
 637     m_filterListCtrl 
= NULL
; 
 640 wxTreeCtrl
* wxGenericDirCtrl::CreateTreeCtrl(wxWindow 
*parent
, wxWindowID id
, const wxPoint
& pos
, const wxSize
& size
, long treeStyle
) 
 642     return new wxTreeCtrl(parent
, id
, pos
, size
, treeStyle
); 
 645 void wxGenericDirCtrl::ShowHidden( bool show 
) 
 649     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::OnBeginEditItem(wxTreeEvent 
&event
) 
 686     // don't rename the main entry "Sections" 
 687     if (event
.GetItem() == m_rootId
) 
 693     // don't rename the individual sections 
 694     if (m_treeCtrl
->GetItemParent( event
.GetItem() ) == m_rootId
) 
 701 void wxGenericDirCtrl::OnEndEditItem(wxTreeEvent 
&event
) 
 703     if (event
.IsEditCancelled()) 
 706     if ((event
.GetLabel().empty()) || 
 707         (event
.GetLabel() == _(".")) || 
 708         (event
.GetLabel() == _("..")) || 
 709         (event
.GetLabel().Find(wxT('/')) != wxNOT_FOUND
) || 
 710         (event
.GetLabel().Find(wxT('\\')) != wxNOT_FOUND
) || 
 711         (event
.GetLabel().Find(wxT('|')) != wxNOT_FOUND
)) 
 713         wxMessageDialog 
dialog(this, _("Illegal directory name."), _("Error"), wxOK 
| wxICON_ERROR 
); 
 719     wxTreeItemId id 
= event
.GetItem(); 
 720     wxDirItemData 
*data 
= (wxDirItemData
*)m_treeCtrl
->GetItemData( id 
); 
 723     wxString 
new_name( wxPathOnly( data
->m_path 
) ); 
 724     new_name 
+= wxString(wxFILE_SEP_PATH
); 
 725     new_name 
+= event
.GetLabel(); 
 729     if (wxFileExists(new_name
)) 
 731         wxMessageDialog 
dialog(this, _("File name exists already."), _("Error"), wxOK 
| wxICON_ERROR 
); 
 736     if (wxRenameFile(data
->m_path
,new_name
)) 
 738         data
->SetNewDirName( new_name 
); 
 742         wxMessageDialog 
dialog(this, _("Operation not permitted."), _("Error"), wxOK 
| wxICON_ERROR 
); 
 748 void wxGenericDirCtrl::OnExpandItem(wxTreeEvent 
&event
) 
 750     wxTreeItemId parentId 
= event
.GetItem(); 
 752     // VS: this is needed because the event handler is called from wxTreeCtrl 
 753     //     ctor when wxTR_HIDE_ROOT was specified 
 755     if (!m_rootId
.IsOk()) 
 757         m_rootId 
= m_treeCtrl
->GetRootItem(); 
 762 void wxGenericDirCtrl::OnCollapseItem(wxTreeEvent 
&event 
) 
 764     CollapseDir(event
.GetItem()); 
 767 void wxGenericDirCtrl::CollapseDir(wxTreeItemId parentId
) 
 771     wxDirItemData 
*data 
= (wxDirItemData 
*) m_treeCtrl
->GetItemData(parentId
); 
 772     if (!data
->m_isExpanded
) 
 775     data
->m_isExpanded 
= false; 
 776     wxTreeItemIdValue cookie
; 
 777     /* Workaround because DeleteChildren has disapeared (why?) and 
 778      * CollapseAndReset doesn't work as advertised (deletes parent too) */ 
 779     child 
= m_treeCtrl
->GetFirstChild(parentId
, cookie
); 
 782         m_treeCtrl
->Delete(child
); 
 783         /* Not GetNextChild below, because the cookie mechanism can't 
 784          * handle disappearing children! */ 
 785         child 
= m_treeCtrl
->GetFirstChild(parentId
, cookie
); 
 787     if (parentId 
!= m_treeCtrl
->GetRootItem()) 
 788         m_treeCtrl
->Collapse(parentId
); 
 791 void wxGenericDirCtrl::ExpandDir(wxTreeItemId parentId
) 
 793     wxDirItemData 
*data 
= (wxDirItemData 
*) m_treeCtrl
->GetItemData(parentId
); 
 795     if (data
->m_isExpanded
) 
 798     data
->m_isExpanded 
= true; 
 800     if (parentId 
== m_treeCtrl
->GetRootItem()) 
 808     wxString search
,path
,filename
; 
 810     wxString 
dirName(data
->m_path
); 
 812 #if (defined(__WINDOWS__) && !defined(__WXWINCE__)) || defined(__DOS__) || defined(__OS2__) 
 813     // Check if this is a root directory and if so, 
 814     // whether the drive is avaiable. 
 815     if (!wxIsDriveAvailable(dirName
)) 
 817         data
->m_isExpanded 
= false; 
 818         //wxMessageBox(wxT("Sorry, this drive is not available.")); 
 823     // This may take a longish time. Go to busy cursor 
 826 #if defined(__WINDOWS__) || defined(__DOS__) || defined(__OS2__) 
 827     if (dirName
.Last() == ':') 
 828         dirName 
+= wxString(wxFILE_SEP_PATH
); 
 832     wxArrayString filenames
; 
 835     wxString eachFilename
; 
 842         int style 
= wxDIR_DIRS
; 
 843         if (m_showHidden
) style 
|= wxDIR_HIDDEN
; 
 844         if (d
.GetFirst(& eachFilename
, wxEmptyString
, style
)) 
 848                 if ((eachFilename 
!= wxT(".")) && (eachFilename 
!= wxT(".."))) 
 850                     dirs
.Add(eachFilename
); 
 853             while (d
.GetNext(&eachFilename
)); 
 856     dirs
.Sort(wxDirCtrlStringCompareFunction
); 
 858     // Now do the filenames -- but only if we're allowed to 
 859     if ((GetWindowStyle() & wxDIRCTRL_DIR_ONLY
) == 0) 
 865             int style 
= wxDIR_FILES
; 
 866             if (m_showHidden
) style 
|= wxDIR_HIDDEN
; 
 867             // Process each filter (ex: "JPEG Files (*.jpg;*.jpeg)|*.jpg;*.jpeg") 
 868             wxStringTokenizer strTok
; 
 870             strTok
.SetString(m_currentFilterStr
,wxT(";")); 
 871             while(strTok
.HasMoreTokens()) 
 873                 curFilter 
= strTok
.GetNextToken(); 
 874                 if (d
.GetFirst(& eachFilename
, curFilter
, style
)) 
 878                         if ((eachFilename 
!= wxT(".")) && (eachFilename 
!= wxT(".."))) 
 880                             filenames
.Add(eachFilename
); 
 883                     while (d
.GetNext(& eachFilename
)); 
 887         filenames
.Sort(wxDirCtrlStringCompareFunction
); 
 890     // Add the sorted dirs 
 892     for (i 
= 0; i 
< dirs
.Count(); i
++) 
 894         eachFilename 
= dirs
[i
]; 
 896         if (!wxEndsWithPathSeparator(path
)) 
 897             path 
+= wxString(wxFILE_SEP_PATH
); 
 898         path 
+= eachFilename
; 
 900         wxDirItemData 
*dir_item 
= new wxDirItemData(path
,eachFilename
,true); 
 901         wxTreeItemId id 
= AppendItem( parentId
, eachFilename
, 
 902                                       wxFileIconsTable::folder
, -1, dir_item
); 
 903         m_treeCtrl
->SetItemImage( id
, wxFileIconsTable::folder_open
, 
 904                                   wxTreeItemIcon_Expanded 
); 
 906         // Has this got any children? If so, make it expandable. 
 907         // (There are two situations when a dir has children: either it 
 908         // has subdirectories or it contains files that weren't filtered 
 909         // out. The latter only applies to dirctrl with files.) 
 910         if ( dir_item
->HasSubDirs() || 
 911              (((GetWindowStyle() & wxDIRCTRL_DIR_ONLY
) == 0) && 
 912                dir_item
->HasFiles(m_currentFilterStr
)) ) 
 914             m_treeCtrl
->SetItemHasChildren(id
); 
 918     // Add the sorted filenames 
 919     if ((GetWindowStyle() & wxDIRCTRL_DIR_ONLY
) == 0) 
 921         for (i 
= 0; i 
< filenames
.Count(); i
++) 
 923             eachFilename 
= filenames
[i
]; 
 925             if (!wxEndsWithPathSeparator(path
)) 
 926                 path 
+= wxString(wxFILE_SEP_PATH
); 
 927             path 
+= eachFilename
; 
 928             //path = dirName + wxString(wxT("/")) + eachFilename; 
 929             wxDirItemData 
*dir_item 
= new wxDirItemData(path
,eachFilename
,false); 
 930             int image_id 
= wxFileIconsTable::file
; 
 931             if (eachFilename
.Find(wxT('.')) != wxNOT_FOUND
) 
 932                 image_id 
= wxTheFileIconsTable
->GetIconID(eachFilename
.AfterLast(wxT('.'))); 
 933             (void) AppendItem( parentId
, eachFilename
, image_id
, -1, dir_item
); 
 938 void wxGenericDirCtrl::ReCreateTree() 
 940     CollapseDir(m_treeCtrl
->GetRootItem()); 
 944 void wxGenericDirCtrl::CollapseTree() 
 946     wxTreeItemIdValue cookie
; 
 947     wxTreeItemId child 
= m_treeCtrl
->GetFirstChild(m_rootId
, cookie
); 
 951         child 
= m_treeCtrl
->GetNextChild(m_rootId
, cookie
); 
 955 // Find the child that matches the first part of 'path'. 
 956 // E.g. if a child path is "/usr" and 'path' is "/usr/include" 
 957 // then the child for /usr is returned. 
 958 wxTreeItemId 
wxGenericDirCtrl::FindChild(wxTreeItemId parentId
, const wxString
& path
, bool& done
) 
 960     wxString 
path2(path
); 
 962     // Make sure all separators are as per the current platform 
 963     path2
.Replace(wxT("\\"), wxString(wxFILE_SEP_PATH
)); 
 964     path2
.Replace(wxT("/"), wxString(wxFILE_SEP_PATH
)); 
 966     // Append a separator to foil bogus substring matching 
 967     path2 
+= wxString(wxFILE_SEP_PATH
); 
 969     // In MSW or PM, case is not significant 
 970 #if defined(__WINDOWS__) || defined(__DOS__) || defined(__OS2__) 
 974     wxTreeItemIdValue cookie
; 
 975     wxTreeItemId childId 
= m_treeCtrl
->GetFirstChild(parentId
, cookie
); 
 976     while (childId
.IsOk()) 
 978         wxDirItemData
* data 
= (wxDirItemData
*) m_treeCtrl
->GetItemData(childId
); 
 980         if (data 
&& !data
->m_path
.empty()) 
 982             wxString 
childPath(data
->m_path
); 
 983             if (!wxEndsWithPathSeparator(childPath
)) 
 984                 childPath 
+= wxString(wxFILE_SEP_PATH
); 
 986             // In MSW and PM, case is not significant 
 987 #if defined(__WINDOWS__) || defined(__DOS__) || defined(__OS2__) 
 988             childPath
.MakeLower(); 
 991             if (childPath
.length() <= path2
.length()) 
 993                 wxString path3 
= path2
.Mid(0, childPath
.length()); 
 994                 if (childPath 
== path3
) 
 996                     if (path3
.length() == path2
.length()) 
1005         childId 
= m_treeCtrl
->GetNextChild(parentId
, cookie
); 
1007     wxTreeItemId invalid
; 
1011 // Try to expand as much of the given path as possible, 
1012 // and select the given tree item. 
1013 bool wxGenericDirCtrl::ExpandPath(const wxString
& path
) 
1016     wxTreeItemId id 
= FindChild(m_rootId
, path
, done
); 
1017     wxTreeItemId lastId 
= id
; // The last non-zero id 
1018     while (id
.IsOk() && !done
) 
1022         id 
= FindChild(id
, path
, done
); 
1029     wxDirItemData 
*data 
= (wxDirItemData 
*) m_treeCtrl
->GetItemData(lastId
); 
1032         m_treeCtrl
->Expand(lastId
); 
1034     if ((GetWindowStyle() & wxDIRCTRL_SELECT_FIRST
) && data
->m_isDir
) 
1036         // Find the first file in this directory 
1037         wxTreeItemIdValue cookie
; 
1038         wxTreeItemId childId 
= m_treeCtrl
->GetFirstChild(lastId
, cookie
); 
1039         bool selectedChild 
= false; 
1040         while (childId
.IsOk()) 
1042             data 
= (wxDirItemData
*) m_treeCtrl
->GetItemData(childId
); 
1044             if (data 
&& data
->m_path 
!= wxEmptyString 
&& !data
->m_isDir
) 
1046                 m_treeCtrl
->SelectItem(childId
); 
1047                 m_treeCtrl
->EnsureVisible(childId
); 
1048                 selectedChild 
= true; 
1051             childId 
= m_treeCtrl
->GetNextChild(lastId
, cookie
); 
1055             m_treeCtrl
->SelectItem(lastId
); 
1056             m_treeCtrl
->EnsureVisible(lastId
); 
1061         m_treeCtrl
->SelectItem(lastId
); 
1062         m_treeCtrl
->EnsureVisible(lastId
); 
1069 bool wxGenericDirCtrl::CollapsePath(const wxString
& path
) 
1072     wxTreeItemId id     
= FindChild(m_rootId
, path
, done
); 
1073     wxTreeItemId lastId 
= id
; // The last non-zero id 
1075     while ( id
.IsOk() && !done 
) 
1079         id 
= FindChild(id
, path
, done
); 
1085     if ( !lastId
.IsOk() ) 
1088     m_treeCtrl
->SelectItem(lastId
); 
1089     m_treeCtrl
->EnsureVisible(lastId
); 
1095 wxString 
wxGenericDirCtrl::GetPath() const 
1097     wxTreeItemId id 
= m_treeCtrl
->GetSelection(); 
1100         wxDirItemData
* data 
= (wxDirItemData
*) m_treeCtrl
->GetItemData(id
); 
1101         return data
->m_path
; 
1104         return wxEmptyString
; 
1107 wxString 
wxGenericDirCtrl::GetFilePath() const 
1109     wxTreeItemId id 
= m_treeCtrl
->GetSelection(); 
1112         wxDirItemData
* data 
= (wxDirItemData
*) m_treeCtrl
->GetItemData(id
); 
1114             return wxEmptyString
; 
1116             return data
->m_path
; 
1119         return wxEmptyString
; 
1122 void wxGenericDirCtrl::SetPath(const wxString
& path
) 
1124     m_defaultPath 
= path
; 
1131 void wxGenericDirCtrl::FindChildFiles(wxTreeItemId id
, int dirFlags
, wxArrayString
& filenames
) 
1133     wxDirItemData 
*data 
= (wxDirItemData 
*) m_treeCtrl
->GetItemData(id
); 
1135     // This may take a longish time. Go to busy cursor 
1140     wxString search
,path
,filename
; 
1142     wxString 
dirName(data
->m_path
); 
1144 #if defined(__WXMSW__) || defined(__OS2__) 
1145     if (dirName
.Last() == ':') 
1146         dirName 
+= wxString(wxFILE_SEP_PATH
); 
1150     wxString eachFilename
; 
1157         if (d
.GetFirst(& eachFilename
, m_currentFilterStr
, dirFlags
)) 
1161                 if ((eachFilename 
!= wxT(".")) && (eachFilename 
!= wxT(".."))) 
1163                     filenames
.Add(eachFilename
); 
1166             while (d
.GetNext(& eachFilename
)) ; 
1172 void wxGenericDirCtrl::SetFilterIndex(int n
) 
1174     m_currentFilter 
= n
; 
1177     if (ExtractWildcard(m_filter
, n
, f
, d
)) 
1178         m_currentFilterStr 
= f
; 
1181         m_currentFilterStr 
= wxT("*"); 
1183         m_currentFilterStr 
= wxT("*.*"); 
1187 void wxGenericDirCtrl::SetFilter(const wxString
& filter
) 
1192     if (ExtractWildcard(m_filter
, m_currentFilter
, f
, d
)) 
1193         m_currentFilterStr 
= f
; 
1196         m_currentFilterStr 
= wxT("*"); 
1198         m_currentFilterStr 
= wxT("*.*"); 
1202 // Extract description and actual filter from overall filter string 
1203 bool wxGenericDirCtrl::ExtractWildcard(const wxString
& filterStr
, int n
, wxString
& filter
, wxString
& description
) 
1205     wxArrayString filters
, descriptions
; 
1206     int count 
= wxParseCommonDialogsFilter(filterStr
, descriptions
, filters
); 
1207     if (count 
> 0 && n 
< count
) 
1209         filter 
= filters
[n
]; 
1210         description 
= descriptions
[n
]; 
1217 #if WXWIN_COMPATIBILITY_2_4 
1218 // Parses the global filter, returning the number of filters. 
1219 // Returns 0 if none or if there's a problem. 
1220 // filterStr is in the form: "All files (*.*)|*.*|JPEG Files (*.jpeg)|*.jpg" 
1221 int wxGenericDirCtrl::ParseFilter(const wxString
& filterStr
, wxArrayString
& filters
, wxArrayString
& descriptions
) 
1223     return wxParseCommonDialogsFilter(filterStr
, descriptions
, filters 
); 
1225 #endif // WXWIN_COMPATIBILITY_2_4 
1227 void wxGenericDirCtrl::DoResize() 
1229     wxSize sz 
= GetClientSize(); 
1230     int verticalSpacing 
= 3; 
1234         if (m_filterListCtrl
) 
1236             filterSz 
= m_filterListCtrl
->GetSize(); 
1237             sz
.y 
-= (filterSz
.y 
+ verticalSpacing
); 
1239         m_treeCtrl
->SetSize(0, 0, sz
.x
, sz
.y
); 
1240         if (m_filterListCtrl
) 
1242             m_filterListCtrl
->SetSize(0, sz
.y 
+ verticalSpacing
, sz
.x
, filterSz
.y
); 
1243             // Don't know why, but this needs refreshing after a resize (wxMSW) 
1244             m_filterListCtrl
->Refresh(); 
1250 void wxGenericDirCtrl::OnSize(wxSizeEvent
& WXUNUSED(event
)) 
1255 wxTreeItemId 
wxGenericDirCtrl::AppendItem (const wxTreeItemId 
& parent
, 
1256                                            const wxString 
& text
, 
1257                                            int image
, int selectedImage
, 
1258                                            wxTreeItemData 
* data
) 
1260   wxTreeCtrl 
*treeCtrl 
= GetTreeCtrl (); 
1262   wxASSERT (treeCtrl
); 
1266     return treeCtrl
->AppendItem (parent
, text
, image
, selectedImage
, data
); 
1270     return wxTreeItemId(); 
1275 //----------------------------------------------------------------------------- 
1276 // wxDirFilterListCtrl 
1277 //----------------------------------------------------------------------------- 
1279 IMPLEMENT_CLASS(wxDirFilterListCtrl
, wxChoice
) 
1281 BEGIN_EVENT_TABLE(wxDirFilterListCtrl
, wxChoice
) 
1282     EVT_CHOICE(wxID_ANY
, wxDirFilterListCtrl::OnSelFilter
) 
1285 bool wxDirFilterListCtrl::Create(wxGenericDirCtrl
* parent
, const wxWindowID id
, 
1291     return wxChoice::Create(parent
, id
, pos
, size
, 0, NULL
, style
); 
1294 void wxDirFilterListCtrl::Init() 
1299 void wxDirFilterListCtrl::OnSelFilter(wxCommandEvent
& WXUNUSED(event
)) 
1301     int sel 
= GetSelection(); 
1303     wxString currentPath 
= m_dirCtrl
->GetPath(); 
1305     m_dirCtrl
->SetFilterIndex(sel
); 
1307     // If the filter has changed, the view is out of date, so 
1308     // collapse the tree. 
1309     m_dirCtrl
->ReCreateTree(); 
1311     // Try to restore the selection, or at least the directory 
1312     m_dirCtrl
->ExpandPath(currentPath
); 
1315 void wxDirFilterListCtrl::FillFilterList(const wxString
& filter
, int defaultFilter
) 
1318     wxArrayString descriptions
, filters
; 
1319     size_t n 
= (size_t) wxParseCommonDialogsFilter(filter
, descriptions
, filters
); 
1321     if (n 
> 0 && defaultFilter 
< (int) n
) 
1323         for (size_t i 
= 0; i 
< n
; i
++) 
1324             Append(descriptions
[i
]); 
1325         SetSelection(defaultFilter
); 
1328 #endif // wxUSE_DIRDLG 
1330 #if wxUSE_DIRDLG || wxUSE_FILEDLG 
1332 // ---------------------------------------------------------------------------- 
1333 // wxFileIconsTable icons 
1334 // ---------------------------------------------------------------------------- 
1337 /* Computer (c) Julian Smart */ 
1338 static const char * file_icons_tbl_computer_xpm
[] = { 
1339 /* columns rows colors chars-per-pixel */ 
1401 #endif // GTK+ < 2.4 
1403 // ---------------------------------------------------------------------------- 
1404 // wxFileIconsTable & friends 
1405 // ---------------------------------------------------------------------------- 
1407 // global instance of a wxFileIconsTable 
1408 wxFileIconsTable
* wxTheFileIconsTable 
= (wxFileIconsTable 
*)NULL
; 
1410 // A module to allow icons table cleanup 
1412 class wxFileIconsTableModule
: public wxModule
 
1414 DECLARE_DYNAMIC_CLASS(wxFileIconsTableModule
) 
1416     wxFileIconsTableModule() {} 
1417     bool OnInit() { wxTheFileIconsTable 
= new wxFileIconsTable
; return true; } 
1420         if (wxTheFileIconsTable
) 
1422             delete wxTheFileIconsTable
; 
1423             wxTheFileIconsTable 
= NULL
; 
1428 IMPLEMENT_DYNAMIC_CLASS(wxFileIconsTableModule
, wxModule
) 
1430 class wxFileIconEntry 
: public wxObject
 
1433     wxFileIconEntry(int i
) { id 
= i
; } 
1438 wxFileIconsTable::wxFileIconsTable() 
1441     m_smallImageList 
= NULL
; 
1444 wxFileIconsTable::~wxFileIconsTable() 
1448         WX_CLEAR_HASH_TABLE(*m_HashTable
); 
1451     if (m_smallImageList
) delete m_smallImageList
; 
1454 // delayed initialization - wait until first use (wxArtProv not created yet) 
1455 void wxFileIconsTable::Create() 
1457     wxCHECK_RET(!m_smallImageList 
&& !m_HashTable
, wxT("creating icons twice")); 
1458     m_HashTable 
= new wxHashTable(wxKEY_STRING
); 
1459     m_smallImageList 
= new wxImageList(16, 16); 
1462     m_smallImageList
->Add(wxArtProvider::GetBitmap(wxART_FOLDER
, 
1466     m_smallImageList
->Add(wxArtProvider::GetBitmap(wxART_FOLDER_OPEN
, 
1471     // GTK24 uses this icon in the file open dialog 
1472     m_smallImageList
->Add(wxArtProvider::GetBitmap(wxART_HARDDISK
, 
1476     m_smallImageList
->Add(wxIcon(file_icons_tbl_computer_xpm
)); 
1479     m_smallImageList
->Add(wxArtProvider::GetBitmap(wxART_HARDDISK
, 
1483     m_smallImageList
->Add(wxArtProvider::GetBitmap(wxART_CDROM
, 
1487     m_smallImageList
->Add(wxArtProvider::GetBitmap(wxART_FLOPPY
, 
1491     m_smallImageList
->Add(wxArtProvider::GetBitmap(wxART_REMOVABLE
, 
1495     m_smallImageList
->Add(wxArtProvider::GetBitmap(wxART_NORMAL_FILE
, 
1499     if (GetIconID(wxEmptyString
, _T("application/x-executable")) == file
) 
1501         m_smallImageList
->Add(wxArtProvider::GetBitmap(wxART_EXECUTABLE_FILE
, 
1504         delete m_HashTable
->Get(_T("exe")); 
1505         m_HashTable
->Delete(_T("exe")); 
1506         m_HashTable
->Put(_T("exe"), new wxFileIconEntry(executable
)); 
1508     /* else put into list by GetIconID 
1509        (KDE defines application/x-executable for *.exe and has nice icon) 
1513 wxImageList 
*wxFileIconsTable::GetSmallImageList() 
1515     if (!m_smallImageList
) 
1518     return m_smallImageList
; 
1521 #if wxUSE_MIMETYPE && wxUSE_IMAGE && (!defined(__WXMSW__) || wxUSE_WXDIB) 
1522 // VS: we don't need this function w/o wxMimeTypesManager because we'll only have 
1523 //     one icon and we won't resize it 
1525 static wxBitmap 
CreateAntialiasedBitmap(const wxImage
& img
) 
1527     const unsigned int size 
= 16; 
1529     wxImage 
smallimg (size
, size
); 
1530     unsigned char *p1
, *p2
, *ps
; 
1531     unsigned char mr 
= img
.GetMaskRed(), 
1532                   mg 
= img
.GetMaskGreen(), 
1533                   mb 
= img
.GetMaskBlue(); 
1536     unsigned sr
, sg
, sb
, smask
; 
1538     p1 
= img
.GetData(), p2 
= img
.GetData() + 3 * size
*2, ps 
= smallimg
.GetData(); 
1539     smallimg
.SetMaskColour(mr
, mr
, mr
); 
1541     for (y 
= 0; y 
< size
; y
++) 
1543         for (x 
= 0; x 
< size
; x
++) 
1545             sr 
= sg 
= sb 
= smask 
= 0; 
1546             if (p1
[0] != mr 
|| p1
[1] != mg 
|| p1
[2] != mb
) 
1547                 sr 
+= p1
[0], sg 
+= p1
[1], sb 
+= p1
[2]; 
1550             if (p1
[0] != mr 
|| p1
[1] != mg 
|| p1
[2] != mb
) 
1551                 sr 
+= p1
[0], sg 
+= p1
[1], sb 
+= p1
[2]; 
1554             if (p2
[0] != mr 
|| p2
[1] != mg 
|| p2
[2] != mb
) 
1555                 sr 
+= p2
[0], sg 
+= p2
[1], sb 
+= p2
[2]; 
1558             if (p2
[0] != mr 
|| p2
[1] != mg 
|| p2
[2] != mb
) 
1559                 sr 
+= p2
[0], sg 
+= p2
[1], sb 
+= p2
[2]; 
1564                 ps
[0] = ps
[1] = ps
[2] = mr
; 
1567                 ps
[0] = (unsigned char)(sr 
>> 2); 
1568                 ps
[1] = (unsigned char)(sg 
>> 2); 
1569                 ps
[2] = (unsigned char)(sb 
>> 2); 
1573         p1 
+= size
*2 * 3, p2 
+= size
*2 * 3; 
1576     return wxBitmap(smallimg
); 
1579 // This function is currently not unused anymore 
1581 // finds empty borders and return non-empty area of image: 
1582 static wxImage 
CutEmptyBorders(const wxImage
& img
) 
1584     unsigned char mr 
= img
.GetMaskRed(), 
1585                   mg 
= img
.GetMaskGreen(), 
1586                   mb 
= img
.GetMaskBlue(); 
1587     unsigned char *dt 
= img
.GetData(), *dttmp
; 
1588     unsigned w 
= img
.GetWidth(), h 
= img
.GetHeight(); 
1590     unsigned top
, bottom
, left
, right
, i
; 
1593 #define MK_DTTMP(x,y)      dttmp = dt + ((x + y * w) * 3) 
1594 #define NOEMPTY_PIX(empt)  if (dttmp[0] != mr || dttmp[1] != mg || dttmp[2] != mb) {empt = false; break;} 
1596     for (empt 
= true, top 
= 0; empt 
&& top 
< h
; top
++) 
1599         for (i 
= 0; i 
< w
; i
++, dttmp
+=3) 
1602     for (empt 
= true, bottom 
= h
-1; empt 
&& bottom 
> top
; bottom
--) 
1604         MK_DTTMP(0, bottom
); 
1605         for (i 
= 0; i 
< w
; i
++, dttmp
+=3) 
1608     for (empt 
= true, left 
= 0; empt 
&& left 
< w
; left
++) 
1611         for (i 
= 0; i 
< h
; i
++, dttmp
+=3*w
) 
1614     for (empt 
= true, right 
= w
-1; empt 
&& right 
> left
; right
--) 
1617         for (i 
= 0; i 
< h
; i
++, dttmp
+=3*w
) 
1620     top
--, left
--, bottom
++, right
++; 
1622     return img
.GetSubImage(wxRect(left
, top
, right 
- left 
+ 1, bottom 
- top 
+ 1)); 
1626 #endif // wxUSE_MIMETYPE 
1628 int wxFileIconsTable::GetIconID(const wxString
& extension
, const wxString
& mime
) 
1630     if (!m_smallImageList
) 
1634     if (!extension
.empty()) 
1636         wxFileIconEntry 
*entry 
= (wxFileIconEntry
*) m_HashTable
->Get(extension
); 
1637         if (entry
) return (entry 
-> id
); 
1640     wxFileType 
*ft 
= (mime
.empty()) ? 
1641                    wxTheMimeTypesManager 
-> GetFileTypeFromExtension(extension
) : 
1642                    wxTheMimeTypesManager 
-> GetFileTypeFromMimeType(mime
); 
1644     wxIconLocation iconLoc
; 
1649         if ( ft 
&& ft
->GetIcon(&iconLoc
) ) 
1651             ic 
= wxIcon( iconLoc 
); 
1660         m_HashTable
->Put(extension
, new wxFileIconEntry(newid
)); 
1665     bmp
.CopyFromIcon(ic
); 
1670         m_HashTable
->Put(extension
, new wxFileIconEntry(newid
)); 
1674     const unsigned int size 
= 16; 
1676     int id 
= m_smallImageList
->GetImageCount(); 
1677     if ((bmp
.GetWidth() == (int) size
) && (bmp
.GetHeight() == (int) size
)) 
1679         m_smallImageList
->Add(bmp
); 
1681 #if wxUSE_IMAGE && (!defined(__WXMSW__) || wxUSE_WXDIB) 
1684         wxImage img 
= bmp
.ConvertToImage(); 
1686         if ((img
.GetWidth() != size
*2) || (img
.GetHeight() != size
*2)) 
1687 //            m_smallImageList->Add(CreateAntialiasedBitmap(CutEmptyBorders(img).Rescale(size*2, size*2))); 
1688             m_smallImageList
->Add(CreateAntialiasedBitmap(img
.Rescale(size
*2, size
*2))); 
1690             m_smallImageList
->Add(CreateAntialiasedBitmap(img
)); 
1692 #endif // wxUSE_IMAGE 
1694     m_HashTable
->Put(extension
, new wxFileIconEntry(id
)); 
1697 #else // !wxUSE_MIMETYPE 
1700     if (extension 
== wxT("exe")) 
1704 #endif // wxUSE_MIMETYPE/!wxUSE_MIMETYPE 
1707 #endif // wxUSE_DIRDLG || wxUSE_FILEDLG