Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef WIN32
Toshihiro Shimizu 890ddd
#pragma warning(disable : 4996)
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#define TTWAINLIB_MAIN
Toshihiro Shimizu 890ddd
#include <assert.h></assert.h>
Toshihiro Shimizu 890ddd
#include <string.h></string.h>
Toshihiro Shimizu 890ddd
#include <stdlib.h></stdlib.h>
Toshihiro Shimizu 890ddd
#include <ctype.h></ctype.h>
Toshihiro Shimizu 890ddd
#include <stdio.h></stdio.h>
Toshihiro Shimizu 890ddd
#include "ttwain_state.h"
Toshihiro Shimizu 890ddd
#include "ttwain_statePD.h"
Toshihiro Shimizu 890ddd
#include "ttwain_error.h"
Toshihiro Shimizu 890ddd
#include "ttwain_win.h"
Toshihiro Shimizu 890ddd
#include "ttwain_winPD.h"
Toshihiro Shimizu 890ddd
#include "ttwain_util.h"
Toshihiro Shimizu 890ddd
#include "ttwain_utilP.h"
Toshihiro Shimizu 890ddd
#include "ttwain_conversion.h"
Toshihiro Shimizu 890ddd
#include "ttwainP.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "ttwain_global_def.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef __cplusplus
Toshihiro Shimizu 890ddd
extern "C" {
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
#ifdef MACOSX
Toshihiro Shimizu 890ddd
extern int exitTwainSession(void);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
static void TTWAIN_FreeVar(void);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#define CASE \
Toshihiro Shimizu 890ddd
	break;   \
Toshihiro Shimizu 890ddd
	case
Toshihiro Shimizu 890ddd
#define DEFAULT \
Toshihiro Shimizu 890ddd
	break;      \
Toshihiro Shimizu 890ddd
	default
Toshihiro Shimizu 890ddd
#define RELEASE_STR "5.1"
Toshihiro Shimizu 890ddd
#define TITLEBAR_STR "Toonz5.1"
Toshihiro Shimizu 890ddd
#define TwProgramName "Toonz5.1"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#define COMPANY "Digital Video"
Toshihiro Shimizu 890ddd
#define PRODUCT "TOONZ"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#define MIN(A, B) (((A) < (B)) ? (A) : (B))
Toshihiro Shimizu 890ddd
#define CEIL(x) ((int)(x) < (x) ? (int)(x) + 1 : (int)(x))
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#define PRINTF
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
/* LOCAL PROTOTYPES															                             */
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
static int TTWAIN_DoOneTransfer(void);
Toshihiro Shimizu 890ddd
static int TTWAIN_WaitForXfer(void *hwnd);
Toshihiro Shimizu 890ddd
static void *TTWAIN_WaitForNativeXfer(void *hwnd);
Toshihiro Shimizu 890ddd
static int TTWAIN_WaitForMemoryXfer(void *hwnd);
Toshihiro Shimizu 890ddd
static int TTWAIN_NativeXferHandler(void);
Toshihiro Shimizu 890ddd
static int TTWAIN_MemoryXferHandler(void);
Toshihiro Shimizu 890ddd
static int TTWAIN_AbortAllPendingXfers(void);
Toshihiro Shimizu 890ddd
static void TTWAIN_ModalEventLoop(void);
Toshihiro Shimizu 890ddd
static void TTWAIN_BreakModalLoop(void);
Toshihiro Shimizu 890ddd
static void TTWAIN_EmptyMessageQueue(void);
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
void TTWAIN_SetState(TWAINSTATE status);
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
/* int TTWAIN_LoadSourceManager(void)      <- this is in ttwain_state.h */
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/* int TTWAIN_SelectImageSource(void* hwnd) <-\
Toshihiro Shimizu 890ddd
   int TTWAIN_SelectImageSource(void* hwnd) <-|--\
Toshihiro Shimizu 890ddd
   int TTWAIN_OpenDefaultSource(void)       <-|-- these are in ttwain.h
Toshihiro Shimizu 890ddd
   int TTWAIN_CloseAll        (void *hwnd)  <-/
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/* these are local */
Toshihiro Shimizu 890ddd
static int TTWAIN_EnableSource(void *hwnd);
Toshihiro Shimizu 890ddd
int TTWAIN_MessageHook(void *lpmsg);
Toshihiro Shimizu 890ddd
static int TTWAIN_EndXfer(void);
Toshihiro Shimizu 890ddd
static int TTWAIN_DisableSource(void);
Toshihiro Shimizu 890ddd
static int TTWAIN_CloseSource(void);
Toshihiro Shimizu 890ddd
static int TTWAIN_CloseSourceManager(void *hwnd);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/* int TTWAIN_UnloadSourceManager(void)       <- this is in ttwain_state.h */
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static int TTWAIN_MGR(TUINT32 dg, TUINT32 dat, TUINT32 msg, void *pd);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#define INVERT_BYTE(START, HOWMANY)                  \
Toshihiro Shimizu 890ddd
	{                                                \
Toshihiro Shimizu 890ddd
		UCHAR *p = (START);                          \
Toshihiro Shimizu 890ddd
		unsigned int ijk;                            \
Toshihiro Shimizu 890ddd
		for (ijk = 0; ijk < (HOWMANY); ijk++, p++) { \
Toshihiro Shimizu 890ddd
			*p = ~*p;                                \
Toshihiro Shimizu 890ddd
		}                                            \
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#define BB(H, L) (H << 8 | L)
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
/*	  TWAIN STATE		 					     */
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
/*STATE 1 TO 2*/
Toshihiro Shimizu 890ddd
int TTWAIN_LoadSourceManager(void)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TTWAIN_InitVar();
Toshihiro Shimizu 890ddd
	return TTWAIN_LoadSourceManagerPD();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
/*STATE 2 TO 3*/
Toshihiro Shimizu 890ddd
int TTWAIN_OpenSourceManager(void *hwnd)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TTwainData.hwnd32SM = (TW_INT32)TTWAIN_GetValidHwnd(hwnd);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (TTWAIN_GetState() < TWAIN_SM_OPEN) {
Toshihiro Shimizu 890ddd
		if (TTWAIN_LoadSourceManager() &&
Toshihiro Shimizu 890ddd
			TTWAIN_MGR(DG_CONTROL, DAT_PARENT, MSG_OPENDSM, &TTwainData.hwnd32SM)) {
Toshihiro Shimizu 890ddd
			assert(TTWAIN_GetState() == TWAIN_SM_OPEN);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return (TTWAIN_GetState() >= TWAIN_SM_OPEN);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
/*STATE 3*/
Toshihiro Shimizu 890ddd
static TW_IDENTITY newSourceId;
Toshihiro Shimizu 890ddd
int TTWAIN_SelectImageSource(void *hwnd)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int success = FALSE;
Toshihiro Shimizu 890ddd
	TWAINSTATE entryState = TTWAIN_GetState();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (TTWAIN_GetState() >= TWAIN_SM_OPEN ||
Toshihiro Shimizu 890ddd
		TTWAIN_OpenSourceManager(hwnd)) {
Toshihiro Shimizu 890ddd
		//TW_IDENTITY	newSourceId;
Toshihiro Shimizu 890ddd
		memset(&newSourceId, 0, sizeof newSourceId);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TTWAIN_MGR(DG_CONTROL, DAT_IDENTITY, MSG_GETDEFAULT, &newSourceId);
Toshihiro Shimizu 890ddd
		/* Post the Select Source dialog */
Toshihiro Shimizu 890ddd
		success = TTWAIN_MGR(DG_CONTROL, DAT_IDENTITY, MSG_USERSELECT, &newSourceId);
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		char msg[2048];
Toshihiro Shimizu 890ddd
		sprintf(msg, "Unable to open Source Manager (%s)", DSM_FILENAME);
Toshihiro Shimizu 890ddd
		TTWAIN_ErrorBox(msg);
Toshihiro Shimizu 890ddd
		return FALSE;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (entryState < TWAIN_SM_OPEN) {
Toshihiro Shimizu 890ddd
		TTWAIN_CloseSourceManager(hwnd);
Toshihiro Shimizu 890ddd
		if (entryState < TWAIN_SM_LOADED) {
Toshihiro Shimizu 890ddd
			TTWAIN_UnloadSourceManager();
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return success;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
/*STATE 3 TO 4*/
Toshihiro Shimizu 890ddd
int TTWAIN_OpenDefaultSource(void)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TW_IDENTITY tempId;
Toshihiro Shimizu 890ddd
	int rc;
Toshihiro Shimizu 890ddd
	static int first_time = TRUE;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (TTWAIN_GetState() < TWAIN_SOURCE_OPEN) {
Toshihiro Shimizu 890ddd
		if (TTWAIN_GetState() < TWAIN_SM_OPEN && !TTWAIN_OpenSourceManager(NULL))
Toshihiro Shimizu 890ddd
			return FALSE;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		rc = TTWAIN_MGR(DG_CONTROL, DAT_IDENTITY, MSG_GETFIRST, &tempId);
Toshihiro Shimizu 890ddd
		while (rc && tempId.Id != 0) {
Toshihiro Shimizu 890ddd
			if (strcmp((char *)newSourceId.ProductName, (char *)tempId.ProductName) == 0) {
Toshihiro Shimizu 890ddd
				newSourceId = tempId;
Toshihiro Shimizu 890ddd
				break;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			rc = TTWAIN_MGR(DG_CONTROL, DAT_IDENTITY, MSG_GETNEXT, &tempId);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (TTWAIN_MGR(DG_CONTROL, DAT_IDENTITY, MSG_OPENDS, &newSourceId)) {
Toshihiro Shimizu 890ddd
			assert(TTWAIN_GetState() == TWAIN_SOURCE_OPEN);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (first_time && (TTWAIN_GetState() == TWAIN_SOURCE_OPEN)) {
Toshihiro Shimizu 890ddd
		TTWAIN_GetSupportedCaps();
Toshihiro Shimizu 890ddd
		/*first_time = FALSE;*/
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return (TTWAIN_GetState() == TWAIN_SOURCE_OPEN);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
/*STATE 4 TO 5*/
Toshihiro Shimizu 890ddd
static int TTWAIN_EnableSource(void *hwnd)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (TTWAIN_GetState() < TWAIN_SOURCE_OPEN &&
Toshihiro Shimizu 890ddd
		!TTWAIN_OpenDefaultSource())
Toshihiro Shimizu 890ddd
		return FALSE;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TTwainData.twainUI.ShowUI = TTWAIN_GetUIStatus();
Toshihiro Shimizu 890ddd
	TTwainData.twainUI.ModalUI = TTWAIN_GetModalStatus();
Toshihiro Shimizu 890ddd
	TTwainData.twainUI.hParent = (TW_HANDLE)TTWAIN_GetValidHwnd(hwnd);
Toshihiro Shimizu 890ddd
	TTWAIN_DS(DG_CONTROL, DAT_USERINTERFACE, MSG_ENABLEDS, &TTwainData.twainUI);
Toshihiro Shimizu 890ddd
	return (TTWAIN_GetState() == TWAIN_SOURCE_ENABLED);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
/*STATE 5 TO 6 TO 7*/
Toshihiro Shimizu 890ddd
int TTWAIN_MessageHook(void *lpmsg)
Toshihiro Shimizu 890ddd
/* returns TRUE if msg processed by TWAIN (source) */
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int bProcessed = FALSE;
Toshihiro Shimizu 890ddd
	//printf("%s\n", __PRETTY_FUNCTION__);
Toshihiro Shimizu 890ddd
	if (TTWAIN_GetState() >= TWAIN_SOURCE_ENABLED) {
Toshihiro Shimizu 890ddd
/* source enabled */
Toshihiro Shimizu 890ddd
#ifdef WIN32
Toshihiro Shimizu 890ddd
		TW_EVENT twEvent;
Toshihiro Shimizu 890ddd
		twEvent.pEvent = (TW_MEMREF)lpmsg;
Toshihiro Shimizu 890ddd
		twEvent.TWMessage = MSG_NULL;
Toshihiro Shimizu 890ddd
		/* see if source wants to process (eat) the message */
Toshihiro Shimizu 890ddd
		bProcessed = (TTWAIN_DS(DG_CONTROL, DAT_EVENT, MSG_PROCESSEVENT, &twEvent) == TWRC_DSEVENT);
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
		TW_EVENT twEvent;
Toshihiro Shimizu 890ddd
		twEvent.pEvent = (TW_MEMREF)0;
Toshihiro Shimizu 890ddd
		twEvent.TWMessage = (TW_UINT32)lpmsg;
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
		switch (twEvent.TWMessage) {
Toshihiro Shimizu 890ddd
		case MSG_XFERREADY:
Toshihiro Shimizu 890ddd
#ifdef MACOSX
Toshihiro Shimizu 890ddd
			TTWAIN_SetState(TWAIN_TRANSFER_READY);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
			assert(TTWAIN_GetState() == TWAIN_TRANSFER_READY);
Toshihiro Shimizu 890ddd
			TTWAIN_DoOneTransfer();
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		case MSG_CLOSEDSREQ:
Toshihiro Shimizu 890ddd
			TTWAIN_DisableSource();
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		case MSG_NULL:
Toshihiro Shimizu 890ddd
			/* no message returned from DS */
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		} /* switch */
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return bProcessed;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
/*STATE 7 TO 6 TO 5*/
Toshihiro Shimizu 890ddd
static int TTWAIN_EndXfer(void)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (TTWAIN_GetState() == TWAIN_TRANSFERRING)
Toshihiro Shimizu 890ddd
		TTWAIN_DS(DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER,
Toshihiro Shimizu 890ddd
				  &TTwainData.transferInfo.pendingXfers);
Toshihiro Shimizu 890ddd
	return (TTWAIN_GetState() < TWAIN_TRANSFERRING);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
/* STATE 5 TO 1 */
Toshihiro Shimizu 890ddd
/* 3 OP + 1 PD OP*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*STATE 5 TO 4*/
Toshihiro Shimizu 890ddd
static int TTWAIN_DisableSource(void)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TTWAIN_AbortAllPendingXfers();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if ((TTWAIN_GetState() >= TWAIN_SOURCE_ENABLED) &&
Toshihiro Shimizu 890ddd
		(TTWAIN_DS(DG_CONTROL, DAT_USERINTERFACE, MSG_DISABLEDS,
Toshihiro Shimizu 890ddd
				   &TTwainData.twainUI) == TWRC_SUCCESS)) {
Toshihiro Shimizu 890ddd
		assert(TTWAIN_GetState() == TWAIN_SOURCE_OPEN);
Toshihiro Shimizu 890ddd
		return FALSE;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	TTWAIN_EmptyMessageQueue();
Toshihiro Shimizu 890ddd
	return (TTWAIN_GetState() < TWAIN_SOURCE_ENABLED);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
/*STATE 4 TO 3*/
Toshihiro Shimizu 890ddd
static int TTWAIN_CloseSource(void)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TTwainData.resultCode = TWRC_SUCCESS;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TTWAIN_DisableSource();
Toshihiro Shimizu 890ddd
	if (TTWAIN_GetState() == TWAIN_SOURCE_OPEN &&
Toshihiro Shimizu 890ddd
		TTWAIN_MGR(DG_CONTROL, DAT_IDENTITY, MSG_CLOSEDS, &TTwainData.sourceId)) {
Toshihiro Shimizu 890ddd
		assert(TTWAIN_GetState() == TWAIN_SM_OPEN);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return (TTWAIN_GetState() <= TWAIN_SM_OPEN);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
/*STATE 3 TO 2*/
Toshihiro Shimizu 890ddd
static int TTWAIN_CloseSourceManager(void *hwnd)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TTWAIN_EmptyMessageQueue();
Toshihiro Shimizu 890ddd
	TTwainData.hwnd32SM = (TW_INT32)TTWAIN_GetValidHwnd(hwnd);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TTwainData.resultCode = TWRC_SUCCESS;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (TTWAIN_CloseSource() &&
Toshihiro Shimizu 890ddd
		TTWAIN_MGR(DG_CONTROL, DAT_PARENT, MSG_CLOSEDSM, &TTwainData.hwnd32SM)) {
Toshihiro Shimizu 890ddd
		assert(TTWAIN_GetState() == TWAIN_SM_LOADED);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return (TTWAIN_GetState() <= TWAIN_SM_LOADED);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
/*STATE 2 TO 1*/
Toshihiro Shimizu 890ddd
int TTWAIN_UnloadSourceManager(void)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TTWAIN_CloseSourceManager(NULL);
Toshihiro Shimizu 890ddd
	return TTWAIN_UnloadSourceManagerPD();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
int TTWAIN_CloseAll(void *hwnd)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TTWAIN_EndXfer();
Toshihiro Shimizu 890ddd
	TTWAIN_DisableSource();
Toshihiro Shimizu 890ddd
	TTWAIN_CloseSource();
Toshihiro Shimizu 890ddd
	TTWAIN_CloseSourceManager(hwnd);
Toshihiro Shimizu 890ddd
	TTWAIN_UnloadSourceManager();
Toshihiro Shimizu 890ddd
	TTWAIN_FreeVar();
Toshihiro Shimizu 890ddd
	return 1;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
/*    MISC. AUX FUNCTIONS						     */
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
TWAINSTATE TTWAIN_GetState(void)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return TTwainData.twainState;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
void TTWAIN_SetState(TWAINSTATE status)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TTwainData.twainState = status;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
static int TTWAIN_AbortAllPendingXfers(void)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TTWAIN_EndXfer();
Toshihiro Shimizu 890ddd
	if (TTWAIN_GetState() == TWAIN_TRANSFER_READY) {
Toshihiro Shimizu 890ddd
		TTWAIN_DS(DG_CONTROL, DAT_PENDINGXFERS, MSG_RESET,
Toshihiro Shimizu 890ddd
				  &TTwainData.transferInfo.pendingXfers);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	TTWAIN_EmptyMessageQueue();
Toshihiro Shimizu 890ddd
	return (TTWAIN_GetState() < TWAIN_TRANSFER_READY);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
/*		DATA SOURCE						     */
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
TW_INT16 TTWAIN_DS(TUINT32 dg, TUINT32 dat, TUINT32 msg, void *pd)
Toshihiro Shimizu 890ddd
{ /* Call the current source with a triplet */
Toshihiro Shimizu 890ddd
	int bOk = FALSE;
Toshihiro Shimizu 890ddd
	static TUINT32 nMemBuffer = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	PRINTF("%s dg=0x%x dat=0x%x msg=0x%x pd=0x%x\n", __FUNCTION__, dg, dat, msg, pd);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(TTWAIN_GetState() >= TWAIN_SOURCE_OPEN);
Toshihiro Shimizu 890ddd
	TTwainData.resultCode = TWRC_FAILURE;
Toshihiro Shimizu 890ddd
	if (dg == DG_IMAGE) {
Toshihiro Shimizu 890ddd
		if (dat == DAT_IMAGEMEMXFER) {
Toshihiro Shimizu 890ddd
			if (msg == MSG_GET && pd != NULL) {
Toshihiro Shimizu 890ddd
				pTW_IMAGEMEMXFER pmxb = (pTW_IMAGEMEMXFER)pd;
Toshihiro Shimizu 890ddd
				pmxb->Compression = TWON_DONTCARE16;
Toshihiro Shimizu 890ddd
				pmxb->BytesPerRow = TWON_DONTCARE32;
Toshihiro Shimizu 890ddd
				pmxb->Columns = TWON_DONTCARE32;
Toshihiro Shimizu 890ddd
				pmxb->Rows = TWON_DONTCARE32;
Toshihiro Shimizu 890ddd
				pmxb->XOffset = TWON_DONTCARE32;
Toshihiro Shimizu 890ddd
				pmxb->YOffset = TWON_DONTCARE32;
Toshihiro Shimizu 890ddd
				pmxb->BytesWritten = TWON_DONTCARE32;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (TTwainData.DSM_Entry) {
Toshihiro Shimizu 890ddd
		TTwainData.resultCode = (*TTwainData.DSM_Entry)(&TTwainData.appId,
Toshihiro Shimizu 890ddd
														&TTwainData.sourceId,
Toshihiro Shimizu 890ddd
														(TW_UINT32)dg,
Toshihiro Shimizu 890ddd
														(TW_UINT16)dat,
Toshihiro Shimizu 890ddd
														(TW_UINT16)msg,
Toshihiro Shimizu 890ddd
														(TW_MEMREF)pd);
Toshihiro Shimizu 890ddd
		bOk = (TTwainData.resultCode == TWRC_SUCCESS);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (dg == DG_CONTROL) {
Toshihiro Shimizu 890ddd
			switch (dat) {
Toshihiro Shimizu 890ddd
			case DAT_EVENT:
Toshihiro Shimizu 890ddd
				if (msg == MSG_PROCESSEVENT) {
Toshihiro Shimizu 890ddd
					if (((pTW_EVENT)pd)->TWMessage == MSG_XFERREADY) {
Toshihiro Shimizu 890ddd
						TTWAIN_SetState(TWAIN_TRANSFER_READY);
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
					bOk = (TTwainData.resultCode == TWRC_DSEVENT);
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
				break;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			case DAT_CAPABILITY:
Toshihiro Shimizu 890ddd
				break;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			case DAT_PENDINGXFERS:
Toshihiro Shimizu 890ddd
				if (msg == MSG_ENDXFER && bOk) {
Toshihiro Shimizu 890ddd
					TTWAIN_SetState(((pTW_PENDINGXFERS)pd)->Count ? TWAIN_TRANSFER_READY : TWAIN_SOURCE_ENABLED);
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
				if (msg == MSG_RESET && bOk) {
Toshihiro Shimizu 890ddd
					TTWAIN_SetState(TWAIN_SOURCE_ENABLED);
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
				break;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			case DAT_USERINTERFACE:
Toshihiro Shimizu 890ddd
				if (msg == MSG_ENABLEDS) {
Toshihiro Shimizu 890ddd
					if (TTwainData.resultCode == TWRC_FAILURE || TTwainData.resultCode == TWRC_CANCEL) {
Toshihiro Shimizu 890ddd
						TTWAIN_RecordError();
Toshihiro Shimizu 890ddd
					} else {
Toshihiro Shimizu 890ddd
						/* TTwainData.resultCode could be either SUCCESS or CHECKSTATUS */
Toshihiro Shimizu 890ddd
						TTWAIN_SetState(TWAIN_SOURCE_ENABLED);
Toshihiro Shimizu 890ddd
						bOk = TRUE;
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
				if (msg == MSG_DISABLEDS && bOk) {
Toshihiro Shimizu 890ddd
					TTWAIN_SetState(TWAIN_SOURCE_OPEN);
Toshihiro Shimizu 890ddd
#ifdef MACOSX
Toshihiro Shimizu 890ddd
					exitTwainSession(); // exited from TwainUI using close button
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
				break;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			case DAT_SETUPMEMXFER:
Toshihiro Shimizu 890ddd
				if (msg == MSG_GET && bOk) {
Toshihiro Shimizu 890ddd
					nMemBuffer = 0;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
				break;
Toshihiro Shimizu 890ddd
			} /* switch */
Toshihiro Shimizu 890ddd
		} else if (dg == DG_IMAGE) {
Toshihiro Shimizu 890ddd
			if (dat == DAT_IMAGENATIVEXFER || dat == DAT_IMAGEFILEXFER) {
Toshihiro Shimizu 890ddd
				/* Native and File transfers work much the same way. */
Toshihiro Shimizu 890ddd
				if (msg == MSG_GET) {
Toshihiro Shimizu 890ddd
					bOk = (TTwainData.resultCode == TWRC_XFERDONE);
Toshihiro Shimizu 890ddd
					switch (TTwainData.resultCode) {
Toshihiro Shimizu 890ddd
					case TWRC_XFERDONE:
Toshihiro Shimizu 890ddd
					case TWRC_CANCEL:
Toshihiro Shimizu 890ddd
						TTWAIN_SetState(TWAIN_TRANSFERRING);
Toshihiro Shimizu 890ddd
						/* Need to acknowledge end of transfer with */
Toshihiro Shimizu 890ddd
						/* DG_CONTROL / DAT_PENDINGXFERS / MSG_ENDXFER */
Toshihiro Shimizu 890ddd
						break;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					case TWRC_FAILURE:
Toshihiro Shimizu 890ddd
					default:
Toshihiro Shimizu 890ddd
						/* Transfer failed (e.g. insufficient memory, write-locked file) */
Toshihiro Shimizu 890ddd
						/* check condition code for more info */
Toshihiro Shimizu 890ddd
						TTWAIN_SetState(TWAIN_TRANSFER_READY);
Toshihiro Shimizu 890ddd
						/* The image is still pending */
Toshihiro Shimizu 890ddd
						break;
Toshihiro Shimizu 890ddd
					} /* switch */
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			} else if (dat == DAT_IMAGEMEMXFER) {
Toshihiro Shimizu 890ddd
				if (msg == MSG_GET) {
Toshihiro Shimizu 890ddd
					bOk = FALSE;
Toshihiro Shimizu 890ddd
					switch (TTwainData.resultCode) {
Toshihiro Shimizu 890ddd
					case TWRC_SUCCESS:
Toshihiro Shimizu 890ddd
					case TWRC_XFERDONE:
Toshihiro Shimizu 890ddd
						bOk = TRUE;
Toshihiro Shimizu 890ddd
						nMemBuffer++;
Toshihiro Shimizu 890ddd
						TTWAIN_SetState(TWAIN_TRANSFERRING);
Toshihiro Shimizu 890ddd
						break;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					case TWRC_FAILURE:
Toshihiro Shimizu 890ddd
						/* "If the failure occurred during the transfer of the first
Toshihiro Shimizu 890ddd
                  buffer, the session is in State 6. If the failure occurred
Toshihiro Shimizu 890ddd
                  on a subsequent buffer, the session is in State 7."
Toshihiro Shimizu 890ddd
	      */
Toshihiro Shimizu 890ddd
						TTWAIN_SetState(nMemBuffer == 0 ? TWAIN_TRANSFER_READY : TWAIN_TRANSFERRING);
Toshihiro Shimizu 890ddd
						break;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					case TWRC_CANCEL:
Toshihiro Shimizu 890ddd
						/* Transfer cancelled, no state change. */
Toshihiro Shimizu 890ddd
						TTWAIN_BreakModalLoop();
Toshihiro Shimizu 890ddd
						break;
Toshihiro Shimizu 890ddd
					} /* switch */
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/*
Toshihiro Shimizu 890ddd
if (!bOk)
Toshihiro Shimizu 890ddd
  TTWAIN_RecordError();
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
	return TTwainData.resultCode;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
/*	    DATA SOURCE MANAGER						     */
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
static int TTWAIN_MGR(TUINT32 dg, TUINT32 dat, TUINT32 msg, void *pd)
Toshihiro Shimizu 890ddd
/* Call the Source Manager with a triplet */
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int bOk = FALSE;
Toshihiro Shimizu 890ddd
	TTwainData.resultCode = TWRC_FAILURE;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (TTwainData.DSM_Entry) {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TTwainData.resultCode = (*TTwainData.DSM_Entry)(&TTwainData.appId,
Toshihiro Shimizu 890ddd
														NULL,
Toshihiro Shimizu 890ddd
														(TW_UINT32)dg,
Toshihiro Shimizu 890ddd
														(TW_UINT16)dat,
Toshihiro Shimizu 890ddd
														(TW_UINT16)msg,
Toshihiro Shimizu 890ddd
														(TW_MEMREF)pd);
Toshihiro Shimizu 890ddd
		bOk = (TTwainData.resultCode == TWRC_SUCCESS);
Toshihiro Shimizu 890ddd
		if (dg == DG_CONTROL) {
Toshihiro Shimizu 890ddd
			if (dat == DAT_IDENTITY) {
Toshihiro Shimizu 890ddd
				if (msg == MSG_OPENDS) {
Toshihiro Shimizu 890ddd
					if (bOk) {
Toshihiro Shimizu 890ddd
						/* Source opened - record identity for future triplets */
Toshihiro Shimizu 890ddd
						memcpy(&TTwainData.sourceId, pd, sizeof(TW_IDENTITY));
Toshihiro Shimizu 890ddd
						TTWAIN_SetState(TWAIN_SOURCE_OPEN);
Toshihiro Shimizu 890ddd
					} else { /*RecordError(ED_DSM_FAILURE);*/
Toshihiro Shimizu 890ddd
						TTWAIN_RecordError();
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
				if (msg == MSG_CLOSEDS && bOk) {
Toshihiro Shimizu 890ddd
					TTWAIN_SetState(TWAIN_SM_OPEN);
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			if (dat == DAT_PARENT) {
Toshihiro Shimizu 890ddd
				if (msg == MSG_OPENDSM && bOk) {
Toshihiro Shimizu 890ddd
					TTWAIN_SetState(TWAIN_SM_OPEN);
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
				if (msg == MSG_CLOSEDSM && bOk) {
Toshihiro Shimizu 890ddd
					TTWAIN_SetState(TWAIN_SM_LOADED);
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return bOk;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
/*			ERRORS						     */
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
TUINT32 TTWAIN_GetConditionCode(void)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TW_STATUS twStatus;
Toshihiro Shimizu 890ddd
	TW_INT16 rcLast = TTwainData.resultCode;
Toshihiro Shimizu 890ddd
	TW_INT16 rc = TWRC_FAILURE;
Toshihiro Shimizu 890ddd
	twStatus.ConditionCode = TWCC_BUMMER;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (TTWAIN_GetState() >= 4) {
Toshihiro Shimizu 890ddd
		/* get source status if open */
Toshihiro Shimizu 890ddd
		rc = TTWAIN_DS(DG_CONTROL, DAT_STATUS, MSG_GET, (TW_MEMREF)&twStatus);
Toshihiro Shimizu 890ddd
	} else if (TTWAIN_GetState() == 3) {
Toshihiro Shimizu 890ddd
		/* otherwise get source manager status */
Toshihiro Shimizu 890ddd
		rc = TTWAIN_MGR(DG_CONTROL, DAT_STATUS, MSG_GET, (TW_MEMREF)&twStatus);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	TTwainData.resultCode = rcLast;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (rc != TWRC_SUCCESS)
Toshihiro Shimizu 890ddd
		return -1;
Toshihiro Shimizu 890ddd
	return twStatus.ConditionCode;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
TUINT32 TTWAIN_GetResultCode(void)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return TTwainData.resultCode;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
int TTWAIN_DSM_HasEntryPoint(void)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return !!(TTwainData.DSM_Entry);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
static int TTWAIN_DoOneTransfer(void)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int rc = FALSE;
Toshihiro Shimizu 890ddd
	switch (TTwainData.transferInfo.transferMech) {
Toshihiro Shimizu 890ddd
	case TTWAIN_TRANSFERMODE_NATIVE:
Toshihiro Shimizu 890ddd
		rc = TTWAIN_NativeXferHandler();
Toshihiro Shimizu 890ddd
		break;
Toshihiro Shimizu 890ddd
	case TTWAIN_TRANSFERMODE_FILE:
Toshihiro Shimizu 890ddd
		assert(!"NOT IMPL!");
Toshihiro Shimizu 890ddd
		/*TTWAIN_FileXferHandler(); */
Toshihiro Shimizu 890ddd
		break;
Toshihiro Shimizu 890ddd
	case TTWAIN_TRANSFERMODE_MEMORY:
Toshihiro Shimizu 890ddd
		rc = TTWAIN_MemoryXferHandler();
Toshihiro Shimizu 890ddd
		break;
Toshihiro Shimizu 890ddd
	} /* switch */
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TTwainData.transferInfo.lastTransferWasOk = rc;
Toshihiro Shimizu 890ddd
	/* If inside ModalEventLoop, break out */
Toshihiro Shimizu 890ddd
	TTWAIN_BreakModalLoop();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/* Acknowledge transfer */
Toshihiro Shimizu 890ddd
	TTWAIN_EndXfer();
Toshihiro Shimizu 890ddd
	assert(TTWAIN_GetState() == TWAIN_TRANSFER_READY ||
Toshihiro Shimizu 890ddd
		   TTWAIN_GetState() == TWAIN_SOURCE_ENABLED);
Toshihiro Shimizu 890ddd
	return rc;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
void TTWAIN_RegisterApp(int majorNum, int minorNum, /* app. revision*/
Toshihiro Shimizu 890ddd
						int nLanguage,				/* (human) language (use TWLG_xxx from TWAIN.H) */
Toshihiro Shimizu 890ddd
						int nCountry,				/* country (use TWCY_xxx from TWAIN.H)	     */
Toshihiro Shimizu 890ddd
						char *version,				/* version info string                          */
Toshihiro Shimizu 890ddd
						char *manufacter,			/* name of manufacter			     */
Toshihiro Shimizu 890ddd
						char *family,				/* product family				     */
Toshihiro Shimizu 890ddd
						char *product)				/* specific product			     */
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	memset(&TTwainData.appId, 0, sizeof(TTwainData.appId));
Toshihiro Shimizu 890ddd
	TTwainData.appId.Id = 0; /* init to 0, but Source Manager will assign THE real value*/
Toshihiro Shimizu 890ddd
	TTwainData.appId.Version.MajorNum = majorNum;
Toshihiro Shimizu 890ddd
	TTwainData.appId.Version.MinorNum = minorNum;
Toshihiro Shimizu 890ddd
	TTwainData.appId.Version.Language = nLanguage;
Toshihiro Shimizu 890ddd
	TTwainData.appId.Version.Country = nCountry;
Toshihiro Shimizu 890ddd
	TTwainData.appId.ProtocolMajor = TWON_PROTOCOLMAJOR;
Toshihiro Shimizu 890ddd
	TTwainData.appId.ProtocolMinor = TWON_PROTOCOLMINOR;
Toshihiro Shimizu 890ddd
	TTwainData.appId.SupportedGroups = DG_IMAGE | DG_CONTROL;
Toshihiro Shimizu 890ddd
	strcpy((char *)TTwainData.appId.Version.Info, version);
Toshihiro Shimizu 890ddd
	strcpy((char *)TTwainData.appId.Manufacturer, manufacter);
Toshihiro Shimizu 890ddd
	strcpy((char *)TTwainData.appId.ProductFamily, family);
Toshihiro Shimizu 890ddd
	strcpy((char *)TTwainData.appId.ProductName, product);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
void *TTWAIN_AcquireNative(void *hwnd)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	void *hnative = NULL;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TTwainData.transferInfo.lastTransferWasOk = FALSE;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (TTwainData.transferInfo.transferMech != TTWAIN_TRANSFERMODE_NATIVE)
Toshihiro Shimizu 890ddd
		return 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	hwnd = TTWAIN_GetValidHwnd(hwnd);
Toshihiro Shimizu 890ddd
	if (TTWAIN_GetState() < TWAIN_SOURCE_OPEN) {
Toshihiro Shimizu 890ddd
		if (!TTWAIN_OpenSourceManager(hwnd)) /* Bring up to state 4 */
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			char msg[2048];
Toshihiro Shimizu 890ddd
			sprintf(msg, "Unable to open Source Manager (%s)", DSM_FILENAME);
Toshihiro Shimizu 890ddd
			TTWAIN_ErrorBox(msg);
Toshihiro Shimizu 890ddd
			return 0;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		if (!TTWAIN_OpenDefaultSource())
Toshihiro Shimizu 890ddd
			/*TTWAIN_ReportLastError("Unable to open default Data Source.");*/
Toshihiro Shimizu 890ddd
			TTWAIN_RecordError();
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			assert(TTWAIN_GetState() == TWAIN_SOURCE_OPEN);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (TTWAIN_GetState() >= TWAIN_SOURCE_OPEN)
Toshihiro Shimizu 890ddd
		hnative = TTWAIN_WaitForNativeXfer(hwnd);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!TTwainData.transferInfo.multiTransfer) {
Toshihiro Shimizu 890ddd
		/* shut everything down in the right sequence */
Toshihiro Shimizu 890ddd
		TTWAIN_AbortAllPendingXfers(); /* TRANSFER_READY or TRANSFERRING -> SOURCE_ENABLED */
Toshihiro Shimizu 890ddd
		TTWAIN_UnloadSourceManager();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TTwainData.transferInfo.lastTransferWasOk = !!(hnative);
Toshihiro Shimizu 890ddd
	return hnative;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
#ifdef WIN32
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
typedef void(MyFun)(HWND);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*it's an hack function to force bring to top the twain UI module window     */
Toshihiro Shimizu 890ddd
static BOOL CALLBACK myHackEnumFunction(HWND hwnd, LPARAM lParam)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	MyFun *f = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#define TITLESIZE (1024)
Toshihiro Shimizu 890ddd
	char title[TITLESIZE + 1];
Toshihiro Shimizu 890ddd
	int len;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	GetWindowText(hwnd, (char *)&title, TITLESIZE);
Toshihiro Shimizu 890ddd
	if (title[0] == 0x00)
Toshihiro Shimizu 890ddd
		return 1; /*continue the search....*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	len = strlen(TTwainData.sourceId.ProductName);
Toshihiro Shimizu 890ddd
	if (!len)
Toshihiro Shimizu 890ddd
		return 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	len--;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	while (len &&
Toshihiro Shimizu 890ddd
		   (isdigit(TTwainData.sourceId.ProductName[len])	/*skip digit at the end*/
Toshihiro Shimizu 890ddd
			|| TTwainData.sourceId.ProductName[len] == '.')) /*skip . */
Toshihiro Shimizu 890ddd
		len--;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (len && !strncmp(title, TTwainData.sourceId.ProductName, len)) {
Toshihiro Shimizu 890ddd
		/*
Toshihiro Shimizu 890ddd
  char dbg_str[1024];
Toshihiro Shimizu 890ddd
  sprintf(dbg_str,"set focus on 0x%8x %s\n",hwnd, title);
Toshihiro Shimizu 890ddd
  OutputDebugString(dbg_str);
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
		f = (MyFun *)lParam;
Toshihiro Shimizu 890ddd
		f(hwnd);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		return FALSE; /*it means stop the search...*/
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return 1; /*continue the search....*/
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static BOOL CALLBACK myHackEnumFunction2(HWND hwnd, LPARAM lParam)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	MyFun *f = 0;
Toshihiro Shimizu 890ddd
	char *ptr;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#define TITLESIZE (1024)
Toshihiro Shimizu 890ddd
	char title[TITLESIZE + 1];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	GetWindowText(hwnd, (char *)&title, TITLESIZE);
Toshihiro Shimizu 890ddd
	if (title[0] == 0x00)
Toshihiro Shimizu 890ddd
		return 1; /*continue the search....*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ptr = strstr(title, TTwainData.sourceId.Manufacturer);
Toshihiro Shimizu 890ddd
	if (!ptr)
Toshihiro Shimizu 890ddd
		return 1; /*continue the search....*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	f = (MyFun *)lParam;
Toshihiro Shimizu 890ddd
	f(hwnd);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return FALSE; /*it means stop the search...*/
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void bringToTop(HWND hwnd)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	BringWindowToTop(hwnd);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void putToBottom(HWND hwnd)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	const int unused = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	BOOL rc = SetWindowPos(
Toshihiro Shimizu 890ddd
		hwnd,										 // handle to window
Toshihiro Shimizu 890ddd
		HWND_BOTTOM,								 // placement-order handle
Toshihiro Shimizu 890ddd
		unused,										 // horizontal position
Toshihiro Shimizu 890ddd
		unused,										 // vertical position
Toshihiro Shimizu 890ddd
		unused,										 // width
Toshihiro Shimizu 890ddd
		unused,										 // height
Toshihiro Shimizu 890ddd
		SWP_ASYNCWINDOWPOS | SWP_NOMOVE | SWP_NOSIZE // window-positioning options
Toshihiro Shimizu 890ddd
		);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static void myHackFunction(int v)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	BOOL rc;
Toshihiro Shimizu 890ddd
	if (v == 1)
Toshihiro Shimizu 890ddd
		rc = EnumWindows((WNDENUMPROC)myHackEnumFunction, (LPARAM)&bringToTop);
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		rc = EnumWindows((WNDENUMPROC)myHackEnumFunction, (LPARAM)&putToBottom);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (rc) /* it means that myHackEnumFunction fails to find the proper window to bring up or put down*/
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		if (v == 1)
Toshihiro Shimizu 890ddd
			rc = EnumWindows((WNDENUMPROC)myHackEnumFunction2, (LPARAM)&bringToTop);
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			rc = EnumWindows((WNDENUMPROC)myHackEnumFunction2, (LPARAM)&putToBottom);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
static void myHackFunction(int v)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	/*it's empty...*/
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
int TTWAIN_AcquireMemory(void *hwnd)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int rc = FALSE;
Toshihiro Shimizu 890ddd
	TTwainData.transferInfo.lastTransferWasOk = FALSE;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (TTwainData.transferInfo.transferMech != TTWAIN_TRANSFERMODE_MEMORY)
Toshihiro Shimizu 890ddd
		return FALSE;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	myHackFunction(1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	hwnd = TTWAIN_GetValidHwnd(hwnd);
Toshihiro Shimizu 890ddd
	if (TTWAIN_GetState() < TWAIN_SOURCE_OPEN) {
Toshihiro Shimizu 890ddd
		if (!TTWAIN_OpenSourceManager(hwnd)) /* Bring up to state 4 */
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			TTWAIN_ErrorBox("Unable to open Source Manager (" DSM_FILENAME ")");
Toshihiro Shimizu 890ddd
			return FALSE;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		if (!TTWAIN_OpenDefaultSource())
Toshihiro Shimizu 890ddd
			/*TTWAIN_ReportLastError("Unable to open default Data Source.");*/
Toshihiro Shimizu 890ddd
			TTWAIN_RecordError();
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			assert(TTWAIN_GetState() == TWAIN_SOURCE_OPEN);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (TTWAIN_GetState() >= TWAIN_SOURCE_OPEN)
Toshihiro Shimizu 890ddd
		rc = TTWAIN_WaitForMemoryXfer(hwnd);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!TTwainData.transferInfo.multiTransfer) {
Toshihiro Shimizu 890ddd
		/* shut everything down in the right sequence */
Toshihiro Shimizu 890ddd
		TTWAIN_AbortAllPendingXfers(); /* TRANSFER_READY or TRANSFERRING -> SOURCE_ENABLED */
Toshihiro Shimizu 890ddd
		TTWAIN_UnloadSourceManager();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	myHackFunction(0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return TTwainData.transferInfo.lastTransferWasOk;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
void TTWAIN_StopAcquire(void)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TTwainData.transferInfo.oneAtLeast = FALSE;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
static void *TTWAIN_WaitForNativeXfer(void *hwnd)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TTwainData.transferInfo.hDib = NULL;
Toshihiro Shimizu 890ddd
	if (TTWAIN_GetState() >= TWAIN_SOURCE_OPEN)
Toshihiro Shimizu 890ddd
		TTWAIN_WaitForXfer(hwnd);
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		TTWAIN_ErrorBox("TWAIN_WaitForNativeXfer called in state < 4.");
Toshihiro Shimizu 890ddd
	return TTwainData.transferInfo.hDib;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
static int TTWAIN_WaitForMemoryXfer(void *hwnd)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int rc = FALSE;
Toshihiro Shimizu 890ddd
	if (TTWAIN_GetState() >= TWAIN_SOURCE_OPEN)
Toshihiro Shimizu 890ddd
		rc = TTWAIN_WaitForXfer(hwnd);
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		TTWAIN_ErrorBox("TWAIN_WaitForNativeXfer called in state < 4.");
Toshihiro Shimizu 890ddd
	return rc;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
static int TTWAIN_WaitForXfer(void *hwnd)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int bWasEnabled;
Toshihiro Shimizu 890ddd
	int rc = FALSE;
Toshihiro Shimizu 890ddd
	/* Make up a valid window if we weren't given one */
Toshihiro Shimizu 890ddd
	hwnd = TTWAIN_GetValidHwnd(hwnd);
Toshihiro Shimizu 890ddd
	/* Disable the parent window during the modal acquire */
Toshihiro Shimizu 890ddd
	bWasEnabled = (TTWAIN_EnableWindow(hwnd, FALSE) == 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TTwainData.transferInfo.oneAtLeast = TRUE;
Toshihiro Shimizu 890ddd
	/*
Toshihiro Shimizu 890ddd
TTWAIN_DS( DG_CONTROL,DAT_PENDINGXFERS, MSG_ENDXFER,
Toshihiro Shimizu 890ddd
             (TW_MEMREF)&TTwainData.transferInfo.pendingXfers);
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
	do {
Toshihiro Shimizu 890ddd
		if (TTWAIN_GetState() == TWAIN_TRANSFER_READY)
Toshihiro Shimizu 890ddd
			rc = TTWAIN_DoOneTransfer();
Toshihiro Shimizu 890ddd
		else if (TTWAIN_GetState() >= TWAIN_SOURCE_ENABLED ||
Toshihiro Shimizu 890ddd
				 TTWAIN_EnableSource(hwnd)) {
Toshihiro Shimizu 890ddd
			/* source is enabled, wait for transfer or source closed */
Toshihiro Shimizu 890ddd
			if (TTwainData.resultCode != TWRC_CANCEL)
Toshihiro Shimizu 890ddd
				TTWAIN_ModalEventLoop();
Toshihiro Shimizu 890ddd
			else {
Toshihiro Shimizu 890ddd
				TTWAIN_BreakModalLoop();
Toshihiro Shimizu 890ddd
				break;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		} else
Toshihiro Shimizu 890ddd
			/*TTWAIN_ReportLastError("Failed to enable Data Source.");*/
Toshihiro Shimizu 890ddd
			TTWAIN_RecordError();
Toshihiro Shimizu 890ddd
	} while (TTwainData.transferInfo.pendingXfers.Count &&
Toshihiro Shimizu 890ddd
			 TTwainData.transferInfo.oneAtLeast /*&& rc*/);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/* Re-enable the parent window if it was enabled */
Toshihiro Shimizu 890ddd
	TTWAIN_EnableWindow(hwnd, bWasEnabled);
Toshihiro Shimizu 890ddd
	return rc;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
void TTWAIN_FreeMemory(void *hMem)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	free(hMem);
Toshihiro Shimizu 890ddd
	/*
Toshihiro Shimizu 890ddd
if (hMem) 
Toshihiro Shimizu 890ddd
  GLOBAL_FREE(hMem);
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
static void TTWAIN_ModalEventLoop(void)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TTWAIN_ModalEventLoopPD();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
static void TTWAIN_BreakModalLoop(void)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TTwainData.breakModalLoop = TRUE;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
static void TTWAIN_EmptyMessageQueue(void)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TTWAIN_EmptyMessageQueuePD();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
static int TTWAIN_NativeXferHandler(void)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TW_UINT32 hNative;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(TTWAIN_GetState() == TWAIN_TRANSFER_READY);
Toshihiro Shimizu 890ddd
	if (TTWAIN_DS(DG_IMAGE, DAT_IMAGENATIVEXFER, MSG_GET, &hNative) == TWRC_XFERDONE)
Toshihiro Shimizu 890ddd
		TTwainData.transferInfo.hDib = (void *)hNative;
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		TTwainData.transferInfo.hDib = NULL;
Toshihiro Shimizu 890ddd
	return (!!TTwainData.transferInfo.hDib);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
static int TTWAIN_MemoryXferHandler(void)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TW_IMAGEMEMXFER *imageMemXfer = 0;
Toshihiro Shimizu 890ddd
	TW_HANDLE imageMemXferH = 0;
Toshihiro Shimizu 890ddd
	TW_HANDLE transferBufferH = 0;
Toshihiro Shimizu 890ddd
	TW_SETUPMEMXFER setup;
Toshihiro Shimizu 890ddd
	TW_IMAGEINFO info;
Toshihiro Shimizu 890ddd
	TW_IMAGELAYOUT imageLayout;
Toshihiro Shimizu 890ddd
	TUINT32 nTransferDone;
Toshihiro Shimizu 890ddd
	TW_INT16 rc1, rc2, rc3, rc4, twRC2;
Toshihiro Shimizu 890ddd
	int ret = FALSE;
Toshihiro Shimizu 890ddd
	int stopScanning = 0;
Toshihiro Shimizu 890ddd
	UCHAR *transferBuffer = 0;
Toshihiro Shimizu 890ddd
	UCHAR *sourceBuffer = 0;
Toshihiro Shimizu 890ddd
	UCHAR *targetBuffer = 0;
Toshihiro Shimizu 890ddd
	unsigned int rows;
Toshihiro Shimizu 890ddd
	double pixSize;
Toshihiro Shimizu 890ddd
	int extraX = 0;
Toshihiro Shimizu 890ddd
	int extraY = 0;
Toshihiro Shimizu 890ddd
	TW_UINT32 rowsToCopy = 0;
Toshihiro Shimizu 890ddd
	TW_UINT32 rowsRemaining = 0;
Toshihiro Shimizu 890ddd
	TW_UINT32 bytesToCopy = 0;
Toshihiro Shimizu 890ddd
	TW_UINT32 bytesToWrap = 0;
Toshihiro Shimizu 890ddd
	TW_UINT32 memorySize = 0;
Toshihiro Shimizu 890ddd
	int imgInfoOk; /* on Mac often (always) is impossible to get the imageinfo
Toshihiro Shimizu 890ddd
										 about the transfer... so no I can't prealloc memory 
Toshihiro Shimizu 890ddd
										 and do other checks about size etc...
Toshihiro Shimizu 890ddd
									*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/*printf("%s\n", __PRETTY_FUNCTION__);*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	memset(&info, 0, sizeof(TW_IMAGEINFO));
Toshihiro Shimizu 890ddd
	rc1 = TTWAIN_DS(DG_IMAGE, DAT_IMAGEINFO, MSG_GET, (TW_MEMREF)&info);
Toshihiro Shimizu 890ddd
	imgInfoOk = (rc1 == TWRC_SUCCESS);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/*printf("get image info returns %d\n", imgInfoOk);*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	rc4 = TTWAIN_DS(DG_IMAGE, DAT_IMAGELAYOUT, MSG_GET, &imageLayout);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/* determine the transfer buffer size */
Toshihiro Shimizu 890ddd
	rc2 = TTWAIN_DS(DG_CONTROL, DAT_SETUPMEMXFER, MSG_GET, (TW_MEMREF)&setup);
Toshihiro Shimizu 890ddd
	transferBufferH = GLOBAL_ALLOC(GMEM_FIXED, setup.Preferred);
Toshihiro Shimizu 890ddd
	if (!transferBufferH)
Toshihiro Shimizu 890ddd
		return FALSE;
Toshihiro Shimizu 890ddd
	transferBuffer = (UCHAR *)GLOBAL_LOCK(transferBufferH);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (imgInfoOk) {
Toshihiro Shimizu 890ddd
		pixSize = info.BitsPerPixel / 8.0;
Toshihiro Shimizu 890ddd
		memorySize = info.ImageLength * CEIL(info.ImageWidth * pixSize);
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		/* we need to allocate incrementally the memory needs to store the image*/
Toshihiro Shimizu 890ddd
		memorySize = setup.Preferred; /* start using the setupmemxfer.preferred size*/
Toshihiro Shimizu 890ddd
		pixSize = 3;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (TTwainData.transferInfo.usageMode == TTWAIN_MODE_UNLEASHED) {
Toshihiro Shimizu 890ddd
		/*
Toshihiro Shimizu 890ddd
  TTwainData.transferInfo = GLOBAL_ALLOC(GMEM_FIXED, memorySize); 
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
		TTwainData.transferInfo.memoryBuffer = (UCHAR *)malloc(memorySize);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (!TTwainData.transferInfo.memoryBuffer) {
Toshihiro Shimizu 890ddd
			/*tmsg_error("unable to allocate memory!");*/
Toshihiro Shimizu 890ddd
			return FALSE;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		if (imgInfoOk) {
Toshihiro Shimizu 890ddd
			TTwainData.transferInfo.memorySize = memorySize;
Toshihiro Shimizu 890ddd
			TTwainData.transferInfo.preferredLx = info.ImageWidth;
Toshihiro Shimizu 890ddd
			TTwainData.transferInfo.preferredLy = info.ImageLength;
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			TTwainData.transferInfo.memorySize = setup.Preferred;
Toshihiro Shimizu 890ddd
			TTwainData.transferInfo.preferredLx = 0;
Toshihiro Shimizu 890ddd
			TTwainData.transferInfo.preferredLy = 0;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	extraX = info.ImageWidth - TTwainData.transferInfo.preferredLx;
Toshihiro Shimizu 890ddd
	extraY = info.ImageLength - TTwainData.transferInfo.preferredLy;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	rowsRemaining = MIN(TTwainData.transferInfo.preferredLy, info.ImageLength);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	targetBuffer = TTwainData.transferInfo.memoryBuffer;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/*clean-up the buffer
Toshihiro Shimizu 890ddd
memset(targetBuffer, 0xff, TTwainData.transferInfo.memorySize);
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	imageMemXferH = GLOBAL_ALLOC(GMEM_FIXED, sizeof(TW_IMAGEMEMXFER));
Toshihiro Shimizu 890ddd
	if (!imageMemXferH)
Toshihiro Shimizu 890ddd
		return FALSE;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	imageMemXfer = (TW_IMAGEMEMXFER *)GLOBAL_LOCK(imageMemXferH);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	imageMemXfer->Memory.TheMem = (char *)transferBuffer;
Toshihiro Shimizu 890ddd
	imageMemXfer->Memory.Length = setup.Preferred;
Toshihiro Shimizu 890ddd
	imageMemXfer->Memory.Flags = TWMF_APPOWNS | TWMF_POINTER;
Toshihiro Shimizu 890ddd
	TTwainData.transferInfo.pendingXfers.Count = 0;
Toshihiro Shimizu 890ddd
	/* transfer the data -- loop until done or canceled */
Toshihiro Shimizu 890ddd
	nTransferDone = 0;
Toshihiro Shimizu 890ddd
	do {
Toshihiro Shimizu 890ddd
		rc3 = TTWAIN_DS(DG_IMAGE, DAT_IMAGEMEMXFER, MSG_GET, (TW_MEMREF)imageMemXfer);
Toshihiro Shimizu 890ddd
		nTransferDone++;
Toshihiro Shimizu 890ddd
		switch (rc3) {
Toshihiro Shimizu 890ddd
			CASE TWRC_SUCCESS : PRINTF("IMAGEMEMXFER, GET, returns SUCCESS\n");
Toshihiro Shimizu 890ddd
			if (imgInfoOk) {
Toshihiro Shimizu 890ddd
				TW_UINT32 colsToCopy;
Toshihiro Shimizu 890ddd
				rowsToCopy = MIN(imageMemXfer->Rows, rowsRemaining);
Toshihiro Shimizu 890ddd
				colsToCopy = MIN(imageMemXfer->Columns, (unsigned long)TTwainData.transferInfo.preferredLx);
Toshihiro Shimizu 890ddd
				bytesToCopy = CEIL(colsToCopy * pixSize);
Toshihiro Shimizu 890ddd
				bytesToWrap = CEIL(TTwainData.transferInfo.preferredLx * pixSize);
Toshihiro Shimizu 890ddd
			} else {
Toshihiro Shimizu 890ddd
				TW_UINT32 newMemorySize;
Toshihiro Shimizu 890ddd
				rowsToCopy = imageMemXfer->Rows;
Toshihiro Shimizu 890ddd
				bytesToCopy = imageMemXfer->BytesPerRow;
Toshihiro Shimizu 890ddd
				bytesToWrap = bytesToCopy;
Toshihiro Shimizu 890ddd
				newMemorySize = (TTwainData.transferInfo.preferredLy + imageMemXfer->Rows) * imageMemXfer->BytesPerRow;
Toshihiro Shimizu 890ddd
				if (TTwainData.transferInfo.memorySize < newMemorySize) {
Toshihiro Shimizu 890ddd
					TTwainData.transferInfo.memoryBuffer = (UCHAR *)realloc(TTwainData.transferInfo.memoryBuffer, newMemorySize);
Toshihiro Shimizu 890ddd
					TTwainData.transferInfo.memorySize = newMemorySize;
Toshihiro Shimizu 890ddd
					targetBuffer = TTwainData.transferInfo.memoryBuffer + (TTwainData.transferInfo.preferredLy * imageMemXfer->BytesPerRow);
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
				TTwainData.transferInfo.preferredLy += rowsToCopy;
Toshihiro Shimizu 890ddd
				if ((int)imageMemXfer->Columns > TTwainData.transferInfo.preferredLx)
Toshihiro Shimizu 890ddd
					TTwainData.transferInfo.preferredLx = imageMemXfer->Columns;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			sourceBuffer = (UCHAR *)imageMemXfer->Memory.TheMem;
Toshihiro Shimizu 890ddd
			if (TTwainData.transferInfo.nextImageNeedsToBeInverted)
Toshihiro Shimizu 890ddd
				INVERT_BYTE(sourceBuffer, bytesToCopy)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			for (rows = 0; rows < rowsToCopy; rows++) {
Toshihiro Shimizu 890ddd
				memcpy(targetBuffer, sourceBuffer, bytesToCopy);
Toshihiro Shimizu 890ddd
				targetBuffer += bytesToWrap;
Toshihiro Shimizu 890ddd
				sourceBuffer += imageMemXfer->BytesPerRow;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			rowsRemaining -= rowsToCopy;
Toshihiro Shimizu 890ddd
			CASE TWRC_XFERDONE : PRINTF("IMAGEMEMXFER, GET, returns XFERDONE\n");
Toshihiro Shimizu 890ddd
			/*copy the last transfer data*/
Toshihiro Shimizu 890ddd
			if (imgInfoOk) {
Toshihiro Shimizu 890ddd
				TW_UINT32 colsToCopy;
Toshihiro Shimizu 890ddd
				rowsToCopy = MIN(imageMemXfer->Rows, rowsRemaining);
Toshihiro Shimizu 890ddd
				colsToCopy = MIN(imageMemXfer->Columns, (unsigned long)TTwainData.transferInfo.preferredLx);
Toshihiro Shimizu 890ddd
				bytesToCopy = CEIL(colsToCopy * pixSize);
Toshihiro Shimizu 890ddd
				bytesToWrap = CEIL(TTwainData.transferInfo.preferredLx * pixSize);
Toshihiro Shimizu 890ddd
			} else {
Toshihiro Shimizu 890ddd
				TW_UINT32 newMemorySize;
Toshihiro Shimizu 890ddd
				rowsToCopy = imageMemXfer->Rows;
Toshihiro Shimizu 890ddd
				bytesToCopy = imageMemXfer->BytesPerRow;
Toshihiro Shimizu 890ddd
				bytesToWrap = bytesToCopy;
Toshihiro Shimizu 890ddd
				newMemorySize = (TTwainData.transferInfo.preferredLy + imageMemXfer->Rows) * imageMemXfer->BytesPerRow;
Toshihiro Shimizu 890ddd
				if (TTwainData.transferInfo.memorySize < newMemorySize) {
Toshihiro Shimizu 890ddd
					TTwainData.transferInfo.memoryBuffer = (UCHAR *)realloc(TTwainData.transferInfo.memoryBuffer, newMemorySize);
Toshihiro Shimizu 890ddd
					TTwainData.transferInfo.memorySize = newMemorySize;
Toshihiro Shimizu 890ddd
					targetBuffer = TTwainData.transferInfo.memoryBuffer + (TTwainData.transferInfo.preferredLy * imageMemXfer->BytesPerRow);
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
				TTwainData.transferInfo.preferredLy += rowsToCopy;
Toshihiro Shimizu 890ddd
				if ((int)imageMemXfer->Columns > TTwainData.transferInfo.preferredLx)
Toshihiro Shimizu 890ddd
					TTwainData.transferInfo.preferredLx = imageMemXfer->Columns;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			sourceBuffer = (UCHAR *)imageMemXfer->Memory.TheMem;
Toshihiro Shimizu 890ddd
			if (TTwainData.transferInfo.nextImageNeedsToBeInverted)
Toshihiro Shimizu 890ddd
				INVERT_BYTE(sourceBuffer, bytesToCopy)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			for (rows = 0; rows < rowsToCopy; rows++) {
Toshihiro Shimizu 890ddd
				memcpy(targetBuffer, sourceBuffer, bytesToCopy);
Toshihiro Shimizu 890ddd
				targetBuffer += bytesToWrap;
Toshihiro Shimizu 890ddd
				sourceBuffer += imageMemXfer->BytesPerRow;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			rowsRemaining -= rowsToCopy;
Toshihiro Shimizu 890ddd
			PRINTF("get pending xfers\n");
Toshihiro Shimizu 890ddd
			twRC2 = TTWAIN_DS(DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER,
Toshihiro Shimizu 890ddd
							  (TW_MEMREF)&TTwainData.transferInfo.pendingXfers);
Toshihiro Shimizu 890ddd
			if (twRC2 != TWRC_SUCCESS) {
Toshihiro Shimizu 890ddd
				printf("pending xfers != success");
Toshihiro Shimizu 890ddd
				ret = FALSE;
Toshihiro Shimizu 890ddd
				goto done;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			PRINTF(" pending count = %d\n", TTwainData.transferInfo.pendingXfers.Count);
Toshihiro Shimizu 890ddd
			if (TTwainData.transferInfo.pendingXfers.Count == 0) {
Toshihiro Shimizu 890ddd
				ret = TRUE;
Toshihiro Shimizu 890ddd
				goto done;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			if (TTwainData.transferInfo.pendingXfers.Count == 0xffff) {
Toshihiro Shimizu 890ddd
				ret = TRUE;
Toshihiro Shimizu 890ddd
				goto done;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			if (TTwainData.transferInfo.pendingXfers.Count == 0xfffe) {
Toshihiro Shimizu 890ddd
				ret = TRUE;
Toshihiro Shimizu 890ddd
				goto done;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			ret = TRUE;
Toshihiro Shimizu 890ddd
			goto done;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			CASE TWRC_CANCEL : TTWAIN_RecordError();
Toshihiro Shimizu 890ddd
			twRC2 = TTWAIN_DS(DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER,
Toshihiro Shimizu 890ddd
							  (TW_MEMREF)&TTwainData.transferInfo.pendingXfers);
Toshihiro Shimizu 890ddd
			if (twRC2 != TWRC_SUCCESS) {
Toshihiro Shimizu 890ddd
				ret = FALSE;
Toshihiro Shimizu 890ddd
				goto done;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			if (TTwainData.transferInfo.pendingXfers.Count == 0) {
Toshihiro Shimizu 890ddd
				ret = FALSE;
Toshihiro Shimizu 890ddd
				goto done;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			CASE TWRC_FAILURE : PRINTF("IMAGEMEMXFER, GET, returns FAILURE\n");
Toshihiro Shimizu 890ddd
			TTWAIN_RecordError();
Toshihiro Shimizu 890ddd
			twRC2 = TTWAIN_DS(DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER,
Toshihiro Shimizu 890ddd
							  (TW_MEMREF)&TTwainData.transferInfo.pendingXfers);
Toshihiro Shimizu 890ddd
			if (twRC2 != TWRC_SUCCESS) {
Toshihiro Shimizu 890ddd
				ret = FALSE;
Toshihiro Shimizu 890ddd
				goto done;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			if (TTwainData.transferInfo.pendingXfers.Count == 0) {
Toshihiro Shimizu 890ddd
				ret = FALSE;
Toshihiro Shimizu 890ddd
				goto done;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		DEFAULT:
Toshihiro Shimizu 890ddd
			PRINTF("IMAGEMEMXFER, GET, returns ?!? Default handler called\n");
Toshihiro Shimizu 890ddd
			/* Abort the image */
Toshihiro Shimizu 890ddd
			TTWAIN_RecordError();
Toshihiro Shimizu 890ddd
			twRC2 = TTWAIN_DS(DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER,
Toshihiro Shimizu 890ddd
							  (TW_MEMREF)&TTwainData.transferInfo.pendingXfers);
Toshihiro Shimizu 890ddd
			if (twRC2 != TWRC_SUCCESS) {
Toshihiro Shimizu 890ddd
				ret = FALSE;
Toshihiro Shimizu 890ddd
				goto done;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			if (TTwainData.transferInfo.pendingXfers.Count == 0) {
Toshihiro Shimizu 890ddd
				ret = FALSE;
Toshihiro Shimizu 890ddd
				goto done;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} while (rc3 == TWRC_SUCCESS);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
done:
Toshihiro Shimizu 890ddd
	if (ret == TRUE) {
Toshihiro Shimizu 890ddd
		if (TTwainData.callback.onDoneCb) {
Toshihiro Shimizu 890ddd
			float xdpi, ydpi;
Toshihiro Shimizu 890ddd
			TTWAIN_PIXTYPE pixType;
Toshihiro Shimizu 890ddd
			xdpi = TTWAIN_Fix32ToFloat(info.XResolution);
Toshihiro Shimizu 890ddd
			ydpi = TTWAIN_Fix32ToFloat(info.YResolution);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (imgInfoOk) {
Toshihiro Shimizu 890ddd
				xdpi = TTWAIN_Fix32ToFloat(info.XResolution);
Toshihiro Shimizu 890ddd
				ydpi = TTWAIN_Fix32ToFloat(info.YResolution);
Toshihiro Shimizu 890ddd
				switch (BB(info.PixelType, info.BitsPerPixel)) {
Toshihiro Shimizu 890ddd
					CASE BB(TWPT_BW, 1) : pixType = TTWAIN_BW;
Toshihiro Shimizu 890ddd
					CASE BB(TWPT_GRAY, 8) : pixType = TTWAIN_GRAY8;
Toshihiro Shimizu 890ddd
					CASE BB(TWPT_RGB, 24) : pixType = TTWAIN_RGB24;
Toshihiro Shimizu 890ddd
				DEFAULT:
Toshihiro Shimizu 890ddd
					pixType = TTWAIN_RGB24;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			} else {
Toshihiro Shimizu 890ddd
				float lx = TTWAIN_Fix32ToFloat(imageLayout.Frame.Right) - TTWAIN_Fix32ToFloat(imageLayout.Frame.Left);
Toshihiro Shimizu 890ddd
				float ly = TTWAIN_Fix32ToFloat(imageLayout.Frame.Bottom) - TTWAIN_Fix32ToFloat(imageLayout.Frame.Top);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				xdpi = (float)TTwainData.transferInfo.preferredLx / lx;
Toshihiro Shimizu 890ddd
				ydpi = (float)TTwainData.transferInfo.preferredLy / ly;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				/*
Toshihiro Shimizu 890ddd
					TW_UINT16 rc = TTWAIN_GetCurrentPixelType(&pixType);
Toshihiro Shimizu 890ddd
					printf("get cur pix type %s\n", (rc==TWRC_SUCCESS)?"OK":"FAIL");
Toshihiro Shimizu 890ddd
					if (rc == TWRC_SUCCESS)
Toshihiro Shimizu 890ddd
						switch (pixType)
Toshihiro Shimizu 890ddd
							{
Toshihiro Shimizu 890ddd
							CASE TWPT_BW  : pixType = TTWAIN_BW;
Toshihiro Shimizu 890ddd
  						CASE TWPT_GRAY: pixType = TTWAIN_GRAY8;
Toshihiro Shimizu 890ddd
    					CASE TWPT_RGB : pixType = TTWAIN_RGB24;
Toshihiro Shimizu 890ddd
    					DEFAULT : pixType = TTWAIN_RGB24;
Toshihiro Shimizu 890ddd
							}
Toshihiro Shimizu 890ddd
					else
Toshihiro Shimizu 890ddd
  					pixType = TTWAIN_RGB24;
Toshihiro Shimizu 890ddd
		*/
Toshihiro Shimizu 890ddd
				switch (imageMemXfer->BytesPerRow / TTwainData.transferInfo.preferredLx) {
Toshihiro Shimizu 890ddd
				case 1:
Toshihiro Shimizu 890ddd
					pixType = TTWAIN_GRAY8;
Toshihiro Shimizu 890ddd
					break;
Toshihiro Shimizu 890ddd
				case 3:
Toshihiro Shimizu 890ddd
					pixType = TTWAIN_RGB24;
Toshihiro Shimizu 890ddd
					break;
Toshihiro Shimizu 890ddd
				default: {
Toshihiro Shimizu 890ddd
					double b = (imageMemXfer->BytesPerRow /
Toshihiro Shimizu 890ddd
								(double)TTwainData.transferInfo.preferredLx);
Toshihiro Shimizu 890ddd
					if ((b >= 0.125) && (b < 8))
Toshihiro Shimizu 890ddd
						pixType = TTWAIN_BW;
Toshihiro Shimizu 890ddd
					else {
Toshihiro Shimizu 890ddd
						printf("unable to det pix type assume RGB24\n");
Toshihiro Shimizu 890ddd
						pixType = TTWAIN_RGB24;
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
					break;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			stopScanning = !TTwainData.callback.onDoneCb(
Toshihiro Shimizu 890ddd
				TTwainData.transferInfo.memoryBuffer,
Toshihiro Shimizu 890ddd
				pixType,
Toshihiro Shimizu 890ddd
				TTwainData.transferInfo.preferredLx,
Toshihiro Shimizu 890ddd
				TTwainData.transferInfo.preferredLy,
Toshihiro Shimizu 890ddd
				TTwainData.transferInfo.preferredLx,
Toshihiro Shimizu 890ddd
				xdpi, ydpi,
Toshihiro Shimizu 890ddd
				TTwainData.callback.onDoneArg);
Toshihiro Shimizu 890ddd
#ifdef MACOSX
Toshihiro Shimizu 890ddd
			PRINTF("stopScanning = %d\n", stopScanning);
Toshihiro Shimizu 890ddd
			exitTwainSession();
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} else /*ret == FALSE*/
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		if (TTwainData.callback.onErrorCb) {
Toshihiro Shimizu 890ddd
			TTwainData.callback.onErrorCb(TTwainData.callback.onErrorArg, 0);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (imageMemXferH) {
Toshihiro Shimizu 890ddd
		GLOBAL_UNLOCK(imageMemXferH);
Toshihiro Shimizu 890ddd
		GLOBAL_FREE(imageMemXferH);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (transferBufferH) {
Toshihiro Shimizu 890ddd
		GLOBAL_UNLOCK(transferBuffer);
Toshihiro Shimizu 890ddd
		GLOBAL_FREE(transferBufferH);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return ret && !stopScanning;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
int TTWAIN_InitVar(void)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	char *c;
Toshihiro Shimizu 890ddd
	if (TTwainData.initDone)
Toshihiro Shimizu 890ddd
		return TRUE;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TTwainData.DSM_Entry = 0;
Toshihiro Shimizu 890ddd
	TTwainData.hwnd32SM = 0;
Toshihiro Shimizu 890ddd
	TTwainData.twainAvailable = AVAIABLE_DONTKNOW;
Toshihiro Shimizu 890ddd
	TTwainData.breakModalLoop = FALSE;
Toshihiro Shimizu 890ddd
	TTwainData.UIStatus = FALSE;
Toshihiro Shimizu 890ddd
	TTwainData.twainState = TWAIN_PRESESSION;
Toshihiro Shimizu 890ddd
	TTwainData.transferInfo.hDib = 0;
Toshihiro Shimizu 890ddd
	TTwainData.transferInfo.multiTransfer = TRUE;
Toshihiro Shimizu 890ddd
	TTwainData.supportedCaps = 0;
Toshihiro Shimizu 890ddd
	TTwainData.resultCode = 0;
Toshihiro Shimizu 890ddd
	TTwainData.ErrRC = 0;
Toshihiro Shimizu 890ddd
	TTwainData.ErrCC = 0;
Toshihiro Shimizu 890ddd
	TTwainData.modalStatus = FALSE;
Toshihiro Shimizu 890ddd
	TTwainData.appId.Id = 0;
Toshihiro Shimizu 890ddd
	TTWAIN_ConvertRevStrToRevNum(RELEASE_STR, &TTwainData.appId.Version.MajorNum,
Toshihiro Shimizu 890ddd
								 &TTwainData.appId.Version.MinorNum);
Toshihiro Shimizu 890ddd
	TTwainData.appId.Version.Language = TWLG_USA;
Toshihiro Shimizu 890ddd
	TTwainData.appId.Version.Country = TWCY_USA;
Toshihiro Shimizu 890ddd
	strcpy((char *)TTwainData.appId.Version.Info, TITLEBAR_STR);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TTwainData.appId.ProtocolMajor = TWON_PROTOCOLMAJOR;
Toshihiro Shimizu 890ddd
	TTwainData.appId.ProtocolMinor = TWON_PROTOCOLMINOR;
Toshihiro Shimizu 890ddd
	TTwainData.appId.SupportedGroups = DG_IMAGE | DG_CONTROL;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	c = (char *)TTwainData.appId.Manufacturer;
Toshihiro Shimizu 890ddd
#ifdef MACOSX
Toshihiro Shimizu 890ddd
	*c = strlen(COMPANY);
Toshihiro Shimizu 890ddd
	c++;
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
	strcpy(c, COMPANY);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	c = (char *)TTwainData.appId.ProductFamily;
Toshihiro Shimizu 890ddd
#ifdef MACOSX
Toshihiro Shimizu 890ddd
	*c = strlen(PRODUCT);
Toshihiro Shimizu 890ddd
	c++;
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
	strcpy(c, PRODUCT);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	c = (char *)TTwainData.appId.ProductName;
Toshihiro Shimizu 890ddd
#ifdef MACOSX
Toshihiro Shimizu 890ddd
	*c = strlen(TwProgramName);
Toshihiro Shimizu 890ddd
	c++;
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
	strcpy(c, TwProgramName);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TTwainData.initDone = TRUE;
Toshihiro Shimizu 890ddd
	return TRUE;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
static void TTWAIN_FreeVar(void)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (TTwainData.supportedCaps) {
Toshihiro Shimizu 890ddd
		/* MEMORY LEAK !
Toshihiro Shimizu 890ddd
  GLOBAL_FREE(TTwainData.supportedCaps);
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
		TTwainData.supportedCaps = 0;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef __cplusplus
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
#endif