1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/utilscmn.cpp
3 // Purpose: Miscellaneous utility functions and classes
4 // Author: Julian Smart
7 // Copyright: (c) 1998 Julian Smart
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // ============================================================================
13 // ============================================================================
15 // ----------------------------------------------------------------------------
17 // ----------------------------------------------------------------------------
19 // For compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
28 #include "wx/string.h"
34 #include "wx/window.h"
37 #include "wx/msgdlg.h"
38 #include "wx/textdlg.h"
39 #include "wx/textctrl.h" // for wxTE_PASSWORD
41 #include "wx/menuitem.h"
47 #include "wx/apptrait.h"
49 #include "wx/process.h"
50 #include "wx/txtstrm.h"
52 #include "wx/mimetype.h"
53 #include "wx/config.h"
54 #include "wx/versioninfo.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/notebook.h"
73 #include "wx/statusbr.h"
79 #include "wx/msw/wince/time.h"
83 #include "wx/osx/private.h"
86 #if !defined(__WXWINCE__)
87 #include <sys/types.h>
91 #if defined(__WINDOWS__)
92 #include "wx/msw/private.h"
93 #include "wx/filesys.h"
96 #if wxUSE_GUI && defined(__WXGTK__)
97 #include <gtk/gtk.h> // for GTK_XXX_VERSION constants
102 // ============================================================================
104 // ============================================================================
106 // Array used in DecToHex conversion routine.
107 static const wxChar hexArray
[] = wxT("0123456789ABCDEF");
109 // Convert 2-digit hex number to decimal
110 int wxHexToDec(const wxString
& str
)
113 buf
[0] = str
.GetChar(0);
114 buf
[1] = str
.GetChar(1);
115 return wxHexToDec((const char*) buf
);
118 // Convert decimal integer to 2-character hex string
119 void wxDecToHex(int dec
, wxChar
*buf
)
121 int firstDigit
= (int)(dec
/16.0);
122 int secondDigit
= (int)(dec
- (firstDigit
*16.0));
123 buf
[0] = hexArray
[firstDigit
];
124 buf
[1] = hexArray
[secondDigit
];
128 // Convert decimal integer to 2 characters
129 void wxDecToHex(int dec
, char* ch1
, char* ch2
)
131 int firstDigit
= (int)(dec
/16.0);
132 int secondDigit
= (int)(dec
- (firstDigit
*16.0));
133 (*ch1
) = (char) hexArray
[firstDigit
];
134 (*ch2
) = (char) hexArray
[secondDigit
];
137 // Convert decimal integer to 2-character hex string
138 wxString
wxDecToHex(int dec
)
141 wxDecToHex(dec
, buf
);
142 return wxString(buf
);
145 // ----------------------------------------------------------------------------
147 // ----------------------------------------------------------------------------
149 // Return the current date/time
154 wxDateTime now
= wxDateTime::Now();
157 return wxEmptyString
;
160 time_t now
= time(NULL
);
161 char *date
= ctime(&now
);
163 return wxString::FromAscii(date
);
167 #if WXWIN_COMPATIBILITY_2_8
168 void wxUsleep(unsigned long milliseconds
)
170 wxMilliSleep(milliseconds
);
174 const wxChar
*wxGetInstallPrefix()
178 if ( wxGetEnv(wxT("WXPREFIX"), &prefix
) )
179 return prefix
.c_str();
181 #ifdef wxINSTALL_PREFIX
182 return wxT(wxINSTALL_PREFIX
);
184 return wxEmptyString
;
188 wxString
wxGetDataDir()
190 wxString dir
= wxGetInstallPrefix();
191 dir
<< wxFILE_SEP_PATH
<< wxT("share") << wxFILE_SEP_PATH
<< wxT("wx");
195 bool wxIsPlatformLittleEndian()
197 // Are we little or big endian? This method is from Harbison & Steele.
201 char c
[sizeof(long)];
209 // ----------------------------------------------------------------------------
211 // ----------------------------------------------------------------------------
214 * Class to make it easier to specify platform-dependent values
217 wxArrayInt
* wxPlatform::sm_customPlatforms
= NULL
;
219 void wxPlatform::Copy(const wxPlatform
& platform
)
221 m_longValue
= platform
.m_longValue
;
222 m_doubleValue
= platform
.m_doubleValue
;
223 m_stringValue
= platform
.m_stringValue
;
226 wxPlatform
wxPlatform::If(int platform
, long value
)
229 return wxPlatform(value
);
234 wxPlatform
wxPlatform::IfNot(int platform
, long value
)
237 return wxPlatform(value
);
242 wxPlatform
& wxPlatform::ElseIf(int platform
, long value
)
249 wxPlatform
& wxPlatform::ElseIfNot(int platform
, long value
)
256 wxPlatform
wxPlatform::If(int platform
, double value
)
259 return wxPlatform(value
);
264 wxPlatform
wxPlatform::IfNot(int platform
, double value
)
267 return wxPlatform(value
);
272 wxPlatform
& wxPlatform::ElseIf(int platform
, double value
)
275 m_doubleValue
= value
;
279 wxPlatform
& wxPlatform::ElseIfNot(int platform
, double value
)
282 m_doubleValue
= value
;
286 wxPlatform
wxPlatform::If(int platform
, const wxString
& value
)
289 return wxPlatform(value
);
294 wxPlatform
wxPlatform::IfNot(int platform
, const wxString
& value
)
297 return wxPlatform(value
);
302 wxPlatform
& wxPlatform::ElseIf(int platform
, const wxString
& value
)
305 m_stringValue
= value
;
309 wxPlatform
& wxPlatform::ElseIfNot(int platform
, const wxString
& value
)
312 m_stringValue
= value
;
316 wxPlatform
& wxPlatform::Else(long value
)
322 wxPlatform
& wxPlatform::Else(double value
)
324 m_doubleValue
= value
;
328 wxPlatform
& wxPlatform::Else(const wxString
& value
)
330 m_stringValue
= value
;
334 void wxPlatform::AddPlatform(int platform
)
336 if (!sm_customPlatforms
)
337 sm_customPlatforms
= new wxArrayInt
;
338 sm_customPlatforms
->Add(platform
);
341 void wxPlatform::ClearPlatforms()
343 wxDELETE(sm_customPlatforms
);
346 /// Function for testing current platform
348 bool wxPlatform::Is(int platform
)
351 if (platform
== wxOS_WINDOWS
)
355 if (platform
== wxOS_WINDOWS_CE
)
361 // FIXME: wxWinPocketPC and wxWinSmartPhone are unknown symbols
363 #if defined(__WXWINCE__) && defined(__POCKETPC__)
364 if (platform
== wxWinPocketPC
)
367 #if defined(__WXWINCE__) && defined(__SMARTPHONE__)
368 if (platform
== wxWinSmartPhone
)
375 if (platform
== wxPORT_GTK
)
379 if (platform
== wxPORT_MAC
)
383 if (platform
== wxPORT_X11
)
387 if (platform
== wxOS_UNIX
)
391 if (platform
== wxOS_OS2
)
395 if (platform
== wxPORT_PM
)
399 if (platform
== wxPORT_MAC
)
403 if (sm_customPlatforms
&& sm_customPlatforms
->Index(platform
) != wxNOT_FOUND
)
409 // ----------------------------------------------------------------------------
410 // network and user id functions
411 // ----------------------------------------------------------------------------
413 // Get Full RFC822 style email address
414 bool wxGetEmailAddress(wxChar
*address
, int maxSize
)
416 wxString email
= wxGetEmailAddress();
420 wxStrlcpy(address
, email
.t_str(), maxSize
);
425 wxString
wxGetEmailAddress()
429 wxString host
= wxGetFullHostName();
432 wxString user
= wxGetUserId();
435 email
<< user
<< wxT('@') << host
;
442 wxString
wxGetUserId()
444 static const int maxLoginLen
= 256; // FIXME arbitrary number
447 bool ok
= wxGetUserId(wxStringBuffer(buf
, maxLoginLen
), maxLoginLen
);
455 wxString
wxGetUserName()
457 static const int maxUserNameLen
= 1024; // FIXME arbitrary number
460 bool ok
= wxGetUserName(wxStringBuffer(buf
, maxUserNameLen
), maxUserNameLen
);
468 wxString
wxGetHostName()
470 static const size_t hostnameSize
= 257;
473 bool ok
= wxGetHostName(wxStringBuffer(buf
, hostnameSize
), hostnameSize
);
481 wxString
wxGetFullHostName()
483 static const size_t hostnameSize
= 257;
486 bool ok
= wxGetFullHostName(wxStringBuffer(buf
, hostnameSize
), hostnameSize
);
494 wxString
wxGetHomeDir()
504 wxString
wxGetCurrentDir()
511 ok
= getcwd(dir
.GetWriteBuf(len
+ 1), len
) != NULL
;
516 if ( errno
!= ERANGE
)
518 wxLogSysError(wxT("Failed to get current directory"));
520 return wxEmptyString
;
524 // buffer was too small, retry with a larger one
536 // ----------------------------------------------------------------------------
538 // ----------------------------------------------------------------------------
541 #if wxOSX_USE_COCOA_OR_CARBON
542 #include <crt_externs.h>
546 bool wxGetEnvMap(wxEnvVariableHashMap
*map
)
548 wxCHECK_MSG( map
, false, wxS("output pointer can't be NULL") );
550 #if defined(__VISUALC__)
551 // This variable only exists to force the CRT to fill the wide char array,
552 // it might only have it in narrow char version until now as we use main()
553 // (and not _wmain()) as our entry point.
554 static wxChar
* s_dummyEnvVar
= _tgetenv(wxT("TEMP"));
556 wxChar
**env
= _tenviron
;
558 // Now this routine wil give false for OpenVMS
559 // TODO : should we do something with logicals?
561 #elif defined(__DARWIN__)
562 #if wxOSX_USE_COCOA_OR_CARBON
563 // Under Mac shared libraries don't have access to the global environ
564 // variable so use this Mac-specific function instead as advised by
565 // environ(7) under Darwin
566 char ***penv
= _NSGetEnviron();
572 // todo translate NSProcessInfo environment into map
574 #else // non-MSVC non-Mac
575 // Not sure if other compilers have _tenviron so use the (more standard)
576 // ANSI version only for them.
578 // Both POSIX and Single UNIX Specification say that this variable must
579 // exist but not that it must be declared anywhere and, indeed, it's not
580 // declared in several common systems (some BSDs, Solaris with native CC)
581 // so we (re)declare it ourselves to deal with these cases. However we do
582 // not do this under MSW where there can be DLL-related complications, i.e.
583 // the variable might be DLL-imported or not. Luckily we don't have to
584 // worry about this as all MSW compilers do seem to define it in their
585 // standard headers anyhow so we can just rely on already having the
586 // correct declaration. And if this turns out to be wrong, we can always
587 // add a configure test checking whether it is declared later.
589 extern char **environ
;
590 #endif // !__WINDOWS__
592 char **env
= environ
;
601 const wxString
var(*env
);
603 name
= var
.BeforeFirst(wxS('='), &value
);
605 (*map
)[name
] = value
;
616 // ----------------------------------------------------------------------------
618 // ----------------------------------------------------------------------------
620 // wxDoExecuteWithCapture() helper: reads an entire stream into one array if
621 // the stream is non-NULL (it doesn't do anything if it's NULL).
623 // returns true if ok, false if error
625 static bool ReadAll(wxInputStream
*is
, wxArrayString
& output
)
630 // the stream could be already at EOF or in wxSTREAM_BROKEN_PIPE state
633 wxTextInputStream
tis(*is
);
637 wxString line
= tis
.ReadLine();
639 // check for EOF before other errors as it's not really an error
642 // add the last, possibly incomplete, line
648 // any other error is fatal
657 #endif // wxUSE_STREAMS
659 // this is a private function because it hasn't a clean interface: the first
660 // array is passed by reference, the second by pointer - instead we have 2
661 // public versions of wxExecute() below
662 static long wxDoExecuteWithCapture(const wxString
& command
,
663 wxArrayString
& output
,
664 wxArrayString
* error
,
666 const wxExecuteEnv
*env
)
668 // create a wxProcess which will capture the output
669 wxProcess
*process
= new wxProcess
;
672 long rc
= wxExecute(command
, wxEXEC_SYNC
| flags
, process
, env
);
675 // Notice that while -1 indicates an error exit code for us, a program
676 // exiting with this code could still have written something to its stdout
677 // and, especially, stderr, so we still need to read from them.
678 if ( !ReadAll(process
->GetInputStream(), output
) )
683 if ( !ReadAll(process
->GetErrorStream(), *error
) )
689 #endif // wxUSE_STREAMS/!wxUSE_STREAMS
696 long wxExecute(const wxString
& command
, wxArrayString
& output
, int flags
,
697 const wxExecuteEnv
*env
)
699 return wxDoExecuteWithCapture(command
, output
, NULL
, flags
, env
);
702 long wxExecute(const wxString
& command
,
703 wxArrayString
& output
,
704 wxArrayString
& error
,
706 const wxExecuteEnv
*env
)
708 return wxDoExecuteWithCapture(command
, output
, &error
, flags
, env
);
711 // ----------------------------------------------------------------------------
713 // ----------------------------------------------------------------------------
716 static int wxCurrentId
= 100;
720 // skip the part of IDs space that contains hard-coded values:
721 if (wxCurrentId
== wxID_LOWEST
)
722 wxCurrentId
= wxID_HIGHEST
+ 1;
724 return wxCurrentId
++;
728 wxGetCurrentId(void) { return wxCurrentId
; }
731 wxRegisterId (int id
)
733 if (id
>= wxCurrentId
)
734 wxCurrentId
= id
+ 1;
737 // ----------------------------------------------------------------------------
738 // wxQsort, adapted by RR to allow user_data
739 // ----------------------------------------------------------------------------
741 /* This file is part of the GNU C Library.
742 Written by Douglas C. Schmidt (schmidt@ics.uci.edu).
744 Douglas Schmidt kindly gave permission to relicence the
745 code under the wxWindows licence:
747 From: "Douglas C. Schmidt" <schmidt@dre.vanderbilt.edu>
748 To: Robert Roebling <robert.roebling@uni-ulm.de>
749 Subject: Re: qsort licence
750 Date: Mon, 23 Jul 2007 03:44:25 -0500
751 Sender: schmidt@dre.vanderbilt.edu
752 Message-Id: <20070723084426.64F511000A8@tango.dre.vanderbilt.edu>
756 > [...] I'm asking if you'd be willing to relicence your code
757 > under the wxWindows licence. [...]
759 That's fine with me [...]
766 /* Byte-wise swap two items of size SIZE. */
767 #define SWAP(a, b, size) \
770 register size_t __size = (size); \
771 register char *__a = (a), *__b = (b); \
777 } while (--__size > 0); \
780 /* Discontinue quicksort algorithm when partition gets below this size.
781 This particular magic number was chosen to work best on a Sun 4/260. */
784 /* Stack node declarations used to store unfulfilled partition obligations. */
791 /* The next 4 #defines implement a very fast in-line stack abstraction. */
792 #define STACK_SIZE (8 * sizeof(unsigned long int))
793 #define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top))
794 #define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi)))
795 #define STACK_NOT_EMPTY (stack < top)
798 /* Order size using quicksort. This implementation incorporates
799 four optimizations discussed in Sedgewick:
801 1. Non-recursive, using an explicit stack of pointer that store the
802 next array partition to sort. To save time, this maximum amount
803 of space required to store an array of MAX_INT is allocated on the
804 stack. Assuming a 32-bit integer, this needs only 32 *
805 sizeof(stack_node) == 136 bits. Pretty cheap, actually.
807 2. Chose the pivot element using a median-of-three decision tree.
808 This reduces the probability of selecting a bad pivot value and
809 eliminates certain extraneous comparisons.
811 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving
812 insertion sort to order the MAX_THRESH items within each partition.
813 This is a big win, since insertion sort is faster for small, mostly
814 sorted array segments.
816 4. The larger of the two sub-partitions is always pushed onto the
817 stack first, with the algorithm then concentrating on the
818 smaller partition. This *guarantees* no more than log (n)
819 stack size is needed (actually O(1) in this case)! */
821 void wxQsort(void* pbase
, size_t total_elems
,
822 size_t size
, wxSortCallback cmp
, const void* user_data
)
824 register char *base_ptr
= (char *) pbase
;
825 const size_t max_thresh
= MAX_THRESH
* size
;
827 if (total_elems
== 0)
828 /* Avoid lossage with unsigned arithmetic below. */
831 if (total_elems
> MAX_THRESH
)
834 char *hi
= &lo
[size
* (total_elems
- 1)];
835 stack_node stack
[STACK_SIZE
];
836 stack_node
*top
= stack
;
840 while (STACK_NOT_EMPTY
)
845 /* Select median value from among LO, MID, and HI. Rearrange
846 LO and HI so the three values are sorted. This lowers the
847 probability of picking a pathological pivot value and
848 skips a comparison for both the LEFT_PTR and RIGHT_PTR. */
850 char *mid
= lo
+ size
* ((hi
- lo
) / size
>> 1);
852 if ((*cmp
) ((void *) mid
, (void *) lo
, user_data
) < 0)
853 SWAP (mid
, lo
, size
);
854 if ((*cmp
) ((void *) hi
, (void *) mid
, user_data
) < 0)
855 SWAP (mid
, hi
, size
);
858 if ((*cmp
) ((void *) mid
, (void *) lo
, user_data
) < 0)
859 SWAP (mid
, lo
, size
);
861 left_ptr
= lo
+ size
;
862 right_ptr
= hi
- size
;
864 /* Here's the famous ``collapse the walls'' section of quicksort.
865 Gotta like those tight inner loops! They are the main reason
866 that this algorithm runs much faster than others. */
869 while ((*cmp
) ((void *) left_ptr
, (void *) mid
, user_data
) < 0)
872 while ((*cmp
) ((void *) mid
, (void *) right_ptr
, user_data
) < 0)
875 if (left_ptr
< right_ptr
)
877 SWAP (left_ptr
, right_ptr
, size
);
880 else if (mid
== right_ptr
)
885 else if (left_ptr
== right_ptr
)
892 while (left_ptr
<= right_ptr
);
894 /* Set up pointers for next iteration. First determine whether
895 left and right partitions are below the threshold size. If so,
896 ignore one or both. Otherwise, push the larger partition's
897 bounds on the stack and continue sorting the smaller one. */
899 if ((size_t) (right_ptr
- lo
) <= max_thresh
)
901 if ((size_t) (hi
- left_ptr
) <= max_thresh
)
902 /* Ignore both small partitions. */
905 /* Ignore small left partition. */
908 else if ((size_t) (hi
- left_ptr
) <= max_thresh
)
909 /* Ignore small right partition. */
911 else if ((right_ptr
- lo
) > (hi
- left_ptr
))
913 /* Push larger left partition indices. */
914 PUSH (lo
, right_ptr
);
919 /* Push larger right partition indices. */
926 /* Once the BASE_PTR array is partially sorted by quicksort the rest
927 is completely sorted using insertion sort, since this is efficient
928 for partitions below MAX_THRESH size. BASE_PTR points to the beginning
929 of the array to sort, and END_PTR points at the very last element in
930 the array (*not* one beyond it!). */
933 char *const end_ptr
= &base_ptr
[size
* (total_elems
- 1)];
934 char *tmp_ptr
= base_ptr
;
935 char *thresh
= base_ptr
+ max_thresh
;
936 if ( thresh
> end_ptr
)
938 register char *run_ptr
;
940 /* Find smallest element in first threshold and place it at the
941 array's beginning. This is the smallest array element,
942 and the operation speeds up insertion sort's inner loop. */
944 for (run_ptr
= tmp_ptr
+ size
; run_ptr
<= thresh
; run_ptr
+= size
)
945 if ((*cmp
) ((void *) run_ptr
, (void *) tmp_ptr
, user_data
) < 0)
948 if (tmp_ptr
!= base_ptr
)
949 SWAP (tmp_ptr
, base_ptr
, size
);
951 /* Insertion sort, running from left-hand-side up to right-hand-side. */
953 run_ptr
= base_ptr
+ size
;
954 while ((run_ptr
+= size
) <= end_ptr
)
956 tmp_ptr
= run_ptr
- size
;
957 while ((*cmp
) ((void *) run_ptr
, (void *) tmp_ptr
, user_data
) < 0)
961 if (tmp_ptr
!= run_ptr
)
965 trav
= run_ptr
+ size
;
966 while (--trav
>= run_ptr
)
971 for (hi
= lo
= trav
; (lo
-= size
) >= tmp_ptr
; hi
= lo
)
984 // ============================================================================
985 // GUI-only functions from now on
986 // ============================================================================
990 // this function is only really implemented for X11-based ports, including GTK1
991 // (GTK2 sets detectable auto-repeat automatically anyhow)
992 #if !(defined(__WXX11__) || defined(__WXMOTIF__) || \
993 (defined(__WXGTK__) && !defined(__WXGTK20__)))
994 bool wxSetDetectableAutoRepeat( bool WXUNUSED(flag
) )
998 #endif // !X11-based port
1000 // ----------------------------------------------------------------------------
1001 // Launch default browser
1002 // ----------------------------------------------------------------------------
1004 #if defined(__WINDOWS__)
1006 // implemented in a port-specific utils source file:
1007 bool wxDoLaunchDefaultBrowser(const wxString
& url
, const wxString
& scheme
, int flags
);
1009 #elif defined(__WXX11__) || defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXCOCOA__) || \
1010 (defined(__WXOSX__) )
1012 // implemented in a port-specific utils source file:
1013 bool wxDoLaunchDefaultBrowser(const wxString
& url
, int flags
);
1017 // a "generic" implementation:
1018 bool wxDoLaunchDefaultBrowser(const wxString
& url
, int flags
)
1020 // on other platforms try to use mime types or wxExecute...
1026 wxFileType
*ft
= wxTheMimeTypesManager
->GetFileTypeFromExtension(wxT("html"));
1030 ft
->GetMimeType(&mt
);
1032 ok
= ft
->GetOpenCommand(&cmd
, wxFileType::MessageParameters(url
));
1035 #endif // wxUSE_MIMETYPE
1037 if ( !ok
|| cmd
.empty() )
1039 // fallback to checking for the BROWSER environment variable
1040 if ( !wxGetEnv(wxT("BROWSER"), &cmd
) || cmd
.empty() )
1041 cmd
<< wxT(' ') << url
;
1044 ok
= ( !cmd
.empty() && wxExecute(cmd
) );
1048 // no file type for HTML extension
1049 wxLogError(_("No default application configured for HTML files."));
1055 static bool DoLaunchDefaultBrowserHelper(const wxString
& urlOrig
, int flags
)
1057 // NOTE: we don't have to care about the wxBROWSER_NOBUSYCURSOR flag
1058 // as it was already handled by wxLaunchDefaultBrowser
1062 wxString
url(urlOrig
), scheme
;
1065 // this check is useful to avoid that wxURI recognizes as scheme parts of
1066 // the filename, in case urlOrig is a local filename
1067 // (e.g. "C:\\test.txt" when parsed by wxURI reports a scheme == "C")
1068 bool hasValidScheme
= uri
.HasScheme() && uri
.GetScheme().length() > 1;
1070 #if defined(__WINDOWS__)
1072 // NOTE: when testing wxMSW's wxLaunchDefaultBrowser all possible forms
1073 // of the URL/flags should be tested; e.g.:
1075 // for (int i=0; i<2; i++)
1077 // // test arguments without a valid URL scheme:
1078 // wxLaunchDefaultBrowser("C:\\test.txt", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1079 // wxLaunchDefaultBrowser("wxwidgets.org", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1081 // // test arguments with different valid schemes:
1082 // wxLaunchDefaultBrowser("file:/C%3A/test.txt", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1083 // wxLaunchDefaultBrowser("http://wxwidgets.org", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1084 // wxLaunchDefaultBrowser("mailto:user@host.org", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1086 // (assuming you have a C:\test.txt file)
1088 if ( !hasValidScheme
)
1090 if (wxFileExists(urlOrig
) || wxDirExists(urlOrig
))
1093 // do not prepend the file scheme to the URL as ShellExecuteEx() doesn't like it
1097 url
.Prepend(wxS("http://"));
1101 else if ( hasValidScheme
)
1103 scheme
= uri
.GetScheme();
1105 if ( uri
.GetScheme() == "file" )
1107 // TODO: extract URLToFileName() to some always compiled in
1109 #if wxUSE_FILESYSTEM
1110 // ShellExecuteEx() doesn't like the "file" scheme when opening local files;
1112 url
= wxFileSystem::URLToFileName(url
).GetFullPath();
1113 #endif // wxUSE_FILESYSTEM
1117 if (wxDoLaunchDefaultBrowser(url
, scheme
, flags
))
1119 //else: call wxLogSysError
1121 if ( !hasValidScheme
)
1123 // set the scheme of url to "http" or "file" if it does not have one
1124 if (wxFileExists(urlOrig
) || wxDirExists(urlOrig
))
1125 url
.Prepend(wxS("file://"));
1127 url
.Prepend(wxS("http://"));
1130 if (wxDoLaunchDefaultBrowser(url
, flags
))
1132 //else: call wxLogSysError
1135 wxLogSysError(_("Failed to open URL \"%s\" in default browser."),
1141 bool wxLaunchDefaultBrowser(const wxString
& url
, int flags
)
1143 // NOTE: as documented, "url" may be both a real well-formed URL
1144 // and a local file name
1146 if ( flags
& wxBROWSER_NOBUSYCURSOR
)
1147 return DoLaunchDefaultBrowserHelper(url
, flags
);
1150 return DoLaunchDefaultBrowserHelper(url
, flags
);
1153 // ----------------------------------------------------------------------------
1154 // Menu accelerators related functions
1155 // ----------------------------------------------------------------------------
1157 #if WXWIN_COMPATIBILITY_2_6
1158 wxChar
*wxStripMenuCodes(const wxChar
*in
, wxChar
*out
)
1161 wxString s
= wxMenuItem::GetLabelText(in
);
1164 wxString s
= wxStripMenuCodes(str
);
1165 #endif // wxUSE_MENUS
1168 // go smash their buffer if it's not big enough - I love char * params
1169 memcpy(out
, s
.c_str(), s
.length() * sizeof(wxChar
));
1173 out
= new wxChar
[s
.length() + 1];
1174 wxStrcpy(out
, s
.c_str());
1181 wxString
wxStripMenuCodes(const wxString
& in
, int flags
)
1183 wxASSERT_MSG( flags
, wxT("this is useless to call without any flags") );
1187 size_t len
= in
.length();
1190 for ( wxString::const_iterator it
= in
.begin(); it
!= in
.end(); ++it
)
1193 if ( (flags
& wxStrip_Mnemonics
) && ch
== wxT('&') )
1195 // skip it, it is used to introduce the accel char (or to quote
1196 // itself in which case it should still be skipped): note that it
1197 // can't be the last character of the string
1198 if ( ++it
== in
.end() )
1200 wxLogDebug(wxT("Invalid menu string '%s'"), in
.c_str());
1204 // use the next char instead
1208 else if ( (flags
& wxStrip_Accel
) && ch
== wxT('\t') )
1210 // everything after TAB is accel string, exit the loop
1220 // ----------------------------------------------------------------------------
1221 // Window search functions
1222 // ----------------------------------------------------------------------------
1225 * If parent is non-NULL, look through children for a label or title
1226 * matching the specified string. If NULL, look through all top-level windows.
1231 wxFindWindowByLabel (const wxString
& title
, wxWindow
* parent
)
1233 return wxWindow::FindWindowByLabel( title
, parent
);
1238 * If parent is non-NULL, look through children for a name
1239 * matching the specified string. If NULL, look through all top-level windows.
1244 wxFindWindowByName (const wxString
& name
, wxWindow
* parent
)
1246 return wxWindow::FindWindowByName( name
, parent
);
1249 // Returns menu item id or wxNOT_FOUND if none.
1251 wxFindMenuItemId(wxFrame
*frame
,
1252 const wxString
& menuString
,
1253 const wxString
& itemString
)
1256 wxMenuBar
*menuBar
= frame
->GetMenuBar ();
1258 return menuBar
->FindMenuItem (menuString
, itemString
);
1259 #else // !wxUSE_MENUS
1261 wxUnusedVar(menuString
);
1262 wxUnusedVar(itemString
);
1263 #endif // wxUSE_MENUS/!wxUSE_MENUS
1268 // Try to find the deepest child that contains 'pt'.
1269 // We go backwards, to try to allow for controls that are spacially
1270 // within other controls, but are still siblings (e.g. buttons within
1271 // static boxes). Static boxes are likely to be created _before_ controls
1272 // that sit inside them.
1273 wxWindow
* wxFindWindowAtPoint(wxWindow
* win
, const wxPoint
& pt
)
1275 if (!win
->IsShown())
1278 // Hack for wxNotebook case: at least in wxGTK, all pages
1279 // claim to be shown, so we must only deal with the selected one.
1281 if (wxDynamicCast(win
, wxNotebook
))
1283 wxNotebook
* nb
= (wxNotebook
*) win
;
1284 int sel
= nb
->GetSelection();
1287 wxWindow
* child
= nb
->GetPage(sel
);
1288 wxWindow
* foundWin
= wxFindWindowAtPoint(child
, pt
);
1295 wxWindowList::compatibility_iterator node
= win
->GetChildren().GetLast();
1298 wxWindow
* child
= node
->GetData();
1299 wxWindow
* foundWin
= wxFindWindowAtPoint(child
, pt
);
1302 node
= node
->GetPrevious();
1305 wxPoint pos
= win
->GetPosition();
1306 wxSize sz
= win
->GetSize();
1307 if ( !win
->IsTopLevel() && win
->GetParent() )
1309 pos
= win
->GetParent()->ClientToScreen(pos
);
1312 wxRect
rect(pos
, sz
);
1313 if (rect
.Contains(pt
))
1319 wxWindow
* wxGenericFindWindowAtPoint(const wxPoint
& pt
)
1321 // Go backwards through the list since windows
1322 // on top are likely to have been appended most
1324 wxWindowList::compatibility_iterator node
= wxTopLevelWindows
.GetLast();
1327 wxWindow
* win
= node
->GetData();
1328 wxWindow
* found
= wxFindWindowAtPoint(win
, pt
);
1331 node
= node
->GetPrevious();
1336 // ----------------------------------------------------------------------------
1338 // ----------------------------------------------------------------------------
1341 * N.B. these convenience functions must be separate from msgdlgg.cpp, textdlgg.cpp
1342 * since otherwise the generic code may be pulled in unnecessarily.
1347 int wxMessageBox(const wxString
& message
, const wxString
& caption
, long style
,
1348 wxWindow
*parent
, int WXUNUSED(x
), int WXUNUSED(y
) )
1350 // add the appropriate icon unless this was explicitly disabled by use of
1352 if ( !(style
& wxICON_NONE
) && !(style
& wxICON_MASK
) )
1354 style
|= style
& wxYES
? wxICON_QUESTION
: wxICON_INFORMATION
;
1357 wxMessageDialog
dialog(parent
, message
, caption
, style
);
1359 int ans
= dialog
.ShowModal();
1374 wxFAIL_MSG( wxT("unexpected return code from wxMessageDialog") );
1379 wxVersionInfo
wxGetLibraryVersionInfo()
1381 // don't translate these strings, they're for diagnostics purposes only
1383 msg
.Printf(wxS("wxWidgets Library (%s port)\n")
1384 wxS("Version %d.%d.%d (Unicode: %s, debug level: %d),\n")
1385 wxS("compiled at %s %s\n\n")
1386 wxS("Runtime version of toolkit used is %d.%d.\n"),
1387 wxPlatformInfo::Get().GetPortIdName(),
1391 #if wxUSE_UNICODE_UTF8
1401 wxPlatformInfo::Get().GetToolkitMajorVersion(),
1402 wxPlatformInfo::Get().GetToolkitMinorVersion()
1406 msg
+= wxString::Format("Compile-time GTK+ version is %d.%d.%d.\n",
1412 return wxVersionInfo(wxS("wxWidgets"),
1417 wxS("Copyright (c) 1995-2011 wxWidgets team"));
1420 void wxInfoMessageBox(wxWindow
* parent
)
1422 wxVersionInfo info
= wxGetLibraryVersionInfo();
1423 wxString msg
= info
.ToString();
1425 msg
<< wxS("\n") << info
.GetCopyright();
1427 wxMessageBox(msg
, wxT("wxWidgets information"),
1428 wxICON_INFORMATION
| wxOK
,
1432 #endif // wxUSE_MSGDLG
1436 wxString
wxGetTextFromUser(const wxString
& message
, const wxString
& caption
,
1437 const wxString
& defaultValue
, wxWindow
*parent
,
1438 wxCoord x
, wxCoord y
, bool centre
)
1441 long style
= wxTextEntryDialogStyle
;
1448 wxTextEntryDialog
dialog(parent
, message
, caption
, defaultValue
, style
, wxPoint(x
, y
));
1450 if (dialog
.ShowModal() == wxID_OK
)
1452 str
= dialog
.GetValue();
1458 wxString
wxGetPasswordFromUser(const wxString
& message
,
1459 const wxString
& caption
,
1460 const wxString
& defaultValue
,
1462 wxCoord x
, wxCoord y
, bool centre
)
1465 long style
= wxTextEntryDialogStyle
;
1472 wxPasswordEntryDialog
dialog(parent
, message
, caption
, defaultValue
,
1473 style
, wxPoint(x
, y
));
1474 if ( dialog
.ShowModal() == wxID_OK
)
1476 str
= dialog
.GetValue();
1482 #endif // wxUSE_TEXTDLG
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 #if defined(__WXOSX__) && wxOSX_USE_COCOA
1497 // defined in evtloop.mm
1501 wxWindowDisabler::wxWindowDisabler(bool disable
)
1503 m_disabled
= disable
;
1508 wxWindowDisabler::wxWindowDisabler(wxWindow
*winToSkip
)
1511 DoDisable(winToSkip
);
1514 void wxWindowDisabler::DoDisable(wxWindow
*winToSkip
)
1516 // remember the top level windows which were already disabled, so that we
1517 // don't reenable them later
1518 m_winDisabled
= NULL
;
1520 wxWindowList::compatibility_iterator node
;
1521 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1523 wxWindow
*winTop
= node
->GetData();
1524 if ( winTop
== winToSkip
)
1527 // we don't need to disable the hidden or already disabled windows
1528 if ( winTop
->IsEnabled() && winTop
->IsShown() )
1534 if ( !m_winDisabled
)
1536 m_winDisabled
= new wxWindowList
;
1539 m_winDisabled
->Append(winTop
);
1544 wxWindowDisabler::~wxWindowDisabler()
1549 wxWindowList::compatibility_iterator node
;
1550 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1552 wxWindow
*winTop
= node
->GetData();
1553 if ( !m_winDisabled
|| !m_winDisabled
->Find(winTop
) )
1557 //else: had been already disabled, don't reenable
1560 delete m_winDisabled
;
1565 // Yield to other apps/messages and disable user input to all windows except
1567 bool wxSafeYield(wxWindow
*win
, bool onlyIfNeeded
)
1569 wxWindowDisabler
wd(win
);
1573 rc
= wxYieldIfNeeded();
1580 // ----------------------------------------------------------------------------
1581 // wxApp::Yield() wrappers for backwards compatibility
1582 // ----------------------------------------------------------------------------
1586 return wxTheApp
&& wxTheApp
->Yield();
1589 bool wxYieldIfNeeded()
1591 return wxTheApp
&& wxTheApp
->Yield(true);