home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2233.zip / wxOS2-2_3_3.zip / wxWindows-2.3.3 / src / generic / filedlgg.cpp < prev    next >
C/C++ Source or Header  |  2002-09-08  |  47KB  |  1,622 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name:        filedlgg.cpp
  3. // Purpose:     wxFileDialog
  4. // Author:      Robert Roebling
  5. // Modified by:
  6. // Created:     12/12/98
  7. // RCS-ID:      $Id: filedlgg.cpp,v 1.72 2002/09/08 14:10:22 JS Exp $
  8. // Copyright:   (c) Robert Roebling
  9. // Licence:     wxWindows licence
  10. /////////////////////////////////////////////////////////////////////////////
  11.  
  12. // ============================================================================
  13. // declarations
  14. // ============================================================================
  15.  
  16. // ----------------------------------------------------------------------------
  17. // headers
  18. // ----------------------------------------------------------------------------
  19.  
  20. #ifdef __GNUG__
  21. #pragma implementation "filedlgg.h"
  22. #endif
  23.  
  24. // For compilers that support precompilation, includes "wx.h".
  25. #include "wx/wxprec.h"
  26.  
  27. #ifdef __BORLANDC__
  28. #pragma hdrstop
  29. #endif
  30.  
  31. #if wxUSE_FILEDLG
  32.  
  33. #if !defined(__UNIX__) && !defined(__DOS__)
  34. #error wxFileDialog currently only supports Unix and DOS
  35. #endif
  36.  
  37. #include "wx/checkbox.h"
  38. #include "wx/textctrl.h"
  39. #include "wx/choice.h"
  40. #include "wx/checkbox.h"
  41. #include "wx/stattext.h"
  42. #include "wx/filedlg.h"
  43. #include "wx/debug.h"
  44. #include "wx/log.h"
  45. #include "wx/intl.h"
  46. #include "wx/listctrl.h"
  47. #include "wx/msgdlg.h"
  48. #include "wx/sizer.h"
  49. #include "wx/bmpbuttn.h"
  50. #include "wx/tokenzr.h"
  51. #include "wx/mimetype.h"
  52. #include "wx/image.h"
  53. #include "wx/module.h"
  54. #include "wx/config.h"
  55. #include "wx/imaglist.h"
  56. #include "wx/dir.h"
  57. #include "wx/artprov.h"
  58.  
  59. #if wxUSE_TOOLTIPS
  60.     #include "wx/tooltip.h"
  61. #endif
  62.  
  63. #include <sys/types.h>
  64. #include <sys/stat.h>
  65.  
  66. #ifdef __UNIX__
  67.     #include <dirent.h>
  68.     #include <pwd.h>
  69.     #ifndef __VMS
  70.     # include <grp.h>
  71.     #endif
  72. #endif
  73.  
  74. #ifdef __WATCOMC__
  75.     #include <direct.h>
  76. #endif
  77.  
  78. #include <time.h>
  79. #include <unistd.h>
  80.  
  81. // ----------------------------------------------------------------------------
  82. // constants
  83. // ----------------------------------------------------------------------------
  84.  
  85. // the list ctrl fields in report view
  86. enum FileListField
  87. {
  88.     FileList_Name,
  89.     FileList_Type,
  90.     FileList_Date,
  91.     FileList_Time,
  92. #ifdef __UNIX__
  93.     FileList_Perm,
  94. #endif // __UNIX__
  95.     FileList_Max
  96. };
  97.  
  98. //-----------------------------------------------------------------------------
  99. //  wxFileData
  100. //-----------------------------------------------------------------------------
  101.  
  102. class wxFileData
  103. {
  104. public:
  105.     wxFileData( const wxString &name, const wxString &fname );
  106.     wxString GetName() const;
  107.     wxString GetFullName() const;
  108.     wxString GetHint() const;
  109.     wxString GetEntry( FileListField num ) const;
  110.  
  111.     bool IsDir() const { return m_isDir; }
  112.     bool IsLink() const { return m_isLink; }
  113.     bool IsExe() const { return m_isExe; }
  114.     long GetSize() const { return m_size; }
  115.  
  116.     void MakeItem( wxListItem &item );
  117.     void SetNewName( const wxString &name, const wxString &fname );
  118.  
  119. private:
  120.     wxString m_name;
  121.     wxString m_fileName;
  122.     long     m_size;
  123.     int      m_hour;
  124.     int      m_minute;
  125.     int      m_year;
  126.     int      m_month;
  127.     int      m_day;
  128.     wxString m_permissions;
  129.     bool     m_isDir;
  130.     bool     m_isLink;
  131.     bool     m_isExe;
  132. };
  133.  
  134. //-----------------------------------------------------------------------------
  135. //  wxFileCtrl
  136. //-----------------------------------------------------------------------------
  137.  
  138. class wxFileCtrl : public wxListCtrl
  139. {
  140. public:
  141.     wxFileCtrl();
  142.     wxFileCtrl( wxWindow *win,
  143.                 wxWindowID id,
  144.                 const wxString &wild,
  145.                 bool showHidden,
  146.                 const wxPoint &pos = wxDefaultPosition,
  147.                 const wxSize &size = wxDefaultSize,
  148.                 long style = wxLC_LIST,
  149.                 const wxValidator &validator = wxDefaultValidator,
  150.                 const wxString &name = wxT("filelist") );
  151.     virtual ~wxFileCtrl();
  152.  
  153.     void ChangeToListMode();
  154.     void ChangeToReportMode();
  155.     void ChangeToIconMode();
  156.     void ShowHidden( bool show = TRUE );
  157.     long Add( wxFileData *fd, wxListItem &item );
  158.     void UpdateFiles();
  159.     virtual void StatusbarText( wxChar *WXUNUSED(text) ) {};
  160.     void MakeDir();
  161.     void GoToParentDir();
  162.     void GoToHomeDir();
  163.     void GoToDir( const wxString &dir );
  164.     void SetWild( const wxString &wild );
  165.     void GetDir( wxString &dir );
  166.     void OnListDeleteItem( wxListEvent &event );
  167.     void OnListEndLabelEdit( wxListEvent &event );
  168.  
  169.     // Associate commonly used UI controls with wxFileCtrl so that they can be
  170.     // disabled when they cannot be used (e.g. can't go to parent directory
  171.     // if wxFileCtrl already is in the root dir):
  172.     void SetGoToParentControl(wxWindow *ctrl) { m_goToParentControl = ctrl; }
  173.     void SetNewDirControl(wxWindow *ctrl) { m_newDirControl = ctrl; }
  174.  
  175. private:
  176.     void FreeItemData(const wxListItem& item);
  177.     void FreeAllItemsData();
  178.  
  179.     wxString      m_dirName;
  180.     bool          m_showHidden;
  181.     wxString      m_wild;
  182.  
  183.     wxWindow     *m_goToParentControl;
  184.     wxWindow     *m_newDirControl;
  185.  
  186.     DECLARE_DYNAMIC_CLASS(wxFileCtrl);
  187.     DECLARE_EVENT_TABLE()
  188. };
  189.  
  190. // ----------------------------------------------------------------------------
  191. // private classes - icons list management
  192. // ----------------------------------------------------------------------------
  193.  
  194. class wxFileIconEntry : public wxObject
  195. {
  196. public:
  197.     wxFileIconEntry(int i) { id = i; }
  198.  
  199.     int id;
  200. };
  201.  
  202.  
  203. class wxFileIconsTable
  204. {
  205. public:
  206.     wxFileIconsTable();
  207.  
  208.     int GetIconID(const wxString& extension, const wxString& mime = wxEmptyString);
  209.     wxImageList *GetImageList() { return &m_ImageList; }
  210.  
  211. protected:
  212.     wxImageList m_ImageList;
  213.     wxHashTable m_HashTable;
  214. };
  215.  
  216. static wxFileIconsTable *g_IconsTable = NULL;
  217.  
  218. #define FI_FOLDER     0
  219. #define FI_UNKNOWN    1
  220. #define FI_EXECUTABLE 2
  221.  
  222. wxFileIconsTable::wxFileIconsTable() :
  223.                     m_ImageList(16, 16),
  224.                     m_HashTable(wxKEY_STRING)
  225. {
  226.     m_HashTable.DeleteContents(TRUE);
  227.     // FI_FOLDER:
  228.     m_ImageList.Add(wxArtProvider::GetBitmap(wxART_FOLDER, wxART_CMN_DIALOG));
  229.     // FI_UNKNOWN:
  230.     m_ImageList.Add(wxArtProvider::GetBitmap(wxART_NORMAL_FILE, wxART_CMN_DIALOG));
  231.     // FI_EXECUTABLE:
  232.     if (GetIconID(wxEmptyString, _T("application/x-executable")) == FI_UNKNOWN)
  233.     {
  234.         m_ImageList.Add(wxArtProvider::GetBitmap(wxART_EXECUTABLE_FILE, wxART_CMN_DIALOG));
  235.         m_HashTable.Delete(_T("exe"));
  236.         m_HashTable.Put(_T("exe"), new wxFileIconEntry(FI_EXECUTABLE));
  237.     }
  238.     /* else put into list by GetIconID
  239.        (KDE defines application/x-executable for *.exe and has nice icon)
  240.      */
  241. }
  242.  
  243.  
  244.  
  245. #if wxUSE_MIMETYPE
  246. // VS: we don't need this function w/o wxMimeTypesManager because we'll only have
  247. //     one icon and we won't resize it
  248.  
  249. static wxBitmap CreateAntialiasedBitmap(const wxImage& img)
  250. {
  251.     wxImage small(16, 16);
  252.     unsigned char *p1, *p2, *ps;
  253.     unsigned char mr = img.GetMaskRed(),
  254.                   mg = img.GetMaskGreen(),
  255.                   mb = img.GetMaskBlue();
  256.  
  257.     unsigned x, y;
  258.     unsigned sr, sg, sb, smask;
  259.  
  260.     p1 = img.GetData(), p2 = img.GetData() + 3 * 32, ps = small.GetData();
  261.     small.SetMaskColour(mr, mr, mr);
  262.  
  263.     for (y = 0; y < 16; y++)
  264.     {
  265.         for (x = 0; x < 16; x++)
  266.         {
  267.             sr = sg = sb = smask = 0;
  268.             if (p1[0] != mr || p1[1] != mg || p1[2] != mb)
  269.                 sr += p1[0], sg += p1[1], sb += p1[2];
  270.             else smask++;
  271.             p1 += 3;
  272.             if (p1[0] != mr || p1[1] != mg || p1[2] != mb)
  273.                 sr += p1[0], sg += p1[1], sb += p1[2];
  274.             else smask++;
  275.             p1 += 3;
  276.             if (p2[0] != mr || p2[1] != mg || p2[2] != mb)
  277.                 sr += p2[0], sg += p2[1], sb += p2[2];
  278.             else smask++;
  279.             p2 += 3;
  280.             if (p2[0] != mr || p2[1] != mg || p2[2] != mb)
  281.                 sr += p2[0], sg += p2[1], sb += p2[2];
  282.             else smask++;
  283.             p2 += 3;
  284.  
  285.             if (smask > 2)
  286.                 ps[0] = ps[1] = ps[2] = mr;
  287.             else
  288.                 ps[0] = sr >> 2, ps[1] = sg >> 2, ps[2] = sb >> 2;
  289.             ps += 3;
  290.         }
  291.         p1 += 32 * 3, p2 += 32 * 3;
  292.     }
  293.  
  294.     return wxBitmap(small);
  295. }
  296.  
  297. // finds empty borders and return non-empty area of image:
  298. static wxImage CutEmptyBorders(const wxImage& img)
  299. {
  300.     unsigned char mr = img.GetMaskRed(),
  301.                   mg = img.GetMaskGreen(),
  302.                   mb = img.GetMaskBlue();
  303.     unsigned char *dt = img.GetData(), *dttmp;
  304.     unsigned w = img.GetWidth(), h = img.GetHeight();
  305.  
  306.     unsigned top, bottom, left, right, i;
  307.     bool empt;
  308.  
  309. #define MK_DTTMP(x,y)      dttmp = dt + ((x + y * w) * 3)
  310. #define NOEMPTY_PIX(empt)  if (dttmp[0] != mr || dttmp[1] != mg || dttmp[2] != mb) {empt = FALSE; break;}
  311.  
  312.     for (empt = TRUE, top = 0; empt && top < h; top++)
  313.     {
  314.         MK_DTTMP(0, top);
  315.         for (i = 0; i < w; i++, dttmp+=3)
  316.             NOEMPTY_PIX(empt)
  317.     }
  318.     for (empt = TRUE, bottom = h-1; empt && bottom > top; bottom--)
  319.     {
  320.         MK_DTTMP(0, bottom);
  321.         for (i = 0; i < w; i++, dttmp+=3)
  322.             NOEMPTY_PIX(empt)
  323.     }
  324.     for (empt = TRUE, left = 0; empt && left < w; left++)
  325.     {
  326.         MK_DTTMP(left, 0);
  327.         for (i = 0; i < h; i++, dttmp+=3*w)
  328.             NOEMPTY_PIX(empt)
  329.     }
  330.     for (empt = TRUE, right = w-1; empt && right > left; right--)
  331.     {
  332.         MK_DTTMP(right, 0);
  333.         for (i = 0; i < h; i++, dttmp+=3*w)
  334.             NOEMPTY_PIX(empt)
  335.     }
  336.     top--, left--, bottom++, right++;
  337.  
  338.     return img.GetSubImage(wxRect(left, top, right - left + 1, bottom - top + 1));
  339. }
  340. #endif // wxUSE_MIMETYPE
  341.  
  342.  
  343.  
  344. int wxFileIconsTable::GetIconID(const wxString& extension, const wxString& mime)
  345. {
  346. #if wxUSE_MIMETYPE
  347.     if (!extension.IsEmpty())
  348.     {
  349.         wxFileIconEntry *entry = (wxFileIconEntry*) m_HashTable.Get(extension);
  350.         if (entry) return (entry -> id);
  351.     }
  352.  
  353.     wxFileType *ft = (mime.IsEmpty()) ?
  354.                    wxTheMimeTypesManager -> GetFileTypeFromExtension(extension) :
  355.                    wxTheMimeTypesManager -> GetFileTypeFromMimeType(mime);
  356.     wxIcon ic;
  357.     if (ft == NULL || (!ft -> GetIcon(&ic)) || (!ic.Ok()))
  358.     {
  359.         int newid = FI_UNKNOWN;
  360.         m_HashTable.Put(extension, new wxFileIconEntry(newid));
  361.         return newid;
  362.     }
  363.     wxImage img = ic.ConvertToImage();
  364.     delete ft;
  365.  
  366.     int id = m_ImageList.GetImageCount();
  367.     if (img.GetWidth() == 16 && img.GetHeight() == 16)
  368.         m_ImageList.Add(wxBitmap(img));
  369.     else
  370.     {
  371.         if (img.GetWidth() != 32 || img.GetHeight() != 32)
  372.             m_ImageList.Add(CreateAntialiasedBitmap(CutEmptyBorders(img).Rescale(32, 32)));
  373.         else
  374.             m_ImageList.Add(CreateAntialiasedBitmap(img));
  375.     }
  376.     m_HashTable.Put(extension, new wxFileIconEntry(id));
  377.     return id;
  378.  
  379. #else // !wxUSE_MIMETYPE
  380.  
  381.     if (extension == wxT("exe"))
  382.         return FI_EXECUTABLE;
  383.     else
  384.         return FI_UNKNOWN;
  385. #endif // wxUSE_MIMETYPE/!wxUSE_MIMETYPE
  386. }
  387.  
  388.  
  389.  
  390. // ----------------------------------------------------------------------------
  391. // private functions
  392. // ----------------------------------------------------------------------------
  393.  
  394. static
  395. int ListCompare( long data1, long data2, long WXUNUSED(data) )
  396. {
  397.      wxFileData *fd1 = (wxFileData*)data1 ;
  398.      wxFileData *fd2 = (wxFileData*)data2 ;
  399.      if (fd1->GetName() == wxT("..")) return -1;
  400.      if (fd2->GetName() == wxT("..")) return 1;
  401.      if (fd1->IsDir() && !fd2->IsDir()) return -1;
  402.      if (fd2->IsDir() && !fd1->IsDir()) return 1;
  403.      return wxStrcmp( fd1->GetName(), fd2->GetName() );
  404. }
  405.  
  406. #ifdef __UNIX__
  407. #define IsTopMostDir(dir)   (dir == wxT("/"))
  408. #endif
  409.  
  410. #if defined(__DOS__) || defined(__WINDOWS__)
  411. #define IsTopMostDir(dir)   (dir.IsEmpty())
  412. #endif
  413.  
  414. #if defined(__DOS__) || defined(__WINDOWS__)
  415. extern bool wxIsDriveAvailable(const wxString& dirName);
  416. #endif
  417.  
  418. //-----------------------------------------------------------------------------
  419. //  wxFileData
  420. //-----------------------------------------------------------------------------
  421.  
  422. wxFileData::wxFileData( const wxString &name, const wxString &fname )
  423. {
  424.     m_name = name;
  425.     m_fileName = fname;
  426.  
  427. #if defined(__DOS__) || defined(__WINDOWS__)
  428.     // VS: In case the file is root directory of a volume (e.g. "C:"),
  429.     //     we don't want it stat()ed, since the drive may not be in:
  430.     if (name.length() == 2 && name[1u] == wxT(':'))
  431.     {
  432.         m_isDir = TRUE;
  433.         m_isExe = m_isLink = FALSE;
  434.         m_size = 0;
  435.         return;
  436.     }
  437. #endif
  438.  
  439.     wxStructStat buff;
  440.     wxStat( m_fileName, &buff );
  441.  
  442. #if defined(__UNIX__) && (!defined( __EMX__ ) && !defined(__VMS))
  443.     struct stat lbuff;
  444.     lstat( m_fileName.fn_str(), &lbuff );
  445.     m_isLink = S_ISLNK( lbuff.st_mode );
  446.     struct tm *t = localtime( &lbuff.st_mtime );
  447. #else
  448.     m_isLink = FALSE;
  449.     struct tm *t = localtime( &buff.st_mtime );
  450. #endif
  451.  
  452. //  struct passwd *user = getpwuid( buff.st_uid );
  453. //  struct group *grp = getgrgid( buff.st_gid );
  454.  
  455.     m_isDir = S_ISDIR( buff.st_mode );
  456.     m_isExe = ((buff.st_mode & S_IXUSR ) == S_IXUSR );
  457.  
  458.     m_size = buff.st_size;
  459.  
  460.     m_hour = t->tm_hour;
  461.     m_minute = t->tm_min;
  462.     m_month = t->tm_mon+1;
  463.     m_day = t->tm_mday;
  464.     m_year = t->tm_year;
  465.     m_year += 1900;
  466.  
  467.     char buffer[10];
  468.     sprintf( buffer, "%c%c%c",
  469.      ((( buff.st_mode & S_IRUSR ) == S_IRUSR ) ? 'r' : '-'),
  470.      ((( buff.st_mode & S_IWUSR ) == S_IWUSR ) ? 'w' : '-'),
  471.      ((( buff.st_mode & S_IXUSR ) == S_IXUSR ) ? 'x' : '-') );
  472. #if wxUSE_UNICODE
  473.     m_permissions = wxConvUTF8.cMB2WC( buffer );
  474. #else
  475.     m_permissions = buffer;
  476. #endif
  477.  
  478. //    m_permissions.sprintf( wxT("%c%c%c"),
  479. //     ((( buff.st_mode & S_IRUSR ) == S_IRUSR ) ? wxT('r') : wxT('-')),
  480. //     ((( buff.st_mode & S_IWUSR ) == S_IWUSR ) ? wxT('w') : wxT('-')),
  481. //     ((( buff.st_mode & S_IXUSR ) == S_IXUSR ) ? wxT('x') : wxT('-')) );
  482. }
  483.  
  484. wxString wxFileData::GetName() const
  485. {
  486.     return m_name;
  487. }
  488.  
  489. wxString wxFileData::GetFullName() const
  490. {
  491.     return m_fileName;
  492. }
  493.  
  494. wxString wxFileData::GetHint() const
  495. {
  496.     wxString s = m_fileName;
  497.     s += "  ";
  498.     if (m_isDir) s += _("<DIR> ");
  499.     else if (m_isLink) s += _("<LINK> ");
  500.     else
  501.     {
  502.         s += LongToString( m_size );
  503.         s += _(" bytes ");
  504.     }
  505.     s += IntToString( m_day );
  506.     s += wxT(".");
  507.     s += IntToString( m_month );
  508.     s += wxT(".");
  509.     s += IntToString( m_year );
  510.     s += wxT("  ");
  511.     s += IntToString( m_hour );
  512.     s += wxT(":");
  513.     s += IntToString( m_minute );
  514.     s += wxT("  ");
  515.     s += m_permissions;
  516.     return s;
  517. };
  518.  
  519. wxString wxFileData::GetEntry( FileListField num ) const
  520. {
  521.     wxString s;
  522.     switch ( num )
  523.     {
  524.         case FileList_Name:
  525.             s = m_name;
  526.             break;
  527.  
  528.         case FileList_Type:
  529.             if (m_isDir)
  530.                 s = _("<DIR>");
  531.             else if (m_isLink)
  532.                 s = _("<LINK>");
  533.             else
  534.                 s.Printf(_T("%ld"), m_size);
  535.             break;
  536.  
  537.         case FileList_Date:
  538.             s.Printf(_T("%02d.%02d.%d"), m_day, m_month, m_year);
  539.             break;
  540.  
  541.         case FileList_Time:
  542.             s.Printf(_T("%02d:%02d"), m_hour, m_minute);
  543.             break;
  544.  
  545. #ifdef __UNIX__
  546.         case FileList_Perm:
  547.             s = m_permissions;
  548.             break;
  549. #endif // __UNIX__
  550.  
  551.         default:
  552.             wxFAIL_MSG( _T("unexpected field in wxFileData::GetEntry()") );
  553.     }
  554.  
  555.     return s;
  556. }
  557.  
  558. void wxFileData::SetNewName( const wxString &name, const wxString &fname )
  559. {
  560.     m_name = name;
  561.     m_fileName = fname;
  562. }
  563.  
  564. void wxFileData::MakeItem( wxListItem &item )
  565. {
  566.     item.m_text = m_name;
  567.     item.ClearAttributes();
  568.     if (IsExe())
  569.         item.SetTextColour(*wxRED);
  570.     if (IsDir())
  571.         item.SetTextColour(*wxBLUE);
  572.  
  573.     if (IsDir())
  574.         item.m_image = FI_FOLDER;
  575.     else if (IsExe())
  576.         item.m_image = FI_EXECUTABLE;
  577.     else if (m_name.Find(wxT('.')) != wxNOT_FOUND)
  578.         item.m_image = g_IconsTable->GetIconID(m_name.AfterLast(wxT('.')));
  579.     else
  580.         item.m_image = FI_UNKNOWN;
  581.  
  582.     if (IsLink())
  583.     {
  584.         wxColour *dg = wxTheColourDatabase->FindColour( _T("MEDIUM GREY") );
  585.         item.SetTextColour(*dg);
  586.     }
  587.     item.m_data = (long)this;
  588. }
  589.  
  590. //-----------------------------------------------------------------------------
  591. //  wxFileCtrl
  592. //-----------------------------------------------------------------------------
  593.  
  594. IMPLEMENT_DYNAMIC_CLASS(wxFileCtrl,wxListCtrl)
  595.  
  596. BEGIN_EVENT_TABLE(wxFileCtrl,wxListCtrl)
  597.     EVT_LIST_DELETE_ITEM(-1, wxFileCtrl::OnListDeleteItem)
  598.     EVT_LIST_END_LABEL_EDIT(-1, wxFileCtrl::OnListEndLabelEdit)
  599. END_EVENT_TABLE()
  600.  
  601.  
  602. wxFileCtrl::wxFileCtrl()
  603. {
  604.     m_showHidden = FALSE;
  605. }
  606.  
  607. wxFileCtrl::wxFileCtrl(wxWindow *win,
  608.                        wxWindowID id,
  609.                        const wxString& wild,
  610.                        bool showHidden,
  611.                        const wxPoint& pos,
  612.                        const wxSize& size,
  613.                        long style,
  614.                        const wxValidator &validator,
  615.                        const wxString &name)
  616.           : wxListCtrl(win, id, pos, size, style, validator, name),
  617.             m_wild(wild)
  618. {
  619.     if (! g_IconsTable)
  620.         g_IconsTable = new wxFileIconsTable;
  621.     wxImageList *imageList = g_IconsTable->GetImageList();
  622.  
  623.     SetImageList( imageList, wxIMAGE_LIST_SMALL );
  624.  
  625.     m_goToParentControl =
  626.     m_newDirControl = NULL;
  627.  
  628.     m_showHidden = showHidden;
  629. }
  630.  
  631. void wxFileCtrl::ChangeToListMode()
  632. {
  633.     SetSingleStyle( wxLC_LIST );
  634.     UpdateFiles();
  635. }
  636.  
  637. void wxFileCtrl::ChangeToReportMode()
  638. {
  639.     SetSingleStyle( wxLC_REPORT );
  640.     UpdateFiles();
  641. }
  642.  
  643. void wxFileCtrl::ChangeToIconMode()
  644. {
  645.     SetSingleStyle( wxLC_ICON );
  646.     UpdateFiles();
  647. }
  648.  
  649. void wxFileCtrl::ShowHidden( bool show )
  650. {
  651.     m_showHidden = show;
  652.     UpdateFiles();
  653. }
  654.  
  655. long wxFileCtrl::Add( wxFileData *fd, wxListItem &item )
  656. {
  657.     long ret = -1;
  658.     item.m_mask = wxLIST_MASK_TEXT + wxLIST_MASK_DATA + wxLIST_MASK_IMAGE;
  659.     fd->MakeItem( item );
  660.     long my_style = GetWindowStyleFlag();
  661.     if (my_style & wxLC_REPORT)
  662.     {
  663.         ret = InsertItem( item );
  664.         for (int i = 1; i < FileList_Max; i++)
  665.             SetItem( item.m_itemId, i, fd->GetEntry((FileListField)i) );
  666.     }
  667.     else if (my_style & wxLC_LIST)
  668.     {
  669.         ret = InsertItem( item );
  670.     }
  671.     return ret;
  672. }
  673.  
  674. void wxFileCtrl::UpdateFiles()
  675. {
  676.     wxBusyCursor bcur; // this may take a while...
  677.  
  678.     long my_style = GetWindowStyleFlag();
  679.     int name_col_width = 0;
  680.     if (my_style & wxLC_REPORT)
  681.     {
  682.         if (GetColumnCount() > 0)
  683.             name_col_width = GetColumnWidth( 0 );
  684.     }
  685.  
  686.     FreeAllItemsData();
  687.     ClearAll();
  688.  
  689.     if (my_style & wxLC_REPORT)
  690.     {
  691.         if (name_col_width < 140) name_col_width = 140;
  692.         InsertColumn( 0, _("Name"), wxLIST_FORMAT_LEFT, name_col_width );
  693.         InsertColumn( 1, _("Size"), wxLIST_FORMAT_LEFT, 60 );
  694.         InsertColumn( 2, _("Date"), wxLIST_FORMAT_LEFT, 65 );
  695.         InsertColumn( 3, _("Time"), wxLIST_FORMAT_LEFT, 50 );
  696. #ifdef __UNIX__
  697.         InsertColumn( 4, _("Permissions"), wxLIST_FORMAT_LEFT, 120 );
  698. #endif
  699.     }
  700.     wxFileData *fd = (wxFileData *) NULL;
  701.     wxListItem item;
  702.     item.m_itemId = 0;
  703.     item.m_col = 0;
  704.  
  705. #if defined(__DOS__) || defined(__WINDOWS__)
  706.     if ( IsTopMostDir(m_dirName) )
  707.     {
  708.         // Pseudo-directory with all available drives listed...
  709.         for (int drive = 1; drive <= 26; drive++)
  710.         {
  711.             wxString path;
  712.             path.Printf(wxT("%c:\\"), (char)(drive + 'A' - 1));
  713.             if ( wxIsDriveAvailable(path) )
  714.             {
  715.                 path.RemoveLast();
  716.                 fd = new wxFileData(path, path);
  717.                 Add(fd, item);
  718.                 item.m_itemId++;
  719.             }
  720.         }
  721.     }
  722.     else
  723. #endif
  724.     {
  725.         // Real directory...
  726.         if ( !IsTopMostDir(m_dirName) )
  727.         {
  728.             wxString p(wxPathOnly(m_dirName));
  729. #ifdef __UNIX__
  730.             if (p.IsEmpty()) p = wxT("/");
  731. #endif
  732.             fd = new wxFileData( wxT(".."), p );
  733.             Add(fd, item);
  734.             item.m_itemId++;
  735.         }
  736.  
  737.         wxString dirname(m_dirName);
  738. #if defined(__DOS__) || defined(__WINDOWS__)
  739.         if (dirname.length() == 2 && dirname[1u] == wxT(':'))
  740.             dirname << wxT('\\');
  741. #endif
  742.         wxDir dir(dirname);
  743.  
  744.         if ( dir.IsOpened() )
  745.         {
  746.             wxString dirPrefix(dirname + wxFILE_SEP_PATH);
  747.             int hiddenFlag = m_showHidden ? wxDIR_HIDDEN : 0;
  748.  
  749.             bool cont;
  750.             wxString f;
  751.  
  752.             // Get the directories first (not matched against wildcards):
  753.             cont = dir.GetFirst(&f, wxEmptyString, wxDIR_DIRS | hiddenFlag);
  754.             while (cont)
  755.             {
  756.                 fd = new wxFileData(f, dirPrefix + f);
  757.                 Add(fd, item);
  758.                 item.m_itemId++;
  759.                 cont = dir.GetNext(&f);
  760.             }
  761.  
  762.             // Tokenize the wildcard string, so we can handle more than 1
  763.             // search pattern in a wildcard.
  764.             wxStringTokenizer tokenWild(m_wild, wxT(";"));
  765.             while ( tokenWild.HasMoreTokens() )
  766.             {
  767.                 cont = dir.GetFirst(&f, tokenWild.GetNextToken(),
  768.                                         wxDIR_FILES | hiddenFlag);
  769.                 while (cont)
  770.                 {
  771.                     fd = new wxFileData(f, dirPrefix + f);
  772.                     Add(fd, item);
  773.                     item.m_itemId++;
  774.                     cont = dir.GetNext(&f);
  775.                 }
  776.             }
  777.         }
  778.     }
  779.  
  780.     SortItems(ListCompare, 0);
  781.  
  782.     if ( my_style & wxLC_REPORT )
  783.     {
  784.        SetColumnWidth(1, wxLIST_AUTOSIZE);
  785.        SetColumnWidth(2, wxLIST_AUTOSIZE);
  786.        SetColumnWidth(3, wxLIST_AUTOSIZE);
  787.     }
  788.  
  789.     // Finally, enable/disable context-dependent controls:
  790.     if ( m_goToParentControl )
  791.         m_goToParentControl->Enable(!IsTopMostDir(m_dirName));
  792. #if defined(__DOS__) || defined(__WINDOWS__)
  793.     if ( m_newDirControl )
  794.         m_newDirControl->Enable(!IsTopMostDir(m_dirName));
  795. #endif
  796. }
  797.  
  798. void wxFileCtrl::SetWild( const wxString &wild )
  799. {
  800.     m_wild = wild;
  801.     UpdateFiles();
  802. }
  803.  
  804. void wxFileCtrl::MakeDir()
  805. {
  806.     wxString new_name( _("NewName") );
  807.     wxString path( m_dirName );
  808.     path += wxFILE_SEP_PATH;
  809.     path += new_name;
  810.     if (wxFileExists(path))
  811.     {
  812.         // try NewName0, NewName1 etc.
  813.         int i = 0;
  814.         do {
  815.             new_name = _("NewName");
  816.             wxString num;
  817.             num.Printf( wxT("%d"), i );
  818.             new_name += num;
  819.  
  820.             path = m_dirName;
  821.             path += wxFILE_SEP_PATH;
  822.             path += new_name;
  823.             i++;
  824.         } while (wxFileExists(path));
  825.     }
  826.  
  827.     wxLogNull log;
  828.     if (!wxMkdir(path))
  829.     {
  830.         wxMessageDialog dialog(this, _("Operation not permitted."), _("Error"), wxOK | wxICON_ERROR );
  831.         dialog.ShowModal();
  832.         return;
  833.     }
  834.  
  835.     wxFileData *fd = new wxFileData( new_name, path );
  836.     wxListItem item;
  837.     item.m_itemId = 0;
  838.     item.m_col = 0;
  839.     long id = Add( fd, item );
  840.  
  841.     if (id != -1)
  842.     {
  843.         SortItems( ListCompare, 0 );
  844.         id = FindItem( 0, (long)fd );
  845.         EnsureVisible( id );
  846.         EditLabel( id );
  847.     }
  848. }
  849.  
  850. void wxFileCtrl::GoToParentDir()
  851. {
  852.     if (!IsTopMostDir(m_dirName))
  853.     {
  854.         size_t len = m_dirName.Len();
  855.         if (m_dirName[len-1] == wxFILE_SEP_PATH)
  856.             m_dirName.Remove( len-1, 1 );
  857.         wxString fname( wxFileNameFromPath(m_dirName) );
  858.         m_dirName = wxPathOnly( m_dirName );
  859. #ifdef __UNIX__
  860.         if (m_dirName.IsEmpty())
  861.             m_dirName = wxT("/");
  862. #endif
  863.         UpdateFiles();
  864.         long id = FindItem( 0, fname );
  865.         if (id != -1)
  866.         {
  867.             SetItemState( id, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED );
  868.             EnsureVisible( id );
  869.         }
  870.     }
  871. }
  872.  
  873. void wxFileCtrl::GoToHomeDir()
  874. {
  875.     wxString s = wxGetUserHome( wxString() );
  876.     GoToDir(s);
  877. }
  878.  
  879. void wxFileCtrl::GoToDir( const wxString &dir )
  880. {
  881.     m_dirName = dir;
  882.     UpdateFiles();
  883.     SetItemState( 0, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED );
  884.     EnsureVisible( 0 );
  885. }
  886.  
  887. void wxFileCtrl::GetDir( wxString &dir )
  888. {
  889.     dir = m_dirName;
  890. }
  891.  
  892. void wxFileCtrl::FreeItemData(const wxListItem& item)
  893. {
  894.     wxFileData *fd = (wxFileData*)item.m_data;
  895.     delete fd;
  896. }
  897.  
  898. void wxFileCtrl::OnListDeleteItem( wxListEvent &event )
  899. {
  900.     FreeItemData(event.m_item);
  901. }
  902.  
  903. void wxFileCtrl::FreeAllItemsData()
  904. {
  905.     wxListItem item;
  906.     item.m_mask = wxLIST_MASK_DATA;
  907.  
  908.     item.m_itemId = GetNextItem( -1, wxLIST_NEXT_ALL );
  909.     while ( item.m_itemId != -1 )
  910.     {
  911.         GetItem( item );
  912.         FreeItemData(item);
  913.         item.m_itemId = GetNextItem( item.m_itemId, wxLIST_NEXT_ALL );
  914.     }
  915. }
  916.  
  917. void wxFileCtrl::OnListEndLabelEdit( wxListEvent &event )
  918. {
  919.     wxFileData *fd = (wxFileData*)event.m_item.m_data;
  920.     wxASSERT( fd );
  921.  
  922.     if ((event.GetLabel().IsEmpty()) ||
  923.         (event.GetLabel() == _(".")) ||
  924.         (event.GetLabel() == _("..")) ||
  925.         (event.GetLabel().First( wxFILE_SEP_PATH ) != wxNOT_FOUND))
  926.     {
  927.         wxMessageDialog dialog(this, _("Illegal directory name."), _("Error"), wxOK | wxICON_ERROR );
  928.         dialog.ShowModal();
  929.         event.Veto();
  930.         return;
  931.     }
  932.  
  933.     wxString new_name( wxPathOnly( fd->GetFullName() ) );
  934.     new_name += wxFILE_SEP_PATH;
  935.     new_name += event.GetLabel();
  936.  
  937.     wxLogNull log;
  938.  
  939.     if (wxFileExists(new_name))
  940.     {
  941.         wxMessageDialog dialog(this, _("File name exists already."), _("Error"), wxOK | wxICON_ERROR );
  942.         dialog.ShowModal();
  943.         event.Veto();
  944.     }
  945.  
  946.     if (wxRenameFile(fd->GetFullName(),new_name))
  947.     {
  948.         fd->SetNewName( new_name, event.GetLabel() );
  949.         SetItemState( event.GetItem(), wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED );
  950.         EnsureVisible( event.GetItem() );
  951.     }
  952.     else
  953.     {
  954.         wxMessageDialog dialog(this, _("Operation not permitted."), _("Error"), wxOK | wxICON_ERROR );
  955.         dialog.ShowModal();
  956.         event.Veto();
  957.     }
  958. }
  959.  
  960. wxFileCtrl::~wxFileCtrl()
  961. {
  962.     FreeAllItemsData();
  963. }
  964.  
  965. //-----------------------------------------------------------------------------
  966. // wxFileDialog
  967. //-----------------------------------------------------------------------------
  968.  
  969. #define  ID_LIST_MODE     (wxID_FILEDLGG    )
  970. #define  ID_REPORT_MODE   (wxID_FILEDLGG + 1)
  971. #define  ID_UP_DIR        (wxID_FILEDLGG + 5)
  972. #define  ID_PARENT_DIR    (wxID_FILEDLGG + 6)
  973. #define  ID_NEW_DIR       (wxID_FILEDLGG + 7)
  974. #define  ID_CHOICE        (wxID_FILEDLGG + 8)
  975. #define  ID_TEXT          (wxID_FILEDLGG + 9)
  976. #define  ID_LIST_CTRL     (wxID_FILEDLGG + 10)
  977. #define  ID_ACTIVATED     (wxID_FILEDLGG + 11)
  978. #define  ID_CHECK         (wxID_FILEDLGG + 12)
  979.  
  980. IMPLEMENT_DYNAMIC_CLASS(wxFileDialog,wxDialog)
  981.  
  982. BEGIN_EVENT_TABLE(wxFileDialog,wxDialog)
  983.         EVT_BUTTON(ID_LIST_MODE, wxFileDialog::OnList)
  984.         EVT_BUTTON(ID_REPORT_MODE, wxFileDialog::OnReport)
  985.         EVT_BUTTON(ID_UP_DIR, wxFileDialog::OnUp)
  986.         EVT_BUTTON(ID_PARENT_DIR, wxFileDialog::OnHome)
  987.         EVT_BUTTON(ID_NEW_DIR, wxFileDialog::OnNew)
  988.         EVT_BUTTON(wxID_OK, wxFileDialog::OnListOk)
  989.         EVT_LIST_ITEM_SELECTED(ID_LIST_CTRL, wxFileDialog::OnSelected)
  990.         EVT_LIST_ITEM_ACTIVATED(ID_LIST_CTRL, wxFileDialog::OnActivated)
  991.         EVT_CHOICE(ID_CHOICE,wxFileDialog::OnChoice)
  992.         EVT_TEXT_ENTER(ID_TEXT,wxFileDialog::OnTextEnter)
  993.         EVT_CHECKBOX(ID_CHECK,wxFileDialog::OnCheck)
  994. END_EVENT_TABLE()
  995.  
  996. long wxFileDialog::ms_lastViewStyle = wxLC_LIST;
  997. bool wxFileDialog::ms_lastShowHidden = FALSE;
  998.  
  999. wxFileDialog::wxFileDialog(wxWindow *parent,
  1000.                            const wxString& message,
  1001.                            const wxString& defaultDir,
  1002.                            const wxString& defaultFile,
  1003.                            const wxString& wildCard,
  1004.                            long style,
  1005.                            const wxPoint& pos )
  1006.             : wxDialog( parent, -1, message, pos, wxDefaultSize,
  1007.                         wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER )
  1008. {
  1009.     if (wxConfig::Get(FALSE))
  1010.     {
  1011.         wxConfig::Get()->Read(wxT("/wxWindows/wxFileDialog/ViewStyle"),
  1012.                               &ms_lastViewStyle);
  1013.         wxConfig::Get()->Read(wxT("/wxWindows/wxFileDialog/ShowHidden"),
  1014.                               &ms_lastShowHidden);
  1015.     }
  1016.  
  1017.     m_message = message;
  1018.     m_dialogStyle = style;
  1019.  
  1020.     if (m_dialogStyle == 0)
  1021.         m_dialogStyle = wxOPEN;
  1022.     if ((m_dialogStyle & wxMULTIPLE ) && !(m_dialogStyle & wxOPEN))
  1023.         m_dialogStyle |= wxOPEN;
  1024.  
  1025.     m_dir = defaultDir;
  1026.     if ((m_dir.empty()) || (m_dir == wxT(".")))
  1027.     {
  1028.         m_dir = wxGetCwd();
  1029.     }
  1030.  
  1031.     size_t len = m_dir.Len();
  1032.     if ((len > 1) && (m_dir[len-1] == wxFILE_SEP_PATH))
  1033.         m_dir.Remove( len-1, 1 );
  1034.  
  1035.     m_path = m_dir;
  1036.     m_path += wxFILE_SEP_PATH;
  1037.     m_path += defaultFile;
  1038.     m_fileName = defaultFile;
  1039.     m_wildCard = wildCard;
  1040.     m_filterIndex = 0;
  1041.     m_filterExtension = wxEmptyString;
  1042.  
  1043.     // interpret wildcards
  1044.  
  1045.     if (m_wildCard.IsEmpty())
  1046.         m_wildCard = _("All files (*)|*");
  1047.  
  1048.     wxStringTokenizer tokens( m_wildCard, wxT("|") );
  1049.     wxString firstWild;
  1050.     wxString firstWildText;
  1051.     if (tokens.CountTokens() == 1)
  1052.     {
  1053.         firstWildText = tokens.GetNextToken();
  1054.         firstWild = firstWildText;
  1055.     }
  1056.     else
  1057.     {
  1058.         wxASSERT_MSG( tokens.CountTokens() % 2 == 0, wxT("Wrong file type descripition") );
  1059.         firstWildText = tokens.GetNextToken();
  1060.         firstWild = tokens.GetNextToken();
  1061.     }
  1062.     if ( firstWild.Left( 2 ) == wxT("*.") )
  1063.         m_filterExtension = firstWild.Mid( 1 );
  1064.     if ( m_filterExtension == ".*" ) m_filterExtension = wxEmptyString;
  1065.  
  1066.     // layout
  1067.  
  1068.     wxBoxSizer *mainsizer = new wxBoxSizer( wxVERTICAL );
  1069.  
  1070.     wxBoxSizer *buttonsizer = new wxBoxSizer( wxHORIZONTAL );
  1071.  
  1072.     wxBitmapButton *but;
  1073.  
  1074.     but = new wxBitmapButton(this, ID_LIST_MODE,
  1075.                              wxArtProvider::GetBitmap(wxART_LIST_VIEW, wxART_CMN_DIALOG));
  1076. #if wxUSE_TOOLTIPS
  1077.     but->SetToolTip( _("View files as a list view") );
  1078. #endif
  1079.     buttonsizer->Add( but, 0, wxALL, 5 );
  1080.  
  1081.     but = new wxBitmapButton(this, ID_REPORT_MODE,
  1082.                              wxArtProvider::GetBitmap(wxART_REPORT_VIEW, wxART_CMN_DIALOG));
  1083. #if wxUSE_TOOLTIPS
  1084.     but->SetToolTip( _("View files as a detailed view") );
  1085. #endif
  1086.     buttonsizer->Add( but, 0, wxALL, 5 );
  1087.  
  1088.     buttonsizer->Add( 30, 5, 1 );
  1089.  
  1090.     wxWindow *butDirUp =
  1091.         new wxBitmapButton(this, ID_UP_DIR,
  1092.                            wxArtProvider::GetBitmap(wxART_GO_DIR_UP, wxART_CMN_DIALOG));
  1093. #if wxUSE_TOOLTIPS
  1094.     butDirUp->SetToolTip( _("Go to parent directory") );
  1095. #endif
  1096.     buttonsizer->Add( butDirUp, 0, wxALL, 5 );
  1097.  
  1098. #ifndef __DOS__ // VS: Home directory is meaningless in MS-DOS...
  1099.     but = new wxBitmapButton(this, ID_PARENT_DIR,
  1100.                              wxArtProvider::GetBitmap(wxART_GO_HOME, wxART_CMN_DIALOG));
  1101. #if wxUSE_TOOLTIPS
  1102.     but->SetToolTip( _("Go to home directory") );
  1103. #endif
  1104.     buttonsizer->Add( but, 0, wxALL, 5);
  1105.  
  1106.     buttonsizer->Add( 20, 20 );
  1107. #endif //!__DOS__
  1108.  
  1109.     wxWindow *butNewDir =
  1110.         new wxBitmapButton(this, ID_NEW_DIR,
  1111.                            wxArtProvider::GetBitmap(wxART_NEW_DIR, wxART_CMN_DIALOG));
  1112. #if wxUSE_TOOLTIPS
  1113.     butNewDir->SetToolTip( _("Create new directory") );
  1114. #endif
  1115.     buttonsizer->Add( butNewDir, 0, wxALL, 5 );
  1116.  
  1117.     if (wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA)
  1118.         mainsizer->Add( buttonsizer, 0, wxALL | wxEXPAND, 0 );
  1119.     else
  1120.         mainsizer->Add( buttonsizer, 0, wxALL | wxEXPAND, 5 );
  1121.  
  1122.     wxBoxSizer *staticsizer = new wxBoxSizer( wxHORIZONTAL );
  1123.     if (wxSystemSettings::GetScreenType() > wxSYS_SCREEN_PDA)
  1124.         staticsizer->Add( new wxStaticText( this, -1, _("Current directory:") ), 0, wxRIGHT, 10 );
  1125.     m_static = new wxStaticText( this, -1, m_dir );
  1126.     staticsizer->Add( m_static, 1 );
  1127.     mainsizer->Add( staticsizer, 0, wxEXPAND | wxLEFT|wxRIGHT|wxBOTTOM, 10 );
  1128.  
  1129.     long style2 = ms_lastViewStyle | wxSUNKEN_BORDER;
  1130.     if ( !(m_dialogStyle & wxMULTIPLE) )
  1131.         style2 |= wxLC_SINGLE_SEL;
  1132.  
  1133.     m_list = new wxFileCtrl( this, ID_LIST_CTRL, firstWild, ms_lastShowHidden,
  1134.                              wxDefaultPosition, wxSize(540,200),
  1135.                              style2);
  1136.  
  1137.     m_list->SetNewDirControl(butNewDir);
  1138.     m_list->SetGoToParentControl(butDirUp);
  1139.  
  1140.     if (wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA)
  1141.     {
  1142.         // PDAs have a different screen layout
  1143.         mainsizer->Add( m_list, 1, wxEXPAND | wxLEFT|wxRIGHT, 5 );
  1144.  
  1145.         wxBoxSizer *choicesizer = new wxBoxSizer( wxHORIZONTAL );
  1146.         m_choice = new wxChoice( this, ID_CHOICE );
  1147.         choicesizer->Add( m_choice, 1, wxCENTER|wxALL, 5 );
  1148.         mainsizer->Add( choicesizer, 0, wxEXPAND );
  1149.  
  1150.         wxBoxSizer *textsizer = new wxBoxSizer( wxHORIZONTAL );
  1151.         m_text = new wxTextCtrl( this, ID_TEXT, m_fileName, wxDefaultPosition, wxDefaultSize, wxPROCESS_ENTER );
  1152.         textsizer->Add( m_text, 1, wxCENTER | wxALL, 5 );
  1153.         mainsizer->Add( textsizer, 0, wxEXPAND );
  1154.  
  1155.         m_check = new wxCheckBox( this, ID_CHECK, _("Show hidden files") );
  1156.         m_check->SetValue( ms_lastShowHidden );
  1157.         textsizer->Add( m_check, 0, wxCENTER|wxALL, 5 );
  1158.  
  1159.         buttonsizer = new wxBoxSizer( wxHORIZONTAL );
  1160.         buttonsizer->Add( new wxButton( this, wxID_OK, _("OK") ), 0, wxCENTER | wxALL, 5 );
  1161.         buttonsizer->Add( new wxButton( this, wxID_CANCEL, _("Cancel") ), 0, wxCENTER | wxALL, 5 );
  1162.         mainsizer->Add( buttonsizer, 0, wxALIGN_RIGHT );
  1163.     }
  1164.     else
  1165.     {
  1166.         mainsizer->Add( m_list, 1, wxEXPAND | wxLEFT|wxRIGHT, 10 );
  1167.  
  1168.         wxBoxSizer *textsizer = new wxBoxSizer( wxHORIZONTAL );
  1169.         m_text = new wxTextCtrl( this, ID_TEXT, m_fileName, wxDefaultPosition, wxDefaultSize, wxPROCESS_ENTER );
  1170.         textsizer->Add( m_text, 1, wxCENTER | wxLEFT|wxRIGHT|wxTOP, 10 );
  1171.         textsizer->Add( new wxButton( this, wxID_OK, _("OK") ), 0, wxCENTER | wxLEFT|wxRIGHT|wxTOP, 10 );
  1172.         mainsizer->Add( textsizer, 0, wxEXPAND );
  1173.  
  1174.         wxBoxSizer *choicesizer = new wxBoxSizer( wxHORIZONTAL );
  1175.         m_choice = new wxChoice( this, ID_CHOICE );
  1176.         choicesizer->Add( m_choice, 1, wxCENTER|wxALL, 10 );
  1177.         m_check = new wxCheckBox( this, ID_CHECK, _("Show hidden files") );
  1178.         m_check->SetValue( ms_lastShowHidden );
  1179.         choicesizer->Add( m_check, 0, wxCENTER|wxALL, 10 );
  1180.         choicesizer->Add( new wxButton( this, wxID_CANCEL, _("Cancel") ), 0, wxCENTER | wxALL, 10 );
  1181.         mainsizer->Add( choicesizer, 0, wxEXPAND );
  1182.     }
  1183.  
  1184.     m_choice->Append( firstWildText, (void*) new wxString( firstWild ) );
  1185.     while (tokens.HasMoreTokens())
  1186.     {
  1187.         firstWildText = tokens.GetNextToken();
  1188.         firstWild = tokens.GetNextToken();
  1189.         m_choice->Append( firstWildText, (void*) new wxString( firstWild ) );
  1190.     }
  1191.     m_choice->SetSelection( 0 );
  1192.  
  1193.     SetAutoLayout( TRUE );
  1194.     SetSizer( mainsizer );
  1195.  
  1196.     mainsizer->Fit( this );
  1197.     mainsizer->SetSizeHints( this );
  1198.  
  1199.     Centre( wxBOTH );
  1200.  
  1201.     m_text->SetFocus();
  1202. }
  1203.  
  1204. wxFileDialog::~wxFileDialog()
  1205. {
  1206.     if (wxConfig::Get(FALSE))
  1207.     {
  1208.         wxConfig::Get()->Write(wxT("/wxWindows/wxFileDialog/ViewStyle"),
  1209.                                ms_lastViewStyle);
  1210.         wxConfig::Get()->Write(wxT("/wxWindows/wxFileDialog/ShowHidden"),
  1211.                                ms_lastShowHidden);
  1212.     }
  1213. }
  1214.  
  1215. int wxFileDialog::ShowModal()
  1216. {
  1217.     m_list->GoToDir(m_dir);
  1218.  
  1219.     return wxDialog::ShowModal();
  1220. }
  1221.  
  1222. void wxFileDialog::SetFilterIndex( int filterindex )
  1223. {
  1224.     m_choice->SetSelection( filterindex );
  1225.     wxCommandEvent event;
  1226.     event.SetInt( filterindex );
  1227.     OnChoice( event );
  1228. }
  1229.  
  1230. void wxFileDialog::OnChoice( wxCommandEvent &event )
  1231. {
  1232.     int index = (int)event.GetInt();
  1233.     wxString *str = (wxString*) m_choice->GetClientData( index );
  1234.     m_list->SetWild( *str );
  1235.     m_filterIndex = index;
  1236.     if ( str -> Left( 2 ) == wxT("*.") )
  1237.     {
  1238.         m_filterExtension = str -> Mid( 1 );
  1239.         if (m_filterExtension == ".*") m_filterExtension = wxEmptyString;
  1240.     }
  1241.     else
  1242.         m_filterExtension = wxEmptyString;
  1243. }
  1244.  
  1245. void wxFileDialog::OnCheck( wxCommandEvent &event )
  1246. {
  1247.     m_list->ShowHidden( (ms_lastShowHidden = event.GetInt() != 0) );
  1248. }
  1249.  
  1250. void wxFileDialog::OnActivated( wxListEvent &event )
  1251. {
  1252.     HandleAction( event.m_item.m_text );
  1253. }
  1254.  
  1255. void wxFileDialog::OnTextEnter( wxCommandEvent &WXUNUSED(event) )
  1256. {
  1257.     wxCommandEvent cevent(wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK);
  1258.     cevent.SetEventObject( this );
  1259.     GetEventHandler()->ProcessEvent( cevent );
  1260. }
  1261.  
  1262. void wxFileDialog::OnSelected( wxListEvent &event )
  1263. {
  1264.     wxString filename( event.m_item.m_text );
  1265.     if (filename == wxT("..")) return;
  1266.  
  1267.     wxString dir;
  1268.     m_list->GetDir( dir );
  1269.     if (!IsTopMostDir(dir))
  1270.         dir += wxFILE_SEP_PATH;
  1271.     dir += filename;
  1272.     if (wxDirExists(dir)) return;
  1273.  
  1274.     m_text->SetValue( filename );
  1275. }
  1276.  
  1277. void wxFileDialog::HandleAction( const wxString &fn )
  1278. {
  1279.     wxString filename( fn );
  1280.     wxString dir;
  1281.     m_list->GetDir( dir );
  1282.     if (filename.IsEmpty()) return;
  1283.     if (filename == wxT(".")) return;
  1284.  
  1285.     if (filename == wxT(".."))
  1286.     {
  1287.         m_list->GoToParentDir();
  1288.         m_list->SetFocus();
  1289.         m_list->GetDir( dir );
  1290.         m_static->SetLabel( dir );
  1291.         return;
  1292.     }
  1293.  
  1294. #ifdef __UNIX__
  1295.     if (filename == wxT("~"))
  1296.     {
  1297.         m_list->GoToHomeDir();
  1298.         m_list->SetFocus();
  1299.         m_list->GetDir( dir );
  1300.         m_static->SetLabel( dir );
  1301.         return;
  1302.     }
  1303.  
  1304.     if (filename[0u] == wxT('~'))
  1305.     {
  1306.         filename.Remove( 0, 1 );
  1307.         wxString tmp( wxGetUserHome() );
  1308.         tmp += wxT('/');
  1309.         tmp += filename;
  1310.         filename = tmp;
  1311.     }
  1312. #endif // __UNIX__
  1313.  
  1314.     if ((filename.Find(wxT('*')) != wxNOT_FOUND) ||
  1315.         (filename.Find(wxT('?')) != wxNOT_FOUND))
  1316.     {
  1317.         if (filename.Find(wxFILE_SEP_PATH) != wxNOT_FOUND)
  1318.         {
  1319.             wxMessageBox(_("Illegal file specification."), _("Error"), wxOK | wxICON_ERROR );
  1320.             return;
  1321.         }
  1322.         m_list->SetWild( filename );
  1323.         return;
  1324.     }
  1325.  
  1326.     if (!IsTopMostDir(dir))
  1327.         dir += wxFILE_SEP_PATH;
  1328.     if (!wxIsAbsolutePath(filename))
  1329.     {
  1330.         dir += filename;
  1331.         filename = dir;
  1332.     }
  1333.  
  1334.     if (wxDirExists(filename))
  1335.     {
  1336.         m_list->GoToDir( filename );
  1337.         m_list->GetDir( dir );
  1338.         m_static->SetLabel( dir );
  1339.         return;
  1340.     }
  1341.  
  1342.  
  1343.     if ( (m_dialogStyle & wxSAVE) && (m_dialogStyle & wxOVERWRITE_PROMPT) )
  1344.     {
  1345.         if (filename.Find( wxT('.') ) == wxNOT_FOUND ||
  1346.                 filename.AfterLast( wxT('.') ).Find( wxFILE_SEP_PATH ) != wxNOT_FOUND)
  1347.             filename << m_filterExtension;
  1348.         if (wxFileExists( filename ))
  1349.         {
  1350.             wxString msg;
  1351.             msg.Printf( _("File '%s' already exists, do you really want to "
  1352.                          "overwrite it?"), filename.c_str() );
  1353.  
  1354.             if (wxMessageBox(msg, _("Confirm"), wxYES_NO) != wxYES)
  1355.                 return;
  1356.         }
  1357.     }
  1358.     else if ( m_dialogStyle & wxOPEN )
  1359.     {
  1360.         if ( !wxFileExists( filename ) )
  1361.             if (filename.Find( wxT('.') ) == wxNOT_FOUND ||
  1362.                   filename.AfterLast( wxT('.') ).Find( wxFILE_SEP_PATH ) != wxNOT_FOUND)
  1363.                 filename << m_filterExtension;
  1364.  
  1365.         if ( m_dialogStyle & wxFILE_MUST_EXIST )
  1366.         {
  1367.             if ( !wxFileExists( filename ) )
  1368.             {
  1369.                 wxMessageBox(_("Please choose an existing file."), _("Error"), wxOK | wxICON_ERROR );
  1370.                 return;
  1371.             }
  1372.         }
  1373.     }
  1374.  
  1375.     SetPath( filename );
  1376.  
  1377.     // change to the directory where the user went if asked
  1378.     if ( m_dialogStyle & wxCHANGE_DIR )
  1379.     {
  1380.         wxString cwd;
  1381.         wxSplitPath(filename, &cwd, NULL, NULL);
  1382.  
  1383.         if ( cwd != wxGetWorkingDirectory() )
  1384.         {
  1385.             wxSetWorkingDirectory(cwd);
  1386.         }
  1387.     }
  1388.  
  1389.     wxCommandEvent event;
  1390.     wxDialog::OnOK(event);
  1391. }
  1392.  
  1393. void wxFileDialog::OnListOk( wxCommandEvent &WXUNUSED(event) )
  1394. {
  1395.     HandleAction( m_text->GetValue() );
  1396. }
  1397.  
  1398. void wxFileDialog::OnList( wxCommandEvent &WXUNUSED(event) )
  1399. {
  1400.     m_list->ChangeToListMode();
  1401.     ms_lastViewStyle = wxLC_LIST;
  1402.     m_list->SetFocus();
  1403. }
  1404.  
  1405. void wxFileDialog::OnReport( wxCommandEvent &WXUNUSED(event) )
  1406. {
  1407.     m_list->ChangeToReportMode();
  1408.     ms_lastViewStyle = wxLC_REPORT;
  1409.     m_list->SetFocus();
  1410. }
  1411.  
  1412. void wxFileDialog::OnUp( wxCommandEvent &WXUNUSED(event) )
  1413. {
  1414.     m_list->GoToParentDir();
  1415.     m_list->SetFocus();
  1416.     wxString dir;
  1417.     m_list->GetDir( dir );
  1418.     m_static->SetLabel( dir );
  1419. }
  1420.  
  1421. void wxFileDialog::OnHome( wxCommandEvent &WXUNUSED(event) )
  1422. {
  1423.     m_list->GoToHomeDir();
  1424.     m_list->SetFocus();
  1425.     wxString dir;
  1426.     m_list->GetDir( dir );
  1427.     m_static->SetLabel( dir );
  1428.  
  1429.     m_text->SetFocus();
  1430. }
  1431.  
  1432. void wxFileDialog::OnNew( wxCommandEvent &WXUNUSED(event) )
  1433. {
  1434.     m_list->MakeDir();
  1435. }
  1436.  
  1437. void wxFileDialog::SetPath( const wxString& path )
  1438. {
  1439.     // not only set the full path but also update filename and dir
  1440.     m_path = path;
  1441.     if ( !path.empty() )
  1442.     {
  1443.         wxString ext;
  1444.         wxSplitPath(path, &m_dir, &m_fileName, &ext);
  1445.         if (!ext.empty())
  1446.         {
  1447.             m_fileName += wxT(".");
  1448.             m_fileName += ext;
  1449.         }
  1450.     }
  1451. }
  1452.  
  1453. void wxFileDialog::GetPaths( wxArrayString& paths ) const
  1454. {
  1455.     paths.Empty();
  1456.     if (m_list->GetSelectedItemCount() == 0)
  1457.     {
  1458.         paths.Add( GetPath() );
  1459.         return;
  1460.     }
  1461.  
  1462.     paths.Alloc( m_list->GetSelectedItemCount() );
  1463.  
  1464.     wxString dir;
  1465.     m_list->GetDir( dir );
  1466. #ifdef __UNIX__
  1467.     if (dir != wxT("/"))
  1468. #endif
  1469.         dir += wxFILE_SEP_PATH;
  1470.  
  1471.     wxListItem item;
  1472.     item.m_mask = wxLIST_MASK_TEXT;
  1473.  
  1474.     item.m_itemId = m_list->GetNextItem( -1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED );
  1475.     while ( item.m_itemId != -1 )
  1476.     {
  1477.         m_list->GetItem( item );
  1478.         paths.Add( dir + item.m_text );
  1479.         item.m_itemId = m_list->GetNextItem( item.m_itemId,
  1480.             wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED );
  1481.     }
  1482. }
  1483.  
  1484. void wxFileDialog::GetFilenames(wxArrayString& files) const
  1485. {
  1486.     files.Empty();
  1487.     if (m_list->GetSelectedItemCount() == 0)
  1488.     {
  1489.         files.Add( GetFilename() );
  1490.         return;
  1491.     }
  1492.     files.Alloc( m_list->GetSelectedItemCount() );
  1493.  
  1494.     wxListItem item;
  1495.     item.m_mask = wxLIST_MASK_TEXT;
  1496.  
  1497.     item.m_itemId = m_list->GetNextItem( -1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED );
  1498.     while ( item.m_itemId != -1 )
  1499.     {
  1500.         m_list->GetItem( item );
  1501.         files.Add( item.m_text );
  1502.         item.m_itemId = m_list->GetNextItem( item.m_itemId,
  1503.             wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED );
  1504.     }
  1505. }
  1506.  
  1507.  
  1508.  
  1509. // ----------------------------------------------------------------------------
  1510. // global functions
  1511. // ----------------------------------------------------------------------------
  1512.  
  1513. wxString
  1514. wxFileSelectorEx(const wxChar *message,
  1515.                  const wxChar *default_path,
  1516.                  const wxChar *default_filename,
  1517.                  int *WXUNUSED(indexDefaultExtension),
  1518.                  const wxChar *wildcard,
  1519.                  int flags,
  1520.                  wxWindow *parent,
  1521.                  int x, int y)
  1522. {
  1523.     // TODO: implement this somehow
  1524.     return wxFileSelector(message, default_path, default_filename, wxT(""),
  1525.                           wildcard, flags, parent, x, y);
  1526. }
  1527.  
  1528. wxString wxFileSelector( const wxChar *title,
  1529.                       const wxChar *defaultDir, const wxChar *defaultFileName,
  1530.                       const wxChar *defaultExtension, const wxChar *filter, int flags,
  1531.                       wxWindow *parent, int x, int y )
  1532. {
  1533.     wxString filter2;
  1534.     if ( defaultExtension && !filter )
  1535.         filter2 = wxString(wxT("*.")) + wxString(defaultExtension) ;
  1536.     else if ( filter )
  1537.         filter2 = filter;
  1538.  
  1539.     wxString defaultDirString;
  1540.     if (defaultDir)
  1541.         defaultDirString = defaultDir;
  1542.  
  1543.     wxString defaultFilenameString;
  1544.     if (defaultFileName)
  1545.         defaultFilenameString = defaultFileName;
  1546.  
  1547.     wxFileDialog fileDialog( parent, title, defaultDirString, defaultFilenameString, filter2, flags, wxPoint(x, y) );
  1548.  
  1549.     if ( fileDialog.ShowModal() == wxID_OK )
  1550.     {
  1551.         return fileDialog.GetPath();
  1552.     }
  1553.     else
  1554.     {
  1555.         return wxEmptyString;
  1556.     }
  1557. }
  1558.  
  1559. static wxString GetWildcardString(const wxChar *ext)
  1560. {
  1561.     wxString wild;
  1562.     if ( ext )
  1563.     {
  1564.         if ( *ext == wxT('.') )
  1565.             ext++;
  1566.  
  1567.         wild << _T("*.") << ext;
  1568.     }
  1569.     else // no extension specified
  1570.     {
  1571.         wild = wxFileSelectorDefaultWildcardStr;
  1572.     }
  1573.  
  1574.     return wild;
  1575. }
  1576.  
  1577. wxString wxLoadFileSelector(const wxChar *what,
  1578.                             const wxChar *ext,
  1579.                             const wxChar *nameDef,
  1580.                             wxWindow *parent)
  1581. {
  1582.     wxString prompt;
  1583.     if ( what && *what )
  1584.         prompt = wxString::Format(_("Load %s file"), what);
  1585.     else
  1586.         prompt = _("Load file");
  1587.  
  1588.     return wxFileSelector(prompt, NULL, nameDef, ext,
  1589.                           GetWildcardString(ext), 0, parent);
  1590. }
  1591.  
  1592. wxString wxSaveFileSelector(const wxChar *what,
  1593.                             const wxChar *ext,
  1594.                             const wxChar *nameDef,
  1595.                             wxWindow *parent)
  1596. {
  1597.     wxString prompt;
  1598.     if ( what && *what )
  1599.         prompt = wxString::Format(_("Save %s file"), what);
  1600.     else
  1601.         prompt = _("Save file");
  1602.  
  1603.     return wxFileSelector(prompt, NULL, nameDef, ext,
  1604.                           GetWildcardString(ext), 0, parent);
  1605. }
  1606.  
  1607. // A module to allow icons table cleanup
  1608.  
  1609. class wxFileDialogGenericModule: public wxModule
  1610. {
  1611. DECLARE_DYNAMIC_CLASS(wxFileDialogGenericModule)
  1612. public:
  1613.     wxFileDialogGenericModule() {}
  1614.     bool OnInit() { return TRUE; }
  1615.     void OnExit() { if (g_IconsTable) {delete g_IconsTable; g_IconsTable = NULL;} }
  1616. };
  1617.  
  1618. IMPLEMENT_DYNAMIC_CLASS(wxFileDialogGenericModule, wxModule)
  1619.  
  1620. #endif // wxUSE_FILEDLG
  1621.  
  1622.