1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/utilscmn.cpp
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 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
29 #include "wx/string.h"
35 #include "wx/window.h"
38 #include "wx/msgdlg.h"
39 #include "wx/textdlg.h"
40 #include "wx/textctrl.h" // for wxTE_PASSWORD
42 #include "wx/menuitem.h"
48 #include "wx/apptrait.h"
50 #include "wx/process.h"
51 #include "wx/txtstrm.h"
53 #include "wx/mimetype.h"
54 #include "wx/config.h"
56 #if defined(__WXWINCE__) && wxUSE_DATETIME
57 #include "wx/datetime.h"
65 #if !wxONLY_WATCOM_EARLIER_THAN(1,4)
66 #if !(defined(_MSC_VER) && (_MSC_VER > 800))
72 #include "wx/colordlg.h"
73 #include "wx/fontdlg.h"
74 #include "wx/notebook.h"
75 #include "wx/statusbr.h"
82 #include "wx/msw/wince/time.h"
84 #endif // ! __WXPALMOS5__
87 #include "wx/osx/private.h"
91 #if !defined(__MWERKS__) && !defined(__WXWINCE__)
92 #include <sys/types.h>
95 #endif // ! __WXPALMOS5__
97 #if defined(__WXMSW__)
98 #include "wx/msw/private.h"
99 #include "wx/filesys.h"
102 #if wxUSE_GUI && defined(__WXGTK__)
103 #include <gtk/gtk.h> // for GTK_XXX_VERSION constants
108 // ============================================================================
110 // ============================================================================
112 // Array used in DecToHex conversion routine.
113 static wxChar hexArray
[] = wxT("0123456789ABCDEF");
115 // Convert 2-digit hex number to decimal
116 int wxHexToDec(const wxString
& buf
)
118 int firstDigit
, secondDigit
;
120 if (buf
.GetChar(0) >= wxT('A'))
121 firstDigit
= buf
.GetChar(0) - wxT('A') + 10;
123 firstDigit
= buf
.GetChar(0) - wxT('0');
125 if (buf
.GetChar(1) >= wxT('A'))
126 secondDigit
= buf
.GetChar(1) - wxT('A') + 10;
128 secondDigit
= buf
.GetChar(1) - wxT('0');
130 return (firstDigit
& 0xF) * 16 + (secondDigit
& 0xF );
133 // Convert decimal integer to 2-character hex string
134 void wxDecToHex(int dec
, wxChar
*buf
)
136 int firstDigit
= (int)(dec
/16.0);
137 int secondDigit
= (int)(dec
- (firstDigit
*16.0));
138 buf
[0] = hexArray
[firstDigit
];
139 buf
[1] = hexArray
[secondDigit
];
143 // Convert decimal integer to 2 characters
144 void wxDecToHex(int dec
, char* ch1
, char* ch2
)
146 int firstDigit
= (int)(dec
/16.0);
147 int secondDigit
= (int)(dec
- (firstDigit
*16.0));
148 (*ch1
) = (char) hexArray
[firstDigit
];
149 (*ch2
) = (char) hexArray
[secondDigit
];
152 // Convert decimal integer to 2-character hex string
153 wxString
wxDecToHex(int dec
)
156 wxDecToHex(dec
, buf
);
157 return wxString(buf
);
160 // ----------------------------------------------------------------------------
162 // ----------------------------------------------------------------------------
164 // Don't synthesize KeyUp events holding down a key and producing KeyDown
165 // events with autorepeat. On by default and always on in wxMSW. wxGTK version
168 bool wxSetDetectableAutoRepeat( bool WXUNUSED(flag
) )
170 return true; // detectable auto-repeat is the only mode MSW supports
174 // Return the current date/time
179 wxDateTime now
= wxDateTime::Now();
182 return wxEmptyString
;
185 time_t now
= time(NULL
);
186 char *date
= ctime(&now
);
188 return wxString::FromAscii(date
);
192 #if WXWIN_COMPATIBILITY_2_8
193 void wxUsleep(unsigned long milliseconds
)
195 wxMilliSleep(milliseconds
);
199 const wxChar
*wxGetInstallPrefix()
203 if ( wxGetEnv(wxT("WXPREFIX"), &prefix
) )
204 return prefix
.c_str();
206 #ifdef wxINSTALL_PREFIX
207 return wxT(wxINSTALL_PREFIX
);
209 return wxEmptyString
;
213 wxString
wxGetDataDir()
215 wxString dir
= wxGetInstallPrefix();
216 dir
<< wxFILE_SEP_PATH
<< wxT("share") << wxFILE_SEP_PATH
<< wxT("wx");
220 bool wxIsPlatformLittleEndian()
222 // Are we little or big endian? This method is from Harbison & Steele.
226 char c
[sizeof(long)];
234 // ----------------------------------------------------------------------------
236 // ----------------------------------------------------------------------------
239 * Class to make it easier to specify platform-dependent values
242 wxArrayInt
* wxPlatform::sm_customPlatforms
= NULL
;
244 void wxPlatform::Copy(const wxPlatform
& platform
)
246 m_longValue
= platform
.m_longValue
;
247 m_doubleValue
= platform
.m_doubleValue
;
248 m_stringValue
= platform
.m_stringValue
;
251 wxPlatform
wxPlatform::If(int platform
, long value
)
254 return wxPlatform(value
);
259 wxPlatform
wxPlatform::IfNot(int platform
, long value
)
262 return wxPlatform(value
);
267 wxPlatform
& wxPlatform::ElseIf(int platform
, long value
)
274 wxPlatform
& wxPlatform::ElseIfNot(int platform
, long value
)
281 wxPlatform
wxPlatform::If(int platform
, double value
)
284 return wxPlatform(value
);
289 wxPlatform
wxPlatform::IfNot(int platform
, double value
)
292 return wxPlatform(value
);
297 wxPlatform
& wxPlatform::ElseIf(int platform
, double value
)
300 m_doubleValue
= value
;
304 wxPlatform
& wxPlatform::ElseIfNot(int platform
, double value
)
307 m_doubleValue
= value
;
311 wxPlatform
wxPlatform::If(int platform
, const wxString
& value
)
314 return wxPlatform(value
);
319 wxPlatform
wxPlatform::IfNot(int platform
, const wxString
& value
)
322 return wxPlatform(value
);
327 wxPlatform
& wxPlatform::ElseIf(int platform
, const wxString
& value
)
330 m_stringValue
= value
;
334 wxPlatform
& wxPlatform::ElseIfNot(int platform
, const wxString
& value
)
337 m_stringValue
= value
;
341 wxPlatform
& wxPlatform::Else(long value
)
347 wxPlatform
& wxPlatform::Else(double value
)
349 m_doubleValue
= value
;
353 wxPlatform
& wxPlatform::Else(const wxString
& value
)
355 m_stringValue
= value
;
359 void wxPlatform::AddPlatform(int platform
)
361 if (!sm_customPlatforms
)
362 sm_customPlatforms
= new wxArrayInt
;
363 sm_customPlatforms
->Add(platform
);
366 void wxPlatform::ClearPlatforms()
368 delete sm_customPlatforms
;
369 sm_customPlatforms
= NULL
;
372 /// Function for testing current platform
374 bool wxPlatform::Is(int platform
)
377 if (platform
== wxOS_WINDOWS
)
381 if (platform
== wxOS_WINDOWS_CE
)
387 // FIXME: wxWinPocketPC and wxWinSmartPhone are unknown symbols
389 #if defined(__WXWINCE__) && defined(__POCKETPC__)
390 if (platform
== wxWinPocketPC
)
393 #if defined(__WXWINCE__) && defined(__SMARTPHONE__)
394 if (platform
== wxWinSmartPhone
)
401 if (platform
== wxPORT_GTK
)
405 if (platform
== wxPORT_MAC
)
409 if (platform
== wxPORT_X11
)
413 if (platform
== wxOS_UNIX
)
417 if (platform
== wxPORT_MGL
)
421 if (platform
== wxOS_OS2
)
425 if (platform
== wxPORT_PM
)
429 if (platform
== wxPORT_MAC
)
433 if (sm_customPlatforms
&& sm_customPlatforms
->Index(platform
) != wxNOT_FOUND
)
439 // ----------------------------------------------------------------------------
440 // network and user id functions
441 // ----------------------------------------------------------------------------
443 // Get Full RFC822 style email address
444 bool wxGetEmailAddress(wxChar
*address
, int maxSize
)
446 wxString email
= wxGetEmailAddress();
450 wxStrlcpy(address
, email
.t_str(), maxSize
);
455 wxString
wxGetEmailAddress()
459 wxString host
= wxGetFullHostName();
462 wxString user
= wxGetUserId();
465 email
<< user
<< wxT('@') << host
;
472 wxString
wxGetUserId()
474 static const int maxLoginLen
= 256; // FIXME arbitrary number
477 bool ok
= wxGetUserId(wxStringBuffer(buf
, maxLoginLen
), maxLoginLen
);
485 wxString
wxGetUserName()
487 static const int maxUserNameLen
= 1024; // FIXME arbitrary number
490 bool ok
= wxGetUserName(wxStringBuffer(buf
, maxUserNameLen
), maxUserNameLen
);
498 wxString
wxGetHostName()
500 static const size_t hostnameSize
= 257;
503 bool ok
= wxGetHostName(wxStringBuffer(buf
, hostnameSize
), hostnameSize
);
511 wxString
wxGetFullHostName()
513 static const size_t hostnameSize
= 257;
516 bool ok
= wxGetFullHostName(wxStringBuffer(buf
, hostnameSize
), hostnameSize
);
524 wxString
wxGetHomeDir()
534 wxString
wxGetCurrentDir()
541 ok
= getcwd(dir
.GetWriteBuf(len
+ 1), len
) != NULL
;
546 if ( errno
!= ERANGE
)
548 wxLogSysError(_T("Failed to get current directory"));
550 return wxEmptyString
;
554 // buffer was too small, retry with a larger one
566 // ----------------------------------------------------------------------------
568 // ----------------------------------------------------------------------------
570 // wxDoExecuteWithCapture() helper: reads an entire stream into one array
572 // returns true if ok, false if error
574 static bool ReadAll(wxInputStream
*is
, wxArrayString
& output
)
576 wxCHECK_MSG( is
, false, _T("NULL stream in wxExecute()?") );
578 // the stream could be already at EOF or in wxSTREAM_BROKEN_PIPE state
581 wxTextInputStream
tis(*is
);
585 wxString line
= tis
.ReadLine();
587 // check for EOF before other errors as it's not really an error
590 // add the last, possibly incomplete, line
596 // any other error is fatal
605 #endif // wxUSE_STREAMS
607 // this is a private function because it hasn't a clean interface: the first
608 // array is passed by reference, the second by pointer - instead we have 2
609 // public versions of wxExecute() below
610 static long wxDoExecuteWithCapture(const wxString
& command
,
611 wxArrayString
& output
,
612 wxArrayString
* error
,
615 // create a wxProcess which will capture the output
616 wxProcess
*process
= new wxProcess
;
619 long rc
= wxExecute(command
, wxEXEC_SYNC
| flags
, process
);
624 if ( !ReadAll(process
->GetInputStream(), output
) )
629 if ( !ReadAll(process
->GetErrorStream(), *error
) )
637 #endif // wxUSE_STREAMS/!wxUSE_STREAMS
644 long wxExecute(const wxString
& command
, wxArrayString
& output
, int flags
)
646 return wxDoExecuteWithCapture(command
, output
, NULL
, flags
);
649 long wxExecute(const wxString
& command
,
650 wxArrayString
& output
,
651 wxArrayString
& error
,
654 return wxDoExecuteWithCapture(command
, output
, &error
, flags
);
657 // ----------------------------------------------------------------------------
659 // ----------------------------------------------------------------------------
662 static long wxCurrentId
= 100;
666 // skip the part of IDs space that contains hard-coded values:
667 if (wxCurrentId
== wxID_LOWEST
)
668 wxCurrentId
= wxID_HIGHEST
+ 1;
670 return wxCurrentId
++;
674 wxGetCurrentId(void) { return wxCurrentId
; }
677 wxRegisterId (long id
)
679 if (id
>= wxCurrentId
)
680 wxCurrentId
= id
+ 1;
683 // ----------------------------------------------------------------------------
684 // wxQsort, adapted by RR to allow user_data
685 // ----------------------------------------------------------------------------
687 /* This file is part of the GNU C Library.
688 Written by Douglas C. Schmidt (schmidt@ics.uci.edu).
690 Douglas Schmidt kindly gave permission to relicence the
691 code under the wxWindows licence:
693 From: "Douglas C. Schmidt" <schmidt@dre.vanderbilt.edu>
694 To: Robert Roebling <robert.roebling@uni-ulm.de>
695 Subject: Re: qsort licence
696 Date: Mon, 23 Jul 2007 03:44:25 -0500
697 Sender: schmidt@dre.vanderbilt.edu
698 Message-Id: <20070723084426.64F511000A8@tango.dre.vanderbilt.edu>
702 > [...] I'm asking if you'd be willing to relicence your code
703 > under the wxWindows licence. [...]
705 That's fine with me [...]
712 /* Byte-wise swap two items of size SIZE. */
713 #define SWAP(a, b, size) \
716 register size_t __size = (size); \
717 register char *__a = (a), *__b = (b); \
723 } while (--__size > 0); \
726 /* Discontinue quicksort algorithm when partition gets below this size.
727 This particular magic number was chosen to work best on a Sun 4/260. */
730 /* Stack node declarations used to store unfulfilled partition obligations. */
737 /* The next 4 #defines implement a very fast in-line stack abstraction. */
738 #define STACK_SIZE (8 * sizeof(unsigned long int))
739 #define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top))
740 #define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi)))
741 #define STACK_NOT_EMPTY (stack < top)
744 /* Order size using quicksort. This implementation incorporates
745 four optimizations discussed in Sedgewick:
747 1. Non-recursive, using an explicit stack of pointer that store the
748 next array partition to sort. To save time, this maximum amount
749 of space required to store an array of MAX_INT is allocated on the
750 stack. Assuming a 32-bit integer, this needs only 32 *
751 sizeof(stack_node) == 136 bits. Pretty cheap, actually.
753 2. Chose the pivot element using a median-of-three decision tree.
754 This reduces the probability of selecting a bad pivot value and
755 eliminates certain extraneous comparisons.
757 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving
758 insertion sort to order the MAX_THRESH items within each partition.
759 This is a big win, since insertion sort is faster for small, mostly
760 sorted array segments.
762 4. The larger of the two sub-partitions is always pushed onto the
763 stack first, with the algorithm then concentrating on the
764 smaller partition. This *guarantees* no more than log (n)
765 stack size is needed (actually O(1) in this case)! */
767 void wxQsort(void *const pbase
, size_t total_elems
,
768 size_t size
, CMPFUNCDATA cmp
, const void* user_data
)
770 register char *base_ptr
= (char *) pbase
;
771 const size_t max_thresh
= MAX_THRESH
* size
;
773 if (total_elems
== 0)
774 /* Avoid lossage with unsigned arithmetic below. */
777 if (total_elems
> MAX_THRESH
)
780 char *hi
= &lo
[size
* (total_elems
- 1)];
781 stack_node stack
[STACK_SIZE
];
782 stack_node
*top
= stack
;
786 while (STACK_NOT_EMPTY
)
791 /* Select median value from among LO, MID, and HI. Rearrange
792 LO and HI so the three values are sorted. This lowers the
793 probability of picking a pathological pivot value and
794 skips a comparison for both the LEFT_PTR and RIGHT_PTR. */
796 char *mid
= lo
+ size
* ((hi
- lo
) / size
>> 1);
798 if ((*cmp
) ((void *) mid
, (void *) lo
, user_data
) < 0)
799 SWAP (mid
, lo
, size
);
800 if ((*cmp
) ((void *) hi
, (void *) mid
, user_data
) < 0)
801 SWAP (mid
, hi
, size
);
804 if ((*cmp
) ((void *) mid
, (void *) lo
, user_data
) < 0)
805 SWAP (mid
, lo
, size
);
807 left_ptr
= lo
+ size
;
808 right_ptr
= hi
- size
;
810 /* Here's the famous ``collapse the walls'' section of quicksort.
811 Gotta like those tight inner loops! They are the main reason
812 that this algorithm runs much faster than others. */
815 while ((*cmp
) ((void *) left_ptr
, (void *) mid
, user_data
) < 0)
818 while ((*cmp
) ((void *) mid
, (void *) right_ptr
, user_data
) < 0)
821 if (left_ptr
< right_ptr
)
823 SWAP (left_ptr
, right_ptr
, size
);
826 else if (mid
== right_ptr
)
831 else if (left_ptr
== right_ptr
)
838 while (left_ptr
<= right_ptr
);
840 /* Set up pointers for next iteration. First determine whether
841 left and right partitions are below the threshold size. If so,
842 ignore one or both. Otherwise, push the larger partition's
843 bounds on the stack and continue sorting the smaller one. */
845 if ((size_t) (right_ptr
- lo
) <= max_thresh
)
847 if ((size_t) (hi
- left_ptr
) <= max_thresh
)
848 /* Ignore both small partitions. */
851 /* Ignore small left partition. */
854 else if ((size_t) (hi
- left_ptr
) <= max_thresh
)
855 /* Ignore small right partition. */
857 else if ((right_ptr
- lo
) > (hi
- left_ptr
))
859 /* Push larger left partition indices. */
860 PUSH (lo
, right_ptr
);
865 /* Push larger right partition indices. */
872 /* Once the BASE_PTR array is partially sorted by quicksort the rest
873 is completely sorted using insertion sort, since this is efficient
874 for partitions below MAX_THRESH size. BASE_PTR points to the beginning
875 of the array to sort, and END_PTR points at the very last element in
876 the array (*not* one beyond it!). */
879 char *const end_ptr
= &base_ptr
[size
* (total_elems
- 1)];
880 char *tmp_ptr
= base_ptr
;
881 char *thresh
= base_ptr
+ max_thresh
;
882 if ( thresh
> end_ptr
)
884 register char *run_ptr
;
886 /* Find smallest element in first threshold and place it at the
887 array's beginning. This is the smallest array element,
888 and the operation speeds up insertion sort's inner loop. */
890 for (run_ptr
= tmp_ptr
+ size
; run_ptr
<= thresh
; run_ptr
+= size
)
891 if ((*cmp
) ((void *) run_ptr
, (void *) tmp_ptr
, user_data
) < 0)
894 if (tmp_ptr
!= base_ptr
)
895 SWAP (tmp_ptr
, base_ptr
, size
);
897 /* Insertion sort, running from left-hand-side up to right-hand-side. */
899 run_ptr
= base_ptr
+ size
;
900 while ((run_ptr
+= size
) <= end_ptr
)
902 tmp_ptr
= run_ptr
- size
;
903 while ((*cmp
) ((void *) run_ptr
, (void *) tmp_ptr
, user_data
) < 0)
907 if (tmp_ptr
!= run_ptr
)
911 trav
= run_ptr
+ size
;
912 while (--trav
>= run_ptr
)
917 for (hi
= lo
= trav
; (lo
-= size
) >= tmp_ptr
; hi
= lo
)
930 // ============================================================================
931 // GUI-only functions from now on
932 // ============================================================================
936 // ----------------------------------------------------------------------------
937 // Launch default browser
938 // ----------------------------------------------------------------------------
940 #if defined(__WXMSW__)
942 // implemented in a port-specific utils source file:
943 bool wxDoLaunchDefaultBrowser(const wxString
& url
, const wxString
& scheme
, int flags
);
945 #elif defined(__WXX11__) || defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXCOCOA__) || \
946 (defined(__WXMAC__) && !defined(__WXOSX_IPHONE__))
948 // implemented in a port-specific utils source file:
949 bool wxDoLaunchDefaultBrowser(const wxString
& url
, int flags
);
953 // a "generic" implementation:
954 bool wxDoLaunchDefaultBrowser(const wxString
& url
, int flags
)
956 // on other platforms try to use mime types or wxExecute...
962 wxFileType
*ft
= wxTheMimeTypesManager
->GetFileTypeFromExtension(_T("html"));
966 ft
->GetMimeType(&mt
);
968 ok
= ft
->GetOpenCommand(&cmd
, wxFileType::MessageParameters(url
));
971 #endif // wxUSE_MIMETYPE
973 if ( !ok
|| cmd
.empty() )
975 // fallback to checking for the BROWSER environment variable
976 if ( !wxGetEnv(wxT("BROWSER"), &cmd
) || cmd
.empty() )
977 cmd
<< _T(' ') << url
;
980 ok
= ( !cmd
.empty() && wxExecute(cmd
) );
984 // no file type for HTML extension
985 wxLogError(_("No default application configured for HTML files."));
991 static bool DoLaunchDefaultBrowserHelper(const wxString
& urlOrig
, int flags
)
993 // NOTE: we don't have to care about the wxBROWSER_NOBUSYCURSOR flag
994 // as it was already handled by wxLaunchDefaultBrowser
998 wxString
url(urlOrig
), scheme
;
1001 // this check is useful to avoid that wxURI recognizes as scheme parts of
1002 // the filename, in case urlOrig is a local filename
1003 // (e.g. "C:\\test.txt" when parsed by wxURI reports a scheme == "C")
1004 bool hasValidScheme
= uri
.HasScheme() && uri
.GetScheme().length() > 1;
1006 #if defined(__WXMSW__)
1008 // NOTE: when testing wxMSW's wxLaunchDefaultBrowser all possible forms
1009 // of the URL/flags should be tested; e.g.:
1011 // for (int i=0; i<2; i++)
1013 // wxLaunchDefaultBrowser("C:\\test.txt", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1014 // wxLaunchDefaultBrowser("wxwidgets.org", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1015 // wxLaunchDefaultBrowser("file:/C%3A/test.txt", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1016 // wxLaunchDefaultBrowser("http://wxwidgets.org", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1018 // (assuming you have a C:\test.txt file)
1020 if ( !hasValidScheme
)
1022 if (wxFileExists(urlOrig
) || wxDirExists(urlOrig
))
1025 // do not prepend the file scheme to the URL as ShellExecuteEx() doesn't like it
1029 url
.Prepend(wxS("http://"));
1033 else if ( hasValidScheme
)
1035 scheme
= uri
.GetScheme();
1037 if ( uri
.GetScheme() == "file" )
1039 // TODO: extract URLToFileName() to some always compiled in
1041 #if wxUSE_FILESYSTEM
1042 // ShellExecuteEx() doesn't like the "file" scheme when opening local files;
1044 url
= wxFileSystem::URLToFileName(url
).GetFullPath();
1045 #endif // wxUSE_FILESYSTEM
1049 if (wxDoLaunchDefaultBrowser(url
, scheme
, flags
))
1051 //else: call wxLogSysError
1053 if ( !hasValidScheme
)
1055 // set the scheme of url to "http" or "file" if it does not have one
1056 if (wxFileExists(urlOrig
) || wxDirExists(urlOrig
))
1057 url
.Prepend(wxS("file://"));
1059 url
.Prepend(wxS("http://"));
1062 if (wxDoLaunchDefaultBrowser(url
, flags
))
1064 //else: call wxLogSysError
1067 wxLogSysError(_("Failed to open URL \"%s\" in default browser."),
1073 bool wxLaunchDefaultBrowser(const wxString
& url
, int flags
)
1075 // NOTE: as documented, "url" may be both a real well-formed URL
1076 // and a local file name
1078 if ( flags
& wxBROWSER_NOBUSYCURSOR
)
1079 return DoLaunchDefaultBrowserHelper(url
, flags
);
1082 return DoLaunchDefaultBrowserHelper(url
, flags
);
1085 // ----------------------------------------------------------------------------
1086 // Menu accelerators related functions
1087 // ----------------------------------------------------------------------------
1089 #if WXWIN_COMPATIBILITY_2_6
1090 wxChar
*wxStripMenuCodes(const wxChar
*in
, wxChar
*out
)
1093 wxString s
= wxMenuItem::GetLabelText(in
);
1096 wxString s
= wxStripMenuCodes(str
);
1097 #endif // wxUSE_MENUS
1100 // go smash their buffer if it's not big enough - I love char * params
1101 memcpy(out
, s
.c_str(), s
.length() * sizeof(wxChar
));
1105 out
= new wxChar
[s
.length() + 1];
1106 wxStrcpy(out
, s
.c_str());
1113 wxString
wxStripMenuCodes(const wxString
& in
, int flags
)
1115 wxASSERT_MSG( flags
, _T("this is useless to call without any flags") );
1119 size_t len
= in
.length();
1122 for ( size_t n
= 0; n
< len
; n
++ )
1125 if ( (flags
& wxStrip_Mnemonics
) && ch
== _T('&') )
1127 // skip it, it is used to introduce the accel char (or to quote
1128 // itself in which case it should still be skipped): note that it
1129 // can't be the last character of the string
1132 wxLogDebug(_T("Invalid menu string '%s'"), in
.c_str());
1136 // use the next char instead
1140 else if ( (flags
& wxStrip_Accel
) && ch
== _T('\t') )
1142 // everything after TAB is accel string, exit the loop
1152 // ----------------------------------------------------------------------------
1153 // Window search functions
1154 // ----------------------------------------------------------------------------
1157 * If parent is non-NULL, look through children for a label or title
1158 * matching the specified string. If NULL, look through all top-level windows.
1163 wxFindWindowByLabel (const wxString
& title
, wxWindow
* parent
)
1165 return wxWindow::FindWindowByLabel( title
, parent
);
1170 * If parent is non-NULL, look through children for a name
1171 * matching the specified string. If NULL, look through all top-level windows.
1176 wxFindWindowByName (const wxString
& name
, wxWindow
* parent
)
1178 return wxWindow::FindWindowByName( name
, parent
);
1181 // Returns menu item id or wxNOT_FOUND if none.
1183 wxFindMenuItemId(wxFrame
*frame
,
1184 const wxString
& menuString
,
1185 const wxString
& itemString
)
1188 wxMenuBar
*menuBar
= frame
->GetMenuBar ();
1190 return menuBar
->FindMenuItem (menuString
, itemString
);
1191 #else // !wxUSE_MENUS
1193 wxUnusedVar(menuString
);
1194 wxUnusedVar(itemString
);
1195 #endif // wxUSE_MENUS/!wxUSE_MENUS
1200 // Try to find the deepest child that contains 'pt'.
1201 // We go backwards, to try to allow for controls that are spacially
1202 // within other controls, but are still siblings (e.g. buttons within
1203 // static boxes). Static boxes are likely to be created _before_ controls
1204 // that sit inside them.
1205 wxWindow
* wxFindWindowAtPoint(wxWindow
* win
, const wxPoint
& pt
)
1207 if (!win
->IsShown())
1210 // Hack for wxNotebook case: at least in wxGTK, all pages
1211 // claim to be shown, so we must only deal with the selected one.
1213 if (win
->IsKindOf(CLASSINFO(wxNotebook
)))
1215 wxNotebook
* nb
= (wxNotebook
*) win
;
1216 int sel
= nb
->GetSelection();
1219 wxWindow
* child
= nb
->GetPage(sel
);
1220 wxWindow
* foundWin
= wxFindWindowAtPoint(child
, pt
);
1227 wxWindowList::compatibility_iterator node
= win
->GetChildren().GetLast();
1230 wxWindow
* child
= node
->GetData();
1231 wxWindow
* foundWin
= wxFindWindowAtPoint(child
, pt
);
1234 node
= node
->GetPrevious();
1237 wxPoint pos
= win
->GetPosition();
1238 wxSize sz
= win
->GetSize();
1239 if ( !win
->IsTopLevel() && win
->GetParent() )
1241 pos
= win
->GetParent()->ClientToScreen(pos
);
1244 wxRect
rect(pos
, sz
);
1245 if (rect
.Contains(pt
))
1251 wxWindow
* wxGenericFindWindowAtPoint(const wxPoint
& pt
)
1253 // Go backwards through the list since windows
1254 // on top are likely to have been appended most
1256 wxWindowList::compatibility_iterator node
= wxTopLevelWindows
.GetLast();
1259 wxWindow
* win
= node
->GetData();
1260 wxWindow
* found
= wxFindWindowAtPoint(win
, pt
);
1263 node
= node
->GetPrevious();
1268 // ----------------------------------------------------------------------------
1270 // ----------------------------------------------------------------------------
1273 * N.B. these convenience functions must be separate from msgdlgg.cpp, textdlgg.cpp
1274 * since otherwise the generic code may be pulled in unnecessarily.
1279 int wxMessageBox(const wxString
& message
, const wxString
& caption
, long style
,
1280 wxWindow
*parent
, int WXUNUSED(x
), int WXUNUSED(y
) )
1282 long decorated_style
= style
;
1284 if ( ( style
& ( wxICON_EXCLAMATION
| wxICON_HAND
| wxICON_INFORMATION
| wxICON_QUESTION
) ) == 0 )
1286 decorated_style
|= ( style
& wxYES
) ? wxICON_QUESTION
: wxICON_INFORMATION
;
1289 wxMessageDialog
dialog(parent
, message
, caption
, decorated_style
);
1291 int ans
= dialog
.ShowModal();
1304 wxFAIL_MSG( _T("unexpected return code from wxMessageDialog") );
1309 void wxInfoMessageBox(wxWindow
* parent
)
1311 // don't translate these strings, they're for diagnostics purposes only
1313 msg
.Printf(_T("wxWidgets Library (%s port)\n")
1314 _T("Version %d.%d.%d%s%s, compiled at %s %s\n")
1315 _T("Runtime version of toolkit used is %d.%d.%s\n")
1316 _T("Copyright (c) 1995-2009 wxWidgets team"),
1317 wxPlatformInfo::Get().GetPortIdName().c_str(),
1333 wxPlatformInfo::Get().GetToolkitMajorVersion(),
1334 wxPlatformInfo::Get().GetToolkitMinorVersion(),
1336 wxString::Format("\nThe compile-time GTK+ version is %d.%d.%d.",
1339 GTK_MICRO_VERSION
).c_str()
1344 wxMessageBox(msg
, _T("wxWidgets information"),
1345 wxICON_INFORMATION
| wxOK
,
1349 #endif // wxUSE_MSGDLG
1353 wxString
wxGetTextFromUser(const wxString
& message
, const wxString
& caption
,
1354 const wxString
& defaultValue
, wxWindow
*parent
,
1355 wxCoord x
, wxCoord y
, bool centre
)
1358 long style
= wxTextEntryDialogStyle
;
1365 wxTextEntryDialog
dialog(parent
, message
, caption
, defaultValue
, style
, wxPoint(x
, y
));
1367 if (dialog
.ShowModal() == wxID_OK
)
1369 str
= dialog
.GetValue();
1375 wxString
wxGetPasswordFromUser(const wxString
& message
,
1376 const wxString
& caption
,
1377 const wxString
& defaultValue
,
1379 wxCoord x
, wxCoord y
, bool centre
)
1382 long style
= wxTextEntryDialogStyle
;
1389 wxPasswordEntryDialog
dialog(parent
, message
, caption
, defaultValue
,
1390 style
, wxPoint(x
, y
));
1391 if ( dialog
.ShowModal() == wxID_OK
)
1393 str
= dialog
.GetValue();
1399 #endif // wxUSE_TEXTDLG
1403 wxColour
wxGetColourFromUser(wxWindow
*parent
,
1404 const wxColour
& colInit
,
1405 const wxString
& caption
,
1406 wxColourData
*ptrData
)
1408 // contains serialized representation of wxColourData used the last time
1409 // the dialog was shown: we want to reuse it the next time in order to show
1410 // the same custom colours to the user (and we can't just have static
1411 // wxColourData itself because it's a GUI object and so should be destroyed
1412 // before GUI shutdown and doing it during static cleanup is too late)
1413 static wxString s_strColourData
;
1419 if ( !s_strColourData
.empty() )
1421 if ( !data
.FromString(s_strColourData
) )
1423 wxFAIL_MSG( "bug in wxColourData::FromString()?" );
1427 // we don't get back the "choose full" flag value from the native
1428 // dialog and so we can't preserve it between runs, so we decide to
1429 // always use it as it seems better than not using it (user can
1430 // just ignore the extra controls in the dialog but having to click
1431 // a button each time to show them would be very annoying
1432 data
.SetChooseFull(true);
1437 if ( colInit
.IsOk() )
1439 ptrData
->SetColour(colInit
);
1443 wxColourDialog
dialog(parent
, ptrData
);
1444 if (!caption
.empty())
1445 dialog
.SetTitle(caption
);
1446 if ( dialog
.ShowModal() == wxID_OK
)
1448 *ptrData
= dialog
.GetColourData();
1449 colRet
= ptrData
->GetColour();
1450 s_strColourData
= ptrData
->ToString();
1452 //else: leave colRet invalid
1457 #endif // wxUSE_COLOURDLG
1461 wxFont
wxGetFontFromUser(wxWindow
*parent
, const wxFont
& fontInit
, const wxString
& caption
)
1464 if ( fontInit
.Ok() )
1466 data
.SetInitialFont(fontInit
);
1470 wxFontDialog
dialog(parent
, data
);
1471 if (!caption
.empty())
1472 dialog
.SetTitle(caption
);
1473 if ( dialog
.ShowModal() == wxID_OK
)
1475 fontRet
= dialog
.GetFontData().GetChosenFont();
1477 //else: leave it invalid
1482 #endif // wxUSE_FONTDLG
1484 // ----------------------------------------------------------------------------
1485 // wxSafeYield and supporting functions
1486 // ----------------------------------------------------------------------------
1488 void wxEnableTopLevelWindows(bool enable
)
1490 wxWindowList::compatibility_iterator node
;
1491 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1492 node
->GetData()->Enable(enable
);
1495 wxWindowDisabler::wxWindowDisabler(bool disable
)
1497 m_disabled
= disable
;
1502 wxWindowDisabler::wxWindowDisabler(wxWindow
*winToSkip
)
1505 DoDisable(winToSkip
);
1508 void wxWindowDisabler::DoDisable(wxWindow
*winToSkip
)
1510 // remember the top level windows which were already disabled, so that we
1511 // don't reenable them later
1512 m_winDisabled
= NULL
;
1514 wxWindowList::compatibility_iterator node
;
1515 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1517 wxWindow
*winTop
= node
->GetData();
1518 if ( winTop
== winToSkip
)
1521 // we don't need to disable the hidden or already disabled windows
1522 if ( winTop
->IsEnabled() && winTop
->IsShown() )
1528 if ( !m_winDisabled
)
1530 m_winDisabled
= new wxWindowList
;
1533 m_winDisabled
->Append(winTop
);
1538 wxWindowDisabler::~wxWindowDisabler()
1543 wxWindowList::compatibility_iterator node
;
1544 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1546 wxWindow
*winTop
= node
->GetData();
1547 if ( !m_winDisabled
|| !m_winDisabled
->Find(winTop
) )
1551 //else: had been already disabled, don't reenable
1554 delete m_winDisabled
;
1557 // Yield to other apps/messages and disable user input to all windows except
1559 bool wxSafeYield(wxWindow
*win
, bool onlyIfNeeded
)
1561 wxWindowDisabler
wd(win
);
1565 rc
= wxYieldIfNeeded();
1572 // ----------------------------------------------------------------------------
1573 // wxApp::Yield() wrappers for backwards compatibility
1574 // ----------------------------------------------------------------------------
1578 return wxTheApp
&& wxTheApp
->Yield();
1581 bool wxYieldIfNeeded()
1583 return wxTheApp
&& wxTheApp
->Yield(true);