twain2/hugaotwainds/TWAINContainerFix32.cpp

412 lines
11 KiB
C++
Raw Permalink Blame History

/***************************************************************************
* Copyright <20> 2007 TWAIN Working Group:
* Adobe Systems Incorporated, AnyDoc Software Inc., Eastman Kodak Company,
* Fujitsu Computer Products of America, JFL Peripheral Solutions Inc.,
* Ricoh Corporation, and Xerox Corporation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the TWAIN Working Group nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY TWAIN Working Group ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL TWAIN Working Group BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
***************************************************************************/
/**
* @file TWAINContainerFix32.cpp
* Fix32 Container class for negotiating capabilities.
* @author TWAIN Working Group
* @date April 2007
*/
#include "stdafx.h"
#include "CommonDS.h"
#include <algorithm>
#include <float.h>
CTWAINContainerFix32::CTWAINContainerFix32(const TW_UINT16 _unCapID,
const TW_UINT16 _unGetType,
const TW_INT32 _nSupportedQueries/* = TWQC_ALL*/,
const TW_UINT16 _unGetCurrentType/* = TWON_ONEVALUE*/,
const TW_UINT16 _unGetDefaultType/* = TWON_ONEVALUE*/)
: CTWAINContainer(_unCapID, TWTY_FIX32, _unGetType, _nSupportedQueries,_unGetCurrentType,_unGetDefaultType)
{
}
CTWAINContainerFix32::~CTWAINContainerFix32()
{
}
TW_HANDLE CTWAINContainerFix32::GetContainer(const TW_UINT16 _unMsg)
{
TW_HANDLE hContainer = 0;
TW_UINT16 unGetType=TWON_ONEVALUE;
switch(_unMsg)
{
case MSG_GET:
unGetType = m_unGetType;
break;
case MSG_GETCURRENT:
unGetType = m_unGetCurrentType;
break;
case MSG_GETDEFAULT:
unGetType = m_unGetDefaultType;
break;
}
switch(unGetType)
{
default:
case TWON_ONEVALUE:
{
hContainer = _DSM_Alloc(sizeof(TW_ONEVALUE_FIX32));
if(0 != hContainer)
{
pTW_ONEVALUE_FIX32 pCap = (pTW_ONEVALUE_FIX32)_DSM_LockMemory(hContainer);
pCap->ItemType = TWTY_FIX32;
// If the Cap has been constrained the default may only be in the m_listFloatsDefault.
const float flVal = (MSG_GETDEFAULT == _unMsg)?m_listFloatsDefault[m_nDefault]:m_listFloats[m_nCurrent];
pCap->Item = FloatToFIX32(flVal);
_DSM_UnlockMemory(hContainer);
}
}
break;
case TWON_ENUMERATION:
{
hContainer = _DSM_Alloc(sizeof(TW_ENUMERATION_FIX32) + (sizeof(TW_FIX32) * (m_listFloats.size()-1))); // -1 because already contains 1 element
if(0 != hContainer)
{
pTW_ENUMERATION_FIX32 pCap = (pTW_ENUMERATION_FIX32)_DSM_LockMemory(hContainer);
pCap->ItemType = TWTY_FIX32;
pCap->NumItems = (TW_UINT32)m_listFloats.size();
pCap->CurrentIndex = m_nCurrent;
//If the CAP has been constrained m_nDefault index might not point
// to the correct index and the index may not be valid. We need to
// find the value in the default list and see if we can find a match
// in the current list. If no match found then set to first index.
// see spec on twain.org Chap4 p73 Advanced Application Implementation |
// Capabilities | Constrained Capabilities and Message Responses | MSG_SET
const float flVal = m_listFloatsDefault[m_nDefault];
int nIndex = getIndexForValue(flVal);
if(nIndex != -1)
{
pCap->DefaultIndex = nIndex;
}
else
{
// We use the first index. We could try transversing through the
// list and finding the closest match in value. But either way
// the application should not be using this value.
pCap->DefaultIndex = 0;
}
for(TW_UINT32 x = 0; x < pCap->NumItems; ++x)
{
pCap->ItemList[x] = FloatToFIX32(m_listFloats[x]);
}
_DSM_UnlockMemory(hContainer);
}
}
break;
case TWON_ARRAY:
{
hContainer = _DSM_Alloc(sizeof(TW_ARRAY_FIX32) + (sizeof(TW_FIX32) * (m_listFloats.size()-1))); // -1 because a TW_ARRAY_FIX32 already includes 1 element
if(0 != hContainer)
{
pTW_ARRAY_FIX32 pCap = (pTW_ARRAY_FIX32)_DSM_LockMemory(hContainer);
pCap->ItemType = m_unItemType;
pCap->NumItems = (TW_UINT32)m_listFloats.size();
for(TW_UINT32 x = 0; x < pCap->NumItems; ++x)
{
pCap->ItemList[x] = FloatToFIX32(m_listFloats[x]);
}
_DSM_UnlockMemory(hContainer);
}
}
}
return hContainer;
}
bool CTWAINContainerFix32::isValidType(const TW_UINT16 _unTWType)
{
bool bret = false;
if(TWTY_FIX32 == _unTWType)
{
bret = true;
}
return bret;
}
TW_INT16 CTWAINContainerFix32::Set(pTW_CAPABILITY _pCap, TW_INT16 &Condition)
{
TW_INT16 twrc = TWRC_SUCCESS;
Condition = TWCC_SUCCESS;
if(TWON_ONEVALUE == _pCap->ConType)
{
pTW_ONEVALUE_FIX32 pCap = (pTW_ONEVALUE_FIX32)_DSM_LockMemory(_pCap->hContainer);
if(isValidType(pCap->ItemType))
{
float flVal = FIX32ToFloat(pCap->Item);
switch(m_unGetType)
{
case TWON_ONEVALUE:
{
m_listFloats.clear();
m_listFloats.push_back(flVal);
m_nCurrent = 0;
}
break;
case TWON_ENUMERATION:
{
int nVal = -1;
if((nVal = getIndexForValue(flVal)) >= 0)
{
m_nCurrent = nVal;
}
else
{
twrc = TWRC_FAILURE;
Condition = TWCC_BADVALUE;
}
}
break;
//case TWON_ARRAY:
//break;
//case TWON_RANGE:
//break;
default:
twrc = TWRC_FAILURE;
Condition = TWCC_CAPBADOPERATION;
break;
}
}
_DSM_UnlockMemory(_pCap->hContainer);
}
else if(TWON_ENUMERATION == _pCap->ConType)
{
pTW_ENUMERATION_FIX32 pCap = (pTW_ENUMERATION_FIX32)_DSM_LockMemory(_pCap->hContainer);
if(isValidType(pCap->ItemType))
{
int nNewCurrentIndex = pCap->CurrentIndex;
FloatVector::iterator iter;
bool bListCleared = false; // We only want to crear the current list if we are passed
// valid data, and only clear it once through the loop of testing
float flVal;
for(TW_UINT32 x = 0; x < pCap->NumItems; ++x)
{
flVal = FIX32ToFloat(pCap->ItemList[x]);
// only set the value if it exists in m_listFloatsDefault
iter = find(m_listFloatsDefault.begin(), m_listFloatsDefault.end(), flVal);
if(iter != m_listFloatsDefault.end())
{
// We have valid data
if(!bListCleared)
{
// only clear the list if we have not done so already
m_listFloats.clear();
bListCleared = true;
}
// only add it if it was not added already
iter = find(m_listFloats.begin(), m_listFloats.end(), flVal);
if(iter == m_listFloats.end())
{
m_listFloats.push_back(flVal);
}
else
{
if(x < pCap->CurrentIndex)
{
nNewCurrentIndex--;
}
twrc = TWRC_CHECKSTATUS;
Condition = TWCC_BADVALUE;
}
}
else
{
// if the index is below the current then we need to adjust what is going to be current
if(x < pCap->CurrentIndex)
{
nNewCurrentIndex--;
}
twrc = TWRC_CHECKSTATUS;
Condition = TWCC_BADVALUE;
}
}
// If the list has been cleared then there was at at least some valid data
if(bListCleared)
{
if(nNewCurrentIndex >= 0 && nNewCurrentIndex < (int)(m_listFloats.size()))
{
m_nCurrent = nNewCurrentIndex;
}
else
{
// the new current index is not in range
m_nCurrent = 0;
twrc = TWRC_CHECKSTATUS;
Condition = TWCC_BADVALUE;
}
}
else
{
twrc = TWRC_FAILURE;
Condition = TWCC_BADVALUE;
}
}
else // NOT isValidType(pCap->ItemType))
{
twrc = TWRC_FAILURE;
Condition = TWCC_CAPBADOPERATION;
}
_DSM_UnlockMemory(_pCap->hContainer);
}
else //bad container type
{
twrc = TWRC_FAILURE;
Condition = TWCC_BADVALUE;
}
return twrc;
}
bool CTWAINContainerFix32::Reset()
{
m_nCurrent = m_nDefault;
m_listFloats.clear();
const int nSize = (int)(m_listFloatsDefault.size());
for(int x = 0; x < nSize; ++x)
{
m_listFloats.push_back(m_listFloatsDefault[x]);
}
return true;
}
bool CTWAINContainerFix32::GetCurrent(float &_flVal)
{
bool bret = false;
if((m_nCurrent >= 0) && ((int)(m_listFloats.size()) > m_nCurrent))
{
_flVal = m_listFloats[m_nCurrent];
bret = true;
}
return bret;
}
bool CTWAINContainerFix32::GetDefault(float &_flVal)
{
bool bret = false;
if((m_nDefault >= 0) && ((int)(m_listFloatsDefault.size()) > m_nDefault))
{
_flVal = m_listFloatsDefault[m_nDefault];
bret = true;
}
return bret;
}
const FloatVector &CTWAINContainerFix32::GetSupported()
{
return m_listFloats;
}
bool CTWAINContainerFix32::Add(const float _flAdd, bool _bDefault /*= false*/)
{
m_listFloats.push_back(_flAdd);
m_listFloatsDefault.push_back(_flAdd);
if(m_nDefault == -1 || _bDefault)
{
m_nCurrent = m_nDefault = getIndexForValue(_flAdd);
}
return true;
}
bool CTWAINContainerFix32::SetCurrent(float _flCurr)
{
if(TWON_ONEVALUE == m_unGetType)//check before call
{
m_listFloats.clear();
m_listFloats.push_back(_flCurr);
m_nCurrent = 0;
}
else
{
int nIdx = getIndexForValue(_flCurr);
if(nIdx < 0)
{
return false;
}
m_nCurrent = nIdx;
}
return true;
}
int CTWAINContainerFix32::getIndexForValue(const float _flVal)
{
int ret = -1;
const int nSize = (int)(m_listFloats.size());
for(int x = 0; x < nSize; ++x)
{
if(_flVal >= m_listFloats[x]-1.0/65536.0 && _flVal <= m_listFloats[x]+1.0/65536.0) //@TODO remove float comparison
{
ret = x;
break;
}
}
return ret;
}