1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     Miscellaneous utility functions and classes 
   4 // Author:      Julian Smart 
   8 // Copyright:   (c) 1998 Julian Smart 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) && !defined(__EMX__) 
  21 // Some older compilers (such as EMX) cannot handle 
  22 // #pragma interface/implementation correctly, iff 
  23 // #pragma implementation is used in _two_ translation 
  24 // units (as created by e.g. event.cpp compiled for 
  25 // libwx_base and event.cpp compiled for libwx_gui_core). 
  26 // So we must not use those pragmas for those compilers in 
  28     #pragma implementation "utils.h" 
  31 // For compilers that support precompilation, includes "wx.h". 
  32 #include "wx/wxprec.h" 
  40     #include "wx/string.h" 
  46         #include "wx/window.h" 
  49         #include "wx/msgdlg.h" 
  50         #include "wx/textdlg.h" 
  51         #include "wx/textctrl.h"    // for wxTE_PASSWORD 
  53             #include "wx/menuitem.h" 
  59 #include "wx/apptrait.h" 
  61 #include "wx/process.h" 
  62 #include "wx/txtstrm.h" 
  64 #if defined(__WXWINCE__) && wxUSE_DATETIME 
  65 #include "wx/datetime.h" 
  73 #if !defined(__WATCOMC__) 
  74     #if !(defined(_MSC_VER) && (_MSC_VER > 800)) 
  80     #include "wx/colordlg.h" 
  81     #include "wx/fontdlg.h" 
  82     #include "wx/notebook.h" 
  84     #include "wx/statusbr.h" 
  90 #include "wx/msw/wince/time.h" 
  93 #if !defined(__MWERKS__) && !defined(__WXWINCE__) 
  94     #include <sys/types.h> 
  98 #if defined(__WXMSW__) 
  99     #include "wx/msw/private.h" 
 104 // ---------------------------------------------------------------------------- 
 106 // ---------------------------------------------------------------------------- 
 108 #if WXWIN_COMPATIBILITY_2_2 
 109     const wxChar 
*wxInternalErrorStr 
= wxT("wxWidgets Internal Error"); 
 110     const wxChar 
*wxFatalErrorStr 
= wxT("wxWidgets Fatal Error"); 
 111 #endif // WXWIN_COMPATIBILITY_2_2 
 113 // ============================================================================ 
 115 // ============================================================================ 
 117 #if WXWIN_COMPATIBILITY_2_4 
 120 copystring (const wxChar 
*s
) 
 122   if (s 
== NULL
) s 
= wxEmptyString
; 
 123   size_t len 
= wxStrlen (s
) + 1; 
 125   wxChar 
*news 
= new wxChar
[len
]; 
 126   memcpy (news
, s
, len 
* sizeof(wxChar
));    // Should be the fastest 
 131 #endif // WXWIN_COMPATIBILITY_2_4 
 133 // ---------------------------------------------------------------------------- 
 134 // String <-> Number conversions (deprecated) 
 135 // ---------------------------------------------------------------------------- 
 137 #if WXWIN_COMPATIBILITY_2_4 
 139 WXDLLIMPEXP_DATA_BASE(const wxChar 
*) wxFloatToStringStr 
= wxT("%.2f"); 
 140 WXDLLIMPEXP_DATA_BASE(const wxChar 
*) wxDoubleToStringStr 
= wxT("%.2f"); 
 143 StringToFloat (const wxChar 
*s
, float *number
) 
 145   if (s 
&& *s 
&& number
) 
 146     *number 
= (float) wxStrtod (s
, (wxChar 
**) NULL
); 
 150 StringToDouble (const wxChar 
*s
, double *number
) 
 152   if (s 
&& *s 
&& number
) 
 153     *number 
= wxStrtod (s
, (wxChar 
**) NULL
); 
 157 FloatToString (float number
, const wxChar 
*fmt
) 
 159   static wxChar buf
[256]; 
 161   wxSprintf (buf
, fmt
, number
); 
 166 DoubleToString (double number
, const wxChar 
*fmt
) 
 168   static wxChar buf
[256]; 
 170   wxSprintf (buf
, fmt
, number
); 
 175 StringToInt (const wxChar 
*s
, int *number
) 
 177   if (s 
&& *s 
&& number
) 
 178     *number 
= (int) wxStrtol (s
, (wxChar 
**) NULL
, 10); 
 182 StringToLong (const wxChar 
*s
, long *number
) 
 184   if (s 
&& *s 
&& number
) 
 185     *number 
= wxStrtol (s
, (wxChar 
**) NULL
, 10); 
 189 IntToString (int number
) 
 191   static wxChar buf
[20]; 
 193   wxSprintf (buf
, wxT("%d"), number
); 
 198 LongToString (long number
) 
 200   static wxChar buf
[20]; 
 202   wxSprintf (buf
, wxT("%ld"), number
); 
 206 #endif // WXWIN_COMPATIBILITY_2_4 
 208 // Array used in DecToHex conversion routine. 
 209 static wxChar hexArray
[] = wxT("0123456789ABCDEF"); 
 211 // Convert 2-digit hex number to decimal 
 212 int wxHexToDec(const wxString
& buf
) 
 214   int firstDigit
, secondDigit
; 
 216   if (buf
.GetChar(0) >= wxT('A')) 
 217     firstDigit 
= buf
.GetChar(0) - wxT('A') + 10; 
 219     firstDigit 
= buf
.GetChar(0) - wxT('0'); 
 221   if (buf
.GetChar(1) >= wxT('A')) 
 222     secondDigit 
= buf
.GetChar(1) - wxT('A') + 10; 
 224     secondDigit 
= buf
.GetChar(1) - wxT('0'); 
 226   return (firstDigit 
& 0xF) * 16 + (secondDigit 
& 0xF ); 
 229 // Convert decimal integer to 2-character hex string 
 230 void wxDecToHex(int dec
, wxChar 
*buf
) 
 232   int firstDigit 
= (int)(dec
/16.0); 
 233   int secondDigit 
= (int)(dec 
- (firstDigit
*16.0)); 
 234   buf
[0] = hexArray
[firstDigit
]; 
 235   buf
[1] = hexArray
[secondDigit
]; 
 239 // Convert decimal integer to 2-character hex string 
 240 wxString 
wxDecToHex(int dec
) 
 243     wxDecToHex(dec
, buf
); 
 244     return wxString(buf
); 
 247 // ---------------------------------------------------------------------------- 
 249 // ---------------------------------------------------------------------------- 
 251 // Return the current date/time 
 256     wxDateTime now 
= wxDateTime::Now(); 
 259     return wxEmptyString
; 
 262     time_t now 
= time((time_t *) NULL
); 
 263     char *date 
= ctime(&now
); 
 265     return wxString::FromAscii(date
); 
 269 void wxUsleep(unsigned long milliseconds
) 
 271     wxMilliSleep(milliseconds
); 
 274 const wxChar 
*wxGetInstallPrefix() 
 278     if ( wxGetEnv(wxT("WXPREFIX"), &prefix
) ) 
 279         return prefix
.c_str(); 
 281 #ifdef wxINSTALL_PREFIX 
 282     return wxT(wxINSTALL_PREFIX
); 
 284     return wxEmptyString
; 
 288 wxString 
wxGetDataDir() 
 290     wxString dir 
= wxGetInstallPrefix(); 
 291     dir 
<<  wxFILE_SEP_PATH 
<< wxT("share") << wxFILE_SEP_PATH 
<< wxT("wx"); 
 295 int wxGetOsVersion(int *verMaj
, int *verMin
) 
 297     // we want this function to work even if there is no wxApp 
 298     wxConsoleAppTraits traitsConsole
; 
 299     wxAppTraits 
*traits 
= wxTheApp 
? wxTheApp
->GetTraits() : NULL
; 
 301         traits 
= &traitsConsole
; 
 303     wxToolkitInfo
& info 
= traits
->GetToolkitInfo(); 
 305         *verMaj 
= info
.versionMajor
; 
 307         *verMin 
= info
.versionMinor
; 
 311 // ---------------------------------------------------------------------------- 
 312 // network and user id functions 
 313 // ---------------------------------------------------------------------------- 
 315 // Get Full RFC822 style email address 
 316 bool wxGetEmailAddress(wxChar 
*address
, int maxSize
) 
 318     wxString email 
= wxGetEmailAddress(); 
 322     wxStrncpy(address
, email
, maxSize 
- 1); 
 323     address
[maxSize 
- 1] = wxT('\0'); 
 328 wxString 
wxGetEmailAddress() 
 332     wxString host 
= wxGetFullHostName(); 
 335         wxString user 
= wxGetUserId(); 
 338             email 
<< user 
<< wxT('@') << host
; 
 345 wxString 
wxGetUserId() 
 347     static const int maxLoginLen 
= 256; // FIXME arbitrary number 
 350     bool ok 
= wxGetUserId(wxStringBuffer(buf
, maxLoginLen
), maxLoginLen
); 
 358 wxString 
wxGetUserName() 
 360     static const int maxUserNameLen 
= 1024; // FIXME arbitrary number 
 363     bool ok 
= wxGetUserName(wxStringBuffer(buf
, maxUserNameLen
), maxUserNameLen
); 
 371 wxString 
wxGetHostName() 
 373     static const size_t hostnameSize 
= 257; 
 376     bool ok 
= wxGetHostName(wxStringBuffer(buf
, hostnameSize
), hostnameSize
); 
 384 wxString 
wxGetFullHostName() 
 386     static const size_t hostnameSize 
= 257; 
 389     bool ok 
= wxGetFullHostName(wxStringBuffer(buf
, hostnameSize
), hostnameSize
); 
 397 wxString 
wxGetHomeDir() 
 407 wxString 
wxGetCurrentDir() 
 414         ok 
= getcwd(dir
.GetWriteBuf(len 
+ 1), len
) != NULL
; 
 419             if ( errno 
!= ERANGE 
) 
 421                 wxLogSysError(_T("Failed to get current directory")); 
 423                 return wxEmptyString
; 
 427                 // buffer was too small, retry with a larger one 
 439 // ---------------------------------------------------------------------------- 
 441 // ---------------------------------------------------------------------------- 
 443 // wxDoExecuteWithCapture() helper: reads an entire stream into one array 
 445 // returns true if ok, false if error 
 447 static bool ReadAll(wxInputStream 
*is
, wxArrayString
& output
) 
 449     wxCHECK_MSG( is
, false, _T("NULL stream in wxExecute()?") ); 
 451     // the stream could be already at EOF or in wxSTREAM_BROKEN_PIPE state 
 454     wxTextInputStream 
tis(*is
); 
 459         wxString line 
= tis
.ReadLine(); 
 475 #endif // wxUSE_STREAMS 
 477 // this is a private function because it hasn't a clean interface: the first 
 478 // array is passed by reference, the second by pointer - instead we have 2 
 479 // public versions of wxExecute() below 
 480 static long wxDoExecuteWithCapture(const wxString
& command
, 
 481                                    wxArrayString
& output
, 
 482                                    wxArrayString
* error
, 
 485     // create a wxProcess which will capture the output 
 486     wxProcess 
*process 
= new wxProcess
; 
 489     long rc 
= wxExecute(command
, wxEXEC_SYNC 
| flags
, process
); 
 494         if ( !ReadAll(process
->GetInputStream(), output
) ) 
 499             if ( !ReadAll(process
->GetErrorStream(), *error
) ) 
 507 #endif // wxUSE_STREAMS/!wxUSE_STREAMS 
 514 long wxExecute(const wxString
& command
, wxArrayString
& output
, int flags
) 
 516     return wxDoExecuteWithCapture(command
, output
, NULL
, flags
); 
 519 long wxExecute(const wxString
& command
, 
 520                wxArrayString
& output
, 
 521                wxArrayString
& error
, 
 524     return wxDoExecuteWithCapture(command
, output
, &error
, flags
); 
 527 // ---------------------------------------------------------------------------- 
 528 // wxApp::Yield() wrappers for backwards compatibility 
 529 // ---------------------------------------------------------------------------- 
 533     return wxTheApp 
&& wxTheApp
->Yield(); 
 536 bool wxYieldIfNeeded() 
 538     return wxTheApp 
&& wxTheApp
->Yield(true); 
 543 // ============================================================================ 
 544 // GUI-only functions from now on 
 545 // ============================================================================ 
 550 static long wxCurrentId 
= 100; 
 554     // skip the part of IDs space that contains hard-coded values: 
 555     if (wxCurrentId 
== wxID_LOWEST
) 
 556         wxCurrentId 
= wxID_HIGHEST 
+ 1; 
 558     return wxCurrentId
++; 
 562 wxGetCurrentId(void) { return wxCurrentId
; } 
 565 wxRegisterId (long id
) 
 567   if (id 
>= wxCurrentId
) 
 568     wxCurrentId 
= id 
+ 1; 
 573 // ---------------------------------------------------------------------------- 
 574 // Menu accelerators related functions 
 575 // ---------------------------------------------------------------------------- 
 577 wxChar 
*wxStripMenuCodes(const wxChar 
*in
, wxChar 
*out
) 
 579     wxString s 
= wxMenuItem::GetLabelFromText(in
); 
 582         // go smash their buffer if it's not big enough - I love char * params 
 583         memcpy(out
, s
.c_str(), s
.length() * sizeof(wxChar
)); 
 587         // MYcopystring - for easier search... 
 588         out 
= new wxChar
[s
.length() + 1]; 
 589         wxStrcpy(out
, s
.c_str()); 
 595 wxString 
wxStripMenuCodes(const wxString
& in
) 
 599     size_t len 
= in
.length(); 
 602     for ( size_t n 
= 0; n 
< len
; n
++ ) 
 607             // skip it, it is used to introduce the accel char (or to quote 
 608             // itself in which case it should still be skipped): note that it 
 609             // can't be the last character of the string 
 612                 wxLogDebug(_T("Invalid menu string '%s'"), in
.c_str()); 
 616                 // use the next char instead 
 620         else if ( ch 
== _T('\t') ) 
 622             // everything after TAB is accel string, exit the loop 
 632 #endif // wxUSE_MENUS 
 634 // ---------------------------------------------------------------------------- 
 635 // Window search functions 
 636 // ---------------------------------------------------------------------------- 
 639  * If parent is non-NULL, look through children for a label or title 
 640  * matching the specified string. If NULL, look through all top-level windows. 
 645 wxFindWindowByLabel (const wxString
& title
, wxWindow 
* parent
) 
 647     return wxWindow::FindWindowByLabel( title
, parent 
); 
 652  * If parent is non-NULL, look through children for a name 
 653  * matching the specified string. If NULL, look through all top-level windows. 
 658 wxFindWindowByName (const wxString
& name
, wxWindow 
* parent
) 
 660     return wxWindow::FindWindowByName( name
, parent 
); 
 663 // Returns menu item id or wxNOT_FOUND if none. 
 665 wxFindMenuItemId (wxFrame 
* frame
, const wxString
& menuString
, const wxString
& itemString
) 
 668   wxMenuBar 
*menuBar 
= frame
->GetMenuBar (); 
 670       return menuBar
->FindMenuItem (menuString
, itemString
); 
 671 #endif // wxUSE_MENUS 
 676 // Try to find the deepest child that contains 'pt'. 
 677 // We go backwards, to try to allow for controls that are spacially 
 678 // within other controls, but are still siblings (e.g. buttons within 
 679 // static boxes). Static boxes are likely to be created _before_ controls 
 680 // that sit inside them. 
 681 wxWindow
* wxFindWindowAtPoint(wxWindow
* win
, const wxPoint
& pt
) 
 686     // Hack for wxNotebook case: at least in wxGTK, all pages 
 687     // claim to be shown, so we must only deal with the selected one. 
 689     if (win
->IsKindOf(CLASSINFO(wxNotebook
))) 
 691       wxNotebook
* nb 
= (wxNotebook
*) win
; 
 692       int sel 
= nb
->GetSelection(); 
 695         wxWindow
* child 
= nb
->GetPage(sel
); 
 696         wxWindow
* foundWin 
= wxFindWindowAtPoint(child
, pt
); 
 703     wxWindowList::compatibility_iterator node 
= win
->GetChildren().GetLast(); 
 706         wxWindow
* child 
= node
->GetData(); 
 707         wxWindow
* foundWin 
= wxFindWindowAtPoint(child
, pt
); 
 710         node 
= node
->GetPrevious(); 
 713     wxPoint pos 
= win
->GetPosition(); 
 714     wxSize sz 
= win
->GetSize(); 
 715     if (win
->GetParent()) 
 717         pos 
= win
->GetParent()->ClientToScreen(pos
); 
 720     wxRect 
rect(pos
, sz
); 
 727 wxWindow
* wxGenericFindWindowAtPoint(const wxPoint
& pt
) 
 729     // Go backwards through the list since windows 
 730     // on top are likely to have been appended most 
 732     wxWindowList::compatibility_iterator node 
= wxTopLevelWindows
.GetLast(); 
 735         wxWindow
* win 
= node
->GetData(); 
 736         wxWindow
* found 
= wxFindWindowAtPoint(win
, pt
); 
 739         node 
= node
->GetPrevious(); 
 744 // ---------------------------------------------------------------------------- 
 746 // ---------------------------------------------------------------------------- 
 749  * N.B. these convenience functions must be separate from msgdlgg.cpp, textdlgg.cpp 
 750  * since otherwise the generic code may be pulled in unnecessarily. 
 755 int wxMessageBox(const wxString
& message
, const wxString
& caption
, long style
, 
 756                  wxWindow 
*parent
, int WXUNUSED(x
), int WXUNUSED(y
) ) 
 758     long decorated_style 
= style
; 
 760     if ( ( style 
& ( wxICON_EXCLAMATION 
| wxICON_HAND 
| wxICON_INFORMATION 
| wxICON_QUESTION 
) ) == 0 ) 
 762         decorated_style 
|= ( style 
& wxYES 
) ? wxICON_QUESTION 
: wxICON_INFORMATION 
; 
 765     wxMessageDialog 
dialog(parent
, message
, caption
, decorated_style
); 
 767     int ans 
= dialog
.ShowModal(); 
 780     wxFAIL_MSG( _T("unexpected return code from wxMessageDialog") ); 
 785 #endif // wxUSE_MSGDLG 
 789 wxString 
wxGetTextFromUser(const wxString
& message
, const wxString
& caption
, 
 790                         const wxString
& defaultValue
, wxWindow 
*parent
, 
 791                         wxCoord x
, wxCoord y
, bool centre 
) 
 794     long style 
= wxTextEntryDialogStyle
; 
 801     wxTextEntryDialog 
dialog(parent
, message
, caption
, defaultValue
, style
, wxPoint(x
, y
)); 
 803     if (dialog
.ShowModal() == wxID_OK
) 
 805         str 
= dialog
.GetValue(); 
 811 wxString 
wxGetPasswordFromUser(const wxString
& message
, 
 812                                const wxString
& caption
, 
 813                                const wxString
& defaultValue
, 
 815                                wxCoord x
, wxCoord y
, bool centre 
) 
 818     long style 
= wxTextEntryDialogStyle
; 
 825     wxPasswordEntryDialog 
dialog(parent
, message
, caption
, defaultValue
, 
 826                              style
, wxPoint(x
, y
)); 
 827     if ( dialog
.ShowModal() == wxID_OK 
) 
 829         str 
= dialog
.GetValue(); 
 835 #endif // wxUSE_TEXTDLG 
 839 wxColour 
wxGetColourFromUser(wxWindow 
*parent
, const wxColour
& colInit
) 
 842     data
.SetChooseFull(true); 
 845         data
.SetColour((wxColour 
&)colInit
); // const_cast 
 849     wxColourDialog 
dialog(parent
, &data
); 
 850     if ( dialog
.ShowModal() == wxID_OK 
) 
 852         colRet 
= dialog
.GetColourData().GetColour(); 
 854     //else: leave it invalid 
 859 #endif // wxUSE_COLOURDLG 
 863 wxFont 
wxGetFontFromUser(wxWindow 
*parent
, const wxFont
& fontInit
) 
 868         data
.SetInitialFont(fontInit
); 
 872     wxFontDialog 
dialog(parent
, data
); 
 873     if ( dialog
.ShowModal() == wxID_OK 
) 
 875         fontRet 
= dialog
.GetFontData().GetChosenFont(); 
 877     //else: leave it invalid 
 882 #endif // wxUSE_FONTDLG 
 884 // ---------------------------------------------------------------------------- 
 885 // wxSafeYield and supporting functions 
 886 // ---------------------------------------------------------------------------- 
 888 void wxEnableTopLevelWindows(bool enable
) 
 890     wxWindowList::compatibility_iterator node
; 
 891     for ( node 
= wxTopLevelWindows
.GetFirst(); node
; node 
= node
->GetNext() ) 
 892         node
->GetData()->Enable(enable
); 
 895 wxWindowDisabler::wxWindowDisabler(wxWindow 
*winToSkip
) 
 897     // remember the top level windows which were already disabled, so that we 
 898     // don't reenable them later 
 899     m_winDisabled 
= NULL
; 
 901     wxWindowList::compatibility_iterator node
; 
 902     for ( node 
= wxTopLevelWindows
.GetFirst(); node
; node 
= node
->GetNext() ) 
 904         wxWindow 
*winTop 
= node
->GetData(); 
 905         if ( winTop 
== winToSkip 
) 
 908         // we don't need to disable the hidden or already disabled windows 
 909         if ( winTop
->IsEnabled() && winTop
->IsShown() ) 
 915             if ( !m_winDisabled 
) 
 917                 m_winDisabled 
= new wxWindowList
; 
 920             m_winDisabled
->Append(winTop
); 
 925 wxWindowDisabler::~wxWindowDisabler() 
 927     wxWindowList::compatibility_iterator node
; 
 928     for ( node 
= wxTopLevelWindows
.GetFirst(); node
; node 
= node
->GetNext() ) 
 930         wxWindow 
*winTop 
= node
->GetData(); 
 931         if ( !m_winDisabled 
|| !m_winDisabled
->Find(winTop
) ) 
 935         //else: had been already disabled, don't reenable 
 938     delete m_winDisabled
; 
 941 // Yield to other apps/messages and disable user input to all windows except 
 943 bool wxSafeYield(wxWindow 
*win
, bool onlyIfNeeded
) 
 945     wxWindowDisabler 
wd(win
); 
 949         rc 
= wxYieldIfNeeded(); 
 956 // Don't synthesize KeyUp events holding down a key and producing KeyDown 
 957 // events with autorepeat. On by default and always on in wxMSW. wxGTK version 
 960 bool wxSetDetectableAutoRepeat( bool WXUNUSED(flag
) ) 
 962     return true;    // detectable auto-repeat is the only mode MSW supports