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 // ============================================================================
115 // ============================================================================
117 // Array used in DecToHex conversion routine.
118 static wxChar hexArray
[] = wxT("0123456789ABCDEF");
120 // Convert 2-digit hex number to decimal
121 int wxHexToDec(const wxString
& buf
)
123 int firstDigit
, secondDigit
;
125 if (buf
.GetChar(0) >= wxT('A'))
126 firstDigit
= buf
.GetChar(0) - wxT('A') + 10;
128 firstDigit
= buf
.GetChar(0) - wxT('0');
130 if (buf
.GetChar(1) >= wxT('A'))
131 secondDigit
= buf
.GetChar(1) - wxT('A') + 10;
133 secondDigit
= buf
.GetChar(1) - wxT('0');
135 return (firstDigit
& 0xF) * 16 + (secondDigit
& 0xF );
138 // Convert decimal integer to 2-character hex string
139 void wxDecToHex(int dec
, wxChar
*buf
)
141 int firstDigit
= (int)(dec
/16.0);
142 int secondDigit
= (int)(dec
- (firstDigit
*16.0));
143 buf
[0] = hexArray
[firstDigit
];
144 buf
[1] = hexArray
[secondDigit
];
148 // Convert decimal integer to 2 characters
149 void wxDecToHex(int dec
, char* ch1
, char* ch2
)
151 int firstDigit
= (int)(dec
/16.0);
152 int secondDigit
= (int)(dec
- (firstDigit
*16.0));
153 (*ch1
) = (char) hexArray
[firstDigit
];
154 (*ch2
) = (char) hexArray
[secondDigit
];
157 // Convert decimal integer to 2-character hex string
158 wxString
wxDecToHex(int dec
)
161 wxDecToHex(dec
, buf
);
162 return wxString(buf
);
165 // ----------------------------------------------------------------------------
167 // ----------------------------------------------------------------------------
169 // Return the current date/time
174 wxDateTime now
= wxDateTime::Now();
177 return wxEmptyString
;
180 time_t now
= time((time_t *) NULL
);
181 char *date
= ctime(&now
);
183 return wxString::FromAscii(date
);
187 void wxUsleep(unsigned long milliseconds
)
189 wxMilliSleep(milliseconds
);
192 const wxChar
*wxGetInstallPrefix()
196 if ( wxGetEnv(wxT("WXPREFIX"), &prefix
) )
197 return prefix
.c_str();
199 #ifdef wxINSTALL_PREFIX
200 return wxT(wxINSTALL_PREFIX
);
202 return wxEmptyString
;
206 wxString
wxGetDataDir()
208 wxString dir
= wxGetInstallPrefix();
209 dir
<< wxFILE_SEP_PATH
<< wxT("share") << wxFILE_SEP_PATH
<< wxT("wx");
213 bool wxIsPlatformLittleEndian()
215 // Are we little or big endian? This method is from Harbison & Steele.
219 char c
[sizeof(long)];
228 * Class to make it easier to specify platform-dependent values
231 wxArrayInt
* wxPlatform::sm_customPlatforms
= NULL
;
233 void wxPlatform::Copy(const wxPlatform
& platform
)
235 m_longValue
= platform
.m_longValue
;
236 m_doubleValue
= platform
.m_doubleValue
;
237 m_stringValue
= platform
.m_stringValue
;
240 wxPlatform
wxPlatform::If(int platform
, long value
)
243 return wxPlatform(value
);
248 wxPlatform
wxPlatform::IfNot(int platform
, long value
)
251 return wxPlatform(value
);
256 wxPlatform
& wxPlatform::ElseIf(int platform
, long value
)
263 wxPlatform
& wxPlatform::ElseIfNot(int platform
, long value
)
270 wxPlatform
wxPlatform::If(int platform
, double value
)
273 return wxPlatform(value
);
278 wxPlatform
wxPlatform::IfNot(int platform
, double value
)
281 return wxPlatform(value
);
286 wxPlatform
& wxPlatform::ElseIf(int platform
, double value
)
289 m_doubleValue
= value
;
293 wxPlatform
& wxPlatform::ElseIfNot(int platform
, double value
)
296 m_doubleValue
= value
;
300 wxPlatform
wxPlatform::If(int platform
, const wxString
& value
)
303 return wxPlatform(value
);
308 wxPlatform
wxPlatform::IfNot(int platform
, const wxString
& value
)
311 return wxPlatform(value
);
316 wxPlatform
& wxPlatform::ElseIf(int platform
, const wxString
& value
)
319 m_stringValue
= value
;
323 wxPlatform
& wxPlatform::ElseIfNot(int platform
, const wxString
& value
)
326 m_stringValue
= value
;
330 wxPlatform
& wxPlatform::Else(long value
)
336 wxPlatform
& wxPlatform::Else(double value
)
338 m_doubleValue
= value
;
342 wxPlatform
& wxPlatform::Else(const wxString
& value
)
344 m_stringValue
= value
;
348 void wxPlatform::AddPlatform(int platform
)
350 if (!sm_customPlatforms
)
351 sm_customPlatforms
= new wxArrayInt
;
352 sm_customPlatforms
->Add(platform
);
355 void wxPlatform::ClearPlatforms()
357 delete sm_customPlatforms
;
358 sm_customPlatforms
= NULL
;
361 /// Function for testing current platform
363 bool wxPlatform::Is(int platform
)
366 if (platform
== wxOS_WINDOWS
)
370 if (platform
== wxOS_WINDOWS_CE
)
376 // FIXME: wxWinPocketPC and wxWinSmartPhone are unknown symbols
378 #if defined(__WXWINCE__) && defined(__POCKETPC__)
379 if (platform
== wxWinPocketPC
)
382 #if defined(__WXWINCE__) && defined(__SMARTPHONE__)
383 if (platform
== wxWinSmartPhone
)
390 if (platform
== wxPORT_GTK
)
394 if (platform
== wxPORT_MAC
)
398 if (platform
== wxPORT_X11
)
402 if (platform
== wxOS_UNIX
)
406 if (platform
== wxPORT_MGL
)
410 if (platform
== wxOS_OS2
)
414 if (platform
== wxPORT_PM
)
418 if (platform
== wxPORT_MAC
)
422 if (sm_customPlatforms
&& sm_customPlatforms
->Index(platform
) != wxNOT_FOUND
)
428 // ----------------------------------------------------------------------------
429 // network and user id functions
430 // ----------------------------------------------------------------------------
432 // Get Full RFC822 style email address
433 bool wxGetEmailAddress(wxChar
*address
, int maxSize
)
435 wxString email
= wxGetEmailAddress();
439 wxStrncpy(address
, email
, maxSize
- 1);
440 address
[maxSize
- 1] = wxT('\0');
445 wxString
wxGetEmailAddress()
449 wxString host
= wxGetFullHostName();
452 wxString user
= wxGetUserId();
455 email
<< user
<< wxT('@') << host
;
462 wxString
wxGetUserId()
464 static const int maxLoginLen
= 256; // FIXME arbitrary number
467 bool ok
= wxGetUserId(wxStringBuffer(buf
, maxLoginLen
), maxLoginLen
);
475 wxString
wxGetUserName()
477 static const int maxUserNameLen
= 1024; // FIXME arbitrary number
480 bool ok
= wxGetUserName(wxStringBuffer(buf
, maxUserNameLen
), maxUserNameLen
);
488 wxString
wxGetHostName()
490 static const size_t hostnameSize
= 257;
493 bool ok
= wxGetHostName(wxStringBuffer(buf
, hostnameSize
), hostnameSize
);
501 wxString
wxGetFullHostName()
503 static const size_t hostnameSize
= 257;
506 bool ok
= wxGetFullHostName(wxStringBuffer(buf
, hostnameSize
), hostnameSize
);
514 wxString
wxGetHomeDir()
524 wxString
wxGetCurrentDir()
531 ok
= getcwd(dir
.GetWriteBuf(len
+ 1), len
) != NULL
;
536 if ( errno
!= ERANGE
)
538 wxLogSysError(_T("Failed to get current directory"));
540 return wxEmptyString
;
544 // buffer was too small, retry with a larger one
556 // ----------------------------------------------------------------------------
558 // ----------------------------------------------------------------------------
560 // wxDoExecuteWithCapture() helper: reads an entire stream into one array
562 // returns true if ok, false if error
564 static bool ReadAll(wxInputStream
*is
, wxArrayString
& output
)
566 wxCHECK_MSG( is
, false, _T("NULL stream in wxExecute()?") );
568 // the stream could be already at EOF or in wxSTREAM_BROKEN_PIPE state
571 wxTextInputStream
tis(*is
);
575 wxString line
= tis
.ReadLine();
577 // check for EOF before other errors as it's not really an error
580 // add the last, possibly incomplete, line
586 // any other error is fatal
595 #endif // wxUSE_STREAMS
597 // this is a private function because it hasn't a clean interface: the first
598 // array is passed by reference, the second by pointer - instead we have 2
599 // public versions of wxExecute() below
600 static long wxDoExecuteWithCapture(const wxString
& command
,
601 wxArrayString
& output
,
602 wxArrayString
* error
,
605 // create a wxProcess which will capture the output
606 wxProcess
*process
= new wxProcess
;
609 long rc
= wxExecute(command
, wxEXEC_SYNC
| flags
, process
);
614 if ( !ReadAll(process
->GetInputStream(), output
) )
619 if ( !ReadAll(process
->GetErrorStream(), *error
) )
627 #endif // wxUSE_STREAMS/!wxUSE_STREAMS
634 long wxExecute(const wxString
& command
, wxArrayString
& output
, int flags
)
636 return wxDoExecuteWithCapture(command
, output
, NULL
, flags
);
639 long wxExecute(const wxString
& command
,
640 wxArrayString
& output
,
641 wxArrayString
& error
,
644 return wxDoExecuteWithCapture(command
, output
, &error
, flags
);
647 // ----------------------------------------------------------------------------
648 // wxApp::Yield() wrappers for backwards compatibility
649 // ----------------------------------------------------------------------------
653 return wxTheApp
&& wxTheApp
->Yield();
656 bool wxYieldIfNeeded()
658 return wxTheApp
&& wxTheApp
->Yield(true);
662 static long wxCurrentId
= 100;
666 // skip the part of IDs space that contains hard-coded values:
667 if (wxCurrentId
== wxID_LOWEST
)
668 wxCurrentId
= wxID_HIGHEST
+ 1;
670 return wxCurrentId
++;
674 wxGetCurrentId(void) { return wxCurrentId
; }
677 wxRegisterId (long id
)
679 if (id
>= wxCurrentId
)
680 wxCurrentId
= id
+ 1;
683 // ----------------------------------------------------------------------------
684 // wxQsort, adapted by RR to allow user_data
685 // ----------------------------------------------------------------------------
687 /* This file is part of the GNU C Library.
688 Written by Douglas C. Schmidt (schmidt@ics.uci.edu).
690 Douglas Schmidt kindly gave permission to relicence the
691 code under the wxWindows licence:
693 From: "Douglas C. Schmidt" <schmidt@dre.vanderbilt.edu>
694 To: Robert Roebling <robert.roebling@uni-ulm.de>
695 Subject: Re: qsort licence
696 Date: Mon, 23 Jul 2007 03:44:25 -0500
697 Sender: schmidt@dre.vanderbilt.edu
698 Message-Id: <20070723084426.64F511000A8@tango.dre.vanderbilt.edu>
702 > [...] I'm asking if you'd be willing to relicence your code
703 > under the wxWindows licence. [...]
705 That's fine with me [...]
712 /* Byte-wise swap two items of size SIZE. */
713 #define SWAP(a, b, size) \
716 register size_t __size = (size); \
717 register char *__a = (a), *__b = (b); \
723 } while (--__size > 0); \
726 /* Discontinue quicksort algorithm when partition gets below this size.
727 This particular magic number was chosen to work best on a Sun 4/260. */
730 /* Stack node declarations used to store unfulfilled partition obligations. */
737 /* The next 4 #defines implement a very fast in-line stack abstraction. */
738 #define STACK_SIZE (8 * sizeof(unsigned long int))
739 #define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top))
740 #define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi)))
741 #define STACK_NOT_EMPTY (stack < top)
744 /* Order size using quicksort. This implementation incorporates
745 four optimizations discussed in Sedgewick:
747 1. Non-recursive, using an explicit stack of pointer that store the
748 next array partition to sort. To save time, this maximum amount
749 of space required to store an array of MAX_INT is allocated on the
750 stack. Assuming a 32-bit integer, this needs only 32 *
751 sizeof(stack_node) == 136 bits. Pretty cheap, actually.
753 2. Chose the pivot element using a median-of-three decision tree.
754 This reduces the probability of selecting a bad pivot value and
755 eliminates certain extraneous comparisons.
757 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving
758 insertion sort to order the MAX_THRESH items within each partition.
759 This is a big win, since insertion sort is faster for small, mostly
760 sorted array segments.
762 4. The larger of the two sub-partitions is always pushed onto the
763 stack first, with the algorithm then concentrating on the
764 smaller partition. This *guarantees* no more than log (n)
765 stack size is needed (actually O(1) in this case)! */
767 void wxQsort(void *const pbase
, size_t total_elems
,
768 size_t size
, CMPFUNCDATA cmp
, const void* user_data
)
770 register char *base_ptr
= (char *) pbase
;
771 const size_t max_thresh
= MAX_THRESH
* size
;
773 if (total_elems
== 0)
774 /* Avoid lossage with unsigned arithmetic below. */
777 if (total_elems
> MAX_THRESH
)
780 char *hi
= &lo
[size
* (total_elems
- 1)];
781 stack_node stack
[STACK_SIZE
];
782 stack_node
*top
= stack
;
786 while (STACK_NOT_EMPTY
)
791 /* Select median value from among LO, MID, and HI. Rearrange
792 LO and HI so the three values are sorted. This lowers the
793 probability of picking a pathological pivot value and
794 skips a comparison for both the LEFT_PTR and RIGHT_PTR. */
796 char *mid
= lo
+ size
* ((hi
- lo
) / size
>> 1);
798 if ((*cmp
) ((void *) mid
, (void *) lo
, user_data
) < 0)
799 SWAP (mid
, lo
, size
);
800 if ((*cmp
) ((void *) hi
, (void *) mid
, user_data
) < 0)
801 SWAP (mid
, hi
, size
);
804 if ((*cmp
) ((void *) mid
, (void *) lo
, user_data
) < 0)
805 SWAP (mid
, lo
, size
);
807 left_ptr
= lo
+ size
;
808 right_ptr
= hi
- size
;
810 /* Here's the famous ``collapse the walls'' section of quicksort.
811 Gotta like those tight inner loops! They are the main reason
812 that this algorithm runs much faster than others. */
815 while ((*cmp
) ((void *) left_ptr
, (void *) mid
, user_data
) < 0)
818 while ((*cmp
) ((void *) mid
, (void *) right_ptr
, user_data
) < 0)
821 if (left_ptr
< right_ptr
)
823 SWAP (left_ptr
, right_ptr
, size
);
826 else if (mid
== right_ptr
)
831 else if (left_ptr
== right_ptr
)
838 while (left_ptr
<= right_ptr
);
840 /* Set up pointers for next iteration. First determine whether
841 left and right partitions are below the threshold size. If so,
842 ignore one or both. Otherwise, push the larger partition's
843 bounds on the stack and continue sorting the smaller one. */
845 if ((size_t) (right_ptr
- lo
) <= max_thresh
)
847 if ((size_t) (hi
- left_ptr
) <= max_thresh
)
848 /* Ignore both small partitions. */
851 /* Ignore small left partition. */
854 else if ((size_t) (hi
- left_ptr
) <= max_thresh
)
855 /* Ignore small right partition. */
857 else if ((right_ptr
- lo
) > (hi
- left_ptr
))
859 /* Push larger left partition indices. */
860 PUSH (lo
, right_ptr
);
865 /* Push larger right partition indices. */
872 /* Once the BASE_PTR array is partially sorted by quicksort the rest
873 is completely sorted using insertion sort, since this is efficient
874 for partitions below MAX_THRESH size. BASE_PTR points to the beginning
875 of the array to sort, and END_PTR points at the very last element in
876 the array (*not* one beyond it!). */
879 char *const end_ptr
= &base_ptr
[size
* (total_elems
- 1)];
880 char *tmp_ptr
= base_ptr
;
881 char *thresh
= base_ptr
+ max_thresh
;
882 if ( thresh
> end_ptr
)
884 register char *run_ptr
;
886 /* Find smallest element in first threshold and place it at the
887 array's beginning. This is the smallest array element,
888 and the operation speeds up insertion sort's inner loop. */
890 for (run_ptr
= tmp_ptr
+ size
; run_ptr
<= thresh
; run_ptr
+= size
)
891 if ((*cmp
) ((void *) run_ptr
, (void *) tmp_ptr
, user_data
) < 0)
894 if (tmp_ptr
!= base_ptr
)
895 SWAP (tmp_ptr
, base_ptr
, size
);
897 /* Insertion sort, running from left-hand-side up to right-hand-side. */
899 run_ptr
= base_ptr
+ size
;
900 while ((run_ptr
+= size
) <= end_ptr
)
902 tmp_ptr
= run_ptr
- size
;
903 while ((*cmp
) ((void *) run_ptr
, (void *) tmp_ptr
, user_data
) < 0)
907 if (tmp_ptr
!= run_ptr
)
911 trav
= run_ptr
+ size
;
912 while (--trav
>= run_ptr
)
917 for (hi
= lo
= trav
; (lo
-= size
) >= tmp_ptr
; hi
= lo
)
930 // ============================================================================
931 // GUI-only functions from now on
932 // ============================================================================
936 // ----------------------------------------------------------------------------
937 // Launch document with default app
938 // ----------------------------------------------------------------------------
940 bool wxLaunchDefaultApplication(const wxString
& document
, int flags
)
945 static const char * const OPEN_CMD
= "/usr/bin/open";
946 if ( wxFileExists(OPEN_CMD
) &&
947 wxExecute(wxString(OPEN_CMD
) + " " + document
) )
949 #elif defined(__UNIX__)
950 // Our best best is to use xdg-open from freedesktop.org cross-desktop
951 // compatibility suite xdg-utils
952 // (see http://portland.freedesktop.org/wiki/) -- this is installed on
953 // most modern distributions and may be tweaked by them to handle
954 // distribution specifics.
955 wxString path
, xdg_open
;
956 if ( wxGetEnv("PATH", &path
) &&
957 wxFindFileInPath(&xdg_open
, path
, "xdg-open") )
959 if ( wxExecute(xdg_open
+ " " + document
) )
962 #elif defined(__WXMSW__)
963 const INT_PTR result
= (INT_PTR
)::ShellExecute
965 NULL
, // parent window
969 NULL
, // working directory
979 // ----------------------------------------------------------------------------
980 // Launch default browser
981 // ----------------------------------------------------------------------------
984 // Private method in Objective-C++ source file.
985 bool wxCocoaLaunchDefaultBrowser(const wxString
& url
, int flags
);
988 static bool DoLaunchDefaultBrowser(const wxString
& urlOrig
, int flags
)
992 // set the scheme of url to http if it does not have one
993 // RR: This doesn't work if the url is just a local path
994 wxString
url(urlOrig
);
996 if ( !uri
.HasScheme() )
998 if (wxFileExists(urlOrig
))
999 url
.Prepend( wxT("file://") );
1001 url
.Prepend(wxT("http://"));
1005 #if defined(__WXMSW__)
1008 if ( flags
& wxBROWSER_NEW_WINDOW
)
1010 // ShellExecuteEx() opens the URL in an existing window by default so
1011 // we can't use it if we need a new window
1012 wxRegKey
key(wxRegKey::HKCR
, uri
.GetScheme() + _T("\\shell\\open"));
1013 if ( !key
.Exists() )
1015 // try default browser, it must be registered at least for http URLs
1016 key
.SetName(wxRegKey::HKCR
, _T("http\\shell\\open"));
1021 wxRegKey
keyDDE(key
, wxT("DDEExec"));
1022 if ( keyDDE
.Exists() )
1024 // we only know the syntax of WWW_OpenURL DDE request for IE,
1025 // optimistically assume that all other browsers are compatible
1027 static const wxChar
*TOPIC_OPEN_URL
= wxT("WWW_OpenURL");
1029 wxRegKey
keyTopic(keyDDE
, wxT("topic"));
1030 bool ok
= keyTopic
.Exists() &&
1031 keyTopic
.QueryDefaultValue() == TOPIC_OPEN_URL
;
1034 ddeCmd
= keyDDE
.QueryDefaultValue();
1035 ok
= !ddeCmd
.empty();
1040 // for WWW_OpenURL, the index of the window to open the URL
1041 // in is -1 (meaning "current") by default, replace it with
1042 // 0 which means "new" (see KB article 160957)
1043 ok
= ddeCmd
.Replace(wxT("-1"), wxT("0"),
1044 false /* only first occurrence */) == 1;
1049 // and also replace the parameters: the topic should
1050 // contain a placeholder for the URL
1051 ok
= ddeCmd
.Replace(wxT("%1"), url
, false) == 1;
1056 // try to send it the DDE request now but ignore the errors
1059 const wxString ddeServer
= wxRegKey(keyDDE
, wxT("application"));
1060 if ( wxExecuteDDE(ddeServer
, TOPIC_OPEN_URL
, ddeCmd
) )
1063 // this is not necessarily an error: maybe browser is
1064 // simply not running, but no matter, in any case we're
1065 // going to launch it using ShellExecuteEx() below now and
1066 // we shouldn't try to open a new window if we open a new
1074 WinStruct
<SHELLEXECUTEINFO
> sei
;
1075 sei
.lpFile
= url
.c_str();
1076 sei
.lpVerb
= _T("open");
1077 sei
.nShow
= SW_SHOWNORMAL
;
1078 sei
.fMask
= SEE_MASK_FLAG_NO_UI
; // we give error message ourselves
1080 ::ShellExecuteEx(&sei
);
1082 const INT_PTR nResult
= (INT_PTR
)sei
.hInstApp
;
1084 // Firefox returns file not found for some reason, so make an exception
1086 if ( nResult
> 32 || nResult
== SE_ERR_FNF
)
1089 // Log something if SE_ERR_FNF happens
1090 if ( nResult
== SE_ERR_FNF
)
1091 wxLogDebug(wxT("SE_ERR_FNF from ShellExecute -- maybe FireFox?"));
1092 #endif // __WXDEBUG__
1095 #elif defined(__WXCOCOA__)
1096 // NOTE: We need to call the real implementation from src/cocoa/utils.mm
1097 // because the code must use Objective-C features.
1098 return wxCocoaLaunchDefaultBrowser(url
, flags
);
1099 #elif defined(__WXMAC__) && !defined(__WXOSX_IPHONE__)
1100 wxCFRef
< CFURLRef
> curl( CFURLCreateWithString( kCFAllocatorDefault
,
1101 wxCFStringRef( url
), NULL
) );
1102 OSStatus err
= LSOpenCFURLRef( curl
, NULL
);
1110 wxLogDebug(wxT("Browser Launch error %d"), (int) err
);
1114 // (non-Mac, non-MSW)
1118 // Our best best is to use xdg-open from freedesktop.org cross-desktop
1119 // compatibility suite xdg-utils
1120 // (see http://portland.freedesktop.org/wiki/) -- this is installed on
1121 // most modern distributions and may be tweaked by them to handle
1122 // distribution specifics. Only if that fails, try to find the right
1123 // browser ourselves.
1124 wxString path
, xdg_open
;
1125 if ( wxGetEnv("PATH", &path
) &&
1126 wxFindFileInPath(&xdg_open
, path
, "xdg-open") )
1128 if ( wxExecute(xdg_open
+ " " + url
) )
1132 wxString desktop
= wxTheApp
->GetTraits()->GetDesktopEnvironment();
1134 // GNOME and KDE desktops have some applications which should be always installed
1135 // together with their main parts, which give us the
1136 if (desktop
== wxT("GNOME"))
1138 wxArrayString errors
;
1139 wxArrayString output
;
1141 // gconf will tell us the path of the application to use as browser
1142 long res
= wxExecute( wxT("gconftool-2 --get /desktop/gnome/applications/browser/exec"),
1143 output
, errors
, wxEXEC_NODISABLE
);
1144 if (res
>= 0 && errors
.GetCount() == 0)
1146 wxString cmd
= output
[0];
1147 cmd
<< _T(' ') << url
;
1152 else if (desktop
== wxT("KDE"))
1154 // kfmclient directly opens the given URL
1155 if (wxExecute(wxT("kfmclient openURL ") + url
))
1164 wxFileType
*ft
= wxTheMimeTypesManager
->GetFileTypeFromExtension(_T("html"));
1168 ft
->GetMimeType(&mt
);
1170 ok
= ft
->GetOpenCommand(&cmd
, wxFileType::MessageParameters(url
));
1173 #endif // wxUSE_MIMETYPE
1175 if ( !ok
|| cmd
.empty() )
1177 // fallback to checking for the BROWSER environment variable
1178 cmd
= wxGetenv(wxT("BROWSER"));
1180 cmd
<< _T(' ') << url
;
1183 ok
= ( !cmd
.empty() && wxExecute(cmd
) );
1187 // no file type for HTML extension
1188 wxLogError(_("No default application configured for HTML files."));
1190 #endif // !wxUSE_MIMETYPE && !__WXMSW__
1192 wxLogSysError(_("Failed to open URL \"%s\" in default browser."),
1198 bool wxLaunchDefaultBrowser(const wxString
& url
, int flags
)
1200 if ( flags
& wxBROWSER_NOBUSYCURSOR
)
1201 return DoLaunchDefaultBrowser(url
, flags
);
1204 return DoLaunchDefaultBrowser(url
, flags
);
1207 // ----------------------------------------------------------------------------
1208 // Menu accelerators related functions
1209 // ----------------------------------------------------------------------------
1211 wxChar
*wxStripMenuCodes(const wxChar
*in
, wxChar
*out
)
1214 wxString s
= wxMenuItem::GetLabelText(in
);
1217 wxString s
= wxStripMenuCodes(str
);
1218 #endif // wxUSE_MENUS
1221 // go smash their buffer if it's not big enough - I love char * params
1222 memcpy(out
, s
.c_str(), s
.length() * sizeof(wxChar
));
1226 out
= new wxChar
[s
.length() + 1];
1227 wxStrcpy(out
, s
.c_str());
1233 wxString
wxStripMenuCodes(const wxString
& in
, int flags
)
1235 wxASSERT_MSG( flags
, _T("this is useless to call without any flags") );
1239 size_t len
= in
.length();
1242 for ( size_t n
= 0; n
< len
; n
++ )
1245 if ( (flags
& wxStrip_Mnemonics
) && ch
== _T('&') )
1247 // skip it, it is used to introduce the accel char (or to quote
1248 // itself in which case it should still be skipped): note that it
1249 // can't be the last character of the string
1252 wxLogDebug(_T("Invalid menu string '%s'"), in
.c_str());
1256 // use the next char instead
1260 else if ( (flags
& wxStrip_Accel
) && ch
== _T('\t') )
1262 // everything after TAB is accel string, exit the loop
1272 // ----------------------------------------------------------------------------
1273 // Window search functions
1274 // ----------------------------------------------------------------------------
1277 * If parent is non-NULL, look through children for a label or title
1278 * matching the specified string. If NULL, look through all top-level windows.
1283 wxFindWindowByLabel (const wxString
& title
, wxWindow
* parent
)
1285 return wxWindow::FindWindowByLabel( title
, parent
);
1290 * If parent is non-NULL, look through children for a name
1291 * matching the specified string. If NULL, look through all top-level windows.
1296 wxFindWindowByName (const wxString
& name
, wxWindow
* parent
)
1298 return wxWindow::FindWindowByName( name
, parent
);
1301 // Returns menu item id or wxNOT_FOUND if none.
1303 wxFindMenuItemId(wxFrame
*frame
,
1304 const wxString
& menuString
,
1305 const wxString
& itemString
)
1308 wxMenuBar
*menuBar
= frame
->GetMenuBar ();
1310 return menuBar
->FindMenuItem (menuString
, itemString
);
1311 #else // !wxUSE_MENUS
1313 wxUnusedVar(menuString
);
1314 wxUnusedVar(itemString
);
1315 #endif // wxUSE_MENUS/!wxUSE_MENUS
1320 // Try to find the deepest child that contains 'pt'.
1321 // We go backwards, to try to allow for controls that are spacially
1322 // within other controls, but are still siblings (e.g. buttons within
1323 // static boxes). Static boxes are likely to be created _before_ controls
1324 // that sit inside them.
1325 wxWindow
* wxFindWindowAtPoint(wxWindow
* win
, const wxPoint
& pt
)
1327 if (!win
->IsShown())
1330 // Hack for wxNotebook case: at least in wxGTK, all pages
1331 // claim to be shown, so we must only deal with the selected one.
1333 if (win
->IsKindOf(CLASSINFO(wxNotebook
)))
1335 wxNotebook
* nb
= (wxNotebook
*) win
;
1336 int sel
= nb
->GetSelection();
1339 wxWindow
* child
= nb
->GetPage(sel
);
1340 wxWindow
* foundWin
= wxFindWindowAtPoint(child
, pt
);
1347 wxWindowList::compatibility_iterator node
= win
->GetChildren().GetLast();
1350 wxWindow
* child
= node
->GetData();
1351 wxWindow
* foundWin
= wxFindWindowAtPoint(child
, pt
);
1354 node
= node
->GetPrevious();
1357 wxPoint pos
= win
->GetPosition();
1358 wxSize sz
= win
->GetSize();
1359 if ( !win
->IsTopLevel() && win
->GetParent() )
1361 pos
= win
->GetParent()->ClientToScreen(pos
);
1364 wxRect
rect(pos
, sz
);
1365 if (rect
.Contains(pt
))
1371 wxWindow
* wxGenericFindWindowAtPoint(const wxPoint
& pt
)
1373 // Go backwards through the list since windows
1374 // on top are likely to have been appended most
1376 wxWindowList::compatibility_iterator node
= wxTopLevelWindows
.GetLast();
1379 wxWindow
* win
= node
->GetData();
1380 wxWindow
* found
= wxFindWindowAtPoint(win
, pt
);
1383 node
= node
->GetPrevious();
1388 // ----------------------------------------------------------------------------
1390 // ----------------------------------------------------------------------------
1393 * N.B. these convenience functions must be separate from msgdlgg.cpp, textdlgg.cpp
1394 * since otherwise the generic code may be pulled in unnecessarily.
1399 int wxMessageBox(const wxString
& message
, const wxString
& caption
, long style
,
1400 wxWindow
*parent
, int WXUNUSED(x
), int WXUNUSED(y
) )
1402 long decorated_style
= style
;
1404 if ( ( style
& ( wxICON_EXCLAMATION
| wxICON_HAND
| wxICON_INFORMATION
| wxICON_QUESTION
) ) == 0 )
1406 decorated_style
|= ( style
& wxYES
) ? wxICON_QUESTION
: wxICON_INFORMATION
;
1409 wxMessageDialog
dialog(parent
, message
, caption
, decorated_style
);
1411 int ans
= dialog
.ShowModal();
1424 wxFAIL_MSG( _T("unexpected return code from wxMessageDialog") );
1429 void wxInfoMessageBox(wxWindow
* parent
)
1431 // don't translate these strings, they're for diagnostics purposes only
1433 msg
.Printf(_T("wxWidgets Library (%s port)\n")
1434 _T("Version %d.%d.%d%s%s, compiled at %s %s\n")
1435 _T("Runtime version of toolkit used is %d.%d.%s\n")
1436 _T("Copyright (c) 1995-2008 wxWidgets team"),
1437 wxPlatformInfo::Get().GetPortIdName().c_str(),
1453 wxPlatformInfo::Get().GetToolkitMajorVersion(),
1454 wxPlatformInfo::Get().GetToolkitMinorVersion(),
1456 wxString::Format("\nThe compile-time GTK+ version is %d.%d.%d.",
1459 GTK_MICRO_VERSION
).c_str()
1464 wxMessageBox(msg
, _T("wxWidgets information"),
1465 wxICON_INFORMATION
| wxOK
,
1469 #endif // wxUSE_MSGDLG
1473 wxString
wxGetTextFromUser(const wxString
& message
, const wxString
& caption
,
1474 const wxString
& defaultValue
, wxWindow
*parent
,
1475 wxCoord x
, wxCoord y
, bool centre
)
1478 long style
= wxTextEntryDialogStyle
;
1485 wxTextEntryDialog
dialog(parent
, message
, caption
, defaultValue
, style
, wxPoint(x
, y
));
1487 if (dialog
.ShowModal() == wxID_OK
)
1489 str
= dialog
.GetValue();
1495 wxString
wxGetPasswordFromUser(const wxString
& message
,
1496 const wxString
& caption
,
1497 const wxString
& defaultValue
,
1499 wxCoord x
, wxCoord y
, bool centre
)
1502 long style
= wxTextEntryDialogStyle
;
1509 wxPasswordEntryDialog
dialog(parent
, message
, caption
, defaultValue
,
1510 style
, wxPoint(x
, y
));
1511 if ( dialog
.ShowModal() == wxID_OK
)
1513 str
= dialog
.GetValue();
1519 #endif // wxUSE_TEXTDLG
1523 wxColour
wxGetColourFromUser(wxWindow
*parent
,
1524 const wxColour
& colInit
,
1525 const wxString
& caption
,
1526 wxColourData
*ptrData
)
1528 // contains serialized representation of wxColourData used the last time
1529 // the dialog was shown: we want to reuse it the next time in order to show
1530 // the same custom colours to the user (and we can't just have static
1531 // wxColourData itself because it's a GUI object and so should be destroyed
1532 // before GUI shutdown and doing it during static cleanup is too late)
1533 static wxString s_strColourData
;
1539 if ( !s_strColourData
.empty() )
1541 if ( !data
.FromString(s_strColourData
) )
1543 wxFAIL_MSG( "bug in wxColourData::FromString()?" );
1547 // we don't get back the "choose full" flag value from the native
1548 // dialog and so we can't preserve it between runs, so we decide to
1549 // always use it as it seems better than not using it (user can
1550 // just ignore the extra controls in the dialog but having to click
1551 // a button each time to show them would be very annoying
1552 data
.SetChooseFull(true);
1557 if ( colInit
.IsOk() )
1559 ptrData
->SetColour(colInit
);
1563 wxColourDialog
dialog(parent
, ptrData
);
1564 if (!caption
.empty())
1565 dialog
.SetTitle(caption
);
1566 if ( dialog
.ShowModal() == wxID_OK
)
1568 *ptrData
= dialog
.GetColourData();
1569 colRet
= ptrData
->GetColour();
1570 s_strColourData
= ptrData
->ToString();
1572 //else: leave colRet invalid
1577 #endif // wxUSE_COLOURDLG
1581 wxFont
wxGetFontFromUser(wxWindow
*parent
, const wxFont
& fontInit
, const wxString
& caption
)
1584 if ( fontInit
.Ok() )
1586 data
.SetInitialFont(fontInit
);
1590 wxFontDialog
dialog(parent
, data
);
1591 if (!caption
.empty())
1592 dialog
.SetTitle(caption
);
1593 if ( dialog
.ShowModal() == wxID_OK
)
1595 fontRet
= dialog
.GetFontData().GetChosenFont();
1597 //else: leave it invalid
1602 #endif // wxUSE_FONTDLG
1604 // ----------------------------------------------------------------------------
1605 // wxSafeYield and supporting functions
1606 // ----------------------------------------------------------------------------
1608 void wxEnableTopLevelWindows(bool enable
)
1610 wxWindowList::compatibility_iterator node
;
1611 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1612 node
->GetData()->Enable(enable
);
1615 wxWindowDisabler::wxWindowDisabler(bool disable
)
1617 m_disabled
= disable
;
1622 wxWindowDisabler::wxWindowDisabler(wxWindow
*winToSkip
)
1625 DoDisable(winToSkip
);
1628 void wxWindowDisabler::DoDisable(wxWindow
*winToSkip
)
1630 // remember the top level windows which were already disabled, so that we
1631 // don't reenable them later
1632 m_winDisabled
= NULL
;
1634 wxWindowList::compatibility_iterator node
;
1635 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1637 wxWindow
*winTop
= node
->GetData();
1638 if ( winTop
== winToSkip
)
1641 // we don't need to disable the hidden or already disabled windows
1642 if ( winTop
->IsEnabled() && winTop
->IsShown() )
1648 if ( !m_winDisabled
)
1650 m_winDisabled
= new wxWindowList
;
1653 m_winDisabled
->Append(winTop
);
1658 wxWindowDisabler::~wxWindowDisabler()
1663 wxWindowList::compatibility_iterator node
;
1664 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1666 wxWindow
*winTop
= node
->GetData();
1667 if ( !m_winDisabled
|| !m_winDisabled
->Find(winTop
) )
1671 //else: had been already disabled, don't reenable
1674 delete m_winDisabled
;
1677 // Yield to other apps/messages and disable user input to all windows except
1679 bool wxSafeYield(wxWindow
*win
, bool onlyIfNeeded
)
1681 wxWindowDisabler
wd(win
);
1685 rc
= wxYieldIfNeeded();
1692 // Don't synthesize KeyUp events holding down a key and producing KeyDown
1693 // events with autorepeat. On by default and always on in wxMSW. wxGTK version
1696 bool wxSetDetectableAutoRepeat( bool WXUNUSED(flag
) )
1698 return true; // detectable auto-repeat is the only mode MSW supports