#endif
#include "wx/msw/ole/oleutils.h"
+#include "wx/msw/ole/safearray.h"
#if defined(__VISUALC__) && (__VISUALC__ > 1000)
#include <docobj.h>
#if wxUSE_VARIANT
-namespace
+// ----------------------------------------------------------------------------
+// wxVariantDataCurrency
+// ----------------------------------------------------------------------------
+
+
+#if wxUSE_ANY
+
+bool wxVariantDataCurrency::GetAsAny(wxAny* any) const
{
+ *any = m_value;
+ return true;
+}
-// Helper class for creating and filling SAFEARRAY. To use it, call Create()
-// first, then SetElement() for each element and finally Detach() the SAFEARRAY
-// from it if you don't want it to be deleted when this class is.
-class wxSafeArrayHelper
+wxVariantData* wxVariantDataCurrency::VariantDataFactory(const wxAny& any)
{
-public:
- wxSafeArrayHelper();
- ~wxSafeArrayHelper();
+ return new wxVariantDataCurrency(wxANY_AS(any, CURRENCY));
+}
- bool Create(VARTYPE vt, long count); // creates and locks the array
+REGISTER_WXANY_CONVERSION(CURRENCY, wxVariantDataCurrency)
- bool SetElement(size_t index, const wxVariant& variant);
- bool SetElement(size_t index, const wxString& str);
+#endif // wxUSE_ANY
- SAFEARRAY* Detach(); // unlocks the array and gives up its ownership
+bool wxVariantDataCurrency::Eq(wxVariantData& data) const
+{
+ wxASSERT_MSG( (data.GetType() == wxS("currency")),
+ "wxVariantDataCurrency::Eq: argument mismatch" );
-private:
- void Unlock();
+ wxVariantDataCurrency& otherData = (wxVariantDataCurrency&) data;
- SAFEARRAY* m_array;
-};
+ return otherData.m_value.int64 == m_value.int64;
+}
-wxSafeArrayHelper::wxSafeArrayHelper()
+#if wxUSE_STD_IOSTREAM
+bool wxVariantDataCurrency::Write(wxSTD ostream& str) const
{
- m_array = NULL;
+ wxString s;
+ Write(s);
+ str << s;
+ return true;
}
+#endif
-wxSafeArrayHelper::~wxSafeArrayHelper()
+bool wxVariantDataCurrency::Write(wxString& str) const
{
- if ( m_array )
+ BSTR bStr = NULL;
+ if ( SUCCEEDED(VarBstrFromCy(m_value, LOCALE_USER_DEFAULT, 0, &bStr)) )
{
- Unlock();
- SafeArrayDestroy(m_array);
+ str = wxConvertStringFromOle(bStr);
+ SysFreeString(bStr);
+ return true;
}
+ return false;
+}
+
+// ----------------------------------------------------------------------------
+// wxVariantDataErrorCode
+// ----------------------------------------------------------------------------
+
+#if wxUSE_ANY
+
+bool wxVariantDataErrorCode::GetAsAny(wxAny* any) const
+{
+ *any = m_value;
+ return true;
}
-bool wxSafeArrayHelper::Create(VARTYPE vt, long count)
+wxVariantData* wxVariantDataErrorCode::VariantDataFactory(const wxAny& any)
{
- SAFEARRAYBOUND saBound;
+ return new wxVariantDataErrorCode(wxANY_AS(any, SCODE));
+}
- saBound.lLbound = 0;
- saBound.cElements = count;
- m_array = SafeArrayCreate(vt, 1, &saBound);
- if ( !m_array )
- return false;
- return SUCCEEDED( SafeArrayLock(m_array) );
+REGISTER_WXANY_CONVERSION(SCODE, wxVariantDataErrorCode)
+
+#endif // wxUSE_ANY
+
+bool wxVariantDataErrorCode::Eq(wxVariantData& data) const
+{
+ wxASSERT_MSG( (data.GetType() == wxS("errorcode")),
+ "wxVariantDataErrorCode::Eq: argument mismatch" );
+
+ wxVariantDataErrorCode& otherData = (wxVariantDataErrorCode&) data;
+
+ return otherData.m_value == m_value;
}
-bool wxSafeArrayHelper::SetElement(size_t index, const wxVariant& variant)
+#if wxUSE_STD_IOSTREAM
+bool wxVariantDataErrorCode::Write(wxSTD ostream& str) const
{
- VARIANT* data = (VARIANT*)m_array->pvData;
- return wxConvertVariantToOle(variant, data[index]);
+ wxString s;
+ Write(s);
+ str << s;
+ return true;
}
+#endif
-bool wxSafeArrayHelper::SetElement(size_t index, const wxString& str)
+bool wxVariantDataErrorCode::Write(wxString& str) const
{
- BSTR bstr = wxConvertStringToOle(str);
+ str << m_value;
+ return true;
+}
- if ( !bstr && !str.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;
- }
- BSTR* data = (BSTR*)m_array->pvData;
- data[index] = bstr;
+// ----------------------------------------------------------------------------
+// wxVariantDataSafeArray
+// ----------------------------------------------------------------------------
+
+#if wxUSE_ANY
+
+bool wxVariantDataSafeArray::GetAsAny(wxAny* any) const
+{
+ *any = m_value;
return true;
}
-SAFEARRAY* wxSafeArrayHelper::Detach()
+wxVariantData* wxVariantDataSafeArray::VariantDataFactory(const wxAny& any)
{
- Unlock();
- SAFEARRAY* result = m_array;
- m_array = NULL;
- return result;
+ return new wxVariantDataSafeArray(wxANY_AS(any, SAFEARRAY*));
}
-void wxSafeArrayHelper::Unlock()
+REGISTER_WXANY_CONVERSION(SAFEARRAY*, wxVariantDataSafeArray)
+
+#endif // wxUSE_ANY
+
+bool wxVariantDataSafeArray::Eq(wxVariantData& data) const
{
- if ( m_array )
- SafeArrayUnlock(m_array);
+ wxASSERT_MSG( (data.GetType() == wxS("safearray")),
+ "wxVariantDataSafeArray::Eq: argument mismatch" );
+
+ wxVariantDataSafeArray& otherData = (wxVariantDataSafeArray&) data;
+
+ return otherData.m_value == m_value;
}
-} // unnamed namespace
+#if wxUSE_STD_IOSTREAM
+bool wxVariantDataSafeArray::Write(wxSTD ostream& str) const
+{
+ wxString s;
+ Write(s);
+ str << s;
+ return true;
+}
+#endif
+bool wxVariantDataSafeArray::Write(wxString& str) const
+{
+ str.Printf(wxS("SAFEARRAY: %p"), (void*)m_value);
+ return true;
+}
WXDLLEXPORT bool wxConvertVariantToOle(const wxVariant& variant, VARIANTARG& oleVariant)
{
wxString type(variant.GetType());
-
- if (type == wxT("long"))
+ if (type == wxT("errorcode"))
+ {
+ wxVariantDataErrorCode* const
+ ec = wxStaticCastVariantData(variant.GetData(),
+ wxVariantDataErrorCode);
+ oleVariant.vt = VT_ERROR;
+ oleVariant.scode = ec->GetValue();
+ }
+ else if (type == wxT("currency"))
+ {
+ wxVariantDataCurrency* const
+ c = wxStaticCastVariantData(variant.GetData(),
+ wxVariantDataCurrency);
+ oleVariant.vt = VT_CY;
+ oleVariant.cyVal = c->GetValue();
+ }
+ else if (type == wxT("safearray"))
+ {
+ wxVariantDataSafeArray* const
+ vsa = wxStaticCastVariantData(variant.GetData(),
+ wxVariantDataSafeArray);
+ SAFEARRAY* psa = vsa->GetValue();
+ VARTYPE vt;
+
+ wxCHECK(psa, false);
+ HRESULT hr = SafeArrayGetVartype(psa, &vt);
+ if ( FAILED(hr) )
+ {
+ wxLogApiError(wxS("SafeArrayGetVartype()"), hr);
+ SafeArrayDestroy(psa);
+ return false;
+ }
+ oleVariant.vt = vt | VT_ARRAY;
+ oleVariant.parray = psa;
+ }
+ else if (type == wxT("long"))
{
oleVariant.vt = VT_I4;
oleVariant.lVal = variant.GetLong() ;
}
else if (type == wxT("list"))
{
- wxSafeArrayHelper sah;
-
- if (!sah.Create(VT_VARIANT, variant.GetCount()))
+ wxSafeArray<VT_VARIANT> safeArray;
+ if (!safeArray.CreateFromListVariant(variant))
return false;
- for (size_t i = 0; i < variant.GetCount(); i++)
- {
- if (!sah.SetElement(i, variant[i]))
- return false;
- }
-
oleVariant.vt = VT_VARIANT | VT_ARRAY;
- oleVariant.parray = sah.Detach();
+ oleVariant.parray = safeArray.Detach();
}
else if (type == wxT("arrstring"))
{
- wxArrayString strings(variant.GetArrayString());
- wxSafeArrayHelper sah;
+ wxSafeArray<VT_BSTR> safeArray;
- if (!sah.Create(VT_BSTR, strings.GetCount()))
+ if (!safeArray.CreateFromArrayString(variant.GetArrayString()))
return false;
- for (size_t i = 0; i < strings.GetCount(); i++)
- {
- if (!sah.SetElement(i, strings[i]))
- return false;
- }
-
oleVariant.vt = VT_BSTR | VT_ARRAY;
- oleVariant.parray = sah.Detach();
+ oleVariant.parray = safeArray.Detach();
}
else
{
bool ok = true;
if ( oleVariant.vt & VT_ARRAY )
{
-
- // Compute the total number of elements in all array dimensions
- int cElements = 1;
- for ( int cDims = 0; cDims < oleVariant.parray->cDims; cDims++ )
- cElements *= oleVariant.parray->rgsabound[cDims].cElements;
-
- // Get a pointer to the data
- void* pvdata;
- HRESULT hr = SafeArrayAccessData(oleVariant.parray, &pvdata);
- if ( FAILED(hr) )
- return false;
-
+ // TODO: We currently return arrays as wxVariant of the list type
+ // containing the flattened form of array but we should allow
+ // getting it as wxVariantDataSafeArray instead. Doing this is
+ // simple, we'd just need to do something like this:
+ //
+ // if ( oleVariant.parray && SafeArrayGetDim(oleVariant.parray) > 1 )
+ // {
+ // variant.SetData(new wxVariantDataSafeArray(oleVariant.parray));
+ // }
+ //
+ // but currently we don't do it for compatibility reasons.
switch (oleVariant.vt & VT_TYPEMASK)
{
+ case VT_I2:
+ ok = wxSafeArray<VT_I2>::ConvertToVariant(oleVariant.parray, variant);
+ break;
+ case VT_I4:
+ ok = wxSafeArray<VT_I4>::ConvertToVariant(oleVariant.parray, variant);
+ break;
+ case VT_R4:
+ ok = wxSafeArray<VT_R4>::ConvertToVariant(oleVariant.parray, variant);
+ break;
+ case VT_R8:
+ ok = wxSafeArray<VT_R8>::ConvertToVariant(oleVariant.parray, variant);
+ break;
case VT_VARIANT:
- {
- variant.ClearList();
- VARIANTARG *variant_data=(VARIANTARG*)pvdata;
- for ( int i = 0; i < cElements; i++ )
- {
- VARIANTARG& oleElement = variant_data[i];
- wxVariant vElement;
- if ( !wxConvertOleToVariant(oleElement, vElement) )
- {
- ok = false;
- variant.ClearList();
- break;
- }
-
- variant.Append(vElement);
- }
- }
+ ok = wxSafeArray<VT_VARIANT>::ConvertToVariant(oleVariant.parray, variant);
break;
-
case VT_BSTR:
{
wxArrayString strings;
- BSTR *string_val=(BSTR*)pvdata;
- for ( int i = 0; i < cElements; ++i )
- {
- wxString str=wxConvertStringFromOle(*string_val);
- strings.Add(str);
- ++string_val;
- }
- variant=strings;
+ if ( wxSafeArray<VT_BSTR>::ConvertToArrayString(oleVariant.parray, strings) )
+ variant = strings;
+ else
+ ok = false;
}
break;
-
default:
- wxLogDebug(wxT("unhandled VT_ARRAY type %x in wxConvertOleToVariant"),
- oleVariant.vt & VT_TYPEMASK);
- variant = wxVariant();
ok = false;
break;
}
-
- SafeArrayUnaccessData(oleVariant.parray);
+ if ( !ok )
+ {
+ wxLogDebug(wxT("unhandled VT_ARRAY type %x in wxConvertOleToVariant"),
+ oleVariant.vt & VT_TYPEMASK);
+ variant = wxVariant();
+ }
}
else if ( oleVariant.vt & VT_BYREF )
{
{
switch ( oleVariant.vt & VT_TYPEMASK )
{
+ case VT_ERROR:
+ variant.SetData(new wxVariantDataErrorCode(oleVariant.scode));
+ break;
+
+ case VT_CY:
+ variant.SetData(new wxVariantDataCurrency(oleVariant.cyVal));
+ break;
+
case VT_BSTR:
{
wxString str(wxConvertStringFromOle(oleVariant.bstrVal));