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
1059 err
= ICFindConfigFile(inst
, 0, NULL
);
1063 ConstStr255Param hint
= 0;
1065 endSel
= url
.length();
1066 err
= ICLaunchURL(inst
, hint
, url
.fn_str(), endSel
, &startSel
, &endSel
);
1068 wxLogDebug(wxT("ICLaunchURL error %d"), (int) err
);
1075 wxLogDebug(wxT("ICStart error %d"), (int) err
);
1079 // (non-Mac, non-MSW)
1083 wxString desktop
= wxTheApp
->GetTraits()->GetDesktopEnvironment();
1085 // GNOME and KDE desktops have some applications which should be always installed
1086 // together with their main parts, which give us the
1087 if (desktop
== wxT("GNOME"))
1089 wxArrayString errors
;
1090 wxArrayString output
;
1092 // gconf will tell us the path of the application to use as browser
1093 long res
= wxExecute( wxT("gconftool-2 --get /desktop/gnome/applications/browser/exec"),
1094 output
, errors
, wxEXEC_NODISABLE
);
1095 if (res
>= 0 && errors
.GetCount() == 0)
1097 wxString cmd
= output
[0];
1098 cmd
<< _T(' ') << url
;
1103 else if (desktop
== wxT("KDE"))
1105 // kfmclient directly opens the given URL
1106 if (wxExecute(wxT("kfmclient openURL ") + url
))
1115 wxFileType
*ft
= wxTheMimeTypesManager
->GetFileTypeFromExtension(_T("html"));
1119 ft
->GetMimeType(&mt
);
1121 ok
= ft
->GetOpenCommand(&cmd
, wxFileType::MessageParameters(url
));
1124 #endif // wxUSE_MIMETYPE
1126 if ( !ok
|| cmd
.empty() )
1128 // fallback to checking for the BROWSER environment variable
1129 cmd
= wxGetenv(wxT("BROWSER"));
1131 cmd
<< _T(' ') << url
;
1134 ok
= ( !cmd
.empty() && wxExecute(cmd
) );
1138 // no file type for HTML extension
1139 wxLogError(_T("No default application configured for HTML files."));
1141 #endif // !wxUSE_MIMETYPE && !__WXMSW__
1143 wxLogSysError(_T("Failed to open URL \"%s\" in default browser."),
1149 // ----------------------------------------------------------------------------
1150 // Menu accelerators related functions
1151 // ----------------------------------------------------------------------------
1153 wxChar
*wxStripMenuCodes(const wxChar
*in
, wxChar
*out
)
1156 wxString s
= wxMenuItem::GetLabelText(in
);
1159 wxString s
= wxStripMenuCodes(str
);
1160 #endif // wxUSE_MENUS
1163 // go smash their buffer if it's not big enough - I love char * params
1164 memcpy(out
, s
.c_str(), s
.length() * sizeof(wxChar
));
1168 out
= new wxChar
[s
.length() + 1];
1169 wxStrcpy(out
, s
.c_str());
1175 wxString
wxStripMenuCodes(const wxString
& in
, int flags
)
1177 wxASSERT_MSG( flags
, _T("this is useless to call without any flags") );
1181 size_t len
= in
.length();
1184 for ( size_t n
= 0; n
< len
; n
++ )
1187 if ( (flags
& wxStrip_Mnemonics
) && ch
== _T('&') )
1189 // skip it, it is used to introduce the accel char (or to quote
1190 // itself in which case it should still be skipped): note that it
1191 // can't be the last character of the string
1194 wxLogDebug(_T("Invalid menu string '%s'"), in
.c_str());
1198 // use the next char instead
1202 else if ( (flags
& wxStrip_Accel
) && ch
== _T('\t') )
1204 // everything after TAB is accel string, exit the loop
1214 // ----------------------------------------------------------------------------
1215 // Window search functions
1216 // ----------------------------------------------------------------------------
1219 * If parent is non-NULL, look through children for a label or title
1220 * matching the specified string. If NULL, look through all top-level windows.
1225 wxFindWindowByLabel (const wxString
& title
, wxWindow
* parent
)
1227 return wxWindow::FindWindowByLabel( title
, parent
);
1232 * If parent is non-NULL, look through children for a name
1233 * matching the specified string. If NULL, look through all top-level windows.
1238 wxFindWindowByName (const wxString
& name
, wxWindow
* parent
)
1240 return wxWindow::FindWindowByName( name
, parent
);
1243 // Returns menu item id or wxNOT_FOUND if none.
1245 wxFindMenuItemId(wxFrame
*frame
,
1246 const wxString
& menuString
,
1247 const wxString
& itemString
)
1250 wxMenuBar
*menuBar
= frame
->GetMenuBar ();
1252 return menuBar
->FindMenuItem (menuString
, itemString
);
1253 #else // !wxUSE_MENUS
1255 wxUnusedVar(menuString
);
1256 wxUnusedVar(itemString
);
1257 #endif // wxUSE_MENUS/!wxUSE_MENUS
1262 // Try to find the deepest child that contains 'pt'.
1263 // We go backwards, to try to allow for controls that are spacially
1264 // within other controls, but are still siblings (e.g. buttons within
1265 // static boxes). Static boxes are likely to be created _before_ controls
1266 // that sit inside them.
1267 wxWindow
* wxFindWindowAtPoint(wxWindow
* win
, const wxPoint
& pt
)
1269 if (!win
->IsShown())
1272 // Hack for wxNotebook case: at least in wxGTK, all pages
1273 // claim to be shown, so we must only deal with the selected one.
1275 if (win
->IsKindOf(CLASSINFO(wxNotebook
)))
1277 wxNotebook
* nb
= (wxNotebook
*) win
;
1278 int sel
= nb
->GetSelection();
1281 wxWindow
* child
= nb
->GetPage(sel
);
1282 wxWindow
* foundWin
= wxFindWindowAtPoint(child
, pt
);
1289 wxWindowList::compatibility_iterator node
= win
->GetChildren().GetLast();
1292 wxWindow
* child
= node
->GetData();
1293 wxWindow
* foundWin
= wxFindWindowAtPoint(child
, pt
);
1296 node
= node
->GetPrevious();
1299 wxPoint pos
= win
->GetPosition();
1300 wxSize sz
= win
->GetSize();
1301 if ( !win
->IsTopLevel() && win
->GetParent() )
1303 pos
= win
->GetParent()->ClientToScreen(pos
);
1306 wxRect
rect(pos
, sz
);
1307 if (rect
.Contains(pt
))
1313 wxWindow
* wxGenericFindWindowAtPoint(const wxPoint
& pt
)
1315 // Go backwards through the list since windows
1316 // on top are likely to have been appended most
1318 wxWindowList::compatibility_iterator node
= wxTopLevelWindows
.GetLast();
1321 wxWindow
* win
= node
->GetData();
1322 wxWindow
* found
= wxFindWindowAtPoint(win
, pt
);
1325 node
= node
->GetPrevious();
1330 // ----------------------------------------------------------------------------
1332 // ----------------------------------------------------------------------------
1335 * N.B. these convenience functions must be separate from msgdlgg.cpp, textdlgg.cpp
1336 * since otherwise the generic code may be pulled in unnecessarily.
1341 int wxMessageBox(const wxString
& message
, const wxString
& caption
, long style
,
1342 wxWindow
*parent
, int WXUNUSED(x
), int WXUNUSED(y
) )
1344 long decorated_style
= style
;
1346 if ( ( style
& ( wxICON_EXCLAMATION
| wxICON_HAND
| wxICON_INFORMATION
| wxICON_QUESTION
) ) == 0 )
1348 decorated_style
|= ( style
& wxYES
) ? wxICON_QUESTION
: wxICON_INFORMATION
;
1351 wxMessageDialog
dialog(parent
, message
, caption
, decorated_style
);
1353 int ans
= dialog
.ShowModal();
1366 wxFAIL_MSG( _T("unexpected return code from wxMessageDialog") );
1371 #endif // wxUSE_MSGDLG
1375 wxString
wxGetTextFromUser(const wxString
& message
, const wxString
& caption
,
1376 const wxString
& defaultValue
, wxWindow
*parent
,
1377 wxCoord x
, wxCoord y
, bool centre
)
1380 long style
= wxTextEntryDialogStyle
;
1387 wxTextEntryDialog
dialog(parent
, message
, caption
, defaultValue
, style
, wxPoint(x
, y
));
1389 if (dialog
.ShowModal() == wxID_OK
)
1391 str
= dialog
.GetValue();
1397 wxString
wxGetPasswordFromUser(const wxString
& message
,
1398 const wxString
& caption
,
1399 const wxString
& defaultValue
,
1401 wxCoord x
, wxCoord y
, bool centre
)
1404 long style
= wxTextEntryDialogStyle
;
1411 wxPasswordEntryDialog
dialog(parent
, message
, caption
, defaultValue
,
1412 style
, wxPoint(x
, y
));
1413 if ( dialog
.ShowModal() == wxID_OK
)
1415 str
= dialog
.GetValue();
1421 #endif // wxUSE_TEXTDLG
1425 wxColour
wxGetColourFromUser(wxWindow
*parent
, const wxColour
& colInit
, const wxString
& caption
)
1428 data
.SetChooseFull(true);
1431 data
.SetColour((wxColour
&)colInit
); // const_cast
1435 wxColourDialog
dialog(parent
, &data
);
1436 if (!caption
.empty())
1437 dialog
.SetTitle(caption
);
1438 if ( dialog
.ShowModal() == wxID_OK
)
1440 colRet
= dialog
.GetColourData().GetColour();
1442 //else: leave it invalid
1447 #endif // wxUSE_COLOURDLG
1451 wxFont
wxGetFontFromUser(wxWindow
*parent
, const wxFont
& fontInit
, const wxString
& caption
)
1454 if ( fontInit
.Ok() )
1456 data
.SetInitialFont(fontInit
);
1460 wxFontDialog
dialog(parent
, data
);
1461 if (!caption
.empty())
1462 dialog
.SetTitle(caption
);
1463 if ( dialog
.ShowModal() == wxID_OK
)
1465 fontRet
= dialog
.GetFontData().GetChosenFont();
1467 //else: leave it invalid
1472 #endif // wxUSE_FONTDLG
1474 // ----------------------------------------------------------------------------
1475 // wxSafeYield and supporting functions
1476 // ----------------------------------------------------------------------------
1478 void wxEnableTopLevelWindows(bool enable
)
1480 wxWindowList::compatibility_iterator node
;
1481 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1482 node
->GetData()->Enable(enable
);
1485 wxWindowDisabler::wxWindowDisabler(wxWindow
*winToSkip
)
1487 // remember the top level windows which were already disabled, so that we
1488 // don't reenable them later
1489 m_winDisabled
= NULL
;
1491 wxWindowList::compatibility_iterator node
;
1492 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1494 wxWindow
*winTop
= node
->GetData();
1495 if ( winTop
== winToSkip
)
1498 // we don't need to disable the hidden or already disabled windows
1499 if ( winTop
->IsEnabled() && winTop
->IsShown() )
1505 if ( !m_winDisabled
)
1507 m_winDisabled
= new wxWindowList
;
1510 m_winDisabled
->Append(winTop
);
1515 wxWindowDisabler::~wxWindowDisabler()
1517 wxWindowList::compatibility_iterator node
;
1518 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1520 wxWindow
*winTop
= node
->GetData();
1521 if ( !m_winDisabled
|| !m_winDisabled
->Find(winTop
) )
1525 //else: had been already disabled, don't reenable
1528 delete m_winDisabled
;
1531 // Yield to other apps/messages and disable user input to all windows except
1533 bool wxSafeYield(wxWindow
*win
, bool onlyIfNeeded
)
1535 wxWindowDisabler
wd(win
);
1539 rc
= wxYieldIfNeeded();
1546 // Don't synthesize KeyUp events holding down a key and producing KeyDown
1547 // events with autorepeat. On by default and always on in wxMSW. wxGTK version
1550 bool wxSetDetectableAutoRepeat( bool WXUNUSED(flag
) )
1552 return true; // detectable auto-repeat is the only mode MSW supports