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