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 #include <crt_externs.h>
555 bool wxGetEnvMap(wxEnvVariableHashMap
*map
)
557 wxCHECK_MSG( map
, false, wxS("output pointer can't be NULL") );
559 #if defined(__VISUALC__)
560 wxChar
**env
= _tenviron
;
562 // Now this routine wil give false for OpenVMS
563 // TODO : should we do something with logicals?
565 #elif defined(__WXOSX__)
566 // Under Mac shared libraries don't have access to the global environ
567 // variable so use this Mac-specific function instead as advised by
568 // environ(7) under Darwin
569 char ***penv
= _NSGetEnviron();
573 #else // non-MSVC non-Mac
574 // Not sure if other compilers have _tenviron so use the (more standard)
575 // ANSI version only for them.
576 char **env
= environ
;
585 const wxString
var(*env
);
587 name
= var
.BeforeFirst(wxS('='), &value
);
589 (*map
)[name
] = value
;
600 // ----------------------------------------------------------------------------
602 // ----------------------------------------------------------------------------
604 // wxDoExecuteWithCapture() helper: reads an entire stream into one array
606 // returns true if ok, false if error
608 static bool ReadAll(wxInputStream
*is
, wxArrayString
& output
)
610 wxCHECK_MSG( is
, false, wxT("NULL stream in wxExecute()?") );
612 // the stream could be already at EOF or in wxSTREAM_BROKEN_PIPE state
615 wxTextInputStream
tis(*is
);
619 wxString line
= tis
.ReadLine();
621 // check for EOF before other errors as it's not really an error
624 // add the last, possibly incomplete, line
630 // any other error is fatal
639 #endif // wxUSE_STREAMS
641 // this is a private function because it hasn't a clean interface: the first
642 // array is passed by reference, the second by pointer - instead we have 2
643 // public versions of wxExecute() below
644 static long wxDoExecuteWithCapture(const wxString
& command
,
645 wxArrayString
& output
,
646 wxArrayString
* error
,
648 const wxExecuteEnv
*env
)
650 // create a wxProcess which will capture the output
651 wxProcess
*process
= new wxProcess
;
654 long rc
= wxExecute(command
, wxEXEC_SYNC
| flags
, process
, env
);
659 if ( !ReadAll(process
->GetInputStream(), output
) )
664 if ( !ReadAll(process
->GetErrorStream(), *error
) )
672 #endif // wxUSE_STREAMS/!wxUSE_STREAMS
679 long wxExecute(const wxString
& command
, wxArrayString
& output
, int flags
,
680 const wxExecuteEnv
*env
)
682 return wxDoExecuteWithCapture(command
, output
, NULL
, flags
, env
);
685 long wxExecute(const wxString
& command
,
686 wxArrayString
& output
,
687 wxArrayString
& error
,
689 const wxExecuteEnv
*env
)
691 return wxDoExecuteWithCapture(command
, output
, &error
, flags
, env
);
694 // ----------------------------------------------------------------------------
696 // ----------------------------------------------------------------------------
699 static long wxCurrentId
= 100;
703 // skip the part of IDs space that contains hard-coded values:
704 if (wxCurrentId
== wxID_LOWEST
)
705 wxCurrentId
= wxID_HIGHEST
+ 1;
707 return wxCurrentId
++;
711 wxGetCurrentId(void) { return wxCurrentId
; }
714 wxRegisterId (long id
)
716 if (id
>= wxCurrentId
)
717 wxCurrentId
= id
+ 1;
720 // ----------------------------------------------------------------------------
721 // wxQsort, adapted by RR to allow user_data
722 // ----------------------------------------------------------------------------
724 /* This file is part of the GNU C Library.
725 Written by Douglas C. Schmidt (schmidt@ics.uci.edu).
727 Douglas Schmidt kindly gave permission to relicence the
728 code under the wxWindows licence:
730 From: "Douglas C. Schmidt" <schmidt@dre.vanderbilt.edu>
731 To: Robert Roebling <robert.roebling@uni-ulm.de>
732 Subject: Re: qsort licence
733 Date: Mon, 23 Jul 2007 03:44:25 -0500
734 Sender: schmidt@dre.vanderbilt.edu
735 Message-Id: <20070723084426.64F511000A8@tango.dre.vanderbilt.edu>
739 > [...] I'm asking if you'd be willing to relicence your code
740 > under the wxWindows licence. [...]
742 That's fine with me [...]
749 /* Byte-wise swap two items of size SIZE. */
750 #define SWAP(a, b, size) \
753 register size_t __size = (size); \
754 register char *__a = (a), *__b = (b); \
760 } while (--__size > 0); \
763 /* Discontinue quicksort algorithm when partition gets below this size.
764 This particular magic number was chosen to work best on a Sun 4/260. */
767 /* Stack node declarations used to store unfulfilled partition obligations. */
774 /* The next 4 #defines implement a very fast in-line stack abstraction. */
775 #define STACK_SIZE (8 * sizeof(unsigned long int))
776 #define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top))
777 #define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi)))
778 #define STACK_NOT_EMPTY (stack < top)
781 /* Order size using quicksort. This implementation incorporates
782 four optimizations discussed in Sedgewick:
784 1. Non-recursive, using an explicit stack of pointer that store the
785 next array partition to sort. To save time, this maximum amount
786 of space required to store an array of MAX_INT is allocated on the
787 stack. Assuming a 32-bit integer, this needs only 32 *
788 sizeof(stack_node) == 136 bits. Pretty cheap, actually.
790 2. Chose the pivot element using a median-of-three decision tree.
791 This reduces the probability of selecting a bad pivot value and
792 eliminates certain extraneous comparisons.
794 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving
795 insertion sort to order the MAX_THRESH items within each partition.
796 This is a big win, since insertion sort is faster for small, mostly
797 sorted array segments.
799 4. The larger of the two sub-partitions is always pushed onto the
800 stack first, with the algorithm then concentrating on the
801 smaller partition. This *guarantees* no more than log (n)
802 stack size is needed (actually O(1) in this case)! */
804 void wxQsort(void *const pbase
, size_t total_elems
,
805 size_t size
, CMPFUNCDATA cmp
, const void* user_data
)
807 register char *base_ptr
= (char *) pbase
;
808 const size_t max_thresh
= MAX_THRESH
* size
;
810 if (total_elems
== 0)
811 /* Avoid lossage with unsigned arithmetic below. */
814 if (total_elems
> MAX_THRESH
)
817 char *hi
= &lo
[size
* (total_elems
- 1)];
818 stack_node stack
[STACK_SIZE
];
819 stack_node
*top
= stack
;
823 while (STACK_NOT_EMPTY
)
828 /* Select median value from among LO, MID, and HI. Rearrange
829 LO and HI so the three values are sorted. This lowers the
830 probability of picking a pathological pivot value and
831 skips a comparison for both the LEFT_PTR and RIGHT_PTR. */
833 char *mid
= lo
+ size
* ((hi
- lo
) / size
>> 1);
835 if ((*cmp
) ((void *) mid
, (void *) lo
, user_data
) < 0)
836 SWAP (mid
, lo
, size
);
837 if ((*cmp
) ((void *) hi
, (void *) mid
, user_data
) < 0)
838 SWAP (mid
, hi
, size
);
841 if ((*cmp
) ((void *) mid
, (void *) lo
, user_data
) < 0)
842 SWAP (mid
, lo
, size
);
844 left_ptr
= lo
+ size
;
845 right_ptr
= hi
- size
;
847 /* Here's the famous ``collapse the walls'' section of quicksort.
848 Gotta like those tight inner loops! They are the main reason
849 that this algorithm runs much faster than others. */
852 while ((*cmp
) ((void *) left_ptr
, (void *) mid
, user_data
) < 0)
855 while ((*cmp
) ((void *) mid
, (void *) right_ptr
, user_data
) < 0)
858 if (left_ptr
< right_ptr
)
860 SWAP (left_ptr
, right_ptr
, size
);
863 else if (mid
== right_ptr
)
868 else if (left_ptr
== right_ptr
)
875 while (left_ptr
<= right_ptr
);
877 /* Set up pointers for next iteration. First determine whether
878 left and right partitions are below the threshold size. If so,
879 ignore one or both. Otherwise, push the larger partition's
880 bounds on the stack and continue sorting the smaller one. */
882 if ((size_t) (right_ptr
- lo
) <= max_thresh
)
884 if ((size_t) (hi
- left_ptr
) <= max_thresh
)
885 /* Ignore both small partitions. */
888 /* Ignore small left partition. */
891 else if ((size_t) (hi
- left_ptr
) <= max_thresh
)
892 /* Ignore small right partition. */
894 else if ((right_ptr
- lo
) > (hi
- left_ptr
))
896 /* Push larger left partition indices. */
897 PUSH (lo
, right_ptr
);
902 /* Push larger right partition indices. */
909 /* Once the BASE_PTR array is partially sorted by quicksort the rest
910 is completely sorted using insertion sort, since this is efficient
911 for partitions below MAX_THRESH size. BASE_PTR points to the beginning
912 of the array to sort, and END_PTR points at the very last element in
913 the array (*not* one beyond it!). */
916 char *const end_ptr
= &base_ptr
[size
* (total_elems
- 1)];
917 char *tmp_ptr
= base_ptr
;
918 char *thresh
= base_ptr
+ max_thresh
;
919 if ( thresh
> end_ptr
)
921 register char *run_ptr
;
923 /* Find smallest element in first threshold and place it at the
924 array's beginning. This is the smallest array element,
925 and the operation speeds up insertion sort's inner loop. */
927 for (run_ptr
= tmp_ptr
+ size
; run_ptr
<= thresh
; run_ptr
+= size
)
928 if ((*cmp
) ((void *) run_ptr
, (void *) tmp_ptr
, user_data
) < 0)
931 if (tmp_ptr
!= base_ptr
)
932 SWAP (tmp_ptr
, base_ptr
, size
);
934 /* Insertion sort, running from left-hand-side up to right-hand-side. */
936 run_ptr
= base_ptr
+ size
;
937 while ((run_ptr
+= size
) <= end_ptr
)
939 tmp_ptr
= run_ptr
- size
;
940 while ((*cmp
) ((void *) run_ptr
, (void *) tmp_ptr
, user_data
) < 0)
944 if (tmp_ptr
!= run_ptr
)
948 trav
= run_ptr
+ size
;
949 while (--trav
>= run_ptr
)
954 for (hi
= lo
= trav
; (lo
-= size
) >= tmp_ptr
; hi
= lo
)
967 // ============================================================================
968 // GUI-only functions from now on
969 // ============================================================================
973 // this function is only really implemented for X11-based ports, including GTK1
974 // (GTK2 sets detectable auto-repeat automatically anyhow)
975 #if !(defined(__WXX11__) || defined(__WXMOTIF__) || \
976 (defined(__WXGTK__) && !defined(__WXGTK20__)))
977 bool wxSetDetectableAutoRepeat( bool WXUNUSED(flag
) )
981 #endif // !X11-based port
983 // ----------------------------------------------------------------------------
984 // Launch default browser
985 // ----------------------------------------------------------------------------
987 #if defined(__WXMSW__)
989 // implemented in a port-specific utils source file:
990 bool wxDoLaunchDefaultBrowser(const wxString
& url
, const wxString
& scheme
, int flags
);
992 #elif defined(__WXX11__) || defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXCOCOA__) || \
993 (defined(__WXOSX__) )
995 // implemented in a port-specific utils source file:
996 bool wxDoLaunchDefaultBrowser(const wxString
& url
, int flags
);
1000 // a "generic" implementation:
1001 bool wxDoLaunchDefaultBrowser(const wxString
& url
, int flags
)
1003 // on other platforms try to use mime types or wxExecute...
1009 wxFileType
*ft
= wxTheMimeTypesManager
->GetFileTypeFromExtension(wxT("html"));
1013 ft
->GetMimeType(&mt
);
1015 ok
= ft
->GetOpenCommand(&cmd
, wxFileType::MessageParameters(url
));
1018 #endif // wxUSE_MIMETYPE
1020 if ( !ok
|| cmd
.empty() )
1022 // fallback to checking for the BROWSER environment variable
1023 if ( !wxGetEnv(wxT("BROWSER"), &cmd
) || cmd
.empty() )
1024 cmd
<< wxT(' ') << url
;
1027 ok
= ( !cmd
.empty() && wxExecute(cmd
) );
1031 // no file type for HTML extension
1032 wxLogError(_("No default application configured for HTML files."));
1038 static bool DoLaunchDefaultBrowserHelper(const wxString
& urlOrig
, int flags
)
1040 // NOTE: we don't have to care about the wxBROWSER_NOBUSYCURSOR flag
1041 // as it was already handled by wxLaunchDefaultBrowser
1045 wxString
url(urlOrig
), scheme
;
1048 // this check is useful to avoid that wxURI recognizes as scheme parts of
1049 // the filename, in case urlOrig is a local filename
1050 // (e.g. "C:\\test.txt" when parsed by wxURI reports a scheme == "C")
1051 bool hasValidScheme
= uri
.HasScheme() && uri
.GetScheme().length() > 1;
1053 #if defined(__WXMSW__)
1055 // NOTE: when testing wxMSW's wxLaunchDefaultBrowser all possible forms
1056 // of the URL/flags should be tested; e.g.:
1058 // for (int i=0; i<2; i++)
1060 // // test arguments without a valid URL scheme:
1061 // wxLaunchDefaultBrowser("C:\\test.txt", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1062 // wxLaunchDefaultBrowser("wxwidgets.org", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1064 // // test arguments with different valid schemes:
1065 // wxLaunchDefaultBrowser("file:/C%3A/test.txt", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1066 // wxLaunchDefaultBrowser("http://wxwidgets.org", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1067 // wxLaunchDefaultBrowser("mailto:user@host.org", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1069 // (assuming you have a C:\test.txt file)
1071 if ( !hasValidScheme
)
1073 if (wxFileExists(urlOrig
) || wxDirExists(urlOrig
))
1076 // do not prepend the file scheme to the URL as ShellExecuteEx() doesn't like it
1080 url
.Prepend(wxS("http://"));
1084 else if ( hasValidScheme
)
1086 scheme
= uri
.GetScheme();
1088 if ( uri
.GetScheme() == "file" )
1090 // TODO: extract URLToFileName() to some always compiled in
1092 #if wxUSE_FILESYSTEM
1093 // ShellExecuteEx() doesn't like the "file" scheme when opening local files;
1095 url
= wxFileSystem::URLToFileName(url
).GetFullPath();
1096 #endif // wxUSE_FILESYSTEM
1100 if (wxDoLaunchDefaultBrowser(url
, scheme
, flags
))
1102 //else: call wxLogSysError
1104 if ( !hasValidScheme
)
1106 // set the scheme of url to "http" or "file" if it does not have one
1107 if (wxFileExists(urlOrig
) || wxDirExists(urlOrig
))
1108 url
.Prepend(wxS("file://"));
1110 url
.Prepend(wxS("http://"));
1113 if (wxDoLaunchDefaultBrowser(url
, flags
))
1115 //else: call wxLogSysError
1118 wxLogSysError(_("Failed to open URL \"%s\" in default browser."),
1124 bool wxLaunchDefaultBrowser(const wxString
& url
, int flags
)
1126 // NOTE: as documented, "url" may be both a real well-formed URL
1127 // and a local file name
1129 if ( flags
& wxBROWSER_NOBUSYCURSOR
)
1130 return DoLaunchDefaultBrowserHelper(url
, flags
);
1133 return DoLaunchDefaultBrowserHelper(url
, flags
);
1136 // ----------------------------------------------------------------------------
1137 // Menu accelerators related functions
1138 // ----------------------------------------------------------------------------
1140 #if WXWIN_COMPATIBILITY_2_6
1141 wxChar
*wxStripMenuCodes(const wxChar
*in
, wxChar
*out
)
1144 wxString s
= wxMenuItem::GetLabelText(in
);
1147 wxString s
= wxStripMenuCodes(str
);
1148 #endif // wxUSE_MENUS
1151 // go smash their buffer if it's not big enough - I love char * params
1152 memcpy(out
, s
.c_str(), s
.length() * sizeof(wxChar
));
1156 out
= new wxChar
[s
.length() + 1];
1157 wxStrcpy(out
, s
.c_str());
1164 wxString
wxStripMenuCodes(const wxString
& in
, int flags
)
1166 wxASSERT_MSG( flags
, wxT("this is useless to call without any flags") );
1170 size_t len
= in
.length();
1173 for ( size_t n
= 0; n
< len
; n
++ )
1176 if ( (flags
& wxStrip_Mnemonics
) && ch
== wxT('&') )
1178 // skip it, it is used to introduce the accel char (or to quote
1179 // itself in which case it should still be skipped): note that it
1180 // can't be the last character of the string
1183 wxLogDebug(wxT("Invalid menu string '%s'"), in
.c_str());
1187 // use the next char instead
1191 else if ( (flags
& wxStrip_Accel
) && ch
== wxT('\t') )
1193 // everything after TAB is accel string, exit the loop
1203 // ----------------------------------------------------------------------------
1204 // Window search functions
1205 // ----------------------------------------------------------------------------
1208 * If parent is non-NULL, look through children for a label or title
1209 * matching the specified string. If NULL, look through all top-level windows.
1214 wxFindWindowByLabel (const wxString
& title
, wxWindow
* parent
)
1216 return wxWindow::FindWindowByLabel( title
, parent
);
1221 * If parent is non-NULL, look through children for a name
1222 * matching the specified string. If NULL, look through all top-level windows.
1227 wxFindWindowByName (const wxString
& name
, wxWindow
* parent
)
1229 return wxWindow::FindWindowByName( name
, parent
);
1232 // Returns menu item id or wxNOT_FOUND if none.
1234 wxFindMenuItemId(wxFrame
*frame
,
1235 const wxString
& menuString
,
1236 const wxString
& itemString
)
1239 wxMenuBar
*menuBar
= frame
->GetMenuBar ();
1241 return menuBar
->FindMenuItem (menuString
, itemString
);
1242 #else // !wxUSE_MENUS
1244 wxUnusedVar(menuString
);
1245 wxUnusedVar(itemString
);
1246 #endif // wxUSE_MENUS/!wxUSE_MENUS
1251 // Try to find the deepest child that contains 'pt'.
1252 // We go backwards, to try to allow for controls that are spacially
1253 // within other controls, but are still siblings (e.g. buttons within
1254 // static boxes). Static boxes are likely to be created _before_ controls
1255 // that sit inside them.
1256 wxWindow
* wxFindWindowAtPoint(wxWindow
* win
, const wxPoint
& pt
)
1258 if (!win
->IsShown())
1261 // Hack for wxNotebook case: at least in wxGTK, all pages
1262 // claim to be shown, so we must only deal with the selected one.
1264 if (win
->IsKindOf(CLASSINFO(wxNotebook
)))
1266 wxNotebook
* nb
= (wxNotebook
*) win
;
1267 int sel
= nb
->GetSelection();
1270 wxWindow
* child
= nb
->GetPage(sel
);
1271 wxWindow
* foundWin
= wxFindWindowAtPoint(child
, pt
);
1278 wxWindowList::compatibility_iterator node
= win
->GetChildren().GetLast();
1281 wxWindow
* child
= node
->GetData();
1282 wxWindow
* foundWin
= wxFindWindowAtPoint(child
, pt
);
1285 node
= node
->GetPrevious();
1288 wxPoint pos
= win
->GetPosition();
1289 wxSize sz
= win
->GetSize();
1290 if ( !win
->IsTopLevel() && win
->GetParent() )
1292 pos
= win
->GetParent()->ClientToScreen(pos
);
1295 wxRect
rect(pos
, sz
);
1296 if (rect
.Contains(pt
))
1302 wxWindow
* wxGenericFindWindowAtPoint(const wxPoint
& pt
)
1304 // Go backwards through the list since windows
1305 // on top are likely to have been appended most
1307 wxWindowList::compatibility_iterator node
= wxTopLevelWindows
.GetLast();
1310 wxWindow
* win
= node
->GetData();
1311 wxWindow
* found
= wxFindWindowAtPoint(win
, pt
);
1314 node
= node
->GetPrevious();
1319 // ----------------------------------------------------------------------------
1321 // ----------------------------------------------------------------------------
1324 * N.B. these convenience functions must be separate from msgdlgg.cpp, textdlgg.cpp
1325 * since otherwise the generic code may be pulled in unnecessarily.
1330 int wxMessageBox(const wxString
& message
, const wxString
& caption
, long style
,
1331 wxWindow
*parent
, int WXUNUSED(x
), int WXUNUSED(y
) )
1333 // add the appropriate icon unless this was explicitly disabled by use of
1335 if ( !(style
& wxICON_NONE
) && !(style
& wxICON_MASK
) )
1337 style
|= style
& wxYES
? wxICON_QUESTION
: wxICON_INFORMATION
;
1340 wxMessageDialog
dialog(parent
, message
, caption
, style
);
1342 int ans
= dialog
.ShowModal();
1355 wxFAIL_MSG( wxT("unexpected return code from wxMessageDialog") );
1360 wxVersionInfo
wxGetLibraryVersionInfo()
1362 // don't translate these strings, they're for diagnostics purposes only
1364 msg
.Printf(wxS("wxWidgets Library (%s port)\n")
1365 wxS("Version %d.%d.%d (Unicode: %s, debug level: %d),\n")
1366 wxS("compiled at %s %s\n\n")
1367 wxS("Runtime version of toolkit used is %d.%d.\n"),
1368 wxPlatformInfo::Get().GetPortIdName(),
1372 #if wxUSE_UNICODE_UTF8
1382 wxPlatformInfo::Get().GetToolkitMajorVersion(),
1383 wxPlatformInfo::Get().GetToolkitMinorVersion()
1387 msg
+= wxString::Format("Compile-time GTK+ version is %d.%d.%d.\n",
1393 return wxVersionInfo(wxS("wxWidgets"),
1398 wxS("Copyright (c) 1995-2010 wxWidgets team"));
1401 void wxInfoMessageBox(wxWindow
* parent
)
1403 wxVersionInfo info
= wxGetLibraryVersionInfo();
1404 wxString msg
= info
.ToString();
1406 msg
<< wxS("\n") << info
.GetCopyright();
1408 wxMessageBox(msg
, wxT("wxWidgets information"),
1409 wxICON_INFORMATION
| wxOK
,
1413 #endif // wxUSE_MSGDLG
1417 wxString
wxGetTextFromUser(const wxString
& message
, const wxString
& caption
,
1418 const wxString
& defaultValue
, wxWindow
*parent
,
1419 wxCoord x
, wxCoord y
, bool centre
)
1422 long style
= wxTextEntryDialogStyle
;
1429 wxTextEntryDialog
dialog(parent
, message
, caption
, defaultValue
, style
, wxPoint(x
, y
));
1431 if (dialog
.ShowModal() == wxID_OK
)
1433 str
= dialog
.GetValue();
1439 wxString
wxGetPasswordFromUser(const wxString
& message
,
1440 const wxString
& caption
,
1441 const wxString
& defaultValue
,
1443 wxCoord x
, wxCoord y
, bool centre
)
1446 long style
= wxTextEntryDialogStyle
;
1453 wxPasswordEntryDialog
dialog(parent
, message
, caption
, defaultValue
,
1454 style
, wxPoint(x
, y
));
1455 if ( dialog
.ShowModal() == wxID_OK
)
1457 str
= dialog
.GetValue();
1463 #endif // wxUSE_TEXTDLG
1467 wxColour
wxGetColourFromUser(wxWindow
*parent
,
1468 const wxColour
& colInit
,
1469 const wxString
& caption
,
1470 wxColourData
*ptrData
)
1472 // contains serialized representation of wxColourData used the last time
1473 // the dialog was shown: we want to reuse it the next time in order to show
1474 // the same custom colours to the user (and we can't just have static
1475 // wxColourData itself because it's a GUI object and so should be destroyed
1476 // before GUI shutdown and doing it during static cleanup is too late)
1477 static wxString s_strColourData
;
1483 if ( !s_strColourData
.empty() )
1485 if ( !data
.FromString(s_strColourData
) )
1487 wxFAIL_MSG( "bug in wxColourData::FromString()?" );
1491 // we don't get back the "choose full" flag value from the native
1492 // dialog and so we can't preserve it between runs, so we decide to
1493 // always use it as it seems better than not using it (user can
1494 // just ignore the extra controls in the dialog but having to click
1495 // a button each time to show them would be very annoying
1496 data
.SetChooseFull(true);
1501 if ( colInit
.IsOk() )
1503 ptrData
->SetColour(colInit
);
1507 wxColourDialog
dialog(parent
, ptrData
);
1508 if (!caption
.empty())
1509 dialog
.SetTitle(caption
);
1510 if ( dialog
.ShowModal() == wxID_OK
)
1512 *ptrData
= dialog
.GetColourData();
1513 colRet
= ptrData
->GetColour();
1514 s_strColourData
= ptrData
->ToString();
1516 //else: leave colRet invalid
1521 #endif // wxUSE_COLOURDLG
1525 wxFont
wxGetFontFromUser(wxWindow
*parent
, const wxFont
& fontInit
, const wxString
& caption
)
1528 if ( fontInit
.Ok() )
1530 data
.SetInitialFont(fontInit
);
1534 wxFontDialog
dialog(parent
, data
);
1535 if (!caption
.empty())
1536 dialog
.SetTitle(caption
);
1537 if ( dialog
.ShowModal() == wxID_OK
)
1539 fontRet
= dialog
.GetFontData().GetChosenFont();
1541 //else: leave it invalid
1546 #endif // wxUSE_FONTDLG
1548 // ----------------------------------------------------------------------------
1549 // wxSafeYield and supporting functions
1550 // ----------------------------------------------------------------------------
1552 void wxEnableTopLevelWindows(bool enable
)
1554 wxWindowList::compatibility_iterator node
;
1555 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1556 node
->GetData()->Enable(enable
);
1559 wxWindowDisabler::wxWindowDisabler(bool disable
)
1561 m_disabled
= disable
;
1566 wxWindowDisabler::wxWindowDisabler(wxWindow
*winToSkip
)
1569 DoDisable(winToSkip
);
1572 void wxWindowDisabler::DoDisable(wxWindow
*winToSkip
)
1574 // remember the top level windows which were already disabled, so that we
1575 // don't reenable them later
1576 m_winDisabled
= NULL
;
1578 wxWindowList::compatibility_iterator node
;
1579 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1581 wxWindow
*winTop
= node
->GetData();
1582 if ( winTop
== winToSkip
)
1585 // we don't need to disable the hidden or already disabled windows
1586 if ( winTop
->IsEnabled() && winTop
->IsShown() )
1592 if ( !m_winDisabled
)
1594 m_winDisabled
= new wxWindowList
;
1597 m_winDisabled
->Append(winTop
);
1602 wxWindowDisabler::~wxWindowDisabler()
1607 wxWindowList::compatibility_iterator node
;
1608 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1610 wxWindow
*winTop
= node
->GetData();
1611 if ( !m_winDisabled
|| !m_winDisabled
->Find(winTop
) )
1615 //else: had been already disabled, don't reenable
1618 delete m_winDisabled
;
1621 // Yield to other apps/messages and disable user input to all windows except
1623 bool wxSafeYield(wxWindow
*win
, bool onlyIfNeeded
)
1625 wxWindowDisabler
wd(win
);
1629 rc
= wxYieldIfNeeded();
1636 // ----------------------------------------------------------------------------
1637 // wxApp::Yield() wrappers for backwards compatibility
1638 // ----------------------------------------------------------------------------
1642 return wxTheApp
&& wxTheApp
->Yield();
1645 bool wxYieldIfNeeded()
1647 return wxTheApp
&& wxTheApp
->Yield(true);