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"
55 #include "wx/versioninfo.h"
57 #if defined(__WXWINCE__) && wxUSE_DATETIME
58 #include "wx/datetime.h"
66 #if !wxONLY_WATCOM_EARLIER_THAN(1,4)
67 #if !(defined(_MSC_VER) && (_MSC_VER > 800))
73 #include "wx/colordlg.h"
74 #include "wx/fontdlg.h"
75 #include "wx/notebook.h"
76 #include "wx/statusbr.h"
83 #include "wx/msw/wince/time.h"
85 #endif // ! __WXPALMOS5__
88 #include "wx/osx/private.h"
92 #if !defined(__MWERKS__) && !defined(__WXWINCE__)
93 #include <sys/types.h>
96 #endif // ! __WXPALMOS5__
98 #if defined(__WXMSW__)
99 #include "wx/msw/private.h"
100 #include "wx/filesys.h"
103 #if wxUSE_GUI && defined(__WXGTK__)
104 #include <gtk/gtk.h> // for GTK_XXX_VERSION constants
109 // ============================================================================
111 // ============================================================================
113 // Array used in DecToHex conversion routine.
114 static const wxChar hexArray
[] = wxT("0123456789ABCDEF");
116 // Convert 2-digit hex number to decimal
117 int wxHexToDec(const wxString
& str
)
120 buf
[0] = str
.GetChar(0);
121 buf
[1] = str
.GetChar(1);
122 return wxHexToDec((const char*) buf
);
125 // Convert decimal integer to 2-character hex string
126 void wxDecToHex(int dec
, wxChar
*buf
)
128 int firstDigit
= (int)(dec
/16.0);
129 int secondDigit
= (int)(dec
- (firstDigit
*16.0));
130 buf
[0] = hexArray
[firstDigit
];
131 buf
[1] = hexArray
[secondDigit
];
135 // Convert decimal integer to 2 characters
136 void wxDecToHex(int dec
, char* ch1
, char* ch2
)
138 int firstDigit
= (int)(dec
/16.0);
139 int secondDigit
= (int)(dec
- (firstDigit
*16.0));
140 (*ch1
) = (char) hexArray
[firstDigit
];
141 (*ch2
) = (char) hexArray
[secondDigit
];
144 // Convert decimal integer to 2-character hex string
145 wxString
wxDecToHex(int dec
)
148 wxDecToHex(dec
, buf
);
149 return wxString(buf
);
152 // ----------------------------------------------------------------------------
154 // ----------------------------------------------------------------------------
156 // Return the current date/time
161 wxDateTime now
= wxDateTime::Now();
164 return wxEmptyString
;
167 time_t now
= time(NULL
);
168 char *date
= ctime(&now
);
170 return wxString::FromAscii(date
);
174 #if WXWIN_COMPATIBILITY_2_8
175 void wxUsleep(unsigned long milliseconds
)
177 wxMilliSleep(milliseconds
);
181 const wxChar
*wxGetInstallPrefix()
185 if ( wxGetEnv(wxT("WXPREFIX"), &prefix
) )
186 return prefix
.c_str();
188 #ifdef wxINSTALL_PREFIX
189 return wxT(wxINSTALL_PREFIX
);
191 return wxEmptyString
;
195 wxString
wxGetDataDir()
197 wxString dir
= wxGetInstallPrefix();
198 dir
<< wxFILE_SEP_PATH
<< wxT("share") << wxFILE_SEP_PATH
<< wxT("wx");
202 bool wxIsPlatformLittleEndian()
204 // Are we little or big endian? This method is from Harbison & Steele.
208 char c
[sizeof(long)];
216 // ----------------------------------------------------------------------------
218 // ----------------------------------------------------------------------------
221 * Class to make it easier to specify platform-dependent values
224 wxArrayInt
* wxPlatform::sm_customPlatforms
= NULL
;
226 void wxPlatform::Copy(const wxPlatform
& platform
)
228 m_longValue
= platform
.m_longValue
;
229 m_doubleValue
= platform
.m_doubleValue
;
230 m_stringValue
= platform
.m_stringValue
;
233 wxPlatform
wxPlatform::If(int platform
, long value
)
236 return wxPlatform(value
);
241 wxPlatform
wxPlatform::IfNot(int platform
, long value
)
244 return wxPlatform(value
);
249 wxPlatform
& wxPlatform::ElseIf(int platform
, long value
)
256 wxPlatform
& wxPlatform::ElseIfNot(int platform
, long value
)
263 wxPlatform
wxPlatform::If(int platform
, double value
)
266 return wxPlatform(value
);
271 wxPlatform
wxPlatform::IfNot(int platform
, double value
)
274 return wxPlatform(value
);
279 wxPlatform
& wxPlatform::ElseIf(int platform
, double value
)
282 m_doubleValue
= value
;
286 wxPlatform
& wxPlatform::ElseIfNot(int platform
, double value
)
289 m_doubleValue
= value
;
293 wxPlatform
wxPlatform::If(int platform
, const wxString
& value
)
296 return wxPlatform(value
);
301 wxPlatform
wxPlatform::IfNot(int platform
, const wxString
& value
)
304 return wxPlatform(value
);
309 wxPlatform
& wxPlatform::ElseIf(int platform
, const wxString
& value
)
312 m_stringValue
= value
;
316 wxPlatform
& wxPlatform::ElseIfNot(int platform
, const wxString
& value
)
319 m_stringValue
= value
;
323 wxPlatform
& wxPlatform::Else(long value
)
329 wxPlatform
& wxPlatform::Else(double value
)
331 m_doubleValue
= value
;
335 wxPlatform
& wxPlatform::Else(const wxString
& value
)
337 m_stringValue
= value
;
341 void wxPlatform::AddPlatform(int platform
)
343 if (!sm_customPlatforms
)
344 sm_customPlatforms
= new wxArrayInt
;
345 sm_customPlatforms
->Add(platform
);
348 void wxPlatform::ClearPlatforms()
350 wxDELETE(sm_customPlatforms
);
353 /// Function for testing current platform
355 bool wxPlatform::Is(int platform
)
358 if (platform
== wxOS_WINDOWS
)
362 if (platform
== wxOS_WINDOWS_CE
)
368 // FIXME: wxWinPocketPC and wxWinSmartPhone are unknown symbols
370 #if defined(__WXWINCE__) && defined(__POCKETPC__)
371 if (platform
== wxWinPocketPC
)
374 #if defined(__WXWINCE__) && defined(__SMARTPHONE__)
375 if (platform
== wxWinSmartPhone
)
382 if (platform
== wxPORT_GTK
)
386 if (platform
== wxPORT_MAC
)
390 if (platform
== wxPORT_X11
)
394 if (platform
== wxOS_UNIX
)
398 if (platform
== wxPORT_MGL
)
402 if (platform
== wxOS_OS2
)
406 if (platform
== wxPORT_PM
)
410 if (platform
== wxPORT_MAC
)
414 if (sm_customPlatforms
&& sm_customPlatforms
->Index(platform
) != wxNOT_FOUND
)
420 // ----------------------------------------------------------------------------
421 // network and user id functions
422 // ----------------------------------------------------------------------------
424 // Get Full RFC822 style email address
425 bool wxGetEmailAddress(wxChar
*address
, int maxSize
)
427 wxString email
= wxGetEmailAddress();
431 wxStrlcpy(address
, email
.t_str(), maxSize
);
436 wxString
wxGetEmailAddress()
440 wxString host
= wxGetFullHostName();
443 wxString user
= wxGetUserId();
446 email
<< user
<< wxT('@') << host
;
453 wxString
wxGetUserId()
455 static const int maxLoginLen
= 256; // FIXME arbitrary number
458 bool ok
= wxGetUserId(wxStringBuffer(buf
, maxLoginLen
), maxLoginLen
);
466 wxString
wxGetUserName()
468 static const int maxUserNameLen
= 1024; // FIXME arbitrary number
471 bool ok
= wxGetUserName(wxStringBuffer(buf
, maxUserNameLen
), maxUserNameLen
);
479 wxString
wxGetHostName()
481 static const size_t hostnameSize
= 257;
484 bool ok
= wxGetHostName(wxStringBuffer(buf
, hostnameSize
), hostnameSize
);
492 wxString
wxGetFullHostName()
494 static const size_t hostnameSize
= 257;
497 bool ok
= wxGetFullHostName(wxStringBuffer(buf
, hostnameSize
), hostnameSize
);
505 wxString
wxGetHomeDir()
515 wxString
wxGetCurrentDir()
522 ok
= getcwd(dir
.GetWriteBuf(len
+ 1), len
) != NULL
;
527 if ( errno
!= ERANGE
)
529 wxLogSysError(wxT("Failed to get current directory"));
531 return wxEmptyString
;
535 // buffer was too small, retry with a larger one
547 // ----------------------------------------------------------------------------
549 // ----------------------------------------------------------------------------
552 #if wxOSX_USE_COCOA_OR_CARBON
553 #include <crt_externs.h>
557 bool wxGetEnvMap(wxEnvVariableHashMap
*map
)
559 wxCHECK_MSG( map
, false, wxS("output pointer can't be NULL") );
561 #if defined(__VISUALC__)
562 wxChar
**env
= _tenviron
;
564 // Now this routine wil give false for OpenVMS
565 // TODO : should we do something with logicals?
567 #elif defined(__WXOSX__)
568 #if wxOSX_USE_COCOA_OR_CARBON
569 // Under Mac shared libraries don't have access to the global environ
570 // variable so use this Mac-specific function instead as advised by
571 // environ(7) under Darwin
572 char ***penv
= _NSGetEnviron();
578 // todo translate NSProcessInfo environment into map
580 #else // non-MSVC non-Mac
581 // Not sure if other compilers have _tenviron so use the (more standard)
582 // ANSI version only for them.
584 // Both POSIX and Single UNIX Specification say that this variable must
585 // exist but not that it must be declared anywhere and, indeed, it's not
586 // declared in several common systems (some BSDs, Solaris with native CC).
587 extern char **environ
;
589 char **env
= environ
;
598 const wxString
var(*env
);
600 name
= var
.BeforeFirst(wxS('='), &value
);
602 (*map
)[name
] = value
;
613 // ----------------------------------------------------------------------------
615 // ----------------------------------------------------------------------------
617 // wxDoExecuteWithCapture() helper: reads an entire stream into one array
619 // returns true if ok, false if error
621 static bool ReadAll(wxInputStream
*is
, wxArrayString
& output
)
623 wxCHECK_MSG( is
, false, wxT("NULL stream in wxExecute()?") );
625 // the stream could be already at EOF or in wxSTREAM_BROKEN_PIPE state
628 wxTextInputStream
tis(*is
);
632 wxString line
= tis
.ReadLine();
634 // check for EOF before other errors as it's not really an error
637 // add the last, possibly incomplete, line
643 // any other error is fatal
652 #endif // wxUSE_STREAMS
654 // this is a private function because it hasn't a clean interface: the first
655 // array is passed by reference, the second by pointer - instead we have 2
656 // public versions of wxExecute() below
657 static long wxDoExecuteWithCapture(const wxString
& command
,
658 wxArrayString
& output
,
659 wxArrayString
* error
,
661 const wxExecuteEnv
*env
)
663 // create a wxProcess which will capture the output
664 wxProcess
*process
= new wxProcess
;
667 long rc
= wxExecute(command
, wxEXEC_SYNC
| flags
, process
, env
);
672 if ( !ReadAll(process
->GetInputStream(), output
) )
677 if ( !ReadAll(process
->GetErrorStream(), *error
) )
685 #endif // wxUSE_STREAMS/!wxUSE_STREAMS
692 long wxExecute(const wxString
& command
, wxArrayString
& output
, int flags
,
693 const wxExecuteEnv
*env
)
695 return wxDoExecuteWithCapture(command
, output
, NULL
, flags
, env
);
698 long wxExecute(const wxString
& command
,
699 wxArrayString
& output
,
700 wxArrayString
& error
,
702 const wxExecuteEnv
*env
)
704 return wxDoExecuteWithCapture(command
, output
, &error
, flags
, env
);
707 // ----------------------------------------------------------------------------
709 // ----------------------------------------------------------------------------
712 static long wxCurrentId
= 100;
716 // skip the part of IDs space that contains hard-coded values:
717 if (wxCurrentId
== wxID_LOWEST
)
718 wxCurrentId
= wxID_HIGHEST
+ 1;
720 return wxCurrentId
++;
724 wxGetCurrentId(void) { return wxCurrentId
; }
727 wxRegisterId (long id
)
729 if (id
>= wxCurrentId
)
730 wxCurrentId
= id
+ 1;
733 // ----------------------------------------------------------------------------
734 // wxQsort, adapted by RR to allow user_data
735 // ----------------------------------------------------------------------------
737 /* This file is part of the GNU C Library.
738 Written by Douglas C. Schmidt (schmidt@ics.uci.edu).
740 Douglas Schmidt kindly gave permission to relicence the
741 code under the wxWindows licence:
743 From: "Douglas C. Schmidt" <schmidt@dre.vanderbilt.edu>
744 To: Robert Roebling <robert.roebling@uni-ulm.de>
745 Subject: Re: qsort licence
746 Date: Mon, 23 Jul 2007 03:44:25 -0500
747 Sender: schmidt@dre.vanderbilt.edu
748 Message-Id: <20070723084426.64F511000A8@tango.dre.vanderbilt.edu>
752 > [...] I'm asking if you'd be willing to relicence your code
753 > under the wxWindows licence. [...]
755 That's fine with me [...]
762 /* Byte-wise swap two items of size SIZE. */
763 #define SWAP(a, b, size) \
766 register size_t __size = (size); \
767 register char *__a = (a), *__b = (b); \
773 } while (--__size > 0); \
776 /* Discontinue quicksort algorithm when partition gets below this size.
777 This particular magic number was chosen to work best on a Sun 4/260. */
780 /* Stack node declarations used to store unfulfilled partition obligations. */
787 /* The next 4 #defines implement a very fast in-line stack abstraction. */
788 #define STACK_SIZE (8 * sizeof(unsigned long int))
789 #define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top))
790 #define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi)))
791 #define STACK_NOT_EMPTY (stack < top)
794 /* Order size using quicksort. This implementation incorporates
795 four optimizations discussed in Sedgewick:
797 1. Non-recursive, using an explicit stack of pointer that store the
798 next array partition to sort. To save time, this maximum amount
799 of space required to store an array of MAX_INT is allocated on the
800 stack. Assuming a 32-bit integer, this needs only 32 *
801 sizeof(stack_node) == 136 bits. Pretty cheap, actually.
803 2. Chose the pivot element using a median-of-three decision tree.
804 This reduces the probability of selecting a bad pivot value and
805 eliminates certain extraneous comparisons.
807 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving
808 insertion sort to order the MAX_THRESH items within each partition.
809 This is a big win, since insertion sort is faster for small, mostly
810 sorted array segments.
812 4. The larger of the two sub-partitions is always pushed onto the
813 stack first, with the algorithm then concentrating on the
814 smaller partition. This *guarantees* no more than log (n)
815 stack size is needed (actually O(1) in this case)! */
817 void wxQsort(void* pbase
, size_t total_elems
,
818 size_t size
, wxSortCallback cmp
, const void* user_data
)
820 register char *base_ptr
= (char *) pbase
;
821 const size_t max_thresh
= MAX_THRESH
* size
;
823 if (total_elems
== 0)
824 /* Avoid lossage with unsigned arithmetic below. */
827 if (total_elems
> MAX_THRESH
)
830 char *hi
= &lo
[size
* (total_elems
- 1)];
831 stack_node stack
[STACK_SIZE
];
832 stack_node
*top
= stack
;
836 while (STACK_NOT_EMPTY
)
841 /* Select median value from among LO, MID, and HI. Rearrange
842 LO and HI so the three values are sorted. This lowers the
843 probability of picking a pathological pivot value and
844 skips a comparison for both the LEFT_PTR and RIGHT_PTR. */
846 char *mid
= lo
+ size
* ((hi
- lo
) / size
>> 1);
848 if ((*cmp
) ((void *) mid
, (void *) lo
, user_data
) < 0)
849 SWAP (mid
, lo
, size
);
850 if ((*cmp
) ((void *) hi
, (void *) mid
, user_data
) < 0)
851 SWAP (mid
, hi
, size
);
854 if ((*cmp
) ((void *) mid
, (void *) lo
, user_data
) < 0)
855 SWAP (mid
, lo
, size
);
857 left_ptr
= lo
+ size
;
858 right_ptr
= hi
- size
;
860 /* Here's the famous ``collapse the walls'' section of quicksort.
861 Gotta like those tight inner loops! They are the main reason
862 that this algorithm runs much faster than others. */
865 while ((*cmp
) ((void *) left_ptr
, (void *) mid
, user_data
) < 0)
868 while ((*cmp
) ((void *) mid
, (void *) right_ptr
, user_data
) < 0)
871 if (left_ptr
< right_ptr
)
873 SWAP (left_ptr
, right_ptr
, size
);
876 else if (mid
== right_ptr
)
881 else if (left_ptr
== right_ptr
)
888 while (left_ptr
<= right_ptr
);
890 /* Set up pointers for next iteration. First determine whether
891 left and right partitions are below the threshold size. If so,
892 ignore one or both. Otherwise, push the larger partition's
893 bounds on the stack and continue sorting the smaller one. */
895 if ((size_t) (right_ptr
- lo
) <= max_thresh
)
897 if ((size_t) (hi
- left_ptr
) <= max_thresh
)
898 /* Ignore both small partitions. */
901 /* Ignore small left partition. */
904 else if ((size_t) (hi
- left_ptr
) <= max_thresh
)
905 /* Ignore small right partition. */
907 else if ((right_ptr
- lo
) > (hi
- left_ptr
))
909 /* Push larger left partition indices. */
910 PUSH (lo
, right_ptr
);
915 /* Push larger right partition indices. */
922 /* Once the BASE_PTR array is partially sorted by quicksort the rest
923 is completely sorted using insertion sort, since this is efficient
924 for partitions below MAX_THRESH size. BASE_PTR points to the beginning
925 of the array to sort, and END_PTR points at the very last element in
926 the array (*not* one beyond it!). */
929 char *const end_ptr
= &base_ptr
[size
* (total_elems
- 1)];
930 char *tmp_ptr
= base_ptr
;
931 char *thresh
= base_ptr
+ max_thresh
;
932 if ( thresh
> end_ptr
)
934 register char *run_ptr
;
936 /* Find smallest element in first threshold and place it at the
937 array's beginning. This is the smallest array element,
938 and the operation speeds up insertion sort's inner loop. */
940 for (run_ptr
= tmp_ptr
+ size
; run_ptr
<= thresh
; run_ptr
+= size
)
941 if ((*cmp
) ((void *) run_ptr
, (void *) tmp_ptr
, user_data
) < 0)
944 if (tmp_ptr
!= base_ptr
)
945 SWAP (tmp_ptr
, base_ptr
, size
);
947 /* Insertion sort, running from left-hand-side up to right-hand-side. */
949 run_ptr
= base_ptr
+ size
;
950 while ((run_ptr
+= size
) <= end_ptr
)
952 tmp_ptr
= run_ptr
- size
;
953 while ((*cmp
) ((void *) run_ptr
, (void *) tmp_ptr
, user_data
) < 0)
957 if (tmp_ptr
!= run_ptr
)
961 trav
= run_ptr
+ size
;
962 while (--trav
>= run_ptr
)
967 for (hi
= lo
= trav
; (lo
-= size
) >= tmp_ptr
; hi
= lo
)
980 // ============================================================================
981 // GUI-only functions from now on
982 // ============================================================================
986 // this function is only really implemented for X11-based ports, including GTK1
987 // (GTK2 sets detectable auto-repeat automatically anyhow)
988 #if !(defined(__WXX11__) || defined(__WXMOTIF__) || \
989 (defined(__WXGTK__) && !defined(__WXGTK20__)))
990 bool wxSetDetectableAutoRepeat( bool WXUNUSED(flag
) )
994 #endif // !X11-based port
996 // ----------------------------------------------------------------------------
997 // Launch default browser
998 // ----------------------------------------------------------------------------
1000 #if defined(__WXMSW__)
1002 // implemented in a port-specific utils source file:
1003 bool wxDoLaunchDefaultBrowser(const wxString
& url
, const wxString
& scheme
, int flags
);
1005 #elif defined(__WXX11__) || defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXCOCOA__) || \
1006 (defined(__WXOSX__) )
1008 // implemented in a port-specific utils source file:
1009 bool wxDoLaunchDefaultBrowser(const wxString
& url
, int flags
);
1013 // a "generic" implementation:
1014 bool wxDoLaunchDefaultBrowser(const wxString
& url
, int flags
)
1016 // on other platforms try to use mime types or wxExecute...
1022 wxFileType
*ft
= wxTheMimeTypesManager
->GetFileTypeFromExtension(wxT("html"));
1026 ft
->GetMimeType(&mt
);
1028 ok
= ft
->GetOpenCommand(&cmd
, wxFileType::MessageParameters(url
));
1031 #endif // wxUSE_MIMETYPE
1033 if ( !ok
|| cmd
.empty() )
1035 // fallback to checking for the BROWSER environment variable
1036 if ( !wxGetEnv(wxT("BROWSER"), &cmd
) || cmd
.empty() )
1037 cmd
<< wxT(' ') << url
;
1040 ok
= ( !cmd
.empty() && wxExecute(cmd
) );
1044 // no file type for HTML extension
1045 wxLogError(_("No default application configured for HTML files."));
1051 static bool DoLaunchDefaultBrowserHelper(const wxString
& urlOrig
, int flags
)
1053 // NOTE: we don't have to care about the wxBROWSER_NOBUSYCURSOR flag
1054 // as it was already handled by wxLaunchDefaultBrowser
1058 wxString
url(urlOrig
), scheme
;
1061 // this check is useful to avoid that wxURI recognizes as scheme parts of
1062 // the filename, in case urlOrig is a local filename
1063 // (e.g. "C:\\test.txt" when parsed by wxURI reports a scheme == "C")
1064 bool hasValidScheme
= uri
.HasScheme() && uri
.GetScheme().length() > 1;
1066 #if defined(__WXMSW__)
1068 // NOTE: when testing wxMSW's wxLaunchDefaultBrowser all possible forms
1069 // of the URL/flags should be tested; e.g.:
1071 // for (int i=0; i<2; i++)
1073 // // test arguments without a valid URL scheme:
1074 // wxLaunchDefaultBrowser("C:\\test.txt", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1075 // wxLaunchDefaultBrowser("wxwidgets.org", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1077 // // test arguments with different valid schemes:
1078 // wxLaunchDefaultBrowser("file:/C%3A/test.txt", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1079 // wxLaunchDefaultBrowser("http://wxwidgets.org", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1080 // wxLaunchDefaultBrowser("mailto:user@host.org", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1082 // (assuming you have a C:\test.txt file)
1084 if ( !hasValidScheme
)
1086 if (wxFileExists(urlOrig
) || wxDirExists(urlOrig
))
1089 // do not prepend the file scheme to the URL as ShellExecuteEx() doesn't like it
1093 url
.Prepend(wxS("http://"));
1097 else if ( hasValidScheme
)
1099 scheme
= uri
.GetScheme();
1101 if ( uri
.GetScheme() == "file" )
1103 // TODO: extract URLToFileName() to some always compiled in
1105 #if wxUSE_FILESYSTEM
1106 // ShellExecuteEx() doesn't like the "file" scheme when opening local files;
1108 url
= wxFileSystem::URLToFileName(url
).GetFullPath();
1109 #endif // wxUSE_FILESYSTEM
1113 if (wxDoLaunchDefaultBrowser(url
, scheme
, flags
))
1115 //else: call wxLogSysError
1117 if ( !hasValidScheme
)
1119 // set the scheme of url to "http" or "file" if it does not have one
1120 if (wxFileExists(urlOrig
) || wxDirExists(urlOrig
))
1121 url
.Prepend(wxS("file://"));
1123 url
.Prepend(wxS("http://"));
1126 if (wxDoLaunchDefaultBrowser(url
, flags
))
1128 //else: call wxLogSysError
1131 wxLogSysError(_("Failed to open URL \"%s\" in default browser."),
1137 bool wxLaunchDefaultBrowser(const wxString
& url
, int flags
)
1139 // NOTE: as documented, "url" may be both a real well-formed URL
1140 // and a local file name
1142 if ( flags
& wxBROWSER_NOBUSYCURSOR
)
1143 return DoLaunchDefaultBrowserHelper(url
, flags
);
1146 return DoLaunchDefaultBrowserHelper(url
, flags
);
1149 // ----------------------------------------------------------------------------
1150 // Menu accelerators related functions
1151 // ----------------------------------------------------------------------------
1153 #if WXWIN_COMPATIBILITY_2_6
1154 wxChar
*wxStripMenuCodes(const wxChar
*in
, wxChar
*out
)
1157 wxString s
= wxMenuItem::GetLabelText(in
);
1160 wxString s
= wxStripMenuCodes(str
);
1161 #endif // wxUSE_MENUS
1164 // go smash their buffer if it's not big enough - I love char * params
1165 memcpy(out
, s
.c_str(), s
.length() * sizeof(wxChar
));
1169 out
= new wxChar
[s
.length() + 1];
1170 wxStrcpy(out
, s
.c_str());
1177 wxString
wxStripMenuCodes(const wxString
& in
, int flags
)
1179 wxASSERT_MSG( flags
, wxT("this is useless to call without any flags") );
1183 size_t len
= in
.length();
1186 for ( size_t n
= 0; n
< len
; n
++ )
1189 if ( (flags
& wxStrip_Mnemonics
) && ch
== wxT('&') )
1191 // skip it, it is used to introduce the accel char (or to quote
1192 // itself in which case it should still be skipped): note that it
1193 // can't be the last character of the string
1196 wxLogDebug(wxT("Invalid menu string '%s'"), in
.c_str());
1200 // use the next char instead
1204 else if ( (flags
& wxStrip_Accel
) && ch
== wxT('\t') )
1206 // everything after TAB is accel string, exit the loop
1216 // ----------------------------------------------------------------------------
1217 // Window search functions
1218 // ----------------------------------------------------------------------------
1221 * If parent is non-NULL, look through children for a label or title
1222 * matching the specified string. If NULL, look through all top-level windows.
1227 wxFindWindowByLabel (const wxString
& title
, wxWindow
* parent
)
1229 return wxWindow::FindWindowByLabel( title
, parent
);
1234 * If parent is non-NULL, look through children for a name
1235 * matching the specified string. If NULL, look through all top-level windows.
1240 wxFindWindowByName (const wxString
& name
, wxWindow
* parent
)
1242 return wxWindow::FindWindowByName( name
, parent
);
1245 // Returns menu item id or wxNOT_FOUND if none.
1247 wxFindMenuItemId(wxFrame
*frame
,
1248 const wxString
& menuString
,
1249 const wxString
& itemString
)
1252 wxMenuBar
*menuBar
= frame
->GetMenuBar ();
1254 return menuBar
->FindMenuItem (menuString
, itemString
);
1255 #else // !wxUSE_MENUS
1257 wxUnusedVar(menuString
);
1258 wxUnusedVar(itemString
);
1259 #endif // wxUSE_MENUS/!wxUSE_MENUS
1264 // Try to find the deepest child that contains 'pt'.
1265 // We go backwards, to try to allow for controls that are spacially
1266 // within other controls, but are still siblings (e.g. buttons within
1267 // static boxes). Static boxes are likely to be created _before_ controls
1268 // that sit inside them.
1269 wxWindow
* wxFindWindowAtPoint(wxWindow
* win
, const wxPoint
& pt
)
1271 if (!win
->IsShown())
1274 // Hack for wxNotebook case: at least in wxGTK, all pages
1275 // claim to be shown, so we must only deal with the selected one.
1277 if (win
->IsKindOf(CLASSINFO(wxNotebook
)))
1279 wxNotebook
* nb
= (wxNotebook
*) win
;
1280 int sel
= nb
->GetSelection();
1283 wxWindow
* child
= nb
->GetPage(sel
);
1284 wxWindow
* foundWin
= wxFindWindowAtPoint(child
, pt
);
1291 wxWindowList::compatibility_iterator node
= win
->GetChildren().GetLast();
1294 wxWindow
* child
= node
->GetData();
1295 wxWindow
* foundWin
= wxFindWindowAtPoint(child
, pt
);
1298 node
= node
->GetPrevious();
1301 wxPoint pos
= win
->GetPosition();
1302 wxSize sz
= win
->GetSize();
1303 if ( !win
->IsTopLevel() && win
->GetParent() )
1305 pos
= win
->GetParent()->ClientToScreen(pos
);
1308 wxRect
rect(pos
, sz
);
1309 if (rect
.Contains(pt
))
1315 wxWindow
* wxGenericFindWindowAtPoint(const wxPoint
& pt
)
1317 // Go backwards through the list since windows
1318 // on top are likely to have been appended most
1320 wxWindowList::compatibility_iterator node
= wxTopLevelWindows
.GetLast();
1323 wxWindow
* win
= node
->GetData();
1324 wxWindow
* found
= wxFindWindowAtPoint(win
, pt
);
1327 node
= node
->GetPrevious();
1332 // ----------------------------------------------------------------------------
1334 // ----------------------------------------------------------------------------
1337 * N.B. these convenience functions must be separate from msgdlgg.cpp, textdlgg.cpp
1338 * since otherwise the generic code may be pulled in unnecessarily.
1343 int wxMessageBox(const wxString
& message
, const wxString
& caption
, long style
,
1344 wxWindow
*parent
, int WXUNUSED(x
), int WXUNUSED(y
) )
1346 // add the appropriate icon unless this was explicitly disabled by use of
1348 if ( !(style
& wxICON_NONE
) && !(style
& wxICON_MASK
) )
1350 style
|= style
& wxYES
? wxICON_QUESTION
: wxICON_INFORMATION
;
1353 wxMessageDialog
dialog(parent
, message
, caption
, style
);
1355 int ans
= dialog
.ShowModal();
1370 wxFAIL_MSG( wxT("unexpected return code from wxMessageDialog") );
1375 wxVersionInfo
wxGetLibraryVersionInfo()
1377 // don't translate these strings, they're for diagnostics purposes only
1379 msg
.Printf(wxS("wxWidgets Library (%s port)\n")
1380 wxS("Version %d.%d.%d (Unicode: %s, debug level: %d),\n")
1381 wxS("compiled at %s %s\n\n")
1382 wxS("Runtime version of toolkit used is %d.%d.\n"),
1383 wxPlatformInfo::Get().GetPortIdName(),
1387 #if wxUSE_UNICODE_UTF8
1397 wxPlatformInfo::Get().GetToolkitMajorVersion(),
1398 wxPlatformInfo::Get().GetToolkitMinorVersion()
1402 msg
+= wxString::Format("Compile-time GTK+ version is %d.%d.%d.\n",
1408 return wxVersionInfo(wxS("wxWidgets"),
1413 wxS("Copyright (c) 1995-2011 wxWidgets team"));
1416 void wxInfoMessageBox(wxWindow
* parent
)
1418 wxVersionInfo info
= wxGetLibraryVersionInfo();
1419 wxString msg
= info
.ToString();
1421 msg
<< wxS("\n") << info
.GetCopyright();
1423 wxMessageBox(msg
, wxT("wxWidgets information"),
1424 wxICON_INFORMATION
| wxOK
,
1428 #endif // wxUSE_MSGDLG
1432 wxString
wxGetTextFromUser(const wxString
& message
, const wxString
& caption
,
1433 const wxString
& defaultValue
, wxWindow
*parent
,
1434 wxCoord x
, wxCoord y
, bool centre
)
1437 long style
= wxTextEntryDialogStyle
;
1444 wxTextEntryDialog
dialog(parent
, message
, caption
, defaultValue
, style
, wxPoint(x
, y
));
1446 if (dialog
.ShowModal() == wxID_OK
)
1448 str
= dialog
.GetValue();
1454 wxString
wxGetPasswordFromUser(const wxString
& message
,
1455 const wxString
& caption
,
1456 const wxString
& defaultValue
,
1458 wxCoord x
, wxCoord y
, bool centre
)
1461 long style
= wxTextEntryDialogStyle
;
1468 wxPasswordEntryDialog
dialog(parent
, message
, caption
, defaultValue
,
1469 style
, wxPoint(x
, y
));
1470 if ( dialog
.ShowModal() == wxID_OK
)
1472 str
= dialog
.GetValue();
1478 #endif // wxUSE_TEXTDLG
1482 wxColour
wxGetColourFromUser(wxWindow
*parent
,
1483 const wxColour
& colInit
,
1484 const wxString
& caption
,
1485 wxColourData
*ptrData
)
1487 // contains serialized representation of wxColourData used the last time
1488 // the dialog was shown: we want to reuse it the next time in order to show
1489 // the same custom colours to the user (and we can't just have static
1490 // wxColourData itself because it's a GUI object and so should be destroyed
1491 // before GUI shutdown and doing it during static cleanup is too late)
1492 static wxString s_strColourData
;
1498 if ( !s_strColourData
.empty() )
1500 if ( !data
.FromString(s_strColourData
) )
1502 wxFAIL_MSG( "bug in wxColourData::FromString()?" );
1506 // we don't get back the "choose full" flag value from the native
1507 // dialog and so we can't preserve it between runs, so we decide to
1508 // always use it as it seems better than not using it (user can
1509 // just ignore the extra controls in the dialog but having to click
1510 // a button each time to show them would be very annoying
1511 data
.SetChooseFull(true);
1516 if ( colInit
.IsOk() )
1518 ptrData
->SetColour(colInit
);
1522 wxColourDialog
dialog(parent
, ptrData
);
1523 if (!caption
.empty())
1524 dialog
.SetTitle(caption
);
1525 if ( dialog
.ShowModal() == wxID_OK
)
1527 *ptrData
= dialog
.GetColourData();
1528 colRet
= ptrData
->GetColour();
1529 s_strColourData
= ptrData
->ToString();
1531 //else: leave colRet invalid
1536 #endif // wxUSE_COLOURDLG
1540 wxFont
wxGetFontFromUser(wxWindow
*parent
, const wxFont
& fontInit
, const wxString
& caption
)
1543 if ( fontInit
.IsOk() )
1545 data
.SetInitialFont(fontInit
);
1549 wxFontDialog
dialog(parent
, data
);
1550 if (!caption
.empty())
1551 dialog
.SetTitle(caption
);
1552 if ( dialog
.ShowModal() == wxID_OK
)
1554 fontRet
= dialog
.GetFontData().GetChosenFont();
1556 //else: leave it invalid
1561 #endif // wxUSE_FONTDLG
1563 // ----------------------------------------------------------------------------
1564 // wxSafeYield and supporting functions
1565 // ----------------------------------------------------------------------------
1567 void wxEnableTopLevelWindows(bool enable
)
1569 wxWindowList::compatibility_iterator node
;
1570 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1571 node
->GetData()->Enable(enable
);
1574 #if defined(__WXOSX__) && wxOSX_USE_COCOA
1576 // defined in evtloop.mm
1580 wxWindowDisabler::wxWindowDisabler(bool disable
)
1582 m_disabled
= disable
;
1587 wxWindowDisabler::wxWindowDisabler(wxWindow
*winToSkip
)
1590 DoDisable(winToSkip
);
1593 void wxWindowDisabler::DoDisable(wxWindow
*winToSkip
)
1595 // remember the top level windows which were already disabled, so that we
1596 // don't reenable them later
1597 m_winDisabled
= NULL
;
1599 wxWindowList::compatibility_iterator node
;
1600 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1602 wxWindow
*winTop
= node
->GetData();
1603 if ( winTop
== winToSkip
)
1606 // we don't need to disable the hidden or already disabled windows
1607 if ( winTop
->IsEnabled() && winTop
->IsShown() )
1613 if ( !m_winDisabled
)
1615 m_winDisabled
= new wxWindowList
;
1618 m_winDisabled
->Append(winTop
);
1623 wxWindowDisabler::~wxWindowDisabler()
1628 wxWindowList::compatibility_iterator node
;
1629 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1631 wxWindow
*winTop
= node
->GetData();
1632 if ( !m_winDisabled
|| !m_winDisabled
->Find(winTop
) )
1636 //else: had been already disabled, don't reenable
1639 delete m_winDisabled
;
1644 // Yield to other apps/messages and disable user input to all windows except
1646 bool wxSafeYield(wxWindow
*win
, bool onlyIfNeeded
)
1648 wxWindowDisabler
wd(win
);
1652 rc
= wxYieldIfNeeded();
1659 // ----------------------------------------------------------------------------
1660 // wxApp::Yield() wrappers for backwards compatibility
1661 // ----------------------------------------------------------------------------
1665 return wxTheApp
&& wxTheApp
->Yield();
1668 bool wxYieldIfNeeded()
1670 return wxTheApp
&& wxTheApp
->Yield(true);