X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/e90c1d2a19361551eb07778280f22be3e759cf64..236a9de39afa090fdee3cf91cb5364ceca69e3f8:/src/common/utilscmn.cpp diff --git a/src/common/utilscmn.cpp b/src/common/utilscmn.cpp index f41b535fca..b8841a57b0 100644 --- a/src/common/utilscmn.cpp +++ b/src/common/utilscmn.cpp @@ -32,6 +32,8 @@ #include "wx/defs.h" #include "wx/string.h" #include "wx/utils.h" + #include "wx/intl.h" + #include "wx/log.h" #if wxUSE_GUI #include "wx/window.h" @@ -39,9 +41,16 @@ #include "wx/frame.h" #include "wx/msgdlg.h" #include "wx/textdlg.h" + #if wxUSE_ACCEL + #include "wx/menuitem.h" + #include "wx/accel.h" + #endif // wxUSE_ACCEL #endif // wxUSE_GUI #endif // WX_PRECOMP +#include "wx/process.h" +#include "wx/txtstrm.h" + #include #include #include @@ -53,6 +62,10 @@ #endif #endif +#if wxUSE_GUI + #include "wx/colordlg.h" +#endif // wxUSE_GUI + #include #ifndef __MWERKS__ @@ -64,16 +77,8 @@ #include #endif -// Pattern matching code. (FIXME) -// Yes, this path is deliberate (for Borland compilation) -#ifdef wx_mac /* MATTHEW: [5] Mac doesn't like paths with "/" */ -#include "glob.inc" -#else -#include "../common/glob.inc" -#endif - #ifdef __WXMSW__ - #include "windows.h" + #include "wx/msw/private.h" #endif // ---------------------------------------------------------------------------- @@ -124,7 +129,7 @@ int strncasecmp(const char *str_1, const char *str_2, size_t maxchar) } #endif // wxMAC -#ifdef __VMS__ +#if defined( __VMS__ ) && ( __VMS_VER < 70000000 ) // we have no strI functions under VMS, therefore I have implemented // an inefficient but portable version: convert copies of strings to lowercase // and then use the normal comparison @@ -145,7 +150,7 @@ int strcasecmp(const char *str_1, const char *str_2) myLowerString(temp1); myLowerString(temp2); - int result = strcmp(temp1,temp2); + int result = wxStrcmp(temp1,temp2); delete[] temp1; delete[] temp2; @@ -207,7 +212,7 @@ extern "C" wxChar * copystring (const wxChar *s) { - if (s == NULL) s = T(""); + if (s == NULL) s = wxT(""); size_t len = wxStrlen (s) + 1; wxChar *news = new wxChar[len]; @@ -287,7 +292,7 @@ IntToString (int number) { static wxChar buf[20]; - wxSprintf (buf, T("%d"), number); + wxSprintf (buf, wxT("%d"), number); return buf; } @@ -296,27 +301,27 @@ LongToString (long number) { static wxChar buf[20]; - wxSprintf (buf, T("%ld"), number); + wxSprintf (buf, wxT("%ld"), number); return buf; } // Array used in DecToHex conversion routine. -static wxChar hexArray[] = T("0123456789ABCDEF"); +static wxChar hexArray[] = wxT("0123456789ABCDEF"); // Convert 2-digit hex number to decimal int wxHexToDec(const wxString& buf) { int firstDigit, secondDigit; - if (buf.GetChar(0) >= T('A')) - firstDigit = buf.GetChar(0) - T('A') + 10; + if (buf.GetChar(0) >= wxT('A')) + firstDigit = buf.GetChar(0) - wxT('A') + 10; else - firstDigit = buf.GetChar(0) - T('0'); + firstDigit = buf.GetChar(0) - wxT('0'); - if (buf.GetChar(1) >= T('A')) - secondDigit = buf.GetChar(1) - T('A') + 10; + if (buf.GetChar(1) >= wxT('A')) + secondDigit = buf.GetChar(1) - wxT('A') + 10; else - secondDigit = buf.GetChar(1) - T('0'); + secondDigit = buf.GetChar(1) - wxT('0'); return firstDigit * 16 + secondDigit; } @@ -392,7 +397,7 @@ wxString wxNow() #if wxUSE_GUI // ---------------------------------------------------------------------------- -// Strip out any menu codes +// Menu accelerators related functions // ---------------------------------------------------------------------------- wxChar *wxStripMenuCodes (wxChar *in, wxChar *out) @@ -407,13 +412,13 @@ wxChar *wxStripMenuCodes (wxChar *in, wxChar *out) while (*in) { - if (*in == T('&')) + if (*in == wxT('&')) { // Check && -> &, &x -> x - if (*++in == T('&')) + if (*++in == wxT('&')) *out++ = *in++; } - else if (*in == T('\t')) + else if (*in == wxT('\t')) { // Remove all stuff after \t in X mode, and let the stuff as is // in Windows mode. @@ -425,7 +430,7 @@ wxChar *wxStripMenuCodes (wxChar *in, wxChar *out) *out++ = *in++; } // while - *out = T('\0'); + *out = wxT('\0'); return tmpOut; } @@ -439,6 +444,91 @@ wxString wxStripMenuCodes(const wxString& str) return str1; } +#if wxUSE_ACCEL + +// return wxAcceleratorEntry for the given menu string or NULL if none +// specified +wxAcceleratorEntry *wxGetAccelFromString(const wxString& label) +{ + // check for accelerators: they are given after '\t' + int posTab = label.Find(wxT('\t')); + if ( posTab != wxNOT_FOUND ) { + // parse the accelerator string + int keyCode = 0; + int accelFlags = wxACCEL_NORMAL; + wxString current; + for ( size_t n = (size_t)posTab + 1; n < label.Len(); n++ ) { + if ( (label[n] == '+') || (label[n] == '-') ) { + if ( current == _("ctrl") ) + accelFlags |= wxACCEL_CTRL; + else if ( current == _("alt") ) + accelFlags |= wxACCEL_ALT; + else if ( current == _("shift") ) + accelFlags |= wxACCEL_SHIFT; + else { + wxLogDebug(wxT("Unknown accel modifier: '%s'"), + current.c_str()); + } + + current.Empty(); + } + else { + current += wxTolower(label[n]); + } + } + + if ( current.IsEmpty() ) { + wxLogDebug(wxT("No accel key found, accel string ignored.")); + } + else { + if ( current.Len() == 1 ) { + // it's a letter + keyCode = wxToupper(current[0U]); + } + else { + // is it a function key? + if ( current[0U] == 'f' && isdigit(current[1U]) && + (current.Len() == 2 || + (current.Len() == 3 && isdigit(current[2U]))) ) { + int n; + wxSscanf(current.c_str() + 1, wxT("%d"), &n); + + 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; + } + else if ( current == wxT("PGUP") ) { + keyCode = VK_PRIOR; + } + else if ( current == wxT("PGDN") ) { + keyCode = VK_NEXT; + } + else +#endif // 0 + { + wxLogDebug(wxT("Unrecognized accel key '%s', accel " + "string ignored."), current.c_str()); + } + } + } + } + + if ( keyCode ) { + // we do have something + return new wxAcceleratorEntry(accelFlags, keyCode); + } + } + + return (wxAcceleratorEntry *)NULL; +} + +#endif // wxUSE_ACCEL + // ---------------------------------------------------------------------------- // Window search functions // ---------------------------------------------------------------------------- @@ -782,19 +872,14 @@ int wxMessageBox(const wxString& message, const wxString& caption, long style, { case wxID_OK: return wxOK; - break; case wxID_YES: return wxYES; - break; case wxID_NO: return wxNO; - break; default: case wxID_CANCEL: return wxCANCEL; - break; } - return ans; } #if wxUSE_TEXTDLG @@ -802,14 +887,58 @@ wxString wxGetTextFromUser(const wxString& message, const wxString& caption, const wxString& defaultValue, wxWindow *parent, int x, int y, bool WXUNUSED(centre) ) { + wxString str; wxTextEntryDialog dialog(parent, message, caption, defaultValue, wxOK|wxCANCEL, wxPoint(x, y)); if (dialog.ShowModal() == wxID_OK) - return dialog.GetValue(); - else - return wxString(""); + { + str = dialog.GetValue(); + } + + return str; +} + +wxString wxGetPasswordFromUser(const wxString& message, + const wxString& caption, + const wxString& defaultValue, + wxWindow *parent) +{ + wxString str; + wxTextEntryDialog dialog(parent, message, caption, defaultValue, + wxOK | wxCANCEL | wxTE_PASSWORD); + if ( dialog.ShowModal() == wxID_OK ) + { + str = dialog.GetValue(); + } + + return str; } + #endif // wxUSE_TEXTDLG +wxColour wxGetColourFromUser(wxWindow *parent, const wxColour& colInit) +{ + wxColourData data; + data.SetChooseFull(TRUE); + if ( colInit.Ok() ) + { + data.SetColour((wxColour &)colInit); // const_cast + } + + wxColour colRet; + wxColourDialog dialog(parent, &data); + if ( dialog.ShowModal() == wxID_OK ) + { + colRet = dialog.GetColourData().GetColour(); + } + //else: leave it invalid + + return colRet; +} + +// ---------------------------------------------------------------------------- +// missing C RTL functions (FIXME shouldn't be here at all) +// ---------------------------------------------------------------------------- + #ifdef __MWERKS__ char *strdup(const char *s) { @@ -823,35 +952,117 @@ int isascii( int c ) #endif // __MWERKS__ // ---------------------------------------------------------------------------- -// misc functions +// wxSafeYield and supporting functions // ---------------------------------------------------------------------------- void wxEnableTopLevelWindows(bool enable) { - wxWindowList::Node *node; - for ( node = wxTopLevelWindows.GetFirst(); node; node = node->GetNext() ) - node->GetData()->Enable(enable); + wxWindowList::Node *node; + for ( node = wxTopLevelWindows.GetFirst(); node; node = node->GetNext() ) + node->GetData()->Enable(enable); } -// Yield to other apps/messages and disable user input +wxWindowDisabler::wxWindowDisabler(wxWindow *winToSkip) +{ +#ifdef __WXMSW__ +#ifdef __WIN32__ + // and the top level window too + HWND hwndFG = ::GetForegroundWindow(); + m_winTop = hwndFG ? wxFindWinFromHandle((WXHWND)hwndFG) : (wxWindow *)NULL; +#else + HWND hwndFG = ::GetTopWindow(); + m_winTop = hwndFG ? wxFindWinFromHandle((WXHWND)hwndFG) : (wxWindow *)NULL; +#endif +#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() ) + { + winTop->Disable(); + } + else + { + if ( !m_winDisabled ) + { + m_winDisabled = new wxWindowList; + } + + m_winDisabled->Append(winTop); + } + } +} + +wxWindowDisabler::~wxWindowDisabler() +{ + wxWindowList::Node *node; + for ( node = wxTopLevelWindows.GetFirst(); node; node = node->GetNext() ) + { + wxWindow *winTop = node->GetData(); + if ( !m_winDisabled || !m_winDisabled->Find(winTop) ) + { + winTop->Enable(); + } + //else: had been already disabled, don't reenable + } + + delete m_winDisabled; + +#ifdef __WXMSW__ +#ifdef __WIN32__ + if ( m_winTop ) + { + if ( !::SetForegroundWindow(GetHwndOf(m_winTop)) ) + { + wxLogLastError("SetForegroundWindow"); + } + } +#else + if ( m_winTop ) + { + // 16-bit SetForegroundWindow() replacement + RECT reWin; + GetWindowRect(m_winTop, &reWin); + SetWindowPos (m_winTop, HWND_TOP, + reWin.left, reWin.top, + reWin.right - reWin.left, reWin.bottom, + SWP_SHOWWINDOW); + } +#endif +#endif // MSW +} + +// Yield to other apps/messages and disable user input to all windows except +// the given one bool wxSafeYield(wxWindow *win) { - wxEnableTopLevelWindows(FALSE); - // always enable ourselves - if ( win ) - win->Enable(TRUE); - bool rc = wxYield(); - wxEnableTopLevelWindows(TRUE); - return rc; + wxWindowDisabler wd; + + 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. #ifndef __WXGTK__ bool wxSetDetectableAutoRepeat( bool WXUNUSED(flag) ) { - return TRUE; // detectable auto-repeat is the only mode MSW supports + return TRUE; // detectable auto-repeat is the only mode MSW supports } #endif // !wxGTK @@ -869,7 +1080,7 @@ bool wxGetEmailAddress(wxChar *address, int maxSize) return FALSE; wxStrncpy(address, email, maxSize - 1); - address[maxSize - 1] = T('\0'); + address[maxSize - 1] = wxT('\0'); return TRUE; } @@ -885,7 +1096,7 @@ wxString wxGetEmailAddress() if ( !!user ) { wxString email(user); - email << T('@') << host; + email << wxT('@') << host; } } @@ -950,3 +1161,72 @@ wxString wxGetFullHostName() return buf; } +wxString wxGetHomeDir() +{ + wxString home; + wxGetHomeDir(&home); + + return home; +} + +#if 0 + +wxString wxGetCurrentDir() +{ + wxString dir; + size_t len = 1024; + bool ok; + do + { + ok = getcwd(dir.GetWriteBuf(len + 1), len) != NULL; + dir.UngetWriteBuf(); + + if ( !ok ) + { + if ( errno != ERANGE ) + { + wxLogSysError(_T("Failed to get current directory")); + + return wxEmptyString; + } + else + { + // buffer was too small, retry with a larger one + len *= 2; + } + } + //else: ok + } while ( !ok ); + + return dir; +} + +#endif // 0 + +// ---------------------------------------------------------------------------- +// wxExecute +// ---------------------------------------------------------------------------- + +long wxExecute(const wxString& command, wxArrayString& output) +{ + // create a wxProcess which will capture the output + wxProcess *process = new wxProcess; + process->Redirect(); + + long rc = wxExecute(command, TRUE /* sync */, process); + if ( rc != -1 ) + { + wxInputStream& is = *process->GetInputStream(); + wxTextInputStream tis(is); + while ( !is.Eof() && is.IsOk() ) + { + wxString line = tis.ReadLine(); + if ( is.LastError() ) + break; + + output.Add(line); + } + } + + return rc; +}