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(__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 wxChar
**env
= _tenviron
;
556 // Now this routine wil give false for OpenVMS
557 // TODO : should we do something with logicals?
559 #elif defined(__WXOSX__)
560 #if wxOSX_USE_COCOA_OR_CARBON
561 // Under Mac shared libraries don't have access to the global environ
562 // variable so use this Mac-specific function instead as advised by
563 // environ(7) under Darwin
564 char ***penv
= _NSGetEnviron();
570 // todo translate NSProcessInfo environment into map
572 #else // non-MSVC non-Mac
573 // Not sure if other compilers have _tenviron so use the (more standard)
574 // ANSI version only for them.
576 // Both POSIX and Single UNIX Specification say that this variable must
577 // exist but not that it must be declared anywhere and, indeed, it's not
578 // declared in several common systems (some BSDs, Solaris with native CC)
579 // so we (re)declare it ourselves to deal with these cases. However we do
580 // not do this under MSW where there can be DLL-related complications, i.e.
581 // the variable might be DLL-imported or not. Luckily we don't have to
582 // worry about this as all MSW compilers do seem to define it in their
583 // standard headers anyhow so we can just rely on already having the
584 // correct declaration. And if this turns out to be wrong, we can always
585 // add a configure test checking whether it is declared later.
587 extern char **environ
;
588 #endif // !__WINDOWS__
590 char **env
= environ
;
599 const wxString
var(*env
);
601 name
= var
.BeforeFirst(wxS('='), &value
);
603 (*map
)[name
] = value
;
614 // ----------------------------------------------------------------------------
616 // ----------------------------------------------------------------------------
618 // wxDoExecuteWithCapture() helper: reads an entire stream into one array
620 // returns true if ok, false if error
622 static bool ReadAll(wxInputStream
*is
, wxArrayString
& output
)
624 wxCHECK_MSG( is
, false, wxT("NULL stream in wxExecute()?") );
626 // the stream could be already at EOF or in wxSTREAM_BROKEN_PIPE state
629 wxTextInputStream
tis(*is
);
633 wxString line
= tis
.ReadLine();
635 // check for EOF before other errors as it's not really an error
638 // add the last, possibly incomplete, line
644 // any other error is fatal
653 #endif // wxUSE_STREAMS
655 // this is a private function because it hasn't a clean interface: the first
656 // array is passed by reference, the second by pointer - instead we have 2
657 // public versions of wxExecute() below
658 static long wxDoExecuteWithCapture(const wxString
& command
,
659 wxArrayString
& output
,
660 wxArrayString
* error
,
662 const wxExecuteEnv
*env
)
664 // create a wxProcess which will capture the output
665 wxProcess
*process
= new wxProcess
;
668 long rc
= wxExecute(command
, wxEXEC_SYNC
| flags
, process
, env
);
673 if ( !ReadAll(process
->GetInputStream(), output
) )
678 if ( !ReadAll(process
->GetErrorStream(), *error
) )
686 #endif // wxUSE_STREAMS/!wxUSE_STREAMS
693 long wxExecute(const wxString
& command
, wxArrayString
& output
, int flags
,
694 const wxExecuteEnv
*env
)
696 return wxDoExecuteWithCapture(command
, output
, NULL
, flags
, env
);
699 long wxExecute(const wxString
& command
,
700 wxArrayString
& output
,
701 wxArrayString
& error
,
703 const wxExecuteEnv
*env
)
705 return wxDoExecuteWithCapture(command
, output
, &error
, flags
, env
);
708 // ----------------------------------------------------------------------------
710 // ----------------------------------------------------------------------------
713 static long wxCurrentId
= 100;
717 // skip the part of IDs space that contains hard-coded values:
718 if (wxCurrentId
== wxID_LOWEST
)
719 wxCurrentId
= wxID_HIGHEST
+ 1;
721 return wxCurrentId
++;
725 wxGetCurrentId(void) { return wxCurrentId
; }
728 wxRegisterId (long id
)
730 if (id
>= wxCurrentId
)
731 wxCurrentId
= id
+ 1;
734 // ----------------------------------------------------------------------------
735 // wxQsort, adapted by RR to allow user_data
736 // ----------------------------------------------------------------------------
738 /* This file is part of the GNU C Library.
739 Written by Douglas C. Schmidt (schmidt@ics.uci.edu).
741 Douglas Schmidt kindly gave permission to relicence the
742 code under the wxWindows licence:
744 From: "Douglas C. Schmidt" <schmidt@dre.vanderbilt.edu>
745 To: Robert Roebling <robert.roebling@uni-ulm.de>
746 Subject: Re: qsort licence
747 Date: Mon, 23 Jul 2007 03:44:25 -0500
748 Sender: schmidt@dre.vanderbilt.edu
749 Message-Id: <20070723084426.64F511000A8@tango.dre.vanderbilt.edu>
753 > [...] I'm asking if you'd be willing to relicence your code
754 > under the wxWindows licence. [...]
756 That's fine with me [...]
763 /* Byte-wise swap two items of size SIZE. */
764 #define SWAP(a, b, size) \
767 register size_t __size = (size); \
768 register char *__a = (a), *__b = (b); \
774 } while (--__size > 0); \
777 /* Discontinue quicksort algorithm when partition gets below this size.
778 This particular magic number was chosen to work best on a Sun 4/260. */
781 /* Stack node declarations used to store unfulfilled partition obligations. */
788 /* The next 4 #defines implement a very fast in-line stack abstraction. */
789 #define STACK_SIZE (8 * sizeof(unsigned long int))
790 #define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top))
791 #define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi)))
792 #define STACK_NOT_EMPTY (stack < top)
795 /* Order size using quicksort. This implementation incorporates
796 four optimizations discussed in Sedgewick:
798 1. Non-recursive, using an explicit stack of pointer that store the
799 next array partition to sort. To save time, this maximum amount
800 of space required to store an array of MAX_INT is allocated on the
801 stack. Assuming a 32-bit integer, this needs only 32 *
802 sizeof(stack_node) == 136 bits. Pretty cheap, actually.
804 2. Chose the pivot element using a median-of-three decision tree.
805 This reduces the probability of selecting a bad pivot value and
806 eliminates certain extraneous comparisons.
808 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving
809 insertion sort to order the MAX_THRESH items within each partition.
810 This is a big win, since insertion sort is faster for small, mostly
811 sorted array segments.
813 4. The larger of the two sub-partitions is always pushed onto the
814 stack first, with the algorithm then concentrating on the
815 smaller partition. This *guarantees* no more than log (n)
816 stack size is needed (actually O(1) in this case)! */
818 void wxQsort(void* pbase
, size_t total_elems
,
819 size_t size
, wxSortCallback cmp
, const void* user_data
)
821 register char *base_ptr
= (char *) pbase
;
822 const size_t max_thresh
= MAX_THRESH
* size
;
824 if (total_elems
== 0)
825 /* Avoid lossage with unsigned arithmetic below. */
828 if (total_elems
> MAX_THRESH
)
831 char *hi
= &lo
[size
* (total_elems
- 1)];
832 stack_node stack
[STACK_SIZE
];
833 stack_node
*top
= stack
;
837 while (STACK_NOT_EMPTY
)
842 /* Select median value from among LO, MID, and HI. Rearrange
843 LO and HI so the three values are sorted. This lowers the
844 probability of picking a pathological pivot value and
845 skips a comparison for both the LEFT_PTR and RIGHT_PTR. */
847 char *mid
= lo
+ size
* ((hi
- lo
) / size
>> 1);
849 if ((*cmp
) ((void *) mid
, (void *) lo
, user_data
) < 0)
850 SWAP (mid
, lo
, size
);
851 if ((*cmp
) ((void *) hi
, (void *) mid
, user_data
) < 0)
852 SWAP (mid
, hi
, size
);
855 if ((*cmp
) ((void *) mid
, (void *) lo
, user_data
) < 0)
856 SWAP (mid
, lo
, size
);
858 left_ptr
= lo
+ size
;
859 right_ptr
= hi
- size
;
861 /* Here's the famous ``collapse the walls'' section of quicksort.
862 Gotta like those tight inner loops! They are the main reason
863 that this algorithm runs much faster than others. */
866 while ((*cmp
) ((void *) left_ptr
, (void *) mid
, user_data
) < 0)
869 while ((*cmp
) ((void *) mid
, (void *) right_ptr
, user_data
) < 0)
872 if (left_ptr
< right_ptr
)
874 SWAP (left_ptr
, right_ptr
, size
);
877 else if (mid
== right_ptr
)
882 else if (left_ptr
== right_ptr
)
889 while (left_ptr
<= right_ptr
);
891 /* Set up pointers for next iteration. First determine whether
892 left and right partitions are below the threshold size. If so,
893 ignore one or both. Otherwise, push the larger partition's
894 bounds on the stack and continue sorting the smaller one. */
896 if ((size_t) (right_ptr
- lo
) <= max_thresh
)
898 if ((size_t) (hi
- left_ptr
) <= max_thresh
)
899 /* Ignore both small partitions. */
902 /* Ignore small left partition. */
905 else if ((size_t) (hi
- left_ptr
) <= max_thresh
)
906 /* Ignore small right partition. */
908 else if ((right_ptr
- lo
) > (hi
- left_ptr
))
910 /* Push larger left partition indices. */
911 PUSH (lo
, right_ptr
);
916 /* Push larger right partition indices. */
923 /* Once the BASE_PTR array is partially sorted by quicksort the rest
924 is completely sorted using insertion sort, since this is efficient
925 for partitions below MAX_THRESH size. BASE_PTR points to the beginning
926 of the array to sort, and END_PTR points at the very last element in
927 the array (*not* one beyond it!). */
930 char *const end_ptr
= &base_ptr
[size
* (total_elems
- 1)];
931 char *tmp_ptr
= base_ptr
;
932 char *thresh
= base_ptr
+ max_thresh
;
933 if ( thresh
> end_ptr
)
935 register char *run_ptr
;
937 /* Find smallest element in first threshold and place it at the
938 array's beginning. This is the smallest array element,
939 and the operation speeds up insertion sort's inner loop. */
941 for (run_ptr
= tmp_ptr
+ size
; run_ptr
<= thresh
; run_ptr
+= size
)
942 if ((*cmp
) ((void *) run_ptr
, (void *) tmp_ptr
, user_data
) < 0)
945 if (tmp_ptr
!= base_ptr
)
946 SWAP (tmp_ptr
, base_ptr
, size
);
948 /* Insertion sort, running from left-hand-side up to right-hand-side. */
950 run_ptr
= base_ptr
+ size
;
951 while ((run_ptr
+= size
) <= end_ptr
)
953 tmp_ptr
= run_ptr
- size
;
954 while ((*cmp
) ((void *) run_ptr
, (void *) tmp_ptr
, user_data
) < 0)
958 if (tmp_ptr
!= run_ptr
)
962 trav
= run_ptr
+ size
;
963 while (--trav
>= run_ptr
)
968 for (hi
= lo
= trav
; (lo
-= size
) >= tmp_ptr
; hi
= lo
)
981 // ============================================================================
982 // GUI-only functions from now on
983 // ============================================================================
987 // this function is only really implemented for X11-based ports, including GTK1
988 // (GTK2 sets detectable auto-repeat automatically anyhow)
989 #if !(defined(__WXX11__) || defined(__WXMOTIF__) || \
990 (defined(__WXGTK__) && !defined(__WXGTK20__)))
991 bool wxSetDetectableAutoRepeat( bool WXUNUSED(flag
) )
995 #endif // !X11-based port
997 // ----------------------------------------------------------------------------
998 // Launch default browser
999 // ----------------------------------------------------------------------------
1001 #if defined(__WINDOWS__)
1003 // implemented in a port-specific utils source file:
1004 bool wxDoLaunchDefaultBrowser(const wxString
& url
, const wxString
& scheme
, int flags
);
1006 #elif defined(__WXX11__) || defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXCOCOA__) || \
1007 (defined(__WXOSX__) )
1009 // implemented in a port-specific utils source file:
1010 bool wxDoLaunchDefaultBrowser(const wxString
& url
, int flags
);
1014 // a "generic" implementation:
1015 bool wxDoLaunchDefaultBrowser(const wxString
& url
, int flags
)
1017 // on other platforms try to use mime types or wxExecute...
1023 wxFileType
*ft
= wxTheMimeTypesManager
->GetFileTypeFromExtension(wxT("html"));
1027 ft
->GetMimeType(&mt
);
1029 ok
= ft
->GetOpenCommand(&cmd
, wxFileType::MessageParameters(url
));
1032 #endif // wxUSE_MIMETYPE
1034 if ( !ok
|| cmd
.empty() )
1036 // fallback to checking for the BROWSER environment variable
1037 if ( !wxGetEnv(wxT("BROWSER"), &cmd
) || cmd
.empty() )
1038 cmd
<< wxT(' ') << url
;
1041 ok
= ( !cmd
.empty() && wxExecute(cmd
) );
1045 // no file type for HTML extension
1046 wxLogError(_("No default application configured for HTML files."));
1052 static bool DoLaunchDefaultBrowserHelper(const wxString
& urlOrig
, int flags
)
1054 // NOTE: we don't have to care about the wxBROWSER_NOBUSYCURSOR flag
1055 // as it was already handled by wxLaunchDefaultBrowser
1059 wxString
url(urlOrig
), scheme
;
1062 // this check is useful to avoid that wxURI recognizes as scheme parts of
1063 // the filename, in case urlOrig is a local filename
1064 // (e.g. "C:\\test.txt" when parsed by wxURI reports a scheme == "C")
1065 bool hasValidScheme
= uri
.HasScheme() && uri
.GetScheme().length() > 1;
1067 #if defined(__WINDOWS__)
1069 // NOTE: when testing wxMSW's wxLaunchDefaultBrowser all possible forms
1070 // of the URL/flags should be tested; e.g.:
1072 // for (int i=0; i<2; i++)
1074 // // test arguments without a valid URL scheme:
1075 // wxLaunchDefaultBrowser("C:\\test.txt", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1076 // wxLaunchDefaultBrowser("wxwidgets.org", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1078 // // test arguments with different valid schemes:
1079 // wxLaunchDefaultBrowser("file:/C%3A/test.txt", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1080 // wxLaunchDefaultBrowser("http://wxwidgets.org", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1081 // wxLaunchDefaultBrowser("mailto:user@host.org", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1083 // (assuming you have a C:\test.txt file)
1085 if ( !hasValidScheme
)
1087 if (wxFileExists(urlOrig
) || wxDirExists(urlOrig
))
1090 // do not prepend the file scheme to the URL as ShellExecuteEx() doesn't like it
1094 url
.Prepend(wxS("http://"));
1098 else if ( hasValidScheme
)
1100 scheme
= uri
.GetScheme();
1102 if ( uri
.GetScheme() == "file" )
1104 // TODO: extract URLToFileName() to some always compiled in
1106 #if wxUSE_FILESYSTEM
1107 // ShellExecuteEx() doesn't like the "file" scheme when opening local files;
1109 url
= wxFileSystem::URLToFileName(url
).GetFullPath();
1110 #endif // wxUSE_FILESYSTEM
1114 if (wxDoLaunchDefaultBrowser(url
, scheme
, flags
))
1116 //else: call wxLogSysError
1118 if ( !hasValidScheme
)
1120 // set the scheme of url to "http" or "file" if it does not have one
1121 if (wxFileExists(urlOrig
) || wxDirExists(urlOrig
))
1122 url
.Prepend(wxS("file://"));
1124 url
.Prepend(wxS("http://"));
1127 if (wxDoLaunchDefaultBrowser(url
, flags
))
1129 //else: call wxLogSysError
1132 wxLogSysError(_("Failed to open URL \"%s\" in default browser."),
1138 bool wxLaunchDefaultBrowser(const wxString
& url
, int flags
)
1140 // NOTE: as documented, "url" may be both a real well-formed URL
1141 // and a local file name
1143 if ( flags
& wxBROWSER_NOBUSYCURSOR
)
1144 return DoLaunchDefaultBrowserHelper(url
, flags
);
1147 return DoLaunchDefaultBrowserHelper(url
, flags
);
1150 // ----------------------------------------------------------------------------
1151 // Menu accelerators related functions
1152 // ----------------------------------------------------------------------------
1154 #if WXWIN_COMPATIBILITY_2_6
1155 wxChar
*wxStripMenuCodes(const wxChar
*in
, wxChar
*out
)
1158 wxString s
= wxMenuItem::GetLabelText(in
);
1161 wxString s
= wxStripMenuCodes(str
);
1162 #endif // wxUSE_MENUS
1165 // go smash their buffer if it's not big enough - I love char * params
1166 memcpy(out
, s
.c_str(), s
.length() * sizeof(wxChar
));
1170 out
= new wxChar
[s
.length() + 1];
1171 wxStrcpy(out
, s
.c_str());
1178 wxString
wxStripMenuCodes(const wxString
& in
, int flags
)
1180 wxASSERT_MSG( flags
, wxT("this is useless to call without any flags") );
1184 size_t len
= in
.length();
1187 for ( size_t n
= 0; n
< len
; n
++ )
1190 if ( (flags
& wxStrip_Mnemonics
) && ch
== wxT('&') )
1192 // skip it, it is used to introduce the accel char (or to quote
1193 // itself in which case it should still be skipped): note that it
1194 // can't be the last character of the string
1197 wxLogDebug(wxT("Invalid menu string '%s'"), in
.c_str());
1201 // use the next char instead
1205 else if ( (flags
& wxStrip_Accel
) && ch
== wxT('\t') )
1207 // everything after TAB is accel string, exit the loop
1217 // ----------------------------------------------------------------------------
1218 // Window search functions
1219 // ----------------------------------------------------------------------------
1222 * If parent is non-NULL, look through children for a label or title
1223 * matching the specified string. If NULL, look through all top-level windows.
1228 wxFindWindowByLabel (const wxString
& title
, wxWindow
* parent
)
1230 return wxWindow::FindWindowByLabel( title
, parent
);
1235 * If parent is non-NULL, look through children for a name
1236 * matching the specified string. If NULL, look through all top-level windows.
1241 wxFindWindowByName (const wxString
& name
, wxWindow
* parent
)
1243 return wxWindow::FindWindowByName( name
, parent
);
1246 // Returns menu item id or wxNOT_FOUND if none.
1248 wxFindMenuItemId(wxFrame
*frame
,
1249 const wxString
& menuString
,
1250 const wxString
& itemString
)
1253 wxMenuBar
*menuBar
= frame
->GetMenuBar ();
1255 return menuBar
->FindMenuItem (menuString
, itemString
);
1256 #else // !wxUSE_MENUS
1258 wxUnusedVar(menuString
);
1259 wxUnusedVar(itemString
);
1260 #endif // wxUSE_MENUS/!wxUSE_MENUS
1265 // Try to find the deepest child that contains 'pt'.
1266 // We go backwards, to try to allow for controls that are spacially
1267 // within other controls, but are still siblings (e.g. buttons within
1268 // static boxes). Static boxes are likely to be created _before_ controls
1269 // that sit inside them.
1270 wxWindow
* wxFindWindowAtPoint(wxWindow
* win
, const wxPoint
& pt
)
1272 if (!win
->IsShown())
1275 // Hack for wxNotebook case: at least in wxGTK, all pages
1276 // claim to be shown, so we must only deal with the selected one.
1278 if (win
->IsKindOf(CLASSINFO(wxNotebook
)))
1280 wxNotebook
* nb
= (wxNotebook
*) win
;
1281 int sel
= nb
->GetSelection();
1284 wxWindow
* child
= nb
->GetPage(sel
);
1285 wxWindow
* foundWin
= wxFindWindowAtPoint(child
, pt
);
1292 wxWindowList::compatibility_iterator node
= win
->GetChildren().GetLast();
1295 wxWindow
* child
= node
->GetData();
1296 wxWindow
* foundWin
= wxFindWindowAtPoint(child
, pt
);
1299 node
= node
->GetPrevious();
1302 wxPoint pos
= win
->GetPosition();
1303 wxSize sz
= win
->GetSize();
1304 if ( !win
->IsTopLevel() && win
->GetParent() )
1306 pos
= win
->GetParent()->ClientToScreen(pos
);
1309 wxRect
rect(pos
, sz
);
1310 if (rect
.Contains(pt
))
1316 wxWindow
* wxGenericFindWindowAtPoint(const wxPoint
& pt
)
1318 // Go backwards through the list since windows
1319 // on top are likely to have been appended most
1321 wxWindowList::compatibility_iterator node
= wxTopLevelWindows
.GetLast();
1324 wxWindow
* win
= node
->GetData();
1325 wxWindow
* found
= wxFindWindowAtPoint(win
, pt
);
1328 node
= node
->GetPrevious();
1333 // ----------------------------------------------------------------------------
1335 // ----------------------------------------------------------------------------
1338 * N.B. these convenience functions must be separate from msgdlgg.cpp, textdlgg.cpp
1339 * since otherwise the generic code may be pulled in unnecessarily.
1344 int wxMessageBox(const wxString
& message
, const wxString
& caption
, long style
,
1345 wxWindow
*parent
, int WXUNUSED(x
), int WXUNUSED(y
) )
1347 // add the appropriate icon unless this was explicitly disabled by use of
1349 if ( !(style
& wxICON_NONE
) && !(style
& wxICON_MASK
) )
1351 style
|= style
& wxYES
? wxICON_QUESTION
: wxICON_INFORMATION
;
1354 wxMessageDialog
dialog(parent
, message
, caption
, style
);
1356 int ans
= dialog
.ShowModal();
1371 wxFAIL_MSG( wxT("unexpected return code from wxMessageDialog") );
1376 wxVersionInfo
wxGetLibraryVersionInfo()
1378 // don't translate these strings, they're for diagnostics purposes only
1380 msg
.Printf(wxS("wxWidgets Library (%s port)\n")
1381 wxS("Version %d.%d.%d (Unicode: %s, debug level: %d),\n")
1382 wxS("compiled at %s %s\n\n")
1383 wxS("Runtime version of toolkit used is %d.%d.\n"),
1384 wxPlatformInfo::Get().GetPortIdName(),
1388 #if wxUSE_UNICODE_UTF8
1398 wxPlatformInfo::Get().GetToolkitMajorVersion(),
1399 wxPlatformInfo::Get().GetToolkitMinorVersion()
1403 msg
+= wxString::Format("Compile-time GTK+ version is %d.%d.%d.\n",
1409 return wxVersionInfo(wxS("wxWidgets"),
1414 wxS("Copyright (c) 1995-2011 wxWidgets team"));
1417 void wxInfoMessageBox(wxWindow
* parent
)
1419 wxVersionInfo info
= wxGetLibraryVersionInfo();
1420 wxString msg
= info
.ToString();
1422 msg
<< wxS("\n") << info
.GetCopyright();
1424 wxMessageBox(msg
, wxT("wxWidgets information"),
1425 wxICON_INFORMATION
| wxOK
,
1429 #endif // wxUSE_MSGDLG
1433 wxString
wxGetTextFromUser(const wxString
& message
, const wxString
& caption
,
1434 const wxString
& defaultValue
, wxWindow
*parent
,
1435 wxCoord x
, wxCoord y
, bool centre
)
1438 long style
= wxTextEntryDialogStyle
;
1445 wxTextEntryDialog
dialog(parent
, message
, caption
, defaultValue
, style
, wxPoint(x
, y
));
1447 if (dialog
.ShowModal() == wxID_OK
)
1449 str
= dialog
.GetValue();
1455 wxString
wxGetPasswordFromUser(const wxString
& message
,
1456 const wxString
& caption
,
1457 const wxString
& defaultValue
,
1459 wxCoord x
, wxCoord y
, bool centre
)
1462 long style
= wxTextEntryDialogStyle
;
1469 wxPasswordEntryDialog
dialog(parent
, message
, caption
, defaultValue
,
1470 style
, wxPoint(x
, y
));
1471 if ( dialog
.ShowModal() == wxID_OK
)
1473 str
= dialog
.GetValue();
1479 #endif // wxUSE_TEXTDLG
1483 wxColour
wxGetColourFromUser(wxWindow
*parent
,
1484 const wxColour
& colInit
,
1485 const wxString
& caption
,
1486 wxColourData
*ptrData
)
1488 // contains serialized representation of wxColourData used the last time
1489 // the dialog was shown: we want to reuse it the next time in order to show
1490 // the same custom colours to the user (and we can't just have static
1491 // wxColourData itself because it's a GUI object and so should be destroyed
1492 // before GUI shutdown and doing it during static cleanup is too late)
1493 static wxString s_strColourData
;
1499 if ( !s_strColourData
.empty() )
1501 if ( !data
.FromString(s_strColourData
) )
1503 wxFAIL_MSG( "bug in wxColourData::FromString()?" );
1507 // we don't get back the "choose full" flag value from the native
1508 // dialog and so we can't preserve it between runs, so we decide to
1509 // always use it as it seems better than not using it (user can
1510 // just ignore the extra controls in the dialog but having to click
1511 // a button each time to show them would be very annoying
1512 data
.SetChooseFull(true);
1517 if ( colInit
.IsOk() )
1519 ptrData
->SetColour(colInit
);
1523 wxColourDialog
dialog(parent
, ptrData
);
1524 if (!caption
.empty())
1525 dialog
.SetTitle(caption
);
1526 if ( dialog
.ShowModal() == wxID_OK
)
1528 *ptrData
= dialog
.GetColourData();
1529 colRet
= ptrData
->GetColour();
1530 s_strColourData
= ptrData
->ToString();
1532 //else: leave colRet invalid
1537 #endif // wxUSE_COLOURDLG
1541 wxFont
wxGetFontFromUser(wxWindow
*parent
, const wxFont
& fontInit
, const wxString
& caption
)
1544 if ( fontInit
.IsOk() )
1546 data
.SetInitialFont(fontInit
);
1550 wxFontDialog
dialog(parent
, data
);
1551 if (!caption
.empty())
1552 dialog
.SetTitle(caption
);
1553 if ( dialog
.ShowModal() == wxID_OK
)
1555 fontRet
= dialog
.GetFontData().GetChosenFont();
1557 //else: leave it invalid
1562 #endif // wxUSE_FONTDLG
1564 // ----------------------------------------------------------------------------
1565 // wxSafeYield and supporting functions
1566 // ----------------------------------------------------------------------------
1568 void wxEnableTopLevelWindows(bool enable
)
1570 wxWindowList::compatibility_iterator node
;
1571 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1572 node
->GetData()->Enable(enable
);
1575 #if defined(__WXOSX__) && wxOSX_USE_COCOA
1577 // defined in evtloop.mm
1581 wxWindowDisabler::wxWindowDisabler(bool disable
)
1583 m_disabled
= disable
;
1588 wxWindowDisabler::wxWindowDisabler(wxWindow
*winToSkip
)
1591 DoDisable(winToSkip
);
1594 void wxWindowDisabler::DoDisable(wxWindow
*winToSkip
)
1596 // remember the top level windows which were already disabled, so that we
1597 // don't reenable them later
1598 m_winDisabled
= NULL
;
1600 wxWindowList::compatibility_iterator node
;
1601 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1603 wxWindow
*winTop
= node
->GetData();
1604 if ( winTop
== winToSkip
)
1607 // we don't need to disable the hidden or already disabled windows
1608 if ( winTop
->IsEnabled() && winTop
->IsShown() )
1614 if ( !m_winDisabled
)
1616 m_winDisabled
= new wxWindowList
;
1619 m_winDisabled
->Append(winTop
);
1624 wxWindowDisabler::~wxWindowDisabler()
1629 wxWindowList::compatibility_iterator node
;
1630 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1632 wxWindow
*winTop
= node
->GetData();
1633 if ( !m_winDisabled
|| !m_winDisabled
->Find(winTop
) )
1637 //else: had been already disabled, don't reenable
1640 delete m_winDisabled
;
1645 // Yield to other apps/messages and disable user input to all windows except
1647 bool wxSafeYield(wxWindow
*win
, bool onlyIfNeeded
)
1649 wxWindowDisabler
wd(win
);
1653 rc
= wxYieldIfNeeded();
1660 // ----------------------------------------------------------------------------
1661 // wxApp::Yield() wrappers for backwards compatibility
1662 // ----------------------------------------------------------------------------
1666 return wxTheApp
&& wxTheApp
->Yield();
1669 bool wxYieldIfNeeded()
1671 return wxTheApp
&& wxTheApp
->Yield(true);