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