X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/5e1febfacedfb966daaf4050c293e0833593df82..42b1f941b010bee7e5e82b12c1096dce094553d4:/src/common/utilscmn.cpp diff --git a/src/common/utilscmn.cpp b/src/common/utilscmn.cpp index c9e9207ebb..77de515356 100644 --- a/src/common/utilscmn.cpp +++ b/src/common/utilscmn.cpp @@ -48,8 +48,10 @@ #endif // wxUSE_GUI #endif // WX_PRECOMP +#ifndef __WIN16__ #include "wx/process.h" #include "wx/txtstrm.h" +#endif #include #include @@ -64,6 +66,10 @@ #if wxUSE_GUI #include "wx/colordlg.h" + #include "wx/notebook.h" + #include "wx/frame.h" + #include "wx/statusbr.h" + #include "wx/toolbar.h" #endif // wxUSE_GUI #include @@ -496,23 +502,32 @@ wxAcceleratorEntry *wxGetAccelFromString(const wxString& label) keyCode = WXK_F1 + n - 1; } else { -#if 0 // this is not supported by GTK+, apparently // several special cases current.MakeUpper(); if ( current == wxT("DEL") ) { - keyCode = VK_DELETE; + keyCode = WXK_DELETE; + } + else if ( current == wxT("DELETE") ) { + keyCode = WXK_DELETE; + } + else if ( current == wxT("INS") ) { + keyCode = WXK_INSERT; + } + else if ( current == wxT("INSERT") ) { + keyCode = WXK_INSERT; } +#if 0 else if ( current == wxT("PGUP") ) { keyCode = VK_PRIOR; } else if ( current == wxT("PGDN") ) { keyCode = VK_NEXT; } +#endif else -#endif // 0 { - wxLogDebug(wxT("Unrecognized accel key '%s', accel " - "string ignored."), current.c_str()); + wxLogDebug(wxT("Unrecognized accel key '%s', accel string ignored."), + current.c_str()); } } } @@ -656,6 +671,95 @@ wxFindMenuItemId (wxFrame * frame, const wxString& menuString, const wxString& i return menuBar->FindMenuItem (menuString, itemString); } +// Try to find the deepest child that contains 'pt'. +// We go backwards, to try to allow for controls that are spacially +// within other controls, but are still siblings (e.g. buttons within +// static boxes). Static boxes are likely to be created _before_ controls +// that sit inside them. +wxWindow* wxFindWindowAtPoint(wxWindow* win, const wxPoint& pt) +{ + if (!win->IsShown()) + return NULL; + + // Hack for wxNotebook case: at least in wxGTK, all pages + // claim to be shown, so we must only deal with the selected one. + if (win->IsKindOf(CLASSINFO(wxNotebook))) + { + wxNotebook* nb = (wxNotebook*) win; + int sel = nb->GetSelection(); + if (sel >= 0) + { + wxWindow* child = nb->GetPage(sel); + wxWindow* foundWin = wxFindWindowAtPoint(child, pt); + if (foundWin) + return foundWin; + } + } + /* Doesn't work + // Frame case + else if (win->IsKindOf(CLASSINFO(wxFrame))) + { + // Pseudo-children that may not be mentioned in the child list + wxWindowList extraChildren; + wxFrame* frame = (wxFrame*) win; + if (frame->GetStatusBar()) + extraChildren.Append(frame->GetStatusBar()); + if (frame->GetToolBar()) + extraChildren.Append(frame->GetToolBar()); + + wxNode* node = extraChildren.First(); + while (node) + { + wxWindow* child = (wxWindow*) node->Data(); + wxWindow* foundWin = wxFindWindowAtPoint(child, pt); + if (foundWin) + return foundWin; + node = node->Next(); + } + } + */ + + wxNode* node = win->GetChildren().Last(); + while (node) + { + wxWindow* child = (wxWindow*) node->Data(); + wxWindow* foundWin = wxFindWindowAtPoint(child, pt); + if (foundWin) + return foundWin; + node = node->Previous(); + } + + wxPoint pos = win->GetPosition(); + wxSize sz = win->GetSize(); + if (win->GetParent()) + { + pos = win->GetParent()->ClientToScreen(pos); + } + + wxRect rect(pos, sz); + if (rect.Inside(pt)) + return win; + else + return NULL; +} + +wxWindow* wxGenericFindWindowAtPoint(const wxPoint& pt) +{ + // Go backwards through the list since windows + // on top are likely to have been appended most + // recently. + wxNode* node = wxTopLevelWindows.Last(); + while (node) + { + wxWindow* win = (wxWindow*) node->Data(); + wxWindow* found = wxFindWindowAtPoint(win, pt); + if (found) + return found; + node = node->Previous(); + } + return NULL; +} + #endif // wxUSE_GUI /* @@ -876,10 +980,13 @@ int wxMessageBox(const wxString& message, const wxString& caption, long style, return wxYES; case wxID_NO: return wxNO; - default: case wxID_CANCEL: return wxCANCEL; } + + wxFAIL_MSG( _T("unexpected return code from wxMessageDialog") ); + + return wxCANCEL; } #if wxUSE_TEXTDLG @@ -952,7 +1059,7 @@ int isascii( int c ) #endif // __MWERKS__ // ---------------------------------------------------------------------------- -// misc functions +// wxSafeYield and supporting functions // ---------------------------------------------------------------------------- void wxEnableTopLevelWindows(bool enable) @@ -962,86 +1069,66 @@ void wxEnableTopLevelWindows(bool enable) node->GetData()->Enable(enable); } -static void wxFindDisabledWindows(wxWindowList& winDisabled, wxWindow *win) -{ - wxWindowList::Node *node; - for ( node = win->GetChildren().GetFirst(); node; node = node->GetNext() ) - { - wxWindow *child = node->GetData(); - wxFindDisabledWindows(winDisabled, child); - - if ( child->IsEnabled() ) - { - winDisabled.Append(child); - child->Disable(); - } - } -} - wxWindowDisabler::wxWindowDisabler(wxWindow *winToSkip) { - // remember all windows we're going to (temporarily) disable - m_winDisabled = new wxWindowList; - -#ifdef __WXMSW__ - // and the top level window too - HWND hwndFG = ::GetForegroundWindow(); - m_winTop = hwndFG ? wxFindWinFromHandle((WXHWND)hwndFG) : (wxWindow *)NULL; -#endif // MSW + // remember the top level windows which were already disabled, so that we + // don't reenable them later + m_winDisabled = NULL; wxWindowList::Node *node; for ( node = wxTopLevelWindows.GetFirst(); node; node = node->GetNext() ) { wxWindow *winTop = node->GetData(); + if ( winTop == winToSkip ) + continue; + if ( winTop->IsEnabled() ) { - wxFindDisabledWindows(*m_winDisabled, winTop); - - m_winDisabled->Append(winTop); winTop->Disable(); } - } + else + { + if ( !m_winDisabled ) + { + m_winDisabled = new wxWindowList; + } - if ( winToSkip && m_winDisabled->Find(winToSkip) ) - { - // always enable ourselves - m_winDisabled->DeleteObject(winToSkip); - winToSkip->Enable(); + m_winDisabled->Append(winTop); + } } } wxWindowDisabler::~wxWindowDisabler() { wxWindowList::Node *node; - for ( node = m_winDisabled->GetFirst(); node; node = node->GetNext() ) - { - node->GetData()->Enable(); - } - - delete m_winDisabled; - -#ifdef __WXMSW__ - if ( m_winTop ) + for ( node = wxTopLevelWindows.GetFirst(); node; node = node->GetNext() ) { - if ( !::SetForegroundWindow(GetHwndOf(m_winTop)) ) + wxWindow *winTop = node->GetData(); + if ( !m_winDisabled || !m_winDisabled->Find(winTop) ) { - wxLogLastError("SetForegroundWindow"); + winTop->Enable(); } + //else: had been already disabled, don't reenable } -#endif // MSW + + delete m_winDisabled; } // Yield to other apps/messages and disable user input to all windows except // the given one bool wxSafeYield(wxWindow *win) { - wxWindowDisabler wd; + wxWindowDisabler wd(win); bool rc = wxYield(); return rc; } +// ---------------------------------------------------------------------------- +// misc functions +// ---------------------------------------------------------------------------- + // Don't synthesize KeyUp events holding down a key and producing KeyDown // events with autorepeat. On by default and always on in wxMSW. wxGTK version // in utilsgtk.cpp. @@ -1075,14 +1162,13 @@ wxString wxGetEmailAddress() { wxString email; - wxString host = wxGetHostName(); + wxString host = wxGetFullHostName(); if ( !!host ) { wxString user = wxGetUserId(); if ( !!user ) { - wxString email(user); - email << wxT('@') << host; + email << user << wxT('@') << host; } } @@ -1193,26 +1279,89 @@ wxString wxGetCurrentDir() // wxExecute // ---------------------------------------------------------------------------- -long wxExecute(const wxString& command, wxArrayString& output) +// this is a private function because it hasn't a clean interface: the first +// array is passed by reference, the second by pointer - instead we have 2 +// public versions of wxExecute() below +static long wxDoExecuteWithCapture(const wxString& command, + wxArrayString& output, + wxArrayString* error) { +#ifdef __WIN16__ + wxFAIL_MSG("Sorry, this version of wxExecute not implemented on WIN16."); + + return 0; +#else // !Win16 // create a wxProcess which will capture the output wxProcess *process = new wxProcess; process->Redirect(); long rc = wxExecute(command, TRUE /* sync */, process); + +#if wxUSE_STREAMS if ( rc != -1 ) { - wxInputStream& is = *process->GetInputStream(); - wxTextInputStream tis(is); - while ( !is.Eof() && is.IsOk() ) + wxInputStream* is = process->GetInputStream(); + wxCHECK_MSG( is, -1, _T("if wxExecute() succeded, stream can't be NULL") ); + wxTextInputStream tis(*is); + + wxTextInputStream *tes = NULL; + wxInputStream *es = NULL; + if ( error ) { - wxString line = tis.ReadLine(); - if ( is.LastError() ) - break; + es = process->GetErrorStream(); + + wxCHECK_MSG( es, -1, _T("stderr can't be NULL") ); + + tes = new wxTextInputStream(*es); + } + + bool cont; + do + { + cont = FALSE; + + if ( !is->Eof() && is->IsOk() ) + { + wxString line = tis.ReadLine(); + if ( is->LastError() ) + break; + + cont = TRUE; + + output.Add(line); + } + + if ( error && !es->Eof() && es->IsOk() ) + { + wxString line = tes->ReadLine(); + if ( es->LastError() ) + break; + + cont = TRUE; - output.Add(line); + error->Add(line); + } } + while ( cont ); + + delete tes; } +#endif // wxUSE_STREAMS + + delete process; return rc; +#endif // IO redirection supoprted +} + +long wxExecute(const wxString& command, wxArrayString& output) +{ + return wxDoExecuteWithCapture(command, output, NULL); +} + +long wxExecute(const wxString& command, + wxArrayString& output, + wxArrayString& error) +{ + return wxDoExecuteWithCapture(command, output, &error); }