]> git.saurik.com Git - wxWidgets.git/blob - src/common/utilscmn.cpp
wxCocoa: Added preliminary Blit support
[wxWidgets.git] / src / common / utilscmn.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: 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 #ifdef __GNUG__
21 #pragma implementation "utils.h"
22 #endif
23
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
26
27 #ifdef __BORLANDC__
28 #pragma hdrstop
29 #endif
30
31 #ifndef WX_PRECOMP
32 #include "wx/app.h"
33 #include "wx/string.h"
34 #include "wx/utils.h"
35 #include "wx/intl.h"
36 #include "wx/log.h"
37
38 #if wxUSE_GUI
39 #include "wx/window.h"
40 #include "wx/frame.h"
41 #include "wx/menu.h"
42 #include "wx/msgdlg.h"
43 #include "wx/textdlg.h"
44 #include "wx/textctrl.h" // for wxTE_PASSWORD
45 #if wxUSE_ACCEL
46 #include "wx/menuitem.h"
47 #include "wx/accel.h"
48 #endif // wxUSE_ACCEL
49 #endif // wxUSE_GUI
50 #endif // WX_PRECOMP
51
52 #include "wx/apptrait.h"
53
54 #include "wx/process.h"
55 #include "wx/txtstrm.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 !defined(__WATCOMC__)
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/frame.h"
77 #include "wx/statusbr.h"
78 #endif // wxUSE_GUI
79
80 #ifndef __WXWINCE__
81 #include <time.h>
82 #else
83 #include "wx/msw/wince/time.h"
84 #endif
85
86 #if !defined(__MWERKS__) && !defined(__WXWINCE__)
87 #include <sys/types.h>
88 #include <sys/stat.h>
89 #endif
90
91 #ifdef __WXMSW__
92 #include "wx/msw/private.h"
93 #endif
94
95 #if wxUSE_BASE
96
97 // ----------------------------------------------------------------------------
98 // common data
99 // ----------------------------------------------------------------------------
100
101 #if WXWIN_COMPATIBILITY_2_2
102 const wxChar *wxInternalErrorStr = wxT("wxWindows Internal Error");
103 const wxChar *wxFatalErrorStr = wxT("wxWindows Fatal Error");
104 #endif // WXWIN_COMPATIBILITY_2_2
105
106 // ============================================================================
107 // implementation
108 // ============================================================================
109
110 #if WXWIN_COMPATIBILITY_2_4
111
112 wxChar *
113 copystring (const wxChar *s)
114 {
115 if (s == NULL) s = wxT("");
116 size_t len = wxStrlen (s) + 1;
117
118 wxChar *news = new wxChar[len];
119 memcpy (news, s, len * sizeof(wxChar)); // Should be the fastest
120
121 return news;
122 }
123
124 #endif // WXWIN_COMPATIBILITY_2_4
125
126 // ----------------------------------------------------------------------------
127 // String <-> Number conversions (deprecated)
128 // ----------------------------------------------------------------------------
129
130 #if WXWIN_COMPATIBILITY_2_4
131
132 WXDLLIMPEXP_DATA_BASE(const wxChar *) wxFloatToStringStr = wxT("%.2f");
133 WXDLLIMPEXP_DATA_BASE(const wxChar *) wxDoubleToStringStr = wxT("%.2f");
134
135 void
136 StringToFloat (const wxChar *s, float *number)
137 {
138 if (s && *s && number)
139 *number = (float) wxStrtod (s, (wxChar **) NULL);
140 }
141
142 void
143 StringToDouble (const wxChar *s, double *number)
144 {
145 if (s && *s && number)
146 *number = wxStrtod (s, (wxChar **) NULL);
147 }
148
149 wxChar *
150 FloatToString (float number, const wxChar *fmt)
151 {
152 static wxChar buf[256];
153
154 wxSprintf (buf, fmt, number);
155 return buf;
156 }
157
158 wxChar *
159 DoubleToString (double number, const wxChar *fmt)
160 {
161 static wxChar buf[256];
162
163 wxSprintf (buf, fmt, number);
164 return buf;
165 }
166
167 void
168 StringToInt (const wxChar *s, int *number)
169 {
170 if (s && *s && number)
171 *number = (int) wxStrtol (s, (wxChar **) NULL, 10);
172 }
173
174 void
175 StringToLong (const wxChar *s, long *number)
176 {
177 if (s && *s && number)
178 *number = wxStrtol (s, (wxChar **) NULL, 10);
179 }
180
181 wxChar *
182 IntToString (int number)
183 {
184 static wxChar buf[20];
185
186 wxSprintf (buf, wxT("%d"), number);
187 return buf;
188 }
189
190 wxChar *
191 LongToString (long number)
192 {
193 static wxChar buf[20];
194
195 wxSprintf (buf, wxT("%ld"), number);
196 return buf;
197 }
198
199 #endif // WXWIN_COMPATIBILITY_2_4
200
201 // Array used in DecToHex conversion routine.
202 static wxChar hexArray[] = wxT("0123456789ABCDEF");
203
204 // Convert 2-digit hex number to decimal
205 int wxHexToDec(const wxString& buf)
206 {
207 int firstDigit, secondDigit;
208
209 if (buf.GetChar(0) >= wxT('A'))
210 firstDigit = buf.GetChar(0) - wxT('A') + 10;
211 else
212 firstDigit = buf.GetChar(0) - wxT('0');
213
214 if (buf.GetChar(1) >= wxT('A'))
215 secondDigit = buf.GetChar(1) - wxT('A') + 10;
216 else
217 secondDigit = buf.GetChar(1) - wxT('0');
218
219 return (firstDigit & 0xF) * 16 + (secondDigit & 0xF );
220 }
221
222 // Convert decimal integer to 2-character hex string
223 void wxDecToHex(int dec, wxChar *buf)
224 {
225 int firstDigit = (int)(dec/16.0);
226 int secondDigit = (int)(dec - (firstDigit*16.0));
227 buf[0] = hexArray[firstDigit];
228 buf[1] = hexArray[secondDigit];
229 buf[2] = 0;
230 }
231
232 // Convert decimal integer to 2-character hex string
233 wxString wxDecToHex(int dec)
234 {
235 wxChar buf[3];
236 wxDecToHex(dec, buf);
237 return wxString(buf);
238 }
239
240 // ----------------------------------------------------------------------------
241 // misc functions
242 // ----------------------------------------------------------------------------
243
244 // Return the current date/time
245 wxString wxNow()
246 {
247 #ifdef __WXWINCE__
248 #if wxUSE_DATETIME
249 wxDateTime now = wxDateTime::Now();
250 return now.Format();
251 #else
252 return wxEmptyString;
253 #endif
254 #else
255 time_t now = time((time_t *) NULL);
256 char *date = ctime(&now);
257 date[24] = '\0';
258 return wxString::FromAscii(date);
259 #endif
260 }
261
262 const wxChar *wxGetInstallPrefix()
263 {
264 wxString prefix;
265
266 if ( wxGetEnv(wxT("WXPREFIX"), &prefix) )
267 return prefix.c_str();
268
269 #ifdef wxINSTALL_PREFIX
270 return wxT(wxINSTALL_PREFIX);
271 #else
272 return wxT("");
273 #endif
274 }
275
276 wxString wxGetDataDir()
277 {
278 wxString format = wxGetInstallPrefix();
279 format << wxFILE_SEP_PATH
280 << wxT("share") << wxFILE_SEP_PATH
281 << wxT("wx") << wxFILE_SEP_PATH
282 << wxT("%i.%i");
283 wxString dir;
284 dir.Printf(format.c_str(), wxMAJOR_VERSION, wxMINOR_VERSION);
285 return dir;
286 }
287
288 int wxGetOsVersion(int *verMaj, int *verMin)
289 {
290 // we want this function to work even if there is no wxApp
291 wxConsoleAppTraits traitsConsole;
292 wxAppTraits *traits = wxTheApp ? wxTheApp->GetTraits() : NULL;
293 if ( ! traits )
294 traits = &traitsConsole;
295
296 return traits->GetOSVersion(verMaj, verMin);
297 }
298
299 // ----------------------------------------------------------------------------
300 // network and user id functions
301 // ----------------------------------------------------------------------------
302
303 // Get Full RFC822 style email address
304 bool wxGetEmailAddress(wxChar *address, int maxSize)
305 {
306 wxString email = wxGetEmailAddress();
307 if ( !email )
308 return FALSE;
309
310 wxStrncpy(address, email, maxSize - 1);
311 address[maxSize - 1] = wxT('\0');
312
313 return TRUE;
314 }
315
316 wxString wxGetEmailAddress()
317 {
318 wxString email;
319
320 wxString host = wxGetFullHostName();
321 if ( !!host )
322 {
323 wxString user = wxGetUserId();
324 if ( !!user )
325 {
326 email << user << wxT('@') << host;
327 }
328 }
329
330 return email;
331 }
332
333 wxString wxGetUserId()
334 {
335 static const int maxLoginLen = 256; // FIXME arbitrary number
336
337 wxString buf;
338 bool ok = wxGetUserId(wxStringBuffer(buf, maxLoginLen), maxLoginLen);
339
340 if ( !ok )
341 buf.Empty();
342
343 return buf;
344 }
345
346 wxString wxGetUserName()
347 {
348 static const int maxUserNameLen = 1024; // FIXME arbitrary number
349
350 wxString buf;
351 bool ok = wxGetUserName(wxStringBuffer(buf, maxUserNameLen), maxUserNameLen);
352
353 if ( !ok )
354 buf.Empty();
355
356 return buf;
357 }
358
359 wxString wxGetHostName()
360 {
361 static const size_t hostnameSize = 257;
362
363 wxString buf;
364 bool ok = wxGetHostName(wxStringBuffer(buf, hostnameSize), hostnameSize);
365
366 if ( !ok )
367 buf.Empty();
368
369 return buf;
370 }
371
372 wxString wxGetFullHostName()
373 {
374 static const size_t hostnameSize = 257;
375
376 wxString buf;
377 bool ok = wxGetFullHostName(wxStringBuffer(buf, hostnameSize), hostnameSize);
378
379 if ( !ok )
380 buf.Empty();
381
382 return buf;
383 }
384
385 wxString wxGetHomeDir()
386 {
387 wxString home;
388 wxGetHomeDir(&home);
389
390 return home;
391 }
392
393 #if 0
394
395 wxString wxGetCurrentDir()
396 {
397 wxString dir;
398 size_t len = 1024;
399 bool ok;
400 do
401 {
402 ok = getcwd(dir.GetWriteBuf(len + 1), len) != NULL;
403 dir.UngetWriteBuf();
404
405 if ( !ok )
406 {
407 if ( errno != ERANGE )
408 {
409 wxLogSysError(_T("Failed to get current directory"));
410
411 return wxEmptyString;
412 }
413 else
414 {
415 // buffer was too small, retry with a larger one
416 len *= 2;
417 }
418 }
419 //else: ok
420 } while ( !ok );
421
422 return dir;
423 }
424
425 #endif // 0
426
427 // ----------------------------------------------------------------------------
428 // wxExecute
429 // ----------------------------------------------------------------------------
430
431 // wxDoExecuteWithCapture() helper: reads an entire stream into one array
432 //
433 // returns TRUE if ok, FALSE if error
434 #if wxUSE_STREAMS
435 static bool ReadAll(wxInputStream *is, wxArrayString& output)
436 {
437 wxCHECK_MSG( is, FALSE, _T("NULL stream in wxExecute()?") );
438
439 // the stream could be already at EOF or in wxSTREAM_BROKEN_PIPE state
440 is->Reset();
441
442 wxTextInputStream tis(*is);
443
444 bool cont = TRUE;
445 while ( cont )
446 {
447 wxString line = tis.ReadLine();
448 if ( is->Eof() )
449 break;
450
451 if ( !*is )
452 {
453 cont = FALSE;
454 }
455 else
456 {
457 output.Add(line);
458 }
459 }
460
461 return cont;
462 }
463 #endif // wxUSE_STREAMS
464
465 // this is a private function because it hasn't a clean interface: the first
466 // array is passed by reference, the second by pointer - instead we have 2
467 // public versions of wxExecute() below
468 static long wxDoExecuteWithCapture(const wxString& command,
469 wxArrayString& output,
470 wxArrayString* error)
471 {
472 // create a wxProcess which will capture the output
473 wxProcess *process = new wxProcess;
474 process->Redirect();
475
476 long rc = wxExecute(command, wxEXEC_SYNC, process);
477
478 #if wxUSE_STREAMS
479 if ( rc != -1 )
480 {
481 if ( !ReadAll(process->GetInputStream(), output) )
482 rc = -1;
483
484 if ( error )
485 {
486 if ( !ReadAll(process->GetErrorStream(), *error) )
487 rc = -1;
488 }
489
490 }
491 #endif // wxUSE_STREAMS
492
493 delete process;
494
495 return rc;
496 }
497
498 long wxExecute(const wxString& command, wxArrayString& output)
499 {
500 return wxDoExecuteWithCapture(command, output, NULL);
501 }
502
503 long wxExecute(const wxString& command,
504 wxArrayString& output,
505 wxArrayString& error)
506 {
507 return wxDoExecuteWithCapture(command, output, &error);
508 }
509
510 // ----------------------------------------------------------------------------
511 // wxApp::Yield() wrappers for backwards compatibility
512 // ----------------------------------------------------------------------------
513
514 bool wxYield()
515 {
516 return wxTheApp && wxTheApp->Yield();
517 }
518
519 bool wxYieldIfNeeded()
520 {
521 return wxTheApp && wxTheApp->Yield(TRUE);
522 }
523
524 #endif // wxUSE_BASE
525
526 // ============================================================================
527 // GUI-only functions from now on
528 // ============================================================================
529
530 #if wxUSE_GUI
531
532 // Id generation
533 static long wxCurrentId = 100;
534
535 long
536 wxNewId (void)
537 {
538 return wxCurrentId++;
539 }
540
541 long
542 wxGetCurrentId(void) { return wxCurrentId; }
543
544 void
545 wxRegisterId (long id)
546 {
547 if (id >= wxCurrentId)
548 wxCurrentId = id + 1;
549 }
550
551 #if wxUSE_MENUS
552
553 // ----------------------------------------------------------------------------
554 // Menu accelerators related functions
555 // ----------------------------------------------------------------------------
556
557 wxChar *wxStripMenuCodes(const wxChar *in, wxChar *out)
558 {
559 wxString s = wxMenuItem::GetLabelFromText(in);
560 if ( out )
561 {
562 // go smash their buffer if it's not big enough - I love char * params
563 memcpy(out, s.c_str(), s.length() * sizeof(wxChar));
564 }
565 else
566 {
567 // MYcopystring - for easier search...
568 out = new wxChar[s.length() + 1];
569 wxStrcpy(out, s.c_str());
570 }
571
572 return out;
573 }
574
575 wxString wxStripMenuCodes(const wxString& in)
576 {
577 wxString out;
578
579 size_t len = in.length();
580 out.reserve(len);
581
582 for ( size_t n = 0; n < len; n++ )
583 {
584 wxChar ch = in[n];
585 if ( ch == _T('&') )
586 {
587 // skip it, it is used to introduce the accel char (or to quote
588 // itself in which case it should still be skipped): note that it
589 // can't be the last character of the string
590 if ( ++n == len )
591 {
592 wxLogDebug(_T("Invalid menu string '%s'"), in.c_str());
593 }
594 else
595 {
596 // use the next char instead
597 ch = in[n];
598 }
599 }
600 else if ( ch == _T('\t') )
601 {
602 // everything after TAB is accel string, exit the loop
603 break;
604 }
605
606 out += ch;
607 }
608
609 return out;
610 }
611
612 #endif // wxUSE_MENUS
613
614 // ----------------------------------------------------------------------------
615 // Window search functions
616 // ----------------------------------------------------------------------------
617
618 /*
619 * If parent is non-NULL, look through children for a label or title
620 * matching the specified string. If NULL, look through all top-level windows.
621 *
622 */
623
624 wxWindow *
625 wxFindWindowByLabel (const wxString& title, wxWindow * parent)
626 {
627 return wxWindow::FindWindowByLabel( title, parent );
628 }
629
630
631 /*
632 * If parent is non-NULL, look through children for a name
633 * matching the specified string. If NULL, look through all top-level windows.
634 *
635 */
636
637 wxWindow *
638 wxFindWindowByName (const wxString& name, wxWindow * parent)
639 {
640 return wxWindow::FindWindowByName( name, parent );
641 }
642
643 // Returns menu item id or -1 if none.
644 int
645 wxFindMenuItemId (wxFrame * frame, const wxString& menuString, const wxString& itemString)
646 {
647 #if wxUSE_MENUS
648 wxMenuBar *menuBar = frame->GetMenuBar ();
649 if ( menuBar )
650 return menuBar->FindMenuItem (menuString, itemString);
651 #endif // wxUSE_MENUS
652
653 return -1;
654 }
655
656 // Try to find the deepest child that contains 'pt'.
657 // We go backwards, to try to allow for controls that are spacially
658 // within other controls, but are still siblings (e.g. buttons within
659 // static boxes). Static boxes are likely to be created _before_ controls
660 // that sit inside them.
661 wxWindow* wxFindWindowAtPoint(wxWindow* win, const wxPoint& pt)
662 {
663 if (!win->IsShown())
664 return NULL;
665
666 // Hack for wxNotebook case: at least in wxGTK, all pages
667 // claim to be shown, so we must only deal with the selected one.
668 #if wxUSE_NOTEBOOK
669 if (win->IsKindOf(CLASSINFO(wxNotebook)))
670 {
671 wxNotebook* nb = (wxNotebook*) win;
672 int sel = nb->GetSelection();
673 if (sel >= 0)
674 {
675 wxWindow* child = nb->GetPage(sel);
676 wxWindow* foundWin = wxFindWindowAtPoint(child, pt);
677 if (foundWin)
678 return foundWin;
679 }
680 }
681 #endif
682
683 wxWindowList::compatibility_iterator node = win->GetChildren().GetLast();
684 while (node)
685 {
686 wxWindow* child = node->GetData();
687 wxWindow* foundWin = wxFindWindowAtPoint(child, pt);
688 if (foundWin)
689 return foundWin;
690 node = node->GetPrevious();
691 }
692
693 wxPoint pos = win->GetPosition();
694 wxSize sz = win->GetSize();
695 if (win->GetParent())
696 {
697 pos = win->GetParent()->ClientToScreen(pos);
698 }
699
700 wxRect rect(pos, sz);
701 if (rect.Inside(pt))
702 return win;
703 else
704 return NULL;
705 }
706
707 wxWindow* wxGenericFindWindowAtPoint(const wxPoint& pt)
708 {
709 // Go backwards through the list since windows
710 // on top are likely to have been appended most
711 // recently.
712 wxWindowList::compatibility_iterator node = wxTopLevelWindows.GetLast();
713 while (node)
714 {
715 wxWindow* win = node->GetData();
716 wxWindow* found = wxFindWindowAtPoint(win, pt);
717 if (found)
718 return found;
719 node = node->GetPrevious();
720 }
721 return NULL;
722 }
723
724 // ----------------------------------------------------------------------------
725 // GUI helpers
726 // ----------------------------------------------------------------------------
727
728 /*
729 * N.B. these convenience functions must be separate from msgdlgg.cpp, textdlgg.cpp
730 * since otherwise the generic code may be pulled in unnecessarily.
731 */
732
733 #if wxUSE_MSGDLG
734
735 int wxMessageBox(const wxString& message, const wxString& caption, long style,
736 wxWindow *parent, int WXUNUSED(x), int WXUNUSED(y) )
737 {
738 wxMessageDialog dialog(parent, message, caption, style);
739
740 int ans = dialog.ShowModal();
741 switch ( ans )
742 {
743 case wxID_OK:
744 return wxOK;
745 case wxID_YES:
746 return wxYES;
747 case wxID_NO:
748 return wxNO;
749 case wxID_CANCEL:
750 return wxCANCEL;
751 }
752
753 wxFAIL_MSG( _T("unexpected return code from wxMessageDialog") );
754
755 return wxCANCEL;
756 }
757
758 #endif // wxUSE_MSGDLG
759
760 #if wxUSE_TEXTDLG
761
762 wxString wxGetTextFromUser(const wxString& message, const wxString& caption,
763 const wxString& defaultValue, wxWindow *parent,
764 int x, int y, bool WXUNUSED(centre) )
765 {
766 wxString str;
767 wxTextEntryDialog dialog(parent, message, caption, defaultValue, wxOK|wxCANCEL, wxPoint(x, y));
768 if (dialog.ShowModal() == wxID_OK)
769 {
770 str = dialog.GetValue();
771 }
772
773 return str;
774 }
775
776 wxString wxGetPasswordFromUser(const wxString& message,
777 const wxString& caption,
778 const wxString& defaultValue,
779 wxWindow *parent)
780 {
781 wxString str;
782 wxTextEntryDialog dialog(parent, message, caption, defaultValue,
783 wxOK | wxCANCEL | wxTE_PASSWORD);
784 if ( dialog.ShowModal() == wxID_OK )
785 {
786 str = dialog.GetValue();
787 }
788
789 return str;
790 }
791
792 #endif // wxUSE_TEXTDLG
793
794 #if wxUSE_COLOURDLG
795
796 wxColour wxGetColourFromUser(wxWindow *parent, const wxColour& colInit)
797 {
798 wxColourData data;
799 data.SetChooseFull(TRUE);
800 if ( colInit.Ok() )
801 {
802 data.SetColour((wxColour &)colInit); // const_cast
803 }
804
805 wxColour colRet;
806 wxColourDialog dialog(parent, &data);
807 if ( dialog.ShowModal() == wxID_OK )
808 {
809 colRet = dialog.GetColourData().GetColour();
810 }
811 //else: leave it invalid
812
813 return colRet;
814 }
815
816 #endif // wxUSE_COLOURDLG
817
818 #if wxUSE_FONTDLG
819
820 wxFont wxGetFontFromUser(wxWindow *parent, const wxFont& fontInit)
821 {
822 wxFontData data;
823 if ( fontInit.Ok() )
824 {
825 data.SetInitialFont(fontInit);
826 }
827
828 wxFont fontRet;
829 wxFontDialog dialog(parent, data);
830 if ( dialog.ShowModal() == wxID_OK )
831 {
832 fontRet = dialog.GetFontData().GetChosenFont();
833 }
834 //else: leave it invalid
835
836 return fontRet;
837 }
838
839 #endif // wxUSE_FONTDLG
840
841 // ----------------------------------------------------------------------------
842 // wxSafeYield and supporting functions
843 // ----------------------------------------------------------------------------
844
845 void wxEnableTopLevelWindows(bool enable)
846 {
847 wxWindowList::compatibility_iterator node;
848 for ( node = wxTopLevelWindows.GetFirst(); node; node = node->GetNext() )
849 node->GetData()->Enable(enable);
850 }
851
852 wxWindowDisabler::wxWindowDisabler(wxWindow *winToSkip)
853 {
854 // remember the top level windows which were already disabled, so that we
855 // don't reenable them later
856 m_winDisabled = NULL;
857
858 wxWindowList::compatibility_iterator node;
859 for ( node = wxTopLevelWindows.GetFirst(); node; node = node->GetNext() )
860 {
861 wxWindow *winTop = node->GetData();
862 if ( winTop == winToSkip )
863 continue;
864
865 // we don't need to disable the hidden or already disabled windows
866 if ( winTop->IsEnabled() && winTop->IsShown() )
867 {
868 winTop->Disable();
869 }
870 else
871 {
872 if ( !m_winDisabled )
873 {
874 m_winDisabled = new wxWindowList;
875 }
876
877 m_winDisabled->Append(winTop);
878 }
879 }
880 }
881
882 wxWindowDisabler::~wxWindowDisabler()
883 {
884 wxWindowList::compatibility_iterator node;
885 for ( node = wxTopLevelWindows.GetFirst(); node; node = node->GetNext() )
886 {
887 wxWindow *winTop = node->GetData();
888 if ( !m_winDisabled || !m_winDisabled->Find(winTop) )
889 {
890 winTop->Enable();
891 }
892 //else: had been already disabled, don't reenable
893 }
894
895 delete m_winDisabled;
896 }
897
898 // Yield to other apps/messages and disable user input to all windows except
899 // the given one
900 bool wxSafeYield(wxWindow *win, bool onlyIfNeeded)
901 {
902 wxWindowDisabler wd(win);
903
904 bool rc;
905 if (onlyIfNeeded)
906 rc = wxYieldIfNeeded();
907 else
908 rc = wxYield();
909
910 return rc;
911 }
912
913 // Don't synthesize KeyUp events holding down a key and producing KeyDown
914 // events with autorepeat. On by default and always on in wxMSW. wxGTK version
915 // in utilsgtk.cpp.
916 #ifndef __WXGTK__
917 bool wxSetDetectableAutoRepeat( bool WXUNUSED(flag) )
918 {
919 return TRUE; // detectable auto-repeat is the only mode MSW supports
920 }
921 #endif // !wxGTK
922
923 #endif // wxUSE_GUI
924