wine/dlls/twain/dsm_ctrl.c
Shi Quan He 6b0720f5d6 Started TWAIN implementation.
Marcus Meissner <marcus@jet.franken.de>
Merged into WineHQ, made sure it works without SANE.
2002-03-21 02:58:39 +00:00

396 lines
11 KiB
C

/*
* TWAIN32 Source Manager
*
* Copyright 2000 Corel Corporation
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include <stdlib.h>
#include "winbase.h"
#include "twain.h"
#include "twain_i.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(twain);
/* DG_CONTROL/DAT_IDENTITY/MSG_CLOSEDS */
TW_UINT16 TWAIN_CloseDS (pTW_IDENTITY pOrigin, TW_MEMREF pData)
{
#ifndef HAVE_SANE
DSM_twCC = TWCC_NODS;
return TWRC_FAILURE;
#else
TW_UINT16 twRC = TWRC_SUCCESS;
pTW_IDENTITY pIdentity = (pTW_IDENTITY) pData;
activeDS *currentDS = NULL, *prevDS = NULL;
TRACE ("DG_CONTROL/DAT_IDENTITY/MSG_CLOSEDS\n");
for (currentDS = activeSources; currentDS; currentDS = currentDS->next)
{
if (currentDS->identity.Id == pIdentity->Id)
break;
prevDS = currentDS;
}
if (currentDS)
{
/* Only valid to close a data source if it is in state 4 */
if (currentDS->currentState == 4)
{
sane_close (currentDS->deviceHandle);
/* remove the data source from active data source list */
if (prevDS)
prevDS->next = currentDS->next;
else
activeSources = currentDS->next;
HeapFree (GetProcessHeap(), 0, currentDS);
twRC = TWRC_SUCCESS;
DSM_twCC = TWCC_SUCCESS;
}
else
{
twRC = TWRC_FAILURE;
DSM_twCC = TWCC_SEQERROR;
}
}
else
{
twRC = TWRC_FAILURE;
DSM_twCC = TWCC_NODS;
}
return twRC;
#endif
}
/* DG_CONTROL/DAT_IDENTITY/MSG_GETDEFAULT */
TW_UINT16 TWAIN_IdentityGetDefault (pTW_IDENTITY pOrigin, TW_MEMREF pData)
{
#ifndef HAVE_SANE
DSM_twCC = TWCC_NODS;
return TWRC_FAILURE;
#else
TW_UINT16 twRC = TWRC_SUCCESS;
pTW_IDENTITY pSourceIdentity = (pTW_IDENTITY) pData;
TRACE("DG_CONTROL/DAT_IDENTITY/MSG_GETDEFAULT\n");
if (!device_list)
{
if ((sane_get_devices (&device_list, SANE_FALSE) != SANE_STATUS_GOOD))
{
DSM_twCC = TWCC_NODS;
return TWRC_FAILURE;
}
}
/* FIXME: the default device is not necessarily the first device. *
* Users should be able to choose the default device */
if (device_list && device_list[0])
{
pSourceIdentity->Id = DSM_sourceId ++;
strcpy (pSourceIdentity->ProductName, device_list[0]->name);
strcpy (pSourceIdentity->Manufacturer, device_list[0]->vendor);
strcpy (pSourceIdentity->ProductFamily, device_list[0]->model);
pSourceIdentity->ProtocolMajor = TWON_PROTOCOLMAJOR;
pSourceIdentity->ProtocolMinor = TWON_PROTOCOLMINOR;
twRC = TWRC_SUCCESS;
DSM_twCC = TWCC_SUCCESS;
}
else
{
twRC = TWRC_FAILURE;
DSM_twCC = TWCC_NODS;
}
return twRC;
#endif
}
/* DG_CONTROL/DAT_IDENTITY/MSG_GETFIRST */
TW_UINT16 TWAIN_IdentityGetFirst (pTW_IDENTITY pOrigin, TW_MEMREF pData)
{
#ifndef HAVE_SANE
DSM_twCC = TWCC_NODS;
return TWRC_FAILURE;
#else
TW_UINT16 twRC = TWRC_SUCCESS;
pTW_IDENTITY pSourceIdentity;/* = (pTW_IDENTITY) pData;*/
SANE_Status status;
TRACE ("DG_CONTROL/DAT_IDENTITY/MSG_GETFIRST\n");
status = sane_get_devices (&device_list, SANE_FALSE);
if (status == SANE_STATUS_GOOD)
{
if (device_list[0])
{
pSourceIdentity->Id = DSM_sourceId ++;
strcpy (pSourceIdentity->ProductName, device_list[0]->name);
strcpy (pSourceIdentity->Manufacturer, device_list[0]->vendor);
strcpy (pSourceIdentity->ProductFamily, device_list[0]->model);
pSourceIdentity->ProtocolMajor = TWON_PROTOCOLMAJOR;
pSourceIdentity->ProtocolMinor = TWON_PROTOCOLMINOR;
}
DSM_currentDevice = 1;
twRC = TWRC_SUCCESS;
DSM_twCC = TWCC_SUCCESS;
}
else if (status == SANE_STATUS_NO_MEM)
{
twRC = TWRC_FAILURE;
DSM_twCC = TWCC_LOWMEMORY;
}
else
{
WARN("sane_get_devices() failed: %s\n", sane_strstatus (status));
twRC = TWRC_FAILURE;
DSM_twCC = TWCC_NODS;
}
return twRC;
#endif
}
/* DG_CONTROL/DAT_IDENTITY/MSG_GETNEXT */
TW_UINT16 TWAIN_IdentityGetNext (pTW_IDENTITY pOrigin, TW_MEMREF pData)
{
#ifndef HAVE_SANE
DSM_twCC = TWCC_SUCCESS;
return TWRC_ENDOFLIST;
#else
TW_UINT16 twRC = TWRC_SUCCESS;
pTW_IDENTITY pSourceIdentity = (pTW_IDENTITY) pData;
TRACE("DG_CONTROL/DAT_IDENTITY/MSG_GETNEXT\n");
if (device_list && device_list[DSM_currentDevice])
{
pSourceIdentity->Id = DSM_sourceId ++;
strcpy (pSourceIdentity->ProductName, device_list[DSM_currentDevice]->name);
strcpy (pSourceIdentity->Manufacturer, device_list[DSM_currentDevice]->vendor);
strcpy (pSourceIdentity->ProductFamily, device_list[DSM_currentDevice]->model);
pSourceIdentity->ProtocolMajor = TWON_PROTOCOLMAJOR;
pSourceIdentity->ProtocolMinor = TWON_PROTOCOLMINOR;
DSM_currentDevice ++;
twRC = TWRC_SUCCESS;
DSM_twCC = TWCC_SUCCESS;
}
else
{
DSM_twCC = TWCC_SUCCESS;
twRC = TWRC_ENDOFLIST;
}
return twRC;
#endif
}
/* DG_CONTROL/DAT_IDENTITY/MSG_OPENDS */
TW_UINT16 TWAIN_OpenDS (pTW_IDENTITY pOrigin, TW_MEMREF pData)
{
#ifndef HAVE_SANE
DSM_twCC = TWCC_NODS;
return TWRC_FAILURE;
#else
TW_UINT16 twRC = TWRC_SUCCESS, i = 0;
pTW_IDENTITY pIdentity = (pTW_IDENTITY) pData;
activeDS *newSource;
SANE_Status status;
TRACE("DG_CONTROL/DAT_IDENTITY/MSG_OPENDS\n");
if (DSM_currentState != 3)
{
DSM_twCC = TWCC_SEQERROR;
return TWRC_FAILURE;
}
if (!device_list &&
(sane_get_devices (&device_list, SANE_FALSE) != SANE_STATUS_GOOD))
{
DSM_twCC = TWCC_NODS;
return TWRC_FAILURE;
}
if (pIdentity->ProductName[0] != '\0')
{
/* Make sure the source to be open exists in the device list */
for (i = 0; device_list[i]; i ++)
{
if (strcmp (device_list[i]->name, pIdentity->ProductName) == 0)
break;
}
}
if (device_list[i])
{
/* the source is found in the device list */
newSource = HeapAlloc (GetProcessHeap(), 0, sizeof (activeDS));
if (newSource)
{
status = sane_open(device_list[i]->name,&newSource->deviceHandle);
if (status == SANE_STATUS_GOOD)
{
/* Assign name and id for the opened data source */
strcpy (pIdentity->ProductName, device_list[i]->name);
pIdentity->Id = DSM_sourceId ++;
/* add the data source to an internal active source list */
newSource->next = activeSources;
newSource->identity.Id = pIdentity->Id;
strcpy (newSource->identity.ProductName, pIdentity->ProductName);
newSource->currentState = 4; /*transition into state 4*/
newSource->twCC = TWCC_SUCCESS;
activeSources = newSource;
twRC = TWRC_SUCCESS;
DSM_twCC = TWCC_SUCCESS;
}
else
{
twRC = TWRC_FAILURE;
DSM_twCC = TWCC_OPERATIONERROR;
}
}
else
{
twRC = TWRC_FAILURE;
DSM_twCC = TWCC_LOWMEMORY;
}
}
else
{
twRC = TWRC_FAILURE;
DSM_twCC = TWCC_NODS;
}
return twRC;
#endif
}
/* DG_CONTROL/DAT_IDENTITY/MSG_USERSELECT */
TW_UINT16 TWAIN_UserSelect (pTW_IDENTITY pOrigin, TW_MEMREF pData)
{
#ifndef HAVE_SANE
return TWRC_SUCCESS;
#else
TW_UINT16 twRC = TWRC_SUCCESS;
TRACE("DG_CONTROL/DAT_IDENTITY/MSG_USERSELECT\n");
/* FIXME: we should replace xscanimage with our own User Select UI */
system("xscanimage");
DSM_twCC = TWCC_SUCCESS;
return twRC;
#endif
}
/* DG_CONTROL/DAT_PARENT/MSG_CLOSEDSM */
TW_UINT16 TWAIN_CloseDSM (pTW_IDENTITY pOrigin, TW_MEMREF pData)
{
#ifndef HAVE_SANE
return TWRC_FAILURE;
#else
TW_UINT16 twRC = TWRC_SUCCESS;
activeDS *currentDS = activeSources, *nextDS;
TRACE("DG_CONTROL/DAT_PARENT/MSG_CLOSEDSM\n");
if (DSM_currentState == 3)
{
sane_exit ();
DSM_initialized = FALSE;
DSM_parentHWND = 0;
DSM_currentState = 2;
/* If there are data sources still open, close them now. */
while (currentDS != NULL)
{
nextDS = currentDS->next;
sane_close (currentDS->deviceHandle);
HeapFree (GetProcessHeap(), 0, currentDS);
currentDS = nextDS;
}
activeSources = NULL;
DSM_twCC = TWCC_SUCCESS;
twRC = TWRC_SUCCESS;
}
else
{
DSM_twCC = TWCC_SEQERROR;
twRC = TWRC_FAILURE;
}
return twRC;
#endif
}
/* DG_CONTROL/DAT_PARENT/MSG_OPENDSM */
TW_UINT16 TWAIN_OpenDSM (pTW_IDENTITY pOrigin, TW_MEMREF pData)
{
#ifndef HAVE_SANE
return TWRC_FAILURE;
#else
TW_UINT16 twRC = TWRC_SUCCESS;
SANE_Status status;
SANE_Int version_code;
TRACE("DG_CONTROL/DAT_PARENT/MSG_OPENDSM\n");
if (DSM_currentState == 2)
{
if (!DSM_initialized)
{
DSM_initialized = TRUE;
status = sane_init (&version_code, NULL);
device_list = NULL;
DSM_currentDevice = 0;
DSM_sourceId = 0;
}
DSM_parentHWND = *pData;
DSM_currentState = 3; /* transition to state 3 */
DSM_twCC = TWCC_SUCCESS;
twRC = TWRC_SUCCESS;
}
else
{
/* operation invoked in invalid state */
DSM_twCC = TWCC_SEQERROR;
twRC = TWRC_FAILURE;
}
return twRC;
#endif
}
/* DG_CONTROL/DAT_STATUS/MSG_GET */
TW_UINT16 TWAIN_GetDSMStatus (pTW_IDENTITY pOrigin, TW_MEMREF pData)
{
pTW_STATUS pSourceStatus = (pTW_STATUS) pData;
TRACE ("DG_CONTROL/DAT_STATUS/MSG_GET\n");
pSourceStatus->ConditionCode = DSM_twCC;
DSM_twCC = TWCC_SUCCESS; /* clear the condition code */
return TWRC_SUCCESS;
}