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__)
1058 wxCFRef
< CFURLRef
> curl( CFURLCreateWithString( kCFAllocatorDefault
,
1059 wxCFStringRef( url
), NULL
) );
1060 OSStatus err
= LSOpenCFURLRef( curl
, NULL
);
1068 wxLogDebug(wxT("Browser Launch error %d"), (int) err
);
1072 // (non-Mac, non-MSW)
1076 // Our best best is to use xdg-open from freedesktop.org cross-desktop
1077 // compatibility suite xdg-utils
1078 // (see http://portland.freedesktop.org/wiki/) -- this is installed on
1079 // most modern distributions and may be tweaked by them to handle
1080 // distribution specifics. Only if that fails, try to find the right
1081 // browser ourselves.
1082 wxString path
, xdg_open
;
1083 if ( wxGetEnv("PATH", &path
) &&
1084 wxFindFileInPath(&xdg_open
, path
, "xdg-open") )
1086 if ( wxExecute(xdg_open
+ " " + url
) )
1090 wxString desktop
= wxTheApp
->GetTraits()->GetDesktopEnvironment();
1092 // GNOME and KDE desktops have some applications which should be always installed
1093 // together with their main parts, which give us the
1094 if (desktop
== wxT("GNOME"))
1096 wxArrayString errors
;
1097 wxArrayString output
;
1099 // gconf will tell us the path of the application to use as browser
1100 long res
= wxExecute( wxT("gconftool-2 --get /desktop/gnome/applications/browser/exec"),
1101 output
, errors
, wxEXEC_NODISABLE
);
1102 if (res
>= 0 && errors
.GetCount() == 0)
1104 wxString cmd
= output
[0];
1105 cmd
<< _T(' ') << url
;
1110 else if (desktop
== wxT("KDE"))
1112 // kfmclient directly opens the given URL
1113 if (wxExecute(wxT("kfmclient openURL ") + url
))
1122 wxFileType
*ft
= wxTheMimeTypesManager
->GetFileTypeFromExtension(_T("html"));
1126 ft
->GetMimeType(&mt
);
1128 ok
= ft
->GetOpenCommand(&cmd
, wxFileType::MessageParameters(url
));
1131 #endif // wxUSE_MIMETYPE
1133 if ( !ok
|| cmd
.empty() )
1135 // fallback to checking for the BROWSER environment variable
1136 cmd
= wxGetenv(wxT("BROWSER"));
1138 cmd
<< _T(' ') << url
;
1141 ok
= ( !cmd
.empty() && wxExecute(cmd
) );
1145 // no file type for HTML extension
1146 wxLogError(_("No default application configured for HTML files."));
1148 #endif // !wxUSE_MIMETYPE && !__WXMSW__
1150 wxLogSysError(_("Failed to open URL \"%s\" in default browser."),
1156 // ----------------------------------------------------------------------------
1157 // Menu accelerators related functions
1158 // ----------------------------------------------------------------------------
1160 wxChar
*wxStripMenuCodes(const wxChar
*in
, wxChar
*out
)
1163 wxString s
= wxMenuItem::GetLabelText(in
);
1166 wxString s
= wxStripMenuCodes(str
);
1167 #endif // wxUSE_MENUS
1170 // go smash their buffer if it's not big enough - I love char * params
1171 memcpy(out
, s
.c_str(), s
.length() * sizeof(wxChar
));
1175 out
= new wxChar
[s
.length() + 1];
1176 wxStrcpy(out
, s
.c_str());
1182 wxString
wxStripMenuCodes(const wxString
& in
, int flags
)
1184 wxASSERT_MSG( flags
, _T("this is useless to call without any flags") );
1188 size_t len
= in
.length();
1191 for ( size_t n
= 0; n
< len
; n
++ )
1194 if ( (flags
& wxStrip_Mnemonics
) && ch
== _T('&') )
1196 // skip it, it is used to introduce the accel char (or to quote
1197 // itself in which case it should still be skipped): note that it
1198 // can't be the last character of the string
1201 wxLogDebug(_T("Invalid menu string '%s'"), in
.c_str());
1205 // use the next char instead
1209 else if ( (flags
& wxStrip_Accel
) && ch
== _T('\t') )
1211 // everything after TAB is accel string, exit the loop
1221 // ----------------------------------------------------------------------------
1222 // Window search functions
1223 // ----------------------------------------------------------------------------
1226 * If parent is non-NULL, look through children for a label or title
1227 * matching the specified string. If NULL, look through all top-level windows.
1232 wxFindWindowByLabel (const wxString
& title
, wxWindow
* parent
)
1234 return wxWindow::FindWindowByLabel( title
, parent
);
1239 * If parent is non-NULL, look through children for a name
1240 * matching the specified string. If NULL, look through all top-level windows.
1245 wxFindWindowByName (const wxString
& name
, wxWindow
* parent
)
1247 return wxWindow::FindWindowByName( name
, parent
);
1250 // Returns menu item id or wxNOT_FOUND if none.
1252 wxFindMenuItemId(wxFrame
*frame
,
1253 const wxString
& menuString
,
1254 const wxString
& itemString
)
1257 wxMenuBar
*menuBar
= frame
->GetMenuBar ();
1259 return menuBar
->FindMenuItem (menuString
, itemString
);
1260 #else // !wxUSE_MENUS
1262 wxUnusedVar(menuString
);
1263 wxUnusedVar(itemString
);
1264 #endif // wxUSE_MENUS/!wxUSE_MENUS
1269 // Try to find the deepest child that contains 'pt'.
1270 // We go backwards, to try to allow for controls that are spacially
1271 // within other controls, but are still siblings (e.g. buttons within
1272 // static boxes). Static boxes are likely to be created _before_ controls
1273 // that sit inside them.
1274 wxWindow
* wxFindWindowAtPoint(wxWindow
* win
, const wxPoint
& pt
)
1276 if (!win
->IsShown())
1279 // Hack for wxNotebook case: at least in wxGTK, all pages
1280 // claim to be shown, so we must only deal with the selected one.
1282 if (win
->IsKindOf(CLASSINFO(wxNotebook
)))
1284 wxNotebook
* nb
= (wxNotebook
*) win
;
1285 int sel
= nb
->GetSelection();
1288 wxWindow
* child
= nb
->GetPage(sel
);
1289 wxWindow
* foundWin
= wxFindWindowAtPoint(child
, pt
);
1296 wxWindowList::compatibility_iterator node
= win
->GetChildren().GetLast();
1299 wxWindow
* child
= node
->GetData();
1300 wxWindow
* foundWin
= wxFindWindowAtPoint(child
, pt
);
1303 node
= node
->GetPrevious();
1306 wxPoint pos
= win
->GetPosition();
1307 wxSize sz
= win
->GetSize();
1308 if ( !win
->IsTopLevel() && win
->GetParent() )
1310 pos
= win
->GetParent()->ClientToScreen(pos
);
1313 wxRect
rect(pos
, sz
);
1314 if (rect
.Contains(pt
))
1320 wxWindow
* wxGenericFindWindowAtPoint(const wxPoint
& pt
)
1322 // Go backwards through the list since windows
1323 // on top are likely to have been appended most
1325 wxWindowList::compatibility_iterator node
= wxTopLevelWindows
.GetLast();
1328 wxWindow
* win
= node
->GetData();
1329 wxWindow
* found
= wxFindWindowAtPoint(win
, pt
);
1332 node
= node
->GetPrevious();
1337 // ----------------------------------------------------------------------------
1339 // ----------------------------------------------------------------------------
1342 * N.B. these convenience functions must be separate from msgdlgg.cpp, textdlgg.cpp
1343 * since otherwise the generic code may be pulled in unnecessarily.
1348 int wxMessageBox(const wxString
& message
, const wxString
& caption
, long style
,
1349 wxWindow
*parent
, int WXUNUSED(x
), int WXUNUSED(y
) )
1351 long decorated_style
= style
;
1353 if ( ( style
& ( wxICON_EXCLAMATION
| wxICON_HAND
| wxICON_INFORMATION
| wxICON_QUESTION
) ) == 0 )
1355 decorated_style
|= ( style
& wxYES
) ? wxICON_QUESTION
: wxICON_INFORMATION
;
1358 wxMessageDialog
dialog(parent
, message
, caption
, decorated_style
);
1360 int ans
= dialog
.ShowModal();
1373 wxFAIL_MSG( _T("unexpected return code from wxMessageDialog") );
1378 void wxInfoMessageBox(wxWindow
* parent
)
1380 // don't translate these strings, they're for diagnostics purposes only
1382 msg
.Printf(_T("wxWidgets Library (%s port)\n")
1383 _T("Version %d.%d.%d%s%s, compiled at %s %s\n")
1384 _T("Runtime version of toolkit used is %d.%d.%s\n")
1385 _T("Copyright (c) 1995-2007 wxWidgets team"),
1386 wxPlatformInfo::Get().GetPortIdName().c_str(),
1402 wxPlatformInfo::Get().GetToolkitMajorVersion(),
1403 wxPlatformInfo::Get().GetToolkitMinorVersion(),
1405 wxString::Format("\nThe compile-time GTK+ version is %d.%d.%d.",
1408 GTK_MICRO_VERSION
).c_str()
1413 wxMessageBox(msg
, _T("wxWidgets information"),
1414 wxICON_INFORMATION
| wxOK
,
1418 #endif // wxUSE_MSGDLG
1422 wxString
wxGetTextFromUser(const wxString
& message
, const wxString
& caption
,
1423 const wxString
& defaultValue
, wxWindow
*parent
,
1424 wxCoord x
, wxCoord y
, bool centre
)
1427 long style
= wxTextEntryDialogStyle
;
1434 wxTextEntryDialog
dialog(parent
, message
, caption
, defaultValue
, style
, wxPoint(x
, y
));
1436 if (dialog
.ShowModal() == wxID_OK
)
1438 str
= dialog
.GetValue();
1444 wxString
wxGetPasswordFromUser(const wxString
& message
,
1445 const wxString
& caption
,
1446 const wxString
& defaultValue
,
1448 wxCoord x
, wxCoord y
, bool centre
)
1451 long style
= wxTextEntryDialogStyle
;
1458 wxPasswordEntryDialog
dialog(parent
, message
, caption
, defaultValue
,
1459 style
, wxPoint(x
, y
));
1460 if ( dialog
.ShowModal() == wxID_OK
)
1462 str
= dialog
.GetValue();
1468 #endif // wxUSE_TEXTDLG
1472 wxColour
wxGetColourFromUser(wxWindow
*parent
,
1473 const wxColour
& colInit
,
1474 const wxString
& caption
,
1475 wxColourData
*ptrData
)
1477 // contains serialized representation of wxColourData used the last time
1478 // the dialog was shown: we want to reuse it the next time in order to show
1479 // the same custom colours to the user (and we can't just have static
1480 // wxColourData itself because it's a GUI object and so should be destroyed
1481 // before GUI shutdown and doing it during static cleanup is too late)
1482 static wxString s_strColourData
;
1488 if ( !s_strColourData
.empty() )
1490 if ( !data
.FromString(s_strColourData
) )
1492 wxFAIL_MSG( "bug in wxColourData::FromString()?" );
1496 // we don't get back the "choose full" flag value from the native
1497 // dialog and so we can't preserve it between runs, so we decide to
1498 // always use it as it seems better than not using it (user can
1499 // just ignore the extra controls in the dialog but having to click
1500 // a button each time to show them would be very annoying
1501 data
.SetChooseFull(true);
1506 if ( colInit
.IsOk() )
1508 ptrData
->SetColour(colInit
);
1512 wxColourDialog
dialog(parent
, ptrData
);
1513 if (!caption
.empty())
1514 dialog
.SetTitle(caption
);
1515 if ( dialog
.ShowModal() == wxID_OK
)
1517 *ptrData
= dialog
.GetColourData();
1518 colRet
= ptrData
->GetColour();
1519 s_strColourData
= ptrData
->ToString();
1521 //else: leave colRet invalid
1526 #endif // wxUSE_COLOURDLG
1530 wxFont
wxGetFontFromUser(wxWindow
*parent
, const wxFont
& fontInit
, const wxString
& caption
)
1533 if ( fontInit
.Ok() )
1535 data
.SetInitialFont(fontInit
);
1539 wxFontDialog
dialog(parent
, data
);
1540 if (!caption
.empty())
1541 dialog
.SetTitle(caption
);
1542 if ( dialog
.ShowModal() == wxID_OK
)
1544 fontRet
= dialog
.GetFontData().GetChosenFont();
1546 //else: leave it invalid
1551 #endif // wxUSE_FONTDLG
1553 // ----------------------------------------------------------------------------
1554 // wxSafeYield and supporting functions
1555 // ----------------------------------------------------------------------------
1557 void wxEnableTopLevelWindows(bool enable
)
1559 wxWindowList::compatibility_iterator node
;
1560 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1561 node
->GetData()->Enable(enable
);
1564 wxWindowDisabler::wxWindowDisabler(wxWindow
*winToSkip
)
1566 // remember the top level windows which were already disabled, so that we
1567 // don't reenable them later
1568 m_winDisabled
= NULL
;
1570 wxWindowList::compatibility_iterator node
;
1571 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1573 wxWindow
*winTop
= node
->GetData();
1574 if ( winTop
== winToSkip
)
1577 // we don't need to disable the hidden or already disabled windows
1578 if ( winTop
->IsEnabled() && winTop
->IsShown() )
1584 if ( !m_winDisabled
)
1586 m_winDisabled
= new wxWindowList
;
1589 m_winDisabled
->Append(winTop
);
1594 wxWindowDisabler::~wxWindowDisabler()
1596 wxWindowList::compatibility_iterator node
;
1597 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1599 wxWindow
*winTop
= node
->GetData();
1600 if ( !m_winDisabled
|| !m_winDisabled
->Find(winTop
) )
1604 //else: had been already disabled, don't reenable
1607 delete m_winDisabled
;
1610 // Yield to other apps/messages and disable user input to all windows except
1612 bool wxSafeYield(wxWindow
*win
, bool onlyIfNeeded
)
1614 wxWindowDisabler
wd(win
);
1618 rc
= wxYieldIfNeeded();
1625 // Don't synthesize KeyUp events holding down a key and producing KeyDown
1626 // events with autorepeat. On by default and always on in wxMSW. wxGTK version
1629 bool wxSetDetectableAutoRepeat( bool WXUNUSED(flag
) )
1631 return true; // detectable auto-repeat is the only mode MSW supports