X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/3ffbc733a20ffbda22abece30b4a1afb5c8bc75d..1fd1922a49351a377bc6ef8f7e00f150112ee096:/src/msw/utils.cpp?ds=sidebyside diff --git a/src/msw/utils.cpp b/src/msw/utils.cpp index 6d23a03728..d9fcbb0033 100644 --- a/src/msw/utils.cpp +++ b/src/msw/utils.cpp @@ -38,19 +38,14 @@ #endif #endif //WX_PRECOMP -// In some mingws there is a missing extern "C" int the winsock header, -// so we put it here just to be safe. Note that this must appear _before_ -// #include "wx/msw/private.h" which itself includes , as this -// one in turn includes unless we define WIN32_LEAN_AND_MEAN. -// -#if defined(__WIN32__) && !defined(__TWIN32__) && !defined(__WXMICROWIN__) && ! (defined(__GNUWIN32__) && !defined(__MINGW32__)) -extern "C" { - #include // we use socket functions in wxGetFullHostName() -} -#endif - #include "wx/msw/private.h" // includes +#ifdef __GNUWIN32_OLD__ + // apparently we need to include winsock.h to get WSADATA and other stuff + // used in wxGetFullHostName() with the old mingw32 versions + #include +#endif + #include "wx/timer.h" #if !defined(__GNUWIN32__) && !defined(__WXWINE__) && !defined(__SALFORDC__) && !defined(__WXMICROWIN__) @@ -61,7 +56,7 @@ extern "C" { #endif #endif //GNUWIN32 -#if defined(__GNUWIN32__) && !defined(__TWIN32__) +#if defined(__CYGWIN__) && !defined(__TWIN32__) #include #include #include // for cygwin_conv_to_full_win32_path() @@ -178,6 +173,11 @@ bool wxGetFullHostName(wxChar *buf, int maxSize) { #if defined(__WIN32__) && !defined(__TWIN32__) && !defined(__WXMICROWIN__) && ! (defined(__GNUWIN32__) && !defined(__MINGW32__)) // TODO should use GetComputerNameEx() when available + + // the idea is that if someone had set wxUSE_SOCKETS to 0 the code + // shouldn't use winsock.dll (a.k.a. ws2_32.dll) at all so only use this + // code if we link with it anyhow +#if wxUSE_SOCKETS WSADATA wsa; if ( WSAStartup(MAKEWORD(1, 1), &wsa) == 0 ) { @@ -194,7 +194,7 @@ bool wxGetFullHostName(wxChar *buf, int maxSize) if ( pHostEnt ) { // Windows will use DNS internally now - pHostEnt = gethostbyaddr(pHostEnt->h_addr, 4, PF_INET); + pHostEnt = gethostbyaddr(pHostEnt->h_addr, 4, AF_INET); } if ( pHostEnt ) @@ -206,13 +206,15 @@ bool wxGetFullHostName(wxChar *buf, int maxSize) WSACleanup(); - if ( !!host ) + if ( !host.empty() ) { wxStrncpy(buf, host, maxSize); return TRUE; } } +#endif // wxUSE_SOCKETS + #endif // Win32 return wxGetHostName(buf, maxSize); @@ -374,7 +376,7 @@ const wxChar* wxGetHomeDir(wxString *pstr) if ( strDir.Last() != wxT('/') ) strDir << wxT('/'); - #ifdef __GNUWIN32__ + #ifdef __CYGWIN__ // Cygwin returns unix type path but that does not work well static wxChar windowsPath[MAX_PATH]; cygwin_conv_to_full_win32_path(strDir, windowsPath); @@ -382,25 +384,55 @@ const wxChar* wxGetHomeDir(wxString *pstr) #endif #else // Windows #ifdef __WIN32__ - const wxChar *szHome = wxGetenv(wxT("HOMEDRIVE")); + strDir.clear(); + + // If we have a valid HOME directory, as is used on many machines that + // have unix utilities on them, we should use that. + const wxChar *szHome = wxGetenv(wxT("HOME")); + if ( szHome != NULL ) - strDir << szHome; - szHome = wxGetenv(wxT("HOMEPATH")); - if ( szHome != NULL ) { - strDir << szHome; - - // the idea is that under NT these variables have default values - // of "%systemdrive%:" and "\\". As we don't want to create our - // config files in the root directory of the system drive, we will - // create it in our program's dir. However, if the user took care - // to set HOMEPATH to something other than "\\", we suppose that he - // knows what he is doing and use the supplied value. - if ( wxStrcmp(szHome, wxT("\\")) != 0 ) - return strDir.c_str(); + { + strDir = szHome; + } + else // no HOME, try HOMEDRIVE/PATH + { + szHome = wxGetenv(wxT("HOMEDRIVE")); + if ( szHome != NULL ) + strDir << szHome; + szHome = wxGetenv(wxT("HOMEPATH")); + + if ( szHome != NULL ) + { + strDir << szHome; + + // the idea is that under NT these variables have default values + // of "%systemdrive%:" and "\\". As we don't want to create our + // config files in the root directory of the system drive, we will + // create it in our program's dir. However, if the user took care + // to set HOMEPATH to something other than "\\", we suppose that he + // knows what he is doing and use the supplied value. + if ( wxStrcmp(szHome, wxT("\\")) == 0 ) + strDir.clear(); + } + } + + if ( strDir.empty() ) + { + // If we have a valid USERPROFILE directory, as is the case in + // Windows NT, 2000 and XP, we should use that as our home directory. + szHome = wxGetenv(wxT("USERPROFILE")); + + if ( szHome != NULL ) + strDir = szHome; } + if ( !strDir.empty() ) + { + return strDir.c_str(); + } + //else: fall back to the prograrm directory #else // Win16 - // Win16 has no idea about home, so use the working directory instead + // Win16 has no idea about home, so use the executable directory instead #endif // WIN16/32 // 260 was taken from windef.h @@ -498,14 +530,22 @@ bool wxGetDiskSpace(const wxString& path, wxLongLong *pTotal, wxLongLong *pFree) return FALSE; } + // ULARGE_INTEGER is a union of a 64 bit value and a struct containing + // two 32 bit fields which may be or may be not named - try to make it + // compile in all cases +#if defined(__BORLANDC__) && !defined(_ANONYMOUS_STRUCT) + #define UL(ul) ul.u +#else // anon union + #define UL(ul) ul +#endif if ( pTotal ) { - *pTotal = wxLongLong(bytesTotal.u.HighPart, bytesTotal.u.LowPart); + *pTotal = wxLongLong(UL(bytesTotal).HighPart, UL(bytesTotal).LowPart); } if ( pFree ) { - *pFree = wxLongLong(bytesFree.u.HighPart, bytesFree.u.LowPart); + *pFree = wxLongLong(UL(bytesFree).HighPart, UL(bytesFree).LowPart); } } else @@ -800,7 +840,7 @@ int wxKill(long pid, wxSignal sig, wxKillError *krc) return 0; } } -#else // Win15 +#else // Win16 wxFAIL_MSG( _T("not implemented") ); #endif // Win32/Win16 @@ -813,7 +853,7 @@ bool wxShell(const wxString& command) { wxChar *shell = wxGetenv(wxT("COMSPEC")); if ( !shell ) - shell = wxT("\\COMMAND.COM"); + shell = (wxChar*) wxT("\\COMMAND.COM"); wxString cmd; if ( !command ) @@ -830,6 +870,66 @@ bool wxShell(const wxString& command) return wxExecute(cmd, TRUE /* sync */) != 0; } +// Shutdown or reboot the PC +bool wxShutdown(wxShutdownFlags wFlags) +{ +#ifdef __WIN32__ + bool bOK = TRUE; + + if ( wxGetOsVersion(NULL, NULL) == wxWINDOWS_NT ) // if is NT or 2K + { + // Get a token for this process. + HANDLE hToken; + bOK = ::OpenProcessToken(GetCurrentProcess(), + TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, + &hToken) != 0; + if ( bOK ) + { + TOKEN_PRIVILEGES tkp; + + // Get the LUID for the shutdown privilege. + ::LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, + &tkp.Privileges[0].Luid); + + tkp.PrivilegeCount = 1; // one privilege to set + tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + + // Get the shutdown privilege for this process. + ::AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, + (PTOKEN_PRIVILEGES)NULL, 0); + + // Cannot test the return value of AdjustTokenPrivileges. + bOK = ::GetLastError() == ERROR_SUCCESS; + } + } + + if ( bOK ) + { + UINT flags = EWX_SHUTDOWN | EWX_FORCE; + switch ( wFlags ) + { + case wxSHUTDOWN_POWEROFF: + flags |= EWX_POWEROFF; + break; + + case wxSHUTDOWN_REBOOT: + flags |= EWX_REBOOT; + break; + + default: + wxFAIL_MSG( _T("unknown wxShutdown() flag") ); + return FALSE; + } + + bOK = ::ExitWindowsEx(EWX_SHUTDOWN | EWX_FORCE | EWX_REBOOT, 0) != 0; + } + + return bOK; +#else // Win16 + return FALSE; +#endif // Win32/16 +} + // ---------------------------------------------------------------------------- // misc // ---------------------------------------------------------------------------- @@ -847,6 +947,15 @@ long wxGetFreeMemory() #endif } +unsigned long wxGetProcessId() +{ +#ifdef __WIN32__ + return ::GetCurrentProcessId(); +#else + return 0; +#endif +} + // Emit a beeeeeep void wxBell() { @@ -906,31 +1015,43 @@ wxString wxGetOsDescription() int wxGetOsVersion(int *majorVsn, int *minorVsn) { #if defined(__WIN32__) && !defined(__SC__) - OSVERSIONINFO info; - wxZeroMemory(info); + static int ver = -1, major = -1, minor = -1; - info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - if ( ::GetVersionEx(&info) ) + if ( ver == -1 ) { - if (majorVsn) - *majorVsn = info.dwMajorVersion; - if (minorVsn) - *minorVsn = info.dwMinorVersion; + OSVERSIONINFO info; + wxZeroMemory(info); - switch ( info.dwPlatformId ) + ver = wxWINDOWS; + info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + if ( ::GetVersionEx(&info) ) { - case VER_PLATFORM_WIN32s: - return wxWIN32S; + major = info.dwMajorVersion; + minor = info.dwMinorVersion; - case VER_PLATFORM_WIN32_WINDOWS: - return wxWIN95; + switch ( info.dwPlatformId ) + { + case VER_PLATFORM_WIN32s: + ver = wxWIN32S; + break; - case VER_PLATFORM_WIN32_NT: - return wxWINDOWS_NT; + case VER_PLATFORM_WIN32_WINDOWS: + ver = wxWIN95; + break; + + case VER_PLATFORM_WIN32_NT: + ver = wxWINDOWS_NT; + break; + } } } - return wxWINDOWS; // error if we get here, return generic value + if (majorVsn && major != -1) + *majorVsn = major; + if (minorVsn && minor != -1) + *minorVsn = minor; + + return ver; #else // Win16 int retValue = wxWINDOWS; #ifdef __WINDOWS_386__ @@ -1033,14 +1154,13 @@ void wxSleep(int nSecs) } #endif // wxUSE_GUI/!wxUSE_GUI -#endif - // __WXMICROWIN__ +#endif // __WXMICROWIN__ // ---------------------------------------------------------------------------- // deprecated (in favour of wxLog) log functions // ---------------------------------------------------------------------------- -#if wxUSE_GUI +#if WXWIN_COMPATIBILITY_2_2 // Output a debug mess., in a system dependent fashion. #ifndef __WXMICROWIN__ @@ -1050,12 +1170,12 @@ void wxDebugMsg(const wxChar *fmt ...) static wxChar buffer[512]; if (!wxTheApp->GetWantDebugOutput()) - return ; + return; va_start(ap, fmt); - wvsprintf(buffer,fmt,ap) ; - OutputDebugString((LPCTSTR)buffer) ; + wvsprintf(buffer,fmt,ap); + OutputDebugString((LPCTSTR)buffer); va_end(ap); } @@ -1077,6 +1197,10 @@ void wxFatalError(const wxString& msg, const wxString& title) } #endif // __WXMICROWIN__ +#endif // WXWIN_COMPATIBILITY_2_2 + +#if wxUSE_GUI + // ---------------------------------------------------------------------------- // functions to work with .INI files // ---------------------------------------------------------------------------- @@ -1227,7 +1351,7 @@ void wxEndBusyCursor() // TRUE if we're between the above two calls bool wxIsBusy() { - return (gs_wxBusyCursorCount > 0); + return gs_wxBusyCursorCount > 0; } // Check whether this window wants to process messages, e.g. Stop button @@ -1283,7 +1407,7 @@ wxChar *wxLoadUserResource(const wxString& resourceName, const wxString& resourc return s; } -#endif +#endif // __WXMICROWIN__ // ---------------------------------------------------------------------------- // get display info @@ -1340,26 +1464,35 @@ void wxDisplaySize(int *width, int *height) HWND hWnd = GetDesktopWindow(); ::GetWindowRect(hWnd, & rect); - *width = rect.right - rect.left; - *height = rect.bottom - rect.top; -#else + if ( width ) + *width = rect.right - rect.left; + if ( height ) + *height = rect.bottom - rect.top; +#else // !__WXMICROWIN__ ScreenHDC dc; - if ( width ) *width = GetDeviceCaps(dc, HORZRES); - if ( height ) *height = GetDeviceCaps(dc, VERTRES); -#endif + if ( width ) + *width = ::GetDeviceCaps(dc, HORZRES); + if ( height ) + *height = ::GetDeviceCaps(dc, VERTRES); +#endif // __WXMICROWIN__/!__WXMICROWIN__ } void wxDisplaySizeMM(int *width, int *height) { #ifdef __WXMICROWIN__ // MICROWIN_TODO - *width = 0; * height = 0; + if ( width ) + *width = 0; + if ( height ) + *height = 0; #else ScreenHDC dc; - if ( width ) *width = GetDeviceCaps(dc, HORZSIZE); - if ( height ) *height = GetDeviceCaps(dc, VERTSIZE); + if ( width ) + *width = ::GetDeviceCaps(dc, HORZSIZE); + if ( height ) + *height = ::GetDeviceCaps(dc, VERTSIZE); #endif } @@ -1381,7 +1514,6 @@ void wxClientDisplayRect(int *x, int *y, int *width, int *height) #endif } - // --------------------------------------------------------------------------- // window information functions // --------------------------------------------------------------------------- @@ -1441,10 +1573,6 @@ WXWORD WXDLLEXPORT wxGetWindowId(WXHWND hWnd) #endif // Win16/32 } -#endif // wxUSE_GUI - -#if wxUSE_GUI - // ---------------------------------------------------------------------------- // Metafile helpers // ---------------------------------------------------------------------------- @@ -1481,236 +1609,110 @@ extern void HIMETRICToPixel(LONG *x, LONG *y) #endif // wxUSE_GUI -#if 0 -//------------------------------------------------------------------------ -// wild character routines -//------------------------------------------------------------------------ - -bool wxIsWild( const wxString& pattern ) +#ifdef __WXMICROWIN__ +int wxGetOsVersion(int *majorVsn, int *minorVsn) { - wxString tmp = pattern; - char *pat = WXSTRINGCAST(tmp); - while (*pat) { - switch (*pat++) { - case '?': case '*': case '[': case '{': - return TRUE; - case '\\': - if (!*pat++) - return FALSE; - } - } - return FALSE; -}; - + // MICROWIN_TODO + if (majorVsn) *majorVsn = 0; + if (minorVsn) *minorVsn = 0; + return wxUNIX; +} +#endif // __WXMICROWIN__ -bool wxMatchWild( const wxString& pat, const wxString& text, bool dot_special ) -{ - wxString tmp1 = pat; - char *pattern = WXSTRINGCAST(tmp1); - wxString tmp2 = text; - char *str = WXSTRINGCAST(tmp2); - char c; - char *cp; - bool done = FALSE, ret_code, ok; - // Below is for vi fans - const char OB = '{', CB = '}'; - - // dot_special means '.' only matches '.' - if (dot_special && *str == '.' && *pattern != *str) - return FALSE; - - while ((*pattern != '\0') && (!done) - && (((*str=='\0')&&((*pattern==OB)||(*pattern=='*')))||(*str!='\0'))) { - switch (*pattern) { - case '\\': - pattern++; - if (*pattern != '\0') - pattern++; - break; - case '*': - pattern++; - ret_code = FALSE; - while ((*str!='\0') - && (!(ret_code=wxMatchWild(pattern, str++, FALSE)))) - /*loop*/; - if (ret_code) { - while (*str != '\0') - str++; - while (*pattern != '\0') - pattern++; - } - break; - case '[': - pattern++; - repeat: - if ((*pattern == '\0') || (*pattern == ']')) { - done = TRUE; - break; - } - if (*pattern == '\\') { - pattern++; - if (*pattern == '\0') { - done = TRUE; - break; - } - } - if (*(pattern + 1) == '-') { - c = *pattern; - pattern += 2; - if (*pattern == ']') { - done = TRUE; - break; - } - if (*pattern == '\\') { - pattern++; - if (*pattern == '\0') { - done = TRUE; - break; - } - } - if ((*str < c) || (*str > *pattern)) { - pattern++; - goto repeat; - } - } else if (*pattern != *str) { - pattern++; - goto repeat; - } - pattern++; - while ((*pattern != ']') && (*pattern != '\0')) { - if ((*pattern == '\\') && (*(pattern + 1) != '\0')) - pattern++; - pattern++; - } - if (*pattern != '\0') { - pattern++, str++; - } - break; - case '?': - pattern++; - str++; - break; - case OB: - pattern++; - while ((*pattern != CB) && (*pattern != '\0')) { - cp = str; - ok = TRUE; - while (ok && (*cp != '\0') && (*pattern != '\0') - && (*pattern != ',') && (*pattern != CB)) { - if (*pattern == '\\') - pattern++; - ok = (*pattern++ == *cp++); - } - if (*pattern == '\0') { - ok = FALSE; - done = TRUE; - break; - } else if (ok) { - str = cp; - while ((*pattern != CB) && (*pattern != '\0')) { - if (*++pattern == '\\') { - if (*++pattern == CB) - pattern++; - } - } - } else { - while (*pattern!=CB && *pattern!=',' && *pattern!='\0') { - if (*++pattern == '\\') { - if (*++pattern == CB || *pattern == ',') - pattern++; - } - } - } - if (*pattern != '\0') - pattern++; - } - break; - default: - if (*str == *pattern) { - str++, pattern++; - } else { - done = TRUE; - } - } - } - while (*pattern == '*') - pattern++; - return ((*str == '\0') && (*pattern == '\0')); -}; +// ---------------------------------------------------------------------------- +// Win32 codepage conversion functions +// ---------------------------------------------------------------------------- -#endif // 0 +#if defined(__WIN32__) && !defined(__WXMICROWIN__) -#if 0 +// wxGetNativeFontEncoding() doesn't exist neither in wxBase nor in wxUniv +#if wxUSE_GUI && !defined(__WXUNIVERSAL__) -// maximum mumber of lines the output console should have -static const WORD MAX_CONSOLE_LINES = 500; +#include "wx/fontmap.h" -BOOL WINAPI MyConsoleHandler( DWORD dwCtrlType ) { // control signal type - FreeConsole(); - return TRUE; -} +// VZ: the new version of wxCharsetToCodepage() is more politically correct +// and should work on other Windows versions as well but the old version is +// still needed for !wxUSE_FONTMAP || !wxUSE_GUI case -void wxRedirectIOToConsole() +extern long wxEncodingToCodepage(wxFontEncoding encoding) { - int hConHandle; - long lStdHandle; - CONSOLE_SCREEN_BUFFER_INFO coninfo; - FILE *fp; - - // allocate a console for this app - AllocConsole(); - - // set the screen buffer to be big enough to let us scroll text - GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), - &coninfo); - coninfo.dwSize.Y = MAX_CONSOLE_LINES; - SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), - coninfo.dwSize); - - // redirect unbuffered STDOUT to the console - lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE); - hConHandle = _open_osfhandle(lStdHandle, _O_TEXT); - if(hConHandle <= 0) return; - fp = _fdopen( hConHandle, "w" ); - *stdout = *fp; - setvbuf( stdout, NULL, _IONBF, 0 ); - - // redirect unbuffered STDIN to the console - lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE); - hConHandle = _open_osfhandle(lStdHandle, _O_TEXT); - if(hConHandle <= 0) return; - fp = _fdopen( hConHandle, "r" ); - *stdin = *fp; - setvbuf( stdin, NULL, _IONBF, 0 ); - - // redirect unbuffered STDERR to the console - lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE); - hConHandle = _open_osfhandle(lStdHandle, _O_TEXT); - if(hConHandle <= 0) return; - fp = _fdopen( hConHandle, "w" ); - *stderr = *fp; - setvbuf( stderr, NULL, _IONBF, 0 ); - - // make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog - // point to console as well - ios::sync_with_stdio(); - - SetConsoleCtrlHandler(MyConsoleHandler, TRUE); + // translate encoding into the Windows CHARSET + wxNativeEncodingInfo natveEncInfo; + if ( !wxGetNativeFontEncoding(encoding, &natveEncInfo) ) + return -1; + + // translate CHARSET to code page + CHARSETINFO csetInfo; + if ( !::TranslateCharsetInfo((DWORD *)(DWORD)natveEncInfo.charset, + &csetInfo, + TCI_SRCCHARSET) ) + { + wxLogLastError(_T("TranslateCharsetInfo(TCI_SRCCHARSET)")); + + return -1; + } + + return csetInfo.ciACP; } -#else -// Not supported -void wxRedirectIOToConsole() + +#if wxUSE_FONTMAP + +extern long wxCharsetToCodepage(const wxChar *name) { + // first get the font encoding for this charset + if ( !name ) + return -1; + + wxFontEncoding enc = wxFontMapper::Get()->CharsetToEncoding(name, FALSE); + if ( enc == wxFONTENCODING_SYSTEM ) + return -1; + + // the use the helper function + return wxEncodingToCodepage(enc); } -#endif -#ifdef __WXMICROWIN__ -int wxGetOsVersion(int *majorVsn, int *minorVsn) +#endif // wxUSE_FONTMAP + +#endif // wxUSE_GUI + +// include old wxCharsetToCodepage() by OK if needed +#if !wxUSE_GUI || !wxUSE_FONTMAP + +#include "wx/msw/registry.h" + +// this should work if Internet Exploiter is installed +extern long wxCharsetToCodepage(const wxChar *name) { - // MICROWIN_TODO - if (majorVsn) *majorVsn = 0; - if (minorVsn) *minorVsn = 0; - return wxUNIX; + if (!name) + return GetACP(); + + long CP=-1; + + wxString cn(name); + do { + wxString path(wxT("MIME\\Database\\Charset\\")); + path += cn; + wxRegKey key(wxRegKey::HKCR, path); + + if (!key.Exists()) break; + + // two cases: either there's an AliasForCharset string, + // or there are Codepage and InternetEncoding dwords. + // The InternetEncoding gives us the actual encoding, + // the Codepage just says which Windows character set to + // use when displaying the data. + if (key.HasValue(wxT("InternetEncoding")) && + key.QueryValue(wxT("InternetEncoding"), &CP)) break; + + // no encoding, see if it's an alias + if (!key.HasValue(wxT("AliasForCharset")) || + !key.QueryValue(wxT("AliasForCharset"), cn)) break; + } while (1); + + return CP; } -#endif + +#endif // !wxUSE_GUI || !wxUSE_FONTMAP + +#endif // Win32