]> git.saurik.com Git - wxWidgets.git/blob - src/common/utilscmn.cpp
fix crash in wxWindowGTK::GTKHandleUnrealize(), closes #14752
[wxWidgets.git] / src / common / utilscmn.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/utilscmn.cpp
3 // Purpose: Miscellaneous utility functions and classes
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 29/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) 1998 Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22
23 #ifdef __BORLANDC__
24 #pragma hdrstop
25 #endif
26
27 #ifndef WX_PRECOMP
28 #include "wx/app.h"
29 #include "wx/string.h"
30 #include "wx/utils.h"
31 #include "wx/intl.h"
32 #include "wx/log.h"
33
34 #if wxUSE_GUI
35 #include "wx/window.h"
36 #include "wx/frame.h"
37 #include "wx/menu.h"
38 #include "wx/msgdlg.h"
39 #include "wx/textdlg.h"
40 #include "wx/textctrl.h" // for wxTE_PASSWORD
41 #if wxUSE_ACCEL
42 #include "wx/menuitem.h"
43 #include "wx/accel.h"
44 #endif // wxUSE_ACCEL
45 #endif // wxUSE_GUI
46 #endif // WX_PRECOMP
47
48 #include "wx/apptrait.h"
49
50 #include "wx/process.h"
51 #include "wx/txtstrm.h"
52 #include "wx/uri.h"
53 #include "wx/mimetype.h"
54 #include "wx/config.h"
55 #include "wx/versioninfo.h"
56
57 #if defined(__WXWINCE__) && wxUSE_DATETIME
58 #include "wx/datetime.h"
59 #endif
60
61 #include <ctype.h>
62 #include <stdio.h>
63 #include <stdlib.h>
64 #include <string.h>
65
66 #if !wxONLY_WATCOM_EARLIER_THAN(1,4)
67 #if !(defined(_MSC_VER) && (_MSC_VER > 800))
68 #include <errno.h>
69 #endif
70 #endif
71
72 #if wxUSE_GUI
73 #include "wx/colordlg.h"
74 #include "wx/fontdlg.h"
75 #include "wx/notebook.h"
76 #include "wx/statusbr.h"
77 #endif // wxUSE_GUI
78
79 #ifndef __WXWINCE__
80 #include <time.h>
81 #else
82 #include "wx/msw/wince/time.h"
83 #endif
84
85 #ifdef __WXMAC__
86 #include "wx/osx/private.h"
87 #endif
88
89 #if !defined(__WXWINCE__)
90 #include <sys/types.h>
91 #include <sys/stat.h>
92 #endif
93
94 #if defined(__WINDOWS__)
95 #include "wx/msw/private.h"
96 #include "wx/filesys.h"
97 #endif
98
99 #if wxUSE_GUI && defined(__WXGTK__)
100 #include <gtk/gtk.h> // for GTK_XXX_VERSION constants
101 #endif
102
103 #if wxUSE_BASE
104
105 // ============================================================================
106 // implementation
107 // ============================================================================
108
109 // Array used in DecToHex conversion routine.
110 static const wxChar hexArray[] = wxT("0123456789ABCDEF");
111
112 // Convert 2-digit hex number to decimal
113 int wxHexToDec(const wxString& str)
114 {
115 char buf[2];
116 buf[0] = str.GetChar(0);
117 buf[1] = str.GetChar(1);
118 return wxHexToDec((const char*) buf);
119 }
120
121 // Convert decimal integer to 2-character hex string
122 void wxDecToHex(int dec, wxChar *buf)
123 {
124 int firstDigit = (int)(dec/16.0);
125 int secondDigit = (int)(dec - (firstDigit*16.0));
126 buf[0] = hexArray[firstDigit];
127 buf[1] = hexArray[secondDigit];
128 buf[2] = 0;
129 }
130
131 // Convert decimal integer to 2 characters
132 void wxDecToHex(int dec, char* ch1, char* ch2)
133 {
134 int firstDigit = (int)(dec/16.0);
135 int secondDigit = (int)(dec - (firstDigit*16.0));
136 (*ch1) = (char) hexArray[firstDigit];
137 (*ch2) = (char) hexArray[secondDigit];
138 }
139
140 // Convert decimal integer to 2-character hex string
141 wxString wxDecToHex(int dec)
142 {
143 wxChar buf[3];
144 wxDecToHex(dec, buf);
145 return wxString(buf);
146 }
147
148 // ----------------------------------------------------------------------------
149 // misc functions
150 // ----------------------------------------------------------------------------
151
152 // Return the current date/time
153 wxString wxNow()
154 {
155 #ifdef __WXWINCE__
156 #if wxUSE_DATETIME
157 wxDateTime now = wxDateTime::Now();
158 return now.Format();
159 #else
160 return wxEmptyString;
161 #endif
162 #else
163 time_t now = time(NULL);
164 char *date = ctime(&now);
165 date[24] = '\0';
166 return wxString::FromAscii(date);
167 #endif
168 }
169
170 #if WXWIN_COMPATIBILITY_2_8
171 void wxUsleep(unsigned long milliseconds)
172 {
173 wxMilliSleep(milliseconds);
174 }
175 #endif
176
177 const wxChar *wxGetInstallPrefix()
178 {
179 wxString prefix;
180
181 if ( wxGetEnv(wxT("WXPREFIX"), &prefix) )
182 return prefix.c_str();
183
184 #ifdef wxINSTALL_PREFIX
185 return wxT(wxINSTALL_PREFIX);
186 #else
187 return wxEmptyString;
188 #endif
189 }
190
191 wxString wxGetDataDir()
192 {
193 wxString dir = wxGetInstallPrefix();
194 dir << wxFILE_SEP_PATH << wxT("share") << wxFILE_SEP_PATH << wxT("wx");
195 return dir;
196 }
197
198 bool wxIsPlatformLittleEndian()
199 {
200 // Are we little or big endian? This method is from Harbison & Steele.
201 union
202 {
203 long l;
204 char c[sizeof(long)];
205 } u;
206 u.l = 1;
207
208 return u.c[0] == 1;
209 }
210
211
212 // ----------------------------------------------------------------------------
213 // wxPlatform
214 // ----------------------------------------------------------------------------
215
216 /*
217 * Class to make it easier to specify platform-dependent values
218 */
219
220 wxArrayInt* wxPlatform::sm_customPlatforms = NULL;
221
222 void wxPlatform::Copy(const wxPlatform& platform)
223 {
224 m_longValue = platform.m_longValue;
225 m_doubleValue = platform.m_doubleValue;
226 m_stringValue = platform.m_stringValue;
227 }
228
229 wxPlatform wxPlatform::If(int platform, long value)
230 {
231 if (Is(platform))
232 return wxPlatform(value);
233 else
234 return wxPlatform();
235 }
236
237 wxPlatform wxPlatform::IfNot(int platform, long value)
238 {
239 if (!Is(platform))
240 return wxPlatform(value);
241 else
242 return wxPlatform();
243 }
244
245 wxPlatform& wxPlatform::ElseIf(int platform, long value)
246 {
247 if (Is(platform))
248 m_longValue = value;
249 return *this;
250 }
251
252 wxPlatform& wxPlatform::ElseIfNot(int platform, long value)
253 {
254 if (!Is(platform))
255 m_longValue = value;
256 return *this;
257 }
258
259 wxPlatform wxPlatform::If(int platform, double value)
260 {
261 if (Is(platform))
262 return wxPlatform(value);
263 else
264 return wxPlatform();
265 }
266
267 wxPlatform wxPlatform::IfNot(int platform, double value)
268 {
269 if (!Is(platform))
270 return wxPlatform(value);
271 else
272 return wxPlatform();
273 }
274
275 wxPlatform& wxPlatform::ElseIf(int platform, double value)
276 {
277 if (Is(platform))
278 m_doubleValue = value;
279 return *this;
280 }
281
282 wxPlatform& wxPlatform::ElseIfNot(int platform, double value)
283 {
284 if (!Is(platform))
285 m_doubleValue = value;
286 return *this;
287 }
288
289 wxPlatform wxPlatform::If(int platform, const wxString& value)
290 {
291 if (Is(platform))
292 return wxPlatform(value);
293 else
294 return wxPlatform();
295 }
296
297 wxPlatform wxPlatform::IfNot(int platform, const wxString& value)
298 {
299 if (!Is(platform))
300 return wxPlatform(value);
301 else
302 return wxPlatform();
303 }
304
305 wxPlatform& wxPlatform::ElseIf(int platform, const wxString& value)
306 {
307 if (Is(platform))
308 m_stringValue = value;
309 return *this;
310 }
311
312 wxPlatform& wxPlatform::ElseIfNot(int platform, const wxString& value)
313 {
314 if (!Is(platform))
315 m_stringValue = value;
316 return *this;
317 }
318
319 wxPlatform& wxPlatform::Else(long value)
320 {
321 m_longValue = value;
322 return *this;
323 }
324
325 wxPlatform& wxPlatform::Else(double value)
326 {
327 m_doubleValue = value;
328 return *this;
329 }
330
331 wxPlatform& wxPlatform::Else(const wxString& value)
332 {
333 m_stringValue = value;
334 return *this;
335 }
336
337 void wxPlatform::AddPlatform(int platform)
338 {
339 if (!sm_customPlatforms)
340 sm_customPlatforms = new wxArrayInt;
341 sm_customPlatforms->Add(platform);
342 }
343
344 void wxPlatform::ClearPlatforms()
345 {
346 wxDELETE(sm_customPlatforms);
347 }
348
349 /// Function for testing current platform
350
351 bool wxPlatform::Is(int platform)
352 {
353 #ifdef __WINDOWS__
354 if (platform == wxOS_WINDOWS)
355 return true;
356 #endif
357 #ifdef __WXWINCE__
358 if (platform == wxOS_WINDOWS_CE)
359 return true;
360 #endif
361
362 #if 0
363
364 // FIXME: wxWinPocketPC and wxWinSmartPhone are unknown symbols
365
366 #if defined(__WXWINCE__) && defined(__POCKETPC__)
367 if (platform == wxWinPocketPC)
368 return true;
369 #endif
370 #if defined(__WXWINCE__) && defined(__SMARTPHONE__)
371 if (platform == wxWinSmartPhone)
372 return true;
373 #endif
374
375 #endif
376
377 #ifdef __WXGTK__
378 if (platform == wxPORT_GTK)
379 return true;
380 #endif
381 #ifdef __WXMAC__
382 if (platform == wxPORT_MAC)
383 return true;
384 #endif
385 #ifdef __WXX11__
386 if (platform == wxPORT_X11)
387 return true;
388 #endif
389 #ifdef __UNIX__
390 if (platform == wxOS_UNIX)
391 return true;
392 #endif
393 #ifdef __OS2__
394 if (platform == wxOS_OS2)
395 return true;
396 #endif
397 #ifdef __WXPM__
398 if (platform == wxPORT_PM)
399 return true;
400 #endif
401 #ifdef __WXCOCOA__
402 if (platform == wxPORT_MAC)
403 return true;
404 #endif
405
406 if (sm_customPlatforms && sm_customPlatforms->Index(platform) != wxNOT_FOUND)
407 return true;
408
409 return false;
410 }
411
412 // ----------------------------------------------------------------------------
413 // network and user id functions
414 // ----------------------------------------------------------------------------
415
416 // Get Full RFC822 style email address
417 bool wxGetEmailAddress(wxChar *address, int maxSize)
418 {
419 wxString email = wxGetEmailAddress();
420 if ( !email )
421 return false;
422
423 wxStrlcpy(address, email.t_str(), maxSize);
424
425 return true;
426 }
427
428 wxString wxGetEmailAddress()
429 {
430 wxString email;
431
432 wxString host = wxGetFullHostName();
433 if ( !host.empty() )
434 {
435 wxString user = wxGetUserId();
436 if ( !user.empty() )
437 {
438 email << user << wxT('@') << host;
439 }
440 }
441
442 return email;
443 }
444
445 wxString wxGetUserId()
446 {
447 static const int maxLoginLen = 256; // FIXME arbitrary number
448
449 wxString buf;
450 bool ok = wxGetUserId(wxStringBuffer(buf, maxLoginLen), maxLoginLen);
451
452 if ( !ok )
453 buf.Empty();
454
455 return buf;
456 }
457
458 wxString wxGetUserName()
459 {
460 static const int maxUserNameLen = 1024; // FIXME arbitrary number
461
462 wxString buf;
463 bool ok = wxGetUserName(wxStringBuffer(buf, maxUserNameLen), maxUserNameLen);
464
465 if ( !ok )
466 buf.Empty();
467
468 return buf;
469 }
470
471 wxString wxGetHostName()
472 {
473 static const size_t hostnameSize = 257;
474
475 wxString buf;
476 bool ok = wxGetHostName(wxStringBuffer(buf, hostnameSize), hostnameSize);
477
478 if ( !ok )
479 buf.Empty();
480
481 return buf;
482 }
483
484 wxString wxGetFullHostName()
485 {
486 static const size_t hostnameSize = 257;
487
488 wxString buf;
489 bool ok = wxGetFullHostName(wxStringBuffer(buf, hostnameSize), hostnameSize);
490
491 if ( !ok )
492 buf.Empty();
493
494 return buf;
495 }
496
497 wxString wxGetHomeDir()
498 {
499 wxString home;
500 wxGetHomeDir(&home);
501
502 return home;
503 }
504
505 #if 0
506
507 wxString wxGetCurrentDir()
508 {
509 wxString dir;
510 size_t len = 1024;
511 bool ok;
512 do
513 {
514 ok = getcwd(dir.GetWriteBuf(len + 1), len) != NULL;
515 dir.UngetWriteBuf();
516
517 if ( !ok )
518 {
519 if ( errno != ERANGE )
520 {
521 wxLogSysError(wxT("Failed to get current directory"));
522
523 return wxEmptyString;
524 }
525 else
526 {
527 // buffer was too small, retry with a larger one
528 len *= 2;
529 }
530 }
531 //else: ok
532 } while ( !ok );
533
534 return dir;
535 }
536
537 #endif // 0
538
539 // ----------------------------------------------------------------------------
540 // Environment
541 // ----------------------------------------------------------------------------
542
543 #ifdef __WXOSX__
544 #if wxOSX_USE_COCOA_OR_CARBON
545 #include <crt_externs.h>
546 #endif
547 #endif
548
549 bool wxGetEnvMap(wxEnvVariableHashMap *map)
550 {
551 wxCHECK_MSG( map, false, wxS("output pointer can't be NULL") );
552
553 #if defined(__VISUALC__)
554 // This variable only exists to force the CRT to fill the wide char array,
555 // it might only have it in narrow char version until now as we use main()
556 // (and not _wmain()) as our entry point.
557 static wxChar* s_dummyEnvVar = _tgetenv(wxT("TEMP"));
558
559 wxChar **env = _tenviron;
560 #elif defined(__VMS)
561 // Now this routine wil give false for OpenVMS
562 // TODO : should we do something with logicals?
563 char **env=NULL;
564 #elif defined(__DARWIN__)
565 #if wxOSX_USE_COCOA_OR_CARBON
566 // Under Mac shared libraries don't have access to the global environ
567 // variable so use this Mac-specific function instead as advised by
568 // environ(7) under Darwin
569 char ***penv = _NSGetEnviron();
570 if ( !penv )
571 return false;
572 char **env = *penv;
573 #else
574 char **env=NULL;
575 // todo translate NSProcessInfo environment into map
576 #endif
577 #else // non-MSVC non-Mac
578 // Not sure if other compilers have _tenviron so use the (more standard)
579 // ANSI version only for them.
580
581 // Both POSIX and Single UNIX Specification say that this variable must
582 // exist but not that it must be declared anywhere and, indeed, it's not
583 // declared in several common systems (some BSDs, Solaris with native CC)
584 // so we (re)declare it ourselves to deal with these cases. However we do
585 // not do this under MSW where there can be DLL-related complications, i.e.
586 // the variable might be DLL-imported or not. Luckily we don't have to
587 // worry about this as all MSW compilers do seem to define it in their
588 // standard headers anyhow so we can just rely on already having the
589 // correct declaration. And if this turns out to be wrong, we can always
590 // add a configure test checking whether it is declared later.
591 #ifndef __WINDOWS__
592 extern char **environ;
593 #endif // !__WINDOWS__
594
595 char **env = environ;
596 #endif
597
598 if ( env )
599 {
600 wxString name,
601 value;
602 while ( *env )
603 {
604 const wxString var(*env);
605
606 name = var.BeforeFirst(wxS('='), &value);
607
608 (*map)[name] = value;
609
610 env++;
611 }
612
613 return true;
614 }
615
616 return false;
617 }
618
619 // ----------------------------------------------------------------------------
620 // wxExecute
621 // ----------------------------------------------------------------------------
622
623 // wxDoExecuteWithCapture() helper: reads an entire stream into one array
624 //
625 // returns true if ok, false if error
626 #if wxUSE_STREAMS
627 static bool ReadAll(wxInputStream *is, wxArrayString& output)
628 {
629 wxCHECK_MSG( is, false, wxT("NULL stream in wxExecute()?") );
630
631 // the stream could be already at EOF or in wxSTREAM_BROKEN_PIPE state
632 is->Reset();
633
634 wxTextInputStream tis(*is);
635
636 for ( ;; )
637 {
638 wxString line = tis.ReadLine();
639
640 // check for EOF before other errors as it's not really an error
641 if ( is->Eof() )
642 {
643 // add the last, possibly incomplete, line
644 if ( !line.empty() )
645 output.Add(line);
646 break;
647 }
648
649 // any other error is fatal
650 if ( !*is )
651 return false;
652
653 output.Add(line);
654 }
655
656 return true;
657 }
658 #endif // wxUSE_STREAMS
659
660 // this is a private function because it hasn't a clean interface: the first
661 // array is passed by reference, the second by pointer - instead we have 2
662 // public versions of wxExecute() below
663 static long wxDoExecuteWithCapture(const wxString& command,
664 wxArrayString& output,
665 wxArrayString* error,
666 int flags,
667 const wxExecuteEnv *env)
668 {
669 // create a wxProcess which will capture the output
670 wxProcess *process = new wxProcess;
671 process->Redirect();
672
673 long rc = wxExecute(command, wxEXEC_SYNC | flags, process, env);
674
675 #if wxUSE_STREAMS
676 if ( rc != -1 )
677 {
678 if ( !ReadAll(process->GetInputStream(), output) )
679 rc = -1;
680
681 if ( error )
682 {
683 if ( !ReadAll(process->GetErrorStream(), *error) )
684 rc = -1;
685 }
686
687 }
688 #else
689 wxUnusedVar(output);
690 wxUnusedVar(error);
691 #endif // wxUSE_STREAMS/!wxUSE_STREAMS
692
693 delete process;
694
695 return rc;
696 }
697
698 long wxExecute(const wxString& command, wxArrayString& output, int flags,
699 const wxExecuteEnv *env)
700 {
701 return wxDoExecuteWithCapture(command, output, NULL, flags, env);
702 }
703
704 long wxExecute(const wxString& command,
705 wxArrayString& output,
706 wxArrayString& error,
707 int flags,
708 const wxExecuteEnv *env)
709 {
710 return wxDoExecuteWithCapture(command, output, &error, flags, env);
711 }
712
713 // ----------------------------------------------------------------------------
714 // Id functions
715 // ----------------------------------------------------------------------------
716
717 // Id generation
718 static long wxCurrentId = 100;
719
720 long wxNewId()
721 {
722 // skip the part of IDs space that contains hard-coded values:
723 if (wxCurrentId == wxID_LOWEST)
724 wxCurrentId = wxID_HIGHEST + 1;
725
726 return wxCurrentId++;
727 }
728
729 long
730 wxGetCurrentId(void) { return wxCurrentId; }
731
732 void
733 wxRegisterId (long id)
734 {
735 if (id >= wxCurrentId)
736 wxCurrentId = id + 1;
737 }
738
739 // ----------------------------------------------------------------------------
740 // wxQsort, adapted by RR to allow user_data
741 // ----------------------------------------------------------------------------
742
743 /* This file is part of the GNU C Library.
744 Written by Douglas C. Schmidt (schmidt@ics.uci.edu).
745
746 Douglas Schmidt kindly gave permission to relicence the
747 code under the wxWindows licence:
748
749 From: "Douglas C. Schmidt" <schmidt@dre.vanderbilt.edu>
750 To: Robert Roebling <robert.roebling@uni-ulm.de>
751 Subject: Re: qsort licence
752 Date: Mon, 23 Jul 2007 03:44:25 -0500
753 Sender: schmidt@dre.vanderbilt.edu
754 Message-Id: <20070723084426.64F511000A8@tango.dre.vanderbilt.edu>
755
756 Hi Robert,
757
758 > [...] I'm asking if you'd be willing to relicence your code
759 > under the wxWindows licence. [...]
760
761 That's fine with me [...]
762
763 Thanks,
764
765 Doug */
766
767
768 /* Byte-wise swap two items of size SIZE. */
769 #define SWAP(a, b, size) \
770 do \
771 { \
772 register size_t __size = (size); \
773 register char *__a = (a), *__b = (b); \
774 do \
775 { \
776 char __tmp = *__a; \
777 *__a++ = *__b; \
778 *__b++ = __tmp; \
779 } while (--__size > 0); \
780 } while (0)
781
782 /* Discontinue quicksort algorithm when partition gets below this size.
783 This particular magic number was chosen to work best on a Sun 4/260. */
784 #define MAX_THRESH 4
785
786 /* Stack node declarations used to store unfulfilled partition obligations. */
787 typedef struct
788 {
789 char *lo;
790 char *hi;
791 } stack_node;
792
793 /* The next 4 #defines implement a very fast in-line stack abstraction. */
794 #define STACK_SIZE (8 * sizeof(unsigned long int))
795 #define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top))
796 #define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi)))
797 #define STACK_NOT_EMPTY (stack < top)
798
799
800 /* Order size using quicksort. This implementation incorporates
801 four optimizations discussed in Sedgewick:
802
803 1. Non-recursive, using an explicit stack of pointer that store the
804 next array partition to sort. To save time, this maximum amount
805 of space required to store an array of MAX_INT is allocated on the
806 stack. Assuming a 32-bit integer, this needs only 32 *
807 sizeof(stack_node) == 136 bits. Pretty cheap, actually.
808
809 2. Chose the pivot element using a median-of-three decision tree.
810 This reduces the probability of selecting a bad pivot value and
811 eliminates certain extraneous comparisons.
812
813 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving
814 insertion sort to order the MAX_THRESH items within each partition.
815 This is a big win, since insertion sort is faster for small, mostly
816 sorted array segments.
817
818 4. The larger of the two sub-partitions is always pushed onto the
819 stack first, with the algorithm then concentrating on the
820 smaller partition. This *guarantees* no more than log (n)
821 stack size is needed (actually O(1) in this case)! */
822
823 void wxQsort(void* pbase, size_t total_elems,
824 size_t size, wxSortCallback cmp, const void* user_data)
825 {
826 register char *base_ptr = (char *) pbase;
827 const size_t max_thresh = MAX_THRESH * size;
828
829 if (total_elems == 0)
830 /* Avoid lossage with unsigned arithmetic below. */
831 return;
832
833 if (total_elems > MAX_THRESH)
834 {
835 char *lo = base_ptr;
836 char *hi = &lo[size * (total_elems - 1)];
837 stack_node stack[STACK_SIZE];
838 stack_node *top = stack;
839
840 PUSH (NULL, NULL);
841
842 while (STACK_NOT_EMPTY)
843 {
844 char *left_ptr;
845 char *right_ptr;
846
847 /* Select median value from among LO, MID, and HI. Rearrange
848 LO and HI so the three values are sorted. This lowers the
849 probability of picking a pathological pivot value and
850 skips a comparison for both the LEFT_PTR and RIGHT_PTR. */
851
852 char *mid = lo + size * ((hi - lo) / size >> 1);
853
854 if ((*cmp) ((void *) mid, (void *) lo, user_data) < 0)
855 SWAP (mid, lo, size);
856 if ((*cmp) ((void *) hi, (void *) mid, user_data) < 0)
857 SWAP (mid, hi, size);
858 else
859 goto jump_over;
860 if ((*cmp) ((void *) mid, (void *) lo, user_data) < 0)
861 SWAP (mid, lo, size);
862 jump_over:;
863 left_ptr = lo + size;
864 right_ptr = hi - size;
865
866 /* Here's the famous ``collapse the walls'' section of quicksort.
867 Gotta like those tight inner loops! They are the main reason
868 that this algorithm runs much faster than others. */
869 do
870 {
871 while ((*cmp) ((void *) left_ptr, (void *) mid, user_data) < 0)
872 left_ptr += size;
873
874 while ((*cmp) ((void *) mid, (void *) right_ptr, user_data) < 0)
875 right_ptr -= size;
876
877 if (left_ptr < right_ptr)
878 {
879 SWAP (left_ptr, right_ptr, size);
880 if (mid == left_ptr)
881 mid = right_ptr;
882 else if (mid == right_ptr)
883 mid = left_ptr;
884 left_ptr += size;
885 right_ptr -= size;
886 }
887 else if (left_ptr == right_ptr)
888 {
889 left_ptr += size;
890 right_ptr -= size;
891 break;
892 }
893 }
894 while (left_ptr <= right_ptr);
895
896 /* Set up pointers for next iteration. First determine whether
897 left and right partitions are below the threshold size. If so,
898 ignore one or both. Otherwise, push the larger partition's
899 bounds on the stack and continue sorting the smaller one. */
900
901 if ((size_t) (right_ptr - lo) <= max_thresh)
902 {
903 if ((size_t) (hi - left_ptr) <= max_thresh)
904 /* Ignore both small partitions. */
905 POP (lo, hi);
906 else
907 /* Ignore small left partition. */
908 lo = left_ptr;
909 }
910 else if ((size_t) (hi - left_ptr) <= max_thresh)
911 /* Ignore small right partition. */
912 hi = right_ptr;
913 else if ((right_ptr - lo) > (hi - left_ptr))
914 {
915 /* Push larger left partition indices. */
916 PUSH (lo, right_ptr);
917 lo = left_ptr;
918 }
919 else
920 {
921 /* Push larger right partition indices. */
922 PUSH (left_ptr, hi);
923 hi = right_ptr;
924 }
925 }
926 }
927
928 /* Once the BASE_PTR array is partially sorted by quicksort the rest
929 is completely sorted using insertion sort, since this is efficient
930 for partitions below MAX_THRESH size. BASE_PTR points to the beginning
931 of the array to sort, and END_PTR points at the very last element in
932 the array (*not* one beyond it!). */
933
934 {
935 char *const end_ptr = &base_ptr[size * (total_elems - 1)];
936 char *tmp_ptr = base_ptr;
937 char *thresh = base_ptr + max_thresh;
938 if ( thresh > end_ptr )
939 thresh = end_ptr;
940 register char *run_ptr;
941
942 /* Find smallest element in first threshold and place it at the
943 array's beginning. This is the smallest array element,
944 and the operation speeds up insertion sort's inner loop. */
945
946 for (run_ptr = tmp_ptr + size; run_ptr <= thresh; run_ptr += size)
947 if ((*cmp) ((void *) run_ptr, (void *) tmp_ptr, user_data) < 0)
948 tmp_ptr = run_ptr;
949
950 if (tmp_ptr != base_ptr)
951 SWAP (tmp_ptr, base_ptr, size);
952
953 /* Insertion sort, running from left-hand-side up to right-hand-side. */
954
955 run_ptr = base_ptr + size;
956 while ((run_ptr += size) <= end_ptr)
957 {
958 tmp_ptr = run_ptr - size;
959 while ((*cmp) ((void *) run_ptr, (void *) tmp_ptr, user_data) < 0)
960 tmp_ptr -= size;
961
962 tmp_ptr += size;
963 if (tmp_ptr != run_ptr)
964 {
965 char *trav;
966
967 trav = run_ptr + size;
968 while (--trav >= run_ptr)
969 {
970 char c = *trav;
971 char *hi, *lo;
972
973 for (hi = lo = trav; (lo -= size) >= tmp_ptr; hi = lo)
974 *hi = *lo;
975 *hi = c;
976 }
977 }
978 }
979 }
980 }
981
982 #endif // wxUSE_BASE
983
984
985
986 // ============================================================================
987 // GUI-only functions from now on
988 // ============================================================================
989
990 #if wxUSE_GUI
991
992 // this function is only really implemented for X11-based ports, including GTK1
993 // (GTK2 sets detectable auto-repeat automatically anyhow)
994 #if !(defined(__WXX11__) || defined(__WXMOTIF__) || \
995 (defined(__WXGTK__) && !defined(__WXGTK20__)))
996 bool wxSetDetectableAutoRepeat( bool WXUNUSED(flag) )
997 {
998 return true;
999 }
1000 #endif // !X11-based port
1001
1002 // ----------------------------------------------------------------------------
1003 // Launch default browser
1004 // ----------------------------------------------------------------------------
1005
1006 #if defined(__WINDOWS__)
1007
1008 // implemented in a port-specific utils source file:
1009 bool wxDoLaunchDefaultBrowser(const wxString& url, const wxString& scheme, int flags);
1010
1011 #elif defined(__WXX11__) || defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXCOCOA__) || \
1012 (defined(__WXOSX__) )
1013
1014 // implemented in a port-specific utils source file:
1015 bool wxDoLaunchDefaultBrowser(const wxString& url, int flags);
1016
1017 #else
1018
1019 // a "generic" implementation:
1020 bool wxDoLaunchDefaultBrowser(const wxString& url, int flags)
1021 {
1022 // on other platforms try to use mime types or wxExecute...
1023
1024 bool ok = false;
1025 wxString cmd;
1026
1027 #if wxUSE_MIMETYPE
1028 wxFileType *ft = wxTheMimeTypesManager->GetFileTypeFromExtension(wxT("html"));
1029 if ( ft )
1030 {
1031 wxString mt;
1032 ft->GetMimeType(&mt);
1033
1034 ok = ft->GetOpenCommand(&cmd, wxFileType::MessageParameters(url));
1035 delete ft;
1036 }
1037 #endif // wxUSE_MIMETYPE
1038
1039 if ( !ok || cmd.empty() )
1040 {
1041 // fallback to checking for the BROWSER environment variable
1042 if ( !wxGetEnv(wxT("BROWSER"), &cmd) || cmd.empty() )
1043 cmd << wxT(' ') << url;
1044 }
1045
1046 ok = ( !cmd.empty() && wxExecute(cmd) );
1047 if (ok)
1048 return ok;
1049
1050 // no file type for HTML extension
1051 wxLogError(_("No default application configured for HTML files."));
1052
1053 return false;
1054 }
1055 #endif
1056
1057 static bool DoLaunchDefaultBrowserHelper(const wxString& urlOrig, int flags)
1058 {
1059 // NOTE: we don't have to care about the wxBROWSER_NOBUSYCURSOR flag
1060 // as it was already handled by wxLaunchDefaultBrowser
1061
1062 wxUnusedVar(flags);
1063
1064 wxString url(urlOrig), scheme;
1065 wxURI uri(url);
1066
1067 // this check is useful to avoid that wxURI recognizes as scheme parts of
1068 // the filename, in case urlOrig is a local filename
1069 // (e.g. "C:\\test.txt" when parsed by wxURI reports a scheme == "C")
1070 bool hasValidScheme = uri.HasScheme() && uri.GetScheme().length() > 1;
1071
1072 #if defined(__WINDOWS__)
1073
1074 // NOTE: when testing wxMSW's wxLaunchDefaultBrowser all possible forms
1075 // of the URL/flags should be tested; e.g.:
1076 //
1077 // for (int i=0; i<2; i++)
1078 // {
1079 // // test arguments without a valid URL scheme:
1080 // wxLaunchDefaultBrowser("C:\\test.txt", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1081 // wxLaunchDefaultBrowser("wxwidgets.org", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1082 //
1083 // // test arguments with different valid schemes:
1084 // wxLaunchDefaultBrowser("file:/C%3A/test.txt", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1085 // wxLaunchDefaultBrowser("http://wxwidgets.org", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1086 // wxLaunchDefaultBrowser("mailto:user@host.org", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1087 // }
1088 // (assuming you have a C:\test.txt file)
1089
1090 if ( !hasValidScheme )
1091 {
1092 if (wxFileExists(urlOrig) || wxDirExists(urlOrig))
1093 {
1094 scheme = "file";
1095 // do not prepend the file scheme to the URL as ShellExecuteEx() doesn't like it
1096 }
1097 else
1098 {
1099 url.Prepend(wxS("http://"));
1100 scheme = "http";
1101 }
1102 }
1103 else if ( hasValidScheme )
1104 {
1105 scheme = uri.GetScheme();
1106
1107 if ( uri.GetScheme() == "file" )
1108 {
1109 // TODO: extract URLToFileName() to some always compiled in
1110 // function
1111 #if wxUSE_FILESYSTEM
1112 // ShellExecuteEx() doesn't like the "file" scheme when opening local files;
1113 // remove it
1114 url = wxFileSystem::URLToFileName(url).GetFullPath();
1115 #endif // wxUSE_FILESYSTEM
1116 }
1117 }
1118
1119 if (wxDoLaunchDefaultBrowser(url, scheme, flags))
1120 return true;
1121 //else: call wxLogSysError
1122 #else
1123 if ( !hasValidScheme )
1124 {
1125 // set the scheme of url to "http" or "file" if it does not have one
1126 if (wxFileExists(urlOrig) || wxDirExists(urlOrig))
1127 url.Prepend(wxS("file://"));
1128 else
1129 url.Prepend(wxS("http://"));
1130 }
1131
1132 if (wxDoLaunchDefaultBrowser(url, flags))
1133 return true;
1134 //else: call wxLogSysError
1135 #endif
1136
1137 wxLogSysError(_("Failed to open URL \"%s\" in default browser."),
1138 url.c_str());
1139
1140 return false;
1141 }
1142
1143 bool wxLaunchDefaultBrowser(const wxString& url, int flags)
1144 {
1145 // NOTE: as documented, "url" may be both a real well-formed URL
1146 // and a local file name
1147
1148 if ( flags & wxBROWSER_NOBUSYCURSOR )
1149 return DoLaunchDefaultBrowserHelper(url, flags);
1150
1151 wxBusyCursor bc;
1152 return DoLaunchDefaultBrowserHelper(url, flags);
1153 }
1154
1155 // ----------------------------------------------------------------------------
1156 // Menu accelerators related functions
1157 // ----------------------------------------------------------------------------
1158
1159 #if WXWIN_COMPATIBILITY_2_6
1160 wxChar *wxStripMenuCodes(const wxChar *in, wxChar *out)
1161 {
1162 #if wxUSE_MENUS
1163 wxString s = wxMenuItem::GetLabelText(in);
1164 #else
1165 wxString str(in);
1166 wxString s = wxStripMenuCodes(str);
1167 #endif // wxUSE_MENUS
1168 if ( out )
1169 {
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));
1172 }
1173 else
1174 {
1175 out = new wxChar[s.length() + 1];
1176 wxStrcpy(out, s.c_str());
1177 }
1178
1179 return out;
1180 }
1181 #endif
1182
1183 wxString wxStripMenuCodes(const wxString& in, int flags)
1184 {
1185 wxASSERT_MSG( flags, wxT("this is useless to call without any flags") );
1186
1187 wxString out;
1188
1189 size_t len = in.length();
1190 out.reserve(len);
1191
1192 for ( wxString::const_iterator it = in.begin(); it != in.end(); ++it )
1193 {
1194 wxChar ch = *it;
1195 if ( (flags & wxStrip_Mnemonics) && ch == wxT('&') )
1196 {
1197 // skip it, it is used to introduce the accel char (or to quote
1198 // itself in which case it should still be skipped): note that it
1199 // can't be the last character of the string
1200 if ( ++it == in.end() )
1201 {
1202 wxLogDebug(wxT("Invalid menu string '%s'"), in.c_str());
1203 }
1204 else
1205 {
1206 // use the next char instead
1207 ch = *it;
1208 }
1209 }
1210 else if ( (flags & wxStrip_Accel) && ch == wxT('\t') )
1211 {
1212 // everything after TAB is accel string, exit the loop
1213 break;
1214 }
1215
1216 out += ch;
1217 }
1218
1219 return out;
1220 }
1221
1222 // ----------------------------------------------------------------------------
1223 // Window search functions
1224 // ----------------------------------------------------------------------------
1225
1226 /*
1227 * If parent is non-NULL, look through children for a label or title
1228 * matching the specified string. If NULL, look through all top-level windows.
1229 *
1230 */
1231
1232 wxWindow *
1233 wxFindWindowByLabel (const wxString& title, wxWindow * parent)
1234 {
1235 return wxWindow::FindWindowByLabel( title, parent );
1236 }
1237
1238
1239 /*
1240 * If parent is non-NULL, look through children for a name
1241 * matching the specified string. If NULL, look through all top-level windows.
1242 *
1243 */
1244
1245 wxWindow *
1246 wxFindWindowByName (const wxString& name, wxWindow * parent)
1247 {
1248 return wxWindow::FindWindowByName( name, parent );
1249 }
1250
1251 // Returns menu item id or wxNOT_FOUND if none.
1252 int
1253 wxFindMenuItemId(wxFrame *frame,
1254 const wxString& menuString,
1255 const wxString& itemString)
1256 {
1257 #if wxUSE_MENUS
1258 wxMenuBar *menuBar = frame->GetMenuBar ();
1259 if ( menuBar )
1260 return menuBar->FindMenuItem (menuString, itemString);
1261 #else // !wxUSE_MENUS
1262 wxUnusedVar(frame);
1263 wxUnusedVar(menuString);
1264 wxUnusedVar(itemString);
1265 #endif // wxUSE_MENUS/!wxUSE_MENUS
1266
1267 return wxNOT_FOUND;
1268 }
1269
1270 // Try to find the deepest child that contains 'pt'.
1271 // We go backwards, to try to allow for controls that are spacially
1272 // within other controls, but are still siblings (e.g. buttons within
1273 // static boxes). Static boxes are likely to be created _before_ controls
1274 // that sit inside them.
1275 wxWindow* wxFindWindowAtPoint(wxWindow* win, const wxPoint& pt)
1276 {
1277 if (!win->IsShown())
1278 return NULL;
1279
1280 // Hack for wxNotebook case: at least in wxGTK, all pages
1281 // claim to be shown, so we must only deal with the selected one.
1282 #if wxUSE_NOTEBOOK
1283 if (wxDynamicCast(win, wxNotebook))
1284 {
1285 wxNotebook* nb = (wxNotebook*) win;
1286 int sel = nb->GetSelection();
1287 if (sel >= 0)
1288 {
1289 wxWindow* child = nb->GetPage(sel);
1290 wxWindow* foundWin = wxFindWindowAtPoint(child, pt);
1291 if (foundWin)
1292 return foundWin;
1293 }
1294 }
1295 #endif
1296
1297 wxWindowList::compatibility_iterator node = win->GetChildren().GetLast();
1298 while (node)
1299 {
1300 wxWindow* child = node->GetData();
1301 wxWindow* foundWin = wxFindWindowAtPoint(child, pt);
1302 if (foundWin)
1303 return foundWin;
1304 node = node->GetPrevious();
1305 }
1306
1307 wxPoint pos = win->GetPosition();
1308 wxSize sz = win->GetSize();
1309 if ( !win->IsTopLevel() && win->GetParent() )
1310 {
1311 pos = win->GetParent()->ClientToScreen(pos);
1312 }
1313
1314 wxRect rect(pos, sz);
1315 if (rect.Contains(pt))
1316 return win;
1317
1318 return NULL;
1319 }
1320
1321 wxWindow* wxGenericFindWindowAtPoint(const wxPoint& pt)
1322 {
1323 // Go backwards through the list since windows
1324 // on top are likely to have been appended most
1325 // recently.
1326 wxWindowList::compatibility_iterator node = wxTopLevelWindows.GetLast();
1327 while (node)
1328 {
1329 wxWindow* win = node->GetData();
1330 wxWindow* found = wxFindWindowAtPoint(win, pt);
1331 if (found)
1332 return found;
1333 node = node->GetPrevious();
1334 }
1335 return NULL;
1336 }
1337
1338 // ----------------------------------------------------------------------------
1339 // GUI helpers
1340 // ----------------------------------------------------------------------------
1341
1342 /*
1343 * N.B. these convenience functions must be separate from msgdlgg.cpp, textdlgg.cpp
1344 * since otherwise the generic code may be pulled in unnecessarily.
1345 */
1346
1347 #if wxUSE_MSGDLG
1348
1349 int wxMessageBox(const wxString& message, const wxString& caption, long style,
1350 wxWindow *parent, int WXUNUSED(x), int WXUNUSED(y) )
1351 {
1352 // add the appropriate icon unless this was explicitly disabled by use of
1353 // wxICON_NONE
1354 if ( !(style & wxICON_NONE) && !(style & wxICON_MASK) )
1355 {
1356 style |= style & wxYES ? wxICON_QUESTION : wxICON_INFORMATION;
1357 }
1358
1359 wxMessageDialog dialog(parent, message, caption, style);
1360
1361 int ans = dialog.ShowModal();
1362 switch ( ans )
1363 {
1364 case wxID_OK:
1365 return wxOK;
1366 case wxID_YES:
1367 return wxYES;
1368 case wxID_NO:
1369 return wxNO;
1370 case wxID_CANCEL:
1371 return wxCANCEL;
1372 case wxID_HELP:
1373 return wxHELP;
1374 }
1375
1376 wxFAIL_MSG( wxT("unexpected return code from wxMessageDialog") );
1377
1378 return wxCANCEL;
1379 }
1380
1381 wxVersionInfo wxGetLibraryVersionInfo()
1382 {
1383 // don't translate these strings, they're for diagnostics purposes only
1384 wxString msg;
1385 msg.Printf(wxS("wxWidgets Library (%s port)\n")
1386 wxS("Version %d.%d.%d (Unicode: %s, debug level: %d),\n")
1387 wxS("compiled at %s %s\n\n")
1388 wxS("Runtime version of toolkit used is %d.%d.\n"),
1389 wxPlatformInfo::Get().GetPortIdName(),
1390 wxMAJOR_VERSION,
1391 wxMINOR_VERSION,
1392 wxRELEASE_NUMBER,
1393 #if wxUSE_UNICODE_UTF8
1394 "UTF-8",
1395 #elif wxUSE_UNICODE
1396 "wchar_t",
1397 #else
1398 "none",
1399 #endif
1400 wxDEBUG_LEVEL,
1401 __TDATE__,
1402 __TTIME__,
1403 wxPlatformInfo::Get().GetToolkitMajorVersion(),
1404 wxPlatformInfo::Get().GetToolkitMinorVersion()
1405 );
1406
1407 #ifdef __WXGTK__
1408 msg += wxString::Format("Compile-time GTK+ version is %d.%d.%d.\n",
1409 GTK_MAJOR_VERSION,
1410 GTK_MINOR_VERSION,
1411 GTK_MICRO_VERSION);
1412 #endif // __WXGTK__
1413
1414 return wxVersionInfo(wxS("wxWidgets"),
1415 wxMAJOR_VERSION,
1416 wxMINOR_VERSION,
1417 wxRELEASE_NUMBER,
1418 msg,
1419 wxS("Copyright (c) 1995-2011 wxWidgets team"));
1420 }
1421
1422 void wxInfoMessageBox(wxWindow* parent)
1423 {
1424 wxVersionInfo info = wxGetLibraryVersionInfo();
1425 wxString msg = info.ToString();
1426
1427 msg << wxS("\n") << info.GetCopyright();
1428
1429 wxMessageBox(msg, wxT("wxWidgets information"),
1430 wxICON_INFORMATION | wxOK,
1431 parent);
1432 }
1433
1434 #endif // wxUSE_MSGDLG
1435
1436 #if wxUSE_TEXTDLG
1437
1438 wxString wxGetTextFromUser(const wxString& message, const wxString& caption,
1439 const wxString& defaultValue, wxWindow *parent,
1440 wxCoord x, wxCoord y, bool centre )
1441 {
1442 wxString str;
1443 long style = wxTextEntryDialogStyle;
1444
1445 if (centre)
1446 style |= wxCENTRE;
1447 else
1448 style &= ~wxCENTRE;
1449
1450 wxTextEntryDialog dialog(parent, message, caption, defaultValue, style, wxPoint(x, y));
1451
1452 if (dialog.ShowModal() == wxID_OK)
1453 {
1454 str = dialog.GetValue();
1455 }
1456
1457 return str;
1458 }
1459
1460 wxString wxGetPasswordFromUser(const wxString& message,
1461 const wxString& caption,
1462 const wxString& defaultValue,
1463 wxWindow *parent,
1464 wxCoord x, wxCoord y, bool centre )
1465 {
1466 wxString str;
1467 long style = wxTextEntryDialogStyle;
1468
1469 if (centre)
1470 style |= wxCENTRE;
1471 else
1472 style &= ~wxCENTRE;
1473
1474 wxPasswordEntryDialog dialog(parent, message, caption, defaultValue,
1475 style, wxPoint(x, y));
1476 if ( dialog.ShowModal() == wxID_OK )
1477 {
1478 str = dialog.GetValue();
1479 }
1480
1481 return str;
1482 }
1483
1484 #endif // wxUSE_TEXTDLG
1485
1486 #if wxUSE_COLOURDLG
1487
1488 wxColour wxGetColourFromUser(wxWindow *parent,
1489 const wxColour& colInit,
1490 const wxString& caption,
1491 wxColourData *ptrData)
1492 {
1493 // contains serialized representation of wxColourData used the last time
1494 // the dialog was shown: we want to reuse it the next time in order to show
1495 // the same custom colours to the user (and we can't just have static
1496 // wxColourData itself because it's a GUI object and so should be destroyed
1497 // before GUI shutdown and doing it during static cleanup is too late)
1498 static wxString s_strColourData;
1499
1500 wxColourData data;
1501 if ( !ptrData )
1502 {
1503 ptrData = &data;
1504 if ( !s_strColourData.empty() )
1505 {
1506 if ( !data.FromString(s_strColourData) )
1507 {
1508 wxFAIL_MSG( "bug in wxColourData::FromString()?" );
1509 }
1510
1511 #ifdef __WXMSW__
1512 // we don't get back the "choose full" flag value from the native
1513 // dialog and so we can't preserve it between runs, so we decide to
1514 // always use it as it seems better than not using it (user can
1515 // just ignore the extra controls in the dialog but having to click
1516 // a button each time to show them would be very annoying
1517 data.SetChooseFull(true);
1518 #endif // __WXMSW__
1519 }
1520 }
1521
1522 if ( colInit.IsOk() )
1523 {
1524 ptrData->SetColour(colInit);
1525 }
1526
1527 wxColour colRet;
1528 wxColourDialog dialog(parent, ptrData);
1529 if (!caption.empty())
1530 dialog.SetTitle(caption);
1531 if ( dialog.ShowModal() == wxID_OK )
1532 {
1533 *ptrData = dialog.GetColourData();
1534 colRet = ptrData->GetColour();
1535 s_strColourData = ptrData->ToString();
1536 }
1537 //else: leave colRet invalid
1538
1539 return colRet;
1540 }
1541
1542 #endif // wxUSE_COLOURDLG
1543
1544 #if wxUSE_FONTDLG
1545
1546 wxFont wxGetFontFromUser(wxWindow *parent, const wxFont& fontInit, const wxString& caption)
1547 {
1548 wxFontData data;
1549 if ( fontInit.IsOk() )
1550 {
1551 data.SetInitialFont(fontInit);
1552 }
1553
1554 wxFont fontRet;
1555 wxFontDialog dialog(parent, data);
1556 if (!caption.empty())
1557 dialog.SetTitle(caption);
1558 if ( dialog.ShowModal() == wxID_OK )
1559 {
1560 fontRet = dialog.GetFontData().GetChosenFont();
1561 }
1562 //else: leave it invalid
1563
1564 return fontRet;
1565 }
1566
1567 #endif // wxUSE_FONTDLG
1568
1569 // ----------------------------------------------------------------------------
1570 // wxSafeYield and supporting functions
1571 // ----------------------------------------------------------------------------
1572
1573 void wxEnableTopLevelWindows(bool enable)
1574 {
1575 wxWindowList::compatibility_iterator node;
1576 for ( node = wxTopLevelWindows.GetFirst(); node; node = node->GetNext() )
1577 node->GetData()->Enable(enable);
1578 }
1579
1580 #if defined(__WXOSX__) && wxOSX_USE_COCOA
1581
1582 // defined in evtloop.mm
1583
1584 #else
1585
1586 wxWindowDisabler::wxWindowDisabler(bool disable)
1587 {
1588 m_disabled = disable;
1589 if ( disable )
1590 DoDisable();
1591 }
1592
1593 wxWindowDisabler::wxWindowDisabler(wxWindow *winToSkip)
1594 {
1595 m_disabled = true;
1596 DoDisable(winToSkip);
1597 }
1598
1599 void wxWindowDisabler::DoDisable(wxWindow *winToSkip)
1600 {
1601 // remember the top level windows which were already disabled, so that we
1602 // don't reenable them later
1603 m_winDisabled = NULL;
1604
1605 wxWindowList::compatibility_iterator node;
1606 for ( node = wxTopLevelWindows.GetFirst(); node; node = node->GetNext() )
1607 {
1608 wxWindow *winTop = node->GetData();
1609 if ( winTop == winToSkip )
1610 continue;
1611
1612 // we don't need to disable the hidden or already disabled windows
1613 if ( winTop->IsEnabled() && winTop->IsShown() )
1614 {
1615 winTop->Disable();
1616 }
1617 else
1618 {
1619 if ( !m_winDisabled )
1620 {
1621 m_winDisabled = new wxWindowList;
1622 }
1623
1624 m_winDisabled->Append(winTop);
1625 }
1626 }
1627 }
1628
1629 wxWindowDisabler::~wxWindowDisabler()
1630 {
1631 if ( !m_disabled )
1632 return;
1633
1634 wxWindowList::compatibility_iterator node;
1635 for ( node = wxTopLevelWindows.GetFirst(); node; node = node->GetNext() )
1636 {
1637 wxWindow *winTop = node->GetData();
1638 if ( !m_winDisabled || !m_winDisabled->Find(winTop) )
1639 {
1640 winTop->Enable();
1641 }
1642 //else: had been already disabled, don't reenable
1643 }
1644
1645 delete m_winDisabled;
1646 }
1647
1648 #endif
1649
1650 // Yield to other apps/messages and disable user input to all windows except
1651 // the given one
1652 bool wxSafeYield(wxWindow *win, bool onlyIfNeeded)
1653 {
1654 wxWindowDisabler wd(win);
1655
1656 bool rc;
1657 if (onlyIfNeeded)
1658 rc = wxYieldIfNeeded();
1659 else
1660 rc = wxYield();
1661
1662 return rc;
1663 }
1664
1665 // ----------------------------------------------------------------------------
1666 // wxApp::Yield() wrappers for backwards compatibility
1667 // ----------------------------------------------------------------------------
1668
1669 bool wxYield()
1670 {
1671 return wxTheApp && wxTheApp->Yield();
1672 }
1673
1674 bool wxYieldIfNeeded()
1675 {
1676 return wxTheApp && wxTheApp->Yield(true);
1677 }
1678
1679 #endif // wxUSE_GUI