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 wxStrlcpy(address
, email
.t_str(), maxSize
);
444 wxString
wxGetEmailAddress()
448 wxString host
= wxGetFullHostName();
451 wxString user
= wxGetUserId();
454 email
<< user
<< wxT('@') << host
;
461 wxString
wxGetUserId()
463 static const int maxLoginLen
= 256; // FIXME arbitrary number
466 bool ok
= wxGetUserId(wxStringBuffer(buf
, maxLoginLen
), maxLoginLen
);
474 wxString
wxGetUserName()
476 static const int maxUserNameLen
= 1024; // FIXME arbitrary number
479 bool ok
= wxGetUserName(wxStringBuffer(buf
, maxUserNameLen
), maxUserNameLen
);
487 wxString
wxGetHostName()
489 static const size_t hostnameSize
= 257;
492 bool ok
= wxGetHostName(wxStringBuffer(buf
, hostnameSize
), hostnameSize
);
500 wxString
wxGetFullHostName()
502 static const size_t hostnameSize
= 257;
505 bool ok
= wxGetFullHostName(wxStringBuffer(buf
, hostnameSize
), hostnameSize
);
513 wxString
wxGetHomeDir()
523 wxString
wxGetCurrentDir()
530 ok
= getcwd(dir
.GetWriteBuf(len
+ 1), len
) != NULL
;
535 if ( errno
!= ERANGE
)
537 wxLogSysError(_T("Failed to get current directory"));
539 return wxEmptyString
;
543 // buffer was too small, retry with a larger one
555 // ----------------------------------------------------------------------------
557 // ----------------------------------------------------------------------------
559 // wxDoExecuteWithCapture() helper: reads an entire stream into one array
561 // returns true if ok, false if error
563 static bool ReadAll(wxInputStream
*is
, wxArrayString
& output
)
565 wxCHECK_MSG( is
, false, _T("NULL stream in wxExecute()?") );
567 // the stream could be already at EOF or in wxSTREAM_BROKEN_PIPE state
570 wxTextInputStream
tis(*is
);
574 wxString line
= tis
.ReadLine();
576 // check for EOF before other errors as it's not really an error
579 // add the last, possibly incomplete, line
585 // any other error is fatal
594 #endif // wxUSE_STREAMS
596 // this is a private function because it hasn't a clean interface: the first
597 // array is passed by reference, the second by pointer - instead we have 2
598 // public versions of wxExecute() below
599 static long wxDoExecuteWithCapture(const wxString
& command
,
600 wxArrayString
& output
,
601 wxArrayString
* error
,
604 // create a wxProcess which will capture the output
605 wxProcess
*process
= new wxProcess
;
608 long rc
= wxExecute(command
, wxEXEC_SYNC
| flags
, process
);
613 if ( !ReadAll(process
->GetInputStream(), output
) )
618 if ( !ReadAll(process
->GetErrorStream(), *error
) )
626 #endif // wxUSE_STREAMS/!wxUSE_STREAMS
633 long wxExecute(const wxString
& command
, wxArrayString
& output
, int flags
)
635 return wxDoExecuteWithCapture(command
, output
, NULL
, flags
);
638 long wxExecute(const wxString
& command
,
639 wxArrayString
& output
,
640 wxArrayString
& error
,
643 return wxDoExecuteWithCapture(command
, output
, &error
, flags
);
646 // ----------------------------------------------------------------------------
647 // wxApp::Yield() wrappers for backwards compatibility
648 // ----------------------------------------------------------------------------
652 return wxTheApp
&& wxTheApp
->Yield();
655 bool wxYieldIfNeeded()
657 return wxTheApp
&& wxTheApp
->Yield(true);
661 static long wxCurrentId
= 100;
665 // skip the part of IDs space that contains hard-coded values:
666 if (wxCurrentId
== wxID_LOWEST
)
667 wxCurrentId
= wxID_HIGHEST
+ 1;
669 return wxCurrentId
++;
673 wxGetCurrentId(void) { return wxCurrentId
; }
676 wxRegisterId (long id
)
678 if (id
>= wxCurrentId
)
679 wxCurrentId
= id
+ 1;
682 // ----------------------------------------------------------------------------
683 // wxQsort, adapted by RR to allow user_data
684 // ----------------------------------------------------------------------------
686 /* This file is part of the GNU C Library.
687 Written by Douglas C. Schmidt (schmidt@ics.uci.edu).
689 Douglas Schmidt kindly gave permission to relicence the
690 code under the wxWindows licence:
692 From: "Douglas C. Schmidt" <schmidt@dre.vanderbilt.edu>
693 To: Robert Roebling <robert.roebling@uni-ulm.de>
694 Subject: Re: qsort licence
695 Date: Mon, 23 Jul 2007 03:44:25 -0500
696 Sender: schmidt@dre.vanderbilt.edu
697 Message-Id: <20070723084426.64F511000A8@tango.dre.vanderbilt.edu>
701 > [...] I'm asking if you'd be willing to relicence your code
702 > under the wxWindows licence. [...]
704 That's fine with me [...]
711 /* Byte-wise swap two items of size SIZE. */
712 #define SWAP(a, b, size) \
715 register size_t __size = (size); \
716 register char *__a = (a), *__b = (b); \
722 } while (--__size > 0); \
725 /* Discontinue quicksort algorithm when partition gets below this size.
726 This particular magic number was chosen to work best on a Sun 4/260. */
729 /* Stack node declarations used to store unfulfilled partition obligations. */
736 /* The next 4 #defines implement a very fast in-line stack abstraction. */
737 #define STACK_SIZE (8 * sizeof(unsigned long int))
738 #define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top))
739 #define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi)))
740 #define STACK_NOT_EMPTY (stack < top)
743 /* Order size using quicksort. This implementation incorporates
744 four optimizations discussed in Sedgewick:
746 1. Non-recursive, using an explicit stack of pointer that store the
747 next array partition to sort. To save time, this maximum amount
748 of space required to store an array of MAX_INT is allocated on the
749 stack. Assuming a 32-bit integer, this needs only 32 *
750 sizeof(stack_node) == 136 bits. Pretty cheap, actually.
752 2. Chose the pivot element using a median-of-three decision tree.
753 This reduces the probability of selecting a bad pivot value and
754 eliminates certain extraneous comparisons.
756 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving
757 insertion sort to order the MAX_THRESH items within each partition.
758 This is a big win, since insertion sort is faster for small, mostly
759 sorted array segments.
761 4. The larger of the two sub-partitions is always pushed onto the
762 stack first, with the algorithm then concentrating on the
763 smaller partition. This *guarantees* no more than log (n)
764 stack size is needed (actually O(1) in this case)! */
766 void wxQsort(void *const pbase
, size_t total_elems
,
767 size_t size
, CMPFUNCDATA cmp
, const void* user_data
)
769 register char *base_ptr
= (char *) pbase
;
770 const size_t max_thresh
= MAX_THRESH
* size
;
772 if (total_elems
== 0)
773 /* Avoid lossage with unsigned arithmetic below. */
776 if (total_elems
> MAX_THRESH
)
779 char *hi
= &lo
[size
* (total_elems
- 1)];
780 stack_node stack
[STACK_SIZE
];
781 stack_node
*top
= stack
;
785 while (STACK_NOT_EMPTY
)
790 /* Select median value from among LO, MID, and HI. Rearrange
791 LO and HI so the three values are sorted. This lowers the
792 probability of picking a pathological pivot value and
793 skips a comparison for both the LEFT_PTR and RIGHT_PTR. */
795 char *mid
= lo
+ size
* ((hi
- lo
) / size
>> 1);
797 if ((*cmp
) ((void *) mid
, (void *) lo
, user_data
) < 0)
798 SWAP (mid
, lo
, size
);
799 if ((*cmp
) ((void *) hi
, (void *) mid
, user_data
) < 0)
800 SWAP (mid
, hi
, size
);
803 if ((*cmp
) ((void *) mid
, (void *) lo
, user_data
) < 0)
804 SWAP (mid
, lo
, size
);
806 left_ptr
= lo
+ size
;
807 right_ptr
= hi
- size
;
809 /* Here's the famous ``collapse the walls'' section of quicksort.
810 Gotta like those tight inner loops! They are the main reason
811 that this algorithm runs much faster than others. */
814 while ((*cmp
) ((void *) left_ptr
, (void *) mid
, user_data
) < 0)
817 while ((*cmp
) ((void *) mid
, (void *) right_ptr
, user_data
) < 0)
820 if (left_ptr
< right_ptr
)
822 SWAP (left_ptr
, right_ptr
, size
);
825 else if (mid
== right_ptr
)
830 else if (left_ptr
== right_ptr
)
837 while (left_ptr
<= right_ptr
);
839 /* Set up pointers for next iteration. First determine whether
840 left and right partitions are below the threshold size. If so,
841 ignore one or both. Otherwise, push the larger partition's
842 bounds on the stack and continue sorting the smaller one. */
844 if ((size_t) (right_ptr
- lo
) <= max_thresh
)
846 if ((size_t) (hi
- left_ptr
) <= max_thresh
)
847 /* Ignore both small partitions. */
850 /* Ignore small left partition. */
853 else if ((size_t) (hi
- left_ptr
) <= max_thresh
)
854 /* Ignore small right partition. */
856 else if ((right_ptr
- lo
) > (hi
- left_ptr
))
858 /* Push larger left partition indices. */
859 PUSH (lo
, right_ptr
);
864 /* Push larger right partition indices. */
871 /* Once the BASE_PTR array is partially sorted by quicksort the rest
872 is completely sorted using insertion sort, since this is efficient
873 for partitions below MAX_THRESH size. BASE_PTR points to the beginning
874 of the array to sort, and END_PTR points at the very last element in
875 the array (*not* one beyond it!). */
878 char *const end_ptr
= &base_ptr
[size
* (total_elems
- 1)];
879 char *tmp_ptr
= base_ptr
;
880 char *thresh
= base_ptr
+ max_thresh
;
881 if ( thresh
> end_ptr
)
883 register char *run_ptr
;
885 /* Find smallest element in first threshold and place it at the
886 array's beginning. This is the smallest array element,
887 and the operation speeds up insertion sort's inner loop. */
889 for (run_ptr
= tmp_ptr
+ size
; run_ptr
<= thresh
; run_ptr
+= size
)
890 if ((*cmp
) ((void *) run_ptr
, (void *) tmp_ptr
, user_data
) < 0)
893 if (tmp_ptr
!= base_ptr
)
894 SWAP (tmp_ptr
, base_ptr
, size
);
896 /* Insertion sort, running from left-hand-side up to right-hand-side. */
898 run_ptr
= base_ptr
+ size
;
899 while ((run_ptr
+= size
) <= end_ptr
)
901 tmp_ptr
= run_ptr
- size
;
902 while ((*cmp
) ((void *) run_ptr
, (void *) tmp_ptr
, user_data
) < 0)
906 if (tmp_ptr
!= run_ptr
)
910 trav
= run_ptr
+ size
;
911 while (--trav
>= run_ptr
)
916 for (hi
= lo
= trav
; (lo
-= size
) >= tmp_ptr
; hi
= lo
)
929 // ============================================================================
930 // GUI-only functions from now on
931 // ============================================================================
935 // ----------------------------------------------------------------------------
936 // Launch document with default app
937 // ----------------------------------------------------------------------------
939 bool wxLaunchDefaultApplication(const wxString
& document
, int flags
)
944 static const char * const OPEN_CMD
= "/usr/bin/open";
945 if ( wxFileExists(OPEN_CMD
) &&
946 wxExecute(wxString(OPEN_CMD
) + " " + document
) )
948 #elif defined(__UNIX__)
949 // Our best best is to use xdg-open from freedesktop.org cross-desktop
950 // compatibility suite xdg-utils
951 // (see http://portland.freedesktop.org/wiki/) -- this is installed on
952 // most modern distributions and may be tweaked by them to handle
953 // distribution specifics.
954 wxString path
, xdg_open
;
955 if ( wxGetEnv("PATH", &path
) &&
956 wxFindFileInPath(&xdg_open
, path
, "xdg-open") )
958 if ( wxExecute(xdg_open
+ " " + document
) )
961 #elif defined(__WXMSW__)
962 WinStruct
<SHELLEXECUTEINFO
> sei
;
963 sei
.lpFile
= document
.wx_str();
964 sei
.lpVerb
= _T("open");
966 sei
.nShow
= SW_SHOWNORMAL
; // SW_SHOWDEFAULT not defined under CE (#10216)
968 sei
.nShow
= SW_SHOWDEFAULT
;
971 // avoid Windows message box in case of error for consistency with
972 // wxLaunchDefaultBrowser() even if don't show the error ourselves in this
974 sei
.fMask
= SEE_MASK_FLAG_NO_UI
;
976 if ( ::ShellExecuteEx(&sei
) )
983 // ----------------------------------------------------------------------------
984 // Launch default browser
985 // ----------------------------------------------------------------------------
988 // Private method in Objective-C++ source file.
989 bool wxCocoaLaunchDefaultBrowser(const wxString
& url
, int flags
);
992 static bool DoLaunchDefaultBrowser(const wxString
& urlOrig
, int flags
)
996 // set the scheme of url to http if it does not have one
997 // RR: This doesn't work if the url is just a local path
998 wxString
url(urlOrig
);
1000 if ( !uri
.HasScheme() )
1002 if (wxFileExists(urlOrig
))
1003 url
.Prepend( wxT("file://") );
1005 url
.Prepend(wxT("http://"));
1009 #if defined(__WXMSW__)
1012 if ( flags
& wxBROWSER_NEW_WINDOW
)
1014 // ShellExecuteEx() opens the URL in an existing window by default so
1015 // we can't use it if we need a new window
1016 wxRegKey
key(wxRegKey::HKCR
, uri
.GetScheme() + _T("\\shell\\open"));
1017 if ( !key
.Exists() )
1019 // try default browser, it must be registered at least for http URLs
1020 key
.SetName(wxRegKey::HKCR
, _T("http\\shell\\open"));
1025 wxRegKey
keyDDE(key
, wxT("DDEExec"));
1026 if ( keyDDE
.Exists() )
1028 // we only know the syntax of WWW_OpenURL DDE request for IE,
1029 // optimistically assume that all other browsers are compatible
1031 static const wxChar
*TOPIC_OPEN_URL
= wxT("WWW_OpenURL");
1033 wxRegKey
keyTopic(keyDDE
, wxT("topic"));
1034 bool ok
= keyTopic
.Exists() &&
1035 keyTopic
.QueryDefaultValue() == TOPIC_OPEN_URL
;
1038 ddeCmd
= keyDDE
.QueryDefaultValue();
1039 ok
= !ddeCmd
.empty();
1044 // for WWW_OpenURL, the index of the window to open the URL
1045 // in is -1 (meaning "current") by default, replace it with
1046 // 0 which means "new" (see KB article 160957)
1047 ok
= ddeCmd
.Replace(wxT("-1"), wxT("0"),
1048 false /* only first occurrence */) == 1;
1053 // and also replace the parameters: the topic should
1054 // contain a placeholder for the URL
1055 ok
= ddeCmd
.Replace(wxT("%1"), url
, false) == 1;
1060 // try to send it the DDE request now but ignore the errors
1063 const wxString ddeServer
= wxRegKey(keyDDE
, wxT("application"));
1064 if ( wxExecuteDDE(ddeServer
, TOPIC_OPEN_URL
, ddeCmd
) )
1067 // this is not necessarily an error: maybe browser is
1068 // simply not running, but no matter, in any case we're
1069 // going to launch it using ShellExecuteEx() below now and
1070 // we shouldn't try to open a new window if we open a new
1078 WinStruct
<SHELLEXECUTEINFO
> sei
;
1079 sei
.lpFile
= url
.c_str();
1080 sei
.lpVerb
= _T("open");
1081 sei
.nShow
= SW_SHOWNORMAL
;
1082 sei
.fMask
= SEE_MASK_FLAG_NO_UI
; // we give error message ourselves
1084 if ( ::ShellExecuteEx(&sei
) )
1086 #elif defined(__WXCOCOA__)
1087 // NOTE: We need to call the real implementation from src/cocoa/utils.mm
1088 // because the code must use Objective-C features.
1089 return wxCocoaLaunchDefaultBrowser(url
, flags
);
1090 #elif defined(__WXMAC__) && !defined(__WXOSX_IPHONE__)
1091 wxCFRef
< CFURLRef
> curl( CFURLCreateWithString( kCFAllocatorDefault
,
1092 wxCFStringRef( url
), NULL
) );
1093 OSStatus err
= LSOpenCFURLRef( curl
, NULL
);
1101 wxLogDebug(wxT("Browser Launch error %d"), (int) err
);
1105 // (non-Mac, non-MSW)
1109 // Our best best is to use xdg-open from freedesktop.org cross-desktop
1110 // compatibility suite xdg-utils
1111 // (see http://portland.freedesktop.org/wiki/) -- this is installed on
1112 // most modern distributions and may be tweaked by them to handle
1113 // distribution specifics. Only if that fails, try to find the right
1114 // browser ourselves.
1115 wxString path
, xdg_open
;
1116 if ( wxGetEnv("PATH", &path
) &&
1117 wxFindFileInPath(&xdg_open
, path
, "xdg-open") )
1119 if ( wxExecute(xdg_open
+ " " + url
) )
1123 wxString desktop
= wxTheApp
->GetTraits()->GetDesktopEnvironment();
1125 // GNOME and KDE desktops have some applications which should be always installed
1126 // together with their main parts, which give us the
1127 if (desktop
== wxT("GNOME"))
1129 wxArrayString errors
;
1130 wxArrayString output
;
1132 // gconf will tell us the path of the application to use as browser
1133 long res
= wxExecute( wxT("gconftool-2 --get /desktop/gnome/applications/browser/exec"),
1134 output
, errors
, wxEXEC_NODISABLE
);
1135 if (res
>= 0 && errors
.GetCount() == 0)
1137 wxString cmd
= output
[0];
1138 cmd
<< _T(' ') << url
;
1143 else if (desktop
== wxT("KDE"))
1145 // kfmclient directly opens the given URL
1146 if (wxExecute(wxT("kfmclient openURL ") + url
))
1155 wxFileType
*ft
= wxTheMimeTypesManager
->GetFileTypeFromExtension(_T("html"));
1159 ft
->GetMimeType(&mt
);
1161 ok
= ft
->GetOpenCommand(&cmd
, wxFileType::MessageParameters(url
));
1164 #endif // wxUSE_MIMETYPE
1166 if ( !ok
|| cmd
.empty() )
1168 // fallback to checking for the BROWSER environment variable
1169 cmd
= wxGetenv(wxT("BROWSER"));
1171 cmd
<< _T(' ') << url
;
1174 ok
= ( !cmd
.empty() && wxExecute(cmd
) );
1178 // no file type for HTML extension
1179 wxLogError(_("No default application configured for HTML files."));
1181 #endif // !wxUSE_MIMETYPE && !__WXMSW__
1183 wxLogSysError(_("Failed to open URL \"%s\" in default browser."),
1189 bool wxLaunchDefaultBrowser(const wxString
& url
, int flags
)
1191 if ( flags
& wxBROWSER_NOBUSYCURSOR
)
1192 return DoLaunchDefaultBrowser(url
, flags
);
1195 return DoLaunchDefaultBrowser(url
, flags
);
1198 // ----------------------------------------------------------------------------
1199 // Menu accelerators related functions
1200 // ----------------------------------------------------------------------------
1202 wxChar
*wxStripMenuCodes(const wxChar
*in
, wxChar
*out
)
1205 wxString s
= wxMenuItem::GetLabelText(in
);
1208 wxString s
= wxStripMenuCodes(str
);
1209 #endif // wxUSE_MENUS
1212 // go smash their buffer if it's not big enough - I love char * params
1213 memcpy(out
, s
.c_str(), s
.length() * sizeof(wxChar
));
1217 out
= new wxChar
[s
.length() + 1];
1218 wxStrcpy(out
, s
.c_str());
1224 wxString
wxStripMenuCodes(const wxString
& in
, int flags
)
1226 wxASSERT_MSG( flags
, _T("this is useless to call without any flags") );
1230 size_t len
= in
.length();
1233 for ( size_t n
= 0; n
< len
; n
++ )
1236 if ( (flags
& wxStrip_Mnemonics
) && ch
== _T('&') )
1238 // skip it, it is used to introduce the accel char (or to quote
1239 // itself in which case it should still be skipped): note that it
1240 // can't be the last character of the string
1243 wxLogDebug(_T("Invalid menu string '%s'"), in
.c_str());
1247 // use the next char instead
1251 else if ( (flags
& wxStrip_Accel
) && ch
== _T('\t') )
1253 // everything after TAB is accel string, exit the loop
1263 // ----------------------------------------------------------------------------
1264 // Window search functions
1265 // ----------------------------------------------------------------------------
1268 * If parent is non-NULL, look through children for a label or title
1269 * matching the specified string. If NULL, look through all top-level windows.
1274 wxFindWindowByLabel (const wxString
& title
, wxWindow
* parent
)
1276 return wxWindow::FindWindowByLabel( title
, parent
);
1281 * If parent is non-NULL, look through children for a name
1282 * matching the specified string. If NULL, look through all top-level windows.
1287 wxFindWindowByName (const wxString
& name
, wxWindow
* parent
)
1289 return wxWindow::FindWindowByName( name
, parent
);
1292 // Returns menu item id or wxNOT_FOUND if none.
1294 wxFindMenuItemId(wxFrame
*frame
,
1295 const wxString
& menuString
,
1296 const wxString
& itemString
)
1299 wxMenuBar
*menuBar
= frame
->GetMenuBar ();
1301 return menuBar
->FindMenuItem (menuString
, itemString
);
1302 #else // !wxUSE_MENUS
1304 wxUnusedVar(menuString
);
1305 wxUnusedVar(itemString
);
1306 #endif // wxUSE_MENUS/!wxUSE_MENUS
1311 // Try to find the deepest child that contains 'pt'.
1312 // We go backwards, to try to allow for controls that are spacially
1313 // within other controls, but are still siblings (e.g. buttons within
1314 // static boxes). Static boxes are likely to be created _before_ controls
1315 // that sit inside them.
1316 wxWindow
* wxFindWindowAtPoint(wxWindow
* win
, const wxPoint
& pt
)
1318 if (!win
->IsShown())
1321 // Hack for wxNotebook case: at least in wxGTK, all pages
1322 // claim to be shown, so we must only deal with the selected one.
1324 if (win
->IsKindOf(CLASSINFO(wxNotebook
)))
1326 wxNotebook
* nb
= (wxNotebook
*) win
;
1327 int sel
= nb
->GetSelection();
1330 wxWindow
* child
= nb
->GetPage(sel
);
1331 wxWindow
* foundWin
= wxFindWindowAtPoint(child
, pt
);
1338 wxWindowList::compatibility_iterator node
= win
->GetChildren().GetLast();
1341 wxWindow
* child
= node
->GetData();
1342 wxWindow
* foundWin
= wxFindWindowAtPoint(child
, pt
);
1345 node
= node
->GetPrevious();
1348 wxPoint pos
= win
->GetPosition();
1349 wxSize sz
= win
->GetSize();
1350 if ( !win
->IsTopLevel() && win
->GetParent() )
1352 pos
= win
->GetParent()->ClientToScreen(pos
);
1355 wxRect
rect(pos
, sz
);
1356 if (rect
.Contains(pt
))
1362 wxWindow
* wxGenericFindWindowAtPoint(const wxPoint
& pt
)
1364 // Go backwards through the list since windows
1365 // on top are likely to have been appended most
1367 wxWindowList::compatibility_iterator node
= wxTopLevelWindows
.GetLast();
1370 wxWindow
* win
= node
->GetData();
1371 wxWindow
* found
= wxFindWindowAtPoint(win
, pt
);
1374 node
= node
->GetPrevious();
1379 // ----------------------------------------------------------------------------
1381 // ----------------------------------------------------------------------------
1384 * N.B. these convenience functions must be separate from msgdlgg.cpp, textdlgg.cpp
1385 * since otherwise the generic code may be pulled in unnecessarily.
1390 int wxMessageBox(const wxString
& message
, const wxString
& caption
, long style
,
1391 wxWindow
*parent
, int WXUNUSED(x
), int WXUNUSED(y
) )
1393 long decorated_style
= style
;
1395 if ( ( style
& ( wxICON_EXCLAMATION
| wxICON_HAND
| wxICON_INFORMATION
| wxICON_QUESTION
) ) == 0 )
1397 decorated_style
|= ( style
& wxYES
) ? wxICON_QUESTION
: wxICON_INFORMATION
;
1400 wxMessageDialog
dialog(parent
, message
, caption
, decorated_style
);
1402 int ans
= dialog
.ShowModal();
1415 wxFAIL_MSG( _T("unexpected return code from wxMessageDialog") );
1420 void wxInfoMessageBox(wxWindow
* parent
)
1422 // don't translate these strings, they're for diagnostics purposes only
1424 msg
.Printf(_T("wxWidgets Library (%s port)\n")
1425 _T("Version %d.%d.%d%s%s, compiled at %s %s\n")
1426 _T("Runtime version of toolkit used is %d.%d.%s\n")
1427 _T("Copyright (c) 1995-2008 wxWidgets team"),
1428 wxPlatformInfo::Get().GetPortIdName().c_str(),
1444 wxPlatformInfo::Get().GetToolkitMajorVersion(),
1445 wxPlatformInfo::Get().GetToolkitMinorVersion(),
1447 wxString::Format("\nThe compile-time GTK+ version is %d.%d.%d.",
1450 GTK_MICRO_VERSION
).c_str()
1455 wxMessageBox(msg
, _T("wxWidgets information"),
1456 wxICON_INFORMATION
| wxOK
,
1460 #endif // wxUSE_MSGDLG
1464 wxString
wxGetTextFromUser(const wxString
& message
, const wxString
& caption
,
1465 const wxString
& defaultValue
, wxWindow
*parent
,
1466 wxCoord x
, wxCoord y
, bool centre
)
1469 long style
= wxTextEntryDialogStyle
;
1476 wxTextEntryDialog
dialog(parent
, message
, caption
, defaultValue
, style
, wxPoint(x
, y
));
1478 if (dialog
.ShowModal() == wxID_OK
)
1480 str
= dialog
.GetValue();
1486 wxString
wxGetPasswordFromUser(const wxString
& message
,
1487 const wxString
& caption
,
1488 const wxString
& defaultValue
,
1490 wxCoord x
, wxCoord y
, bool centre
)
1493 long style
= wxTextEntryDialogStyle
;
1500 wxPasswordEntryDialog
dialog(parent
, message
, caption
, defaultValue
,
1501 style
, wxPoint(x
, y
));
1502 if ( dialog
.ShowModal() == wxID_OK
)
1504 str
= dialog
.GetValue();
1510 #endif // wxUSE_TEXTDLG
1514 wxColour
wxGetColourFromUser(wxWindow
*parent
,
1515 const wxColour
& colInit
,
1516 const wxString
& caption
,
1517 wxColourData
*ptrData
)
1519 // contains serialized representation of wxColourData used the last time
1520 // the dialog was shown: we want to reuse it the next time in order to show
1521 // the same custom colours to the user (and we can't just have static
1522 // wxColourData itself because it's a GUI object and so should be destroyed
1523 // before GUI shutdown and doing it during static cleanup is too late)
1524 static wxString s_strColourData
;
1530 if ( !s_strColourData
.empty() )
1532 if ( !data
.FromString(s_strColourData
) )
1534 wxFAIL_MSG( "bug in wxColourData::FromString()?" );
1538 // we don't get back the "choose full" flag value from the native
1539 // dialog and so we can't preserve it between runs, so we decide to
1540 // always use it as it seems better than not using it (user can
1541 // just ignore the extra controls in the dialog but having to click
1542 // a button each time to show them would be very annoying
1543 data
.SetChooseFull(true);
1548 if ( colInit
.IsOk() )
1550 ptrData
->SetColour(colInit
);
1554 wxColourDialog
dialog(parent
, ptrData
);
1555 if (!caption
.empty())
1556 dialog
.SetTitle(caption
);
1557 if ( dialog
.ShowModal() == wxID_OK
)
1559 *ptrData
= dialog
.GetColourData();
1560 colRet
= ptrData
->GetColour();
1561 s_strColourData
= ptrData
->ToString();
1563 //else: leave colRet invalid
1568 #endif // wxUSE_COLOURDLG
1572 wxFont
wxGetFontFromUser(wxWindow
*parent
, const wxFont
& fontInit
, const wxString
& caption
)
1575 if ( fontInit
.Ok() )
1577 data
.SetInitialFont(fontInit
);
1581 wxFontDialog
dialog(parent
, data
);
1582 if (!caption
.empty())
1583 dialog
.SetTitle(caption
);
1584 if ( dialog
.ShowModal() == wxID_OK
)
1586 fontRet
= dialog
.GetFontData().GetChosenFont();
1588 //else: leave it invalid
1593 #endif // wxUSE_FONTDLG
1595 // ----------------------------------------------------------------------------
1596 // wxSafeYield and supporting functions
1597 // ----------------------------------------------------------------------------
1599 void wxEnableTopLevelWindows(bool enable
)
1601 wxWindowList::compatibility_iterator node
;
1602 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1603 node
->GetData()->Enable(enable
);
1606 wxWindowDisabler::wxWindowDisabler(bool disable
)
1608 m_disabled
= disable
;
1613 wxWindowDisabler::wxWindowDisabler(wxWindow
*winToSkip
)
1616 DoDisable(winToSkip
);
1619 void wxWindowDisabler::DoDisable(wxWindow
*winToSkip
)
1621 // remember the top level windows which were already disabled, so that we
1622 // don't reenable them later
1623 m_winDisabled
= NULL
;
1625 wxWindowList::compatibility_iterator node
;
1626 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1628 wxWindow
*winTop
= node
->GetData();
1629 if ( winTop
== winToSkip
)
1632 // we don't need to disable the hidden or already disabled windows
1633 if ( winTop
->IsEnabled() && winTop
->IsShown() )
1639 if ( !m_winDisabled
)
1641 m_winDisabled
= new wxWindowList
;
1644 m_winDisabled
->Append(winTop
);
1649 wxWindowDisabler::~wxWindowDisabler()
1654 wxWindowList::compatibility_iterator node
;
1655 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1657 wxWindow
*winTop
= node
->GetData();
1658 if ( !m_winDisabled
|| !m_winDisabled
->Find(winTop
) )
1662 //else: had been already disabled, don't reenable
1665 delete m_winDisabled
;
1668 // Yield to other apps/messages and disable user input to all windows except
1670 bool wxSafeYield(wxWindow
*win
, bool onlyIfNeeded
)
1672 wxWindowDisabler
wd(win
);
1676 rc
= wxYieldIfNeeded();
1683 // Don't synthesize KeyUp events holding down a key and producing KeyDown
1684 // events with autorepeat. On by default and always on in wxMSW. wxGTK version
1687 bool wxSetDetectableAutoRepeat( bool WXUNUSED(flag
) )
1689 return true; // detectable auto-repeat is the only mode MSW supports