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"
81 #include "wx/msw/wince/time.h"
85 #include "wx/mac/private.h"
87 #include "InternetConfig.h"
91 #if !defined(__MWERKS__) && !defined(__WXWINCE__)
92 #include <sys/types.h>
96 #if defined(__WXMSW__)
97 #include "wx/msw/private.h"
98 #include "wx/msw/registry.h"
99 #include <shellapi.h> // needed for SHELLEXECUTEINFO
102 #if wxUSE_GUI && defined(__WXGTK__)
103 #include <gtk/gtk.h> // for GTK_XXX_VERSION constants
108 // ----------------------------------------------------------------------------
110 // ----------------------------------------------------------------------------
112 // ============================================================================
114 // ============================================================================
116 // Array used in DecToHex conversion routine.
117 static wxChar hexArray
[] = wxT("0123456789ABCDEF");
119 // Convert 2-digit hex number to decimal
120 int wxHexToDec(const wxString
& buf
)
122 int firstDigit
, secondDigit
;
124 if (buf
.GetChar(0) >= wxT('A'))
125 firstDigit
= buf
.GetChar(0) - wxT('A') + 10;
127 firstDigit
= buf
.GetChar(0) - wxT('0');
129 if (buf
.GetChar(1) >= wxT('A'))
130 secondDigit
= buf
.GetChar(1) - wxT('A') + 10;
132 secondDigit
= buf
.GetChar(1) - wxT('0');
134 return (firstDigit
& 0xF) * 16 + (secondDigit
& 0xF );
137 // Convert decimal integer to 2-character hex string
138 void wxDecToHex(int dec
, wxChar
*buf
)
140 int firstDigit
= (int)(dec
/16.0);
141 int secondDigit
= (int)(dec
- (firstDigit
*16.0));
142 buf
[0] = hexArray
[firstDigit
];
143 buf
[1] = hexArray
[secondDigit
];
147 // Convert decimal integer to 2 characters
148 void wxDecToHex(int dec
, char* ch1
, char* ch2
)
150 int firstDigit
= (int)(dec
/16.0);
151 int secondDigit
= (int)(dec
- (firstDigit
*16.0));
152 (*ch1
) = (char) hexArray
[firstDigit
];
153 (*ch2
) = (char) hexArray
[secondDigit
];
156 // Convert decimal integer to 2-character hex string
157 wxString
wxDecToHex(int dec
)
160 wxDecToHex(dec
, buf
);
161 return wxString(buf
);
164 // ----------------------------------------------------------------------------
166 // ----------------------------------------------------------------------------
168 // Return the current date/time
173 wxDateTime now
= wxDateTime::Now();
176 return wxEmptyString
;
179 time_t now
= time((time_t *) NULL
);
180 char *date
= ctime(&now
);
182 return wxString::FromAscii(date
);
186 void wxUsleep(unsigned long milliseconds
)
188 wxMilliSleep(milliseconds
);
191 const wxChar
*wxGetInstallPrefix()
195 if ( wxGetEnv(wxT("WXPREFIX"), &prefix
) )
196 return prefix
.c_str();
198 #ifdef wxINSTALL_PREFIX
199 return wxT(wxINSTALL_PREFIX
);
201 return wxEmptyString
;
205 wxString
wxGetDataDir()
207 wxString dir
= wxGetInstallPrefix();
208 dir
<< wxFILE_SEP_PATH
<< wxT("share") << wxFILE_SEP_PATH
<< wxT("wx");
212 bool wxIsPlatformLittleEndian()
214 // Are we little or big endian? This method is from Harbison & Steele.
218 char c
[sizeof(long)];
227 * Class to make it easier to specify platform-dependent values
230 wxArrayInt
* wxPlatform::sm_customPlatforms
= NULL
;
232 void wxPlatform::Copy(const wxPlatform
& platform
)
234 m_longValue
= platform
.m_longValue
;
235 m_doubleValue
= platform
.m_doubleValue
;
236 m_stringValue
= platform
.m_stringValue
;
239 wxPlatform
wxPlatform::If(int platform
, long value
)
242 return wxPlatform(value
);
247 wxPlatform
wxPlatform::IfNot(int platform
, long value
)
250 return wxPlatform(value
);
255 wxPlatform
& wxPlatform::ElseIf(int platform
, long value
)
262 wxPlatform
& wxPlatform::ElseIfNot(int platform
, long value
)
269 wxPlatform
wxPlatform::If(int platform
, double value
)
272 return wxPlatform(value
);
277 wxPlatform
wxPlatform::IfNot(int platform
, double value
)
280 return wxPlatform(value
);
285 wxPlatform
& wxPlatform::ElseIf(int platform
, double value
)
288 m_doubleValue
= value
;
292 wxPlatform
& wxPlatform::ElseIfNot(int platform
, double value
)
295 m_doubleValue
= value
;
299 wxPlatform
wxPlatform::If(int platform
, const wxString
& value
)
302 return wxPlatform(value
);
307 wxPlatform
wxPlatform::IfNot(int platform
, const wxString
& value
)
310 return wxPlatform(value
);
315 wxPlatform
& wxPlatform::ElseIf(int platform
, const wxString
& value
)
318 m_stringValue
= value
;
322 wxPlatform
& wxPlatform::ElseIfNot(int platform
, const wxString
& value
)
325 m_stringValue
= value
;
329 wxPlatform
& wxPlatform::Else(long value
)
335 wxPlatform
& wxPlatform::Else(double value
)
337 m_doubleValue
= value
;
341 wxPlatform
& wxPlatform::Else(const wxString
& value
)
343 m_stringValue
= value
;
347 void wxPlatform::AddPlatform(int platform
)
349 if (!sm_customPlatforms
)
350 sm_customPlatforms
= new wxArrayInt
;
351 sm_customPlatforms
->Add(platform
);
354 void wxPlatform::ClearPlatforms()
356 delete sm_customPlatforms
;
357 sm_customPlatforms
= NULL
;
360 /// Function for testing current platform
362 bool wxPlatform::Is(int platform
)
365 if (platform
== wxOS_WINDOWS
)
369 if (platform
== wxOS_WINDOWS_CE
)
375 // FIXME: wxWinPocketPC and wxWinSmartPhone are unknown symbols
377 #if defined(__WXWINCE__) && defined(__POCKETPC__)
378 if (platform
== wxWinPocketPC
)
381 #if defined(__WXWINCE__) && defined(__SMARTPHONE__)
382 if (platform
== wxWinSmartPhone
)
389 if (platform
== wxPORT_GTK
)
393 if (platform
== wxPORT_MAC
)
397 if (platform
== wxPORT_X11
)
401 if (platform
== wxOS_UNIX
)
405 if (platform
== wxPORT_MGL
)
409 if (platform
== wxOS_OS2
)
413 if (platform
== wxPORT_PM
)
417 if (platform
== wxPORT_MAC
)
421 if (sm_customPlatforms
&& sm_customPlatforms
->Index(platform
) != wxNOT_FOUND
)
427 // ----------------------------------------------------------------------------
428 // network and user id functions
429 // ----------------------------------------------------------------------------
431 // Get Full RFC822 style email address
432 bool wxGetEmailAddress(wxChar
*address
, int maxSize
)
434 wxString email
= wxGetEmailAddress();
438 wxStrncpy(address
, email
, maxSize
- 1);
439 address
[maxSize
- 1] = wxT('\0');
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 default browser
937 // ----------------------------------------------------------------------------
940 // Private method in Objective-C++ source file.
941 bool wxCocoaLaunchDefaultBrowser(const wxString
& url
, int flags
);
944 bool wxLaunchDefaultBrowser(const wxString
& urlOrig
, int flags
)
948 // set the scheme of url to http if it does not have one
949 // RR: This doesn't work if the url is just a local path
950 wxString
url(urlOrig
);
952 if ( !uri
.HasScheme() )
954 if (wxFileExists(urlOrig
))
955 url
.Prepend( wxT("file://") );
957 url
.Prepend(wxT("http://"));
961 #if defined(__WXMSW__)
964 if ( flags
& wxBROWSER_NEW_WINDOW
)
966 // ShellExecuteEx() opens the URL in an existing window by default so
967 // we can't use it if we need a new window
968 wxRegKey
key(wxRegKey::HKCR
, uri
.GetScheme() + _T("\\shell\\open"));
971 // try default browser, it must be registered at least for http URLs
972 key
.SetName(wxRegKey::HKCR
, _T("http\\shell\\open"));
977 wxRegKey
keyDDE(key
, wxT("DDEExec"));
978 if ( keyDDE
.Exists() )
980 const wxString ddeTopic
= wxRegKey(keyDDE
, wxT("topic"));
982 // we only know the syntax of WWW_OpenURL DDE request for IE,
983 // optimistically assume that all other browsers are compatible
986 bool ok
= ddeTopic
== wxT("WWW_OpenURL");
989 ddeCmd
= keyDDE
.QueryDefaultValue();
990 ok
= !ddeCmd
.empty();
995 // for WWW_OpenURL, the index of the window to open the URL
996 // in is -1 (meaning "current") by default, replace it with
997 // 0 which means "new" (see KB article 160957)
998 ok
= ddeCmd
.Replace(wxT("-1"), wxT("0"),
999 false /* only first occurence */) == 1;
1004 // and also replace the parameters: the topic should
1005 // contain a placeholder for the URL
1006 ok
= ddeCmd
.Replace(wxT("%1"), url
, false) == 1;
1011 // try to send it the DDE request now but ignore the errors
1014 const wxString ddeServer
= wxRegKey(keyDDE
, wxT("application"));
1015 if ( wxExecuteDDE(ddeServer
, ddeTopic
, ddeCmd
) )
1018 // this is not necessarily an error: maybe browser is
1019 // simply not running, but no matter, in any case we're
1020 // going to launch it using ShellExecuteEx() below now and
1021 // we shouldn't try to open a new window if we open a new
1029 WinStruct
<SHELLEXECUTEINFO
> sei
;
1030 sei
.lpFile
= url
.c_str();
1031 sei
.lpVerb
= _T("open");
1032 sei
.nShow
= SW_SHOWNORMAL
;
1034 ::ShellExecuteEx(&sei
);
1036 const int nResult
= (int) sei
.hInstApp
;
1038 // Firefox returns file not found for some reason, so make an exception
1040 if ( nResult
> 32 || nResult
== SE_ERR_FNF
)
1043 // Log something if SE_ERR_FNF happens
1044 if ( nResult
== SE_ERR_FNF
)
1045 wxLogDebug(wxT("SE_ERR_FNF from ShellExecute -- maybe FireFox?"));
1046 #endif // __WXDEBUG__
1049 #elif defined(__WXCOCOA__)
1050 // NOTE: We need to call the real implementation from src/cocoa/utils.mm
1051 // because the code must use Objective-C features.
1052 return wxCocoaLaunchDefaultBrowser(url
, flags
);
1053 #elif defined(__WXMAC__)
1059 err
= ICStart(&inst
, 'STKA'); // put your app creator code here
1064 ConstStr255Param hint
= 0;
1066 endSel
= url
.length();
1067 err
= ICLaunchURL(inst
, hint
, url
.fn_str(), endSel
, &startSel
, &endSel
);
1069 wxLogDebug(wxT("ICLaunchURL error %d"), (int) err
);
1076 wxLogDebug(wxT("ICStart error %d"), (int) err
);
1080 // (non-Mac, non-MSW)
1084 // Our best best is to use xdg-open from freedesktop.org cross-desktop
1085 // compatibility suite xdg-utils
1086 // (see http://portland.freedesktop.org/wiki/) -- this is installed on
1087 // most modern distributions and may be tweaked by them to handle
1088 // distribution specifics. Only if that fails, try to find the right
1089 // browser ourselves.
1090 wxString path
, xdg_open
;
1091 if ( wxGetEnv("PATH", &path
) &&
1092 wxFindFileInPath(&xdg_open
, path
, "xdg-open") )
1094 if ( wxExecute(xdg_open
+ " " + url
) )
1098 wxString desktop
= wxTheApp
->GetTraits()->GetDesktopEnvironment();
1100 // GNOME and KDE desktops have some applications which should be always installed
1101 // together with their main parts, which give us the
1102 if (desktop
== wxT("GNOME"))
1104 wxArrayString errors
;
1105 wxArrayString output
;
1107 // gconf will tell us the path of the application to use as browser
1108 long res
= wxExecute( wxT("gconftool-2 --get /desktop/gnome/applications/browser/exec"),
1109 output
, errors
, wxEXEC_NODISABLE
);
1110 if (res
>= 0 && errors
.GetCount() == 0)
1112 wxString cmd
= output
[0];
1113 cmd
<< _T(' ') << url
;
1118 else if (desktop
== wxT("KDE"))
1120 // kfmclient directly opens the given URL
1121 if (wxExecute(wxT("kfmclient openURL ") + url
))
1130 wxFileType
*ft
= wxTheMimeTypesManager
->GetFileTypeFromExtension(_T("html"));
1134 ft
->GetMimeType(&mt
);
1136 ok
= ft
->GetOpenCommand(&cmd
, wxFileType::MessageParameters(url
));
1139 #endif // wxUSE_MIMETYPE
1141 if ( !ok
|| cmd
.empty() )
1143 // fallback to checking for the BROWSER environment variable
1144 cmd
= wxGetenv(wxT("BROWSER"));
1146 cmd
<< _T(' ') << url
;
1149 ok
= ( !cmd
.empty() && wxExecute(cmd
) );
1153 // no file type for HTML extension
1154 wxLogError(_("No default application configured for HTML files."));
1156 #endif // !wxUSE_MIMETYPE && !__WXMSW__
1158 wxLogSysError(_("Failed to open URL \"%s\" in default browser."),
1164 // ----------------------------------------------------------------------------
1165 // Menu accelerators related functions
1166 // ----------------------------------------------------------------------------
1168 wxChar
*wxStripMenuCodes(const wxChar
*in
, wxChar
*out
)
1171 wxString s
= wxMenuItem::GetLabelText(in
);
1174 wxString s
= wxStripMenuCodes(str
);
1175 #endif // wxUSE_MENUS
1178 // go smash their buffer if it's not big enough - I love char * params
1179 memcpy(out
, s
.c_str(), s
.length() * sizeof(wxChar
));
1183 out
= new wxChar
[s
.length() + 1];
1184 wxStrcpy(out
, s
.c_str());
1190 wxString
wxStripMenuCodes(const wxString
& in
, int flags
)
1192 wxASSERT_MSG( flags
, _T("this is useless to call without any flags") );
1196 size_t len
= in
.length();
1199 for ( size_t n
= 0; n
< len
; n
++ )
1202 if ( (flags
& wxStrip_Mnemonics
) && ch
== _T('&') )
1204 // skip it, it is used to introduce the accel char (or to quote
1205 // itself in which case it should still be skipped): note that it
1206 // can't be the last character of the string
1209 wxLogDebug(_T("Invalid menu string '%s'"), in
.c_str());
1213 // use the next char instead
1217 else if ( (flags
& wxStrip_Accel
) && ch
== _T('\t') )
1219 // everything after TAB is accel string, exit the loop
1229 // ----------------------------------------------------------------------------
1230 // Window search functions
1231 // ----------------------------------------------------------------------------
1234 * If parent is non-NULL, look through children for a label or title
1235 * matching the specified string. If NULL, look through all top-level windows.
1240 wxFindWindowByLabel (const wxString
& title
, wxWindow
* parent
)
1242 return wxWindow::FindWindowByLabel( title
, parent
);
1247 * If parent is non-NULL, look through children for a name
1248 * matching the specified string. If NULL, look through all top-level windows.
1253 wxFindWindowByName (const wxString
& name
, wxWindow
* parent
)
1255 return wxWindow::FindWindowByName( name
, parent
);
1258 // Returns menu item id or wxNOT_FOUND if none.
1260 wxFindMenuItemId(wxFrame
*frame
,
1261 const wxString
& menuString
,
1262 const wxString
& itemString
)
1265 wxMenuBar
*menuBar
= frame
->GetMenuBar ();
1267 return menuBar
->FindMenuItem (menuString
, itemString
);
1268 #else // !wxUSE_MENUS
1270 wxUnusedVar(menuString
);
1271 wxUnusedVar(itemString
);
1272 #endif // wxUSE_MENUS/!wxUSE_MENUS
1277 // Try to find the deepest child that contains 'pt'.
1278 // We go backwards, to try to allow for controls that are spacially
1279 // within other controls, but are still siblings (e.g. buttons within
1280 // static boxes). Static boxes are likely to be created _before_ controls
1281 // that sit inside them.
1282 wxWindow
* wxFindWindowAtPoint(wxWindow
* win
, const wxPoint
& pt
)
1284 if (!win
->IsShown())
1287 // Hack for wxNotebook case: at least in wxGTK, all pages
1288 // claim to be shown, so we must only deal with the selected one.
1290 if (win
->IsKindOf(CLASSINFO(wxNotebook
)))
1292 wxNotebook
* nb
= (wxNotebook
*) win
;
1293 int sel
= nb
->GetSelection();
1296 wxWindow
* child
= nb
->GetPage(sel
);
1297 wxWindow
* foundWin
= wxFindWindowAtPoint(child
, pt
);
1304 wxWindowList::compatibility_iterator node
= win
->GetChildren().GetLast();
1307 wxWindow
* child
= node
->GetData();
1308 wxWindow
* foundWin
= wxFindWindowAtPoint(child
, pt
);
1311 node
= node
->GetPrevious();
1314 wxPoint pos
= win
->GetPosition();
1315 wxSize sz
= win
->GetSize();
1316 if ( !win
->IsTopLevel() && win
->GetParent() )
1318 pos
= win
->GetParent()->ClientToScreen(pos
);
1321 wxRect
rect(pos
, sz
);
1322 if (rect
.Contains(pt
))
1328 wxWindow
* wxGenericFindWindowAtPoint(const wxPoint
& pt
)
1330 // Go backwards through the list since windows
1331 // on top are likely to have been appended most
1333 wxWindowList::compatibility_iterator node
= wxTopLevelWindows
.GetLast();
1336 wxWindow
* win
= node
->GetData();
1337 wxWindow
* found
= wxFindWindowAtPoint(win
, pt
);
1340 node
= node
->GetPrevious();
1345 // ----------------------------------------------------------------------------
1347 // ----------------------------------------------------------------------------
1350 * N.B. these convenience functions must be separate from msgdlgg.cpp, textdlgg.cpp
1351 * since otherwise the generic code may be pulled in unnecessarily.
1356 int wxMessageBox(const wxString
& message
, const wxString
& caption
, long style
,
1357 wxWindow
*parent
, int WXUNUSED(x
), int WXUNUSED(y
) )
1359 long decorated_style
= style
;
1361 if ( ( style
& ( wxICON_EXCLAMATION
| wxICON_HAND
| wxICON_INFORMATION
| wxICON_QUESTION
) ) == 0 )
1363 decorated_style
|= ( style
& wxYES
) ? wxICON_QUESTION
: wxICON_INFORMATION
;
1366 wxMessageDialog
dialog(parent
, message
, caption
, decorated_style
);
1368 int ans
= dialog
.ShowModal();
1381 wxFAIL_MSG( _T("unexpected return code from wxMessageDialog") );
1386 void wxInfoMessageBox(wxWindow
* parent
)
1388 // don't translate these strings, they're for diagnostics purposes only
1390 msg
.Printf(_T("wxWidgets Library (%s port)\n")
1391 _T("Version %d.%d.%d%s%s, compiled at %s %s\n")
1392 _T("Runtime version of toolkit used is %d.%d.%s\n")
1393 _T("Copyright (c) 1995-2007 wxWidgets team"),
1394 wxPlatformInfo::Get().GetPortIdName().c_str(),
1410 wxPlatformInfo::Get().GetToolkitMajorVersion(),
1411 wxPlatformInfo::Get().GetToolkitMinorVersion(),
1413 wxString::Format("\nThe compile-time GTK+ version is %d.%d.%d.",
1416 GTK_MICRO_VERSION
).c_str()
1421 wxMessageBox(msg
, _T("wxWidgets information"),
1422 wxICON_INFORMATION
| wxOK
,
1426 #endif // wxUSE_MSGDLG
1430 wxString
wxGetTextFromUser(const wxString
& message
, const wxString
& caption
,
1431 const wxString
& defaultValue
, wxWindow
*parent
,
1432 wxCoord x
, wxCoord y
, bool centre
)
1435 long style
= wxTextEntryDialogStyle
;
1442 wxTextEntryDialog
dialog(parent
, message
, caption
, defaultValue
, style
, wxPoint(x
, y
));
1444 if (dialog
.ShowModal() == wxID_OK
)
1446 str
= dialog
.GetValue();
1452 wxString
wxGetPasswordFromUser(const wxString
& message
,
1453 const wxString
& caption
,
1454 const wxString
& defaultValue
,
1456 wxCoord x
, wxCoord y
, bool centre
)
1459 long style
= wxTextEntryDialogStyle
;
1466 wxPasswordEntryDialog
dialog(parent
, message
, caption
, defaultValue
,
1467 style
, wxPoint(x
, y
));
1468 if ( dialog
.ShowModal() == wxID_OK
)
1470 str
= dialog
.GetValue();
1476 #endif // wxUSE_TEXTDLG
1480 wxColour
wxGetColourFromUser(wxWindow
*parent
,
1481 const wxColour
& colInit
,
1482 const wxString
& caption
,
1483 wxColourData
*ptrData
)
1485 // contains serialized representation of wxColourData used the last time
1486 // the dialog was shown: we want to reuse it the next time in order to show
1487 // the same custom colours to the user (and we can't just have static
1488 // wxColourData itself because it's a GUI object and so should be destroyed
1489 // before GUI shutdown and doing it during static cleanup is too late)
1490 static wxString s_strColourData
;
1496 if ( !s_strColourData
.empty() )
1498 if ( !data
.FromString(s_strColourData
) )
1500 wxFAIL_MSG( "bug in wxColourData::FromString()?" );
1504 // we don't get back the "choose full" flag value from the native
1505 // dialog and so we can't preserve it between runs, so we decide to
1506 // always use it as it seems better than not using it (user can
1507 // just ignore the extra controls in the dialog but having to click
1508 // a button each time to show them would be very annoying
1509 data
.SetChooseFull(true);
1514 if ( colInit
.IsOk() )
1516 ptrData
->SetColour(colInit
);
1520 wxColourDialog
dialog(parent
, ptrData
);
1521 if (!caption
.empty())
1522 dialog
.SetTitle(caption
);
1523 if ( dialog
.ShowModal() == wxID_OK
)
1525 *ptrData
= dialog
.GetColourData();
1526 colRet
= ptrData
->GetColour();
1527 s_strColourData
= ptrData
->ToString();
1529 //else: leave colRet invalid
1534 #endif // wxUSE_COLOURDLG
1538 wxFont
wxGetFontFromUser(wxWindow
*parent
, const wxFont
& fontInit
, const wxString
& caption
)
1541 if ( fontInit
.Ok() )
1543 data
.SetInitialFont(fontInit
);
1547 wxFontDialog
dialog(parent
, data
);
1548 if (!caption
.empty())
1549 dialog
.SetTitle(caption
);
1550 if ( dialog
.ShowModal() == wxID_OK
)
1552 fontRet
= dialog
.GetFontData().GetChosenFont();
1554 //else: leave it invalid
1559 #endif // wxUSE_FONTDLG
1561 // ----------------------------------------------------------------------------
1562 // wxSafeYield and supporting functions
1563 // ----------------------------------------------------------------------------
1565 void wxEnableTopLevelWindows(bool enable
)
1567 wxWindowList::compatibility_iterator node
;
1568 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1569 node
->GetData()->Enable(enable
);
1572 wxWindowDisabler::wxWindowDisabler(wxWindow
*winToSkip
)
1574 // remember the top level windows which were already disabled, so that we
1575 // don't reenable them later
1576 m_winDisabled
= NULL
;
1578 wxWindowList::compatibility_iterator node
;
1579 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1581 wxWindow
*winTop
= node
->GetData();
1582 if ( winTop
== winToSkip
)
1585 // we don't need to disable the hidden or already disabled windows
1586 if ( winTop
->IsEnabled() && winTop
->IsShown() )
1592 if ( !m_winDisabled
)
1594 m_winDisabled
= new wxWindowList
;
1597 m_winDisabled
->Append(winTop
);
1602 wxWindowDisabler::~wxWindowDisabler()
1604 wxWindowList::compatibility_iterator node
;
1605 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
1607 wxWindow
*winTop
= node
->GetData();
1608 if ( !m_winDisabled
|| !m_winDisabled
->Find(winTop
) )
1612 //else: had been already disabled, don't reenable
1615 delete m_winDisabled
;
1618 // Yield to other apps/messages and disable user input to all windows except
1620 bool wxSafeYield(wxWindow
*win
, bool onlyIfNeeded
)
1622 wxWindowDisabler
wd(win
);
1626 rc
= wxYieldIfNeeded();
1633 // Don't synthesize KeyUp events holding down a key and producing KeyDown
1634 // events with autorepeat. On by default and always on in wxMSW. wxGTK version
1637 bool wxSetDetectableAutoRepeat( bool WXUNUSED(flag
) )
1639 return true; // detectable auto-repeat is the only mode MSW supports