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 // POSIX, but not in an include file
585 extern char **environ
;
587 char **env
= environ
;
596 const wxString
var(*env
);
598 name
= var
.BeforeFirst(wxS('='), &value
);
600 (*map
)[name
] = value
;
611 // ----------------------------------------------------------------------------
613 // ----------------------------------------------------------------------------
615 // wxDoExecuteWithCapture() helper: reads an entire stream into one array
617 // returns true if ok, false if error
619 static bool ReadAll(wxInputStream
*is
, wxArrayString
& output
)
621 wxCHECK_MSG( is
, false, wxT("NULL stream in wxExecute()?") );
623 // the stream could be already at EOF or in wxSTREAM_BROKEN_PIPE state
626 wxTextInputStream
tis(*is
);
630 wxString line
= tis
.ReadLine();
632 // check for EOF before other errors as it's not really an error
635 // add the last, possibly incomplete, line
641 // any other error is fatal
650 #endif // wxUSE_STREAMS
652 // this is a private function because it hasn't a clean interface: the first
653 // array is passed by reference, the second by pointer - instead we have 2
654 // public versions of wxExecute() below
655 static long wxDoExecuteWithCapture(const wxString
& command
,
656 wxArrayString
& output
,
657 wxArrayString
* error
,
659 const wxExecuteEnv
*env
)
661 // create a wxProcess which will capture the output
662 wxProcess
*process
= new wxProcess
;
665 long rc
= wxExecute(command
, wxEXEC_SYNC
| flags
, process
, env
);
670 if ( !ReadAll(process
->GetInputStream(), output
) )
675 if ( !ReadAll(process
->GetErrorStream(), *error
) )
683 #endif // wxUSE_STREAMS/!wxUSE_STREAMS
690 long wxExecute(const wxString
& command
, wxArrayString
& output
, int flags
,
691 const wxExecuteEnv
*env
)
693 return wxDoExecuteWithCapture(command
, output
, NULL
, flags
, env
);
696 long wxExecute(const wxString
& command
,
697 wxArrayString
& output
,
698 wxArrayString
& error
,
700 const wxExecuteEnv
*env
)
702 return wxDoExecuteWithCapture(command
, output
, &error
, flags
, env
);
705 // ----------------------------------------------------------------------------
707 // ----------------------------------------------------------------------------
710 static long wxCurrentId
= 100;
714 // skip the part of IDs space that contains hard-coded values:
715 if (wxCurrentId
== wxID_LOWEST
)
716 wxCurrentId
= wxID_HIGHEST
+ 1;
718 return wxCurrentId
++;
722 wxGetCurrentId(void) { return wxCurrentId
; }
725 wxRegisterId (long id
)
727 if (id
>= wxCurrentId
)
728 wxCurrentId
= id
+ 1;
731 // ----------------------------------------------------------------------------
732 // wxQsort, adapted by RR to allow user_data
733 // ----------------------------------------------------------------------------
735 /* This file is part of the GNU C Library.
736 Written by Douglas C. Schmidt (schmidt@ics.uci.edu).
738 Douglas Schmidt kindly gave permission to relicence the
739 code under the wxWindows licence:
741 From: "Douglas C. Schmidt" <schmidt@dre.vanderbilt.edu>
742 To: Robert Roebling <robert.roebling@uni-ulm.de>
743 Subject: Re: qsort licence
744 Date: Mon, 23 Jul 2007 03:44:25 -0500
745 Sender: schmidt@dre.vanderbilt.edu
746 Message-Id: <20070723084426.64F511000A8@tango.dre.vanderbilt.edu>
750 > [...] I'm asking if you'd be willing to relicence your code
751 > under the wxWindows licence. [...]
753 That's fine with me [...]
760 /* Byte-wise swap two items of size SIZE. */
761 #define SWAP(a, b, size) \
764 register size_t __size = (size); \
765 register char *__a = (a), *__b = (b); \
771 } while (--__size > 0); \
774 /* Discontinue quicksort algorithm when partition gets below this size.
775 This particular magic number was chosen to work best on a Sun 4/260. */
778 /* Stack node declarations used to store unfulfilled partition obligations. */
785 /* The next 4 #defines implement a very fast in-line stack abstraction. */
786 #define STACK_SIZE (8 * sizeof(unsigned long int))
787 #define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top))
788 #define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi)))
789 #define STACK_NOT_EMPTY (stack < top)
792 /* Order size using quicksort. This implementation incorporates
793 four optimizations discussed in Sedgewick:
795 1. Non-recursive, using an explicit stack of pointer that store the
796 next array partition to sort. To save time, this maximum amount
797 of space required to store an array of MAX_INT is allocated on the
798 stack. Assuming a 32-bit integer, this needs only 32 *
799 sizeof(stack_node) == 136 bits. Pretty cheap, actually.
801 2. Chose the pivot element using a median-of-three decision tree.
802 This reduces the probability of selecting a bad pivot value and
803 eliminates certain extraneous comparisons.
805 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving
806 insertion sort to order the MAX_THRESH items within each partition.
807 This is a big win, since insertion sort is faster for small, mostly
808 sorted array segments.
810 4. The larger of the two sub-partitions is always pushed onto the
811 stack first, with the algorithm then concentrating on the
812 smaller partition. This *guarantees* no more than log (n)
813 stack size is needed (actually O(1) in this case)! */
815 void wxQsort(void *const pbase
, size_t total_elems
,
816 size_t size
, CMPFUNCDATA cmp
, const void* user_data
)
818 register char *base_ptr
= (char *) pbase
;
819 const size_t max_thresh
= MAX_THRESH
* size
;
821 if (total_elems
== 0)
822 /* Avoid lossage with unsigned arithmetic below. */
825 if (total_elems
> MAX_THRESH
)
828 char *hi
= &lo
[size
* (total_elems
- 1)];
829 stack_node stack
[STACK_SIZE
];
830 stack_node
*top
= stack
;
834 while (STACK_NOT_EMPTY
)
839 /* Select median value from among LO, MID, and HI. Rearrange
840 LO and HI so the three values are sorted. This lowers the
841 probability of picking a pathological pivot value and
842 skips a comparison for both the LEFT_PTR and RIGHT_PTR. */
844 char *mid
= lo
+ size
* ((hi
- lo
) / size
>> 1);
846 if ((*cmp
) ((void *) mid
, (void *) lo
, user_data
) < 0)
847 SWAP (mid
, lo
, size
);
848 if ((*cmp
) ((void *) hi
, (void *) mid
, user_data
) < 0)
849 SWAP (mid
, hi
, size
);
852 if ((*cmp
) ((void *) mid
, (void *) lo
, user_data
) < 0)
853 SWAP (mid
, lo
, size
);
855 left_ptr
= lo
+ size
;
856 right_ptr
= hi
- size
;
858 /* Here's the famous ``collapse the walls'' section of quicksort.
859 Gotta like those tight inner loops! They are the main reason
860 that this algorithm runs much faster than others. */
863 while ((*cmp
) ((void *) left_ptr
, (void *) mid
, user_data
) < 0)
866 while ((*cmp
) ((void *) mid
, (void *) right_ptr
, user_data
) < 0)
869 if (left_ptr
< right_ptr
)
871 SWAP (left_ptr
, right_ptr
, size
);
874 else if (mid
== right_ptr
)
879 else if (left_ptr
== right_ptr
)
886 while (left_ptr
<= right_ptr
);
888 /* Set up pointers for next iteration. First determine whether
889 left and right partitions are below the threshold size. If so,
890 ignore one or both. Otherwise, push the larger partition's
891 bounds on the stack and continue sorting the smaller one. */
893 if ((size_t) (right_ptr
- lo
) <= max_thresh
)
895 if ((size_t) (hi
- left_ptr
) <= max_thresh
)
896 /* Ignore both small partitions. */
899 /* Ignore small left partition. */
902 else if ((size_t) (hi
- left_ptr
) <= max_thresh
)
903 /* Ignore small right partition. */
905 else if ((right_ptr
- lo
) > (hi
- left_ptr
))
907 /* Push larger left partition indices. */
908 PUSH (lo
, right_ptr
);
913 /* Push larger right partition indices. */
920 /* Once the BASE_PTR array is partially sorted by quicksort the rest
921 is completely sorted using insertion sort, since this is efficient
922 for partitions below MAX_THRESH size. BASE_PTR points to the beginning
923 of the array to sort, and END_PTR points at the very last element in
924 the array (*not* one beyond it!). */
927 char *const end_ptr
= &base_ptr
[size
* (total_elems
- 1)];
928 char *tmp_ptr
= base_ptr
;
929 char *thresh
= base_ptr
+ max_thresh
;
930 if ( thresh
> end_ptr
)
932 register char *run_ptr
;
934 /* Find smallest element in first threshold and place it at the
935 array's beginning. This is the smallest array element,
936 and the operation speeds up insertion sort's inner loop. */
938 for (run_ptr
= tmp_ptr
+ size
; run_ptr
<= thresh
; run_ptr
+= size
)
939 if ((*cmp
) ((void *) run_ptr
, (void *) tmp_ptr
, user_data
) < 0)
942 if (tmp_ptr
!= base_ptr
)
943 SWAP (tmp_ptr
, base_ptr
, size
);
945 /* Insertion sort, running from left-hand-side up to right-hand-side. */
947 run_ptr
= base_ptr
+ size
;
948 while ((run_ptr
+= size
) <= end_ptr
)
950 tmp_ptr
= run_ptr
- size
;
951 while ((*cmp
) ((void *) run_ptr
, (void *) tmp_ptr
, user_data
) < 0)
955 if (tmp_ptr
!= run_ptr
)
959 trav
= run_ptr
+ size
;
960 while (--trav
>= run_ptr
)
965 for (hi
= lo
= trav
; (lo
-= size
) >= tmp_ptr
; hi
= lo
)
978 // ============================================================================
979 // GUI-only functions from now on
980 // ============================================================================
984 // this function is only really implemented for X11-based ports, including GTK1
985 // (GTK2 sets detectable auto-repeat automatically anyhow)
986 #if !(defined(__WXX11__) || defined(__WXMOTIF__) || \
987 (defined(__WXGTK__) && !defined(__WXGTK20__)))
988 bool wxSetDetectableAutoRepeat( bool WXUNUSED(flag
) )
992 #endif // !X11-based port
994 // ----------------------------------------------------------------------------
995 // Launch default browser
996 // ----------------------------------------------------------------------------
998 #if defined(__WXMSW__)
1000 // implemented in a port-specific utils source file:
1001 bool wxDoLaunchDefaultBrowser(const wxString
& url
, const wxString
& scheme
, int flags
);
1003 #elif defined(__WXX11__) || defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXCOCOA__) || \
1004 (defined(__WXOSX__) )
1006 // implemented in a port-specific utils source file:
1007 bool wxDoLaunchDefaultBrowser(const wxString
& url
, int flags
);
1011 // a "generic" implementation:
1012 bool wxDoLaunchDefaultBrowser(const wxString
& url
, int flags
)
1014 // on other platforms try to use mime types or wxExecute...
1020 wxFileType
*ft
= wxTheMimeTypesManager
->GetFileTypeFromExtension(wxT("html"));
1024 ft
->GetMimeType(&mt
);
1026 ok
= ft
->GetOpenCommand(&cmd
, wxFileType::MessageParameters(url
));
1029 #endif // wxUSE_MIMETYPE
1031 if ( !ok
|| cmd
.empty() )
1033 // fallback to checking for the BROWSER environment variable
1034 if ( !wxGetEnv(wxT("BROWSER"), &cmd
) || cmd
.empty() )
1035 cmd
<< wxT(' ') << url
;
1038 ok
= ( !cmd
.empty() && wxExecute(cmd
) );
1042 // no file type for HTML extension
1043 wxLogError(_("No default application configured for HTML files."));
1049 static bool DoLaunchDefaultBrowserHelper(const wxString
& urlOrig
, int flags
)
1051 // NOTE: we don't have to care about the wxBROWSER_NOBUSYCURSOR flag
1052 // as it was already handled by wxLaunchDefaultBrowser
1056 wxString
url(urlOrig
), scheme
;
1059 // this check is useful to avoid that wxURI recognizes as scheme parts of
1060 // the filename, in case urlOrig is a local filename
1061 // (e.g. "C:\\test.txt" when parsed by wxURI reports a scheme == "C")
1062 bool hasValidScheme
= uri
.HasScheme() && uri
.GetScheme().length() > 1;
1064 #if defined(__WXMSW__)
1066 // NOTE: when testing wxMSW's wxLaunchDefaultBrowser all possible forms
1067 // of the URL/flags should be tested; e.g.:
1069 // for (int i=0; i<2; i++)
1071 // // test arguments without a valid URL scheme:
1072 // wxLaunchDefaultBrowser("C:\\test.txt", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1073 // wxLaunchDefaultBrowser("wxwidgets.org", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1075 // // test arguments with different valid schemes:
1076 // wxLaunchDefaultBrowser("file:/C%3A/test.txt", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1077 // wxLaunchDefaultBrowser("http://wxwidgets.org", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1078 // wxLaunchDefaultBrowser("mailto:user@host.org", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1080 // (assuming you have a C:\test.txt file)
1082 if ( !hasValidScheme
)
1084 if (wxFileExists(urlOrig
) || wxDirExists(urlOrig
))
1087 // do not prepend the file scheme to the URL as ShellExecuteEx() doesn't like it
1091 url
.Prepend(wxS("http://"));
1095 else if ( hasValidScheme
)
1097 scheme
= uri
.GetScheme();
1099 if ( uri
.GetScheme() == "file" )
1101 // TODO: extract URLToFileName() to some always compiled in
1103 #if wxUSE_FILESYSTEM
1104 // ShellExecuteEx() doesn't like the "file" scheme when opening local files;
1106 url
= wxFileSystem::URLToFileName(url
).GetFullPath();
1107 #endif // wxUSE_FILESYSTEM
1111 if (wxDoLaunchDefaultBrowser(url
, scheme
, flags
))
1113 //else: call wxLogSysError
1115 if ( !hasValidScheme
)
1117 // set the scheme of url to "http" or "file" if it does not have one
1118 if (wxFileExists(urlOrig
) || wxDirExists(urlOrig
))
1119 url
.Prepend(wxS("file://"));
1121 url
.Prepend(wxS("http://"));
1124 if (wxDoLaunchDefaultBrowser(url
, flags
))
1126 //else: call wxLogSysError
1129 wxLogSysError(_("Failed to open URL \"%s\" in default browser."),
1135 bool wxLaunchDefaultBrowser(const wxString
& url
, int flags
)
1137 // NOTE: as documented, "url" may be both a real well-formed URL
1138 // and a local file name
1140 if ( flags
& wxBROWSER_NOBUSYCURSOR
)
1141 return DoLaunchDefaultBrowserHelper(url
, flags
);
1144 return DoLaunchDefaultBrowserHelper(url
, flags
);
1147 // ----------------------------------------------------------------------------
1148 // Menu accelerators related functions
1149 // ----------------------------------------------------------------------------
1151 #if WXWIN_COMPATIBILITY_2_6
1152 wxChar
*wxStripMenuCodes(const wxChar
*in
, wxChar
*out
)
1155 wxString s
= wxMenuItem::GetLabelText(in
);
1158 wxString s
= wxStripMenuCodes(str
);
1159 #endif // wxUSE_MENUS
1162 // go smash their buffer if it's not big enough - I love char * params
1163 memcpy(out
, s
.c_str(), s
.length() * sizeof(wxChar
));
1167 out
= new wxChar
[s
.length() + 1];
1168 wxStrcpy(out
, s
.c_str());
1175 wxString
wxStripMenuCodes(const wxString
& in
, int flags
)
1177 wxASSERT_MSG( flags
, wxT("this is useless to call without any flags") );
1181 size_t len
= in
.length();
1184 for ( size_t n
= 0; n
< len
; n
++ )
1187 if ( (flags
& wxStrip_Mnemonics
) && ch
== wxT('&') )
1189 // skip it, it is used to introduce the accel char (or to quote
1190 // itself in which case it should still be skipped): note that it
1191 // can't be the last character of the string
1194 wxLogDebug(wxT("Invalid menu string '%s'"), in
.c_str());
1198 // use the next char instead
1202 else if ( (flags
& wxStrip_Accel
) && ch
== wxT('\t') )
1204 // everything after TAB is accel string, exit the loop
1214 // ----------------------------------------------------------------------------
1215 // Window search functions
1216 // ----------------------------------------------------------------------------
1219 * If parent is non-NULL, look through children for a label or title
1220 * matching the specified string. If NULL, look through all top-level windows.
1225 wxFindWindowByLabel (const wxString
& title
, wxWindow
* parent
)
1227 return wxWindow::FindWindowByLabel( title
, parent
);
1232 * If parent is non-NULL, look through children for a name
1233 * matching the specified string. If NULL, look through all top-level windows.
1238 wxFindWindowByName (const wxString
& name
, wxWindow
* parent
)
1240 return wxWindow::FindWindowByName( name
, parent
);
1243 // Returns menu item id or wxNOT_FOUND if none.
1245 wxFindMenuItemId(wxFrame
*frame
,
1246 const wxString
& menuString
,
1247 const wxString
& itemString
)
1250 wxMenuBar
*menuBar
= frame
->GetMenuBar ();
1252 return menuBar
->FindMenuItem (menuString
, itemString
);
1253 #else // !wxUSE_MENUS
1255 wxUnusedVar(menuString
);
1256 wxUnusedVar(itemString
);
1257 #endif // wxUSE_MENUS/!wxUSE_MENUS
1262 // Try to find the deepest child that contains 'pt'.
1263 // We go backwards, to try to allow for controls that are spacially
1264 // within other controls, but are still siblings (e.g. buttons within
1265 // static boxes). Static boxes are likely to be created _before_ controls
1266 // that sit inside them.
1267 wxWindow
* wxFindWindowAtPoint(wxWindow
* win
, const wxPoint
& pt
)
1269 if (!win
->IsShown())
1272 // Hack for wxNotebook case: at least in wxGTK, all pages
1273 // claim to be shown, so we must only deal with the selected one.
1275 if (win
->IsKindOf(CLASSINFO(wxNotebook
)))
1277 wxNotebook
* nb
= (wxNotebook
*) win
;
1278 int sel
= nb
->GetSelection();
1281 wxWindow
* child
= nb
->GetPage(sel
);
1282 wxWindow
* foundWin
= wxFindWindowAtPoint(child
, pt
);
1289 wxWindowList::compatibility_iterator node
= win
->GetChildren().GetLast();
1292 wxWindow
* child
= node
->GetData();
1293 wxWindow
* foundWin
= wxFindWindowAtPoint(child
, pt
);
1296 node
= node
->GetPrevious();
1299 wxPoint pos
= win
->GetPosition();
1300 wxSize sz
= win
->GetSize();
1301 if ( !win
->IsTopLevel() && win
->GetParent() )
1303 pos
= win
->GetParent()->ClientToScreen(pos
);
1306 wxRect
rect(pos
, sz
);
1307 if (rect
.Contains(pt
))
1313 wxWindow
* wxGenericFindWindowAtPoint(const wxPoint
& pt
)
1315 // Go backwards through the list since windows
1316 // on top are likely to have been appended most
1318 wxWindowList::compatibility_iterator node
= wxTopLevelWindows
.GetLast();
1321 wxWindow
* win
= node
->GetData();
1322 wxWindow
* found
= wxFindWindowAtPoint(win
, pt
);
1325 node
= node
->GetPrevious();
1330 // ----------------------------------------------------------------------------
1332 // ----------------------------------------------------------------------------
1335 * N.B. these convenience functions must be separate from msgdlgg.cpp, textdlgg.cpp
1336 * since otherwise the generic code may be pulled in unnecessarily.
1341 int wxMessageBox(const wxString
& message
, const wxString
& caption
, long style
,
1342 wxWindow
*parent
, int WXUNUSED(x
), int WXUNUSED(y
) )
1344 // add the appropriate icon unless this was explicitly disabled by use of
1346 if ( !(style
& wxICON_NONE
) && !(style
& wxICON_MASK
) )
1348 style
|= style
& wxYES
? wxICON_QUESTION
: wxICON_INFORMATION
;
1351 wxMessageDialog
dialog(parent
, message
, caption
, style
);
1353 int ans
= dialog
.ShowModal();
1366 wxFAIL_MSG( wxT("unexpected return code from wxMessageDialog") );
1371 wxVersionInfo
wxGetLibraryVersionInfo()
1373 // don't translate these strings, they're for diagnostics purposes only
1375 msg
.Printf(wxS("wxWidgets Library (%s port)\n")
1376 wxS("Version %d.%d.%d (Unicode: %s, debug level: %d),\n")
1377 wxS("compiled at %s %s\n\n")
1378 wxS("Runtime version of toolkit used is %d.%d.\n"),
1379 wxPlatformInfo::Get().GetPortIdName(),
1383 #if wxUSE_UNICODE_UTF8
1393 wxPlatformInfo::Get().GetToolkitMajorVersion(),
1394 wxPlatformInfo::Get().GetToolkitMinorVersion()
1398 msg
+= wxString::Format("Compile-time GTK+ version is %d.%d.%d.\n",
1404 return wxVersionInfo(wxS("wxWidgets"),
1409 wxS("Copyright (c) 1995-2010 wxWidgets team"));
1412 void wxInfoMessageBox(wxWindow
* parent
)
1414 wxVersionInfo info
= wxGetLibraryVersionInfo();
1415 wxString msg
= info
.ToString();
1417 msg
<< wxS("\n") << info
.GetCopyright();
1419 wxMessageBox(msg
, wxT("wxWidgets information"),
1420 wxICON_INFORMATION
| wxOK
,
1424 #endif // wxUSE_MSGDLG
1428 wxString
wxGetTextFromUser(const wxString
& message
, const wxString
& caption
,
1429 const wxString
& defaultValue
, wxWindow
*parent
,
1430 wxCoord x
, wxCoord y
, bool centre
)
1433 long style
= wxTextEntryDialogStyle
;
1440 wxTextEntryDialog
dialog(parent
, message
, caption
, defaultValue
, style
, wxPoint(x
, y
));
1442 if (dialog
.ShowModal() == wxID_OK
)
1444 str
= dialog
.GetValue();
1450 wxString
wxGetPasswordFromUser(const wxString
& message
,
1451 const wxString
& caption
,
1452 const wxString
& defaultValue
,
1454 wxCoord x
, wxCoord y
, bool centre
)
1457 long style
= wxTextEntryDialogStyle
;
1464 wxPasswordEntryDialog
dialog(parent
, message
, caption
, defaultValue
,
1465 style
, wxPoint(x
, y
));
1466 if ( dialog
.ShowModal() == wxID_OK
)
1468 str
= dialog
.GetValue();
1474 #endif // wxUSE_TEXTDLG
1478 wxColour
wxGetColourFromUser(wxWindow
*parent
,
1479 const wxColour
& colInit
,
1480 const wxString
& caption
,
1481 wxColourData
*ptrData
)
1483 // contains serialized representation of wxColourData used the last time
1484 // the dialog was shown: we want to reuse it the next time in order to show
1485 // the same custom colours to the user (and we can't just have static
1486 // wxColourData itself because it's a GUI object and so should be destroyed
1487 // before GUI shutdown and doing it during static cleanup is too late)
1488 static wxString s_strColourData
;
1494 if ( !s_strColourData
.empty() )
1496 if ( !data
.FromString(s_strColourData
) )
1498 wxFAIL_MSG( "bug in wxColourData::FromString()?" );
1502 // we don't get back the "choose full" flag value from the native
1503 // dialog and so we can't preserve it between runs, so we decide to
1504 // always use it as it seems better than not using it (user can
1505 // just ignore the extra controls in the dialog but having to click
1506 // a button each time to show them would be very annoying
1507 data
.SetChooseFull(true);
1512 if ( colInit
.IsOk() )
1514 ptrData
->SetColour(colInit
);
1518 wxColourDialog
dialog(parent
, ptrData
);
1519 if (!caption
.empty())
1520 dialog
.SetTitle(caption
);
1521 if ( dialog
.ShowModal() == wxID_OK
)
1523 *ptrData
= dialog
.GetColourData();
1524 colRet
= ptrData
->GetColour();
1525 s_strColourData
= ptrData
->ToString();
1527 //else: leave colRet invalid
1532 #endif // wxUSE_COLOURDLG
1536 wxFont
wxGetFontFromUser(wxWindow
*parent
, const wxFont
& fontInit
, const wxString
& caption
)
1539 if ( fontInit
.Ok() )
1541 data
.SetInitialFont(fontInit
);
1545 wxFontDialog
dialog(parent
, data
);
1546 if (!caption
.empty())
1547 dialog
.SetTitle(caption
);
1548 if ( dialog
.ShowModal() == wxID_OK
)
1550 fontRet
= dialog
.GetFontData().GetChosenFont();
1552 //else: leave it invalid
1557 #endif // wxUSE_FONTDLG
1559 // ----------------------------------------------------------------------------
1560 // wxSafeYield and supporting functions
1561 // ----------------------------------------------------------------------------
1563 void wxEnableTopLevelWindows(bool enable
)
1565 wxWindowList::compatibility_iterator node
;
1566 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1567 node
->GetData()->Enable(enable
);
1570 wxWindowDisabler::wxWindowDisabler(bool disable
)
1572 m_disabled
= disable
;
1577 wxWindowDisabler::wxWindowDisabler(wxWindow
*winToSkip
)
1580 DoDisable(winToSkip
);
1583 void wxWindowDisabler::DoDisable(wxWindow
*winToSkip
)
1585 // remember the top level windows which were already disabled, so that we
1586 // don't reenable them later
1587 m_winDisabled
= NULL
;
1589 wxWindowList::compatibility_iterator node
;
1590 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1592 wxWindow
*winTop
= node
->GetData();
1593 if ( winTop
== winToSkip
)
1596 // we don't need to disable the hidden or already disabled windows
1597 if ( winTop
->IsEnabled() && winTop
->IsShown() )
1603 if ( !m_winDisabled
)
1605 m_winDisabled
= new wxWindowList
;
1608 m_winDisabled
->Append(winTop
);
1613 wxWindowDisabler::~wxWindowDisabler()
1618 wxWindowList::compatibility_iterator node
;
1619 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1621 wxWindow
*winTop
= node
->GetData();
1622 if ( !m_winDisabled
|| !m_winDisabled
->Find(winTop
) )
1626 //else: had been already disabled, don't reenable
1629 delete m_winDisabled
;
1632 // Yield to other apps/messages and disable user input to all windows except
1634 bool wxSafeYield(wxWindow
*win
, bool onlyIfNeeded
)
1636 wxWindowDisabler
wd(win
);
1640 rc
= wxYieldIfNeeded();
1647 // ----------------------------------------------------------------------------
1648 // wxApp::Yield() wrappers for backwards compatibility
1649 // ----------------------------------------------------------------------------
1653 return wxTheApp
&& wxTheApp
->Yield();
1656 bool wxYieldIfNeeded()
1658 return wxTheApp
&& wxTheApp
->Yield(true);