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(__MWERKS__) && !defined(__WXWINCE__)
90 #include <sys/types.h>
94 #if defined(__WXMSW__)
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
== wxPORT_MGL
)
398 if (platform
== wxOS_OS2
)
402 if (platform
== wxPORT_PM
)
406 if (platform
== wxPORT_MAC
)
410 if (sm_customPlatforms
&& sm_customPlatforms
->Index(platform
) != wxNOT_FOUND
)
416 // ----------------------------------------------------------------------------
417 // network and user id functions
418 // ----------------------------------------------------------------------------
420 // Get Full RFC822 style email address
421 bool wxGetEmailAddress(wxChar
*address
, int maxSize
)
423 wxString email
= wxGetEmailAddress();
427 wxStrlcpy(address
, email
.t_str(), maxSize
);
432 wxString
wxGetEmailAddress()
436 wxString host
= wxGetFullHostName();
439 wxString user
= wxGetUserId();
442 email
<< user
<< wxT('@') << host
;
449 wxString
wxGetUserId()
451 static const int maxLoginLen
= 256; // FIXME arbitrary number
454 bool ok
= wxGetUserId(wxStringBuffer(buf
, maxLoginLen
), maxLoginLen
);
462 wxString
wxGetUserName()
464 static const int maxUserNameLen
= 1024; // FIXME arbitrary number
467 bool ok
= wxGetUserName(wxStringBuffer(buf
, maxUserNameLen
), maxUserNameLen
);
475 wxString
wxGetHostName()
477 static const size_t hostnameSize
= 257;
480 bool ok
= wxGetHostName(wxStringBuffer(buf
, hostnameSize
), hostnameSize
);
488 wxString
wxGetFullHostName()
490 static const size_t hostnameSize
= 257;
493 bool ok
= wxGetFullHostName(wxStringBuffer(buf
, hostnameSize
), hostnameSize
);
501 wxString
wxGetHomeDir()
511 wxString
wxGetCurrentDir()
518 ok
= getcwd(dir
.GetWriteBuf(len
+ 1), len
) != NULL
;
523 if ( errno
!= ERANGE
)
525 wxLogSysError(wxT("Failed to get current directory"));
527 return wxEmptyString
;
531 // buffer was too small, retry with a larger one
543 // ----------------------------------------------------------------------------
545 // ----------------------------------------------------------------------------
548 #if wxOSX_USE_COCOA_OR_CARBON
549 #include <crt_externs.h>
553 bool wxGetEnvMap(wxEnvVariableHashMap
*map
)
555 wxCHECK_MSG( map
, false, wxS("output pointer can't be NULL") );
557 #if defined(__VISUALC__)
558 wxChar
**env
= _tenviron
;
560 // Now this routine wil give false for OpenVMS
561 // TODO : should we do something with logicals?
563 #elif defined(__WXOSX__)
564 #if wxOSX_USE_COCOA_OR_CARBON
565 // Under Mac shared libraries don't have access to the global environ
566 // variable so use this Mac-specific function instead as advised by
567 // environ(7) under Darwin
568 char ***penv
= _NSGetEnviron();
574 // todo translate NSProcessInfo environment into map
576 #else // non-MSVC non-Mac
577 // Not sure if other compilers have _tenviron so use the (more standard)
578 // ANSI version only for them.
580 // Both POSIX and Single UNIX Specification say that this variable must
581 // exist but not that it must be declared anywhere and, indeed, it's not
582 // declared in several common systems (some BSDs, Solaris with native CC)
583 // so we (re)declare it ourselves to deal with these cases. However we do
584 // not do this under MSW where there can be DLL-related complications, i.e.
585 // the variable might be DLL-imported or not. Luckily we don't have to
586 // worry about this as all MSW compilers do seem to define it in their
587 // standard headers anyhow so we can just rely on already having the
588 // correct declaration. And if this turns out to be wrong, we can always
589 // add a configure test checking whether it is declared later.
591 extern char **environ
;
594 char **env
= environ
;
603 const wxString
var(*env
);
605 name
= var
.BeforeFirst(wxS('='), &value
);
607 (*map
)[name
] = value
;
618 // ----------------------------------------------------------------------------
620 // ----------------------------------------------------------------------------
622 // wxDoExecuteWithCapture() helper: reads an entire stream into one array
624 // returns true if ok, false if error
626 static bool ReadAll(wxInputStream
*is
, wxArrayString
& output
)
628 wxCHECK_MSG( is
, false, wxT("NULL stream in wxExecute()?") );
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
);
677 if ( !ReadAll(process
->GetInputStream(), output
) )
682 if ( !ReadAll(process
->GetErrorStream(), *error
) )
690 #endif // wxUSE_STREAMS/!wxUSE_STREAMS
697 long wxExecute(const wxString
& command
, wxArrayString
& output
, int flags
,
698 const wxExecuteEnv
*env
)
700 return wxDoExecuteWithCapture(command
, output
, NULL
, flags
, env
);
703 long wxExecute(const wxString
& command
,
704 wxArrayString
& output
,
705 wxArrayString
& error
,
707 const wxExecuteEnv
*env
)
709 return wxDoExecuteWithCapture(command
, output
, &error
, flags
, env
);
712 // ----------------------------------------------------------------------------
714 // ----------------------------------------------------------------------------
717 static long wxCurrentId
= 100;
721 // skip the part of IDs space that contains hard-coded values:
722 if (wxCurrentId
== wxID_LOWEST
)
723 wxCurrentId
= wxID_HIGHEST
+ 1;
725 return wxCurrentId
++;
729 wxGetCurrentId(void) { return wxCurrentId
; }
732 wxRegisterId (long id
)
734 if (id
>= wxCurrentId
)
735 wxCurrentId
= id
+ 1;
738 // ----------------------------------------------------------------------------
739 // wxQsort, adapted by RR to allow user_data
740 // ----------------------------------------------------------------------------
742 /* This file is part of the GNU C Library.
743 Written by Douglas C. Schmidt (schmidt@ics.uci.edu).
745 Douglas Schmidt kindly gave permission to relicence the
746 code under the wxWindows licence:
748 From: "Douglas C. Schmidt" <schmidt@dre.vanderbilt.edu>
749 To: Robert Roebling <robert.roebling@uni-ulm.de>
750 Subject: Re: qsort licence
751 Date: Mon, 23 Jul 2007 03:44:25 -0500
752 Sender: schmidt@dre.vanderbilt.edu
753 Message-Id: <20070723084426.64F511000A8@tango.dre.vanderbilt.edu>
757 > [...] I'm asking if you'd be willing to relicence your code
758 > under the wxWindows licence. [...]
760 That's fine with me [...]
767 /* Byte-wise swap two items of size SIZE. */
768 #define SWAP(a, b, size) \
771 register size_t __size = (size); \
772 register char *__a = (a), *__b = (b); \
778 } while (--__size > 0); \
781 /* Discontinue quicksort algorithm when partition gets below this size.
782 This particular magic number was chosen to work best on a Sun 4/260. */
785 /* Stack node declarations used to store unfulfilled partition obligations. */
792 /* The next 4 #defines implement a very fast in-line stack abstraction. */
793 #define STACK_SIZE (8 * sizeof(unsigned long int))
794 #define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top))
795 #define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi)))
796 #define STACK_NOT_EMPTY (stack < top)
799 /* Order size using quicksort. This implementation incorporates
800 four optimizations discussed in Sedgewick:
802 1. Non-recursive, using an explicit stack of pointer that store the
803 next array partition to sort. To save time, this maximum amount
804 of space required to store an array of MAX_INT is allocated on the
805 stack. Assuming a 32-bit integer, this needs only 32 *
806 sizeof(stack_node) == 136 bits. Pretty cheap, actually.
808 2. Chose the pivot element using a median-of-three decision tree.
809 This reduces the probability of selecting a bad pivot value and
810 eliminates certain extraneous comparisons.
812 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving
813 insertion sort to order the MAX_THRESH items within each partition.
814 This is a big win, since insertion sort is faster for small, mostly
815 sorted array segments.
817 4. The larger of the two sub-partitions is always pushed onto the
818 stack first, with the algorithm then concentrating on the
819 smaller partition. This *guarantees* no more than log (n)
820 stack size is needed (actually O(1) in this case)! */
822 void wxQsort(void* pbase
, size_t total_elems
,
823 size_t size
, wxSortCallback cmp
, const void* user_data
)
825 register char *base_ptr
= (char *) pbase
;
826 const size_t max_thresh
= MAX_THRESH
* size
;
828 if (total_elems
== 0)
829 /* Avoid lossage with unsigned arithmetic below. */
832 if (total_elems
> MAX_THRESH
)
835 char *hi
= &lo
[size
* (total_elems
- 1)];
836 stack_node stack
[STACK_SIZE
];
837 stack_node
*top
= stack
;
841 while (STACK_NOT_EMPTY
)
846 /* Select median value from among LO, MID, and HI. Rearrange
847 LO and HI so the three values are sorted. This lowers the
848 probability of picking a pathological pivot value and
849 skips a comparison for both the LEFT_PTR and RIGHT_PTR. */
851 char *mid
= lo
+ size
* ((hi
- lo
) / size
>> 1);
853 if ((*cmp
) ((void *) mid
, (void *) lo
, user_data
) < 0)
854 SWAP (mid
, lo
, size
);
855 if ((*cmp
) ((void *) hi
, (void *) mid
, user_data
) < 0)
856 SWAP (mid
, hi
, size
);
859 if ((*cmp
) ((void *) mid
, (void *) lo
, user_data
) < 0)
860 SWAP (mid
, lo
, size
);
862 left_ptr
= lo
+ size
;
863 right_ptr
= hi
- size
;
865 /* Here's the famous ``collapse the walls'' section of quicksort.
866 Gotta like those tight inner loops! They are the main reason
867 that this algorithm runs much faster than others. */
870 while ((*cmp
) ((void *) left_ptr
, (void *) mid
, user_data
) < 0)
873 while ((*cmp
) ((void *) mid
, (void *) right_ptr
, user_data
) < 0)
876 if (left_ptr
< right_ptr
)
878 SWAP (left_ptr
, right_ptr
, size
);
881 else if (mid
== right_ptr
)
886 else if (left_ptr
== right_ptr
)
893 while (left_ptr
<= right_ptr
);
895 /* Set up pointers for next iteration. First determine whether
896 left and right partitions are below the threshold size. If so,
897 ignore one or both. Otherwise, push the larger partition's
898 bounds on the stack and continue sorting the smaller one. */
900 if ((size_t) (right_ptr
- lo
) <= max_thresh
)
902 if ((size_t) (hi
- left_ptr
) <= max_thresh
)
903 /* Ignore both small partitions. */
906 /* Ignore small left partition. */
909 else if ((size_t) (hi
- left_ptr
) <= max_thresh
)
910 /* Ignore small right partition. */
912 else if ((right_ptr
- lo
) > (hi
- left_ptr
))
914 /* Push larger left partition indices. */
915 PUSH (lo
, right_ptr
);
920 /* Push larger right partition indices. */
927 /* Once the BASE_PTR array is partially sorted by quicksort the rest
928 is completely sorted using insertion sort, since this is efficient
929 for partitions below MAX_THRESH size. BASE_PTR points to the beginning
930 of the array to sort, and END_PTR points at the very last element in
931 the array (*not* one beyond it!). */
934 char *const end_ptr
= &base_ptr
[size
* (total_elems
- 1)];
935 char *tmp_ptr
= base_ptr
;
936 char *thresh
= base_ptr
+ max_thresh
;
937 if ( thresh
> end_ptr
)
939 register char *run_ptr
;
941 /* Find smallest element in first threshold and place it at the
942 array's beginning. This is the smallest array element,
943 and the operation speeds up insertion sort's inner loop. */
945 for (run_ptr
= tmp_ptr
+ size
; run_ptr
<= thresh
; run_ptr
+= size
)
946 if ((*cmp
) ((void *) run_ptr
, (void *) tmp_ptr
, user_data
) < 0)
949 if (tmp_ptr
!= base_ptr
)
950 SWAP (tmp_ptr
, base_ptr
, size
);
952 /* Insertion sort, running from left-hand-side up to right-hand-side. */
954 run_ptr
= base_ptr
+ size
;
955 while ((run_ptr
+= size
) <= end_ptr
)
957 tmp_ptr
= run_ptr
- size
;
958 while ((*cmp
) ((void *) run_ptr
, (void *) tmp_ptr
, user_data
) < 0)
962 if (tmp_ptr
!= run_ptr
)
966 trav
= run_ptr
+ size
;
967 while (--trav
>= run_ptr
)
972 for (hi
= lo
= trav
; (lo
-= size
) >= tmp_ptr
; hi
= lo
)
985 // ============================================================================
986 // GUI-only functions from now on
987 // ============================================================================
991 // this function is only really implemented for X11-based ports, including GTK1
992 // (GTK2 sets detectable auto-repeat automatically anyhow)
993 #if !(defined(__WXX11__) || defined(__WXMOTIF__) || \
994 (defined(__WXGTK__) && !defined(__WXGTK20__)))
995 bool wxSetDetectableAutoRepeat( bool WXUNUSED(flag
) )
999 #endif // !X11-based port
1001 // ----------------------------------------------------------------------------
1002 // Launch default browser
1003 // ----------------------------------------------------------------------------
1005 #if defined(__WXMSW__)
1007 // implemented in a port-specific utils source file:
1008 bool wxDoLaunchDefaultBrowser(const wxString
& url
, const wxString
& scheme
, int flags
);
1010 #elif defined(__WXX11__) || defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXCOCOA__) || \
1011 (defined(__WXOSX__) )
1013 // implemented in a port-specific utils source file:
1014 bool wxDoLaunchDefaultBrowser(const wxString
& url
, int flags
);
1018 // a "generic" implementation:
1019 bool wxDoLaunchDefaultBrowser(const wxString
& url
, int flags
)
1021 // on other platforms try to use mime types or wxExecute...
1027 wxFileType
*ft
= wxTheMimeTypesManager
->GetFileTypeFromExtension(wxT("html"));
1031 ft
->GetMimeType(&mt
);
1033 ok
= ft
->GetOpenCommand(&cmd
, wxFileType::MessageParameters(url
));
1036 #endif // wxUSE_MIMETYPE
1038 if ( !ok
|| cmd
.empty() )
1040 // fallback to checking for the BROWSER environment variable
1041 if ( !wxGetEnv(wxT("BROWSER"), &cmd
) || cmd
.empty() )
1042 cmd
<< wxT(' ') << url
;
1045 ok
= ( !cmd
.empty() && wxExecute(cmd
) );
1049 // no file type for HTML extension
1050 wxLogError(_("No default application configured for HTML files."));
1056 static bool DoLaunchDefaultBrowserHelper(const wxString
& urlOrig
, int flags
)
1058 // NOTE: we don't have to care about the wxBROWSER_NOBUSYCURSOR flag
1059 // as it was already handled by wxLaunchDefaultBrowser
1063 wxString
url(urlOrig
), scheme
;
1066 // this check is useful to avoid that wxURI recognizes as scheme parts of
1067 // the filename, in case urlOrig is a local filename
1068 // (e.g. "C:\\test.txt" when parsed by wxURI reports a scheme == "C")
1069 bool hasValidScheme
= uri
.HasScheme() && uri
.GetScheme().length() > 1;
1071 #if defined(__WXMSW__)
1073 // NOTE: when testing wxMSW's wxLaunchDefaultBrowser all possible forms
1074 // of the URL/flags should be tested; e.g.:
1076 // for (int i=0; i<2; i++)
1078 // // test arguments without a valid URL scheme:
1079 // wxLaunchDefaultBrowser("C:\\test.txt", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1080 // wxLaunchDefaultBrowser("wxwidgets.org", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1082 // // test arguments with different valid schemes:
1083 // wxLaunchDefaultBrowser("file:/C%3A/test.txt", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1084 // wxLaunchDefaultBrowser("http://wxwidgets.org", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1085 // wxLaunchDefaultBrowser("mailto:user@host.org", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1087 // (assuming you have a C:\test.txt file)
1089 if ( !hasValidScheme
)
1091 if (wxFileExists(urlOrig
) || wxDirExists(urlOrig
))
1094 // do not prepend the file scheme to the URL as ShellExecuteEx() doesn't like it
1098 url
.Prepend(wxS("http://"));
1102 else if ( hasValidScheme
)
1104 scheme
= uri
.GetScheme();
1106 if ( uri
.GetScheme() == "file" )
1108 // TODO: extract URLToFileName() to some always compiled in
1110 #if wxUSE_FILESYSTEM
1111 // ShellExecuteEx() doesn't like the "file" scheme when opening local files;
1113 url
= wxFileSystem::URLToFileName(url
).GetFullPath();
1114 #endif // wxUSE_FILESYSTEM
1118 if (wxDoLaunchDefaultBrowser(url
, scheme
, flags
))
1120 //else: call wxLogSysError
1122 if ( !hasValidScheme
)
1124 // set the scheme of url to "http" or "file" if it does not have one
1125 if (wxFileExists(urlOrig
) || wxDirExists(urlOrig
))
1126 url
.Prepend(wxS("file://"));
1128 url
.Prepend(wxS("http://"));
1131 if (wxDoLaunchDefaultBrowser(url
, flags
))
1133 //else: call wxLogSysError
1136 wxLogSysError(_("Failed to open URL \"%s\" in default browser."),
1142 bool wxLaunchDefaultBrowser(const wxString
& url
, int flags
)
1144 // NOTE: as documented, "url" may be both a real well-formed URL
1145 // and a local file name
1147 if ( flags
& wxBROWSER_NOBUSYCURSOR
)
1148 return DoLaunchDefaultBrowserHelper(url
, flags
);
1151 return DoLaunchDefaultBrowserHelper(url
, flags
);
1154 // ----------------------------------------------------------------------------
1155 // Menu accelerators related functions
1156 // ----------------------------------------------------------------------------
1158 #if WXWIN_COMPATIBILITY_2_6
1159 wxChar
*wxStripMenuCodes(const wxChar
*in
, wxChar
*out
)
1162 wxString s
= wxMenuItem::GetLabelText(in
);
1165 wxString s
= wxStripMenuCodes(str
);
1166 #endif // wxUSE_MENUS
1169 // go smash their buffer if it's not big enough - I love char * params
1170 memcpy(out
, s
.c_str(), s
.length() * sizeof(wxChar
));
1174 out
= new wxChar
[s
.length() + 1];
1175 wxStrcpy(out
, s
.c_str());
1182 wxString
wxStripMenuCodes(const wxString
& in
, int flags
)
1184 wxASSERT_MSG( flags
, wxT("this is useless to call without any flags") );
1188 size_t len
= in
.length();
1191 for ( size_t n
= 0; n
< len
; n
++ )
1194 if ( (flags
& wxStrip_Mnemonics
) && ch
== wxT('&') )
1196 // skip it, it is used to introduce the accel char (or to quote
1197 // itself in which case it should still be skipped): note that it
1198 // can't be the last character of the string
1201 wxLogDebug(wxT("Invalid menu string '%s'"), in
.c_str());
1205 // use the next char instead
1209 else if ( (flags
& wxStrip_Accel
) && ch
== wxT('\t') )
1211 // everything after TAB is accel string, exit the loop
1221 // ----------------------------------------------------------------------------
1222 // Window search functions
1223 // ----------------------------------------------------------------------------
1226 * If parent is non-NULL, look through children for a label or title
1227 * matching the specified string. If NULL, look through all top-level windows.
1232 wxFindWindowByLabel (const wxString
& title
, wxWindow
* parent
)
1234 return wxWindow::FindWindowByLabel( title
, parent
);
1239 * If parent is non-NULL, look through children for a name
1240 * matching the specified string. If NULL, look through all top-level windows.
1245 wxFindWindowByName (const wxString
& name
, wxWindow
* parent
)
1247 return wxWindow::FindWindowByName( name
, parent
);
1250 // Returns menu item id or wxNOT_FOUND if none.
1252 wxFindMenuItemId(wxFrame
*frame
,
1253 const wxString
& menuString
,
1254 const wxString
& itemString
)
1257 wxMenuBar
*menuBar
= frame
->GetMenuBar ();
1259 return menuBar
->FindMenuItem (menuString
, itemString
);
1260 #else // !wxUSE_MENUS
1262 wxUnusedVar(menuString
);
1263 wxUnusedVar(itemString
);
1264 #endif // wxUSE_MENUS/!wxUSE_MENUS
1269 // Try to find the deepest child that contains 'pt'.
1270 // We go backwards, to try to allow for controls that are spacially
1271 // within other controls, but are still siblings (e.g. buttons within
1272 // static boxes). Static boxes are likely to be created _before_ controls
1273 // that sit inside them.
1274 wxWindow
* wxFindWindowAtPoint(wxWindow
* win
, const wxPoint
& pt
)
1276 if (!win
->IsShown())
1279 // Hack for wxNotebook case: at least in wxGTK, all pages
1280 // claim to be shown, so we must only deal with the selected one.
1282 if (win
->IsKindOf(CLASSINFO(wxNotebook
)))
1284 wxNotebook
* nb
= (wxNotebook
*) win
;
1285 int sel
= nb
->GetSelection();
1288 wxWindow
* child
= nb
->GetPage(sel
);
1289 wxWindow
* foundWin
= wxFindWindowAtPoint(child
, pt
);
1296 wxWindowList::compatibility_iterator node
= win
->GetChildren().GetLast();
1299 wxWindow
* child
= node
->GetData();
1300 wxWindow
* foundWin
= wxFindWindowAtPoint(child
, pt
);
1303 node
= node
->GetPrevious();
1306 wxPoint pos
= win
->GetPosition();
1307 wxSize sz
= win
->GetSize();
1308 if ( !win
->IsTopLevel() && win
->GetParent() )
1310 pos
= win
->GetParent()->ClientToScreen(pos
);
1313 wxRect
rect(pos
, sz
);
1314 if (rect
.Contains(pt
))
1320 wxWindow
* wxGenericFindWindowAtPoint(const wxPoint
& pt
)
1322 // Go backwards through the list since windows
1323 // on top are likely to have been appended most
1325 wxWindowList::compatibility_iterator node
= wxTopLevelWindows
.GetLast();
1328 wxWindow
* win
= node
->GetData();
1329 wxWindow
* found
= wxFindWindowAtPoint(win
, pt
);
1332 node
= node
->GetPrevious();
1337 // ----------------------------------------------------------------------------
1339 // ----------------------------------------------------------------------------
1342 * N.B. these convenience functions must be separate from msgdlgg.cpp, textdlgg.cpp
1343 * since otherwise the generic code may be pulled in unnecessarily.
1348 int wxMessageBox(const wxString
& message
, const wxString
& caption
, long style
,
1349 wxWindow
*parent
, int WXUNUSED(x
), int WXUNUSED(y
) )
1351 // add the appropriate icon unless this was explicitly disabled by use of
1353 if ( !(style
& wxICON_NONE
) && !(style
& wxICON_MASK
) )
1355 style
|= style
& wxYES
? wxICON_QUESTION
: wxICON_INFORMATION
;
1358 wxMessageDialog
dialog(parent
, message
, caption
, style
);
1360 int ans
= dialog
.ShowModal();
1375 wxFAIL_MSG( wxT("unexpected return code from wxMessageDialog") );
1380 wxVersionInfo
wxGetLibraryVersionInfo()
1382 // don't translate these strings, they're for diagnostics purposes only
1384 msg
.Printf(wxS("wxWidgets Library (%s port)\n")
1385 wxS("Version %d.%d.%d (Unicode: %s, debug level: %d),\n")
1386 wxS("compiled at %s %s\n\n")
1387 wxS("Runtime version of toolkit used is %d.%d.\n"),
1388 wxPlatformInfo::Get().GetPortIdName(),
1392 #if wxUSE_UNICODE_UTF8
1402 wxPlatformInfo::Get().GetToolkitMajorVersion(),
1403 wxPlatformInfo::Get().GetToolkitMinorVersion()
1407 msg
+= wxString::Format("Compile-time GTK+ version is %d.%d.%d.\n",
1413 return wxVersionInfo(wxS("wxWidgets"),
1418 wxS("Copyright (c) 1995-2011 wxWidgets team"));
1421 void wxInfoMessageBox(wxWindow
* parent
)
1423 wxVersionInfo info
= wxGetLibraryVersionInfo();
1424 wxString msg
= info
.ToString();
1426 msg
<< wxS("\n") << info
.GetCopyright();
1428 wxMessageBox(msg
, wxT("wxWidgets information"),
1429 wxICON_INFORMATION
| wxOK
,
1433 #endif // wxUSE_MSGDLG
1437 wxString
wxGetTextFromUser(const wxString
& message
, const wxString
& caption
,
1438 const wxString
& defaultValue
, wxWindow
*parent
,
1439 wxCoord x
, wxCoord y
, bool centre
)
1442 long style
= wxTextEntryDialogStyle
;
1449 wxTextEntryDialog
dialog(parent
, message
, caption
, defaultValue
, style
, wxPoint(x
, y
));
1451 if (dialog
.ShowModal() == wxID_OK
)
1453 str
= dialog
.GetValue();
1459 wxString
wxGetPasswordFromUser(const wxString
& message
,
1460 const wxString
& caption
,
1461 const wxString
& defaultValue
,
1463 wxCoord x
, wxCoord y
, bool centre
)
1466 long style
= wxTextEntryDialogStyle
;
1473 wxPasswordEntryDialog
dialog(parent
, message
, caption
, defaultValue
,
1474 style
, wxPoint(x
, y
));
1475 if ( dialog
.ShowModal() == wxID_OK
)
1477 str
= dialog
.GetValue();
1483 #endif // wxUSE_TEXTDLG
1487 wxColour
wxGetColourFromUser(wxWindow
*parent
,
1488 const wxColour
& colInit
,
1489 const wxString
& caption
,
1490 wxColourData
*ptrData
)
1492 // contains serialized representation of wxColourData used the last time
1493 // the dialog was shown: we want to reuse it the next time in order to show
1494 // the same custom colours to the user (and we can't just have static
1495 // wxColourData itself because it's a GUI object and so should be destroyed
1496 // before GUI shutdown and doing it during static cleanup is too late)
1497 static wxString s_strColourData
;
1503 if ( !s_strColourData
.empty() )
1505 if ( !data
.FromString(s_strColourData
) )
1507 wxFAIL_MSG( "bug in wxColourData::FromString()?" );
1511 // we don't get back the "choose full" flag value from the native
1512 // dialog and so we can't preserve it between runs, so we decide to
1513 // always use it as it seems better than not using it (user can
1514 // just ignore the extra controls in the dialog but having to click
1515 // a button each time to show them would be very annoying
1516 data
.SetChooseFull(true);
1521 if ( colInit
.IsOk() )
1523 ptrData
->SetColour(colInit
);
1527 wxColourDialog
dialog(parent
, ptrData
);
1528 if (!caption
.empty())
1529 dialog
.SetTitle(caption
);
1530 if ( dialog
.ShowModal() == wxID_OK
)
1532 *ptrData
= dialog
.GetColourData();
1533 colRet
= ptrData
->GetColour();
1534 s_strColourData
= ptrData
->ToString();
1536 //else: leave colRet invalid
1541 #endif // wxUSE_COLOURDLG
1545 wxFont
wxGetFontFromUser(wxWindow
*parent
, const wxFont
& fontInit
, const wxString
& caption
)
1548 if ( fontInit
.IsOk() )
1550 data
.SetInitialFont(fontInit
);
1554 wxFontDialog
dialog(parent
, data
);
1555 if (!caption
.empty())
1556 dialog
.SetTitle(caption
);
1557 if ( dialog
.ShowModal() == wxID_OK
)
1559 fontRet
= dialog
.GetFontData().GetChosenFont();
1561 //else: leave it invalid
1566 #endif // wxUSE_FONTDLG
1568 // ----------------------------------------------------------------------------
1569 // wxSafeYield and supporting functions
1570 // ----------------------------------------------------------------------------
1572 void wxEnableTopLevelWindows(bool enable
)
1574 wxWindowList::compatibility_iterator node
;
1575 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1576 node
->GetData()->Enable(enable
);
1579 #if defined(__WXOSX__) && wxOSX_USE_COCOA
1581 // defined in evtloop.mm
1585 wxWindowDisabler::wxWindowDisabler(bool disable
)
1587 m_disabled
= disable
;
1592 wxWindowDisabler::wxWindowDisabler(wxWindow
*winToSkip
)
1595 DoDisable(winToSkip
);
1598 void wxWindowDisabler::DoDisable(wxWindow
*winToSkip
)
1600 // remember the top level windows which were already disabled, so that we
1601 // don't reenable them later
1602 m_winDisabled
= NULL
;
1604 wxWindowList::compatibility_iterator node
;
1605 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1607 wxWindow
*winTop
= node
->GetData();
1608 if ( winTop
== winToSkip
)
1611 // we don't need to disable the hidden or already disabled windows
1612 if ( winTop
->IsEnabled() && winTop
->IsShown() )
1618 if ( !m_winDisabled
)
1620 m_winDisabled
= new wxWindowList
;
1623 m_winDisabled
->Append(winTop
);
1628 wxWindowDisabler::~wxWindowDisabler()
1633 wxWindowList::compatibility_iterator node
;
1634 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1636 wxWindow
*winTop
= node
->GetData();
1637 if ( !m_winDisabled
|| !m_winDisabled
->Find(winTop
) )
1641 //else: had been already disabled, don't reenable
1644 delete m_winDisabled
;
1649 // Yield to other apps/messages and disable user input to all windows except
1651 bool wxSafeYield(wxWindow
*win
, bool onlyIfNeeded
)
1653 wxWindowDisabler
wd(win
);
1657 rc
= wxYieldIfNeeded();
1664 // ----------------------------------------------------------------------------
1665 // wxApp::Yield() wrappers for backwards compatibility
1666 // ----------------------------------------------------------------------------
1670 return wxTheApp
&& wxTheApp
->Yield();
1673 bool wxYieldIfNeeded()
1675 return wxTheApp
&& wxTheApp
->Yield(true);