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/mac/private.h"
89 #include "InternetConfig.h"
94 #if !defined(__MWERKS__) && !defined(__WXWINCE__)
95 #include <sys/types.h>
98 #endif // ! __WXPALMOS5__
100 #if defined(__WXMSW__)
101 #include "wx/msw/private.h"
102 #include "wx/msw/registry.h"
103 #include <shellapi.h> // needed for SHELLEXECUTEINFO
106 #if wxUSE_GUI && defined(__WXGTK__)
107 #include <gtk/gtk.h> // for GTK_XXX_VERSION constants
112 // ----------------------------------------------------------------------------
114 // ----------------------------------------------------------------------------
116 // ============================================================================
118 // ============================================================================
120 // Array used in DecToHex conversion routine.
121 static wxChar hexArray
[] = wxT("0123456789ABCDEF");
123 // Convert 2-digit hex number to decimal
124 int wxHexToDec(const wxString
& buf
)
126 int firstDigit
, secondDigit
;
128 if (buf
.GetChar(0) >= wxT('A'))
129 firstDigit
= buf
.GetChar(0) - wxT('A') + 10;
131 firstDigit
= buf
.GetChar(0) - wxT('0');
133 if (buf
.GetChar(1) >= wxT('A'))
134 secondDigit
= buf
.GetChar(1) - wxT('A') + 10;
136 secondDigit
= buf
.GetChar(1) - wxT('0');
138 return (firstDigit
& 0xF) * 16 + (secondDigit
& 0xF );
141 // Convert decimal integer to 2-character hex string
142 void wxDecToHex(int dec
, wxChar
*buf
)
144 int firstDigit
= (int)(dec
/16.0);
145 int secondDigit
= (int)(dec
- (firstDigit
*16.0));
146 buf
[0] = hexArray
[firstDigit
];
147 buf
[1] = hexArray
[secondDigit
];
151 // Convert decimal integer to 2 characters
152 void wxDecToHex(int dec
, char* ch1
, char* ch2
)
154 int firstDigit
= (int)(dec
/16.0);
155 int secondDigit
= (int)(dec
- (firstDigit
*16.0));
156 (*ch1
) = (char) hexArray
[firstDigit
];
157 (*ch2
) = (char) hexArray
[secondDigit
];
160 // Convert decimal integer to 2-character hex string
161 wxString
wxDecToHex(int dec
)
164 wxDecToHex(dec
, buf
);
165 return wxString(buf
);
168 // ----------------------------------------------------------------------------
170 // ----------------------------------------------------------------------------
172 // Return the current date/time
177 wxDateTime now
= wxDateTime::Now();
180 return wxEmptyString
;
183 time_t now
= time((time_t *) NULL
);
184 char *date
= ctime(&now
);
186 return wxString::FromAscii(date
);
190 void wxUsleep(unsigned long milliseconds
)
192 wxMilliSleep(milliseconds
);
195 const wxChar
*wxGetInstallPrefix()
199 if ( wxGetEnv(wxT("WXPREFIX"), &prefix
) )
200 return prefix
.c_str();
202 #ifdef wxINSTALL_PREFIX
203 return wxT(wxINSTALL_PREFIX
);
205 return wxEmptyString
;
209 wxString
wxGetDataDir()
211 wxString dir
= wxGetInstallPrefix();
212 dir
<< wxFILE_SEP_PATH
<< wxT("share") << wxFILE_SEP_PATH
<< wxT("wx");
216 bool wxIsPlatformLittleEndian()
218 // Are we little or big endian? This method is from Harbison & Steele.
222 char c
[sizeof(long)];
231 * Class to make it easier to specify platform-dependent values
234 wxArrayInt
* wxPlatform::sm_customPlatforms
= NULL
;
236 void wxPlatform::Copy(const wxPlatform
& platform
)
238 m_longValue
= platform
.m_longValue
;
239 m_doubleValue
= platform
.m_doubleValue
;
240 m_stringValue
= platform
.m_stringValue
;
243 wxPlatform
wxPlatform::If(int platform
, long value
)
246 return wxPlatform(value
);
251 wxPlatform
wxPlatform::IfNot(int platform
, long value
)
254 return wxPlatform(value
);
259 wxPlatform
& wxPlatform::ElseIf(int platform
, long value
)
266 wxPlatform
& wxPlatform::ElseIfNot(int platform
, long value
)
273 wxPlatform
wxPlatform::If(int platform
, double value
)
276 return wxPlatform(value
);
281 wxPlatform
wxPlatform::IfNot(int platform
, double value
)
284 return wxPlatform(value
);
289 wxPlatform
& wxPlatform::ElseIf(int platform
, double value
)
292 m_doubleValue
= value
;
296 wxPlatform
& wxPlatform::ElseIfNot(int platform
, double value
)
299 m_doubleValue
= value
;
303 wxPlatform
wxPlatform::If(int platform
, const wxString
& value
)
306 return wxPlatform(value
);
311 wxPlatform
wxPlatform::IfNot(int platform
, const wxString
& value
)
314 return wxPlatform(value
);
319 wxPlatform
& wxPlatform::ElseIf(int platform
, const wxString
& value
)
322 m_stringValue
= value
;
326 wxPlatform
& wxPlatform::ElseIfNot(int platform
, const wxString
& value
)
329 m_stringValue
= value
;
333 wxPlatform
& wxPlatform::Else(long value
)
339 wxPlatform
& wxPlatform::Else(double value
)
341 m_doubleValue
= value
;
345 wxPlatform
& wxPlatform::Else(const wxString
& value
)
347 m_stringValue
= value
;
351 void wxPlatform::AddPlatform(int platform
)
353 if (!sm_customPlatforms
)
354 sm_customPlatforms
= new wxArrayInt
;
355 sm_customPlatforms
->Add(platform
);
358 void wxPlatform::ClearPlatforms()
360 delete sm_customPlatforms
;
361 sm_customPlatforms
= NULL
;
364 /// Function for testing current platform
366 bool wxPlatform::Is(int platform
)
369 if (platform
== wxOS_WINDOWS
)
373 if (platform
== wxOS_WINDOWS_CE
)
379 // FIXME: wxWinPocketPC and wxWinSmartPhone are unknown symbols
381 #if defined(__WXWINCE__) && defined(__POCKETPC__)
382 if (platform
== wxWinPocketPC
)
385 #if defined(__WXWINCE__) && defined(__SMARTPHONE__)
386 if (platform
== wxWinSmartPhone
)
393 if (platform
== wxPORT_GTK
)
397 if (platform
== wxPORT_MAC
)
401 if (platform
== wxPORT_X11
)
405 if (platform
== wxOS_UNIX
)
409 if (platform
== wxPORT_MGL
)
413 if (platform
== wxOS_OS2
)
417 if (platform
== wxPORT_PM
)
421 if (platform
== wxPORT_MAC
)
425 if (sm_customPlatforms
&& sm_customPlatforms
->Index(platform
) != wxNOT_FOUND
)
431 // ----------------------------------------------------------------------------
432 // network and user id functions
433 // ----------------------------------------------------------------------------
435 // Get Full RFC822 style email address
436 bool wxGetEmailAddress(wxChar
*address
, int maxSize
)
438 wxString email
= wxGetEmailAddress();
442 wxStrncpy(address
, email
, maxSize
- 1);
443 address
[maxSize
- 1] = wxT('\0');
448 wxString
wxGetEmailAddress()
452 wxString host
= wxGetFullHostName();
455 wxString user
= wxGetUserId();
458 email
<< user
<< wxT('@') << host
;
465 wxString
wxGetUserId()
467 static const int maxLoginLen
= 256; // FIXME arbitrary number
470 bool ok
= wxGetUserId(wxStringBuffer(buf
, maxLoginLen
), maxLoginLen
);
478 wxString
wxGetUserName()
480 static const int maxUserNameLen
= 1024; // FIXME arbitrary number
483 bool ok
= wxGetUserName(wxStringBuffer(buf
, maxUserNameLen
), maxUserNameLen
);
491 wxString
wxGetHostName()
493 static const size_t hostnameSize
= 257;
496 bool ok
= wxGetHostName(wxStringBuffer(buf
, hostnameSize
), hostnameSize
);
504 wxString
wxGetFullHostName()
506 static const size_t hostnameSize
= 257;
509 bool ok
= wxGetFullHostName(wxStringBuffer(buf
, hostnameSize
), hostnameSize
);
517 wxString
wxGetHomeDir()
527 wxString
wxGetCurrentDir()
534 ok
= getcwd(dir
.GetWriteBuf(len
+ 1), len
) != NULL
;
539 if ( errno
!= ERANGE
)
541 wxLogSysError(_T("Failed to get current directory"));
543 return wxEmptyString
;
547 // buffer was too small, retry with a larger one
559 // ----------------------------------------------------------------------------
561 // ----------------------------------------------------------------------------
563 // wxDoExecuteWithCapture() helper: reads an entire stream into one array
565 // returns true if ok, false if error
567 static bool ReadAll(wxInputStream
*is
, wxArrayString
& output
)
569 wxCHECK_MSG( is
, false, _T("NULL stream in wxExecute()?") );
571 // the stream could be already at EOF or in wxSTREAM_BROKEN_PIPE state
574 wxTextInputStream
tis(*is
);
578 wxString line
= tis
.ReadLine();
580 // check for EOF before other errors as it's not really an error
583 // add the last, possibly incomplete, line
589 // any other error is fatal
598 #endif // wxUSE_STREAMS
600 // this is a private function because it hasn't a clean interface: the first
601 // array is passed by reference, the second by pointer - instead we have 2
602 // public versions of wxExecute() below
603 static long wxDoExecuteWithCapture(const wxString
& command
,
604 wxArrayString
& output
,
605 wxArrayString
* error
,
608 // create a wxProcess which will capture the output
609 wxProcess
*process
= new wxProcess
;
612 long rc
= wxExecute(command
, wxEXEC_SYNC
| flags
, process
);
617 if ( !ReadAll(process
->GetInputStream(), output
) )
622 if ( !ReadAll(process
->GetErrorStream(), *error
) )
630 #endif // wxUSE_STREAMS/!wxUSE_STREAMS
637 long wxExecute(const wxString
& command
, wxArrayString
& output
, int flags
)
639 return wxDoExecuteWithCapture(command
, output
, NULL
, flags
);
642 long wxExecute(const wxString
& command
,
643 wxArrayString
& output
,
644 wxArrayString
& error
,
647 return wxDoExecuteWithCapture(command
, output
, &error
, flags
);
650 // ----------------------------------------------------------------------------
651 // wxApp::Yield() wrappers for backwards compatibility
652 // ----------------------------------------------------------------------------
656 return wxTheApp
&& wxTheApp
->Yield();
659 bool wxYieldIfNeeded()
661 return wxTheApp
&& wxTheApp
->Yield(true);
665 static long wxCurrentId
= 100;
669 // skip the part of IDs space that contains hard-coded values:
670 if (wxCurrentId
== wxID_LOWEST
)
671 wxCurrentId
= wxID_HIGHEST
+ 1;
673 return wxCurrentId
++;
677 wxGetCurrentId(void) { return wxCurrentId
; }
680 wxRegisterId (long id
)
682 if (id
>= wxCurrentId
)
683 wxCurrentId
= id
+ 1;
686 // ----------------------------------------------------------------------------
687 // wxQsort, adapted by RR to allow user_data
688 // ----------------------------------------------------------------------------
690 /* This file is part of the GNU C Library.
691 Written by Douglas C. Schmidt (schmidt@ics.uci.edu).
693 Douglas Schmidt kindly gave permission to relicence the
694 code under the wxWindows licence:
696 From: "Douglas C. Schmidt" <schmidt@dre.vanderbilt.edu>
697 To: Robert Roebling <robert.roebling@uni-ulm.de>
698 Subject: Re: qsort licence
699 Date: Mon, 23 Jul 2007 03:44:25 -0500
700 Sender: schmidt@dre.vanderbilt.edu
701 Message-Id: <20070723084426.64F511000A8@tango.dre.vanderbilt.edu>
705 > [...] I'm asking if you'd be willing to relicence your code
706 > under the wxWindows licence. [...]
708 That's fine with me [...]
715 /* Byte-wise swap two items of size SIZE. */
716 #define SWAP(a, b, size) \
719 register size_t __size = (size); \
720 register char *__a = (a), *__b = (b); \
726 } while (--__size > 0); \
729 /* Discontinue quicksort algorithm when partition gets below this size.
730 This particular magic number was chosen to work best on a Sun 4/260. */
733 /* Stack node declarations used to store unfulfilled partition obligations. */
740 /* The next 4 #defines implement a very fast in-line stack abstraction. */
741 #define STACK_SIZE (8 * sizeof(unsigned long int))
742 #define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top))
743 #define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi)))
744 #define STACK_NOT_EMPTY (stack < top)
747 /* Order size using quicksort. This implementation incorporates
748 four optimizations discussed in Sedgewick:
750 1. Non-recursive, using an explicit stack of pointer that store the
751 next array partition to sort. To save time, this maximum amount
752 of space required to store an array of MAX_INT is allocated on the
753 stack. Assuming a 32-bit integer, this needs only 32 *
754 sizeof(stack_node) == 136 bits. Pretty cheap, actually.
756 2. Chose the pivot element using a median-of-three decision tree.
757 This reduces the probability of selecting a bad pivot value and
758 eliminates certain extraneous comparisons.
760 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving
761 insertion sort to order the MAX_THRESH items within each partition.
762 This is a big win, since insertion sort is faster for small, mostly
763 sorted array segments.
765 4. The larger of the two sub-partitions is always pushed onto the
766 stack first, with the algorithm then concentrating on the
767 smaller partition. This *guarantees* no more than log (n)
768 stack size is needed (actually O(1) in this case)! */
770 void wxQsort(void *const pbase
, size_t total_elems
,
771 size_t size
, CMPFUNCDATA cmp
, const void* user_data
)
773 register char *base_ptr
= (char *) pbase
;
774 const size_t max_thresh
= MAX_THRESH
* size
;
776 if (total_elems
== 0)
777 /* Avoid lossage with unsigned arithmetic below. */
780 if (total_elems
> MAX_THRESH
)
783 char *hi
= &lo
[size
* (total_elems
- 1)];
784 stack_node stack
[STACK_SIZE
];
785 stack_node
*top
= stack
;
789 while (STACK_NOT_EMPTY
)
794 /* Select median value from among LO, MID, and HI. Rearrange
795 LO and HI so the three values are sorted. This lowers the
796 probability of picking a pathological pivot value and
797 skips a comparison for both the LEFT_PTR and RIGHT_PTR. */
799 char *mid
= lo
+ size
* ((hi
- lo
) / size
>> 1);
801 if ((*cmp
) ((void *) mid
, (void *) lo
, user_data
) < 0)
802 SWAP (mid
, lo
, size
);
803 if ((*cmp
) ((void *) hi
, (void *) mid
, user_data
) < 0)
804 SWAP (mid
, hi
, size
);
807 if ((*cmp
) ((void *) mid
, (void *) lo
, user_data
) < 0)
808 SWAP (mid
, lo
, size
);
810 left_ptr
= lo
+ size
;
811 right_ptr
= hi
- size
;
813 /* Here's the famous ``collapse the walls'' section of quicksort.
814 Gotta like those tight inner loops! They are the main reason
815 that this algorithm runs much faster than others. */
818 while ((*cmp
) ((void *) left_ptr
, (void *) mid
, user_data
) < 0)
821 while ((*cmp
) ((void *) mid
, (void *) right_ptr
, user_data
) < 0)
824 if (left_ptr
< right_ptr
)
826 SWAP (left_ptr
, right_ptr
, size
);
829 else if (mid
== right_ptr
)
834 else if (left_ptr
== right_ptr
)
841 while (left_ptr
<= right_ptr
);
843 /* Set up pointers for next iteration. First determine whether
844 left and right partitions are below the threshold size. If so,
845 ignore one or both. Otherwise, push the larger partition's
846 bounds on the stack and continue sorting the smaller one. */
848 if ((size_t) (right_ptr
- lo
) <= max_thresh
)
850 if ((size_t) (hi
- left_ptr
) <= max_thresh
)
851 /* Ignore both small partitions. */
854 /* Ignore small left partition. */
857 else if ((size_t) (hi
- left_ptr
) <= max_thresh
)
858 /* Ignore small right partition. */
860 else if ((right_ptr
- lo
) > (hi
- left_ptr
))
862 /* Push larger left partition indices. */
863 PUSH (lo
, right_ptr
);
868 /* Push larger right partition indices. */
875 /* Once the BASE_PTR array is partially sorted by quicksort the rest
876 is completely sorted using insertion sort, since this is efficient
877 for partitions below MAX_THRESH size. BASE_PTR points to the beginning
878 of the array to sort, and END_PTR points at the very last element in
879 the array (*not* one beyond it!). */
882 char *const end_ptr
= &base_ptr
[size
* (total_elems
- 1)];
883 char *tmp_ptr
= base_ptr
;
884 char *thresh
= base_ptr
+ max_thresh
;
885 if ( thresh
> end_ptr
)
887 register char *run_ptr
;
889 /* Find smallest element in first threshold and place it at the
890 array's beginning. This is the smallest array element,
891 and the operation speeds up insertion sort's inner loop. */
893 for (run_ptr
= tmp_ptr
+ size
; run_ptr
<= thresh
; run_ptr
+= size
)
894 if ((*cmp
) ((void *) run_ptr
, (void *) tmp_ptr
, user_data
) < 0)
897 if (tmp_ptr
!= base_ptr
)
898 SWAP (tmp_ptr
, base_ptr
, size
);
900 /* Insertion sort, running from left-hand-side up to right-hand-side. */
902 run_ptr
= base_ptr
+ size
;
903 while ((run_ptr
+= size
) <= end_ptr
)
905 tmp_ptr
= run_ptr
- size
;
906 while ((*cmp
) ((void *) run_ptr
, (void *) tmp_ptr
, user_data
) < 0)
910 if (tmp_ptr
!= run_ptr
)
914 trav
= run_ptr
+ size
;
915 while (--trav
>= run_ptr
)
920 for (hi
= lo
= trav
; (lo
-= size
) >= tmp_ptr
; hi
= lo
)
933 // ============================================================================
934 // GUI-only functions from now on
935 // ============================================================================
939 // ----------------------------------------------------------------------------
940 // Launch default browser
941 // ----------------------------------------------------------------------------
944 // Private method in Objective-C++ source file.
945 bool wxCocoaLaunchDefaultBrowser(const wxString
& url
, int flags
);
948 bool wxLaunchDefaultBrowser(const wxString
& urlOrig
, int flags
)
952 // set the scheme of url to http if it does not have one
953 // RR: This doesn't work if the url is just a local path
954 wxString
url(urlOrig
);
956 if ( !uri
.HasScheme() )
958 if (wxFileExists(urlOrig
))
959 url
.Prepend( wxT("file://") );
961 url
.Prepend(wxT("http://"));
965 #if defined(__WXMSW__)
968 if ( flags
& wxBROWSER_NEW_WINDOW
)
970 // ShellExecuteEx() opens the URL in an existing window by default so
971 // we can't use it if we need a new window
972 wxRegKey
key(wxRegKey::HKCR
, uri
.GetScheme() + _T("\\shell\\open"));
975 // try default browser, it must be registered at least for http URLs
976 key
.SetName(wxRegKey::HKCR
, _T("http\\shell\\open"));
981 wxRegKey
keyDDE(key
, wxT("DDEExec"));
982 if ( keyDDE
.Exists() )
984 const wxString ddeTopic
= wxRegKey(keyDDE
, wxT("topic"));
986 // we only know the syntax of WWW_OpenURL DDE request for IE,
987 // optimistically assume that all other browsers are compatible
990 bool ok
= ddeTopic
== wxT("WWW_OpenURL");
993 ddeCmd
= keyDDE
.QueryDefaultValue();
994 ok
= !ddeCmd
.empty();
999 // for WWW_OpenURL, the index of the window to open the URL
1000 // in is -1 (meaning "current") by default, replace it with
1001 // 0 which means "new" (see KB article 160957)
1002 ok
= ddeCmd
.Replace(wxT("-1"), wxT("0"),
1003 false /* only first occurence */) == 1;
1008 // and also replace the parameters: the topic should
1009 // contain a placeholder for the URL
1010 ok
= ddeCmd
.Replace(wxT("%1"), url
, false) == 1;
1015 // try to send it the DDE request now but ignore the errors
1018 const wxString ddeServer
= wxRegKey(keyDDE
, wxT("application"));
1019 if ( wxExecuteDDE(ddeServer
, ddeTopic
, ddeCmd
) )
1022 // this is not necessarily an error: maybe browser is
1023 // simply not running, but no matter, in any case we're
1024 // going to launch it using ShellExecuteEx() below now and
1025 // we shouldn't try to open a new window if we open a new
1033 WinStruct
<SHELLEXECUTEINFO
> sei
;
1034 sei
.lpFile
= url
.c_str();
1035 sei
.lpVerb
= _T("open");
1036 sei
.nShow
= SW_SHOWNORMAL
;
1038 ::ShellExecuteEx(&sei
);
1040 const INT_PTR nResult
= (INT_PTR
)sei
.hInstApp
;
1042 // Firefox returns file not found for some reason, so make an exception
1044 if ( nResult
> 32 || nResult
== SE_ERR_FNF
)
1047 // Log something if SE_ERR_FNF happens
1048 if ( nResult
== SE_ERR_FNF
)
1049 wxLogDebug(wxT("SE_ERR_FNF from ShellExecute -- maybe FireFox?"));
1050 #endif // __WXDEBUG__
1053 #elif defined(__WXCOCOA__)
1054 // NOTE: We need to call the real implementation from src/cocoa/utils.mm
1055 // because the code must use Objective-C features.
1056 return wxCocoaLaunchDefaultBrowser(url
, flags
);
1057 #elif defined(__WXMAC__)
1063 err
= ICStart(&inst
, 'STKA'); // put your app creator code here
1068 ConstStr255Param hint
= 0;
1070 endSel
= url
.length();
1071 err
= ICLaunchURL(inst
, hint
, url
.fn_str(), endSel
, &startSel
, &endSel
);
1073 wxLogDebug(wxT("ICLaunchURL error %d"), (int) err
);
1080 wxLogDebug(wxT("ICStart error %d"), (int) err
);
1084 // (non-Mac, non-MSW)
1088 // Our best best is to use xdg-open from freedesktop.org cross-desktop
1089 // compatibility suite xdg-utils
1090 // (see http://portland.freedesktop.org/wiki/) -- this is installed on
1091 // most modern distributions and may be tweaked by them to handle
1092 // distribution specifics. Only if that fails, try to find the right
1093 // browser ourselves.
1094 wxString path
, xdg_open
;
1095 if ( wxGetEnv("PATH", &path
) &&
1096 wxFindFileInPath(&xdg_open
, path
, "xdg-open") )
1098 if ( wxExecute(xdg_open
+ " " + url
) )
1102 wxString desktop
= wxTheApp
->GetTraits()->GetDesktopEnvironment();
1104 // GNOME and KDE desktops have some applications which should be always installed
1105 // together with their main parts, which give us the
1106 if (desktop
== wxT("GNOME"))
1108 wxArrayString errors
;
1109 wxArrayString output
;
1111 // gconf will tell us the path of the application to use as browser
1112 long res
= wxExecute( wxT("gconftool-2 --get /desktop/gnome/applications/browser/exec"),
1113 output
, errors
, wxEXEC_NODISABLE
);
1114 if (res
>= 0 && errors
.GetCount() == 0)
1116 wxString cmd
= output
[0];
1117 cmd
<< _T(' ') << url
;
1122 else if (desktop
== wxT("KDE"))
1124 // kfmclient directly opens the given URL
1125 if (wxExecute(wxT("kfmclient openURL ") + url
))
1134 wxFileType
*ft
= wxTheMimeTypesManager
->GetFileTypeFromExtension(_T("html"));
1138 ft
->GetMimeType(&mt
);
1140 ok
= ft
->GetOpenCommand(&cmd
, wxFileType::MessageParameters(url
));
1143 #endif // wxUSE_MIMETYPE
1145 if ( !ok
|| cmd
.empty() )
1147 // fallback to checking for the BROWSER environment variable
1148 cmd
= wxGetenv(wxT("BROWSER"));
1150 cmd
<< _T(' ') << url
;
1153 ok
= ( !cmd
.empty() && wxExecute(cmd
) );
1157 // no file type for HTML extension
1158 wxLogError(_("No default application configured for HTML files."));
1160 #endif // !wxUSE_MIMETYPE && !__WXMSW__
1162 wxLogSysError(_("Failed to open URL \"%s\" in default browser."),
1168 // ----------------------------------------------------------------------------
1169 // Menu accelerators related functions
1170 // ----------------------------------------------------------------------------
1172 wxChar
*wxStripMenuCodes(const wxChar
*in
, wxChar
*out
)
1175 wxString s
= wxMenuItem::GetLabelText(in
);
1178 wxString s
= wxStripMenuCodes(str
);
1179 #endif // wxUSE_MENUS
1182 // go smash their buffer if it's not big enough - I love char * params
1183 memcpy(out
, s
.c_str(), s
.length() * sizeof(wxChar
));
1187 out
= new wxChar
[s
.length() + 1];
1188 wxStrcpy(out
, s
.c_str());
1194 wxString
wxStripMenuCodes(const wxString
& in
, int flags
)
1196 wxASSERT_MSG( flags
, _T("this is useless to call without any flags") );
1200 size_t len
= in
.length();
1203 for ( size_t n
= 0; n
< len
; n
++ )
1206 if ( (flags
& wxStrip_Mnemonics
) && ch
== _T('&') )
1208 // skip it, it is used to introduce the accel char (or to quote
1209 // itself in which case it should still be skipped): note that it
1210 // can't be the last character of the string
1213 wxLogDebug(_T("Invalid menu string '%s'"), in
.c_str());
1217 // use the next char instead
1221 else if ( (flags
& wxStrip_Accel
) && ch
== _T('\t') )
1223 // everything after TAB is accel string, exit the loop
1233 // ----------------------------------------------------------------------------
1234 // Window search functions
1235 // ----------------------------------------------------------------------------
1238 * If parent is non-NULL, look through children for a label or title
1239 * matching the specified string. If NULL, look through all top-level windows.
1244 wxFindWindowByLabel (const wxString
& title
, wxWindow
* parent
)
1246 return wxWindow::FindWindowByLabel( title
, parent
);
1251 * If parent is non-NULL, look through children for a name
1252 * matching the specified string. If NULL, look through all top-level windows.
1257 wxFindWindowByName (const wxString
& name
, wxWindow
* parent
)
1259 return wxWindow::FindWindowByName( name
, parent
);
1262 // Returns menu item id or wxNOT_FOUND if none.
1264 wxFindMenuItemId(wxFrame
*frame
,
1265 const wxString
& menuString
,
1266 const wxString
& itemString
)
1269 wxMenuBar
*menuBar
= frame
->GetMenuBar ();
1271 return menuBar
->FindMenuItem (menuString
, itemString
);
1272 #else // !wxUSE_MENUS
1274 wxUnusedVar(menuString
);
1275 wxUnusedVar(itemString
);
1276 #endif // wxUSE_MENUS/!wxUSE_MENUS
1281 // Try to find the deepest child that contains 'pt'.
1282 // We go backwards, to try to allow for controls that are spacially
1283 // within other controls, but are still siblings (e.g. buttons within
1284 // static boxes). Static boxes are likely to be created _before_ controls
1285 // that sit inside them.
1286 wxWindow
* wxFindWindowAtPoint(wxWindow
* win
, const wxPoint
& pt
)
1288 if (!win
->IsShown())
1291 // Hack for wxNotebook case: at least in wxGTK, all pages
1292 // claim to be shown, so we must only deal with the selected one.
1294 if (win
->IsKindOf(CLASSINFO(wxNotebook
)))
1296 wxNotebook
* nb
= (wxNotebook
*) win
;
1297 int sel
= nb
->GetSelection();
1300 wxWindow
* child
= nb
->GetPage(sel
);
1301 wxWindow
* foundWin
= wxFindWindowAtPoint(child
, pt
);
1308 wxWindowList::compatibility_iterator node
= win
->GetChildren().GetLast();
1311 wxWindow
* child
= node
->GetData();
1312 wxWindow
* foundWin
= wxFindWindowAtPoint(child
, pt
);
1315 node
= node
->GetPrevious();
1318 wxPoint pos
= win
->GetPosition();
1319 wxSize sz
= win
->GetSize();
1320 if ( !win
->IsTopLevel() && win
->GetParent() )
1322 pos
= win
->GetParent()->ClientToScreen(pos
);
1325 wxRect
rect(pos
, sz
);
1326 if (rect
.Contains(pt
))
1332 wxWindow
* wxGenericFindWindowAtPoint(const wxPoint
& pt
)
1334 // Go backwards through the list since windows
1335 // on top are likely to have been appended most
1337 wxWindowList::compatibility_iterator node
= wxTopLevelWindows
.GetLast();
1340 wxWindow
* win
= node
->GetData();
1341 wxWindow
* found
= wxFindWindowAtPoint(win
, pt
);
1344 node
= node
->GetPrevious();
1349 // ----------------------------------------------------------------------------
1351 // ----------------------------------------------------------------------------
1354 * N.B. these convenience functions must be separate from msgdlgg.cpp, textdlgg.cpp
1355 * since otherwise the generic code may be pulled in unnecessarily.
1360 int wxMessageBox(const wxString
& message
, const wxString
& caption
, long style
,
1361 wxWindow
*parent
, int WXUNUSED(x
), int WXUNUSED(y
) )
1363 long decorated_style
= style
;
1365 if ( ( style
& ( wxICON_EXCLAMATION
| wxICON_HAND
| wxICON_INFORMATION
| wxICON_QUESTION
) ) == 0 )
1367 decorated_style
|= ( style
& wxYES
) ? wxICON_QUESTION
: wxICON_INFORMATION
;
1370 wxMessageDialog
dialog(parent
, message
, caption
, decorated_style
);
1372 int ans
= dialog
.ShowModal();
1385 wxFAIL_MSG( _T("unexpected return code from wxMessageDialog") );
1390 void wxInfoMessageBox(wxWindow
* parent
)
1392 // don't translate these strings, they're for diagnostics purposes only
1394 msg
.Printf(_T("wxWidgets Library (%s port)\n")
1395 _T("Version %d.%d.%d%s%s, compiled at %s %s\n")
1396 _T("Runtime version of toolkit used is %d.%d.%s\n")
1397 _T("Copyright (c) 1995-2007 wxWidgets team"),
1398 wxPlatformInfo::Get().GetPortIdName().c_str(),
1414 wxPlatformInfo::Get().GetToolkitMajorVersion(),
1415 wxPlatformInfo::Get().GetToolkitMinorVersion(),
1417 wxString::Format("\nThe compile-time GTK+ version is %d.%d.%d.",
1420 GTK_MICRO_VERSION
).c_str()
1425 wxMessageBox(msg
, _T("wxWidgets information"),
1426 wxICON_INFORMATION
| wxOK
,
1430 #endif // wxUSE_MSGDLG
1434 wxString
wxGetTextFromUser(const wxString
& message
, const wxString
& caption
,
1435 const wxString
& defaultValue
, wxWindow
*parent
,
1436 wxCoord x
, wxCoord y
, bool centre
)
1439 long style
= wxTextEntryDialogStyle
;
1446 wxTextEntryDialog
dialog(parent
, message
, caption
, defaultValue
, style
, wxPoint(x
, y
));
1448 if (dialog
.ShowModal() == wxID_OK
)
1450 str
= dialog
.GetValue();
1456 wxString
wxGetPasswordFromUser(const wxString
& message
,
1457 const wxString
& caption
,
1458 const wxString
& defaultValue
,
1460 wxCoord x
, wxCoord y
, bool centre
)
1463 long style
= wxTextEntryDialogStyle
;
1470 wxPasswordEntryDialog
dialog(parent
, message
, caption
, defaultValue
,
1471 style
, wxPoint(x
, y
));
1472 if ( dialog
.ShowModal() == wxID_OK
)
1474 str
= dialog
.GetValue();
1480 #endif // wxUSE_TEXTDLG
1484 wxColour
wxGetColourFromUser(wxWindow
*parent
,
1485 const wxColour
& colInit
,
1486 const wxString
& caption
,
1487 wxColourData
*ptrData
)
1489 // contains serialized representation of wxColourData used the last time
1490 // the dialog was shown: we want to reuse it the next time in order to show
1491 // the same custom colours to the user (and we can't just have static
1492 // wxColourData itself because it's a GUI object and so should be destroyed
1493 // before GUI shutdown and doing it during static cleanup is too late)
1494 static wxString s_strColourData
;
1500 if ( !s_strColourData
.empty() )
1502 if ( !data
.FromString(s_strColourData
) )
1504 wxFAIL_MSG( "bug in wxColourData::FromString()?" );
1508 // we don't get back the "choose full" flag value from the native
1509 // dialog and so we can't preserve it between runs, so we decide to
1510 // always use it as it seems better than not using it (user can
1511 // just ignore the extra controls in the dialog but having to click
1512 // a button each time to show them would be very annoying
1513 data
.SetChooseFull(true);
1518 if ( colInit
.IsOk() )
1520 ptrData
->SetColour(colInit
);
1524 wxColourDialog
dialog(parent
, ptrData
);
1525 if (!caption
.empty())
1526 dialog
.SetTitle(caption
);
1527 if ( dialog
.ShowModal() == wxID_OK
)
1529 *ptrData
= dialog
.GetColourData();
1530 colRet
= ptrData
->GetColour();
1531 s_strColourData
= ptrData
->ToString();
1533 //else: leave colRet invalid
1538 #endif // wxUSE_COLOURDLG
1542 wxFont
wxGetFontFromUser(wxWindow
*parent
, const wxFont
& fontInit
, const wxString
& caption
)
1545 if ( fontInit
.Ok() )
1547 data
.SetInitialFont(fontInit
);
1551 wxFontDialog
dialog(parent
, data
);
1552 if (!caption
.empty())
1553 dialog
.SetTitle(caption
);
1554 if ( dialog
.ShowModal() == wxID_OK
)
1556 fontRet
= dialog
.GetFontData().GetChosenFont();
1558 //else: leave it invalid
1563 #endif // wxUSE_FONTDLG
1565 // ----------------------------------------------------------------------------
1566 // wxSafeYield and supporting functions
1567 // ----------------------------------------------------------------------------
1569 void wxEnableTopLevelWindows(bool enable
)
1571 wxWindowList::compatibility_iterator node
;
1572 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1573 node
->GetData()->Enable(enable
);
1576 wxWindowDisabler::wxWindowDisabler(wxWindow
*winToSkip
)
1578 // remember the top level windows which were already disabled, so that we
1579 // don't reenable them later
1580 m_winDisabled
= NULL
;
1582 wxWindowList::compatibility_iterator node
;
1583 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1585 wxWindow
*winTop
= node
->GetData();
1586 if ( winTop
== winToSkip
)
1589 // we don't need to disable the hidden or already disabled windows
1590 if ( winTop
->IsEnabled() && winTop
->IsShown() )
1596 if ( !m_winDisabled
)
1598 m_winDisabled
= new wxWindowList
;
1601 m_winDisabled
->Append(winTop
);
1606 wxWindowDisabler::~wxWindowDisabler()
1608 wxWindowList::compatibility_iterator node
;
1609 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1611 wxWindow
*winTop
= node
->GetData();
1612 if ( !m_winDisabled
|| !m_winDisabled
->Find(winTop
) )
1616 //else: had been already disabled, don't reenable
1619 delete m_winDisabled
;
1622 // Yield to other apps/messages and disable user input to all windows except
1624 bool wxSafeYield(wxWindow
*win
, bool onlyIfNeeded
)
1626 wxWindowDisabler
wd(win
);
1630 rc
= wxYieldIfNeeded();
1637 // Don't synthesize KeyUp events holding down a key and producing KeyDown
1638 // events with autorepeat. On by default and always on in wxMSW. wxGTK version
1641 bool wxSetDetectableAutoRepeat( bool WXUNUSED(flag
) )
1643 return true; // detectable auto-repeat is the only mode MSW supports