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