dolphin/Externals/wxWidgets3/src/unix/dlunix.cpp
EmptyChaos 822326eea9 Update wxWidgets to 3.1.0
From wxWidgets master 81570ae070b35c9d52de47b1f14897f3ff1a66c7.

include/wx/defs.h -- __w64 warning disable patch by comex brought forward.

include/wx/msw/window.h -- added GetContentScaleFactor() which was not implemented on Windows but is necessary for wxBitmap scaling on Mac OS X so it needs to work to avoid #ifdef-ing the code.

src/gtk/window.cpp -- Modified DoSetClientSize() to direct call wxWindowGTK::DoSetSize() instead of using public wxWindowBase::SetSize() which now prevents derived classes (like wxAuiToolbar) intercepting the call and breaking it. This matches Windows which does NOT need to call DoSetSize internally. End result is this fixes Dolphin's debug tools toolbars on Linux.

src/osx/window_osx.cpp -- Same fix as for GTK since it has the same issue.

src/msw/radiobox.cpp -- Hacked to fix display in HiDPI (was clipping off end of text).

Updated CMakeLists for Linux and Mac OS X. Small code changes to Dolphin to fix debug error boxes, deprecation warnings, and retain previous UI behavior on Windows.
2016-06-26 15:25:29 +10:00

306 lines
8.4 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// Name: src/unix/dlunix.cpp
// Purpose: Unix-specific part of wxDynamicLibrary and related classes
// Author: Vadim Zeitlin
// Modified by:
// Created: 2005-01-16 (extracted from common/dynlib.cpp)
// Copyright: (c) 2000-2005 Vadim Zeitlin <vadim@wxwindows.org>
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#if wxUSE_DYNLIB_CLASS
#include "wx/dynlib.h"
#include "wx/ffile.h"
#ifndef WX_PRECOMP
#include "wx/intl.h"
#include "wx/log.h"
#endif
#ifdef HAVE_DLOPEN
#include <dlfcn.h>
#endif
#ifdef __DARWIN__
#include <AvailabilityMacros.h>
#endif
// if some flags are not supported, just ignore them
#ifndef RTLD_LAZY
#define RTLD_LAZY 0
#endif
#ifndef RTLD_NOW
#define RTLD_NOW 0
#endif
#ifndef RTLD_GLOBAL
#define RTLD_GLOBAL 0
#endif
#if defined(HAVE_DLOPEN) || defined(__DARWIN__)
#define USE_POSIX_DL_FUNCS
#elif !defined(HAVE_SHL_LOAD)
#error "Don't know how to load dynamic libraries on this platform!"
#endif
// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// loading/unloading DLLs
// ----------------------------------------------------------------------------
wxDllType wxDynamicLibrary::GetProgramHandle()
{
#ifdef USE_POSIX_DL_FUNCS
return dlopen(0, RTLD_LAZY);
#else
return PROG_HANDLE;
#endif
}
/* static */
wxDllType wxDynamicLibrary::RawLoad(const wxString& libname, int flags)
{
wxASSERT_MSG( !(flags & wxDL_NOW) || !(flags & wxDL_LAZY),
wxT("wxDL_LAZY and wxDL_NOW are mutually exclusive.") );
#ifdef USE_POSIX_DL_FUNCS
// we need to use either RTLD_NOW or RTLD_LAZY because if we call dlopen()
// with flags == 0 recent versions of glibc just fail the call, so use
// RTLD_NOW even if wxDL_NOW was not specified
int rtldFlags = flags & wxDL_LAZY ? RTLD_LAZY : RTLD_NOW;
if ( flags & wxDL_GLOBAL )
rtldFlags |= RTLD_GLOBAL;
return dlopen(libname.fn_str(), rtldFlags);
#else // !USE_POSIX_DL_FUNCS
int shlFlags = 0;
if ( flags & wxDL_LAZY )
{
shlFlags |= BIND_DEFERRED;
}
else if ( flags & wxDL_NOW )
{
shlFlags |= BIND_IMMEDIATE;
}
return shl_load(libname.fn_str(), shlFlags, 0);
#endif // USE_POSIX_DL_FUNCS/!USE_POSIX_DL_FUNCS
}
/* static */
void wxDynamicLibrary::Unload(wxDllType handle)
{
#ifdef wxHAVE_DYNLIB_ERROR
int rc =
#endif
#ifdef USE_POSIX_DL_FUNCS
dlclose(handle);
#else // !USE_POSIX_DL_FUNCS
shl_unload(handle);
#endif // USE_POSIX_DL_FUNCS/!USE_POSIX_DL_FUNCS
#if defined(USE_POSIX_DL_FUNCS) && defined(wxHAVE_DYNLIB_ERROR)
if ( rc != 0 )
Error();
#endif
}
/* static */
void *wxDynamicLibrary::RawGetSymbol(wxDllType handle, const wxString& name)
{
void *symbol;
#ifdef USE_POSIX_DL_FUNCS
symbol = dlsym(handle, name.fn_str());
#else // !USE_POSIX_DL_FUNCS
// note that shl_findsym modifies the handle argument to indicate where the
// symbol was found, but it's ok to modify the local handle copy here
if ( shl_findsym(&handle, name.fn_str(), TYPE_UNDEFINED, &symbol) != 0 )
symbol = 0;
#endif // USE_POSIX_DL_FUNCS/!USE_POSIX_DL_FUNCS
return symbol;
}
// ----------------------------------------------------------------------------
// error handling
// ----------------------------------------------------------------------------
#ifdef wxHAVE_DYNLIB_ERROR
/* static */
void wxDynamicLibrary::Error()
{
wxString err(dlerror());
if ( err.empty() )
err = _("Unknown dynamic library error");
wxLogError(wxT("%s"), err);
}
#endif // wxHAVE_DYNLIB_ERROR
// ----------------------------------------------------------------------------
// listing loaded modules
// ----------------------------------------------------------------------------
// wxDynamicLibraryDetails declares this class as its friend, so put the code
// initializing new details objects here
class wxDynamicLibraryDetailsCreator
{
public:
// create a new wxDynamicLibraryDetails from the given data
static wxDynamicLibraryDetails *
New(void *start, void *end, const wxString& path)
{
wxDynamicLibraryDetails *details = new wxDynamicLibraryDetails;
details->m_path = path;
details->m_name = path.AfterLast(wxT('/'));
details->m_address = start;
details->m_length = (char *)end - (char *)start;
// try to extract the library version from its name
const size_t posExt = path.rfind(wxT(".so"));
if ( posExt != wxString::npos )
{
if ( path.c_str()[posExt + 3] == wxT('.') )
{
// assume "libfoo.so.x.y.z" case
details->m_version.assign(path, posExt + 4, wxString::npos);
}
else
{
size_t posDash = path.find_last_of(wxT('-'), posExt);
if ( posDash != wxString::npos )
{
// assume "libbar-x.y.z.so" case
posDash++;
details->m_version.assign(path, posDash, posExt - posDash);
}
}
}
return details;
}
};
/* static */
wxDynamicLibraryDetailsArray wxDynamicLibrary::ListLoaded()
{
wxDynamicLibraryDetailsArray dlls;
#ifdef __LINUX__
// examine /proc/self/maps to find out what is loaded in our address space
wxFFile file(wxT("/proc/self/maps"));
if ( file.IsOpened() )
{
// details of the module currently being parsed
wxString pathCur;
void *startCur = NULL,
*endCur = NULL;
char path[1024];
char buf[1024];
while ( fgets(buf, WXSIZEOF(buf), file.fp()) )
{
// format is: "start-end perm offset maj:min inode path", see proc(5)
void *start,
*end;
switch ( sscanf(buf, "%p-%p %*4s %*p %*02x:%*02x %*d %1024s\n",
&start, &end, path) )
{
case 2:
// there may be no path column
path[0] = '\0';
break;
case 3:
// nothing to do, read everything we wanted
break;
default:
// chop '\n'
buf[strlen(buf) - 1] = '\0';
wxLogDebug(wxT("Failed to parse line \"%s\" in /proc/self/maps."),
buf);
continue;
}
wxASSERT_MSG( start >= endCur,
wxT("overlapping regions in /proc/self/maps?") );
wxString pathNew = wxString::FromAscii(path);
if ( pathCur.empty() )
{
// new module start
pathCur = pathNew;
startCur = start;
endCur = end;
}
else if ( pathCur == pathNew && endCur == end )
{
// continuation of the same module in the address space
endCur = end;
}
else // end of the current module
{
dlls.Add(wxDynamicLibraryDetailsCreator::New(startCur,
endCur,
pathCur));
pathCur.clear();
}
}
}
#endif // __LINUX__
return dlls;
}
/* static */
void* wxDynamicLibrary::GetModuleFromAddress(const void* addr, wxString* path)
{
#ifdef HAVE_DLADDR
Dl_info di = { 0 };
// At least under Solaris dladdr() takes non-const void*.
if ( dladdr(const_cast<void*>(addr), &di) == 0 )
return NULL;
if ( path )
*path = di.dli_fname;
return di.dli_fbase;
#endif // HAVE_DLADDR
return NULL;
}
#endif // wxUSE_DYNLIB_CLASS