1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/utilscmn.cpp
3 // Purpose: Miscellaneous utility functions and classes
4 // Author: Julian Smart
8 // Copyright: (c) 1998 Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
29 #include "wx/string.h"
35 #include "wx/window.h"
38 #include "wx/msgdlg.h"
39 #include "wx/textdlg.h"
40 #include "wx/textctrl.h" // for wxTE_PASSWORD
42 #include "wx/menuitem.h"
48 #include "wx/apptrait.h"
50 #include "wx/process.h"
51 #include "wx/txtstrm.h"
53 #include "wx/mimetype.h"
54 #include "wx/config.h"
55 #include "wx/versioninfo.h"
57 #if defined(__WXWINCE__) && wxUSE_DATETIME
58 #include "wx/datetime.h"
66 #if !wxONLY_WATCOM_EARLIER_THAN(1,4)
67 #if !(defined(_MSC_VER) && (_MSC_VER > 800))
73 #include "wx/colordlg.h"
74 #include "wx/fontdlg.h"
75 #include "wx/notebook.h"
76 #include "wx/statusbr.h"
83 #include "wx/msw/wince/time.h"
85 #endif // ! __WXPALMOS5__
88 #include "wx/osx/private.h"
92 #if !defined(__MWERKS__) && !defined(__WXWINCE__)
93 #include <sys/types.h>
96 #endif // ! __WXPALMOS5__
98 #if defined(__WXMSW__)
99 #include "wx/msw/private.h"
100 #include "wx/filesys.h"
103 #if wxUSE_GUI && defined(__WXGTK__)
104 #include <gtk/gtk.h> // for GTK_XXX_VERSION constants
109 // ============================================================================
111 // ============================================================================
113 // Array used in DecToHex conversion routine.
114 static const wxChar hexArray
[] = wxT("0123456789ABCDEF");
116 // Convert 2-digit hex number to decimal
117 int wxHexToDec(const wxString
& str
)
120 buf
[0] = str
.GetChar(0);
121 buf
[1] = str
.GetChar(1);
122 return wxHexToDec((const char*) buf
);
125 // Convert decimal integer to 2-character hex string
126 void wxDecToHex(int dec
, wxChar
*buf
)
128 int firstDigit
= (int)(dec
/16.0);
129 int secondDigit
= (int)(dec
- (firstDigit
*16.0));
130 buf
[0] = hexArray
[firstDigit
];
131 buf
[1] = hexArray
[secondDigit
];
135 // Convert decimal integer to 2 characters
136 void wxDecToHex(int dec
, char* ch1
, char* ch2
)
138 int firstDigit
= (int)(dec
/16.0);
139 int secondDigit
= (int)(dec
- (firstDigit
*16.0));
140 (*ch1
) = (char) hexArray
[firstDigit
];
141 (*ch2
) = (char) hexArray
[secondDigit
];
144 // Convert decimal integer to 2-character hex string
145 wxString
wxDecToHex(int dec
)
148 wxDecToHex(dec
, buf
);
149 return wxString(buf
);
152 // ----------------------------------------------------------------------------
154 // ----------------------------------------------------------------------------
156 // Return the current date/time
161 wxDateTime now
= wxDateTime::Now();
164 return wxEmptyString
;
167 time_t now
= time(NULL
);
168 char *date
= ctime(&now
);
170 return wxString::FromAscii(date
);
174 #if WXWIN_COMPATIBILITY_2_8
175 void wxUsleep(unsigned long milliseconds
)
177 wxMilliSleep(milliseconds
);
181 const wxChar
*wxGetInstallPrefix()
185 if ( wxGetEnv(wxT("WXPREFIX"), &prefix
) )
186 return prefix
.c_str();
188 #ifdef wxINSTALL_PREFIX
189 return wxT(wxINSTALL_PREFIX
);
191 return wxEmptyString
;
195 wxString
wxGetDataDir()
197 wxString dir
= wxGetInstallPrefix();
198 dir
<< wxFILE_SEP_PATH
<< wxT("share") << wxFILE_SEP_PATH
<< wxT("wx");
202 bool wxIsPlatformLittleEndian()
204 // Are we little or big endian? This method is from Harbison & Steele.
208 char c
[sizeof(long)];
216 // ----------------------------------------------------------------------------
218 // ----------------------------------------------------------------------------
221 * Class to make it easier to specify platform-dependent values
224 wxArrayInt
* wxPlatform::sm_customPlatforms
= NULL
;
226 void wxPlatform::Copy(const wxPlatform
& platform
)
228 m_longValue
= platform
.m_longValue
;
229 m_doubleValue
= platform
.m_doubleValue
;
230 m_stringValue
= platform
.m_stringValue
;
233 wxPlatform
wxPlatform::If(int platform
, long value
)
236 return wxPlatform(value
);
241 wxPlatform
wxPlatform::IfNot(int platform
, long value
)
244 return wxPlatform(value
);
249 wxPlatform
& wxPlatform::ElseIf(int platform
, long value
)
256 wxPlatform
& wxPlatform::ElseIfNot(int platform
, long value
)
263 wxPlatform
wxPlatform::If(int platform
, double value
)
266 return wxPlatform(value
);
271 wxPlatform
wxPlatform::IfNot(int platform
, double value
)
274 return wxPlatform(value
);
279 wxPlatform
& wxPlatform::ElseIf(int platform
, double value
)
282 m_doubleValue
= value
;
286 wxPlatform
& wxPlatform::ElseIfNot(int platform
, double value
)
289 m_doubleValue
= value
;
293 wxPlatform
wxPlatform::If(int platform
, const wxString
& value
)
296 return wxPlatform(value
);
301 wxPlatform
wxPlatform::IfNot(int platform
, const wxString
& value
)
304 return wxPlatform(value
);
309 wxPlatform
& wxPlatform::ElseIf(int platform
, const wxString
& value
)
312 m_stringValue
= value
;
316 wxPlatform
& wxPlatform::ElseIfNot(int platform
, const wxString
& value
)
319 m_stringValue
= value
;
323 wxPlatform
& wxPlatform::Else(long value
)
329 wxPlatform
& wxPlatform::Else(double value
)
331 m_doubleValue
= value
;
335 wxPlatform
& wxPlatform::Else(const wxString
& value
)
337 m_stringValue
= value
;
341 void wxPlatform::AddPlatform(int platform
)
343 if (!sm_customPlatforms
)
344 sm_customPlatforms
= new wxArrayInt
;
345 sm_customPlatforms
->Add(platform
);
348 void wxPlatform::ClearPlatforms()
350 wxDELETE(sm_customPlatforms
);
353 /// Function for testing current platform
355 bool wxPlatform::Is(int platform
)
358 if (platform
== wxOS_WINDOWS
)
362 if (platform
== wxOS_WINDOWS_CE
)
368 // FIXME: wxWinPocketPC and wxWinSmartPhone are unknown symbols
370 #if defined(__WXWINCE__) && defined(__POCKETPC__)
371 if (platform
== wxWinPocketPC
)
374 #if defined(__WXWINCE__) && defined(__SMARTPHONE__)
375 if (platform
== wxWinSmartPhone
)
382 if (platform
== wxPORT_GTK
)
386 if (platform
== wxPORT_MAC
)
390 if (platform
== wxPORT_X11
)
394 if (platform
== wxOS_UNIX
)
398 if (platform
== wxPORT_MGL
)
402 if (platform
== wxOS_OS2
)
406 if (platform
== wxPORT_PM
)
410 if (platform
== wxPORT_MAC
)
414 if (sm_customPlatforms
&& sm_customPlatforms
->Index(platform
) != wxNOT_FOUND
)
420 // ----------------------------------------------------------------------------
421 // network and user id functions
422 // ----------------------------------------------------------------------------
424 // Get Full RFC822 style email address
425 bool wxGetEmailAddress(wxChar
*address
, int maxSize
)
427 wxString email
= wxGetEmailAddress();
431 wxStrlcpy(address
, email
.t_str(), maxSize
);
436 wxString
wxGetEmailAddress()
440 wxString host
= wxGetFullHostName();
443 wxString user
= wxGetUserId();
446 email
<< user
<< wxT('@') << host
;
453 wxString
wxGetUserId()
455 static const int maxLoginLen
= 256; // FIXME arbitrary number
458 bool ok
= wxGetUserId(wxStringBuffer(buf
, maxLoginLen
), maxLoginLen
);
466 wxString
wxGetUserName()
468 static const int maxUserNameLen
= 1024; // FIXME arbitrary number
471 bool ok
= wxGetUserName(wxStringBuffer(buf
, maxUserNameLen
), maxUserNameLen
);
479 wxString
wxGetHostName()
481 static const size_t hostnameSize
= 257;
484 bool ok
= wxGetHostName(wxStringBuffer(buf
, hostnameSize
), hostnameSize
);
492 wxString
wxGetFullHostName()
494 static const size_t hostnameSize
= 257;
497 bool ok
= wxGetFullHostName(wxStringBuffer(buf
, hostnameSize
), hostnameSize
);
505 wxString
wxGetHomeDir()
515 wxString
wxGetCurrentDir()
522 ok
= getcwd(dir
.GetWriteBuf(len
+ 1), len
) != NULL
;
527 if ( errno
!= ERANGE
)
529 wxLogSysError(wxT("Failed to get current directory"));
531 return wxEmptyString
;
535 // buffer was too small, retry with a larger one
547 // ----------------------------------------------------------------------------
549 // ----------------------------------------------------------------------------
552 #if wxOSX_USE_COCOA_OR_CARBON
553 #include <crt_externs.h>
557 bool wxGetEnvMap(wxEnvVariableHashMap
*map
)
559 wxCHECK_MSG( map
, false, wxS("output pointer can't be NULL") );
561 #if defined(__VISUALC__)
562 wxChar
**env
= _tenviron
;
564 // Now this routine wil give false for OpenVMS
565 // TODO : should we do something with logicals?
567 #elif defined(__WXOSX__)
568 #if wxOSX_USE_COCOA_OR_CARBON
569 // Under Mac shared libraries don't have access to the global environ
570 // variable so use this Mac-specific function instead as advised by
571 // environ(7) under Darwin
572 char ***penv
= _NSGetEnviron();
578 // todo translate NSProcessInfo environment into map
580 #else // non-MSVC non-Mac
581 // Not sure if other compilers have _tenviron so use the (more standard)
582 // ANSI version only for them.
584 // Both POSIX and Single UNIX Specification say that this variable must
585 // exist but not that it must be declared anywhere and, indeed, it's not
586 // declared in several common systems (some BSDs, Solaris with native CC)
587 // so we (re)declare it ourselves to deal with these cases. However we do
588 // not do this under MSW where there can be DLL-related complications, i.e.
589 // the variable might be DLL-imported or not. Luckily we don't have to
590 // worry about this as all MSW compilers do seem to define it in their
591 // standard headers anyhow so we can just rely on already having the
592 // correct declaration. And if this turns out to be wrong, we can always
593 // add a configure test checking whether it is declared later.
595 extern char **environ
;
598 char **env
= environ
;
607 const wxString
var(*env
);
609 name
= var
.BeforeFirst(wxS('='), &value
);
611 (*map
)[name
] = value
;
622 // ----------------------------------------------------------------------------
624 // ----------------------------------------------------------------------------
626 // wxDoExecuteWithCapture() helper: reads an entire stream into one array
628 // returns true if ok, false if error
630 static bool ReadAll(wxInputStream
*is
, wxArrayString
& output
)
632 wxCHECK_MSG( is
, false, wxT("NULL stream in wxExecute()?") );
634 // the stream could be already at EOF or in wxSTREAM_BROKEN_PIPE state
637 wxTextInputStream
tis(*is
);
641 wxString line
= tis
.ReadLine();
643 // check for EOF before other errors as it's not really an error
646 // add the last, possibly incomplete, line
652 // any other error is fatal
661 #endif // wxUSE_STREAMS
663 // this is a private function because it hasn't a clean interface: the first
664 // array is passed by reference, the second by pointer - instead we have 2
665 // public versions of wxExecute() below
666 static long wxDoExecuteWithCapture(const wxString
& command
,
667 wxArrayString
& output
,
668 wxArrayString
* error
,
670 const wxExecuteEnv
*env
)
672 // create a wxProcess which will capture the output
673 wxProcess
*process
= new wxProcess
;
676 long rc
= wxExecute(command
, wxEXEC_SYNC
| flags
, process
, env
);
681 if ( !ReadAll(process
->GetInputStream(), output
) )
686 if ( !ReadAll(process
->GetErrorStream(), *error
) )
694 #endif // wxUSE_STREAMS/!wxUSE_STREAMS
701 long wxExecute(const wxString
& command
, wxArrayString
& output
, int flags
,
702 const wxExecuteEnv
*env
)
704 return wxDoExecuteWithCapture(command
, output
, NULL
, flags
, env
);
707 long wxExecute(const wxString
& command
,
708 wxArrayString
& output
,
709 wxArrayString
& error
,
711 const wxExecuteEnv
*env
)
713 return wxDoExecuteWithCapture(command
, output
, &error
, flags
, env
);
716 // ----------------------------------------------------------------------------
718 // ----------------------------------------------------------------------------
721 static long wxCurrentId
= 100;
725 // skip the part of IDs space that contains hard-coded values:
726 if (wxCurrentId
== wxID_LOWEST
)
727 wxCurrentId
= wxID_HIGHEST
+ 1;
729 return wxCurrentId
++;
733 wxGetCurrentId(void) { return wxCurrentId
; }
736 wxRegisterId (long id
)
738 if (id
>= wxCurrentId
)
739 wxCurrentId
= id
+ 1;
742 // ----------------------------------------------------------------------------
743 // wxQsort, adapted by RR to allow user_data
744 // ----------------------------------------------------------------------------
746 /* This file is part of the GNU C Library.
747 Written by Douglas C. Schmidt (schmidt@ics.uci.edu).
749 Douglas Schmidt kindly gave permission to relicence the
750 code under the wxWindows licence:
752 From: "Douglas C. Schmidt" <schmidt@dre.vanderbilt.edu>
753 To: Robert Roebling <robert.roebling@uni-ulm.de>
754 Subject: Re: qsort licence
755 Date: Mon, 23 Jul 2007 03:44:25 -0500
756 Sender: schmidt@dre.vanderbilt.edu
757 Message-Id: <20070723084426.64F511000A8@tango.dre.vanderbilt.edu>
761 > [...] I'm asking if you'd be willing to relicence your code
762 > under the wxWindows licence. [...]
764 That's fine with me [...]
771 /* Byte-wise swap two items of size SIZE. */
772 #define SWAP(a, b, size) \
775 register size_t __size = (size); \
776 register char *__a = (a), *__b = (b); \
782 } while (--__size > 0); \
785 /* Discontinue quicksort algorithm when partition gets below this size.
786 This particular magic number was chosen to work best on a Sun 4/260. */
789 /* Stack node declarations used to store unfulfilled partition obligations. */
796 /* The next 4 #defines implement a very fast in-line stack abstraction. */
797 #define STACK_SIZE (8 * sizeof(unsigned long int))
798 #define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top))
799 #define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi)))
800 #define STACK_NOT_EMPTY (stack < top)
803 /* Order size using quicksort. This implementation incorporates
804 four optimizations discussed in Sedgewick:
806 1. Non-recursive, using an explicit stack of pointer that store the
807 next array partition to sort. To save time, this maximum amount
808 of space required to store an array of MAX_INT is allocated on the
809 stack. Assuming a 32-bit integer, this needs only 32 *
810 sizeof(stack_node) == 136 bits. Pretty cheap, actually.
812 2. Chose the pivot element using a median-of-three decision tree.
813 This reduces the probability of selecting a bad pivot value and
814 eliminates certain extraneous comparisons.
816 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving
817 insertion sort to order the MAX_THRESH items within each partition.
818 This is a big win, since insertion sort is faster for small, mostly
819 sorted array segments.
821 4. The larger of the two sub-partitions is always pushed onto the
822 stack first, with the algorithm then concentrating on the
823 smaller partition. This *guarantees* no more than log (n)
824 stack size is needed (actually O(1) in this case)! */
826 void wxQsort(void* pbase
, size_t total_elems
,
827 size_t size
, wxSortCallback cmp
, const void* user_data
)
829 register char *base_ptr
= (char *) pbase
;
830 const size_t max_thresh
= MAX_THRESH
* size
;
832 if (total_elems
== 0)
833 /* Avoid lossage with unsigned arithmetic below. */
836 if (total_elems
> MAX_THRESH
)
839 char *hi
= &lo
[size
* (total_elems
- 1)];
840 stack_node stack
[STACK_SIZE
];
841 stack_node
*top
= stack
;
845 while (STACK_NOT_EMPTY
)
850 /* Select median value from among LO, MID, and HI. Rearrange
851 LO and HI so the three values are sorted. This lowers the
852 probability of picking a pathological pivot value and
853 skips a comparison for both the LEFT_PTR and RIGHT_PTR. */
855 char *mid
= lo
+ size
* ((hi
- lo
) / size
>> 1);
857 if ((*cmp
) ((void *) mid
, (void *) lo
, user_data
) < 0)
858 SWAP (mid
, lo
, size
);
859 if ((*cmp
) ((void *) hi
, (void *) mid
, user_data
) < 0)
860 SWAP (mid
, hi
, size
);
863 if ((*cmp
) ((void *) mid
, (void *) lo
, user_data
) < 0)
864 SWAP (mid
, lo
, size
);
866 left_ptr
= lo
+ size
;
867 right_ptr
= hi
- size
;
869 /* Here's the famous ``collapse the walls'' section of quicksort.
870 Gotta like those tight inner loops! They are the main reason
871 that this algorithm runs much faster than others. */
874 while ((*cmp
) ((void *) left_ptr
, (void *) mid
, user_data
) < 0)
877 while ((*cmp
) ((void *) mid
, (void *) right_ptr
, user_data
) < 0)
880 if (left_ptr
< right_ptr
)
882 SWAP (left_ptr
, right_ptr
, size
);
885 else if (mid
== right_ptr
)
890 else if (left_ptr
== right_ptr
)
897 while (left_ptr
<= right_ptr
);
899 /* Set up pointers for next iteration. First determine whether
900 left and right partitions are below the threshold size. If so,
901 ignore one or both. Otherwise, push the larger partition's
902 bounds on the stack and continue sorting the smaller one. */
904 if ((size_t) (right_ptr
- lo
) <= max_thresh
)
906 if ((size_t) (hi
- left_ptr
) <= max_thresh
)
907 /* Ignore both small partitions. */
910 /* Ignore small left partition. */
913 else if ((size_t) (hi
- left_ptr
) <= max_thresh
)
914 /* Ignore small right partition. */
916 else if ((right_ptr
- lo
) > (hi
- left_ptr
))
918 /* Push larger left partition indices. */
919 PUSH (lo
, right_ptr
);
924 /* Push larger right partition indices. */
931 /* Once the BASE_PTR array is partially sorted by quicksort the rest
932 is completely sorted using insertion sort, since this is efficient
933 for partitions below MAX_THRESH size. BASE_PTR points to the beginning
934 of the array to sort, and END_PTR points at the very last element in
935 the array (*not* one beyond it!). */
938 char *const end_ptr
= &base_ptr
[size
* (total_elems
- 1)];
939 char *tmp_ptr
= base_ptr
;
940 char *thresh
= base_ptr
+ max_thresh
;
941 if ( thresh
> end_ptr
)
943 register char *run_ptr
;
945 /* Find smallest element in first threshold and place it at the
946 array's beginning. This is the smallest array element,
947 and the operation speeds up insertion sort's inner loop. */
949 for (run_ptr
= tmp_ptr
+ size
; run_ptr
<= thresh
; run_ptr
+= size
)
950 if ((*cmp
) ((void *) run_ptr
, (void *) tmp_ptr
, user_data
) < 0)
953 if (tmp_ptr
!= base_ptr
)
954 SWAP (tmp_ptr
, base_ptr
, size
);
956 /* Insertion sort, running from left-hand-side up to right-hand-side. */
958 run_ptr
= base_ptr
+ size
;
959 while ((run_ptr
+= size
) <= end_ptr
)
961 tmp_ptr
= run_ptr
- size
;
962 while ((*cmp
) ((void *) run_ptr
, (void *) tmp_ptr
, user_data
) < 0)
966 if (tmp_ptr
!= run_ptr
)
970 trav
= run_ptr
+ size
;
971 while (--trav
>= run_ptr
)
976 for (hi
= lo
= trav
; (lo
-= size
) >= tmp_ptr
; hi
= lo
)
989 // ============================================================================
990 // GUI-only functions from now on
991 // ============================================================================
995 // this function is only really implemented for X11-based ports, including GTK1
996 // (GTK2 sets detectable auto-repeat automatically anyhow)
997 #if !(defined(__WXX11__) || defined(__WXMOTIF__) || \
998 (defined(__WXGTK__) && !defined(__WXGTK20__)))
999 bool wxSetDetectableAutoRepeat( bool WXUNUSED(flag
) )
1003 #endif // !X11-based port
1005 // ----------------------------------------------------------------------------
1006 // Launch default browser
1007 // ----------------------------------------------------------------------------
1009 #if defined(__WXMSW__)
1011 // implemented in a port-specific utils source file:
1012 bool wxDoLaunchDefaultBrowser(const wxString
& url
, const wxString
& scheme
, int flags
);
1014 #elif defined(__WXX11__) || defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXCOCOA__) || \
1015 (defined(__WXOSX__) )
1017 // implemented in a port-specific utils source file:
1018 bool wxDoLaunchDefaultBrowser(const wxString
& url
, int flags
);
1022 // a "generic" implementation:
1023 bool wxDoLaunchDefaultBrowser(const wxString
& url
, int flags
)
1025 // on other platforms try to use mime types or wxExecute...
1031 wxFileType
*ft
= wxTheMimeTypesManager
->GetFileTypeFromExtension(wxT("html"));
1035 ft
->GetMimeType(&mt
);
1037 ok
= ft
->GetOpenCommand(&cmd
, wxFileType::MessageParameters(url
));
1040 #endif // wxUSE_MIMETYPE
1042 if ( !ok
|| cmd
.empty() )
1044 // fallback to checking for the BROWSER environment variable
1045 if ( !wxGetEnv(wxT("BROWSER"), &cmd
) || cmd
.empty() )
1046 cmd
<< wxT(' ') << url
;
1049 ok
= ( !cmd
.empty() && wxExecute(cmd
) );
1053 // no file type for HTML extension
1054 wxLogError(_("No default application configured for HTML files."));
1060 static bool DoLaunchDefaultBrowserHelper(const wxString
& urlOrig
, int flags
)
1062 // NOTE: we don't have to care about the wxBROWSER_NOBUSYCURSOR flag
1063 // as it was already handled by wxLaunchDefaultBrowser
1067 wxString
url(urlOrig
), scheme
;
1070 // this check is useful to avoid that wxURI recognizes as scheme parts of
1071 // the filename, in case urlOrig is a local filename
1072 // (e.g. "C:\\test.txt" when parsed by wxURI reports a scheme == "C")
1073 bool hasValidScheme
= uri
.HasScheme() && uri
.GetScheme().length() > 1;
1075 #if defined(__WXMSW__)
1077 // NOTE: when testing wxMSW's wxLaunchDefaultBrowser all possible forms
1078 // of the URL/flags should be tested; e.g.:
1080 // for (int i=0; i<2; i++)
1082 // // test arguments without a valid URL scheme:
1083 // wxLaunchDefaultBrowser("C:\\test.txt", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1084 // wxLaunchDefaultBrowser("wxwidgets.org", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1086 // // test arguments with different valid schemes:
1087 // wxLaunchDefaultBrowser("file:/C%3A/test.txt", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1088 // wxLaunchDefaultBrowser("http://wxwidgets.org", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1089 // wxLaunchDefaultBrowser("mailto:user@host.org", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1091 // (assuming you have a C:\test.txt file)
1093 if ( !hasValidScheme
)
1095 if (wxFileExists(urlOrig
) || wxDirExists(urlOrig
))
1098 // do not prepend the file scheme to the URL as ShellExecuteEx() doesn't like it
1102 url
.Prepend(wxS("http://"));
1106 else if ( hasValidScheme
)
1108 scheme
= uri
.GetScheme();
1110 if ( uri
.GetScheme() == "file" )
1112 // TODO: extract URLToFileName() to some always compiled in
1114 #if wxUSE_FILESYSTEM
1115 // ShellExecuteEx() doesn't like the "file" scheme when opening local files;
1117 url
= wxFileSystem::URLToFileName(url
).GetFullPath();
1118 #endif // wxUSE_FILESYSTEM
1122 if (wxDoLaunchDefaultBrowser(url
, scheme
, flags
))
1124 //else: call wxLogSysError
1126 if ( !hasValidScheme
)
1128 // set the scheme of url to "http" or "file" if it does not have one
1129 if (wxFileExists(urlOrig
) || wxDirExists(urlOrig
))
1130 url
.Prepend(wxS("file://"));
1132 url
.Prepend(wxS("http://"));
1135 if (wxDoLaunchDefaultBrowser(url
, flags
))
1137 //else: call wxLogSysError
1140 wxLogSysError(_("Failed to open URL \"%s\" in default browser."),
1146 bool wxLaunchDefaultBrowser(const wxString
& url
, int flags
)
1148 // NOTE: as documented, "url" may be both a real well-formed URL
1149 // and a local file name
1151 if ( flags
& wxBROWSER_NOBUSYCURSOR
)
1152 return DoLaunchDefaultBrowserHelper(url
, flags
);
1155 return DoLaunchDefaultBrowserHelper(url
, flags
);
1158 // ----------------------------------------------------------------------------
1159 // Menu accelerators related functions
1160 // ----------------------------------------------------------------------------
1162 #if WXWIN_COMPATIBILITY_2_6
1163 wxChar
*wxStripMenuCodes(const wxChar
*in
, wxChar
*out
)
1166 wxString s
= wxMenuItem::GetLabelText(in
);
1169 wxString s
= wxStripMenuCodes(str
);
1170 #endif // wxUSE_MENUS
1173 // go smash their buffer if it's not big enough - I love char * params
1174 memcpy(out
, s
.c_str(), s
.length() * sizeof(wxChar
));
1178 out
= new wxChar
[s
.length() + 1];
1179 wxStrcpy(out
, s
.c_str());
1186 wxString
wxStripMenuCodes(const wxString
& in
, int flags
)
1188 wxASSERT_MSG( flags
, wxT("this is useless to call without any flags") );
1192 size_t len
= in
.length();
1195 for ( size_t n
= 0; n
< len
; n
++ )
1198 if ( (flags
& wxStrip_Mnemonics
) && ch
== wxT('&') )
1200 // skip it, it is used to introduce the accel char (or to quote
1201 // itself in which case it should still be skipped): note that it
1202 // can't be the last character of the string
1205 wxLogDebug(wxT("Invalid menu string '%s'"), in
.c_str());
1209 // use the next char instead
1213 else if ( (flags
& wxStrip_Accel
) && ch
== wxT('\t') )
1215 // everything after TAB is accel string, exit the loop
1225 // ----------------------------------------------------------------------------
1226 // Window search functions
1227 // ----------------------------------------------------------------------------
1230 * If parent is non-NULL, look through children for a label or title
1231 * matching the specified string. If NULL, look through all top-level windows.
1236 wxFindWindowByLabel (const wxString
& title
, wxWindow
* parent
)
1238 return wxWindow::FindWindowByLabel( title
, parent
);
1243 * If parent is non-NULL, look through children for a name
1244 * matching the specified string. If NULL, look through all top-level windows.
1249 wxFindWindowByName (const wxString
& name
, wxWindow
* parent
)
1251 return wxWindow::FindWindowByName( name
, parent
);
1254 // Returns menu item id or wxNOT_FOUND if none.
1256 wxFindMenuItemId(wxFrame
*frame
,
1257 const wxString
& menuString
,
1258 const wxString
& itemString
)
1261 wxMenuBar
*menuBar
= frame
->GetMenuBar ();
1263 return menuBar
->FindMenuItem (menuString
, itemString
);
1264 #else // !wxUSE_MENUS
1266 wxUnusedVar(menuString
);
1267 wxUnusedVar(itemString
);
1268 #endif // wxUSE_MENUS/!wxUSE_MENUS
1273 // Try to find the deepest child that contains 'pt'.
1274 // We go backwards, to try to allow for controls that are spacially
1275 // within other controls, but are still siblings (e.g. buttons within
1276 // static boxes). Static boxes are likely to be created _before_ controls
1277 // that sit inside them.
1278 wxWindow
* wxFindWindowAtPoint(wxWindow
* win
, const wxPoint
& pt
)
1280 if (!win
->IsShown())
1283 // Hack for wxNotebook case: at least in wxGTK, all pages
1284 // claim to be shown, so we must only deal with the selected one.
1286 if (win
->IsKindOf(CLASSINFO(wxNotebook
)))
1288 wxNotebook
* nb
= (wxNotebook
*) win
;
1289 int sel
= nb
->GetSelection();
1292 wxWindow
* child
= nb
->GetPage(sel
);
1293 wxWindow
* foundWin
= wxFindWindowAtPoint(child
, pt
);
1300 wxWindowList::compatibility_iterator node
= win
->GetChildren().GetLast();
1303 wxWindow
* child
= node
->GetData();
1304 wxWindow
* foundWin
= wxFindWindowAtPoint(child
, pt
);
1307 node
= node
->GetPrevious();
1310 wxPoint pos
= win
->GetPosition();
1311 wxSize sz
= win
->GetSize();
1312 if ( !win
->IsTopLevel() && win
->GetParent() )
1314 pos
= win
->GetParent()->ClientToScreen(pos
);
1317 wxRect
rect(pos
, sz
);
1318 if (rect
.Contains(pt
))
1324 wxWindow
* wxGenericFindWindowAtPoint(const wxPoint
& pt
)
1326 // Go backwards through the list since windows
1327 // on top are likely to have been appended most
1329 wxWindowList::compatibility_iterator node
= wxTopLevelWindows
.GetLast();
1332 wxWindow
* win
= node
->GetData();
1333 wxWindow
* found
= wxFindWindowAtPoint(win
, pt
);
1336 node
= node
->GetPrevious();
1341 // ----------------------------------------------------------------------------
1343 // ----------------------------------------------------------------------------
1346 * N.B. these convenience functions must be separate from msgdlgg.cpp, textdlgg.cpp
1347 * since otherwise the generic code may be pulled in unnecessarily.
1352 int wxMessageBox(const wxString
& message
, const wxString
& caption
, long style
,
1353 wxWindow
*parent
, int WXUNUSED(x
), int WXUNUSED(y
) )
1355 // add the appropriate icon unless this was explicitly disabled by use of
1357 if ( !(style
& wxICON_NONE
) && !(style
& wxICON_MASK
) )
1359 style
|= style
& wxYES
? wxICON_QUESTION
: wxICON_INFORMATION
;
1362 wxMessageDialog
dialog(parent
, message
, caption
, style
);
1364 int ans
= dialog
.ShowModal();
1379 wxFAIL_MSG( wxT("unexpected return code from wxMessageDialog") );
1384 wxVersionInfo
wxGetLibraryVersionInfo()
1386 // don't translate these strings, they're for diagnostics purposes only
1388 msg
.Printf(wxS("wxWidgets Library (%s port)\n")
1389 wxS("Version %d.%d.%d (Unicode: %s, debug level: %d),\n")
1390 wxS("compiled at %s %s\n\n")
1391 wxS("Runtime version of toolkit used is %d.%d.\n"),
1392 wxPlatformInfo::Get().GetPortIdName(),
1396 #if wxUSE_UNICODE_UTF8
1406 wxPlatformInfo::Get().GetToolkitMajorVersion(),
1407 wxPlatformInfo::Get().GetToolkitMinorVersion()
1411 msg
+= wxString::Format("Compile-time GTK+ version is %d.%d.%d.\n",
1417 return wxVersionInfo(wxS("wxWidgets"),
1422 wxS("Copyright (c) 1995-2011 wxWidgets team"));
1425 void wxInfoMessageBox(wxWindow
* parent
)
1427 wxVersionInfo info
= wxGetLibraryVersionInfo();
1428 wxString msg
= info
.ToString();
1430 msg
<< wxS("\n") << info
.GetCopyright();
1432 wxMessageBox(msg
, wxT("wxWidgets information"),
1433 wxICON_INFORMATION
| wxOK
,
1437 #endif // wxUSE_MSGDLG
1441 wxString
wxGetTextFromUser(const wxString
& message
, const wxString
& caption
,
1442 const wxString
& defaultValue
, wxWindow
*parent
,
1443 wxCoord x
, wxCoord y
, bool centre
)
1446 long style
= wxTextEntryDialogStyle
;
1453 wxTextEntryDialog
dialog(parent
, message
, caption
, defaultValue
, style
, wxPoint(x
, y
));
1455 if (dialog
.ShowModal() == wxID_OK
)
1457 str
= dialog
.GetValue();
1463 wxString
wxGetPasswordFromUser(const wxString
& message
,
1464 const wxString
& caption
,
1465 const wxString
& defaultValue
,
1467 wxCoord x
, wxCoord y
, bool centre
)
1470 long style
= wxTextEntryDialogStyle
;
1477 wxPasswordEntryDialog
dialog(parent
, message
, caption
, defaultValue
,
1478 style
, wxPoint(x
, y
));
1479 if ( dialog
.ShowModal() == wxID_OK
)
1481 str
= dialog
.GetValue();
1487 #endif // wxUSE_TEXTDLG
1491 wxColour
wxGetColourFromUser(wxWindow
*parent
,
1492 const wxColour
& colInit
,
1493 const wxString
& caption
,
1494 wxColourData
*ptrData
)
1496 // contains serialized representation of wxColourData used the last time
1497 // the dialog was shown: we want to reuse it the next time in order to show
1498 // the same custom colours to the user (and we can't just have static
1499 // wxColourData itself because it's a GUI object and so should be destroyed
1500 // before GUI shutdown and doing it during static cleanup is too late)
1501 static wxString s_strColourData
;
1507 if ( !s_strColourData
.empty() )
1509 if ( !data
.FromString(s_strColourData
) )
1511 wxFAIL_MSG( "bug in wxColourData::FromString()?" );
1515 // we don't get back the "choose full" flag value from the native
1516 // dialog and so we can't preserve it between runs, so we decide to
1517 // always use it as it seems better than not using it (user can
1518 // just ignore the extra controls in the dialog but having to click
1519 // a button each time to show them would be very annoying
1520 data
.SetChooseFull(true);
1525 if ( colInit
.IsOk() )
1527 ptrData
->SetColour(colInit
);
1531 wxColourDialog
dialog(parent
, ptrData
);
1532 if (!caption
.empty())
1533 dialog
.SetTitle(caption
);
1534 if ( dialog
.ShowModal() == wxID_OK
)
1536 *ptrData
= dialog
.GetColourData();
1537 colRet
= ptrData
->GetColour();
1538 s_strColourData
= ptrData
->ToString();
1540 //else: leave colRet invalid
1545 #endif // wxUSE_COLOURDLG
1549 wxFont
wxGetFontFromUser(wxWindow
*parent
, const wxFont
& fontInit
, const wxString
& caption
)
1552 if ( fontInit
.IsOk() )
1554 data
.SetInitialFont(fontInit
);
1558 wxFontDialog
dialog(parent
, data
);
1559 if (!caption
.empty())
1560 dialog
.SetTitle(caption
);
1561 if ( dialog
.ShowModal() == wxID_OK
)
1563 fontRet
= dialog
.GetFontData().GetChosenFont();
1565 //else: leave it invalid
1570 #endif // wxUSE_FONTDLG
1572 // ----------------------------------------------------------------------------
1573 // wxSafeYield and supporting functions
1574 // ----------------------------------------------------------------------------
1576 void wxEnableTopLevelWindows(bool enable
)
1578 wxWindowList::compatibility_iterator node
;
1579 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1580 node
->GetData()->Enable(enable
);
1583 #if defined(__WXOSX__) && wxOSX_USE_COCOA
1585 // defined in evtloop.mm
1589 wxWindowDisabler::wxWindowDisabler(bool disable
)
1591 m_disabled
= disable
;
1596 wxWindowDisabler::wxWindowDisabler(wxWindow
*winToSkip
)
1599 DoDisable(winToSkip
);
1602 void wxWindowDisabler::DoDisable(wxWindow
*winToSkip
)
1604 // remember the top level windows which were already disabled, so that we
1605 // don't reenable them later
1606 m_winDisabled
= NULL
;
1608 wxWindowList::compatibility_iterator node
;
1609 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1611 wxWindow
*winTop
= node
->GetData();
1612 if ( winTop
== winToSkip
)
1615 // we don't need to disable the hidden or already disabled windows
1616 if ( winTop
->IsEnabled() && winTop
->IsShown() )
1622 if ( !m_winDisabled
)
1624 m_winDisabled
= new wxWindowList
;
1627 m_winDisabled
->Append(winTop
);
1632 wxWindowDisabler::~wxWindowDisabler()
1637 wxWindowList::compatibility_iterator node
;
1638 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1640 wxWindow
*winTop
= node
->GetData();
1641 if ( !m_winDisabled
|| !m_winDisabled
->Find(winTop
) )
1645 //else: had been already disabled, don't reenable
1648 delete m_winDisabled
;
1653 // Yield to other apps/messages and disable user input to all windows except
1655 bool wxSafeYield(wxWindow
*win
, bool onlyIfNeeded
)
1657 wxWindowDisabler
wd(win
);
1661 rc
= wxYieldIfNeeded();
1668 // ----------------------------------------------------------------------------
1669 // wxApp::Yield() wrappers for backwards compatibility
1670 // ----------------------------------------------------------------------------
1674 return wxTheApp
&& wxTheApp
->Yield();
1677 bool wxYieldIfNeeded()
1679 return wxTheApp
&& wxTheApp
->Yield(true);