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