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"
82 #include "wx/msw/wince/time.h"
86 #include "wx/osx/private.h"
89 #if !defined(__WXWINCE__)
90 #include <sys/types.h>
94 #if defined(__WINDOWS__)
95 #include "wx/msw/private.h"
96 #include "wx/filesys.h"
99 #if wxUSE_GUI && defined(__WXGTK__)
100 #include <gtk/gtk.h> // for GTK_XXX_VERSION constants
105 // ============================================================================
107 // ============================================================================
109 // Array used in DecToHex conversion routine.
110 static const wxChar hexArray
[] = wxT("0123456789ABCDEF");
112 // Convert 2-digit hex number to decimal
113 int wxHexToDec(const wxString
& str
)
116 buf
[0] = str
.GetChar(0);
117 buf
[1] = str
.GetChar(1);
118 return wxHexToDec((const char*) buf
);
121 // Convert decimal integer to 2-character hex string
122 void wxDecToHex(int dec
, wxChar
*buf
)
124 int firstDigit
= (int)(dec
/16.0);
125 int secondDigit
= (int)(dec
- (firstDigit
*16.0));
126 buf
[0] = hexArray
[firstDigit
];
127 buf
[1] = hexArray
[secondDigit
];
131 // Convert decimal integer to 2 characters
132 void wxDecToHex(int dec
, char* ch1
, char* ch2
)
134 int firstDigit
= (int)(dec
/16.0);
135 int secondDigit
= (int)(dec
- (firstDigit
*16.0));
136 (*ch1
) = (char) hexArray
[firstDigit
];
137 (*ch2
) = (char) hexArray
[secondDigit
];
140 // Convert decimal integer to 2-character hex string
141 wxString
wxDecToHex(int dec
)
144 wxDecToHex(dec
, buf
);
145 return wxString(buf
);
148 // ----------------------------------------------------------------------------
150 // ----------------------------------------------------------------------------
152 // Return the current date/time
157 wxDateTime now
= wxDateTime::Now();
160 return wxEmptyString
;
163 time_t now
= time(NULL
);
164 char *date
= ctime(&now
);
166 return wxString::FromAscii(date
);
170 #if WXWIN_COMPATIBILITY_2_8
171 void wxUsleep(unsigned long milliseconds
)
173 wxMilliSleep(milliseconds
);
177 const wxChar
*wxGetInstallPrefix()
181 if ( wxGetEnv(wxT("WXPREFIX"), &prefix
) )
182 return prefix
.c_str();
184 #ifdef wxINSTALL_PREFIX
185 return wxT(wxINSTALL_PREFIX
);
187 return wxEmptyString
;
191 wxString
wxGetDataDir()
193 wxString dir
= wxGetInstallPrefix();
194 dir
<< wxFILE_SEP_PATH
<< wxT("share") << wxFILE_SEP_PATH
<< wxT("wx");
198 bool wxIsPlatformLittleEndian()
200 // Are we little or big endian? This method is from Harbison & Steele.
204 char c
[sizeof(long)];
212 // ----------------------------------------------------------------------------
214 // ----------------------------------------------------------------------------
217 * Class to make it easier to specify platform-dependent values
220 wxArrayInt
* wxPlatform::sm_customPlatforms
= NULL
;
222 void wxPlatform::Copy(const wxPlatform
& platform
)
224 m_longValue
= platform
.m_longValue
;
225 m_doubleValue
= platform
.m_doubleValue
;
226 m_stringValue
= platform
.m_stringValue
;
229 wxPlatform
wxPlatform::If(int platform
, long value
)
232 return wxPlatform(value
);
237 wxPlatform
wxPlatform::IfNot(int platform
, long value
)
240 return wxPlatform(value
);
245 wxPlatform
& wxPlatform::ElseIf(int platform
, long value
)
252 wxPlatform
& wxPlatform::ElseIfNot(int platform
, long value
)
259 wxPlatform
wxPlatform::If(int platform
, double value
)
262 return wxPlatform(value
);
267 wxPlatform
wxPlatform::IfNot(int platform
, double value
)
270 return wxPlatform(value
);
275 wxPlatform
& wxPlatform::ElseIf(int platform
, double value
)
278 m_doubleValue
= value
;
282 wxPlatform
& wxPlatform::ElseIfNot(int platform
, double value
)
285 m_doubleValue
= value
;
289 wxPlatform
wxPlatform::If(int platform
, const wxString
& value
)
292 return wxPlatform(value
);
297 wxPlatform
wxPlatform::IfNot(int platform
, const wxString
& value
)
300 return wxPlatform(value
);
305 wxPlatform
& wxPlatform::ElseIf(int platform
, const wxString
& value
)
308 m_stringValue
= value
;
312 wxPlatform
& wxPlatform::ElseIfNot(int platform
, const wxString
& value
)
315 m_stringValue
= value
;
319 wxPlatform
& wxPlatform::Else(long value
)
325 wxPlatform
& wxPlatform::Else(double value
)
327 m_doubleValue
= value
;
331 wxPlatform
& wxPlatform::Else(const wxString
& value
)
333 m_stringValue
= value
;
337 void wxPlatform::AddPlatform(int platform
)
339 if (!sm_customPlatforms
)
340 sm_customPlatforms
= new wxArrayInt
;
341 sm_customPlatforms
->Add(platform
);
344 void wxPlatform::ClearPlatforms()
346 wxDELETE(sm_customPlatforms
);
349 /// Function for testing current platform
351 bool wxPlatform::Is(int platform
)
354 if (platform
== wxOS_WINDOWS
)
358 if (platform
== wxOS_WINDOWS_CE
)
364 // FIXME: wxWinPocketPC and wxWinSmartPhone are unknown symbols
366 #if defined(__WXWINCE__) && defined(__POCKETPC__)
367 if (platform
== wxWinPocketPC
)
370 #if defined(__WXWINCE__) && defined(__SMARTPHONE__)
371 if (platform
== wxWinSmartPhone
)
378 if (platform
== wxPORT_GTK
)
382 if (platform
== wxPORT_MAC
)
386 if (platform
== wxPORT_X11
)
390 if (platform
== wxOS_UNIX
)
394 if (platform
== wxOS_OS2
)
398 if (platform
== wxPORT_PM
)
402 if (platform
== wxPORT_MAC
)
406 if (sm_customPlatforms
&& sm_customPlatforms
->Index(platform
) != wxNOT_FOUND
)
412 // ----------------------------------------------------------------------------
413 // network and user id functions
414 // ----------------------------------------------------------------------------
416 // Get Full RFC822 style email address
417 bool wxGetEmailAddress(wxChar
*address
, int maxSize
)
419 wxString email
= wxGetEmailAddress();
423 wxStrlcpy(address
, email
.t_str(), maxSize
);
428 wxString
wxGetEmailAddress()
432 wxString host
= wxGetFullHostName();
435 wxString user
= wxGetUserId();
438 email
<< user
<< wxT('@') << host
;
445 wxString
wxGetUserId()
447 static const int maxLoginLen
= 256; // FIXME arbitrary number
450 bool ok
= wxGetUserId(wxStringBuffer(buf
, maxLoginLen
), maxLoginLen
);
458 wxString
wxGetUserName()
460 static const int maxUserNameLen
= 1024; // FIXME arbitrary number
463 bool ok
= wxGetUserName(wxStringBuffer(buf
, maxUserNameLen
), maxUserNameLen
);
471 wxString
wxGetHostName()
473 static const size_t hostnameSize
= 257;
476 bool ok
= wxGetHostName(wxStringBuffer(buf
, hostnameSize
), hostnameSize
);
484 wxString
wxGetFullHostName()
486 static const size_t hostnameSize
= 257;
489 bool ok
= wxGetFullHostName(wxStringBuffer(buf
, hostnameSize
), hostnameSize
);
497 wxString
wxGetHomeDir()
507 wxString
wxGetCurrentDir()
514 ok
= getcwd(dir
.GetWriteBuf(len
+ 1), len
) != NULL
;
519 if ( errno
!= ERANGE
)
521 wxLogSysError(wxT("Failed to get current directory"));
523 return wxEmptyString
;
527 // buffer was too small, retry with a larger one
539 // ----------------------------------------------------------------------------
541 // ----------------------------------------------------------------------------
544 #if wxOSX_USE_COCOA_OR_CARBON
545 #include <crt_externs.h>
549 bool wxGetEnvMap(wxEnvVariableHashMap
*map
)
551 wxCHECK_MSG( map
, false, wxS("output pointer can't be NULL") );
553 #if defined(__VISUALC__)
554 // This variable only exists to force the CRT to fill the wide char array,
555 // it might only have it in narrow char version until now as we use main()
556 // (and not _wmain()) as our entry point.
557 static wxChar
* s_dummyEnvVar
= _tgetenv(wxT("TEMP"));
559 wxChar
**env
= _tenviron
;
561 // Now this routine wil give false for OpenVMS
562 // TODO : should we do something with logicals?
564 #elif defined(__DARWIN__)
565 #if wxOSX_USE_COCOA_OR_CARBON
566 // Under Mac shared libraries don't have access to the global environ
567 // variable so use this Mac-specific function instead as advised by
568 // environ(7) under Darwin
569 char ***penv
= _NSGetEnviron();
575 // todo translate NSProcessInfo environment into map
577 #else // non-MSVC non-Mac
578 // Not sure if other compilers have _tenviron so use the (more standard)
579 // ANSI version only for them.
581 // Both POSIX and Single UNIX Specification say that this variable must
582 // exist but not that it must be declared anywhere and, indeed, it's not
583 // declared in several common systems (some BSDs, Solaris with native CC)
584 // so we (re)declare it ourselves to deal with these cases. However we do
585 // not do this under MSW where there can be DLL-related complications, i.e.
586 // the variable might be DLL-imported or not. Luckily we don't have to
587 // worry about this as all MSW compilers do seem to define it in their
588 // standard headers anyhow so we can just rely on already having the
589 // correct declaration. And if this turns out to be wrong, we can always
590 // add a configure test checking whether it is declared later.
592 extern char **environ
;
593 #endif // !__WINDOWS__
595 char **env
= environ
;
604 const wxString
var(*env
);
606 name
= var
.BeforeFirst(wxS('='), &value
);
608 (*map
)[name
] = value
;
619 // ----------------------------------------------------------------------------
621 // ----------------------------------------------------------------------------
623 // wxDoExecuteWithCapture() helper: reads an entire stream into one array
625 // returns true if ok, false if error
627 static bool ReadAll(wxInputStream
*is
, wxArrayString
& output
)
629 wxCHECK_MSG( is
, false, wxT("NULL stream in wxExecute()?") );
631 // the stream could be already at EOF or in wxSTREAM_BROKEN_PIPE state
634 wxTextInputStream
tis(*is
);
638 wxString line
= tis
.ReadLine();
640 // check for EOF before other errors as it's not really an error
643 // add the last, possibly incomplete, line
649 // any other error is fatal
658 #endif // wxUSE_STREAMS
660 // this is a private function because it hasn't a clean interface: the first
661 // array is passed by reference, the second by pointer - instead we have 2
662 // public versions of wxExecute() below
663 static long wxDoExecuteWithCapture(const wxString
& command
,
664 wxArrayString
& output
,
665 wxArrayString
* error
,
667 const wxExecuteEnv
*env
)
669 // create a wxProcess which will capture the output
670 wxProcess
*process
= new wxProcess
;
673 long rc
= wxExecute(command
, wxEXEC_SYNC
| flags
, process
, env
);
678 if ( !ReadAll(process
->GetInputStream(), output
) )
683 if ( !ReadAll(process
->GetErrorStream(), *error
) )
691 #endif // wxUSE_STREAMS/!wxUSE_STREAMS
698 long wxExecute(const wxString
& command
, wxArrayString
& output
, int flags
,
699 const wxExecuteEnv
*env
)
701 return wxDoExecuteWithCapture(command
, output
, NULL
, flags
, env
);
704 long wxExecute(const wxString
& command
,
705 wxArrayString
& output
,
706 wxArrayString
& error
,
708 const wxExecuteEnv
*env
)
710 return wxDoExecuteWithCapture(command
, output
, &error
, flags
, env
);
713 // ----------------------------------------------------------------------------
715 // ----------------------------------------------------------------------------
718 static long wxCurrentId
= 100;
722 // skip the part of IDs space that contains hard-coded values:
723 if (wxCurrentId
== wxID_LOWEST
)
724 wxCurrentId
= wxID_HIGHEST
+ 1;
726 return wxCurrentId
++;
730 wxGetCurrentId(void) { return wxCurrentId
; }
733 wxRegisterId (long id
)
735 if (id
>= wxCurrentId
)
736 wxCurrentId
= id
+ 1;
739 // ----------------------------------------------------------------------------
740 // wxQsort, adapted by RR to allow user_data
741 // ----------------------------------------------------------------------------
743 /* This file is part of the GNU C Library.
744 Written by Douglas C. Schmidt (schmidt@ics.uci.edu).
746 Douglas Schmidt kindly gave permission to relicence the
747 code under the wxWindows licence:
749 From: "Douglas C. Schmidt" <schmidt@dre.vanderbilt.edu>
750 To: Robert Roebling <robert.roebling@uni-ulm.de>
751 Subject: Re: qsort licence
752 Date: Mon, 23 Jul 2007 03:44:25 -0500
753 Sender: schmidt@dre.vanderbilt.edu
754 Message-Id: <20070723084426.64F511000A8@tango.dre.vanderbilt.edu>
758 > [...] I'm asking if you'd be willing to relicence your code
759 > under the wxWindows licence. [...]
761 That's fine with me [...]
768 /* Byte-wise swap two items of size SIZE. */
769 #define SWAP(a, b, size) \
772 register size_t __size = (size); \
773 register char *__a = (a), *__b = (b); \
779 } while (--__size > 0); \
782 /* Discontinue quicksort algorithm when partition gets below this size.
783 This particular magic number was chosen to work best on a Sun 4/260. */
786 /* Stack node declarations used to store unfulfilled partition obligations. */
793 /* The next 4 #defines implement a very fast in-line stack abstraction. */
794 #define STACK_SIZE (8 * sizeof(unsigned long int))
795 #define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top))
796 #define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi)))
797 #define STACK_NOT_EMPTY (stack < top)
800 /* Order size using quicksort. This implementation incorporates
801 four optimizations discussed in Sedgewick:
803 1. Non-recursive, using an explicit stack of pointer that store the
804 next array partition to sort. To save time, this maximum amount
805 of space required to store an array of MAX_INT is allocated on the
806 stack. Assuming a 32-bit integer, this needs only 32 *
807 sizeof(stack_node) == 136 bits. Pretty cheap, actually.
809 2. Chose the pivot element using a median-of-three decision tree.
810 This reduces the probability of selecting a bad pivot value and
811 eliminates certain extraneous comparisons.
813 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving
814 insertion sort to order the MAX_THRESH items within each partition.
815 This is a big win, since insertion sort is faster for small, mostly
816 sorted array segments.
818 4. The larger of the two sub-partitions is always pushed onto the
819 stack first, with the algorithm then concentrating on the
820 smaller partition. This *guarantees* no more than log (n)
821 stack size is needed (actually O(1) in this case)! */
823 void wxQsort(void* pbase
, size_t total_elems
,
824 size_t size
, wxSortCallback cmp
, const void* user_data
)
826 register char *base_ptr
= (char *) pbase
;
827 const size_t max_thresh
= MAX_THRESH
* size
;
829 if (total_elems
== 0)
830 /* Avoid lossage with unsigned arithmetic below. */
833 if (total_elems
> MAX_THRESH
)
836 char *hi
= &lo
[size
* (total_elems
- 1)];
837 stack_node stack
[STACK_SIZE
];
838 stack_node
*top
= stack
;
842 while (STACK_NOT_EMPTY
)
847 /* Select median value from among LO, MID, and HI. Rearrange
848 LO and HI so the three values are sorted. This lowers the
849 probability of picking a pathological pivot value and
850 skips a comparison for both the LEFT_PTR and RIGHT_PTR. */
852 char *mid
= lo
+ size
* ((hi
- lo
) / size
>> 1);
854 if ((*cmp
) ((void *) mid
, (void *) lo
, user_data
) < 0)
855 SWAP (mid
, lo
, size
);
856 if ((*cmp
) ((void *) hi
, (void *) mid
, user_data
) < 0)
857 SWAP (mid
, hi
, size
);
860 if ((*cmp
) ((void *) mid
, (void *) lo
, user_data
) < 0)
861 SWAP (mid
, lo
, size
);
863 left_ptr
= lo
+ size
;
864 right_ptr
= hi
- size
;
866 /* Here's the famous ``collapse the walls'' section of quicksort.
867 Gotta like those tight inner loops! They are the main reason
868 that this algorithm runs much faster than others. */
871 while ((*cmp
) ((void *) left_ptr
, (void *) mid
, user_data
) < 0)
874 while ((*cmp
) ((void *) mid
, (void *) right_ptr
, user_data
) < 0)
877 if (left_ptr
< right_ptr
)
879 SWAP (left_ptr
, right_ptr
, size
);
882 else if (mid
== right_ptr
)
887 else if (left_ptr
== right_ptr
)
894 while (left_ptr
<= right_ptr
);
896 /* Set up pointers for next iteration. First determine whether
897 left and right partitions are below the threshold size. If so,
898 ignore one or both. Otherwise, push the larger partition's
899 bounds on the stack and continue sorting the smaller one. */
901 if ((size_t) (right_ptr
- lo
) <= max_thresh
)
903 if ((size_t) (hi
- left_ptr
) <= max_thresh
)
904 /* Ignore both small partitions. */
907 /* Ignore small left partition. */
910 else if ((size_t) (hi
- left_ptr
) <= max_thresh
)
911 /* Ignore small right partition. */
913 else if ((right_ptr
- lo
) > (hi
- left_ptr
))
915 /* Push larger left partition indices. */
916 PUSH (lo
, right_ptr
);
921 /* Push larger right partition indices. */
928 /* Once the BASE_PTR array is partially sorted by quicksort the rest
929 is completely sorted using insertion sort, since this is efficient
930 for partitions below MAX_THRESH size. BASE_PTR points to the beginning
931 of the array to sort, and END_PTR points at the very last element in
932 the array (*not* one beyond it!). */
935 char *const end_ptr
= &base_ptr
[size
* (total_elems
- 1)];
936 char *tmp_ptr
= base_ptr
;
937 char *thresh
= base_ptr
+ max_thresh
;
938 if ( thresh
> end_ptr
)
940 register char *run_ptr
;
942 /* Find smallest element in first threshold and place it at the
943 array's beginning. This is the smallest array element,
944 and the operation speeds up insertion sort's inner loop. */
946 for (run_ptr
= tmp_ptr
+ size
; run_ptr
<= thresh
; run_ptr
+= size
)
947 if ((*cmp
) ((void *) run_ptr
, (void *) tmp_ptr
, user_data
) < 0)
950 if (tmp_ptr
!= base_ptr
)
951 SWAP (tmp_ptr
, base_ptr
, size
);
953 /* Insertion sort, running from left-hand-side up to right-hand-side. */
955 run_ptr
= base_ptr
+ size
;
956 while ((run_ptr
+= size
) <= end_ptr
)
958 tmp_ptr
= run_ptr
- size
;
959 while ((*cmp
) ((void *) run_ptr
, (void *) tmp_ptr
, user_data
) < 0)
963 if (tmp_ptr
!= run_ptr
)
967 trav
= run_ptr
+ size
;
968 while (--trav
>= run_ptr
)
973 for (hi
= lo
= trav
; (lo
-= size
) >= tmp_ptr
; hi
= lo
)
986 // ============================================================================
987 // GUI-only functions from now on
988 // ============================================================================
992 // this function is only really implemented for X11-based ports, including GTK1
993 // (GTK2 sets detectable auto-repeat automatically anyhow)
994 #if !(defined(__WXX11__) || defined(__WXMOTIF__) || \
995 (defined(__WXGTK__) && !defined(__WXGTK20__)))
996 bool wxSetDetectableAutoRepeat( bool WXUNUSED(flag
) )
1000 #endif // !X11-based port
1002 // ----------------------------------------------------------------------------
1003 // Launch default browser
1004 // ----------------------------------------------------------------------------
1006 #if defined(__WINDOWS__)
1008 // implemented in a port-specific utils source file:
1009 bool wxDoLaunchDefaultBrowser(const wxString
& url
, const wxString
& scheme
, int flags
);
1011 #elif defined(__WXX11__) || defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXCOCOA__) || \
1012 (defined(__WXOSX__) )
1014 // implemented in a port-specific utils source file:
1015 bool wxDoLaunchDefaultBrowser(const wxString
& url
, int flags
);
1019 // a "generic" implementation:
1020 bool wxDoLaunchDefaultBrowser(const wxString
& url
, int flags
)
1022 // on other platforms try to use mime types or wxExecute...
1028 wxFileType
*ft
= wxTheMimeTypesManager
->GetFileTypeFromExtension(wxT("html"));
1032 ft
->GetMimeType(&mt
);
1034 ok
= ft
->GetOpenCommand(&cmd
, wxFileType::MessageParameters(url
));
1037 #endif // wxUSE_MIMETYPE
1039 if ( !ok
|| cmd
.empty() )
1041 // fallback to checking for the BROWSER environment variable
1042 if ( !wxGetEnv(wxT("BROWSER"), &cmd
) || cmd
.empty() )
1043 cmd
<< wxT(' ') << url
;
1046 ok
= ( !cmd
.empty() && wxExecute(cmd
) );
1050 // no file type for HTML extension
1051 wxLogError(_("No default application configured for HTML files."));
1057 static bool DoLaunchDefaultBrowserHelper(const wxString
& urlOrig
, int flags
)
1059 // NOTE: we don't have to care about the wxBROWSER_NOBUSYCURSOR flag
1060 // as it was already handled by wxLaunchDefaultBrowser
1064 wxString
url(urlOrig
), scheme
;
1067 // this check is useful to avoid that wxURI recognizes as scheme parts of
1068 // the filename, in case urlOrig is a local filename
1069 // (e.g. "C:\\test.txt" when parsed by wxURI reports a scheme == "C")
1070 bool hasValidScheme
= uri
.HasScheme() && uri
.GetScheme().length() > 1;
1072 #if defined(__WINDOWS__)
1074 // NOTE: when testing wxMSW's wxLaunchDefaultBrowser all possible forms
1075 // of the URL/flags should be tested; e.g.:
1077 // for (int i=0; i<2; i++)
1079 // // test arguments without a valid URL scheme:
1080 // wxLaunchDefaultBrowser("C:\\test.txt", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1081 // wxLaunchDefaultBrowser("wxwidgets.org", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1083 // // test arguments with different valid schemes:
1084 // wxLaunchDefaultBrowser("file:/C%3A/test.txt", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1085 // wxLaunchDefaultBrowser("http://wxwidgets.org", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1086 // wxLaunchDefaultBrowser("mailto:user@host.org", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1088 // (assuming you have a C:\test.txt file)
1090 if ( !hasValidScheme
)
1092 if (wxFileExists(urlOrig
) || wxDirExists(urlOrig
))
1095 // do not prepend the file scheme to the URL as ShellExecuteEx() doesn't like it
1099 url
.Prepend(wxS("http://"));
1103 else if ( hasValidScheme
)
1105 scheme
= uri
.GetScheme();
1107 if ( uri
.GetScheme() == "file" )
1109 // TODO: extract URLToFileName() to some always compiled in
1111 #if wxUSE_FILESYSTEM
1112 // ShellExecuteEx() doesn't like the "file" scheme when opening local files;
1114 url
= wxFileSystem::URLToFileName(url
).GetFullPath();
1115 #endif // wxUSE_FILESYSTEM
1119 if (wxDoLaunchDefaultBrowser(url
, scheme
, flags
))
1121 //else: call wxLogSysError
1123 if ( !hasValidScheme
)
1125 // set the scheme of url to "http" or "file" if it does not have one
1126 if (wxFileExists(urlOrig
) || wxDirExists(urlOrig
))
1127 url
.Prepend(wxS("file://"));
1129 url
.Prepend(wxS("http://"));
1132 if (wxDoLaunchDefaultBrowser(url
, flags
))
1134 //else: call wxLogSysError
1137 wxLogSysError(_("Failed to open URL \"%s\" in default browser."),
1143 bool wxLaunchDefaultBrowser(const wxString
& url
, int flags
)
1145 // NOTE: as documented, "url" may be both a real well-formed URL
1146 // and a local file name
1148 if ( flags
& wxBROWSER_NOBUSYCURSOR
)
1149 return DoLaunchDefaultBrowserHelper(url
, flags
);
1152 return DoLaunchDefaultBrowserHelper(url
, flags
);
1155 // ----------------------------------------------------------------------------
1156 // Menu accelerators related functions
1157 // ----------------------------------------------------------------------------
1159 #if WXWIN_COMPATIBILITY_2_6
1160 wxChar
*wxStripMenuCodes(const wxChar
*in
, wxChar
*out
)
1163 wxString s
= wxMenuItem::GetLabelText(in
);
1166 wxString s
= wxStripMenuCodes(str
);
1167 #endif // wxUSE_MENUS
1170 // go smash their buffer if it's not big enough - I love char * params
1171 memcpy(out
, s
.c_str(), s
.length() * sizeof(wxChar
));
1175 out
= new wxChar
[s
.length() + 1];
1176 wxStrcpy(out
, s
.c_str());
1183 wxString
wxStripMenuCodes(const wxString
& in
, int flags
)
1185 wxASSERT_MSG( flags
, wxT("this is useless to call without any flags") );
1189 size_t len
= in
.length();
1192 for ( wxString::const_iterator it
= in
.begin(); it
!= in
.end(); ++it
)
1195 if ( (flags
& wxStrip_Mnemonics
) && ch
== wxT('&') )
1197 // skip it, it is used to introduce the accel char (or to quote
1198 // itself in which case it should still be skipped): note that it
1199 // can't be the last character of the string
1200 if ( ++it
== in
.end() )
1202 wxLogDebug(wxT("Invalid menu string '%s'"), in
.c_str());
1206 // use the next char instead
1210 else if ( (flags
& wxStrip_Accel
) && ch
== wxT('\t') )
1212 // everything after TAB is accel string, exit the loop
1222 // ----------------------------------------------------------------------------
1223 // Window search functions
1224 // ----------------------------------------------------------------------------
1227 * If parent is non-NULL, look through children for a label or title
1228 * matching the specified string. If NULL, look through all top-level windows.
1233 wxFindWindowByLabel (const wxString
& title
, wxWindow
* parent
)
1235 return wxWindow::FindWindowByLabel( title
, parent
);
1240 * If parent is non-NULL, look through children for a name
1241 * matching the specified string. If NULL, look through all top-level windows.
1246 wxFindWindowByName (const wxString
& name
, wxWindow
* parent
)
1248 return wxWindow::FindWindowByName( name
, parent
);
1251 // Returns menu item id or wxNOT_FOUND if none.
1253 wxFindMenuItemId(wxFrame
*frame
,
1254 const wxString
& menuString
,
1255 const wxString
& itemString
)
1258 wxMenuBar
*menuBar
= frame
->GetMenuBar ();
1260 return menuBar
->FindMenuItem (menuString
, itemString
);
1261 #else // !wxUSE_MENUS
1263 wxUnusedVar(menuString
);
1264 wxUnusedVar(itemString
);
1265 #endif // wxUSE_MENUS/!wxUSE_MENUS
1270 // Try to find the deepest child that contains 'pt'.
1271 // We go backwards, to try to allow for controls that are spacially
1272 // within other controls, but are still siblings (e.g. buttons within
1273 // static boxes). Static boxes are likely to be created _before_ controls
1274 // that sit inside them.
1275 wxWindow
* wxFindWindowAtPoint(wxWindow
* win
, const wxPoint
& pt
)
1277 if (!win
->IsShown())
1280 // Hack for wxNotebook case: at least in wxGTK, all pages
1281 // claim to be shown, so we must only deal with the selected one.
1283 if (wxDynamicCast(win
, wxNotebook
))
1285 wxNotebook
* nb
= (wxNotebook
*) win
;
1286 int sel
= nb
->GetSelection();
1289 wxWindow
* child
= nb
->GetPage(sel
);
1290 wxWindow
* foundWin
= wxFindWindowAtPoint(child
, pt
);
1297 wxWindowList::compatibility_iterator node
= win
->GetChildren().GetLast();
1300 wxWindow
* child
= node
->GetData();
1301 wxWindow
* foundWin
= wxFindWindowAtPoint(child
, pt
);
1304 node
= node
->GetPrevious();
1307 wxPoint pos
= win
->GetPosition();
1308 wxSize sz
= win
->GetSize();
1309 if ( !win
->IsTopLevel() && win
->GetParent() )
1311 pos
= win
->GetParent()->ClientToScreen(pos
);
1314 wxRect
rect(pos
, sz
);
1315 if (rect
.Contains(pt
))
1321 wxWindow
* wxGenericFindWindowAtPoint(const wxPoint
& pt
)
1323 // Go backwards through the list since windows
1324 // on top are likely to have been appended most
1326 wxWindowList::compatibility_iterator node
= wxTopLevelWindows
.GetLast();
1329 wxWindow
* win
= node
->GetData();
1330 wxWindow
* found
= wxFindWindowAtPoint(win
, pt
);
1333 node
= node
->GetPrevious();
1338 // ----------------------------------------------------------------------------
1340 // ----------------------------------------------------------------------------
1343 * N.B. these convenience functions must be separate from msgdlgg.cpp, textdlgg.cpp
1344 * since otherwise the generic code may be pulled in unnecessarily.
1349 int wxMessageBox(const wxString
& message
, const wxString
& caption
, long style
,
1350 wxWindow
*parent
, int WXUNUSED(x
), int WXUNUSED(y
) )
1352 // add the appropriate icon unless this was explicitly disabled by use of
1354 if ( !(style
& wxICON_NONE
) && !(style
& wxICON_MASK
) )
1356 style
|= style
& wxYES
? wxICON_QUESTION
: wxICON_INFORMATION
;
1359 wxMessageDialog
dialog(parent
, message
, caption
, style
);
1361 int ans
= dialog
.ShowModal();
1376 wxFAIL_MSG( wxT("unexpected return code from wxMessageDialog") );
1381 wxVersionInfo
wxGetLibraryVersionInfo()
1383 // don't translate these strings, they're for diagnostics purposes only
1385 msg
.Printf(wxS("wxWidgets Library (%s port)\n")
1386 wxS("Version %d.%d.%d (Unicode: %s, debug level: %d),\n")
1387 wxS("compiled at %s %s\n\n")
1388 wxS("Runtime version of toolkit used is %d.%d.\n"),
1389 wxPlatformInfo::Get().GetPortIdName(),
1393 #if wxUSE_UNICODE_UTF8
1403 wxPlatformInfo::Get().GetToolkitMajorVersion(),
1404 wxPlatformInfo::Get().GetToolkitMinorVersion()
1408 msg
+= wxString::Format("Compile-time GTK+ version is %d.%d.%d.\n",
1414 return wxVersionInfo(wxS("wxWidgets"),
1419 wxS("Copyright (c) 1995-2011 wxWidgets team"));
1422 void wxInfoMessageBox(wxWindow
* parent
)
1424 wxVersionInfo info
= wxGetLibraryVersionInfo();
1425 wxString msg
= info
.ToString();
1427 msg
<< wxS("\n") << info
.GetCopyright();
1429 wxMessageBox(msg
, wxT("wxWidgets information"),
1430 wxICON_INFORMATION
| wxOK
,
1434 #endif // wxUSE_MSGDLG
1438 wxString
wxGetTextFromUser(const wxString
& message
, const wxString
& caption
,
1439 const wxString
& defaultValue
, wxWindow
*parent
,
1440 wxCoord x
, wxCoord y
, bool centre
)
1443 long style
= wxTextEntryDialogStyle
;
1450 wxTextEntryDialog
dialog(parent
, message
, caption
, defaultValue
, style
, wxPoint(x
, y
));
1452 if (dialog
.ShowModal() == wxID_OK
)
1454 str
= dialog
.GetValue();
1460 wxString
wxGetPasswordFromUser(const wxString
& message
,
1461 const wxString
& caption
,
1462 const wxString
& defaultValue
,
1464 wxCoord x
, wxCoord y
, bool centre
)
1467 long style
= wxTextEntryDialogStyle
;
1474 wxPasswordEntryDialog
dialog(parent
, message
, caption
, defaultValue
,
1475 style
, wxPoint(x
, y
));
1476 if ( dialog
.ShowModal() == wxID_OK
)
1478 str
= dialog
.GetValue();
1484 #endif // wxUSE_TEXTDLG
1488 wxColour
wxGetColourFromUser(wxWindow
*parent
,
1489 const wxColour
& colInit
,
1490 const wxString
& caption
,
1491 wxColourData
*ptrData
)
1493 // contains serialized representation of wxColourData used the last time
1494 // the dialog was shown: we want to reuse it the next time in order to show
1495 // the same custom colours to the user (and we can't just have static
1496 // wxColourData itself because it's a GUI object and so should be destroyed
1497 // before GUI shutdown and doing it during static cleanup is too late)
1498 static wxString s_strColourData
;
1504 if ( !s_strColourData
.empty() )
1506 if ( !data
.FromString(s_strColourData
) )
1508 wxFAIL_MSG( "bug in wxColourData::FromString()?" );
1512 // we don't get back the "choose full" flag value from the native
1513 // dialog and so we can't preserve it between runs, so we decide to
1514 // always use it as it seems better than not using it (user can
1515 // just ignore the extra controls in the dialog but having to click
1516 // a button each time to show them would be very annoying
1517 data
.SetChooseFull(true);
1522 if ( colInit
.IsOk() )
1524 ptrData
->SetColour(colInit
);
1528 wxColourDialog
dialog(parent
, ptrData
);
1529 if (!caption
.empty())
1530 dialog
.SetTitle(caption
);
1531 if ( dialog
.ShowModal() == wxID_OK
)
1533 *ptrData
= dialog
.GetColourData();
1534 colRet
= ptrData
->GetColour();
1535 s_strColourData
= ptrData
->ToString();
1537 //else: leave colRet invalid
1542 #endif // wxUSE_COLOURDLG
1546 wxFont
wxGetFontFromUser(wxWindow
*parent
, const wxFont
& fontInit
, const wxString
& caption
)
1549 if ( fontInit
.IsOk() )
1551 data
.SetInitialFont(fontInit
);
1555 wxFontDialog
dialog(parent
, data
);
1556 if (!caption
.empty())
1557 dialog
.SetTitle(caption
);
1558 if ( dialog
.ShowModal() == wxID_OK
)
1560 fontRet
= dialog
.GetFontData().GetChosenFont();
1562 //else: leave it invalid
1567 #endif // wxUSE_FONTDLG
1569 // ----------------------------------------------------------------------------
1570 // wxSafeYield and supporting functions
1571 // ----------------------------------------------------------------------------
1573 void wxEnableTopLevelWindows(bool enable
)
1575 wxWindowList::compatibility_iterator node
;
1576 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1577 node
->GetData()->Enable(enable
);
1580 #if defined(__WXOSX__) && wxOSX_USE_COCOA
1582 // defined in evtloop.mm
1586 wxWindowDisabler::wxWindowDisabler(bool disable
)
1588 m_disabled
= disable
;
1593 wxWindowDisabler::wxWindowDisabler(wxWindow
*winToSkip
)
1596 DoDisable(winToSkip
);
1599 void wxWindowDisabler::DoDisable(wxWindow
*winToSkip
)
1601 // remember the top level windows which were already disabled, so that we
1602 // don't reenable them later
1603 m_winDisabled
= NULL
;
1605 wxWindowList::compatibility_iterator node
;
1606 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1608 wxWindow
*winTop
= node
->GetData();
1609 if ( winTop
== winToSkip
)
1612 // we don't need to disable the hidden or already disabled windows
1613 if ( winTop
->IsEnabled() && winTop
->IsShown() )
1619 if ( !m_winDisabled
)
1621 m_winDisabled
= new wxWindowList
;
1624 m_winDisabled
->Append(winTop
);
1629 wxWindowDisabler::~wxWindowDisabler()
1634 wxWindowList::compatibility_iterator node
;
1635 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1637 wxWindow
*winTop
= node
->GetData();
1638 if ( !m_winDisabled
|| !m_winDisabled
->Find(winTop
) )
1642 //else: had been already disabled, don't reenable
1645 delete m_winDisabled
;
1650 // Yield to other apps/messages and disable user input to all windows except
1652 bool wxSafeYield(wxWindow
*win
, bool onlyIfNeeded
)
1654 wxWindowDisabler
wd(win
);
1658 rc
= wxYieldIfNeeded();
1665 // ----------------------------------------------------------------------------
1666 // wxApp::Yield() wrappers for backwards compatibility
1667 // ----------------------------------------------------------------------------
1671 return wxTheApp
&& wxTheApp
->Yield();
1674 bool wxYieldIfNeeded()
1676 return wxTheApp
&& wxTheApp
->Yield(true);