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"
56 #if defined(__WXWINCE__) && wxUSE_DATETIME
57 #include "wx/datetime.h"
65 #if !wxONLY_WATCOM_EARLIER_THAN(1,4)
66 #if !(defined(_MSC_VER) && (_MSC_VER > 800))
72 #include "wx/colordlg.h"
73 #include "wx/fontdlg.h"
74 #include "wx/notebook.h"
75 #include "wx/statusbr.h"
81 #include "wx/msw/wince/time.h"
85 #include "wx/mac/private.h"
87 #include "InternetConfig.h"
91 #if !defined(__MWERKS__) && !defined(__WXWINCE__)
92 #include <sys/types.h>
96 #if defined(__WXMSW__)
97 #include "wx/msw/private.h"
98 #include "wx/msw/registry.h"
99 #include <shellapi.h> // needed for SHELLEXECUTEINFO
104 // ----------------------------------------------------------------------------
106 // ----------------------------------------------------------------------------
108 // ============================================================================
110 // ============================================================================
112 // Array used in DecToHex conversion routine.
113 static wxChar hexArray
[] = wxT("0123456789ABCDEF");
115 // Convert 2-digit hex number to decimal
116 int wxHexToDec(const wxString
& buf
)
118 int firstDigit
, secondDigit
;
120 if (buf
.GetChar(0) >= wxT('A'))
121 firstDigit
= buf
.GetChar(0) - wxT('A') + 10;
123 firstDigit
= buf
.GetChar(0) - wxT('0');
125 if (buf
.GetChar(1) >= wxT('A'))
126 secondDigit
= buf
.GetChar(1) - wxT('A') + 10;
128 secondDigit
= buf
.GetChar(1) - wxT('0');
130 return (firstDigit
& 0xF) * 16 + (secondDigit
& 0xF );
133 // Convert decimal integer to 2-character hex string
134 void wxDecToHex(int dec
, wxChar
*buf
)
136 int firstDigit
= (int)(dec
/16.0);
137 int secondDigit
= (int)(dec
- (firstDigit
*16.0));
138 buf
[0] = hexArray
[firstDigit
];
139 buf
[1] = hexArray
[secondDigit
];
143 // Convert decimal integer to 2 characters
144 void wxDecToHex(int dec
, char* ch1
, char* ch2
)
146 int firstDigit
= (int)(dec
/16.0);
147 int secondDigit
= (int)(dec
- (firstDigit
*16.0));
148 (*ch1
) = (char) hexArray
[firstDigit
];
149 (*ch2
) = (char) hexArray
[secondDigit
];
152 // Convert decimal integer to 2-character hex string
153 wxString
wxDecToHex(int dec
)
156 wxDecToHex(dec
, buf
);
157 return wxString(buf
);
160 // ----------------------------------------------------------------------------
162 // ----------------------------------------------------------------------------
164 // Return the current date/time
169 wxDateTime now
= wxDateTime::Now();
172 return wxEmptyString
;
175 time_t now
= time((time_t *) NULL
);
176 char *date
= ctime(&now
);
178 return wxString::FromAscii(date
);
182 void wxUsleep(unsigned long milliseconds
)
184 wxMilliSleep(milliseconds
);
187 const wxChar
*wxGetInstallPrefix()
191 if ( wxGetEnv(wxT("WXPREFIX"), &prefix
) )
192 return prefix
.c_str();
194 #ifdef wxINSTALL_PREFIX
195 return wxT(wxINSTALL_PREFIX
);
197 return wxEmptyString
;
201 wxString
wxGetDataDir()
203 wxString dir
= wxGetInstallPrefix();
204 dir
<< wxFILE_SEP_PATH
<< wxT("share") << wxFILE_SEP_PATH
<< wxT("wx");
208 bool wxIsPlatformLittleEndian()
210 // Are we little or big endian? This method is from Harbison & Steele.
214 char c
[sizeof(long)];
223 * Class to make it easier to specify platform-dependent values
226 wxArrayInt
* wxPlatform::sm_customPlatforms
= NULL
;
228 void wxPlatform::Copy(const wxPlatform
& platform
)
230 m_longValue
= platform
.m_longValue
;
231 m_doubleValue
= platform
.m_doubleValue
;
232 m_stringValue
= platform
.m_stringValue
;
235 wxPlatform
wxPlatform::If(int platform
, long value
)
238 return wxPlatform(value
);
243 wxPlatform
wxPlatform::IfNot(int platform
, long value
)
246 return wxPlatform(value
);
251 wxPlatform
& wxPlatform::ElseIf(int platform
, long value
)
258 wxPlatform
& wxPlatform::ElseIfNot(int platform
, long value
)
265 wxPlatform
wxPlatform::If(int platform
, double value
)
268 return wxPlatform(value
);
273 wxPlatform
wxPlatform::IfNot(int platform
, double value
)
276 return wxPlatform(value
);
281 wxPlatform
& wxPlatform::ElseIf(int platform
, double value
)
284 m_doubleValue
= value
;
288 wxPlatform
& wxPlatform::ElseIfNot(int platform
, double value
)
291 m_doubleValue
= value
;
295 wxPlatform
wxPlatform::If(int platform
, const wxString
& value
)
298 return wxPlatform(value
);
303 wxPlatform
wxPlatform::IfNot(int platform
, const wxString
& value
)
306 return wxPlatform(value
);
311 wxPlatform
& wxPlatform::ElseIf(int platform
, const wxString
& value
)
314 m_stringValue
= value
;
318 wxPlatform
& wxPlatform::ElseIfNot(int platform
, const wxString
& value
)
321 m_stringValue
= value
;
325 wxPlatform
& wxPlatform::Else(long value
)
331 wxPlatform
& wxPlatform::Else(double value
)
333 m_doubleValue
= value
;
337 wxPlatform
& wxPlatform::Else(const wxString
& value
)
339 m_stringValue
= value
;
343 void wxPlatform::AddPlatform(int platform
)
345 if (!sm_customPlatforms
)
346 sm_customPlatforms
= new wxArrayInt
;
347 sm_customPlatforms
->Add(platform
);
350 void wxPlatform::ClearPlatforms()
352 delete sm_customPlatforms
;
353 sm_customPlatforms
= NULL
;
356 /// Function for testing current platform
358 bool wxPlatform::Is(int platform
)
361 if (platform
== wxOS_WINDOWS
)
365 if (platform
== wxOS_WINDOWS_CE
)
371 // FIXME: wxWinPocketPC and wxWinSmartPhone are unknown symbols
373 #if defined(__WXWINCE__) && defined(__POCKETPC__)
374 if (platform
== wxWinPocketPC
)
377 #if defined(__WXWINCE__) && defined(__SMARTPHONE__)
378 if (platform
== wxWinSmartPhone
)
385 if (platform
== wxPORT_GTK
)
389 if (platform
== wxPORT_MAC
)
393 if (platform
== wxPORT_X11
)
397 if (platform
== wxOS_UNIX
)
401 if (platform
== wxPORT_MGL
)
405 if (platform
== wxOS_OS2
)
409 if (platform
== wxPORT_PM
)
413 if (platform
== wxPORT_MAC
)
417 if (sm_customPlatforms
&& sm_customPlatforms
->Index(platform
) != wxNOT_FOUND
)
423 // ----------------------------------------------------------------------------
424 // network and user id functions
425 // ----------------------------------------------------------------------------
427 // Get Full RFC822 style email address
428 bool wxGetEmailAddress(wxChar
*address
, int maxSize
)
430 wxString email
= wxGetEmailAddress();
434 wxStrncpy(address
, email
, maxSize
- 1);
435 address
[maxSize
- 1] = wxT('\0');
440 wxString
wxGetEmailAddress()
444 wxString host
= wxGetFullHostName();
447 wxString user
= wxGetUserId();
450 email
<< user
<< wxT('@') << host
;
457 wxString
wxGetUserId()
459 static const int maxLoginLen
= 256; // FIXME arbitrary number
462 bool ok
= wxGetUserId(wxStringBuffer(buf
, maxLoginLen
), maxLoginLen
);
470 wxString
wxGetUserName()
472 static const int maxUserNameLen
= 1024; // FIXME arbitrary number
475 bool ok
= wxGetUserName(wxStringBuffer(buf
, maxUserNameLen
), maxUserNameLen
);
483 wxString
wxGetHostName()
485 static const size_t hostnameSize
= 257;
488 bool ok
= wxGetHostName(wxStringBuffer(buf
, hostnameSize
), hostnameSize
);
496 wxString
wxGetFullHostName()
498 static const size_t hostnameSize
= 257;
501 bool ok
= wxGetFullHostName(wxStringBuffer(buf
, hostnameSize
), hostnameSize
);
509 wxString
wxGetHomeDir()
519 wxString
wxGetCurrentDir()
526 ok
= getcwd(dir
.GetWriteBuf(len
+ 1), len
) != NULL
;
531 if ( errno
!= ERANGE
)
533 wxLogSysError(_T("Failed to get current directory"));
535 return wxEmptyString
;
539 // buffer was too small, retry with a larger one
551 // ----------------------------------------------------------------------------
553 // ----------------------------------------------------------------------------
555 // wxDoExecuteWithCapture() helper: reads an entire stream into one array
557 // returns true if ok, false if error
559 static bool ReadAll(wxInputStream
*is
, wxArrayString
& output
)
561 wxCHECK_MSG( is
, false, _T("NULL stream in wxExecute()?") );
563 // the stream could be already at EOF or in wxSTREAM_BROKEN_PIPE state
566 wxTextInputStream
tis(*is
);
570 wxString line
= tis
.ReadLine();
572 // check for EOF before other errors as it's not really an error
575 // add the last, possibly incomplete, line
581 // any other error is fatal
590 #endif // wxUSE_STREAMS
592 // this is a private function because it hasn't a clean interface: the first
593 // array is passed by reference, the second by pointer - instead we have 2
594 // public versions of wxExecute() below
595 static long wxDoExecuteWithCapture(const wxString
& command
,
596 wxArrayString
& output
,
597 wxArrayString
* error
,
600 // create a wxProcess which will capture the output
601 wxProcess
*process
= new wxProcess
;
604 long rc
= wxExecute(command
, wxEXEC_SYNC
| flags
, process
);
609 if ( !ReadAll(process
->GetInputStream(), output
) )
614 if ( !ReadAll(process
->GetErrorStream(), *error
) )
622 #endif // wxUSE_STREAMS/!wxUSE_STREAMS
629 long wxExecute(const wxString
& command
, wxArrayString
& output
, int flags
)
631 return wxDoExecuteWithCapture(command
, output
, NULL
, flags
);
634 long wxExecute(const wxString
& command
,
635 wxArrayString
& output
,
636 wxArrayString
& error
,
639 return wxDoExecuteWithCapture(command
, output
, &error
, flags
);
642 // ----------------------------------------------------------------------------
643 // wxApp::Yield() wrappers for backwards compatibility
644 // ----------------------------------------------------------------------------
648 return wxTheApp
&& wxTheApp
->Yield();
651 bool wxYieldIfNeeded()
653 return wxTheApp
&& wxTheApp
->Yield(true);
657 static long wxCurrentId
= 100;
661 // skip the part of IDs space that contains hard-coded values:
662 if (wxCurrentId
== wxID_LOWEST
)
663 wxCurrentId
= wxID_HIGHEST
+ 1;
665 return wxCurrentId
++;
669 wxGetCurrentId(void) { return wxCurrentId
; }
672 wxRegisterId (long id
)
674 if (id
>= wxCurrentId
)
675 wxCurrentId
= id
+ 1;
678 // ----------------------------------------------------------------------------
679 // wxQsort, adapted by RR to allow user_data
680 // ----------------------------------------------------------------------------
682 /* This file is part of the GNU C Library.
683 Written by Douglas C. Schmidt (schmidt@ics.uci.edu).
685 Douglas Schmidt kindly gave permission to relicence the
686 code under the wxWindows licence:
688 From: "Douglas C. Schmidt" <schmidt@dre.vanderbilt.edu>
689 To: Robert Roebling <robert.roebling@uni-ulm.de>
690 Subject: Re: qsort licence
691 Date: Mon, 23 Jul 2007 03:44:25 -0500
692 Sender: schmidt@dre.vanderbilt.edu
693 Message-Id: <20070723084426.64F511000A8@tango.dre.vanderbilt.edu>
697 > [...] I'm asking if you'd be willing to relicence your code
698 > under the wxWindows licence. [...]
700 That's fine with me [...]
707 /* Byte-wise swap two items of size SIZE. */
708 #define SWAP(a, b, size) \
711 register size_t __size = (size); \
712 register char *__a = (a), *__b = (b); \
718 } while (--__size > 0); \
721 /* Discontinue quicksort algorithm when partition gets below this size.
722 This particular magic number was chosen to work best on a Sun 4/260. */
725 /* Stack node declarations used to store unfulfilled partition obligations. */
732 /* The next 4 #defines implement a very fast in-line stack abstraction. */
733 #define STACK_SIZE (8 * sizeof(unsigned long int))
734 #define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top))
735 #define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi)))
736 #define STACK_NOT_EMPTY (stack < top)
739 /* Order size using quicksort. This implementation incorporates
740 four optimizations discussed in Sedgewick:
742 1. Non-recursive, using an explicit stack of pointer that store the
743 next array partition to sort. To save time, this maximum amount
744 of space required to store an array of MAX_INT is allocated on the
745 stack. Assuming a 32-bit integer, this needs only 32 *
746 sizeof(stack_node) == 136 bits. Pretty cheap, actually.
748 2. Chose the pivot element using a median-of-three decision tree.
749 This reduces the probability of selecting a bad pivot value and
750 eliminates certain extraneous comparisons.
752 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving
753 insertion sort to order the MAX_THRESH items within each partition.
754 This is a big win, since insertion sort is faster for small, mostly
755 sorted array segments.
757 4. The larger of the two sub-partitions is always pushed onto the
758 stack first, with the algorithm then concentrating on the
759 smaller partition. This *guarantees* no more than log (n)
760 stack size is needed (actually O(1) in this case)! */
762 void wxQsort(void *const pbase
, size_t total_elems
,
763 size_t size
, CMPFUNCDATA cmp
, const void* user_data
)
765 register char *base_ptr
= (char *) pbase
;
766 const size_t max_thresh
= MAX_THRESH
* size
;
768 if (total_elems
== 0)
769 /* Avoid lossage with unsigned arithmetic below. */
772 if (total_elems
> MAX_THRESH
)
775 char *hi
= &lo
[size
* (total_elems
- 1)];
776 stack_node stack
[STACK_SIZE
];
777 stack_node
*top
= stack
;
781 while (STACK_NOT_EMPTY
)
786 /* Select median value from among LO, MID, and HI. Rearrange
787 LO and HI so the three values are sorted. This lowers the
788 probability of picking a pathological pivot value and
789 skips a comparison for both the LEFT_PTR and RIGHT_PTR. */
791 char *mid
= lo
+ size
* ((hi
- lo
) / size
>> 1);
793 if ((*cmp
) ((void *) mid
, (void *) lo
, user_data
) < 0)
794 SWAP (mid
, lo
, size
);
795 if ((*cmp
) ((void *) hi
, (void *) mid
, user_data
) < 0)
796 SWAP (mid
, hi
, size
);
799 if ((*cmp
) ((void *) mid
, (void *) lo
, user_data
) < 0)
800 SWAP (mid
, lo
, size
);
802 left_ptr
= lo
+ size
;
803 right_ptr
= hi
- size
;
805 /* Here's the famous ``collapse the walls'' section of quicksort.
806 Gotta like those tight inner loops! They are the main reason
807 that this algorithm runs much faster than others. */
810 while ((*cmp
) ((void *) left_ptr
, (void *) mid
, user_data
) < 0)
813 while ((*cmp
) ((void *) mid
, (void *) right_ptr
, user_data
) < 0)
816 if (left_ptr
< right_ptr
)
818 SWAP (left_ptr
, right_ptr
, size
);
821 else if (mid
== right_ptr
)
826 else if (left_ptr
== right_ptr
)
833 while (left_ptr
<= right_ptr
);
835 /* Set up pointers for next iteration. First determine whether
836 left and right partitions are below the threshold size. If so,
837 ignore one or both. Otherwise, push the larger partition's
838 bounds on the stack and continue sorting the smaller one. */
840 if ((size_t) (right_ptr
- lo
) <= max_thresh
)
842 if ((size_t) (hi
- left_ptr
) <= max_thresh
)
843 /* Ignore both small partitions. */
846 /* Ignore small left partition. */
849 else if ((size_t) (hi
- left_ptr
) <= max_thresh
)
850 /* Ignore small right partition. */
852 else if ((right_ptr
- lo
) > (hi
- left_ptr
))
854 /* Push larger left partition indices. */
855 PUSH (lo
, right_ptr
);
860 /* Push larger right partition indices. */
867 /* Once the BASE_PTR array is partially sorted by quicksort the rest
868 is completely sorted using insertion sort, since this is efficient
869 for partitions below MAX_THRESH size. BASE_PTR points to the beginning
870 of the array to sort, and END_PTR points at the very last element in
871 the array (*not* one beyond it!). */
874 char *const end_ptr
= &base_ptr
[size
* (total_elems
- 1)];
875 char *tmp_ptr
= base_ptr
;
876 char *thresh
= base_ptr
+ max_thresh
;
877 if ( thresh
> end_ptr
)
879 register char *run_ptr
;
881 /* Find smallest element in first threshold and place it at the
882 array's beginning. This is the smallest array element,
883 and the operation speeds up insertion sort's inner loop. */
885 for (run_ptr
= tmp_ptr
+ size
; run_ptr
<= thresh
; run_ptr
+= size
)
886 if ((*cmp
) ((void *) run_ptr
, (void *) tmp_ptr
, user_data
) < 0)
889 if (tmp_ptr
!= base_ptr
)
890 SWAP (tmp_ptr
, base_ptr
, size
);
892 /* Insertion sort, running from left-hand-side up to right-hand-side. */
894 run_ptr
= base_ptr
+ size
;
895 while ((run_ptr
+= size
) <= end_ptr
)
897 tmp_ptr
= run_ptr
- size
;
898 while ((*cmp
) ((void *) run_ptr
, (void *) tmp_ptr
, user_data
) < 0)
902 if (tmp_ptr
!= run_ptr
)
906 trav
= run_ptr
+ size
;
907 while (--trav
>= run_ptr
)
912 for (hi
= lo
= trav
; (lo
-= size
) >= tmp_ptr
; hi
= lo
)
925 // ============================================================================
926 // GUI-only functions from now on
927 // ============================================================================
931 // ----------------------------------------------------------------------------
932 // Launch default browser
933 // ----------------------------------------------------------------------------
936 // Private method in Objective-C++ source file.
937 bool wxCocoaLaunchDefaultBrowser(const wxString
& url
, int flags
);
940 bool wxLaunchDefaultBrowser(const wxString
& urlOrig
, int flags
)
944 // set the scheme of url to http if it does not have one
945 // RR: This doesn't work if the url is just a local path
946 wxString
url(urlOrig
);
948 if ( !uri
.HasScheme() )
950 if (wxFileExists(urlOrig
))
951 url
.Prepend( wxT("file://") );
953 url
.Prepend(wxT("http://"));
957 #if defined(__WXMSW__)
960 if ( flags
& wxBROWSER_NEW_WINDOW
)
962 // ShellExecuteEx() opens the URL in an existing window by default so
963 // we can't use it if we need a new window
964 wxRegKey
key(wxRegKey::HKCR
, uri
.GetScheme() + _T("\\shell\\open"));
967 // try default browser, it must be registered at least for http URLs
968 key
.SetName(wxRegKey::HKCR
, _T("http\\shell\\open"));
973 wxRegKey
keyDDE(key
, wxT("DDEExec"));
974 if ( keyDDE
.Exists() )
976 const wxString ddeTopic
= wxRegKey(keyDDE
, wxT("topic"));
978 // we only know the syntax of WWW_OpenURL DDE request for IE,
979 // optimistically assume that all other browsers are compatible
982 bool ok
= ddeTopic
== wxT("WWW_OpenURL");
985 ddeCmd
= keyDDE
.QueryDefaultValue();
986 ok
= !ddeCmd
.empty();
991 // for WWW_OpenURL, the index of the window to open the URL
992 // in is -1 (meaning "current") by default, replace it with
993 // 0 which means "new" (see KB article 160957)
994 ok
= ddeCmd
.Replace(wxT("-1"), wxT("0"),
995 false /* only first occurence */) == 1;
1000 // and also replace the parameters: the topic should
1001 // contain a placeholder for the URL
1002 ok
= ddeCmd
.Replace(wxT("%1"), url
, false) == 1;
1007 // try to send it the DDE request now but ignore the errors
1010 const wxString ddeServer
= wxRegKey(keyDDE
, wxT("application"));
1011 if ( wxExecuteDDE(ddeServer
, ddeTopic
, ddeCmd
) )
1014 // this is not necessarily an error: maybe browser is
1015 // simply not running, but no matter, in any case we're
1016 // going to launch it using ShellExecuteEx() below now and
1017 // we shouldn't try to open a new window if we open a new
1025 WinStruct
<SHELLEXECUTEINFO
> sei
;
1026 sei
.lpFile
= url
.c_str();
1027 sei
.lpVerb
= _T("open");
1028 sei
.nShow
= SW_SHOWNORMAL
;
1030 ::ShellExecuteEx(&sei
);
1032 const int nResult
= (int) sei
.hInstApp
;
1034 // Firefox returns file not found for some reason, so make an exception
1036 if ( nResult
> 32 || nResult
== SE_ERR_FNF
)
1039 // Log something if SE_ERR_FNF happens
1040 if ( nResult
== SE_ERR_FNF
)
1041 wxLogDebug(wxT("SE_ERR_FNF from ShellExecute -- maybe FireFox?"));
1042 #endif // __WXDEBUG__
1045 #elif defined(__WXCOCOA__)
1046 // NOTE: We need to call the real implementation from src/cocoa/utils.mm
1047 // because the code must use Objective-C features.
1048 return wxCocoaLaunchDefaultBrowser(url
, flags
);
1049 #elif defined(__WXMAC__)
1055 err
= ICStart(&inst
, 'STKA'); // put your app creator code here
1060 ConstStr255Param hint
= 0;
1062 endSel
= url
.length();
1063 err
= ICLaunchURL(inst
, hint
, url
.fn_str(), endSel
, &startSel
, &endSel
);
1065 wxLogDebug(wxT("ICLaunchURL error %d"), (int) err
);
1072 wxLogDebug(wxT("ICStart error %d"), (int) err
);
1076 // (non-Mac, non-MSW)
1080 wxString desktop
= wxTheApp
->GetTraits()->GetDesktopEnvironment();
1082 // GNOME and KDE desktops have some applications which should be always installed
1083 // together with their main parts, which give us the
1084 if (desktop
== wxT("GNOME"))
1086 wxArrayString errors
;
1087 wxArrayString output
;
1089 // gconf will tell us the path of the application to use as browser
1090 long res
= wxExecute( wxT("gconftool-2 --get /desktop/gnome/applications/browser/exec"),
1091 output
, errors
, wxEXEC_NODISABLE
);
1092 if (res
>= 0 && errors
.GetCount() == 0)
1094 wxString cmd
= output
[0];
1095 cmd
<< _T(' ') << url
;
1100 else if (desktop
== wxT("KDE"))
1102 // kfmclient directly opens the given URL
1103 if (wxExecute(wxT("kfmclient openURL ") + url
))
1112 wxFileType
*ft
= wxTheMimeTypesManager
->GetFileTypeFromExtension(_T("html"));
1116 ft
->GetMimeType(&mt
);
1118 ok
= ft
->GetOpenCommand(&cmd
, wxFileType::MessageParameters(url
));
1121 #endif // wxUSE_MIMETYPE
1123 if ( !ok
|| cmd
.empty() )
1125 // fallback to checking for the BROWSER environment variable
1126 cmd
= wxGetenv(wxT("BROWSER"));
1128 cmd
<< _T(' ') << url
;
1131 ok
= ( !cmd
.empty() && wxExecute(cmd
) );
1135 // no file type for HTML extension
1136 wxLogError(_T("No default application configured for HTML files."));
1138 #endif // !wxUSE_MIMETYPE && !__WXMSW__
1140 wxLogSysError(_T("Failed to open URL \"%s\" in default browser."),
1146 // ----------------------------------------------------------------------------
1147 // Menu accelerators related functions
1148 // ----------------------------------------------------------------------------
1150 wxChar
*wxStripMenuCodes(const wxChar
*in
, wxChar
*out
)
1153 wxString s
= wxMenuItem::GetLabelText(in
);
1156 wxString s
= wxStripMenuCodes(str
);
1157 #endif // wxUSE_MENUS
1160 // go smash their buffer if it's not big enough - I love char * params
1161 memcpy(out
, s
.c_str(), s
.length() * sizeof(wxChar
));
1165 out
= new wxChar
[s
.length() + 1];
1166 wxStrcpy(out
, s
.c_str());
1172 wxString
wxStripMenuCodes(const wxString
& in
, int flags
)
1174 wxASSERT_MSG( flags
, _T("this is useless to call without any flags") );
1178 size_t len
= in
.length();
1181 for ( size_t n
= 0; n
< len
; n
++ )
1184 if ( (flags
& wxStrip_Mnemonics
) && ch
== _T('&') )
1186 // skip it, it is used to introduce the accel char (or to quote
1187 // itself in which case it should still be skipped): note that it
1188 // can't be the last character of the string
1191 wxLogDebug(_T("Invalid menu string '%s'"), in
.c_str());
1195 // use the next char instead
1199 else if ( (flags
& wxStrip_Accel
) && ch
== _T('\t') )
1201 // everything after TAB is accel string, exit the loop
1211 // ----------------------------------------------------------------------------
1212 // Window search functions
1213 // ----------------------------------------------------------------------------
1216 * If parent is non-NULL, look through children for a label or title
1217 * matching the specified string. If NULL, look through all top-level windows.
1222 wxFindWindowByLabel (const wxString
& title
, wxWindow
* parent
)
1224 return wxWindow::FindWindowByLabel( title
, parent
);
1229 * If parent is non-NULL, look through children for a name
1230 * matching the specified string. If NULL, look through all top-level windows.
1235 wxFindWindowByName (const wxString
& name
, wxWindow
* parent
)
1237 return wxWindow::FindWindowByName( name
, parent
);
1240 // Returns menu item id or wxNOT_FOUND if none.
1242 wxFindMenuItemId(wxFrame
*frame
,
1243 const wxString
& menuString
,
1244 const wxString
& itemString
)
1247 wxMenuBar
*menuBar
= frame
->GetMenuBar ();
1249 return menuBar
->FindMenuItem (menuString
, itemString
);
1250 #else // !wxUSE_MENUS
1252 wxUnusedVar(menuString
);
1253 wxUnusedVar(itemString
);
1254 #endif // wxUSE_MENUS/!wxUSE_MENUS
1259 // Try to find the deepest child that contains 'pt'.
1260 // We go backwards, to try to allow for controls that are spacially
1261 // within other controls, but are still siblings (e.g. buttons within
1262 // static boxes). Static boxes are likely to be created _before_ controls
1263 // that sit inside them.
1264 wxWindow
* wxFindWindowAtPoint(wxWindow
* win
, const wxPoint
& pt
)
1266 if (!win
->IsShown())
1269 // Hack for wxNotebook case: at least in wxGTK, all pages
1270 // claim to be shown, so we must only deal with the selected one.
1272 if (win
->IsKindOf(CLASSINFO(wxNotebook
)))
1274 wxNotebook
* nb
= (wxNotebook
*) win
;
1275 int sel
= nb
->GetSelection();
1278 wxWindow
* child
= nb
->GetPage(sel
);
1279 wxWindow
* foundWin
= wxFindWindowAtPoint(child
, pt
);
1286 wxWindowList::compatibility_iterator node
= win
->GetChildren().GetLast();
1289 wxWindow
* child
= node
->GetData();
1290 wxWindow
* foundWin
= wxFindWindowAtPoint(child
, pt
);
1293 node
= node
->GetPrevious();
1296 wxPoint pos
= win
->GetPosition();
1297 wxSize sz
= win
->GetSize();
1298 if ( !win
->IsTopLevel() && win
->GetParent() )
1300 pos
= win
->GetParent()->ClientToScreen(pos
);
1303 wxRect
rect(pos
, sz
);
1304 if (rect
.Contains(pt
))
1310 wxWindow
* wxGenericFindWindowAtPoint(const wxPoint
& pt
)
1312 // Go backwards through the list since windows
1313 // on top are likely to have been appended most
1315 wxWindowList::compatibility_iterator node
= wxTopLevelWindows
.GetLast();
1318 wxWindow
* win
= node
->GetData();
1319 wxWindow
* found
= wxFindWindowAtPoint(win
, pt
);
1322 node
= node
->GetPrevious();
1327 // ----------------------------------------------------------------------------
1329 // ----------------------------------------------------------------------------
1332 * N.B. these convenience functions must be separate from msgdlgg.cpp, textdlgg.cpp
1333 * since otherwise the generic code may be pulled in unnecessarily.
1338 int wxMessageBox(const wxString
& message
, const wxString
& caption
, long style
,
1339 wxWindow
*parent
, int WXUNUSED(x
), int WXUNUSED(y
) )
1341 long decorated_style
= style
;
1343 if ( ( style
& ( wxICON_EXCLAMATION
| wxICON_HAND
| wxICON_INFORMATION
| wxICON_QUESTION
) ) == 0 )
1345 decorated_style
|= ( style
& wxYES
) ? wxICON_QUESTION
: wxICON_INFORMATION
;
1348 wxMessageDialog
dialog(parent
, message
, caption
, decorated_style
);
1350 int ans
= dialog
.ShowModal();
1363 wxFAIL_MSG( _T("unexpected return code from wxMessageDialog") );
1368 #endif // wxUSE_MSGDLG
1372 wxString
wxGetTextFromUser(const wxString
& message
, const wxString
& caption
,
1373 const wxString
& defaultValue
, wxWindow
*parent
,
1374 wxCoord x
, wxCoord y
, bool centre
)
1377 long style
= wxTextEntryDialogStyle
;
1384 wxTextEntryDialog
dialog(parent
, message
, caption
, defaultValue
, style
, wxPoint(x
, y
));
1386 if (dialog
.ShowModal() == wxID_OK
)
1388 str
= dialog
.GetValue();
1394 wxString
wxGetPasswordFromUser(const wxString
& message
,
1395 const wxString
& caption
,
1396 const wxString
& defaultValue
,
1398 wxCoord x
, wxCoord y
, bool centre
)
1401 long style
= wxTextEntryDialogStyle
;
1408 wxPasswordEntryDialog
dialog(parent
, message
, caption
, defaultValue
,
1409 style
, wxPoint(x
, y
));
1410 if ( dialog
.ShowModal() == wxID_OK
)
1412 str
= dialog
.GetValue();
1418 #endif // wxUSE_TEXTDLG
1422 wxColour
wxGetColourFromUser(wxWindow
*parent
, const wxColour
& colInit
, const wxString
& caption
)
1425 data
.SetChooseFull(true);
1428 data
.SetColour((wxColour
&)colInit
); // const_cast
1432 wxColourDialog
dialog(parent
, &data
);
1433 if (!caption
.empty())
1434 dialog
.SetTitle(caption
);
1435 if ( dialog
.ShowModal() == wxID_OK
)
1437 colRet
= dialog
.GetColourData().GetColour();
1439 //else: leave it invalid
1444 #endif // wxUSE_COLOURDLG
1448 wxFont
wxGetFontFromUser(wxWindow
*parent
, const wxFont
& fontInit
, const wxString
& caption
)
1451 if ( fontInit
.Ok() )
1453 data
.SetInitialFont(fontInit
);
1457 wxFontDialog
dialog(parent
, data
);
1458 if (!caption
.empty())
1459 dialog
.SetTitle(caption
);
1460 if ( dialog
.ShowModal() == wxID_OK
)
1462 fontRet
= dialog
.GetFontData().GetChosenFont();
1464 //else: leave it invalid
1469 #endif // wxUSE_FONTDLG
1471 // ----------------------------------------------------------------------------
1472 // wxSafeYield and supporting functions
1473 // ----------------------------------------------------------------------------
1475 void wxEnableTopLevelWindows(bool enable
)
1477 wxWindowList::compatibility_iterator node
;
1478 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1479 node
->GetData()->Enable(enable
);
1482 wxWindowDisabler::wxWindowDisabler(wxWindow
*winToSkip
)
1484 // remember the top level windows which were already disabled, so that we
1485 // don't reenable them later
1486 m_winDisabled
= NULL
;
1488 wxWindowList::compatibility_iterator node
;
1489 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1491 wxWindow
*winTop
= node
->GetData();
1492 if ( winTop
== winToSkip
)
1495 // we don't need to disable the hidden or already disabled windows
1496 if ( winTop
->IsEnabled() && winTop
->IsShown() )
1502 if ( !m_winDisabled
)
1504 m_winDisabled
= new wxWindowList
;
1507 m_winDisabled
->Append(winTop
);
1512 wxWindowDisabler::~wxWindowDisabler()
1514 wxWindowList::compatibility_iterator node
;
1515 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1517 wxWindow
*winTop
= node
->GetData();
1518 if ( !m_winDisabled
|| !m_winDisabled
->Find(winTop
) )
1522 //else: had been already disabled, don't reenable
1525 delete m_winDisabled
;
1528 // Yield to other apps/messages and disable user input to all windows except
1530 bool wxSafeYield(wxWindow
*win
, bool onlyIfNeeded
)
1532 wxWindowDisabler
wd(win
);
1536 rc
= wxYieldIfNeeded();
1543 // Don't synthesize KeyUp events holding down a key and producing KeyDown
1544 // events with autorepeat. On by default and always on in wxMSW. wxGTK version
1547 bool wxSetDetectableAutoRepeat( bool WXUNUSED(flag
) )
1549 return true; // detectable auto-repeat is the only mode MSW supports