Index: third_party/wtl/include/atlddx.h |
diff --git a/third_party/wtl/include/atlddx.h b/third_party/wtl/include/atlddx.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..dc0f31f210ca53662d2bc2f764376a056df59bfe |
--- /dev/null |
+++ b/third_party/wtl/include/atlddx.h |
@@ -0,0 +1,621 @@ |
+// Windows Template Library - WTL version 8.0 |
+// Copyright (C) Microsoft Corporation. All rights reserved. |
+// |
+// This file is a part of the Windows Template Library. |
+// The use and distribution terms for this software are covered by the |
+// Microsoft Permissive License (Ms-PL) which can be found in the file |
+// Ms-PL.txt at the root of this distribution. |
+ |
+#ifndef __ATLDDX_H__ |
+#define __ATLDDX_H__ |
+ |
+#pragma once |
+ |
+#ifndef __cplusplus |
+ #error ATL requires C++ compilation (use a .cpp suffix) |
+#endif |
+ |
+#ifndef __ATLAPP_H__ |
+ #error atlddx.h requires atlapp.h to be included first |
+#endif |
+ |
+#if defined(_ATL_USE_DDX_FLOAT) && defined(_ATL_MIN_CRT) |
+ #error Cannot use floating point DDX with _ATL_MIN_CRT defined |
+#endif // defined(_ATL_USE_DDX_FLOAT) && defined(_ATL_MIN_CRT) |
+ |
+#ifdef _ATL_USE_DDX_FLOAT |
+ #include <float.h> |
+#endif // _ATL_USE_DDX_FLOAT |
+ |
+ |
+/////////////////////////////////////////////////////////////////////////////// |
+// Classes in this file: |
+// |
+// CWinDataExchange<T> |
+ |
+ |
+namespace WTL |
+{ |
+ |
+// Constants |
+#define DDX_LOAD FALSE |
+#define DDX_SAVE TRUE |
+ |
+// DDX map macros |
+#define BEGIN_DDX_MAP(thisClass) \ |
+ BOOL DoDataExchange(BOOL bSaveAndValidate = FALSE, UINT nCtlID = (UINT)-1) \ |
+ { \ |
+ bSaveAndValidate; \ |
+ nCtlID; |
+ |
+#define DDX_TEXT(nID, var) \ |
+ if(nCtlID == (UINT)-1 || nCtlID == nID) \ |
+ { \ |
+ if(!DDX_Text(nID, var, sizeof(var), bSaveAndValidate)) \ |
+ return FALSE; \ |
+ } |
+ |
+#define DDX_TEXT_LEN(nID, var, len) \ |
+ if(nCtlID == (UINT)-1 || nCtlID == nID) \ |
+ { \ |
+ if(!DDX_Text(nID, var, sizeof(var), bSaveAndValidate, TRUE, len)) \ |
+ return FALSE; \ |
+ } |
+ |
+#define DDX_INT(nID, var) \ |
+ if(nCtlID == (UINT)-1 || nCtlID == nID) \ |
+ { \ |
+ if(!DDX_Int(nID, var, TRUE, bSaveAndValidate)) \ |
+ return FALSE; \ |
+ } |
+ |
+#define DDX_INT_RANGE(nID, var, min, max) \ |
+ if(nCtlID == (UINT)-1 || nCtlID == nID) \ |
+ { \ |
+ if(!DDX_Int(nID, var, TRUE, bSaveAndValidate, TRUE, min, max)) \ |
+ return FALSE; \ |
+ } |
+ |
+#define DDX_UINT(nID, var) \ |
+ if(nCtlID == (UINT)-1 || nCtlID == nID) \ |
+ { \ |
+ if(!DDX_Int(nID, var, FALSE, bSaveAndValidate)) \ |
+ return FALSE; \ |
+ } |
+ |
+#define DDX_UINT_RANGE(nID, var, min, max) \ |
+ if(nCtlID == (UINT)-1 || nCtlID == nID) \ |
+ { \ |
+ if(!DDX_Int(nID, var, FALSE, bSaveAndValidate, TRUE, min, max)) \ |
+ return FALSE; \ |
+ } |
+ |
+#ifdef _ATL_USE_DDX_FLOAT |
+#define DDX_FLOAT(nID, var) \ |
+ if(nCtlID == (UINT)-1 || nCtlID == nID) \ |
+ { \ |
+ if(!DDX_Float(nID, var, bSaveAndValidate)) \ |
+ return FALSE; \ |
+ } |
+ |
+#define DDX_FLOAT_RANGE(nID, var, min, max) \ |
+ if(nCtlID == (UINT)-1 || nCtlID == nID) \ |
+ { \ |
+ if(!DDX_Float(nID, var, bSaveAndValidate, TRUE, min, max)) \ |
+ return FALSE; \ |
+ } |
+#define DDX_FLOAT_P(nID, var, precision) \ |
+ if(nCtlID == (UINT)-1 || nCtlID == nID) \ |
+ { \ |
+ if(!DDX_Float(nID, var, bSaveAndValidate, FALSE, 0, 0, precision)) \ |
+ return FALSE; \ |
+ } |
+ |
+#define DDX_FLOAT_P_RANGE(nID, var, min, max, precision) \ |
+ if(nCtlID == (UINT)-1 || nCtlID == nID) \ |
+ { \ |
+ if(!DDX_Float(nID, var, bSaveAndValidate, TRUE, min, max, precision)) \ |
+ return FALSE; \ |
+ } |
+#endif // _ATL_USE_DDX_FLOAT |
+ |
+#define DDX_CONTROL(nID, obj) \ |
+ if(nCtlID == (UINT)-1 || nCtlID == nID) \ |
+ DDX_Control(nID, obj, bSaveAndValidate); |
+ |
+#define DDX_CONTROL_HANDLE(nID, obj) \ |
+ if(nCtlID == (UINT)-1 || nCtlID == nID) \ |
+ DDX_Control_Handle(nID, obj, bSaveAndValidate); |
+ |
+#define DDX_CHECK(nID, var) \ |
+ if(nCtlID == (UINT)-1 || nCtlID == nID) \ |
+ DDX_Check(nID, var, bSaveAndValidate); |
+ |
+#define DDX_RADIO(nID, var) \ |
+ if(nCtlID == (UINT)-1 || nCtlID == nID) \ |
+ DDX_Radio(nID, var, bSaveAndValidate); |
+ |
+#define END_DDX_MAP() \ |
+ return TRUE; \ |
+ } |
+ |
+ |
+/////////////////////////////////////////////////////////////////////////////// |
+// CWinDataExchange - provides support for DDX |
+ |
+template <class T> |
+class CWinDataExchange |
+{ |
+public: |
+// Data exchange method - override in your derived class |
+ BOOL DoDataExchange(BOOL /*bSaveAndValidate*/ = FALSE, UINT /*nCtlID*/ = (UINT)-1) |
+ { |
+ // this one should never be called, override it in |
+ // your derived class by implementing DDX map |
+ ATLASSERT(FALSE); |
+ return FALSE; |
+ } |
+ |
+// Helpers for validation error reporting |
+ enum _XDataType |
+ { |
+ ddxDataNull = 0, |
+ ddxDataText = 1, |
+ ddxDataInt = 2, |
+ ddxDataFloat = 3, |
+ ddxDataDouble = 4 |
+ }; |
+ |
+ struct _XTextData |
+ { |
+ int nLength; |
+ int nMaxLength; |
+ }; |
+ |
+ struct _XIntData |
+ { |
+ long nVal; |
+ long nMin; |
+ long nMax; |
+ }; |
+ |
+ struct _XFloatData |
+ { |
+ double nVal; |
+ double nMin; |
+ double nMax; |
+ }; |
+ |
+ struct _XData |
+ { |
+ _XDataType nDataType; |
+ union |
+ { |
+ _XTextData textData; |
+ _XIntData intData; |
+ _XFloatData floatData; |
+ }; |
+ }; |
+ |
+// Text exchange |
+ BOOL DDX_Text(UINT nID, LPTSTR lpstrText, int cbSize, BOOL bSave, BOOL bValidate = FALSE, int nLength = 0) |
+ { |
+ T* pT = static_cast<T*>(this); |
+ BOOL bSuccess = TRUE; |
+ |
+ if(bSave) |
+ { |
+ HWND hWndCtrl = pT->GetDlgItem(nID); |
+ int nRetLen = ::GetWindowText(hWndCtrl, lpstrText, cbSize / sizeof(TCHAR)); |
+ if(nRetLen < ::GetWindowTextLength(hWndCtrl)) |
+ bSuccess = FALSE; |
+ } |
+ else |
+ { |
+ ATLASSERT(!bValidate || lstrlen(lpstrText) <= nLength); |
+ bSuccess = pT->SetDlgItemText(nID, lpstrText); |
+ } |
+ |
+ if(!bSuccess) |
+ { |
+ pT->OnDataExchangeError(nID, bSave); |
+ } |
+ else if(bSave && bValidate) // validation |
+ { |
+ ATLASSERT(nLength > 0); |
+ if(lstrlen(lpstrText) > nLength) |
+ { |
+ _XData data = { ddxDataText }; |
+ data.textData.nLength = lstrlen(lpstrText); |
+ data.textData.nMaxLength = nLength; |
+ pT->OnDataValidateError(nID, bSave, data); |
+ bSuccess = FALSE; |
+ } |
+ } |
+ return bSuccess; |
+ } |
+ |
+ BOOL DDX_Text(UINT nID, BSTR& bstrText, int /*cbSize*/, BOOL bSave, BOOL bValidate = FALSE, int nLength = 0) |
+ { |
+ T* pT = static_cast<T*>(this); |
+ BOOL bSuccess = TRUE; |
+ |
+ if(bSave) |
+ { |
+ bSuccess = pT->GetDlgItemText(nID, bstrText); |
+ } |
+ else |
+ { |
+ USES_CONVERSION; |
+ LPTSTR lpstrText = OLE2T(bstrText); |
+ ATLASSERT(!bValidate || lstrlen(lpstrText) <= nLength); |
+ bSuccess = pT->SetDlgItemText(nID, lpstrText); |
+ } |
+ |
+ if(!bSuccess) |
+ { |
+ pT->OnDataExchangeError(nID, bSave); |
+ } |
+ else if(bSave && bValidate) // validation |
+ { |
+ ATLASSERT(nLength > 0); |
+ if((int)::SysStringLen(bstrText) > nLength) |
+ { |
+ _XData data = { ddxDataText }; |
+ data.textData.nLength = (int)::SysStringLen(bstrText); |
+ data.textData.nMaxLength = nLength; |
+ pT->OnDataValidateError(nID, bSave, data); |
+ bSuccess = FALSE; |
+ } |
+ } |
+ return bSuccess; |
+ } |
+ |
+ BOOL DDX_Text(UINT nID, ATL::CComBSTR& bstrText, int /*cbSize*/, BOOL bSave, BOOL bValidate = FALSE, int nLength = 0) |
+ { |
+ T* pT = static_cast<T*>(this); |
+ BOOL bSuccess = TRUE; |
+ |
+ if(bSave) |
+ { |
+ bSuccess = pT->GetDlgItemText(nID, (BSTR&)bstrText); |
+ } |
+ else |
+ { |
+ USES_CONVERSION; |
+ LPTSTR lpstrText = OLE2T(bstrText); |
+ ATLASSERT(!bValidate || lstrlen(lpstrText) <= nLength); |
+ bSuccess = pT->SetDlgItemText(nID, lpstrText); |
+ } |
+ |
+ if(!bSuccess) |
+ { |
+ pT->OnDataExchangeError(nID, bSave); |
+ } |
+ else if(bSave && bValidate) // validation |
+ { |
+ ATLASSERT(nLength > 0); |
+ if((int)bstrText.Length() > nLength) |
+ { |
+ _XData data = { ddxDataText }; |
+ data.textData.nLength = (int)bstrText.Length(); |
+ data.textData.nMaxLength = nLength; |
+ pT->OnDataValidateError(nID, bSave, data); |
+ bSuccess = FALSE; |
+ } |
+ } |
+ return bSuccess; |
+ } |
+ |
+#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) |
+ BOOL DDX_Text(UINT nID, _CSTRING_NS::CString& strText, int /*cbSize*/, BOOL bSave, BOOL bValidate = FALSE, int nLength = 0) |
+ { |
+ T* pT = static_cast<T*>(this); |
+ BOOL bSuccess = TRUE; |
+ |
+ if(bSave) |
+ { |
+ HWND hWndCtrl = pT->GetDlgItem(nID); |
+ int nLen = ::GetWindowTextLength(hWndCtrl); |
+ int nRetLen = -1; |
+ LPTSTR lpstr = strText.GetBufferSetLength(nLen); |
+ if(lpstr != NULL) |
+ { |
+ nRetLen = ::GetWindowText(hWndCtrl, lpstr, nLen + 1); |
+ strText.ReleaseBuffer(); |
+ } |
+ if(nRetLen < nLen) |
+ bSuccess = FALSE; |
+ } |
+ else |
+ { |
+ bSuccess = pT->SetDlgItemText(nID, strText); |
+ } |
+ |
+ if(!bSuccess) |
+ { |
+ pT->OnDataExchangeError(nID, bSave); |
+ } |
+ else if(bSave && bValidate) // validation |
+ { |
+ ATLASSERT(nLength > 0); |
+ if(strText.GetLength() > nLength) |
+ { |
+ _XData data = { ddxDataText }; |
+ data.textData.nLength = strText.GetLength(); |
+ data.textData.nMaxLength = nLength; |
+ pT->OnDataValidateError(nID, bSave, data); |
+ bSuccess = FALSE; |
+ } |
+ } |
+ return bSuccess; |
+ } |
+#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) |
+ |
+// Numeric exchange |
+ template <class Type> |
+ BOOL DDX_Int(UINT nID, Type& nVal, BOOL bSigned, BOOL bSave, BOOL bValidate = FALSE, Type nMin = 0, Type nMax = 0) |
+ { |
+ T* pT = static_cast<T*>(this); |
+ BOOL bSuccess = TRUE; |
+ |
+ if(bSave) |
+ { |
+ nVal = (Type)pT->GetDlgItemInt(nID, &bSuccess, bSigned); |
+ } |
+ else |
+ { |
+ ATLASSERT(!bValidate || nVal >= nMin && nVal <= nMax); |
+ bSuccess = pT->SetDlgItemInt(nID, nVal, bSigned); |
+ } |
+ |
+ if(!bSuccess) |
+ { |
+ pT->OnDataExchangeError(nID, bSave); |
+ } |
+ else if(bSave && bValidate) // validation |
+ { |
+ ATLASSERT(nMin != nMax); |
+ if(nVal < nMin || nVal > nMax) |
+ { |
+ _XData data = { ddxDataInt }; |
+ data.intData.nVal = (long)nVal; |
+ data.intData.nMin = (long)nMin; |
+ data.intData.nMax = (long)nMax; |
+ pT->OnDataValidateError(nID, bSave, data); |
+ bSuccess = FALSE; |
+ } |
+ } |
+ return bSuccess; |
+ } |
+ |
+// Float exchange |
+#ifdef _ATL_USE_DDX_FLOAT |
+ static BOOL _AtlSimpleFloatParse(LPCTSTR lpszText, double& d) |
+ { |
+ ATLASSERT(lpszText != NULL); |
+ while (*lpszText == _T(' ') || *lpszText == _T('\t')) |
+ lpszText++; |
+ |
+ TCHAR chFirst = lpszText[0]; |
+ d = _tcstod(lpszText, (LPTSTR*)&lpszText); |
+ if (d == 0.0 && chFirst != _T('0')) |
+ return FALSE; // could not convert |
+ while (*lpszText == _T(' ') || *lpszText == _T('\t')) |
+ lpszText++; |
+ |
+ if (*lpszText != _T('\0')) |
+ return FALSE; // not terminated properly |
+ |
+ return TRUE; |
+ } |
+ |
+ BOOL DDX_Float(UINT nID, float& nVal, BOOL bSave, BOOL bValidate = FALSE, float nMin = 0.F, float nMax = 0.F, int nPrecision = FLT_DIG) |
+ { |
+ T* pT = static_cast<T*>(this); |
+ BOOL bSuccess = TRUE; |
+ const int cchBuff = 32; |
+ TCHAR szBuff[cchBuff] = { 0 }; |
+ |
+ if(bSave) |
+ { |
+ pT->GetDlgItemText(nID, szBuff, cchBuff); |
+ double d = 0; |
+ if(_AtlSimpleFloatParse(szBuff, d)) |
+ nVal = (float)d; |
+ else |
+ bSuccess = FALSE; |
+ } |
+ else |
+ { |
+ ATLASSERT(!bValidate || nVal >= nMin && nVal <= nMax); |
+ SecureHelper::sprintf_x(szBuff, cchBuff, _T("%.*g"), nPrecision, nVal); |
+ bSuccess = pT->SetDlgItemText(nID, szBuff); |
+ } |
+ |
+ if(!bSuccess) |
+ { |
+ pT->OnDataExchangeError(nID, bSave); |
+ } |
+ else if(bSave && bValidate) // validation |
+ { |
+ ATLASSERT(nMin != nMax); |
+ if(nVal < nMin || nVal > nMax) |
+ { |
+ _XData data = { ddxDataFloat }; |
+ data.floatData.nVal = (double)nVal; |
+ data.floatData.nMin = (double)nMin; |
+ data.floatData.nMax = (double)nMax; |
+ pT->OnDataValidateError(nID, bSave, data); |
+ bSuccess = FALSE; |
+ } |
+ } |
+ return bSuccess; |
+ } |
+ |
+ BOOL DDX_Float(UINT nID, double& nVal, BOOL bSave, BOOL bValidate = FALSE, double nMin = 0., double nMax = 0., int nPrecision = DBL_DIG) |
+ { |
+ T* pT = static_cast<T*>(this); |
+ BOOL bSuccess = TRUE; |
+ const int cchBuff = 32; |
+ TCHAR szBuff[cchBuff] = { 0 }; |
+ |
+ if(bSave) |
+ { |
+ pT->GetDlgItemText(nID, szBuff, cchBuff); |
+ double d = 0; |
+ if(_AtlSimpleFloatParse(szBuff, d)) |
+ nVal = d; |
+ else |
+ bSuccess = FALSE; |
+ } |
+ else |
+ { |
+ ATLASSERT(!bValidate || nVal >= nMin && nVal <= nMax); |
+ SecureHelper::sprintf_x(szBuff, cchBuff, _T("%.*g"), nPrecision, nVal); |
+ bSuccess = pT->SetDlgItemText(nID, szBuff); |
+ } |
+ |
+ if(!bSuccess) |
+ { |
+ pT->OnDataExchangeError(nID, bSave); |
+ } |
+ else if(bSave && bValidate) // validation |
+ { |
+ ATLASSERT(nMin != nMax); |
+ if(nVal < nMin || nVal > nMax) |
+ { |
+ _XData data = { ddxDataFloat }; |
+ data.floatData.nVal = nVal; |
+ data.floatData.nMin = nMin; |
+ data.floatData.nMax = nMax; |
+ pT->OnDataValidateError(nID, bSave, data); |
+ bSuccess = FALSE; |
+ } |
+ } |
+ return bSuccess; |
+ } |
+#endif // _ATL_USE_DDX_FLOAT |
+ |
+// Full control subclassing (for CWindowImpl derived controls) |
+ template <class TControl> |
+ void DDX_Control(UINT nID, TControl& ctrl, BOOL bSave) |
+ { |
+ if(!bSave && ctrl.m_hWnd == NULL) |
+ { |
+ T* pT = static_cast<T*>(this); |
+ ctrl.SubclassWindow(pT->GetDlgItem(nID)); |
+ } |
+ } |
+ |
+// Simple control attaching (for HWND wrapper controls) |
+ template <class TControl> |
+ void DDX_Control_Handle(UINT nID, TControl& ctrl, BOOL bSave) |
+ { |
+ if(!bSave && ctrl.m_hWnd == NULL) |
+ { |
+ T* pT = static_cast<T*>(this); |
+ ctrl = pT->GetDlgItem(nID); |
+ } |
+ } |
+ |
+// Control state |
+ void DDX_Check(UINT nID, int& nValue, BOOL bSave) |
+ { |
+ T* pT = static_cast<T*>(this); |
+ HWND hWndCtrl = pT->GetDlgItem(nID); |
+ if(bSave) |
+ { |
+ nValue = (int)::SendMessage(hWndCtrl, BM_GETCHECK, 0, 0L); |
+ ATLASSERT(nValue >= 0 && nValue <= 2); |
+ } |
+ else |
+ { |
+ if(nValue < 0 || nValue > 2) |
+ { |
+ ATLTRACE2(atlTraceUI, 0, _T("ATL: Warning - dialog data checkbox value (%d) out of range.\n"), nValue); |
+ nValue = 0; // default to off |
+ } |
+ ::SendMessage(hWndCtrl, BM_SETCHECK, nValue, 0L); |
+ } |
+ } |
+ |
+ // variant that supports bool (checked/not-checked, no intermediate state) |
+ void DDX_Check(UINT nID, bool& bCheck, BOOL bSave) |
+ { |
+ int nValue = bCheck ? 1 : 0; |
+ DDX_Check(nID, nValue, bSave); |
+ |
+ if(bSave) |
+ { |
+ if(nValue == 2) |
+ ATLTRACE2(atlTraceUI, 0, _T("ATL: Warning - checkbox state (%d) out of supported range.\n"), nValue); |
+ bCheck = (nValue == 1); |
+ } |
+ } |
+ |
+ void DDX_Radio(UINT nID, int& nValue, BOOL bSave) |
+ { |
+ T* pT = static_cast<T*>(this); |
+ HWND hWndCtrl = pT->GetDlgItem(nID); |
+ ATLASSERT(hWndCtrl != NULL); |
+ |
+ // must be first in a group of auto radio buttons |
+ ATLASSERT(::GetWindowLong(hWndCtrl, GWL_STYLE) & WS_GROUP); |
+ ATLASSERT(::SendMessage(hWndCtrl, WM_GETDLGCODE, 0, 0L) & DLGC_RADIOBUTTON); |
+ |
+ if(bSave) |
+ nValue = -1; // value if none found |
+ |
+ // walk all children in group |
+ int nButton = 0; |
+ do |
+ { |
+ if(::SendMessage(hWndCtrl, WM_GETDLGCODE, 0, 0L) & DLGC_RADIOBUTTON) |
+ { |
+ // control in group is a radio button |
+ if(bSave) |
+ { |
+ if(::SendMessage(hWndCtrl, BM_GETCHECK, 0, 0L) != 0) |
+ { |
+ ATLASSERT(nValue == -1); // only set once |
+ nValue = nButton; |
+ } |
+ } |
+ else |
+ { |
+ // select button |
+ ::SendMessage(hWndCtrl, BM_SETCHECK, (nButton == nValue), 0L); |
+ } |
+ nButton++; |
+ } |
+ else |
+ { |
+ ATLTRACE2(atlTraceUI, 0, _T("ATL: Warning - skipping non-radio button in group.\n")); |
+ } |
+ hWndCtrl = ::GetWindow(hWndCtrl, GW_HWNDNEXT); |
+ } |
+ while (hWndCtrl != NULL && !(GetWindowLong(hWndCtrl, GWL_STYLE) & WS_GROUP)); |
+ } |
+ |
+// Overrideables |
+ void OnDataExchangeError(UINT nCtrlID, BOOL /*bSave*/) |
+ { |
+ // Override to display an error message |
+ ::MessageBeep((UINT)-1); |
+ T* pT = static_cast<T*>(this); |
+ ::SetFocus(pT->GetDlgItem(nCtrlID)); |
+ } |
+ |
+ void OnDataValidateError(UINT nCtrlID, BOOL /*bSave*/, _XData& /*data*/) |
+ { |
+ // Override to display an error message |
+ ::MessageBeep((UINT)-1); |
+ T* pT = static_cast<T*>(this); |
+ ::SetFocus(pT->GetDlgItem(nCtrlID)); |
+ } |
+}; |
+ |
+}; // namespace WTL |
+ |
+#endif // __ATLDDX_H__ |