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"
82 #include "wx/msw/wince/time.h"
84 #endif // ! __WXPALMOS5__
87 #include "wx/osx/private.h"
91 #if !defined(__MWERKS__) && !defined(__WXWINCE__)
92 #include <sys/types.h>
95 #endif // ! __WXPALMOS5__
97 #if defined(__WXMSW__)
98 #include "wx/msw/private.h"
99 #include "wx/msw/registry.h"
100 #include <shellapi.h> // needed for SHELLEXECUTEINFO
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 wxChar hexArray
[] = wxT("0123456789ABCDEF");
116 // Convert 2-digit hex number to decimal
117 int wxHexToDec(const wxString
& buf
)
119 int firstDigit
, secondDigit
;
121 if (buf
.GetChar(0) >= wxT('A'))
122 firstDigit
= buf
.GetChar(0) - wxT('A') + 10;
124 firstDigit
= buf
.GetChar(0) - wxT('0');
126 if (buf
.GetChar(1) >= wxT('A'))
127 secondDigit
= buf
.GetChar(1) - wxT('A') + 10;
129 secondDigit
= buf
.GetChar(1) - wxT('0');
131 return (firstDigit
& 0xF) * 16 + (secondDigit
& 0xF );
134 // Convert decimal integer to 2-character hex string
135 void wxDecToHex(int dec
, wxChar
*buf
)
137 int firstDigit
= (int)(dec
/16.0);
138 int secondDigit
= (int)(dec
- (firstDigit
*16.0));
139 buf
[0] = hexArray
[firstDigit
];
140 buf
[1] = hexArray
[secondDigit
];
144 // Convert decimal integer to 2 characters
145 void wxDecToHex(int dec
, char* ch1
, char* ch2
)
147 int firstDigit
= (int)(dec
/16.0);
148 int secondDigit
= (int)(dec
- (firstDigit
*16.0));
149 (*ch1
) = (char) hexArray
[firstDigit
];
150 (*ch2
) = (char) hexArray
[secondDigit
];
153 // Convert decimal integer to 2-character hex string
154 wxString
wxDecToHex(int dec
)
157 wxDecToHex(dec
, buf
);
158 return wxString(buf
);
161 // ----------------------------------------------------------------------------
163 // ----------------------------------------------------------------------------
165 // Don't synthesize KeyUp events holding down a key and producing KeyDown
166 // events with autorepeat. On by default and always on in wxMSW. wxGTK version
169 bool wxSetDetectableAutoRepeat( bool WXUNUSED(flag
) )
171 return true; // detectable auto-repeat is the only mode MSW supports
175 // Return the current date/time
180 wxDateTime now
= wxDateTime::Now();
183 return wxEmptyString
;
186 time_t now
= time((time_t *) NULL
);
187 char *date
= ctime(&now
);
189 return wxString::FromAscii(date
);
193 #if WXWIN_COMPATIBILITY_2_6
194 void wxUsleep(unsigned long milliseconds
)
196 wxMilliSleep(milliseconds
);
200 const wxChar
*wxGetInstallPrefix()
204 if ( wxGetEnv(wxT("WXPREFIX"), &prefix
) )
205 return prefix
.c_str();
207 #ifdef wxINSTALL_PREFIX
208 return wxT(wxINSTALL_PREFIX
);
210 return wxEmptyString
;
214 wxString
wxGetDataDir()
216 wxString dir
= wxGetInstallPrefix();
217 dir
<< wxFILE_SEP_PATH
<< wxT("share") << wxFILE_SEP_PATH
<< wxT("wx");
221 bool wxIsPlatformLittleEndian()
223 // Are we little or big endian? This method is from Harbison & Steele.
227 char c
[sizeof(long)];
235 // ----------------------------------------------------------------------------
237 // ----------------------------------------------------------------------------
240 * Class to make it easier to specify platform-dependent values
243 wxArrayInt
* wxPlatform::sm_customPlatforms
= NULL
;
245 void wxPlatform::Copy(const wxPlatform
& platform
)
247 m_longValue
= platform
.m_longValue
;
248 m_doubleValue
= platform
.m_doubleValue
;
249 m_stringValue
= platform
.m_stringValue
;
252 wxPlatform
wxPlatform::If(int platform
, long value
)
255 return wxPlatform(value
);
260 wxPlatform
wxPlatform::IfNot(int platform
, long value
)
263 return wxPlatform(value
);
268 wxPlatform
& wxPlatform::ElseIf(int platform
, long value
)
275 wxPlatform
& wxPlatform::ElseIfNot(int platform
, long value
)
282 wxPlatform
wxPlatform::If(int platform
, double value
)
285 return wxPlatform(value
);
290 wxPlatform
wxPlatform::IfNot(int platform
, double value
)
293 return wxPlatform(value
);
298 wxPlatform
& wxPlatform::ElseIf(int platform
, double value
)
301 m_doubleValue
= value
;
305 wxPlatform
& wxPlatform::ElseIfNot(int platform
, double value
)
308 m_doubleValue
= value
;
312 wxPlatform
wxPlatform::If(int platform
, const wxString
& value
)
315 return wxPlatform(value
);
320 wxPlatform
wxPlatform::IfNot(int platform
, const wxString
& value
)
323 return wxPlatform(value
);
328 wxPlatform
& wxPlatform::ElseIf(int platform
, const wxString
& value
)
331 m_stringValue
= value
;
335 wxPlatform
& wxPlatform::ElseIfNot(int platform
, const wxString
& value
)
338 m_stringValue
= value
;
342 wxPlatform
& wxPlatform::Else(long value
)
348 wxPlatform
& wxPlatform::Else(double value
)
350 m_doubleValue
= value
;
354 wxPlatform
& wxPlatform::Else(const wxString
& value
)
356 m_stringValue
= value
;
360 void wxPlatform::AddPlatform(int platform
)
362 if (!sm_customPlatforms
)
363 sm_customPlatforms
= new wxArrayInt
;
364 sm_customPlatforms
->Add(platform
);
367 void wxPlatform::ClearPlatforms()
369 delete sm_customPlatforms
;
370 sm_customPlatforms
= NULL
;
373 /// Function for testing current platform
375 bool wxPlatform::Is(int platform
)
378 if (platform
== wxOS_WINDOWS
)
382 if (platform
== wxOS_WINDOWS_CE
)
388 // FIXME: wxWinPocketPC and wxWinSmartPhone are unknown symbols
390 #if defined(__WXWINCE__) && defined(__POCKETPC__)
391 if (platform
== wxWinPocketPC
)
394 #if defined(__WXWINCE__) && defined(__SMARTPHONE__)
395 if (platform
== wxWinSmartPhone
)
402 if (platform
== wxPORT_GTK
)
406 if (platform
== wxPORT_MAC
)
410 if (platform
== wxPORT_X11
)
414 if (platform
== wxOS_UNIX
)
418 if (platform
== wxPORT_MGL
)
422 if (platform
== wxOS_OS2
)
426 if (platform
== wxPORT_PM
)
430 if (platform
== wxPORT_MAC
)
434 if (sm_customPlatforms
&& sm_customPlatforms
->Index(platform
) != wxNOT_FOUND
)
440 // ----------------------------------------------------------------------------
441 // network and user id functions
442 // ----------------------------------------------------------------------------
444 // Get Full RFC822 style email address
445 bool wxGetEmailAddress(wxChar
*address
, int maxSize
)
447 wxString email
= wxGetEmailAddress();
451 wxStrlcpy(address
, email
.t_str(), maxSize
);
456 wxString
wxGetEmailAddress()
460 wxString host
= wxGetFullHostName();
463 wxString user
= wxGetUserId();
466 email
<< user
<< wxT('@') << host
;
473 wxString
wxGetUserId()
475 static const int maxLoginLen
= 256; // FIXME arbitrary number
478 bool ok
= wxGetUserId(wxStringBuffer(buf
, maxLoginLen
), maxLoginLen
);
486 wxString
wxGetUserName()
488 static const int maxUserNameLen
= 1024; // FIXME arbitrary number
491 bool ok
= wxGetUserName(wxStringBuffer(buf
, maxUserNameLen
), maxUserNameLen
);
499 wxString
wxGetHostName()
501 static const size_t hostnameSize
= 257;
504 bool ok
= wxGetHostName(wxStringBuffer(buf
, hostnameSize
), hostnameSize
);
512 wxString
wxGetFullHostName()
514 static const size_t hostnameSize
= 257;
517 bool ok
= wxGetFullHostName(wxStringBuffer(buf
, hostnameSize
), hostnameSize
);
525 wxString
wxGetHomeDir()
535 wxString
wxGetCurrentDir()
542 ok
= getcwd(dir
.GetWriteBuf(len
+ 1), len
) != NULL
;
547 if ( errno
!= ERANGE
)
549 wxLogSysError(_T("Failed to get current directory"));
551 return wxEmptyString
;
555 // buffer was too small, retry with a larger one
567 // ----------------------------------------------------------------------------
569 // ----------------------------------------------------------------------------
571 // wxDoExecuteWithCapture() helper: reads an entire stream into one array
573 // returns true if ok, false if error
575 static bool ReadAll(wxInputStream
*is
, wxArrayString
& output
)
577 wxCHECK_MSG( is
, false, _T("NULL stream in wxExecute()?") );
579 // the stream could be already at EOF or in wxSTREAM_BROKEN_PIPE state
582 wxTextInputStream
tis(*is
);
586 wxString line
= tis
.ReadLine();
588 // check for EOF before other errors as it's not really an error
591 // add the last, possibly incomplete, line
597 // any other error is fatal
606 #endif // wxUSE_STREAMS
608 // this is a private function because it hasn't a clean interface: the first
609 // array is passed by reference, the second by pointer - instead we have 2
610 // public versions of wxExecute() below
611 static long wxDoExecuteWithCapture(const wxString
& command
,
612 wxArrayString
& output
,
613 wxArrayString
* error
,
616 // create a wxProcess which will capture the output
617 wxProcess
*process
= new wxProcess
;
620 long rc
= wxExecute(command
, wxEXEC_SYNC
| flags
, process
);
625 if ( !ReadAll(process
->GetInputStream(), output
) )
630 if ( !ReadAll(process
->GetErrorStream(), *error
) )
638 #endif // wxUSE_STREAMS/!wxUSE_STREAMS
645 long wxExecute(const wxString
& command
, wxArrayString
& output
, int flags
)
647 return wxDoExecuteWithCapture(command
, output
, NULL
, flags
);
650 long wxExecute(const wxString
& command
,
651 wxArrayString
& output
,
652 wxArrayString
& error
,
655 return wxDoExecuteWithCapture(command
, output
, &error
, flags
);
658 // ----------------------------------------------------------------------------
660 // ----------------------------------------------------------------------------
663 static long wxCurrentId
= 100;
667 // skip the part of IDs space that contains hard-coded values:
668 if (wxCurrentId
== wxID_LOWEST
)
669 wxCurrentId
= wxID_HIGHEST
+ 1;
671 return wxCurrentId
++;
675 wxGetCurrentId(void) { return wxCurrentId
; }
678 wxRegisterId (long id
)
680 if (id
>= wxCurrentId
)
681 wxCurrentId
= id
+ 1;
684 // ----------------------------------------------------------------------------
685 // wxQsort, adapted by RR to allow user_data
686 // ----------------------------------------------------------------------------
688 /* This file is part of the GNU C Library.
689 Written by Douglas C. Schmidt (schmidt@ics.uci.edu).
691 Douglas Schmidt kindly gave permission to relicence the
692 code under the wxWindows licence:
694 From: "Douglas C. Schmidt" <schmidt@dre.vanderbilt.edu>
695 To: Robert Roebling <robert.roebling@uni-ulm.de>
696 Subject: Re: qsort licence
697 Date: Mon, 23 Jul 2007 03:44:25 -0500
698 Sender: schmidt@dre.vanderbilt.edu
699 Message-Id: <20070723084426.64F511000A8@tango.dre.vanderbilt.edu>
703 > [...] I'm asking if you'd be willing to relicence your code
704 > under the wxWindows licence. [...]
706 That's fine with me [...]
713 /* Byte-wise swap two items of size SIZE. */
714 #define SWAP(a, b, size) \
717 register size_t __size = (size); \
718 register char *__a = (a), *__b = (b); \
724 } while (--__size > 0); \
727 /* Discontinue quicksort algorithm when partition gets below this size.
728 This particular magic number was chosen to work best on a Sun 4/260. */
731 /* Stack node declarations used to store unfulfilled partition obligations. */
738 /* The next 4 #defines implement a very fast in-line stack abstraction. */
739 #define STACK_SIZE (8 * sizeof(unsigned long int))
740 #define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top))
741 #define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi)))
742 #define STACK_NOT_EMPTY (stack < top)
745 /* Order size using quicksort. This implementation incorporates
746 four optimizations discussed in Sedgewick:
748 1. Non-recursive, using an explicit stack of pointer that store the
749 next array partition to sort. To save time, this maximum amount
750 of space required to store an array of MAX_INT is allocated on the
751 stack. Assuming a 32-bit integer, this needs only 32 *
752 sizeof(stack_node) == 136 bits. Pretty cheap, actually.
754 2. Chose the pivot element using a median-of-three decision tree.
755 This reduces the probability of selecting a bad pivot value and
756 eliminates certain extraneous comparisons.
758 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving
759 insertion sort to order the MAX_THRESH items within each partition.
760 This is a big win, since insertion sort is faster for small, mostly
761 sorted array segments.
763 4. The larger of the two sub-partitions is always pushed onto the
764 stack first, with the algorithm then concentrating on the
765 smaller partition. This *guarantees* no more than log (n)
766 stack size is needed (actually O(1) in this case)! */
768 void wxQsort(void *const pbase
, size_t total_elems
,
769 size_t size
, CMPFUNCDATA cmp
, const void* user_data
)
771 register char *base_ptr
= (char *) pbase
;
772 const size_t max_thresh
= MAX_THRESH
* size
;
774 if (total_elems
== 0)
775 /* Avoid lossage with unsigned arithmetic below. */
778 if (total_elems
> MAX_THRESH
)
781 char *hi
= &lo
[size
* (total_elems
- 1)];
782 stack_node stack
[STACK_SIZE
];
783 stack_node
*top
= stack
;
787 while (STACK_NOT_EMPTY
)
792 /* Select median value from among LO, MID, and HI. Rearrange
793 LO and HI so the three values are sorted. This lowers the
794 probability of picking a pathological pivot value and
795 skips a comparison for both the LEFT_PTR and RIGHT_PTR. */
797 char *mid
= lo
+ size
* ((hi
- lo
) / size
>> 1);
799 if ((*cmp
) ((void *) mid
, (void *) lo
, user_data
) < 0)
800 SWAP (mid
, lo
, size
);
801 if ((*cmp
) ((void *) hi
, (void *) mid
, user_data
) < 0)
802 SWAP (mid
, hi
, size
);
805 if ((*cmp
) ((void *) mid
, (void *) lo
, user_data
) < 0)
806 SWAP (mid
, lo
, size
);
808 left_ptr
= lo
+ size
;
809 right_ptr
= hi
- size
;
811 /* Here's the famous ``collapse the walls'' section of quicksort.
812 Gotta like those tight inner loops! They are the main reason
813 that this algorithm runs much faster than others. */
816 while ((*cmp
) ((void *) left_ptr
, (void *) mid
, user_data
) < 0)
819 while ((*cmp
) ((void *) mid
, (void *) right_ptr
, user_data
) < 0)
822 if (left_ptr
< right_ptr
)
824 SWAP (left_ptr
, right_ptr
, size
);
827 else if (mid
== right_ptr
)
832 else if (left_ptr
== right_ptr
)
839 while (left_ptr
<= right_ptr
);
841 /* Set up pointers for next iteration. First determine whether
842 left and right partitions are below the threshold size. If so,
843 ignore one or both. Otherwise, push the larger partition's
844 bounds on the stack and continue sorting the smaller one. */
846 if ((size_t) (right_ptr
- lo
) <= max_thresh
)
848 if ((size_t) (hi
- left_ptr
) <= max_thresh
)
849 /* Ignore both small partitions. */
852 /* Ignore small left partition. */
855 else if ((size_t) (hi
- left_ptr
) <= max_thresh
)
856 /* Ignore small right partition. */
858 else if ((right_ptr
- lo
) > (hi
- left_ptr
))
860 /* Push larger left partition indices. */
861 PUSH (lo
, right_ptr
);
866 /* Push larger right partition indices. */
873 /* Once the BASE_PTR array is partially sorted by quicksort the rest
874 is completely sorted using insertion sort, since this is efficient
875 for partitions below MAX_THRESH size. BASE_PTR points to the beginning
876 of the array to sort, and END_PTR points at the very last element in
877 the array (*not* one beyond it!). */
880 char *const end_ptr
= &base_ptr
[size
* (total_elems
- 1)];
881 char *tmp_ptr
= base_ptr
;
882 char *thresh
= base_ptr
+ max_thresh
;
883 if ( thresh
> end_ptr
)
885 register char *run_ptr
;
887 /* Find smallest element in first threshold and place it at the
888 array's beginning. This is the smallest array element,
889 and the operation speeds up insertion sort's inner loop. */
891 for (run_ptr
= tmp_ptr
+ size
; run_ptr
<= thresh
; run_ptr
+= size
)
892 if ((*cmp
) ((void *) run_ptr
, (void *) tmp_ptr
, user_data
) < 0)
895 if (tmp_ptr
!= base_ptr
)
896 SWAP (tmp_ptr
, base_ptr
, size
);
898 /* Insertion sort, running from left-hand-side up to right-hand-side. */
900 run_ptr
= base_ptr
+ size
;
901 while ((run_ptr
+= size
) <= end_ptr
)
903 tmp_ptr
= run_ptr
- size
;
904 while ((*cmp
) ((void *) run_ptr
, (void *) tmp_ptr
, user_data
) < 0)
908 if (tmp_ptr
!= run_ptr
)
912 trav
= run_ptr
+ size
;
913 while (--trav
>= run_ptr
)
918 for (hi
= lo
= trav
; (lo
-= size
) >= tmp_ptr
; hi
= lo
)
931 // ============================================================================
932 // GUI-only functions from now on
933 // ============================================================================
937 // ----------------------------------------------------------------------------
938 // Launch document with default app
939 // ----------------------------------------------------------------------------
941 bool wxLaunchDefaultApplication(const wxString
& document
, int flags
)
946 static const char * const OPEN_CMD
= "/usr/bin/open";
947 if ( wxFileExists(OPEN_CMD
) &&
948 wxExecute(wxString(OPEN_CMD
) + " " + document
) )
950 #elif defined(__UNIX__)
951 // Our best best is to use xdg-open from freedesktop.org cross-desktop
952 // compatibility suite xdg-utils
953 // (see http://portland.freedesktop.org/wiki/) -- this is installed on
954 // most modern distributions and may be tweaked by them to handle
955 // distribution specifics.
956 wxString path
, xdg_open
;
957 if ( wxGetEnv("PATH", &path
) &&
958 wxFindFileInPath(&xdg_open
, path
, "xdg-open") )
960 if ( wxExecute(xdg_open
+ " " + document
) )
963 #elif defined(__WXMSW__)
964 WinStruct
<SHELLEXECUTEINFO
> sei
;
965 sei
.lpFile
= document
.wx_str();
966 sei
.lpVerb
= _T("open");
968 sei
.nShow
= SW_SHOWNORMAL
; // SW_SHOWDEFAULT not defined under CE (#10216)
970 sei
.nShow
= SW_SHOWDEFAULT
;
973 // avoid Windows message box in case of error for consistency with
974 // wxLaunchDefaultBrowser() even if don't show the error ourselves in this
976 sei
.fMask
= SEE_MASK_FLAG_NO_UI
;
978 if ( ::ShellExecuteEx(&sei
) )
985 // ----------------------------------------------------------------------------
986 // Launch default browser
987 // ----------------------------------------------------------------------------
990 // Private method in Objective-C++ source file.
991 bool wxCocoaLaunchDefaultBrowser(const wxString
& url
, int flags
);
994 static bool DoLaunchDefaultBrowser(const wxString
& urlOrig
, int flags
)
998 // set the scheme of url to http if it does not have one
999 // RR: This doesn't work if the url is just a local path
1000 wxString
url(urlOrig
);
1002 if ( !uri
.HasScheme() )
1004 if (wxFileExists(urlOrig
))
1005 url
.Prepend( wxT("file://") );
1007 url
.Prepend(wxT("http://"));
1011 #if defined(__WXMSW__)
1014 if ( flags
& wxBROWSER_NEW_WINDOW
)
1016 // ShellExecuteEx() opens the URL in an existing window by default so
1017 // we can't use it if we need a new window
1018 wxRegKey
key(wxRegKey::HKCR
, uri
.GetScheme() + _T("\\shell\\open"));
1019 if ( !key
.Exists() )
1021 // try default browser, it must be registered at least for http URLs
1022 key
.SetName(wxRegKey::HKCR
, _T("http\\shell\\open"));
1027 wxRegKey
keyDDE(key
, wxT("DDEExec"));
1028 if ( keyDDE
.Exists() )
1030 // we only know the syntax of WWW_OpenURL DDE request for IE,
1031 // optimistically assume that all other browsers are compatible
1033 static const wxChar
*TOPIC_OPEN_URL
= wxT("WWW_OpenURL");
1035 wxRegKey
keyTopic(keyDDE
, wxT("topic"));
1036 bool ok
= keyTopic
.Exists() &&
1037 keyTopic
.QueryDefaultValue() == TOPIC_OPEN_URL
;
1040 ddeCmd
= keyDDE
.QueryDefaultValue();
1041 ok
= !ddeCmd
.empty();
1046 // for WWW_OpenURL, the index of the window to open the URL
1047 // in is -1 (meaning "current") by default, replace it with
1048 // 0 which means "new" (see KB article 160957)
1049 ok
= ddeCmd
.Replace(wxT("-1"), wxT("0"),
1050 false /* only first occurrence */) == 1;
1055 // and also replace the parameters: the topic should
1056 // contain a placeholder for the URL
1057 ok
= ddeCmd
.Replace(wxT("%1"), url
, false) == 1;
1062 // try to send it the DDE request now but ignore the errors
1065 const wxString ddeServer
= wxRegKey(keyDDE
, wxT("application"));
1066 if ( wxExecuteDDE(ddeServer
, TOPIC_OPEN_URL
, ddeCmd
) )
1069 // this is not necessarily an error: maybe browser is
1070 // simply not running, but no matter, in any case we're
1071 // going to launch it using ShellExecuteEx() below now and
1072 // we shouldn't try to open a new window if we open a new
1080 WinStruct
<SHELLEXECUTEINFO
> sei
;
1081 sei
.lpFile
= url
.c_str();
1082 sei
.lpVerb
= _T("open");
1083 sei
.nShow
= SW_SHOWNORMAL
;
1084 sei
.fMask
= SEE_MASK_FLAG_NO_UI
; // we give error message ourselves
1086 if ( ::ShellExecuteEx(&sei
) )
1088 #elif defined(__WXCOCOA__)
1089 // NOTE: We need to call the real implementation from src/cocoa/utils.mm
1090 // because the code must use Objective-C features.
1091 return wxCocoaLaunchDefaultBrowser(url
, flags
);
1092 #elif defined(__WXMAC__) && !defined(__WXOSX_IPHONE__)
1093 wxCFRef
< CFURLRef
> curl( CFURLCreateWithString( kCFAllocatorDefault
,
1094 wxCFStringRef( url
), NULL
) );
1095 OSStatus err
= LSOpenCFURLRef( curl
, NULL
);
1103 wxLogDebug(wxT("Browser Launch error %d"), (int) err
);
1107 // (non-Mac, non-MSW)
1111 // Our best best is to use xdg-open from freedesktop.org cross-desktop
1112 // compatibility suite xdg-utils
1113 // (see http://portland.freedesktop.org/wiki/) -- this is installed on
1114 // most modern distributions and may be tweaked by them to handle
1115 // distribution specifics. Only if that fails, try to find the right
1116 // browser ourselves.
1117 wxString path
, xdg_open
;
1118 if ( wxGetEnv("PATH", &path
) &&
1119 wxFindFileInPath(&xdg_open
, path
, "xdg-open") )
1121 if ( wxExecute(xdg_open
+ " " + url
) )
1125 wxString desktop
= wxTheApp
->GetTraits()->GetDesktopEnvironment();
1127 // GNOME and KDE desktops have some applications which should be always installed
1128 // together with their main parts, which give us the
1129 if (desktop
== wxT("GNOME"))
1131 wxArrayString errors
;
1132 wxArrayString output
;
1134 // gconf will tell us the path of the application to use as browser
1135 long res
= wxExecute( wxT("gconftool-2 --get /desktop/gnome/applications/browser/exec"),
1136 output
, errors
, wxEXEC_NODISABLE
);
1137 if (res
>= 0 && errors
.GetCount() == 0)
1139 wxString cmd
= output
[0];
1140 cmd
<< _T(' ') << url
;
1145 else if (desktop
== wxT("KDE"))
1147 // kfmclient directly opens the given URL
1148 if (wxExecute(wxT("kfmclient openURL ") + url
))
1157 wxFileType
*ft
= wxTheMimeTypesManager
->GetFileTypeFromExtension(_T("html"));
1161 ft
->GetMimeType(&mt
);
1163 ok
= ft
->GetOpenCommand(&cmd
, wxFileType::MessageParameters(url
));
1166 #endif // wxUSE_MIMETYPE
1168 if ( !ok
|| cmd
.empty() )
1170 // fallback to checking for the BROWSER environment variable
1171 cmd
= wxGetenv(wxT("BROWSER"));
1173 cmd
<< _T(' ') << url
;
1176 ok
= ( !cmd
.empty() && wxExecute(cmd
) );
1180 // no file type for HTML extension
1181 wxLogError(_("No default application configured for HTML files."));
1183 #endif // !wxUSE_MIMETYPE && !__WXMSW__
1185 wxLogSysError(_("Failed to open URL \"%s\" in default browser."),
1191 bool wxLaunchDefaultBrowser(const wxString
& url
, int flags
)
1193 if ( flags
& wxBROWSER_NOBUSYCURSOR
)
1194 return DoLaunchDefaultBrowser(url
, flags
);
1197 return DoLaunchDefaultBrowser(url
, flags
);
1200 // ----------------------------------------------------------------------------
1201 // Menu accelerators related functions
1202 // ----------------------------------------------------------------------------
1204 wxChar
*wxStripMenuCodes(const wxChar
*in
, wxChar
*out
)
1207 wxString s
= wxMenuItem::GetLabelText(in
);
1210 wxString s
= wxStripMenuCodes(str
);
1211 #endif // wxUSE_MENUS
1214 // go smash their buffer if it's not big enough - I love char * params
1215 memcpy(out
, s
.c_str(), s
.length() * sizeof(wxChar
));
1219 out
= new wxChar
[s
.length() + 1];
1220 wxStrcpy(out
, s
.c_str());
1226 wxString
wxStripMenuCodes(const wxString
& in
, int flags
)
1228 wxASSERT_MSG( flags
, _T("this is useless to call without any flags") );
1232 size_t len
= in
.length();
1235 for ( size_t n
= 0; n
< len
; n
++ )
1238 if ( (flags
& wxStrip_Mnemonics
) && ch
== _T('&') )
1240 // skip it, it is used to introduce the accel char (or to quote
1241 // itself in which case it should still be skipped): note that it
1242 // can't be the last character of the string
1245 wxLogDebug(_T("Invalid menu string '%s'"), in
.c_str());
1249 // use the next char instead
1253 else if ( (flags
& wxStrip_Accel
) && ch
== _T('\t') )
1255 // everything after TAB is accel string, exit the loop
1265 // ----------------------------------------------------------------------------
1266 // Window search functions
1267 // ----------------------------------------------------------------------------
1270 * If parent is non-NULL, look through children for a label or title
1271 * matching the specified string. If NULL, look through all top-level windows.
1276 wxFindWindowByLabel (const wxString
& title
, wxWindow
* parent
)
1278 return wxWindow::FindWindowByLabel( title
, parent
);
1283 * If parent is non-NULL, look through children for a name
1284 * matching the specified string. If NULL, look through all top-level windows.
1289 wxFindWindowByName (const wxString
& name
, wxWindow
* parent
)
1291 return wxWindow::FindWindowByName( name
, parent
);
1294 // Returns menu item id or wxNOT_FOUND if none.
1296 wxFindMenuItemId(wxFrame
*frame
,
1297 const wxString
& menuString
,
1298 const wxString
& itemString
)
1301 wxMenuBar
*menuBar
= frame
->GetMenuBar ();
1303 return menuBar
->FindMenuItem (menuString
, itemString
);
1304 #else // !wxUSE_MENUS
1306 wxUnusedVar(menuString
);
1307 wxUnusedVar(itemString
);
1308 #endif // wxUSE_MENUS/!wxUSE_MENUS
1313 // Try to find the deepest child that contains 'pt'.
1314 // We go backwards, to try to allow for controls that are spacially
1315 // within other controls, but are still siblings (e.g. buttons within
1316 // static boxes). Static boxes are likely to be created _before_ controls
1317 // that sit inside them.
1318 wxWindow
* wxFindWindowAtPoint(wxWindow
* win
, const wxPoint
& pt
)
1320 if (!win
->IsShown())
1323 // Hack for wxNotebook case: at least in wxGTK, all pages
1324 // claim to be shown, so we must only deal with the selected one.
1326 if (win
->IsKindOf(CLASSINFO(wxNotebook
)))
1328 wxNotebook
* nb
= (wxNotebook
*) win
;
1329 int sel
= nb
->GetSelection();
1332 wxWindow
* child
= nb
->GetPage(sel
);
1333 wxWindow
* foundWin
= wxFindWindowAtPoint(child
, pt
);
1340 wxWindowList::compatibility_iterator node
= win
->GetChildren().GetLast();
1343 wxWindow
* child
= node
->GetData();
1344 wxWindow
* foundWin
= wxFindWindowAtPoint(child
, pt
);
1347 node
= node
->GetPrevious();
1350 wxPoint pos
= win
->GetPosition();
1351 wxSize sz
= win
->GetSize();
1352 if ( !win
->IsTopLevel() && win
->GetParent() )
1354 pos
= win
->GetParent()->ClientToScreen(pos
);
1357 wxRect
rect(pos
, sz
);
1358 if (rect
.Contains(pt
))
1364 wxWindow
* wxGenericFindWindowAtPoint(const wxPoint
& pt
)
1366 // Go backwards through the list since windows
1367 // on top are likely to have been appended most
1369 wxWindowList::compatibility_iterator node
= wxTopLevelWindows
.GetLast();
1372 wxWindow
* win
= node
->GetData();
1373 wxWindow
* found
= wxFindWindowAtPoint(win
, pt
);
1376 node
= node
->GetPrevious();
1381 // ----------------------------------------------------------------------------
1383 // ----------------------------------------------------------------------------
1386 * N.B. these convenience functions must be separate from msgdlgg.cpp, textdlgg.cpp
1387 * since otherwise the generic code may be pulled in unnecessarily.
1392 int wxMessageBox(const wxString
& message
, const wxString
& caption
, long style
,
1393 wxWindow
*parent
, int WXUNUSED(x
), int WXUNUSED(y
) )
1395 long decorated_style
= style
;
1397 if ( ( style
& ( wxICON_EXCLAMATION
| wxICON_HAND
| wxICON_INFORMATION
| wxICON_QUESTION
) ) == 0 )
1399 decorated_style
|= ( style
& wxYES
) ? wxICON_QUESTION
: wxICON_INFORMATION
;
1402 wxMessageDialog
dialog(parent
, message
, caption
, decorated_style
);
1404 int ans
= dialog
.ShowModal();
1417 wxFAIL_MSG( _T("unexpected return code from wxMessageDialog") );
1422 void wxInfoMessageBox(wxWindow
* parent
)
1424 // don't translate these strings, they're for diagnostics purposes only
1426 msg
.Printf(_T("wxWidgets Library (%s port)\n")
1427 _T("Version %d.%d.%d%s%s, compiled at %s %s\n")
1428 _T("Runtime version of toolkit used is %d.%d.%s\n")
1429 _T("Copyright (c) 1995-2009 wxWidgets team"),
1430 wxPlatformInfo::Get().GetPortIdName().c_str(),
1446 wxPlatformInfo::Get().GetToolkitMajorVersion(),
1447 wxPlatformInfo::Get().GetToolkitMinorVersion(),
1449 wxString::Format("\nThe compile-time GTK+ version is %d.%d.%d.",
1452 GTK_MICRO_VERSION
).c_str()
1457 wxMessageBox(msg
, _T("wxWidgets information"),
1458 wxICON_INFORMATION
| wxOK
,
1462 #endif // wxUSE_MSGDLG
1466 wxString
wxGetTextFromUser(const wxString
& message
, const wxString
& caption
,
1467 const wxString
& defaultValue
, wxWindow
*parent
,
1468 wxCoord x
, wxCoord y
, bool centre
)
1471 long style
= wxTextEntryDialogStyle
;
1478 wxTextEntryDialog
dialog(parent
, message
, caption
, defaultValue
, style
, wxPoint(x
, y
));
1480 if (dialog
.ShowModal() == wxID_OK
)
1482 str
= dialog
.GetValue();
1488 wxString
wxGetPasswordFromUser(const wxString
& message
,
1489 const wxString
& caption
,
1490 const wxString
& defaultValue
,
1492 wxCoord x
, wxCoord y
, bool centre
)
1495 long style
= wxTextEntryDialogStyle
;
1502 wxPasswordEntryDialog
dialog(parent
, message
, caption
, defaultValue
,
1503 style
, wxPoint(x
, y
));
1504 if ( dialog
.ShowModal() == wxID_OK
)
1506 str
= dialog
.GetValue();
1512 #endif // wxUSE_TEXTDLG
1516 wxColour
wxGetColourFromUser(wxWindow
*parent
,
1517 const wxColour
& colInit
,
1518 const wxString
& caption
,
1519 wxColourData
*ptrData
)
1521 // contains serialized representation of wxColourData used the last time
1522 // the dialog was shown: we want to reuse it the next time in order to show
1523 // the same custom colours to the user (and we can't just have static
1524 // wxColourData itself because it's a GUI object and so should be destroyed
1525 // before GUI shutdown and doing it during static cleanup is too late)
1526 static wxString s_strColourData
;
1532 if ( !s_strColourData
.empty() )
1534 if ( !data
.FromString(s_strColourData
) )
1536 wxFAIL_MSG( "bug in wxColourData::FromString()?" );
1540 // we don't get back the "choose full" flag value from the native
1541 // dialog and so we can't preserve it between runs, so we decide to
1542 // always use it as it seems better than not using it (user can
1543 // just ignore the extra controls in the dialog but having to click
1544 // a button each time to show them would be very annoying
1545 data
.SetChooseFull(true);
1550 if ( colInit
.IsOk() )
1552 ptrData
->SetColour(colInit
);
1556 wxColourDialog
dialog(parent
, ptrData
);
1557 if (!caption
.empty())
1558 dialog
.SetTitle(caption
);
1559 if ( dialog
.ShowModal() == wxID_OK
)
1561 *ptrData
= dialog
.GetColourData();
1562 colRet
= ptrData
->GetColour();
1563 s_strColourData
= ptrData
->ToString();
1565 //else: leave colRet invalid
1570 #endif // wxUSE_COLOURDLG
1574 wxFont
wxGetFontFromUser(wxWindow
*parent
, const wxFont
& fontInit
, const wxString
& caption
)
1577 if ( fontInit
.Ok() )
1579 data
.SetInitialFont(fontInit
);
1583 wxFontDialog
dialog(parent
, data
);
1584 if (!caption
.empty())
1585 dialog
.SetTitle(caption
);
1586 if ( dialog
.ShowModal() == wxID_OK
)
1588 fontRet
= dialog
.GetFontData().GetChosenFont();
1590 //else: leave it invalid
1595 #endif // wxUSE_FONTDLG
1597 // ----------------------------------------------------------------------------
1598 // wxSafeYield and supporting functions
1599 // ----------------------------------------------------------------------------
1601 void wxEnableTopLevelWindows(bool enable
)
1603 wxWindowList::compatibility_iterator node
;
1604 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1605 node
->GetData()->Enable(enable
);
1608 wxWindowDisabler::wxWindowDisabler(bool disable
)
1610 m_disabled
= disable
;
1615 wxWindowDisabler::wxWindowDisabler(wxWindow
*winToSkip
)
1618 DoDisable(winToSkip
);
1621 void wxWindowDisabler::DoDisable(wxWindow
*winToSkip
)
1623 // remember the top level windows which were already disabled, so that we
1624 // don't reenable them later
1625 m_winDisabled
= NULL
;
1627 wxWindowList::compatibility_iterator node
;
1628 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1630 wxWindow
*winTop
= node
->GetData();
1631 if ( winTop
== winToSkip
)
1634 // we don't need to disable the hidden or already disabled windows
1635 if ( winTop
->IsEnabled() && winTop
->IsShown() )
1641 if ( !m_winDisabled
)
1643 m_winDisabled
= new wxWindowList
;
1646 m_winDisabled
->Append(winTop
);
1651 wxWindowDisabler::~wxWindowDisabler()
1656 wxWindowList::compatibility_iterator node
;
1657 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1659 wxWindow
*winTop
= node
->GetData();
1660 if ( !m_winDisabled
|| !m_winDisabled
->Find(winTop
) )
1664 //else: had been already disabled, don't reenable
1667 delete m_winDisabled
;
1670 // Yield to other apps/messages and disable user input to all windows except
1672 bool wxSafeYield(wxWindow
*win
, bool onlyIfNeeded
)
1674 wxWindowDisabler
wd(win
);
1678 rc
= wxYieldIfNeeded();
1685 // ----------------------------------------------------------------------------
1686 // wxApp::Yield() wrappers for backwards compatibility
1687 // ----------------------------------------------------------------------------
1691 return wxTheApp
&& wxTheApp
->Yield();
1694 bool wxYieldIfNeeded()
1696 return wxTheApp
&& wxTheApp
->Yield(true);