mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-31 10:09:36 -06:00
Upgrade WX to r74856, mainly to support @2x.
This commit is contained in:
394
Externals/wxWidgets3/include/wx/msw/ole/safearray.h
vendored
Normal file
394
Externals/wxWidgets3/include/wx/msw/ole/safearray.h
vendored
Normal file
@ -0,0 +1,394 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Name: msw/ole/safearray.h
|
||||
// Purpose: Helpers for working with OLE SAFEARRAYs.
|
||||
// Author: PB
|
||||
// Created: 2012-09-23
|
||||
// Copyright: (c) 2012 wxWidgets development team
|
||||
// Licence: wxWindows licence
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _MSW_OLE_SAFEARRAY_H_
|
||||
#define _MSW_OLE_SAFEARRAY_H_
|
||||
|
||||
#include "wx/msw/ole/oleutils.h"
|
||||
|
||||
#if wxUSE_OLE && wxUSE_VARIANT
|
||||
|
||||
/*
|
||||
wxSafeArray is wxWidgets wrapper for working with MS Windows SAFEARRAYs.
|
||||
It also has convenience functions for converting between SAFEARRAY
|
||||
and wxVariant with list type or wxArrayString.
|
||||
*/
|
||||
|
||||
// The base class with type-independent methods. It exists solely in order to
|
||||
// reduce the template bloat.
|
||||
class WXDLLIMPEXP_CORE wxSafeArrayBase
|
||||
{
|
||||
public:
|
||||
// If owns a SAFEARRAY, it's unlocked and destroyed.
|
||||
virtual ~wxSafeArrayBase() { Destroy(); }
|
||||
|
||||
// Unlocks and destroys the owned SAFEARRAY.
|
||||
void Destroy();
|
||||
|
||||
// Unlocks the owned SAFEARRAY, returns it and gives up its ownership.
|
||||
SAFEARRAY* Detach();
|
||||
|
||||
// Returns true if has a valid SAFEARRAY.
|
||||
bool HasArray() const { return m_array != NULL; }
|
||||
|
||||
// Returns the number of dimensions.
|
||||
size_t GetDim() const;
|
||||
|
||||
// Returns lower bound for dimension dim in bound. Dimensions start at 1.
|
||||
bool GetLBound(size_t dim, long& bound) const;
|
||||
|
||||
// Returns upper bound for dimension dim in bound. Dimensions start at 1.
|
||||
bool GetUBound(size_t dim, long& bound) const;
|
||||
|
||||
// Returns element count for dimension dim. Dimensions start at 1.
|
||||
size_t GetCount(size_t dim) const;
|
||||
|
||||
protected:
|
||||
// Default constructor, protected so the class can't be used on its own,
|
||||
// it's only used as a base class of wxSafeArray<>.
|
||||
wxSafeArrayBase()
|
||||
{
|
||||
m_array = NULL;
|
||||
}
|
||||
|
||||
bool Lock();
|
||||
bool Unlock();
|
||||
|
||||
SAFEARRAY* m_array;
|
||||
};
|
||||
|
||||
// wxSafeArrayConvertor<> must be specialized for the type in order to allow
|
||||
// using it with wxSafeArray<>.
|
||||
//
|
||||
// We specialize it below for the standard types.
|
||||
template <VARTYPE varType>
|
||||
struct wxSafeArrayConvertor {};
|
||||
|
||||
/**
|
||||
Macro for specializing wxSafeArrayConvertor for simple types.
|
||||
|
||||
The template parameters are:
|
||||
- externType: basic C data type, e.g. wxFloat64 or wxInt32
|
||||
- varType: corresponding VARIANT type constant, e.g. VT_R8 or VT_I4.
|
||||
*/
|
||||
#define wxSPECIALIZE_WXSAFEARRAY_CONVERTOR_SIMPLE(externType, varType) \
|
||||
template <> \
|
||||
struct wxSafeArrayConvertor<varType> \
|
||||
{ \
|
||||
typedef externType externT; \
|
||||
typedef externT internT; \
|
||||
static bool ToArray(const externT& from, internT& to) \
|
||||
{ \
|
||||
to = from; \
|
||||
return true; \
|
||||
} \
|
||||
static bool FromArray(const internT& from, externT& to) \
|
||||
{ \
|
||||
to = from; \
|
||||
return true; \
|
||||
} \
|
||||
}
|
||||
|
||||
wxSPECIALIZE_WXSAFEARRAY_CONVERTOR_SIMPLE(wxInt16, VT_I2);
|
||||
wxSPECIALIZE_WXSAFEARRAY_CONVERTOR_SIMPLE(wxInt32, VT_I4);
|
||||
wxSPECIALIZE_WXSAFEARRAY_CONVERTOR_SIMPLE(wxFloat32, VT_R4);
|
||||
wxSPECIALIZE_WXSAFEARRAY_CONVERTOR_SIMPLE(wxFloat64, VT_R8);
|
||||
|
||||
// Specialization for VT_BSTR using wxString.
|
||||
template <>
|
||||
struct wxSafeArrayConvertor<VT_BSTR>
|
||||
{
|
||||
typedef wxString externT;
|
||||
typedef BSTR internT;
|
||||
|
||||
static bool ToArray(const wxString& from, BSTR& to)
|
||||
{
|
||||
BSTR bstr = wxConvertStringToOle(from);
|
||||
|
||||
if ( !bstr && !from.empty() )
|
||||
{
|
||||
// BSTR can be NULL for empty strings but if the string was
|
||||
// not empty, it means we failed to allocate memory for it.
|
||||
return false;
|
||||
}
|
||||
to = bstr;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool FromArray(const BSTR from, wxString& to)
|
||||
{
|
||||
to = wxConvertStringFromOle(from);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// Specialization for VT_VARIANT using wxVariant.
|
||||
template <>
|
||||
struct wxSafeArrayConvertor<VT_VARIANT>
|
||||
{
|
||||
typedef wxVariant externT;
|
||||
typedef VARIANT internT;
|
||||
|
||||
static bool ToArray(const wxVariant& from, VARIANT& to)
|
||||
{
|
||||
return wxConvertVariantToOle(from, to);
|
||||
}
|
||||
|
||||
static bool FromArray(const VARIANT& from, wxVariant& to)
|
||||
{
|
||||
return wxConvertOleToVariant(from, to);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <VARTYPE varType>
|
||||
class wxSafeArray : public wxSafeArrayBase
|
||||
{
|
||||
public:
|
||||
typedef wxSafeArrayConvertor<varType> Convertor;
|
||||
typedef typename Convertor::internT internT;
|
||||
typedef typename Convertor::externT externT;
|
||||
|
||||
// Default constructor.
|
||||
wxSafeArray()
|
||||
{
|
||||
m_array = NULL;
|
||||
}
|
||||
|
||||
// Creates and locks a zero-based one-dimensional SAFEARRAY with the given
|
||||
// number of elements.
|
||||
bool Create(size_t count)
|
||||
{
|
||||
SAFEARRAYBOUND bound;
|
||||
|
||||
bound.lLbound = 0;
|
||||
bound.cElements = count;
|
||||
return Create(&bound, 1);
|
||||
}
|
||||
|
||||
// Creates and locks a SAFEARRAY. See SafeArrayCreate() in MSDN
|
||||
// documentation for more information.
|
||||
bool Create(SAFEARRAYBOUND* bound, size_t dimensions)
|
||||
{
|
||||
wxCHECK_MSG( !m_array, false, wxS("Can't be created twice") );
|
||||
|
||||
m_array = SafeArrayCreate(varType, dimensions, bound);
|
||||
if ( !m_array )
|
||||
return false;
|
||||
|
||||
return Lock();
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a 0-based one-dimensional SAFEARRAY from wxVariant with the
|
||||
list type.
|
||||
|
||||
Can be called only for wxSafeArray<VT_VARIANT>.
|
||||
*/
|
||||
bool CreateFromListVariant(const wxVariant& variant)
|
||||
{
|
||||
wxCHECK(varType == VT_VARIANT, false);
|
||||
wxCHECK(variant.GetType() == wxS("list"), false);
|
||||
|
||||
if ( !Create(variant.GetCount()) )
|
||||
return false;
|
||||
|
||||
VARIANT* data = static_cast<VARIANT*>(m_array->pvData);
|
||||
|
||||
for ( size_t i = 0; i < variant.GetCount(); i++)
|
||||
{
|
||||
if ( !Convertor::ToArray(variant[i], data[i]) )
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a 0-based one-dimensional SAFEARRAY from wxArrayString.
|
||||
|
||||
Can be called only for wxSafeArray<VT_BSTR>.
|
||||
*/
|
||||
bool CreateFromArrayString(const wxArrayString& strings)
|
||||
{
|
||||
wxCHECK(varType == VT_BSTR, false);
|
||||
|
||||
if ( !Create(strings.size()) )
|
||||
return false;
|
||||
|
||||
BSTR* data = static_cast<BSTR*>(m_array->pvData);
|
||||
|
||||
for ( size_t i = 0; i < strings.size(); i++ )
|
||||
{
|
||||
if ( !Convertor::ToArray(strings[i], data[i]) )
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
Attaches and locks an existing SAFEARRAY.
|
||||
The array must have the same VARTYPE as this wxSafeArray was
|
||||
instantiated with.
|
||||
*/
|
||||
bool Attach(SAFEARRAY* array)
|
||||
{
|
||||
wxCHECK_MSG(!m_array && array, false,
|
||||
wxS("Can only attach a valid array to an uninitialized one") );
|
||||
|
||||
VARTYPE vt;
|
||||
HRESULT hr = SafeArrayGetVartype(array, &vt);
|
||||
if ( FAILED(hr) )
|
||||
{
|
||||
wxLogApiError(wxS("SafeArrayGetVarType()"), hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
wxCHECK_MSG(vt == varType, false,
|
||||
wxS("Attaching array of invalid type"));
|
||||
|
||||
m_array = array;
|
||||
return Lock();
|
||||
}
|
||||
|
||||
/**
|
||||
Indices have the same row-column order as rgIndices in
|
||||
SafeArrayPutElement(), i.e. they follow BASIC rules, NOT C ones.
|
||||
*/
|
||||
bool SetElement(long* indices, const externT& element)
|
||||
{
|
||||
wxCHECK_MSG( m_array, false, wxS("Uninitialized array") );
|
||||
wxCHECK_MSG( indices, false, wxS("Invalid index") );
|
||||
|
||||
internT* data;
|
||||
|
||||
if ( FAILED( SafeArrayPtrOfIndex(m_array, indices, (void**)&data) ) )
|
||||
return false;
|
||||
|
||||
return Convertor::ToArray(element, *data);
|
||||
}
|
||||
|
||||
/**
|
||||
Indices have the same row-column order as rgIndices in
|
||||
SafeArrayPutElement(), i.e. they follow BASIC rules, NOT C ones.
|
||||
*/
|
||||
bool GetElement(long* indices, externT& element) const
|
||||
{
|
||||
wxCHECK_MSG( m_array, false, wxS("Uninitialized array") );
|
||||
wxCHECK_MSG( indices, false, wxS("Invalid index") );
|
||||
|
||||
internT* data;
|
||||
|
||||
if ( FAILED( SafeArrayPtrOfIndex(m_array, indices, (void**)&data) ) )
|
||||
return false;
|
||||
|
||||
return Convertor::FromArray(*data, element);
|
||||
}
|
||||
|
||||
/**
|
||||
Converts the array to a wxVariant with the list type, regardless of the
|
||||
underlying SAFEARRAY type.
|
||||
|
||||
If the array is multidimensional, it is flattened using the alghoritm
|
||||
originally employed in wxConvertOleToVariant().
|
||||
*/
|
||||
bool ConvertToVariant(wxVariant& variant) const
|
||||
{
|
||||
wxCHECK_MSG( m_array, false, wxS("Uninitialized array") );
|
||||
|
||||
size_t dims = m_array->cDims;
|
||||
size_t count = 1;
|
||||
|
||||
for ( size_t i = 0; i < dims; i++ )
|
||||
count *= m_array->rgsabound[i].cElements;
|
||||
|
||||
const internT* data = static_cast<const internT*>(m_array->pvData);
|
||||
externT element;
|
||||
|
||||
variant.ClearList();
|
||||
for ( size_t i1 = 0; i1 < count; i1++ )
|
||||
{
|
||||
if ( !Convertor::FromArray(data[i1], element) )
|
||||
{
|
||||
variant.ClearList();
|
||||
return false;
|
||||
}
|
||||
variant.Append(element);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
Converts an array to an ArrayString.
|
||||
|
||||
Can be called only for wxSafeArray<VT_BSTR>. If the array is
|
||||
multidimensional, it is flattened using the alghoritm originally
|
||||
employed in wxConvertOleToVariant().
|
||||
*/
|
||||
bool ConvertToArrayString(wxArrayString& strings) const
|
||||
{
|
||||
wxCHECK_MSG( m_array, false, wxS("Uninitialized array") );
|
||||
wxCHECK(varType == VT_BSTR, false);
|
||||
|
||||
size_t dims = m_array->cDims;
|
||||
size_t count = 1;
|
||||
|
||||
for ( size_t i = 0; i < dims; i++ )
|
||||
count *= m_array->rgsabound[i].cElements;
|
||||
|
||||
const BSTR* data = static_cast<const BSTR*>(m_array->pvData);
|
||||
wxString element;
|
||||
|
||||
strings.clear();
|
||||
strings.reserve(count);
|
||||
for ( size_t i1 = 0; i1 < count; i1++ )
|
||||
{
|
||||
if ( !Convertor::FromArray(data[i1], element) )
|
||||
{
|
||||
strings.clear();
|
||||
return false;
|
||||
}
|
||||
strings.push_back(element);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ConvertToVariant(SAFEARRAY* psa, wxVariant& variant)
|
||||
{
|
||||
wxSafeArray<varType> sa;
|
||||
bool result = false;
|
||||
|
||||
if ( sa.Attach(psa) )
|
||||
result = sa.ConvertToVariant(variant);
|
||||
|
||||
if ( sa.HasArray() )
|
||||
sa.Detach();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool ConvertToArrayString(SAFEARRAY* psa, wxArrayString& strings)
|
||||
{
|
||||
wxSafeArray<varType> sa;
|
||||
bool result = false;
|
||||
|
||||
if ( sa.Attach(psa) )
|
||||
result = sa.ConvertToArrayString(strings);
|
||||
|
||||
if ( sa.HasArray() )
|
||||
sa.Detach();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
wxDECLARE_NO_COPY_TEMPLATE_CLASS(wxSafeArray, varType);
|
||||
};
|
||||
|
||||
#endif // wxUSE_OLE && wxUSE_VARIANT
|
||||
|
||||
#endif // _MSW_OLE_SAFEARRAY_H_
|
Reference in New Issue
Block a user