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