1
2
3 #ifdef _MSC_VER
4 #pragma warning(disable : 4996)
5 #endif
6
7 #define TTWAINLIB_MAIN
8 #include <assert.h>
9 #include <string.h>
10 #include <stdlib.h>
11 #include <ctype.h>
12 #include <stdio.h>
13 #include "ttwain_state.h"
14 #include "ttwain_statePD.h"
15 #include "ttwain_error.h"
16 #include "ttwain_win.h"
17 #include "ttwain_winPD.h"
18 #include "ttwain_util.h"
19 #include "ttwain_utilP.h"
20 #include "ttwain_conversion.h"
21 #include "ttwainP.h"
22
23 #include "ttwain_global_def.h"
24
25 #ifdef __cplusplus
26 extern "C" {
27 #endif
28 #ifdef MACOSX
29 extern int exitTwainSession(void);
30 #endif
31 static void TTWAIN_FreeVar(void);
32
33 #define RELEASE_STR "5.1"
34 #define TITLEBAR_STR "Toonz5.1"
35 #define TwProgramName "Toonz5.1"
36
37 #define COMPANY "Digital Video"
38 #define PRODUCT "TOONZ"
39
40 #ifndef min
41 #define min(a, b) (((a) < (b)) ? (a) : (b))
42 #endif
43 #ifndef max
44 #define max(a, b) (((a) > (b)) ? (a) : (b))
45 #endif
46
47 #define CEIL(x) ((int)(x) < (x) ? (int)(x) + 1 : (int)(x))
48
49 #ifndef _WIN32
50 #define PRINTF(args...)
51 #else
52 #define PRINTF
53 #endif
54 /*---------------------------------------------------------------------------*/
55 /* LOCAL PROTOTYPES
56 */
57 /*---------------------------------------------------------------------------*/
58 static int TTWAIN_DoOneTransfer(void);
59 static int TTWAIN_WaitForXfer(void *hwnd);
60 static void *TTWAIN_WaitForNativeXfer(void *hwnd);
61 static int TTWAIN_WaitForMemoryXfer(void *hwnd);
62 static int TTWAIN_NativeXferHandler(void);
63 static int TTWAIN_MemoryXferHandler(void);
64 static int TTWAIN_AbortAllPendingXfers(void);
65 static void TTWAIN_ModalEventLoop(void);
66 static void TTWAIN_BreakModalLoop(void);
67 static void TTWAIN_EmptyMessageQueue(void);
68 /*---------------------------------------------------------------------------*/
69 void TTWAIN_SetState(TWAINSTATE status);
70 /*---------------------------------------------------------------------------*/
71 /*---------------------------------------------------------------------------*/
72 /* int TTWAIN_LoadSourceManager(void) <- this is in ttwain_state.h */
73
74 /* int TTWAIN_SelectImageSource(void* hwnd) <-\
75 int TTWAIN_SelectImageSource(void* hwnd) <-|--\
76 int TTWAIN_OpenDefaultSource(void) <-|-- these are in ttwain.h
77 int TTWAIN_CloseAll (void *hwnd) <-/
78 */
79
80 /* these are local */
81 static int TTWAIN_EnableSource(void *hwnd);
82 int TTWAIN_MessageHook(void *lpmsg);
83 static int TTWAIN_EndXfer(void);
84 static int TTWAIN_DisableSource(void);
85 static int TTWAIN_CloseSource(void);
86 static int TTWAIN_CloseSourceManager(void *hwnd);
87
88 /* int TTWAIN_UnloadSourceManager(void) <- this is in ttwain_state.h */
89
90 static int TTWAIN_MGR(TUINT32 dg, TUINT32 dat, TUINT32 msg, void *pd);
91
92 #define INVERT_BYTE(START, HOWMANY) \
93 { \
94 UCHAR *p = (START); \
95 unsigned int ijk; \
96 for (ijk = 0; ijk < (HOWMANY); ijk++, p++) { \
97 *p = ~*p; \
98 } \
99 }
100
101 #define BB(H, L) (H << 8 | L)
102 /*---------------------------------------------------------------------------*/
103 /* TWAIN STATE */
104 /*---------------------------------------------------------------------------*/
105 /*STATE 1 TO 2*/
TTWAIN_LoadSourceManager(void)106 int TTWAIN_LoadSourceManager(void) {
107 TTWAIN_InitVar();
108 return TTWAIN_LoadSourceManagerPD();
109 }
110 /*---------------------------------------------------------------------------*/
111 /*STATE 2 TO 3*/
TTWAIN_OpenSourceManager(void * hwnd)112 int TTWAIN_OpenSourceManager(void *hwnd) {
113 TTwainData.hwnd32SM = (TW_INT32)TTWAIN_GetValidHwnd(hwnd);
114
115 if (TTWAIN_GetState() < TWAIN_SM_OPEN) {
116 if (TTWAIN_LoadSourceManager() &&
117 TTWAIN_MGR(DG_CONTROL, DAT_PARENT, MSG_OPENDSM, &TTwainData.hwnd32SM)) {
118 assert(TTWAIN_GetState() == TWAIN_SM_OPEN);
119 }
120 }
121 return (TTWAIN_GetState() >= TWAIN_SM_OPEN);
122 }
123 /*---------------------------------------------------------------------------*/
124 /*STATE 3*/
125 static TW_IDENTITY newSourceId;
TTWAIN_SelectImageSource(void * hwnd)126 int TTWAIN_SelectImageSource(void *hwnd) {
127 int success = FALSE;
128 TWAINSTATE entryState = TTWAIN_GetState();
129
130 if (TTWAIN_GetState() >= TWAIN_SM_OPEN || TTWAIN_OpenSourceManager(hwnd)) {
131 // TW_IDENTITY newSourceId;
132 memset(&newSourceId, 0, sizeof newSourceId);
133
134 TTWAIN_MGR(DG_CONTROL, DAT_IDENTITY, MSG_GETDEFAULT, &newSourceId);
135 /* Post the Select Source dialog */
136 success =
137 TTWAIN_MGR(DG_CONTROL, DAT_IDENTITY, MSG_USERSELECT, &newSourceId);
138 } else {
139 char msg[2048];
140 snprintf(msg, sizeof(msg), "Unable to open Source Manager (%s)",
141 DSM_FILENAME);
142 TTWAIN_ErrorBox(msg);
143 return FALSE;
144 }
145
146 if (entryState < TWAIN_SM_OPEN) {
147 TTWAIN_CloseSourceManager(hwnd);
148 if (entryState < TWAIN_SM_LOADED) {
149 TTWAIN_UnloadSourceManager();
150 }
151 }
152 return success;
153 }
154 /*---------------------------------------------------------------------------*/
155 /*STATE 3 TO 4*/
TTWAIN_OpenDefaultSource(void)156 int TTWAIN_OpenDefaultSource(void) {
157 TW_IDENTITY tempId;
158 int rc;
159 static int first_time = TRUE;
160
161 if (TTWAIN_GetState() < TWAIN_SOURCE_OPEN) {
162 if (TTWAIN_GetState() < TWAIN_SM_OPEN && !TTWAIN_OpenSourceManager(NULL))
163 return FALSE;
164
165 rc = TTWAIN_MGR(DG_CONTROL, DAT_IDENTITY, MSG_GETFIRST, &tempId);
166 while (rc && tempId.Id != 0) {
167 if (strcmp((char *)newSourceId.ProductName, (char *)tempId.ProductName) ==
168 0) {
169 newSourceId = tempId;
170 break;
171 }
172 rc = TTWAIN_MGR(DG_CONTROL, DAT_IDENTITY, MSG_GETNEXT, &tempId);
173 }
174
175 if (TTWAIN_MGR(DG_CONTROL, DAT_IDENTITY, MSG_OPENDS, &newSourceId)) {
176 assert(TTWAIN_GetState() == TWAIN_SOURCE_OPEN);
177 }
178 }
179
180 if (first_time && (TTWAIN_GetState() == TWAIN_SOURCE_OPEN)) {
181 TTWAIN_GetSupportedCaps();
182 /*first_time = FALSE;*/
183 }
184 return (TTWAIN_GetState() == TWAIN_SOURCE_OPEN);
185 }
186 /*---------------------------------------------------------------------------*/
187 /*STATE 4 TO 5*/
TTWAIN_EnableSource(void * hwnd)188 static int TTWAIN_EnableSource(void *hwnd) {
189 if (TTWAIN_GetState() < TWAIN_SOURCE_OPEN && !TTWAIN_OpenDefaultSource())
190 return FALSE;
191
192 TTwainData.twainUI.ShowUI = TTWAIN_GetUIStatus();
193 TTwainData.twainUI.ModalUI = TTWAIN_GetModalStatus();
194 TTwainData.twainUI.hParent = (TW_HANDLE)TTWAIN_GetValidHwnd(hwnd);
195 TTWAIN_DS(DG_CONTROL, DAT_USERINTERFACE, MSG_ENABLEDS, &TTwainData.twainUI);
196 return (TTWAIN_GetState() == TWAIN_SOURCE_ENABLED);
197 }
198 /*---------------------------------------------------------------------------*/
199 /*STATE 5 TO 6 TO 7*/
TTWAIN_MessageHook(void * lpmsg)200 int TTWAIN_MessageHook(void *lpmsg)
201 /* returns TRUE if msg processed by TWAIN (source) */
202 {
203 int bProcessed = FALSE;
204 // printf("%s\n", __PRETTY_FUNCTION__);
205 if (TTWAIN_GetState() >= TWAIN_SOURCE_ENABLED) {
206 /* source enabled */
207 #ifdef _WIN32
208 TW_EVENT twEvent;
209 twEvent.pEvent = (TW_MEMREF)lpmsg;
210 twEvent.TWMessage = MSG_NULL;
211 /* see if source wants to process (eat) the message */
212 bProcessed = (TTWAIN_DS(DG_CONTROL, DAT_EVENT, MSG_PROCESSEVENT,
213 &twEvent) == TWRC_DSEVENT);
214 #else
215 TW_EVENT twEvent;
216 twEvent.pEvent = (TW_MEMREF)0;
217 twEvent.TWMessage = (TW_UINT32)lpmsg;
218 #endif
219 switch (twEvent.TWMessage) {
220 case MSG_XFERREADY:
221 #ifdef MACOSX
222 TTWAIN_SetState(TWAIN_TRANSFER_READY);
223 #endif
224 assert(TTWAIN_GetState() == TWAIN_TRANSFER_READY);
225 TTWAIN_DoOneTransfer();
226 break;
227 case MSG_CLOSEDSREQ:
228 TTWAIN_DisableSource();
229 break;
230 case MSG_NULL:
231 /* no message returned from DS */
232 break;
233 } /* switch */
234 }
235 return bProcessed;
236 }
237 /*---------------------------------------------------------------------------*/
238 /*STATE 7 TO 6 TO 5*/
TTWAIN_EndXfer(void)239 static int TTWAIN_EndXfer(void) {
240 if (TTWAIN_GetState() == TWAIN_TRANSFERRING)
241 TTWAIN_DS(DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER,
242 &TTwainData.transferInfo.pendingXfers);
243 return (TTWAIN_GetState() < TWAIN_TRANSFERRING);
244 }
245 /*---------------------------------------------------------------------------*/
246 /* STATE 5 TO 1 */
247 /* 3 OP + 1 PD OP*/
248
249 /*STATE 5 TO 4*/
TTWAIN_DisableSource(void)250 static int TTWAIN_DisableSource(void) {
251 TTWAIN_AbortAllPendingXfers();
252
253 if ((TTWAIN_GetState() >= TWAIN_SOURCE_ENABLED) &&
254 (TTWAIN_DS(DG_CONTROL, DAT_USERINTERFACE, MSG_DISABLEDS,
255 &TTwainData.twainUI) == TWRC_SUCCESS)) {
256 assert(TTWAIN_GetState() == TWAIN_SOURCE_OPEN);
257 return FALSE;
258 }
259 TTWAIN_EmptyMessageQueue();
260 return (TTWAIN_GetState() < TWAIN_SOURCE_ENABLED);
261 }
262 /*---------------------------------------------------------------------------*/
263 /*STATE 4 TO 3*/
TTWAIN_CloseSource(void)264 static int TTWAIN_CloseSource(void) {
265 TTwainData.resultCode = TWRC_SUCCESS;
266
267 TTWAIN_DisableSource();
268 if (TTWAIN_GetState() == TWAIN_SOURCE_OPEN &&
269 TTWAIN_MGR(DG_CONTROL, DAT_IDENTITY, MSG_CLOSEDS, &TTwainData.sourceId)) {
270 assert(TTWAIN_GetState() == TWAIN_SM_OPEN);
271 }
272 return (TTWAIN_GetState() <= TWAIN_SM_OPEN);
273 }
274 /*---------------------------------------------------------------------------*/
275 /*STATE 3 TO 2*/
TTWAIN_CloseSourceManager(void * hwnd)276 static int TTWAIN_CloseSourceManager(void *hwnd) {
277 TTWAIN_EmptyMessageQueue();
278 TTwainData.hwnd32SM = (TW_INT32)TTWAIN_GetValidHwnd(hwnd);
279
280 TTwainData.resultCode = TWRC_SUCCESS;
281
282 if (TTWAIN_CloseSource() &&
283 TTWAIN_MGR(DG_CONTROL, DAT_PARENT, MSG_CLOSEDSM, &TTwainData.hwnd32SM)) {
284 assert(TTWAIN_GetState() == TWAIN_SM_LOADED);
285 }
286 return (TTWAIN_GetState() <= TWAIN_SM_LOADED);
287 }
288 /*---------------------------------------------------------------------------*/
289 /*STATE 2 TO 1*/
TTWAIN_UnloadSourceManager(void)290 int TTWAIN_UnloadSourceManager(void) {
291 TTWAIN_CloseSourceManager(NULL);
292 return TTWAIN_UnloadSourceManagerPD();
293 }
294 /*---------------------------------------------------------------------------*/
TTWAIN_CloseAll(void * hwnd)295 int TTWAIN_CloseAll(void *hwnd) {
296 TTWAIN_EndXfer();
297 TTWAIN_DisableSource();
298 TTWAIN_CloseSource();
299 TTWAIN_CloseSourceManager(hwnd);
300 TTWAIN_UnloadSourceManager();
301 TTWAIN_FreeVar();
302 return 1;
303 }
304 /*---------------------------------------------------------------------------*/
305 /*---------------------------------------------------------------------------*/
306 /*---------------------------------------------------------------------------*/
307 /* MISC. AUX FUNCTIONS */
308 /*---------------------------------------------------------------------------*/
TTWAIN_GetState(void)309 TWAINSTATE TTWAIN_GetState(void) { return TTwainData.twainState; }
310 /*---------------------------------------------------------------------------*/
TTWAIN_SetState(TWAINSTATE status)311 void TTWAIN_SetState(TWAINSTATE status) { TTwainData.twainState = status; }
312 /*---------------------------------------------------------------------------*/
TTWAIN_AbortAllPendingXfers(void)313 static int TTWAIN_AbortAllPendingXfers(void) {
314 TTWAIN_EndXfer();
315 if (TTWAIN_GetState() == TWAIN_TRANSFER_READY) {
316 TTWAIN_DS(DG_CONTROL, DAT_PENDINGXFERS, MSG_RESET,
317 &TTwainData.transferInfo.pendingXfers);
318 }
319 TTWAIN_EmptyMessageQueue();
320 return (TTWAIN_GetState() < TWAIN_TRANSFER_READY);
321 }
322 /*---------------------------------------------------------------------------*/
323 /*---------------------------------------------------------------------------*/
324 /* DATA SOURCE */
325 /*---------------------------------------------------------------------------*/
TTWAIN_DS(TUINT32 dg,TUINT32 dat,TUINT32 msg,void * pd)326 TW_INT16 TTWAIN_DS(TUINT32 dg, TUINT32 dat, TUINT32 msg,
327 void *pd) { /* Call the current source with a triplet */
328 int bOk = FALSE;
329 static TUINT32 nMemBuffer = 0;
330
331 PRINTF("%s dg=0x%x dat=0x%x msg=0x%x pd=0x%x\n", __FUNCTION__, dg, dat, msg,
332 pd);
333
334 assert(TTWAIN_GetState() >= TWAIN_SOURCE_OPEN);
335 TTwainData.resultCode = TWRC_FAILURE;
336 if (dg == DG_IMAGE) {
337 if (dat == DAT_IMAGEMEMXFER) {
338 if (msg == MSG_GET && pd != NULL) {
339 pTW_IMAGEMEMXFER pmxb = (pTW_IMAGEMEMXFER)pd;
340 pmxb->Compression = TWON_DONTCARE16;
341 pmxb->BytesPerRow = TWON_DONTCARE32;
342 pmxb->Columns = TWON_DONTCARE32;
343 pmxb->Rows = TWON_DONTCARE32;
344 pmxb->XOffset = TWON_DONTCARE32;
345 pmxb->YOffset = TWON_DONTCARE32;
346 pmxb->BytesWritten = TWON_DONTCARE32;
347 }
348 }
349 }
350 if (TTwainData.DSM_Entry) {
351 TTwainData.resultCode = (*TTwainData.DSM_Entry)(
352 &TTwainData.appId, &TTwainData.sourceId, (TW_UINT32)dg, (TW_UINT16)dat,
353 (TW_UINT16)msg, (TW_MEMREF)pd);
354 bOk = (TTwainData.resultCode == TWRC_SUCCESS);
355
356 if (dg == DG_CONTROL) {
357 switch (dat) {
358 case DAT_EVENT:
359 if (msg == MSG_PROCESSEVENT) {
360 if (((pTW_EVENT)pd)->TWMessage == MSG_XFERREADY) {
361 TTWAIN_SetState(TWAIN_TRANSFER_READY);
362 }
363 bOk = (TTwainData.resultCode == TWRC_DSEVENT);
364 }
365 break;
366
367 case DAT_CAPABILITY:
368 break;
369
370 case DAT_PENDINGXFERS:
371 if (msg == MSG_ENDXFER && bOk) {
372 TTWAIN_SetState(((pTW_PENDINGXFERS)pd)->Count ? TWAIN_TRANSFER_READY
373 : TWAIN_SOURCE_ENABLED);
374 }
375 if (msg == MSG_RESET && bOk) {
376 TTWAIN_SetState(TWAIN_SOURCE_ENABLED);
377 }
378 break;
379
380 case DAT_USERINTERFACE:
381 if (msg == MSG_ENABLEDS) {
382 if (TTwainData.resultCode == TWRC_FAILURE ||
383 TTwainData.resultCode == TWRC_CANCEL) {
384 TTWAIN_RecordError();
385 } else {
386 /* TTwainData.resultCode could be either SUCCESS or CHECKSTATUS */
387 TTWAIN_SetState(TWAIN_SOURCE_ENABLED);
388 bOk = TRUE;
389 }
390 }
391 if (msg == MSG_DISABLEDS && bOk) {
392 TTWAIN_SetState(TWAIN_SOURCE_OPEN);
393 #ifdef MACOSX
394 exitTwainSession(); // exited from TwainUI using close button
395 #endif
396 }
397 break;
398
399 case DAT_SETUPMEMXFER:
400 if (msg == MSG_GET && bOk) {
401 nMemBuffer = 0;
402 }
403 break;
404 } /* switch */
405 } else if (dg == DG_IMAGE) {
406 if (dat == DAT_IMAGENATIVEXFER || dat == DAT_IMAGEFILEXFER) {
407 /* Native and File transfers work much the same way. */
408 if (msg == MSG_GET) {
409 bOk = (TTwainData.resultCode == TWRC_XFERDONE);
410 switch (TTwainData.resultCode) {
411 case TWRC_XFERDONE:
412 case TWRC_CANCEL:
413 TTWAIN_SetState(TWAIN_TRANSFERRING);
414 /* Need to acknowledge end of transfer with */
415 /* DG_CONTROL / DAT_PENDINGXFERS / MSG_ENDXFER */
416 break;
417
418 case TWRC_FAILURE:
419 default:
420 /* Transfer failed (e.g. insufficient memory, write-locked file) */
421 /* check condition code for more info */
422 TTWAIN_SetState(TWAIN_TRANSFER_READY);
423 /* The image is still pending */
424 break;
425 } /* switch */
426 }
427 } else if (dat == DAT_IMAGEMEMXFER) {
428 if (msg == MSG_GET) {
429 bOk = FALSE;
430 switch (TTwainData.resultCode) {
431 case TWRC_SUCCESS:
432 case TWRC_XFERDONE:
433 bOk = TRUE;
434 nMemBuffer++;
435 TTWAIN_SetState(TWAIN_TRANSFERRING);
436 break;
437
438 case TWRC_FAILURE:
439 /* "If the failure occurred during the transfer of the first
440 buffer, the session is in State 6. If the failure occurred
441 on a subsequent buffer, the session is in State 7."
442 */
443 TTWAIN_SetState(nMemBuffer == 0 ? TWAIN_TRANSFER_READY
444 : TWAIN_TRANSFERRING);
445 break;
446
447 case TWRC_CANCEL:
448 /* Transfer cancelled, no state change. */
449 TTWAIN_BreakModalLoop();
450 break;
451 } /* switch */
452 }
453 }
454 }
455 }
456
457 /*
458 if (!bOk)
459 TTWAIN_RecordError();
460 */
461 return TTwainData.resultCode;
462 }
463 /*---------------------------------------------------------------------------*/
464 /*---------------------------------------------------------------------------*/
465 /* DATA SOURCE MANAGER */
466 /*---------------------------------------------------------------------------*/
TTWAIN_MGR(TUINT32 dg,TUINT32 dat,TUINT32 msg,void * pd)467 static int TTWAIN_MGR(TUINT32 dg, TUINT32 dat, TUINT32 msg, void *pd)
468 /* Call the Source Manager with a triplet */
469 {
470 int bOk = FALSE;
471 TTwainData.resultCode = TWRC_FAILURE;
472
473 if (TTwainData.DSM_Entry) {
474 TTwainData.resultCode =
475 (*TTwainData.DSM_Entry)(&TTwainData.appId, NULL, (TW_UINT32)dg,
476 (TW_UINT16)dat, (TW_UINT16)msg, (TW_MEMREF)pd);
477 bOk = (TTwainData.resultCode == TWRC_SUCCESS);
478 if (dg == DG_CONTROL) {
479 if (dat == DAT_IDENTITY) {
480 if (msg == MSG_OPENDS) {
481 if (bOk) {
482 /* Source opened - record identity for future triplets */
483 memcpy(&TTwainData.sourceId, pd, sizeof(TW_IDENTITY));
484 TTWAIN_SetState(TWAIN_SOURCE_OPEN);
485 } else { /*RecordError(ED_DSM_FAILURE);*/
486 TTWAIN_RecordError();
487 }
488 }
489 if (msg == MSG_CLOSEDS && bOk) {
490 TTWAIN_SetState(TWAIN_SM_OPEN);
491 }
492 }
493 if (dat == DAT_PARENT) {
494 if (msg == MSG_OPENDSM && bOk) {
495 TTWAIN_SetState(TWAIN_SM_OPEN);
496 }
497 if (msg == MSG_CLOSEDSM && bOk) {
498 TTWAIN_SetState(TWAIN_SM_LOADED);
499 }
500 }
501 }
502 }
503 return bOk;
504 }
505 /*---------------------------------------------------------------------------*/
506 /*---------------------------------------------------------------------------*/
507 /* ERRORS */
508 /*---------------------------------------------------------------------------*/
TTWAIN_GetConditionCode(void)509 TUINT32 TTWAIN_GetConditionCode(void) {
510 TW_STATUS twStatus;
511 TW_INT16 rcLast = TTwainData.resultCode;
512 TW_INT16 rc = TWRC_FAILURE;
513 twStatus.ConditionCode = TWCC_BUMMER;
514
515 if (TTWAIN_GetState() >= 4) {
516 /* get source status if open */
517 rc = TTWAIN_DS(DG_CONTROL, DAT_STATUS, MSG_GET, (TW_MEMREF)&twStatus);
518 } else if (TTWAIN_GetState() == 3) {
519 /* otherwise get source manager status */
520 rc = TTWAIN_MGR(DG_CONTROL, DAT_STATUS, MSG_GET, (TW_MEMREF)&twStatus);
521 }
522 TTwainData.resultCode = rcLast;
523
524 if (rc != TWRC_SUCCESS) return -1;
525 return twStatus.ConditionCode;
526 }
527 /*---------------------------------------------------------------------------*/
TTWAIN_GetResultCode(void)528 TUINT32 TTWAIN_GetResultCode(void) { return TTwainData.resultCode; }
529 /*---------------------------------------------------------------------------*/
TTWAIN_DSM_HasEntryPoint(void)530 int TTWAIN_DSM_HasEntryPoint(void) { return !!(TTwainData.DSM_Entry); }
531 /*---------------------------------------------------------------------------*/
TTWAIN_DoOneTransfer(void)532 static int TTWAIN_DoOneTransfer(void) {
533 int rc = FALSE;
534 switch (TTwainData.transferInfo.transferMech) {
535 case TTWAIN_TRANSFERMODE_NATIVE:
536 rc = TTWAIN_NativeXferHandler();
537 break;
538 case TTWAIN_TRANSFERMODE_FILE:
539 assert(!"NOT IMPL!");
540 /*TTWAIN_FileXferHandler(); */
541 break;
542 case TTWAIN_TRANSFERMODE_MEMORY:
543 rc = TTWAIN_MemoryXferHandler();
544 break;
545 } /* switch */
546
547 TTwainData.transferInfo.lastTransferWasOk = rc;
548 /* If inside ModalEventLoop, break out */
549 TTWAIN_BreakModalLoop();
550
551 /* Acknowledge transfer */
552 TTWAIN_EndXfer();
553 assert(TTWAIN_GetState() == TWAIN_TRANSFER_READY ||
554 TTWAIN_GetState() == TWAIN_SOURCE_ENABLED);
555 return rc;
556 }
557 /*---------------------------------------------------------------------------*/
TTWAIN_RegisterApp(int majorNum,int minorNum,int nLanguage,int nCountry,char * version,char * manufacter,char * family,char * product)558 void TTWAIN_RegisterApp(
559 int majorNum, int minorNum, /* app. revision*/
560 int nLanguage, /* (human) language (use TWLG_xxx from TWAIN.H) */
561 int nCountry, /* country (use TWCY_xxx from TWAIN.H) */
562 char *version, /* version info string */
563 char *manufacter, /* name of manufacter */
564 char *family, /* product family */
565 char *product) /* specific product */
566 {
567 memset(&TTwainData.appId, 0, sizeof(TTwainData.appId));
568 TTwainData.appId.Id =
569 0; /* init to 0, but Source Manager will assign THE real value*/
570 TTwainData.appId.Version.MajorNum = majorNum;
571 TTwainData.appId.Version.MinorNum = minorNum;
572 TTwainData.appId.Version.Language = nLanguage;
573 TTwainData.appId.Version.Country = nCountry;
574 TTwainData.appId.ProtocolMajor = TWON_PROTOCOLMAJOR;
575 TTwainData.appId.ProtocolMinor = TWON_PROTOCOLMINOR;
576 TTwainData.appId.SupportedGroups = DG_IMAGE | DG_CONTROL;
577 strcpy((char *)TTwainData.appId.Version.Info, version);
578 strcpy((char *)TTwainData.appId.Manufacturer, manufacter);
579 strcpy((char *)TTwainData.appId.ProductFamily, family);
580 strcpy((char *)TTwainData.appId.ProductName, product);
581 }
582 /*---------------------------------------------------------------------------*/
TTWAIN_AcquireNative(void * hwnd)583 void *TTWAIN_AcquireNative(void *hwnd) {
584 void *hnative = NULL;
585
586 TTwainData.transferInfo.lastTransferWasOk = FALSE;
587
588 if (TTwainData.transferInfo.transferMech != TTWAIN_TRANSFERMODE_NATIVE)
589 return 0;
590
591 hwnd = TTWAIN_GetValidHwnd(hwnd);
592 if (TTWAIN_GetState() < TWAIN_SOURCE_OPEN) {
593 if (!TTWAIN_OpenSourceManager(hwnd)) /* Bring up to state 4 */
594 {
595 char msg[2048];
596 snprintf(msg, sizeof(msg), "Unable to open Source Manager (%s)",
597 DSM_FILENAME);
598 TTWAIN_ErrorBox(msg);
599 return 0;
600 }
601 if (!TTWAIN_OpenDefaultSource())
602 /*TTWAIN_ReportLastError("Unable to open default Data Source.");*/
603 TTWAIN_RecordError();
604 else
605 assert(TTWAIN_GetState() == TWAIN_SOURCE_OPEN);
606 }
607
608 if (TTWAIN_GetState() >= TWAIN_SOURCE_OPEN)
609 hnative = TTWAIN_WaitForNativeXfer(hwnd);
610
611 if (!TTwainData.transferInfo.multiTransfer) {
612 /* shut everything down in the right sequence */
613 TTWAIN_AbortAllPendingXfers(); /* TRANSFER_READY or TRANSFERRING ->
614 SOURCE_ENABLED */
615 TTWAIN_UnloadSourceManager();
616 }
617
618 TTwainData.transferInfo.lastTransferWasOk = !!(hnative);
619 return hnative;
620 }
621 /*---------------------------------------------------------------------------*/
622 #ifdef _WIN32
623
624 typedef void(MyFun)(HWND);
625
626 /*it's an hack function to force bring to top the twain UI module window */
myHackEnumFunction(HWND hwnd,LPARAM lParam)627 static BOOL CALLBACK myHackEnumFunction(HWND hwnd, LPARAM lParam) {
628 MyFun *f = 0;
629
630 #define TITLESIZE (1024)
631 char title[TITLESIZE + 1];
632 int len;
633
634 GetWindowText(hwnd, (char *)&title, TITLESIZE);
635 if (title[0] == 0x00) return 1; /*continue the search....*/
636
637 len = strlen(TTwainData.sourceId.ProductName);
638 if (!len) return 0;
639
640 len--;
641
642 while (
643 len &&
644 (isdigit(TTwainData.sourceId.ProductName[len]) /*skip digit at the end*/
645 || TTwainData.sourceId.ProductName[len] == '.')) /*skip . */
646 len--;
647
648 if (len && !strncmp(title, TTwainData.sourceId.ProductName, len)) {
649 /*
650 char dbg_str[1024];
651 snprintf(dbg_str, sizeof(dbg_str), "set focus on 0x%8x %s\n",hwnd, title);
652 OutputDebugString(dbg_str);
653 */
654 f = (MyFun *)lParam;
655 f(hwnd);
656
657 return FALSE; /*it means stop the search...*/
658 }
659 return 1; /*continue the search....*/
660 }
661
662 /*---------------------------------------------------------------------------*/
663
myHackEnumFunction2(HWND hwnd,LPARAM lParam)664 static BOOL CALLBACK myHackEnumFunction2(HWND hwnd, LPARAM lParam) {
665 MyFun *f = 0;
666 char *ptr;
667
668 #define TITLESIZE (1024)
669 char title[TITLESIZE + 1];
670
671 GetWindowText(hwnd, (char *)&title, TITLESIZE);
672 if (title[0] == 0x00) return 1; /*continue the search....*/
673
674 ptr = strstr(title, TTwainData.sourceId.Manufacturer);
675 if (!ptr) return 1; /*continue the search....*/
676
677 f = (MyFun *)lParam;
678 f(hwnd);
679
680 return FALSE; /*it means stop the search...*/
681 }
682
683 /*---------------------------------------------------------------------------*/
684
bringToTop(HWND hwnd)685 static void bringToTop(HWND hwnd) { BringWindowToTop(hwnd); }
686
putToBottom(HWND hwnd)687 static void putToBottom(HWND hwnd) {
688 const int unused = 0;
689
690 BOOL rc = SetWindowPos(hwnd, // handle to window
691 HWND_BOTTOM, // placement-order handle
692 unused, // horizontal position
693 unused, // vertical position
694 unused, // width
695 unused, // height
696 SWP_ASYNCWINDOWPOS | SWP_NOMOVE |
697 SWP_NOSIZE // window-positioning options
698 );
699 }
700
myHackFunction(int v)701 static void myHackFunction(int v) {
702 BOOL rc;
703 if (v == 1)
704 rc = EnumWindows((WNDENUMPROC)myHackEnumFunction, (LPARAM)&bringToTop);
705 else
706 rc = EnumWindows((WNDENUMPROC)myHackEnumFunction, (LPARAM)&putToBottom);
707
708 if (rc) /* it means that myHackEnumFunction fails to find the proper window to
709 bring up or put down*/
710 {
711 if (v == 1)
712 rc = EnumWindows((WNDENUMPROC)myHackEnumFunction2, (LPARAM)&bringToTop);
713 else
714 rc = EnumWindows((WNDENUMPROC)myHackEnumFunction2, (LPARAM)&putToBottom);
715 }
716 }
717 #else
myHackFunction(int v)718 static void myHackFunction(int v) { /*it's empty...*/
719 }
720 #endif
721 /*---------------------------------------------------------------------------*/
TTWAIN_AcquireMemory(void * hwnd)722 int TTWAIN_AcquireMemory(void *hwnd) {
723 int rc = FALSE;
724 TTwainData.transferInfo.lastTransferWasOk = FALSE;
725
726 if (TTwainData.transferInfo.transferMech != TTWAIN_TRANSFERMODE_MEMORY)
727 return FALSE;
728
729 myHackFunction(1);
730
731 hwnd = TTWAIN_GetValidHwnd(hwnd);
732 if (TTWAIN_GetState() < TWAIN_SOURCE_OPEN) {
733 if (!TTWAIN_OpenSourceManager(hwnd)) /* Bring up to state 4 */
734 {
735 TTWAIN_ErrorBox("Unable to open Source Manager (" DSM_FILENAME ")");
736 return FALSE;
737 }
738 if (!TTWAIN_OpenDefaultSource())
739 /*TTWAIN_ReportLastError("Unable to open default Data Source.");*/
740 TTWAIN_RecordError();
741 else
742 assert(TTWAIN_GetState() == TWAIN_SOURCE_OPEN);
743 }
744
745 if (TTWAIN_GetState() >= TWAIN_SOURCE_OPEN)
746 rc = TTWAIN_WaitForMemoryXfer(hwnd);
747
748 if (!TTwainData.transferInfo.multiTransfer) {
749 /* shut everything down in the right sequence */
750 TTWAIN_AbortAllPendingXfers(); /* TRANSFER_READY or TRANSFERRING ->
751 SOURCE_ENABLED */
752 TTWAIN_UnloadSourceManager();
753 }
754
755 myHackFunction(0);
756
757 return TTwainData.transferInfo.lastTransferWasOk;
758 }
759 /*---------------------------------------------------------------------------*/
TTWAIN_StopAcquire(void)760 void TTWAIN_StopAcquire(void) { TTwainData.transferInfo.oneAtLeast = FALSE; }
761 /*---------------------------------------------------------------------------*/
TTWAIN_WaitForNativeXfer(void * hwnd)762 static void *TTWAIN_WaitForNativeXfer(void *hwnd) {
763 TTwainData.transferInfo.hDib = NULL;
764 if (TTWAIN_GetState() >= TWAIN_SOURCE_OPEN)
765 TTWAIN_WaitForXfer(hwnd);
766 else
767 TTWAIN_ErrorBox("TWAIN_WaitForNativeXfer called in state < 4.");
768 return TTwainData.transferInfo.hDib;
769 }
770 /*---------------------------------------------------------------------------*/
TTWAIN_WaitForMemoryXfer(void * hwnd)771 static int TTWAIN_WaitForMemoryXfer(void *hwnd) {
772 int rc = FALSE;
773 if (TTWAIN_GetState() >= TWAIN_SOURCE_OPEN)
774 rc = TTWAIN_WaitForXfer(hwnd);
775 else
776 TTWAIN_ErrorBox("TWAIN_WaitForNativeXfer called in state < 4.");
777 return rc;
778 }
779 /*---------------------------------------------------------------------------*/
TTWAIN_WaitForXfer(void * hwnd)780 static int TTWAIN_WaitForXfer(void *hwnd) {
781 int bWasEnabled;
782 int rc = FALSE;
783 /* Make up a valid window if we weren't given one */
784 hwnd = TTWAIN_GetValidHwnd(hwnd);
785 /* Disable the parent window during the modal acquire */
786 bWasEnabled = (TTWAIN_EnableWindow(hwnd, FALSE) == 0);
787
788 TTwainData.transferInfo.oneAtLeast = TRUE;
789 /*
790 TTWAIN_DS( DG_CONTROL,DAT_PENDINGXFERS, MSG_ENDXFER,
791 (TW_MEMREF)&TTwainData.transferInfo.pendingXfers);
792 */
793 do {
794 if (TTWAIN_GetState() == TWAIN_TRANSFER_READY)
795 rc = TTWAIN_DoOneTransfer();
796 else if (TTWAIN_GetState() >= TWAIN_SOURCE_ENABLED ||
797 TTWAIN_EnableSource(hwnd)) {
798 /* source is enabled, wait for transfer or source closed */
799 if (TTwainData.resultCode != TWRC_CANCEL)
800 TTWAIN_ModalEventLoop();
801 else {
802 TTWAIN_BreakModalLoop();
803 break;
804 }
805 } else
806 /*TTWAIN_ReportLastError("Failed to enable Data Source.");*/
807 TTWAIN_RecordError();
808 } while (TTwainData.transferInfo.pendingXfers.Count &&
809 TTwainData.transferInfo.oneAtLeast /*&& rc*/);
810
811 /* Re-enable the parent window if it was enabled */
812 TTWAIN_EnableWindow(hwnd, bWasEnabled);
813 return rc;
814 }
815 /*---------------------------------------------------------------------------*/
TTWAIN_FreeMemory(void * hMem)816 void TTWAIN_FreeMemory(void *hMem) {
817 free(hMem);
818 /*
819 if (hMem)
820 GLOBAL_FREE(hMem);
821 */
822 }
823 /*---------------------------------------------------------------------------*/
TTWAIN_ModalEventLoop(void)824 static void TTWAIN_ModalEventLoop(void) { TTWAIN_ModalEventLoopPD(); }
825 /*---------------------------------------------------------------------------*/
TTWAIN_BreakModalLoop(void)826 static void TTWAIN_BreakModalLoop(void) { TTwainData.breakModalLoop = TRUE; }
827 /*---------------------------------------------------------------------------*/
TTWAIN_EmptyMessageQueue(void)828 static void TTWAIN_EmptyMessageQueue(void) { TTWAIN_EmptyMessageQueuePD(); }
829 /*---------------------------------------------------------------------------*/
TTWAIN_NativeXferHandler(void)830 static int TTWAIN_NativeXferHandler(void) {
831 TW_UINT32 hNative;
832
833 assert(TTWAIN_GetState() == TWAIN_TRANSFER_READY);
834 if (TTWAIN_DS(DG_IMAGE, DAT_IMAGENATIVEXFER, MSG_GET, &hNative) ==
835 TWRC_XFERDONE)
836 TTwainData.transferInfo.hDib = (void *)hNative;
837 else
838 TTwainData.transferInfo.hDib = NULL;
839 return (!!TTwainData.transferInfo.hDib);
840 }
841 /*---------------------------------------------------------------------------*/
TTWAIN_MemoryXferHandler(void)842 static int TTWAIN_MemoryXferHandler(void) {
843 TW_IMAGEMEMXFER *imageMemXfer = 0;
844 TW_HANDLE imageMemXferH = 0;
845 TW_HANDLE transferBufferH = 0;
846 TW_SETUPMEMXFER setup;
847 TW_IMAGEINFO info;
848 TW_IMAGELAYOUT imageLayout;
849 TUINT32 nTransferDone;
850 TW_INT16 rc1, rc2, rc3, rc4, twRC2;
851 int ret = FALSE;
852 int stopScanning = 0;
853 UCHAR *transferBuffer = 0;
854 UCHAR *sourceBuffer = 0;
855 UCHAR *targetBuffer = 0;
856 unsigned int rows;
857 double pixSize;
858 int extraX = 0;
859 int extraY = 0;
860 TW_UINT32 rowsToCopy = 0;
861 TW_UINT32 rowsRemaining = 0;
862 TW_UINT32 bytesToCopy = 0;
863 TW_UINT32 bytesToWrap = 0;
864 TW_UINT32 memorySize = 0;
865 int imgInfoOk; /* on Mac often (always) is impossible to get the imageinfo
866 about
867 the transfer... so no I can't prealloc memory
868 and
869 do other checks about size etc...
870 */
871
872 /*printf("%s\n", __PRETTY_FUNCTION__);*/
873
874 memset(&info, 0, sizeof(TW_IMAGEINFO));
875 rc1 = TTWAIN_DS(DG_IMAGE, DAT_IMAGEINFO, MSG_GET, (TW_MEMREF)&info);
876 imgInfoOk = (rc1 == TWRC_SUCCESS);
877
878 /*printf("get image info returns %d\n", imgInfoOk);*/
879
880 rc4 = TTWAIN_DS(DG_IMAGE, DAT_IMAGELAYOUT, MSG_GET, &imageLayout);
881
882 /* determine the transfer buffer size */
883 rc2 = TTWAIN_DS(DG_CONTROL, DAT_SETUPMEMXFER, MSG_GET, (TW_MEMREF)&setup);
884 transferBufferH = GLOBAL_ALLOC(GMEM_FIXED, setup.Preferred);
885 if (!transferBufferH) return FALSE;
886 transferBuffer = (UCHAR *)GLOBAL_LOCK(transferBufferH);
887
888 if (imgInfoOk) {
889 pixSize = info.BitsPerPixel / 8.0;
890 memorySize = info.ImageLength * CEIL(info.ImageWidth * pixSize);
891 } else {
892 /* we need to allocate incrementally the memory needs to store the image*/
893 memorySize =
894 setup.Preferred; /* start using the setupmemxfer.preferred size*/
895 pixSize = 3;
896 }
897
898 if (TTwainData.transferInfo.usageMode == TTWAIN_MODE_UNLEASHED) {
899 /*
900 TTwainData.transferInfo = GLOBAL_ALLOC(GMEM_FIXED, memorySize);
901 */
902 TTwainData.transferInfo.memoryBuffer = (UCHAR *)malloc(memorySize);
903
904 if (!TTwainData.transferInfo.memoryBuffer) {
905 /*tmsg_error("unable to allocate memory!");*/
906 return FALSE;
907 }
908 if (imgInfoOk) {
909 TTwainData.transferInfo.memorySize = memorySize;
910 TTwainData.transferInfo.preferredLx = info.ImageWidth;
911 TTwainData.transferInfo.preferredLy = info.ImageLength;
912 } else {
913 TTwainData.transferInfo.memorySize = setup.Preferred;
914 TTwainData.transferInfo.preferredLx = 0;
915 TTwainData.transferInfo.preferredLy = 0;
916 }
917 }
918
919 extraX = info.ImageWidth - TTwainData.transferInfo.preferredLx;
920 extraY = info.ImageLength - TTwainData.transferInfo.preferredLy;
921
922 rowsRemaining = min(TTwainData.transferInfo.preferredLy, info.ImageLength);
923
924 targetBuffer = TTwainData.transferInfo.memoryBuffer;
925
926 /*clean-up the buffer
927 memset(targetBuffer, 0xff, TTwainData.transferInfo.memorySize);
928 */
929
930 imageMemXferH = GLOBAL_ALLOC(GMEM_FIXED, sizeof(TW_IMAGEMEMXFER));
931 if (!imageMemXferH) return FALSE;
932
933 imageMemXfer = (TW_IMAGEMEMXFER *)GLOBAL_LOCK(imageMemXferH);
934
935 imageMemXfer->Memory.TheMem = (char *)transferBuffer;
936 imageMemXfer->Memory.Length = setup.Preferred;
937 imageMemXfer->Memory.Flags = TWMF_APPOWNS | TWMF_POINTER;
938 TTwainData.transferInfo.pendingXfers.Count = 0;
939 /* transfer the data -- loop until done or canceled */
940 nTransferDone = 0;
941 do {
942 rc3 =
943 TTWAIN_DS(DG_IMAGE, DAT_IMAGEMEMXFER, MSG_GET, (TW_MEMREF)imageMemXfer);
944 nTransferDone++;
945 switch (rc3) {
946 case TWRC_SUCCESS:
947 PRINTF("IMAGEMEMXFER, GET, returns SUCCESS\n");
948 if (imgInfoOk) {
949 TW_UINT32 colsToCopy;
950 rowsToCopy = min(imageMemXfer->Rows, rowsRemaining);
951 colsToCopy = min(imageMemXfer->Columns,
952 (unsigned long)TTwainData.transferInfo.preferredLx);
953 bytesToCopy = CEIL(colsToCopy * pixSize);
954 bytesToWrap = CEIL(TTwainData.transferInfo.preferredLx * pixSize);
955 } else {
956 TW_UINT32 newMemorySize;
957 rowsToCopy = imageMemXfer->Rows;
958 bytesToCopy = imageMemXfer->BytesPerRow;
959 bytesToWrap = bytesToCopy;
960 newMemorySize =
961 (TTwainData.transferInfo.preferredLy + imageMemXfer->Rows) *
962 imageMemXfer->BytesPerRow;
963 if (TTwainData.transferInfo.memorySize < newMemorySize) {
964 TTwainData.transferInfo.memoryBuffer = (UCHAR *)realloc(
965 TTwainData.transferInfo.memoryBuffer, newMemorySize);
966 TTwainData.transferInfo.memorySize = newMemorySize;
967 targetBuffer =
968 TTwainData.transferInfo.memoryBuffer +
969 (TTwainData.transferInfo.preferredLy * imageMemXfer->BytesPerRow);
970 }
971 TTwainData.transferInfo.preferredLy += rowsToCopy;
972 if ((int)imageMemXfer->Columns > TTwainData.transferInfo.preferredLx)
973 TTwainData.transferInfo.preferredLx = imageMemXfer->Columns;
974 }
975
976 sourceBuffer = (UCHAR *)imageMemXfer->Memory.TheMem;
977 if (TTwainData.transferInfo.nextImageNeedsToBeInverted)
978 INVERT_BYTE(sourceBuffer, bytesToCopy)
979
980 for (rows = 0; rows < rowsToCopy; rows++) {
981 memcpy(targetBuffer, sourceBuffer, bytesToCopy);
982 targetBuffer += bytesToWrap;
983 sourceBuffer += imageMemXfer->BytesPerRow;
984 }
985 rowsRemaining -= rowsToCopy;
986 break;
987
988 case TWRC_XFERDONE:
989 PRINTF("IMAGEMEMXFER, GET, returns XFERDONE\n");
990 /*copy the last transfer data*/
991 if (imgInfoOk) {
992 TW_UINT32 colsToCopy;
993 rowsToCopy = min(imageMemXfer->Rows, rowsRemaining);
994 colsToCopy = min(imageMemXfer->Columns,
995 (unsigned long)TTwainData.transferInfo.preferredLx);
996 bytesToCopy = CEIL(colsToCopy * pixSize);
997 bytesToWrap = CEIL(TTwainData.transferInfo.preferredLx * pixSize);
998 } else {
999 TW_UINT32 newMemorySize;
1000 rowsToCopy = imageMemXfer->Rows;
1001 bytesToCopy = imageMemXfer->BytesPerRow;
1002 bytesToWrap = bytesToCopy;
1003 newMemorySize =
1004 (TTwainData.transferInfo.preferredLy + imageMemXfer->Rows) *
1005 imageMemXfer->BytesPerRow;
1006 if (TTwainData.transferInfo.memorySize < newMemorySize) {
1007 TTwainData.transferInfo.memoryBuffer = (UCHAR *)realloc(
1008 TTwainData.transferInfo.memoryBuffer, newMemorySize);
1009 TTwainData.transferInfo.memorySize = newMemorySize;
1010 targetBuffer =
1011 TTwainData.transferInfo.memoryBuffer +
1012 (TTwainData.transferInfo.preferredLy * imageMemXfer->BytesPerRow);
1013 }
1014 TTwainData.transferInfo.preferredLy += rowsToCopy;
1015 if ((int)imageMemXfer->Columns > TTwainData.transferInfo.preferredLx)
1016 TTwainData.transferInfo.preferredLx = imageMemXfer->Columns;
1017 }
1018 sourceBuffer = (UCHAR *)imageMemXfer->Memory.TheMem;
1019 if (TTwainData.transferInfo.nextImageNeedsToBeInverted)
1020 INVERT_BYTE(sourceBuffer, bytesToCopy)
1021
1022 for (rows = 0; rows < rowsToCopy; rows++) {
1023 memcpy(targetBuffer, sourceBuffer, bytesToCopy);
1024 targetBuffer += bytesToWrap;
1025 sourceBuffer += imageMemXfer->BytesPerRow;
1026 }
1027 rowsRemaining -= rowsToCopy;
1028 PRINTF("get pending xfers\n");
1029 twRC2 = TTWAIN_DS(DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER,
1030 (TW_MEMREF)&TTwainData.transferInfo.pendingXfers);
1031 if (twRC2 != TWRC_SUCCESS) {
1032 printf("pending xfers != success");
1033 ret = FALSE;
1034 goto done;
1035 }
1036 PRINTF(" pending count = %d\n",
1037 TTwainData.transferInfo.pendingXfers.Count);
1038 if (TTwainData.transferInfo.pendingXfers.Count == 0) {
1039 ret = TRUE;
1040 goto done;
1041 }
1042 if (TTwainData.transferInfo.pendingXfers.Count == 0xffff) {
1043 ret = TRUE;
1044 goto done;
1045 }
1046 if (TTwainData.transferInfo.pendingXfers.Count == 0xfffe) {
1047 ret = TRUE;
1048 goto done;
1049 }
1050 ret = TRUE;
1051 goto done;
1052
1053 case TWRC_CANCEL:
1054 TTWAIN_RecordError();
1055 twRC2 = TTWAIN_DS(DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER,
1056 (TW_MEMREF)&TTwainData.transferInfo.pendingXfers);
1057 if (twRC2 != TWRC_SUCCESS) {
1058 ret = FALSE;
1059 goto done;
1060 }
1061 if (TTwainData.transferInfo.pendingXfers.Count == 0) {
1062 ret = FALSE;
1063 goto done;
1064 }
1065 break;
1066
1067 case TWRC_FAILURE:
1068 PRINTF("IMAGEMEMXFER, GET, returns FAILURE\n");
1069 TTWAIN_RecordError();
1070 twRC2 = TTWAIN_DS(DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER,
1071 (TW_MEMREF)&TTwainData.transferInfo.pendingXfers);
1072 if (twRC2 != TWRC_SUCCESS) {
1073 ret = FALSE;
1074 goto done;
1075 }
1076 if (TTwainData.transferInfo.pendingXfers.Count == 0) {
1077 ret = FALSE;
1078 goto done;
1079 }
1080 break;
1081
1082 default:
1083 PRINTF("IMAGEMEMXFER, GET, returns ?!? Default handler called\n");
1084 /* Abort the image */
1085 TTWAIN_RecordError();
1086 twRC2 = TTWAIN_DS(DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER,
1087 (TW_MEMREF)&TTwainData.transferInfo.pendingXfers);
1088 if (twRC2 != TWRC_SUCCESS) {
1089 ret = FALSE;
1090 goto done;
1091 }
1092 if (TTwainData.transferInfo.pendingXfers.Count == 0) {
1093 ret = FALSE;
1094 goto done;
1095 }
1096 }
1097 } while (rc3 == TWRC_SUCCESS);
1098
1099 done:
1100 if (ret == TRUE) {
1101 if (TTwainData.callback.onDoneCb) {
1102 float xdpi, ydpi;
1103 TTWAIN_PIXTYPE pixType;
1104 xdpi = TTWAIN_Fix32ToFloat(info.XResolution);
1105 ydpi = TTWAIN_Fix32ToFloat(info.YResolution);
1106
1107 if (imgInfoOk) {
1108 xdpi = TTWAIN_Fix32ToFloat(info.XResolution);
1109 ydpi = TTWAIN_Fix32ToFloat(info.YResolution);
1110 switch (BB(info.PixelType, info.BitsPerPixel)) {
1111 case BB(TWPT_BW, 1):
1112 pixType = TTWAIN_BW;
1113 break;
1114 case BB(TWPT_GRAY, 8):
1115 pixType = TTWAIN_GRAY8;
1116 break;
1117 case BB(TWPT_RGB, 24):
1118 pixType = TTWAIN_RGB24;
1119 break;
1120 default:
1121 pixType = TTWAIN_RGB24;
1122 break;
1123 }
1124 } else {
1125 float lx = TTWAIN_Fix32ToFloat(imageLayout.Frame.Right) -
1126 TTWAIN_Fix32ToFloat(imageLayout.Frame.Left);
1127 float ly = TTWAIN_Fix32ToFloat(imageLayout.Frame.Bottom) -
1128 TTWAIN_Fix32ToFloat(imageLayout.Frame.Top);
1129
1130 xdpi = (float)TTwainData.transferInfo.preferredLx / lx;
1131 ydpi = (float)TTwainData.transferInfo.preferredLy / ly;
1132
1133 switch (imageMemXfer->BytesPerRow /
1134 TTwainData.transferInfo.preferredLx) {
1135 case 1:
1136 pixType = TTWAIN_GRAY8;
1137 break;
1138 case 3:
1139 pixType = TTWAIN_RGB24;
1140 break;
1141 default: {
1142 double b = (imageMemXfer->BytesPerRow /
1143 (double)TTwainData.transferInfo.preferredLx);
1144 if ((b >= 0.125) && (b < 8))
1145 pixType = TTWAIN_BW;
1146 else {
1147 printf("unable to det pix type assume RGB24\n");
1148 pixType = TTWAIN_RGB24;
1149 }
1150 break;
1151 }
1152 }
1153 }
1154 stopScanning = !TTwainData.callback.onDoneCb(
1155 TTwainData.transferInfo.memoryBuffer, pixType,
1156 TTwainData.transferInfo.preferredLx,
1157 TTwainData.transferInfo.preferredLy,
1158 TTwainData.transferInfo.preferredLx, xdpi, ydpi,
1159 TTwainData.callback.onDoneArg);
1160 #ifdef MACOSX
1161 PRINTF("stopScanning = %d\n", stopScanning);
1162 exitTwainSession();
1163 #endif
1164 }
1165 } else /*ret == FALSE*/
1166 {
1167 if (TTwainData.callback.onErrorCb) {
1168 TTwainData.callback.onErrorCb(TTwainData.callback.onErrorArg, 0);
1169 }
1170 }
1171
1172 if (imageMemXferH) {
1173 GLOBAL_UNLOCK(imageMemXferH);
1174 GLOBAL_FREE(imageMemXferH);
1175 }
1176
1177 if (transferBufferH) {
1178 GLOBAL_UNLOCK(transferBuffer);
1179 GLOBAL_FREE(transferBufferH);
1180 }
1181 return ret && !stopScanning;
1182 }
1183 /*---------------------------------------------------------------------------*/
TTWAIN_InitVar(void)1184 int TTWAIN_InitVar(void) {
1185 char *c;
1186 if (TTwainData.initDone) return TRUE;
1187
1188 TTwainData.DSM_Entry = 0;
1189 TTwainData.hwnd32SM = 0;
1190 TTwainData.twainAvailable = AVAIABLE_DONTKNOW;
1191 TTwainData.breakModalLoop = FALSE;
1192 TTwainData.UIStatus = FALSE;
1193 TTwainData.twainState = TWAIN_PRESESSION;
1194 TTwainData.transferInfo.hDib = 0;
1195 TTwainData.transferInfo.multiTransfer = TRUE;
1196 TTwainData.supportedCaps = 0;
1197 TTwainData.resultCode = 0;
1198 TTwainData.ErrRC = 0;
1199 TTwainData.ErrCC = 0;
1200 TTwainData.modalStatus = FALSE;
1201 TTwainData.appId.Id = 0;
1202 TTWAIN_ConvertRevStrToRevNum(RELEASE_STR, &TTwainData.appId.Version.MajorNum,
1203 &TTwainData.appId.Version.MinorNum);
1204 TTwainData.appId.Version.Language = TWLG_USA;
1205 TTwainData.appId.Version.Country = TWCY_USA;
1206 strcpy((char *)TTwainData.appId.Version.Info, TITLEBAR_STR);
1207
1208 TTwainData.appId.ProtocolMajor = TWON_PROTOCOLMAJOR;
1209 TTwainData.appId.ProtocolMinor = TWON_PROTOCOLMINOR;
1210 TTwainData.appId.SupportedGroups = DG_IMAGE | DG_CONTROL;
1211
1212 c = (char *)TTwainData.appId.Manufacturer;
1213 #ifdef MACOSX
1214 *c = strlen(COMPANY);
1215 c++;
1216 #endif
1217 strcpy(c, COMPANY);
1218
1219 c = (char *)TTwainData.appId.ProductFamily;
1220 #ifdef MACOSX
1221 *c = strlen(PRODUCT);
1222 c++;
1223 #endif
1224 strcpy(c, PRODUCT);
1225
1226 c = (char *)TTwainData.appId.ProductName;
1227 #ifdef MACOSX
1228 *c = strlen(TwProgramName);
1229 c++;
1230 #endif
1231 strcpy(c, TwProgramName);
1232
1233 TTwainData.initDone = TRUE;
1234 return TRUE;
1235 }
1236 /*---------------------------------------------------------------------------*/
TTWAIN_FreeVar(void)1237 static void TTWAIN_FreeVar(void) {
1238 if (TTwainData.supportedCaps) {
1239 /* MEMORY LEAK !
1240 GLOBAL_FREE(TTwainData.supportedCaps);
1241 */
1242 TTwainData.supportedCaps = 0;
1243 }
1244 }
1245 /*---------------------------------------------------------------------------*/
1246
1247 #ifdef __cplusplus
1248 }
1249 #endif
1250