home *** CD-ROM | disk | FTP | other *** search
/ Chip 2002 March / Chip_2002-03_cd1.bin / zkuste / delphi / kompon / d5 / SGSCAN.ZIP / Eztwain.c next >
C/C++ Source or Header  |  1998-07-14  |  56KB  |  1,972 lines

  1. // EZTWAIN.C - Easy TWAIN DLL main module
  2. //
  3. //     05/11/94    spike    initial version
  4. // 1.00    06/17/94    spike
  5. // 1.01    07/27/94    spike - added XferCount negotiation
  6. // 1.02 10/26/94    spike - fixed bug in ModalEventLoop (thanks to Bill DeVoe of HP)
  7. //                            replaced random flags with state tracking
  8. // 1.03 02/06/95    spike - fixed gross omissions in WriteDibToFile
  9. // 1.04 04/05/95    spike - added WriteNativeToFile, WriteNativeToFilename, FreeNative
  10. //                            added Get/SetCurrentUnits, SetCurrentPixelType
  11. //                            added SetCurrentResolution, SetCapOneValue
  12. //                            corrected bug in SelectImageSource
  13. // 1.05 04/02/97    spike - 32-bit version.
  14. //                            Correction to MessageHook, for thunking DSM.
  15. //                            Bugfix: 32-bit version of TWAIN_WriteDibToFile
  16. // 1.06 08/21/97    spike
  17. //                            Yet another correction to MessageHook.
  18. //                            Figured out how to export names 'as is' in 32-bit version.
  19.  
  20. #define VERSION 106        // version number, times 100.
  21.  
  22. //------------ Includes
  23.  
  24. //#include <assert.h>
  25. //#include <memory.h>        // memset, memcpy
  26.  
  27. #include "windows.h"
  28. #include "commdlg.h"
  29.  
  30. #ifdef _WIN32
  31. #ifndef _INC_VFW
  32. #include <vfw.h>
  33. #endif
  34. #else
  35. #include "commdlg.h"
  36. #endif
  37.  
  38. #include "twain.h"
  39.  
  40. #ifdef _WIN32
  41.   #define EZTAPI WINAPI
  42. #else
  43.   #define EZTAPI __export FAR PASCAL
  44. #endif
  45.  
  46. #include "eztwain.h"
  47.  
  48. //------------ Constants and Macros
  49.  
  50. #define STATIC static
  51. #ifdef __BORLANDC__
  52. #define _WIN32
  53. #endif
  54.  
  55. #ifdef _WIN32
  56.   #define INT32 int
  57.   #define DATAGROUP unsigned
  58.   #define DSM_FILENAME "TWAIN_32.DLL"
  59.   #define DSM_ENTRYPOINT "DSM_Entry"
  60.   #define IsValidHandle(h) (h!=NULL)
  61.   #define HUGEWRITE(fh, pb, bc) ((INT32)_lwrite(fh, pb, bc))
  62.   #define FMEMSET(p, v, n) memset(p, v, n);
  63.   #define FMEMCPY(p, q, n) memcpy(p, q, n);
  64. #else
  65.   #define INT32 long
  66.   #define DATAGROUP unsigned long
  67.   #define DSM_FILENAME "TWAIN.DLL"
  68.   #define DSM_ENTRYPOINT "DSM_ENTRY"
  69.   #define VALID_HANDLE 32
  70.   #define IsValidHandle(h) ((h!=0) && ((h) >= 32))
  71.   #define HUGEWRITE(fh, pb, bc) _hwrite(fh, pb, bc)
  72.   #define FMEMSET(p, v, n) _fmemset(p, v, n);
  73.   #define FMEMCPY(p, q, n) _fmemcpy(p, q, n);
  74. #endif
  75.  
  76. #define MAX_IMAGES 999
  77. #define TW_CALLBACK_REGISTERED 0xf0f0f
  78.  
  79. typedef enum {
  80.     ED_NONE,
  81.     ED_START_TRIPLET_ERRS,
  82.     ED_CAP_GET,                // MSG_GET triplet on a capability failed
  83.     ED_CAP_SET,                // MSG_SET triplet on capability failed
  84.     ED_DSM_FAILURE,            // TWAIN DSM returned TWRC_FAILURE
  85.     ED_DS_FAILURE,            // source returned TWRC_FAILURE
  86.     ED_END_TRIPLET_ERRS,
  87.     ED_NOT_STATE_4,            // operation invoked in wrong state
  88.     ED_NULL_HCON,            // MSG_GET returned a null container handle
  89.     ED_BAD_HCON,            // MSG_GET returned an invalid/unlockable container handle
  90.     ED_BAD_CONTYPE,            // returned container ConType is not valid.
  91.     ED_BAD_ITEMTYPE,        // returned container ItemType is not valid.
  92.     ED_CAP_GET_EMPTY,        // returned container has 0 items.
  93.     ED_CAP_SET_EMPTY,        // trying to restrict a cap to empty set
  94. } ErrorDetail;
  95.  
  96. const char *pszErrDescrip[] =
  97.     {    "[no details available]",
  98.         "",
  99.         "DAT_CAPABILITY/MSG_GET failed",
  100.         "DAT_CAPABILITY/MSG_SET failed",
  101.         "Source Manager operation failed",
  102.         "DataSource operation failed",
  103.         "",
  104.         "TWAIN session not in State 4 (Source Open)",
  105.         "MSG_GET returned a NULL container handle",
  106.         "MSG_GET returned an invalid container handle",
  107.         "Returned container is not valid type",
  108.         "Returned container has invalid ItemType",
  109.         "Returned container is empty",
  110.         "App and source found NO values in common",
  111.     };
  112.  
  113. const char *pszRC[] = {
  114.     "TWRC_SUCCESS",
  115.     "TWRC_FAILURE",
  116.     "TWRC_CHECKSTATUS ('tried hard')",
  117.     "TWRC_CANCEL",
  118.     "TWRC_DSEVENT",
  119.     "TWRC_NOTDSEVENT",
  120.     "TWRC_XFERDONE",
  121.     "TWRC_ENDOFLIST",
  122. };
  123.  
  124. const char *pszCC[] = {
  125.     "TWCC_SUCCESS",
  126.     "TWCC_BUMMER (Failure due to unknown causes)",
  127.     "TWCC_LOWMEMORY",
  128.     "TWCC_NODS (No Data Source)",
  129.     "TWCC_MAXCONNECTIONS (DS is connected to max possible apps)",
  130.     "TWCC_OPERATIONERROR (DS or DSM reported error, app shouldn't)",
  131.     "TWCC_BADCAP (Unknown capability)",
  132.     "7 (undefined)",
  133.     "8 (undefined)",
  134.     "TWCC_BADPROTOCOL (Unrecognized triplet)",
  135.     "TWCC_BADVALUE (Data parameter out of range)",
  136.     "TWCC_SEQERROR (Triplet out of sequence)",
  137.     "TWCC_BADDEST (Unknown dest. App/Src in DSM_Entry)",
  138. };
  139.  
  140. //------------ Global variables
  141.  
  142. STATIC int            iAvailable;            // TWAIN available: 0:unknown, -1:No, 1:Yes
  143. STATIC int            nState = 1;            // TWAIN state (per the standard)
  144. STATIC int            nErrDetail;            // detailed error code
  145. STATIC unsigned        nErrRC, nErrCC;        // result code and condition code for last error
  146. STATIC char            szMsg[256];            // scratch buffer for messages
  147. STATIC DSMENTRYPROC    pDSM_Entry;            // entry point of Data Source Manager (TWAIN.DLL)
  148. STATIC HANDLE        hDSMLib;            // handle of DSM
  149. STATIC TW_IDENTITY    AppId = {            // application identity structure
  150.     0,                                    // Id, filled in by DSM
  151.     { 1, 0, TWLG_USA, TWCY_USA, "<?>"},    // Version
  152.      TWON_PROTOCOLMAJOR,
  153.      TWON_PROTOCOLMINOR,
  154.      DG_IMAGE | DG_CONTROL,
  155.      "<?>",                                // Mfg
  156.      "<?>",                                // Family
  157.      "<?>"                                // Product
  158.      };
  159. STATIC TW_IDENTITY    SourceId;            // source identity structure
  160. STATIC BOOL            bHideUI;            // allow source u/i to be hidden
  161. STATIC TW_USERINTERFACE twUI;
  162. STATIC TW_PENDINGXFERS pendingXfers;
  163. STATIC HANDLE        hDib;                // bitmap returned by native transfer
  164. STATIC TW_INT16        rc;                    // result code
  165. STATIC HINSTANCE    hinstLib;            // instance handle for this DLL
  166.  
  167. STATIC HANDLE hDibList[MAX_IMAGES];
  168. STATIC TW_INT32 nDibs;
  169. STATIC HDIBCALLBACKPROC lpfnDibCallback;
  170. STATIC int hDibCallback_registered = 0;
  171.  
  172. const char szInsuffMem[] = "Insufficient Memory";    // error message
  173. STATIC int bTrace = 0;  // debugging helper
  174.  
  175. //------------ Forward declarations
  176.  
  177. void TWAIN_NativeXferReady(LPMSG pmsg);
  178. HWND CreateProxyWindow(void);
  179. unsigned Intersect16(unsigned wMask, unsigned nItems, TW_UINT16 far *pItem);
  180. unsigned BitCount(unsigned W);
  181. void TWAIN_ErrorBox(const char *szMsg);
  182. int RecordError(ErrorDetail ed);
  183. void ClearError(void);
  184. void TWAIN_ReportLastError(LPSTR lpzGeneral);
  185. // TW_UINT32 ToFix32(double r);
  186. // double Fix32ToFloat(TW_FIX32 fix);
  187. // above functions implemented on the Delphi side to avoid need for floating
  188. // point library functions --DSN 7/98
  189. void assert(int);
  190.  
  191. //------------ Public functions
  192. // the two functions below are implemented by hand vs. the C RTL so that the
  193. // resultant OBJ can be neatly linked into a Delphi DCU.
  194. void assert(int a)
  195. {
  196.   if (a == 0)
  197.       MessageBox(NULL, "Assertion failed", "EZTWAIN", MB_OK);
  198. }
  199.  
  200. void *memset(void *s, int c, size_t n)
  201. {
  202.     size_t j;
  203.     char *p;
  204.     p = (char *) s;
  205.  
  206.     for (j = 0; j < n; j++)
  207.         p[j] = (char) c;
  208.  
  209.     return s;
  210. }
  211.  
  212. void *memcpy(void *dest, const void *src, size_t n)
  213. {
  214.     size_t j;
  215.     char *pdest, *psrc;
  216.     pdest = (char *) dest;
  217.     psrc = (char *)src;
  218.     for (j = 0; j < n; j++)
  219.         pdest[j] = psrc[j];
  220.  
  221.     return dest;
  222. }
  223.  
  224. #ifdef _WIN32
  225.  
  226. // Win32 DLL main
  227. /*BOOL WINAPI DllMain(HANDLE hModule,
  228.                           ULONG  ulEvent,
  229.                           LPVOID lpReserved)
  230. {
  231.     return 1;
  232. }*/
  233.  
  234. #else
  235.  
  236. // Win16 DLL initialization and termination routines
  237. int CALLBACK __export LibMain(HINSTANCE hinst, WORD wDataSeg, WORD cbHeapSize, LPSTR lpszCmdLine)
  238. {
  239.     wDataSeg = wDataSeg; cbHeapSize = cbHeapSize; lpszCmdLine = lpszCmdLine;
  240.  
  241.     hinstLib = hinst;
  242.     return 1;        // indicate success
  243. } // LibMain
  244.  
  245.  
  246. int FAR PASCAL __export _WEP(int x)
  247. {
  248.     x = x;                // suppress 'is never used' warning
  249.     return 1;
  250. } // _WEP
  251.  
  252.  
  253. #endif
  254.  
  255.  
  256. void EZTAPI TWAIN_RegisterApp(    // record application information
  257.     int        nMajorNum, int nMinorNum,    // major and incremental revision of application. E.g.
  258.                                         // for version 2.1, nMajorNum == 2 and nMinorNum == 1
  259.     int        nLanguage,                    // language of this version (use TWLG_xxx from TWAIN.H)
  260.     int        nCountry,                    // country of this version (use TWCY_xxx from TWAIN.H)
  261.     LPSTR    lpszVersion,                // version info string e.g. "1.0b3 Beta release"
  262.     LPSTR    lpszMfg,                    // name of manufacturer/developer e.g. "Crazbat Software"
  263.     LPSTR    lpszFamily,                    // product family e.g. "BitStomper"
  264.     LPSTR    lpszProduct)                // specific product e.g. "BitStomper Deluxe Pro"
  265. {
  266.      AppId.Id = 0;                        // init to 0, but Source Manager will assign real value
  267.     AppId.Version.MajorNum = nMajorNum;
  268.     AppId.Version.MinorNum = nMinorNum;
  269.     AppId.Version.Language = nLanguage;
  270.     AppId.Version.Country  = nCountry;
  271.     lstrcpy (AppId.Version.Info,  lpszVersion);
  272.  
  273.     AppId.ProtocolMajor =    TWON_PROTOCOLMAJOR;
  274.      AppId.ProtocolMinor =    TWON_PROTOCOLMINOR;
  275.      AppId.SupportedGroups =  DG_IMAGE | DG_CONTROL;
  276.     lstrcpy (AppId.Manufacturer,  lpszMfg);
  277.     lstrcpy (AppId.ProductFamily, lpszFamily);
  278.     lstrcpy (AppId.ProductName,   lpszProduct);
  279.  
  280. } // TWAIN_RegisterApp
  281.  
  282.  
  283. int EZTAPI TWAIN_SelectImageSource(HWND hwnd)
  284. {
  285.  
  286.     int fSuccess = FALSE;
  287.     int fProxyWindow = FALSE;
  288.  
  289.     if (!IsWindow(hwnd)) {
  290.         if (hwnd != NULL) {
  291.             TWAIN_ErrorBox("TWAIN_SelectImageSource: window handle is invalid");
  292.             return FALSE;
  293.         }
  294.         hwnd = CreateProxyWindow();
  295.         if (!IsWindow(hwnd)) {
  296.             TWAIN_ErrorBox("TWAIN_SelectImageSource: Unable to create proxy window");
  297.             return FALSE;
  298.         }
  299.         fProxyWindow = TRUE;
  300.     }
  301.     if (TWAIN_LoadSourceManager()) {
  302.         if (TWAIN_OpenSourceManager(hwnd)) {
  303.             TW_IDENTITY    NewSourceId;
  304. #ifdef _WIN32
  305.             FMEMSET(&NewSourceId, 0, sizeof NewSourceId);
  306. #else
  307.             // I will settle for the system default.  Shouldn't I get a highlight
  308.             // on system default without this call?
  309.             TWAIN_Mgr(DG_CONTROL, DAT_IDENTITY, MSG_GETDEFAULT, &NewSourceId);
  310. #endif
  311.             // Post the Select Source dialog
  312.             fSuccess = TWAIN_Mgr(DG_CONTROL, DAT_IDENTITY, MSG_USERSELECT, &NewSourceId);
  313.              TWAIN_CloseSourceManager(hwnd);
  314.          } else {
  315.             TWAIN_ErrorBox("Unable to open Source Manager (" DSM_FILENAME ")");
  316.          }
  317.          TWAIN_UnloadSourceManager();
  318.     } else {
  319.         TWAIN_ErrorBox("Unable to load Source Manager (" DSM_FILENAME ")");
  320.     }
  321.      if (fProxyWindow) DestroyWindow(hwnd);
  322.  
  323.     return fSuccess;
  324. } // TWAIN_SelectImageSource
  325.  
  326.  
  327. HANDLE EZTAPI TWAIN_AcquireNative(HWND hwnd, unsigned wPixTypes)
  328. {
  329.     int fProxyWindow = FALSE;
  330.     hDib = NULL;
  331.     ClearError();            // clear error detail
  332.     TWAIN_ClearDibList();
  333.  
  334.     if (!IsWindow(hwnd)) {
  335.         // hwnd isn't a valid window handle - most likely NULL
  336.         hwnd = CreateProxyWindow();
  337.         if (hwnd) fProxyWindow = TRUE;
  338.     }
  339.     if (!IsWindow(hwnd)) {
  340.         TWAIN_ErrorBox("Unable to create proxy window");
  341.     } else if (!TWAIN_LoadSourceManager()) {
  342.         TWAIN_ErrorBox("Unable to load Source Manager (" DSM_FILENAME ")");
  343.     } else if (!TWAIN_OpenSourceManager(hwnd)) {
  344.         TWAIN_ErrorBox("Unable to open Source Manager (" DSM_FILENAME ")");
  345.      } else if (!TWAIN_OpenDefaultSource()) {
  346.         TWAIN_ReportLastError("Unable to open default Data Source.");
  347.     } else if (!TWAIN_NegotiatePixelTypes(wPixTypes)) {
  348.         TWAIN_ReportLastError("Failed to negotiate Pixel Type.");
  349.     } else if (!TWAIN_EnableSource(hwnd)) {
  350.         TWAIN_ReportLastError("Failed to enable Data Source.");
  351.     } else {
  352.         EnableWindow(hwnd, FALSE);
  353.         // source is enabled, wait for transfer or source closed
  354.         TWAIN_ModalEventLoop();
  355.  
  356.         EnableWindow(hwnd, TRUE);
  357.     }
  358.  
  359.     // shut everything down in the right sequence
  360.     // these routines do nothing if the corresponding 'open' failed
  361.     TWAIN_DisableSource();
  362.     TWAIN_CloseSource();
  363.      TWAIN_CloseSourceManager(hwnd);
  364.      TWAIN_UnloadSourceManager();
  365.  
  366.      if (fProxyWindow) {
  367.         DestroyWindow(hwnd);
  368.      }
  369.  
  370.     return hDib;
  371. } // TWAIN_AcquireNative
  372.  
  373.  
  374. void EZTAPI TWAIN_FreeNative(HANDLE hdib)
  375. // Release the memory allocated to a native format image, as returned by TWAIN_AcquireNative.
  376. // (For those coding in C or C++, this is just a call to GlobalFree.)
  377. {
  378.     if (hdib) GlobalFree(hdib);
  379. } // TWAIN_FreeNative
  380.  
  381.  
  382.  
  383. int EZTAPI TWAIN_AcquireToClipboard(HWND hwndApp, unsigned wPixTypes)
  384. // Like AcquireNative, but puts the resulting image, if any, into the system clipboard.
  385. // Useful for environments like Visual Basic where it is hard to make direct use of a DIB handle.
  386. // A return value of 1 indicates success, 0 indicates failure.
  387. {
  388.     int fOk = FALSE;
  389.     HANDLE hDib = TWAIN_AcquireNative(hwndApp, wPixTypes);
  390.     if (hDib) {
  391.         if (OpenClipboard(hwndApp)) {
  392.             if (EmptyClipboard()) {
  393.                 SetClipboardData(CF_DIB, hDib);
  394.                 fOk = TRUE;
  395.                 hDib = NULL;
  396.             }
  397.             CloseClipboard();
  398.         }
  399.         if (hDib) {
  400.             // something went wrong, recycle the image
  401.             GlobalFree(hDib);
  402.         }
  403.     }
  404.     return fOk;        // failed
  405. } // TWAIN_AcquireToClipboard
  406.  
  407.  
  408. int EZTAPI TWAIN_AcquireToFilename(HWND hwndApp, char *pszFile)
  409. // Adapted from a routine by David D. Henseler (ddh) of SOLUTIONS GmbH
  410. {
  411.     int result = -1;
  412.     HANDLE    hDib = TWAIN_AcquireNative(hwndApp, TWAIN_ANYTYPE);
  413.     if (hDib) {
  414.         result = TWAIN_WriteNativeToFilename(hDib, pszFile);
  415.         TWAIN_FreeNative(hDib);
  416.     }
  417.     return result;
  418. } // TWAIN_AcquireToFile
  419.  
  420. //--------- Callback mechanism -------------
  421. // These routines, added by DSN 7/98, allow the user to specify an
  422. // optional callback function to be called each time a new image comes
  423. // in.  This can be a potentially powerful way to increase the primary
  424. // application's efficiency, because upon receipt of an hdib the app
  425. // could start a background thread to begin processing the images as
  426. // needed.  Why bother with this?  Because on my Pentium 150, the Windows
  427. // NT task monitor indicates that when I download images at 112kbps that
  428. // I'm only using 15% of the processor's power, and the remaining 85% of
  429. // the time it is idle!  It's silly to wait to begin processing because
  430. // there's so much untapped processing capacity here.
  431.  
  432. void EZTAPI TWAIN_RegisterCallback(HDIBCALLBACKPROC *fxn)
  433. {
  434.       lpfnDibCallback = fxn;
  435.       hDibCallback_registered = TW_CALLBACK_REGISTERED;  // our signature, because I don't trust
  436.                                                      // the supposed initialization to zero
  437.                                                      // by the compiler
  438. }
  439.  
  440. void EZTAPI TWAIN_UnRegisterCallback()
  441. {
  442.       lpfnDibCallback = NULL;
  443.       hDibCallback_registered = TW_CALLBACK_REGISTERED;
  444. }
  445.  
  446. ///////////////////////////////////////////////////////////////////////
  447. // DIB utilities
  448.  
  449. void EZTAPI TWAIN_ClearDibList()
  450. /// new; added by DSN
  451. /// note: user is responsible for calling TWAIN_FreeNative *before*
  452. /// calling this function!
  453.  
  454. {
  455.       int i;
  456.       for (i = 0; i < MAX_IMAGES; i++)
  457.              hDibList[i] = 0;
  458.       nDibs = 0;
  459. }
  460.  
  461. int EZTAPI TWAIN_GetNumDibs()
  462. {
  463.       return nDibs;
  464. }
  465.  
  466. HANDLE EZTAPI TWAIN_GetDib(int n)
  467. {
  468.       return hDibList[n];
  469. }
  470. int EZTAPI TWAIN_DibDepth(HANDLE hdib)
  471. {
  472.     LPBITMAPINFOHEADER pbi = (LPBITMAPINFOHEADER)GlobalLock(hdib);
  473.     int D = pbi->biBitCount;
  474.     GlobalUnlock(hdib);
  475.     return D;
  476. } // TWAIN_DibDepth
  477.  
  478. int EZTAPI TWAIN_DibWidth(HANDLE hdib)
  479. {
  480.     LPBITMAPINFOHEADER pbi = (LPBITMAPINFOHEADER)GlobalLock(hdib);
  481.     int W = (int)pbi->biWidth;
  482.     GlobalUnlock(hdib);
  483.     return W;
  484. } // TWAIN_DibWidth
  485.  
  486.  
  487. int EZTAPI TWAIN_DibHeight(HANDLE hdib)
  488. {
  489.     LPBITMAPINFOHEADER pbi = (LPBITMAPINFOHEADER)GlobalLock(hdib);
  490.     int H = (int)pbi->biHeight;
  491.     GlobalUnlock(hdib);
  492.     return H;
  493. } // TWAIN_DibHeight
  494.  
  495.  
  496. static int DibNumColors(VOID FAR *pv)
  497. {
  498.      LPBITMAPINFOHEADER    lpbi = ((LPBITMAPINFOHEADER)pv);
  499.      LPBITMAPCOREHEADER    lpbc = ((LPBITMAPCOREHEADER)pv);
  500.  
  501.     int nColors;
  502.  
  503.      if (lpbi->biSize == sizeof(BITMAPCOREHEADER)) {
  504.         nColors = 1 << lpbc->bcBitCount;
  505.      } else if (lpbi->biClrUsed == 0) {
  506.         nColors = 1 << lpbi->biBitCount;
  507.     } else {
  508.         nColors = (int)lpbi->biClrUsed;
  509.     }
  510.     if (nColors > 256) nColors = 0;
  511.     return nColors;
  512. } // DibNumColors
  513.  
  514.  
  515. int EZTAPI TWAIN_DibNumColors(HANDLE hdib)
  516. // given a DIB handle, return the number of palette entries: 0,2,16, or 256
  517. {
  518.     VOID FAR *pv = GlobalLock(hdib);
  519.     int nColors = DibNumColors(pv);
  520.     GlobalUnlock(hdib);
  521.     return nColors;
  522. }
  523.  
  524.  
  525. //---------------------------------------------------------------------------
  526.  
  527. const PALETTEENTRY peStock256[256] = {
  528.     // from 0 .. 9 are Windows fixed colors
  529.      0,   0,   0, 0,    // 000 always black
  530.    128,   0,   0, 0,    // 001 dark red
  531.      0, 128,   0, 0,    // 002 dark green
  532.    128, 128,   0, 0,    // 003 dark brown
  533.      0,   0, 128, 0,    // 004 dark blue
  534.     128,   0, 128, 0,    // 005 dark purple
  535.      0, 128, 128, 0,    // 006 dark teal
  536.    192, 192, 192, 0,    // 007 light gray
  537.     192, 220, 192, 0,    // 008 pale green
  538.    166, 202, 240, 0,    // 009 sky blue
  539.       4,   4,   4, 4,    // 010 dark gray ramp
  540.      8,   8,   8, 4,    // 011
  541.      12,  12,  12, 4,    // 012
  542.     17,  17,  17, 4,    // 013
  543.      22,  22,  22, 4,    // 014
  544.      28,  28,  28, 4,    // 015
  545.     34,  34,  34, 4,    // 016
  546.     41,  41,  41, 4,    // 017
  547.     85,  85,  85, 4,    // 018
  548.     77,  77,  77, 4,    // 019
  549.      66,  66,  66, 4,    // 020
  550.      57,  57,  57, 4,    // 021
  551.    255, 124, 128, 4,    // 022
  552.    255,  80,  80, 4,    // 023
  553.    214,   0, 147, 4,    // 024
  554.    204, 236, 255, 4,    // 025
  555.    239, 214, 198, 4,    // 026
  556.    231, 231, 214, 4,    // 027
  557.    173, 169, 144, 4,    // 028
  558.     51,   0,   0, 4,    // 029
  559.     102,   0,   0, 4,    // 030
  560.    153,   0,   0, 4,    // 031 
  561.    204,   0,   0, 4,    // 032
  562.      0,  51,   0, 4,    // 033
  563.     51,  51,   0, 4,    // 034
  564.    102,  51,   0, 4,    // 035
  565.    153,  51,   0, 4,    // 036
  566.    204,  51,   0, 4,    // 037
  567.    255,  51,   0, 4,    // 038
  568.       0, 102,   0, 4,    // 039
  569.     51, 102,   0, 4,    // 040
  570.    102, 102,   0, 4,    // 041
  571.     153, 102,   0, 4,    // 042
  572.     204, 102,   0, 4,    // 043
  573.     255, 102,   0, 4,    // 044
  574.      0, 153,   0, 4,    // 045     
  575.     51, 153,   0, 4,    // 046
  576.    102, 153,   0, 4,    // 047
  577.     153, 153,   0, 4,    // 048
  578.    204, 153,   0, 4,    // 049
  579.    255, 153,   0, 4,    // 050
  580.      0, 204,   0, 4,    // 051
  581.     51, 204,   0, 4,    // 052
  582.    102, 204,   0, 4,    // 053
  583.     153, 204,   0, 4,    // 054
  584.     204, 204,   0, 4,    // 055
  585.    255, 204,   0, 4,    // 056
  586.    102, 255,   0, 4,    // 057
  587.    153, 255,   0, 4,    // 058
  588.    204, 255,   0, 4,    // 059
  589.      0,   0,  51, 4,    // 060
  590.      51,   0,  51, 4,    // 061
  591.    102,   0,  51, 4,    // 062
  592.    153,   0,  51, 4,    // 063
  593.    204,   0,  51, 4,    // 064
  594.    255,   0,  51, 4,    // 065
  595.      0,  51,  51, 4,    // 066
  596.     51,  51,  51, 4,    // 067
  597.    102,  51,  51, 4,    // 068
  598.    153,  51,  51, 4,    // 069
  599.    204,  51,  51, 4,    // 070
  600.     255,  51,  51, 4,    // 071
  601.      0, 102,  51, 4,    // 072
  602.      51, 102,  51, 4,    // 073
  603.    102, 102,  51, 4,    // 074
  604.    153, 102,  51, 4,    // 075
  605.     204, 102,  51, 4,    // 076
  606.    255, 102,  51, 4,    // 077
  607.       0, 153,  51, 4,    // 078
  608.     51, 153,  51, 4,    // 079
  609.     102, 153,  51, 4,    // 080
  610.    153, 153,  51, 4,    // 081
  611.     204, 153,  51, 4,    // 082
  612.    255, 153,  51, 4,    // 083
  613.      0, 204,  51, 4,    // 084
  614.     51, 204,  51, 4,    // 085
  615.    102, 204,  51, 4,    // 086
  616.    153, 204,  51, 4,    // 087
  617.     204, 204,  51, 4,    // 088
  618.     255, 204,  51, 4,    // 089
  619.     51, 255,  51, 4,    // 090
  620.    102, 255,  51, 4,    // 091
  621.     153, 255,  51, 4,    // 092
  622.    204, 255,  51, 4,    // 093
  623.    255, 255,  51, 4,    // 094
  624.      0,   0, 102, 4,    // 095
  625.     51,   0, 102, 4,    // 096
  626.    102,   0, 102, 4,    // 097
  627.    153,   0, 102, 4,    // 098
  628.     204,   0, 102, 4,    // 099
  629.    255,   0, 102, 4,    // 100
  630.      0,  51, 102, 4,    // 101
  631.     51,  51, 102, 4,    // 102
  632.    102,  51, 102, 4,    // 103
  633.    153,  51, 102, 4,    // 104
  634.    204,  51, 102, 4,    // 105
  635.    255,  51, 102, 4,    // 106
  636.       0, 102, 102, 4,    // 107
  637.     51, 102, 102, 4,    // 108
  638.    102, 102, 102, 4,    // 109
  639.     153, 102, 102, 4,    // 110
  640.    204, 102, 102, 4,    // 111
  641.       0, 153, 102, 4,    // 112
  642.     51, 153, 102, 4,    // 113
  643.     102, 153, 102, 4,    // 114
  644.    153, 153, 102, 4,    // 115
  645.     204, 153, 102, 4,    // 116
  646.    255, 153, 102, 4,    // 117
  647.      0, 204, 102, 4,    // 118
  648.     51, 204, 102, 4,    // 119
  649.    153, 204, 102, 4,    // 120
  650.    204, 204, 102, 4,    // 121
  651.     255, 204, 102, 4,    // 122
  652.       0, 255, 102, 4,    // 123
  653.     51, 255, 102, 4,    // 124
  654.    153, 255, 102, 4,    // 125
  655.    204, 255, 102, 4,    // 126
  656.     255,   0, 204, 4,    // 127
  657.    204,   0, 255, 4,    // 128
  658.      0, 153, 153, 4,    // 129
  659.    153,  51, 153, 4,    // 130
  660.    153,   0, 153, 4,    // 131
  661.    204,   0, 153, 4,    // 132
  662.      0,   0, 153, 4,    // 133
  663.     51,  51, 153, 4,    // 134
  664.    102,   0, 153, 4,    // 135
  665.    204,  51, 153, 4,    // 136
  666.    255,   0, 153, 4,    // 137
  667.      0, 102, 153, 4,    // 138
  668.     51, 102, 153, 4,    // 139
  669.    102,  51, 153, 4,    // 140
  670.    153, 102, 153, 4,    // 141
  671.    204, 102, 153, 4,    // 142
  672.    255,  51, 153, 4,    // 143
  673.     51, 153, 153, 4,    // 144
  674.    102, 153, 153, 4,    // 145
  675.     153, 153, 153, 4,    // 146
  676.    204, 153, 153, 4,    // 147
  677.     255, 153, 153, 4,    // 148
  678.      0, 204, 153, 4,    // 149
  679.      51, 204, 153, 4,    // 150
  680.    102, 204, 102, 4,    // 151
  681.    153, 204, 153, 4,    // 152
  682.    204, 204, 153, 4,    // 153
  683.     255, 204, 153, 4,    // 154
  684.       0, 255, 153, 4,    // 155
  685.      51, 255, 153, 4,    // 156
  686.     102, 204, 153, 4,    // 157
  687.    153, 255, 153, 4,    // 158
  688.    204, 255, 153, 4,    // 159
  689.    255, 255, 153, 4,    // 160
  690.      0,   0, 204, 4,    // 161
  691.     51,   0, 153, 4,    // 162
  692.    102,   0, 204, 4,    // 163
  693.    153,   0, 204, 4,    // 164
  694.    204,   0, 204, 4,    // 165
  695.      0,  51, 153, 4,    // 166
  696.     51,  51, 204, 4,    // 167
  697.    102,  51, 204, 4,    // 168
  698.    153,  51, 204, 4,    // 169
  699.     204,  51, 204, 4,    // 170
  700.    255,  51, 204, 4,    // 171
  701.      0, 102, 204, 4,    // 172
  702.     51, 102, 204, 4,    // 173
  703.    102, 102, 153, 4,    // 174
  704.    153, 102, 204, 4,    // 175
  705.    204, 102, 204, 4,    // 176
  706.    255, 102, 153, 4,    // 177
  707.      0, 153, 204, 4,    // 178
  708.     51, 153, 204, 4,    // 179
  709.     102, 153, 204, 4,    // 180
  710.    153, 153, 204, 4,    // 181
  711.     204, 153, 204, 4,    // 182
  712.     255, 153, 204, 4,    // 183
  713.       0, 204, 204, 4,    // 184
  714.      51, 204, 204, 4,    // 185
  715.    102, 204, 204, 4,    // 186
  716.    153, 204, 204, 4,    // 187
  717.    204, 204, 204, 4,    // 188
  718.    255, 204, 204, 4,    // 189
  719.       0, 255, 204, 4,    // 190
  720.      51, 255, 204, 4,    // 191
  721.    102, 255, 153, 4,    // 192
  722.    153, 255, 204, 4,    // 193
  723.    204, 255, 204, 4,    // 194
  724.    255, 255, 204, 4,    // 195
  725.     51,   0, 204, 4,    // 196
  726.    102,   0, 255, 4,    // 197
  727.    153,   0, 255, 4,    // 198
  728.      0,  51, 204, 4,    // 199
  729.     51,  51, 255, 4,    // 200
  730.    102,  51, 255, 4,    // 201
  731.    153,  51, 255, 4,    // 202
  732.    204,  51, 255, 4,    // 203
  733.     255,  51, 255, 4,    // 204
  734.      0, 102, 255, 4,    // 205
  735.     51, 102, 255, 4,    // 206
  736.    102, 102, 204, 4,    // 207
  737.    153, 102, 255, 4,    // 208
  738.    204, 102, 255, 4,    // 209
  739.    255, 102, 204, 4,    // 210
  740.       0, 153, 255, 4,    // 211
  741.     51, 153, 255, 4,    // 212
  742.    102, 153, 255, 4,    // 213
  743.     153, 153, 255, 4,    // 214
  744.    204, 153, 255, 4,    // 215
  745.     255, 153, 255, 4,    // 216
  746.      0, 204, 255, 4,    // 217
  747.      51, 204, 255, 4,    // 218
  748.    102, 204, 255, 4,    // 219
  749.    153, 204, 255, 4,    // 220
  750.    204, 204, 255, 4,    // 221
  751.    255, 204, 255, 4,    // 222
  752.     51, 255, 255, 4,    // 223
  753.     102, 255, 204, 4,    // 224
  754.     153, 255, 255, 4,    // 225
  755.    204, 255, 255, 4,    // 226
  756.    255, 102, 102, 4,    // 227
  757.    102, 255, 102, 4,    // 228
  758.    255, 255, 102, 4,    // 229
  759.    102, 102, 255, 4,    // 230
  760.    255, 102, 255, 4,    // 231
  761.    102, 255, 255, 4,    // 232
  762.    165,   0,  33, 4,    // 233
  763.     95,  95,  95, 4,    // 234
  764.    119, 119, 119, 4,    // 235 
  765.    134, 134, 134, 4,    // 236
  766.    150, 150, 150, 4,    // 237
  767.     203, 203, 203, 4,    // 238
  768.     178, 178, 178, 4,    // 239
  769.    215, 215, 215, 4,    // 240
  770.    221, 221, 221, 4,    // 241
  771.    227, 227, 227, 4,    // 242
  772.    234, 234, 234, 4,    // 243
  773.    241, 241, 241, 4,    // 244
  774.    248, 248, 248, 4,    // 245
  775.    // 246 - 255 are Windows fixed colors    
  776.     255, 251, 240, 0,    // 246
  777.     160, 160, 164, 0,    // 247
  778.    128, 128, 128, 0,    // 248
  779.     255,   0,   0, 0,    // 249
  780.      0, 255,   0, 0,    // 250
  781.     255, 255,   0, 0,    // 251
  782.      0,   0, 255, 0,    // 252
  783.    255,   0, 255, 0,    // 253
  784.      0, 255, 255, 0,    // 254
  785.    255, 255, 255, 0,    // 255 always white 
  786. };
  787.  
  788. HPALETTE EZTAPI TWAIN_CreateDibPalette (HANDLE hdib)
  789. // given a pointer to a locked DIB, returns a handle to a plausible logical
  790. // palette to be used for rendering the DIB
  791. // For 24-bit dibs, returns a default palette.
  792. {
  793.     HPALETTE            hPalette = NULL;
  794.  
  795.     LPBITMAPINFOHEADER    lpbmi = (LPBITMAPINFOHEADER)GlobalLock(hdib);
  796.  
  797.     if (lpbmi) {
  798.         WORD nColors = TWAIN_DibNumColors(hdib);            // size of DIB palette
  799.         WORD nEntries = nColors ? nColors : 256;            // size of palette to create
  800.         // allocate logical palette structure
  801.          LOGPALETTE *pPal = (LOGPALETTE*)LocalAlloc(LPTR,
  802.                     sizeof(LOGPALETTE) + nEntries * sizeof(PALETTEENTRY));
  803.         if (pPal) {
  804.             // Fill in the palette entries
  805.             pPal->palNumEntries = nEntries;
  806.             pPal->palVersion    = 0x300;            // Windows 3.0 or later
  807.             if (nColors) {
  808.                 // from the DIB color table
  809.                 // Get a pointer to the color table
  810.                 RGBQUAD FAR *pRgb = (RGBQUAD FAR *)((LPSTR)lpbmi + (WORD)lpbmi->biSize);
  811.                  WORD i;
  812.                 // copy from DIB palette (triples, by the way) into the LOGPALETTE
  813.                 for (i = 0; i < nEntries; i++) {
  814.                     pPal->palPalEntry[i].peRed   = pRgb[i].rgbRed;
  815.                     pPal->palPalEntry[i].peGreen = pRgb[i].rgbGreen;
  816.                     pPal->palPalEntry[i].peBlue  = pRgb[i].rgbBlue;
  817.                     pPal->palPalEntry[i].peFlags = (BYTE)0;
  818.                 } // for
  819.             } else {
  820.                 // Deep Dib: Synthesize halftone palette
  821.                 memcpy(pPal->palPalEntry, peStock256, sizeof peStock256);
  822.             }
  823.     
  824.             // create a logical palette
  825.             hPalette = CreatePalette(pPal);
  826.             LocalFree((HANDLE)pPal);
  827.         }
  828.     
  829.         GlobalUnlock(hdib);
  830.     }
  831.     return hPalette;
  832. } // TWAIN_CreateDibPalette
  833.  
  834.  
  835. LPBYTE DibBits(LPBITMAPINFOHEADER lpdib)
  836. // Given a pointer to a locked DIB, return a pointer to the actual bits (pixels)
  837. {
  838.      DWORD dwColorTableSize = (DWORD)(DibNumColors(lpdib) * sizeof(RGBQUAD));
  839.     LPBYTE lpBits = (LPBYTE)lpdib + lpdib->biSize + dwColorTableSize;
  840.  
  841.     return lpBits;
  842. } // end DibBits
  843.  
  844.  
  845. void EZTAPI TWAIN_DrawDibToDC(HDC hDC, int dx, int dy, int w, int h,
  846.                                      HANDLE hdib, int sx, int sy)
  847. {
  848.     LPBITMAPINFOHEADER lpbmi = (LPBITMAPINFOHEADER)GlobalLock(hdib);
  849.     if (lpbmi) {
  850. /*#ifdef _WIN32
  851.         HDRAWDIB hdd = DrawDibOpen();
  852.         if (hdd) {
  853.             DrawDibDraw(hdd, hDC,
  854.                         dx, dy, w, h,
  855.                         lpbmi, DibBits(lpbmi),
  856.                         sx, sy, w, h,
  857.                         0
  858.                         );
  859.             DrawDibClose(hdd);
  860.         }
  861. #else*/
  862.         StretchDIBits(hDC,
  863.                     dx, dy,            // x,y destination
  864.                     w, h,            // pixel width & height in destination
  865.                     sx, sy,            // x,y source
  866.                     w, h,            // width & height in source
  867.                     DibBits(lpbmi), // pointer to 'bits' - the pixels
  868.                     (LPBITMAPINFO)lpbmi,
  869.                     DIB_RGB_COLORS,    // DIB palette is (presumably?) RGB entries
  870.                     SRCCOPY);        // raster operation (copy)
  871. //#endif
  872.         GlobalUnlock(hdib);
  873.     }
  874. } // TWAIN_DrawDibToDC
  875.  
  876.  
  877. ///////////////////////////////////////////////////////////////////////
  878. // TWAIN general
  879.  
  880.  
  881. int EZTAPI TWAIN_IsAvailable(void)
  882. // return 1 if TWAIN services are available, 0 if 'TWAIN-less' system
  883. {
  884.     if (pDSM_Entry) return TRUE;        // SM currently loaded
  885.  
  886.     if (iAvailable == 0) {
  887.         if (TWAIN_LoadSourceManager()) {
  888.             iAvailable = 1;
  889.             TWAIN_UnloadSourceManager();
  890.         } else {
  891.             iAvailable = -1;
  892.         }
  893.     }
  894.     return (iAvailable > 0);
  895. } // TWAIN_IsAvailable
  896.  
  897.  
  898. int EZTAPI TWAIN_EasyVersion(void)
  899. // Returns the version number of EZTWAIN.DLL, multiplied by 100.
  900. // So e.g. version 2.01 will return 201 from this call.
  901. {
  902.     return VERSION;
  903. } // TWAIN_EasyVersion
  904.  
  905.  
  906. int EZTAPI TWAIN_State(void)
  907. // Returns the TWAIN Protocol State per the spec.
  908. {
  909.     return nState;
  910.  
  911. int EZTAPI TWAIN_GetHideUI(void)
  912. {
  913.     return bHideUI;
  914. } // TWAIN_GetHideUI
  915.  
  916. void EZTAPI TWAIN_SetHideUI(int fHide)
  917. {
  918.     bHideUI = (fHide != 0);
  919. } // TWAIN_SetHideUI
  920.  
  921.  
  922. ///////////////////////////////////////////////////////////////////////
  923. // TWAIN State Changers
  924.  
  925. int EZTAPI TWAIN_LoadSourceManager(void)
  926. {
  927.     char        szSMDir[128];
  928.     int            cc;
  929.     OFSTRUCT    of;
  930.  
  931.     if (nState >= 2) return TRUE;            // DSM already loaded
  932.  
  933.     GetWindowsDirectory(szSMDir, sizeof(szSMDir));
  934.     cc = lstrlen(szSMDir);
  935.     if (cc && szSMDir[cc-1] != ':') {
  936.         lstrcat(szSMDir, "\\");
  937.     }
  938.     lstrcat(szSMDir, DSM_FILENAME);            // could crash!
  939.     if (OpenFile(szSMDir, &of, OF_EXIST) != -1) {
  940.         hDSMLib = LoadLibrary(szSMDir);
  941.     } else {
  942.         hDSMLib = NULL;
  943.     }
  944.     if (IsValidHandle(hDSMLib)) {
  945.         pDSM_Entry = (DSMENTRYPROC) GetProcAddress(hDSMLib, DSM_ENTRYPOINT);
  946.         if (pDSM_Entry) {
  947.             iAvailable = 1;
  948.             nState = 2;
  949.         } else {
  950.             FreeLibrary(hDSMLib);
  951.             hDSMLib = NULL;
  952.         }
  953.     } else {
  954.         pDSM_Entry = NULL;
  955.     }
  956.  
  957.     return (nState >= 2);
  958. } // TWAIN_LoadSourceManager
  959.  
  960.  
  961. static TW_INT32 hwnd32SM;
  962.  
  963. int EZTAPI TWAIN_OpenSourceManager(HWND hwnd)
  964. {
  965.     hwnd32SM = (TW_INT32)hwnd;
  966.  
  967.     if (TWAIN_LoadSourceManager() &&
  968.         TWAIN_Mgr(DG_CONTROL, DAT_PARENT, MSG_OPENDSM, &hwnd32SM)) {
  969.         nState = TWAIN_SM_OPEN;
  970.     }
  971.  
  972.     return (nState >= TWAIN_SM_OPEN);
  973. } // TWAIN_OpenSourceManager
  974.  
  975.  
  976. int EZTAPI TWAIN_OpenDefaultSource(void)
  977. {
  978.     if (nState != 3) return FALSE;
  979.     // open the system default source
  980.     SourceId.ProductName[0] = '\0';
  981.     SourceId.Id = 0;
  982.     if (TWAIN_Mgr(DG_CONTROL, DAT_IDENTITY, MSG_OPENDS, &SourceId)) {
  983.         nState = 4;
  984.     } else {
  985.         RecordError(ED_DSM_FAILURE);
  986.     }
  987.  
  988.     return (nState == 4);
  989. } // TWAIN_OpenDefaultSource
  990.  
  991.  
  992. int EZTAPI TWAIN_EnableSource(HWND hwnd)
  993. {
  994.     if (nState != 4) return FALSE;
  995.  
  996.     twUI.ShowUI = !bHideUI;
  997.     twUI.hParent = (TW_HANDLE)hwnd;
  998.     TWAIN_DS(DG_CONTROL, DAT_USERINTERFACE, MSG_ENABLEDS, &twUI);
  999.     if (rc == TWRC_FAILURE) {
  1000.         RecordError(ED_DS_FAILURE);
  1001.     } else {
  1002.         // rc could be either SUCCESS or CHECKSTATUS
  1003.         nState = 5;
  1004.         // note, source will set twUI.ModalUI.
  1005.     }
  1006.     return (nState == 5);
  1007. } // TWAIN_EnableSource
  1008.  
  1009.  
  1010. int EZTAPI TWAIN_DisableSource(void)
  1011. {
  1012.     if (nState == 5 &&
  1013.         TWAIN_DS(DG_CONTROL, DAT_USERINTERFACE, MSG_DISABLEDS, &twUI)) {
  1014.         nState = 4;
  1015.     }
  1016.     return (nState <= 4);
  1017. } // TWAIN_DisableSource
  1018.  
  1019.  
  1020. int EZTAPI TWAIN_CloseSource(void)
  1021. {
  1022.     rc = TWRC_SUCCESS;
  1023.  
  1024.     if (nState == 5) TWAIN_DisableSource();
  1025.     if (nState == 4 &&
  1026.         TWAIN_Mgr(DG_CONTROL, DAT_IDENTITY, MSG_CLOSEDS, &SourceId)) {
  1027.         nState = 3;
  1028.     }
  1029.     return (nState <= 3);
  1030. } // TWAIN_CloseSource
  1031.  
  1032.  
  1033. int EZTAPI TWAIN_CloseSourceManager(HWND hwnd)
  1034. {
  1035.     TW_INT32 hwnd32 = (TW_INT32)hwnd;
  1036.  
  1037.     rc = TWRC_SUCCESS;
  1038.  
  1039.     if (TWAIN_CloseSource() &&
  1040.         TWAIN_Mgr(DG_CONTROL, DAT_PARENT, MSG_CLOSEDSM, &hwnd32)) {
  1041.         nState = 2;
  1042.     }
  1043.     return (nState <= 2);
  1044. } // TWAIN_CloseSourceManager
  1045.  
  1046.  
  1047. int EZTAPI TWAIN_UnloadSourceManager(void)
  1048. {
  1049.     if (nState == 2) {
  1050.  
  1051.         if (hDSMLib) {
  1052.             FreeLibrary(hDSMLib);
  1053.             hDSMLib = NULL;
  1054.         }
  1055.         pDSM_Entry = NULL;
  1056.         nState = 1;
  1057.     }
  1058.     return (nState == 1);
  1059. } // TWAIN_UnloadSourceManager
  1060.  
  1061.  
  1062.  
  1063. void EZTAPI TWAIN_ModalEventLoop(void)
  1064. {
  1065.     MSG msg;
  1066.  
  1067.     while ((nState >= 5) && !hDib && GetMessage((LPMSG)&msg, NULL, 0, 0)) {
  1068.         if (!TWAIN_MessageHook ((LPMSG)&msg)) {
  1069.             TranslateMessage ((LPMSG)&msg);
  1070.             DispatchMessage ((LPMSG)&msg);
  1071.         }
  1072.     } // while
  1073. } // TWAIN_ModalEventLoop
  1074.  
  1075.  
  1076. int EZTAPI TWAIN_MessageHook(LPMSG lpmsg)
  1077. // returns TRUE if msg processed by TWAIN (source)
  1078. {
  1079.     int   bProcessed = FALSE;
  1080.  
  1081.     if (nState >= 5) {
  1082.         // source enabled
  1083.         TW_EVENT    twEvent;
  1084.         twEvent.pEvent = (TW_MEMREF)lpmsg;
  1085.         twEvent.TWMessage = MSG_NULL;
  1086.         // see if source wants to process (eat) the message
  1087.         TWAIN_DS(DG_CONTROL, DAT_EVENT, MSG_PROCESSEVENT, &twEvent);
  1088.         bProcessed = (rc == TWRC_DSEVENT);
  1089.         switch (twEvent.TWMessage) {
  1090.             case MSG_XFERREADY:
  1091.                 nState = 6;
  1092.                 // TWAIN_NativeXferReady(lpmsg);  Spike's original code
  1093.                 TWAIN_NativeXferGetAll(lpmsg);  // replace with this -- DSN 07/98
  1094.                 break;
  1095.             case MSG_CLOSEDSREQ:
  1096.                 TWAIN_DisableSource();
  1097.                 break;
  1098.             case MSG_NULL:
  1099.                 // no message returned from DS
  1100.                 break;
  1101.         } // switch
  1102.      }
  1103.     return bProcessed;
  1104. } // TWAIN_MessageHook
  1105.  
  1106.  
  1107.  
  1108. void TWAIN_NativeXferReady(LPMSG pmsg)
  1109. // Spike's original code.  Note that it doesn't get called any more; instead,
  1110. // Message_Hook calls NativeXferGetAll, which supports multiple image
  1111. // acquisition. -- DSN 7/13/98
  1112. {
  1113.     TW_UINT32        hNative;
  1114.  
  1115.      pmsg = pmsg;        // suppress warning
  1116.  
  1117.     assert(nState == 6);
  1118.     TWAIN_DS(DG_IMAGE, DAT_IMAGENATIVEXFER, MSG_GET, &hNative);
  1119.  
  1120.     if (rc != TWRC_XFERDONE) hDib = NULL;
  1121.  
  1122.     switch (rc) {
  1123.         case TWRC_XFERDONE:
  1124.             // hNative contains a valid native image (handle)
  1125.             // application is responsible for de-allocating.
  1126.             nState = 7;
  1127.             // Need to acknowledge the end of the transfer
  1128.             hDib = (HANDLE)hNative;
  1129.             // above line added by DSN: add to list of hdibs and advance counter
  1130.             break;
  1131.  
  1132.         case TWRC_CANCEL:
  1133.             // user cancelled the transfer
  1134.             // hNative is invalid
  1135.             nState = 7;
  1136.             // acknowledge the end of the transfer
  1137.             break;
  1138.  
  1139.         case TWRC_FAILURE:
  1140.         default:
  1141.             // the transfer failed (e.g. insufficient memory)
  1142.             // hNative is invalid
  1143.             // check condition code for more info
  1144.             nState = 6;
  1145.             // state transition failed
  1146.             // image data is still pending
  1147.             break;
  1148.     } // switch
  1149.     assert(nState >= 6);
  1150.  
  1151.     TWAIN_AbortAllPendingXfers();    // state 7 or 6 -> state 5
  1152.  
  1153. } // TWAIN_NativeXferReady
  1154.  
  1155.  
  1156. int EZTAPI TWAIN_AbortAllPendingXfers(void)
  1157. // Not used any more because its only caller was TWAIN_NativeXferReady, which
  1158. // is now ignored in favor or TWAIN_NativeXferGetAll.  -- DSN 7/13/98
  1159. {
  1160.     if (nState == 7 &&
  1161.         TWAIN_DS(DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER, &pendingXfers)) {
  1162.         nState = pendingXfers.Count ? 6 : 5;
  1163.     }
  1164.     if (nState == 6 &&
  1165.         TWAIN_DS(DG_CONTROL, DAT_PENDINGXFERS, MSG_RESET, &pendingXfers)) {
  1166.         nState = 5;
  1167.     }
  1168.     return (nState <= 5);
  1169. } // TWAIN_AbortAllPendingXfers
  1170.  
  1171.  
  1172. void EZTAPI TWAIN_NativeXferGetAll(LPMSG pmsg)
  1173. // A modified version of Spike's original code that loops through until
  1174. // no more images are left. -- DSN 7/98
  1175. {
  1176.     TW_UINT32        hNative;
  1177.  
  1178.     pmsg = pmsg;        // suppress warning; (sic)  -- does this do anything?  DSN
  1179.     assert(nState == 6);
  1180.  
  1181.     do {
  1182.         TWAIN_DS(DG_IMAGE, DAT_IMAGENATIVEXFER, MSG_GET, &hNative);
  1183.  
  1184.         if (rc != TWRC_XFERDONE) hDib = NULL;
  1185.  
  1186.         switch (rc) {
  1187.             case TWRC_XFERDONE:
  1188.                 // hNative contains a valid native image (handle)
  1189.                 // application is responsible for de-allocating.
  1190.                 nState = 7;
  1191.                 // Need to acknowledge the end of the transfer
  1192.                 hDib = (HANDLE)hNative;  // thus hDib represents MOST RECENT image!
  1193.                 hDibList[nDibs] = hDib;
  1194.                 // added by DSN: add to list of hdibs and advance counter
  1195.                 if (hDibCallback_registered == TW_CALLBACK_REGISTERED)    // user may specify callback
  1196.                       (*lpfnDibCallback)(hDibList[nDibs], nDibs);   // great for multithreading!
  1197.                 nDibs++;
  1198.                 break;
  1199.  
  1200.             case TWRC_CANCEL:
  1201.                 // user cancelled the transfer
  1202.                 // hNative is invalid
  1203.                 nState = 7;
  1204.                 // acknowledge the end of the transfer
  1205.                 break;
  1206.  
  1207.             case TWRC_FAILURE:
  1208.                 default:
  1209.                 // the transfer failed (e.g. insufficient memory)
  1210.                 // hNative is invalid
  1211.                 // check condition code for more info
  1212.                 nState = 6;
  1213.                 // state transition failed
  1214.                 // image data is still pending
  1215.                 break;
  1216.         } // switch
  1217.         assert(nState >= 6);
  1218.         if (nState == 7 && TWAIN_DS(DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER, &pendingXfers))
  1219.             nState = pendingXfers.Count ? 6 : 5;
  1220.     } while (nState == 6);
  1221.  
  1222.     //    TWAIN_AbortAllPendingXfers();    // state 7 or 6 -> state 5
  1223.     // Commented out the above; we want to get all xfers!!
  1224.  
  1225. } // TWAIN_NativeXferReady
  1226. ///////////////////////////////////////////////////////////////////////
  1227. // DIB/BMP File I/O
  1228.  
  1229. int EZTAPI TWAIN_WriteNativeToFilename(HANDLE hdib, LPCSTR pszFile)
  1230. // Writes a DIB handle to a .BMP file
  1231. //
  1232. // hdib        = DIB handle, as returned by TWAIN_AcquireNative
  1233. // pszFile    = far pointer to NUL-terminated filename
  1234. // If pszFile is NULL or points to a null string, prompts the user
  1235. // for the filename with a standard file-save dialog.
  1236. //
  1237. // Return values:
  1238. //     0    success
  1239. //    -1    user cancelled File Save dialog
  1240. //    -2    file open error (invalid path or name, or access denied)
  1241. //    -3    (weird) unable to lock DIB - probably an invalid handle.
  1242. //    -4    writing BMP data failed, possibly output device is full
  1243. {
  1244.     int result;
  1245.     char szFile[256];
  1246.     HFILE fh;
  1247.     OFSTRUCT ofs;
  1248.  
  1249.     if (!pszFile || !*pszFile) {
  1250.         // prompt for filename
  1251.         OPENFILENAME ofn;
  1252.         int nExt;
  1253.  
  1254.         FMEMSET(&ofn, 0, sizeof ofn);
  1255.         szFile[0] = '\0';
  1256.         ofn.lStructSize = sizeof(OPENFILENAME);
  1257.         ofn.hwndOwner = NULL;
  1258.         ofn.lpstrFilter = "Windows Bitmap (*.bmp)\0*.bmp\0\0";
  1259.         ofn.lpstrFile= szFile;
  1260.         ofn.nMaxFile = sizeof(szFile) - 5;
  1261.         ofn.Flags = OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY |
  1262.                     OFN_NOREADONLYRETURN;
  1263.  
  1264.         if (!GetSaveFileName(&ofn)) {
  1265.             return -1;                    // user cancelled dialog
  1266.         }
  1267.         // supply default extension - GetSaveFileName doesn't seem to do it!
  1268.         nExt = ofn.nFileExtension;
  1269.         if (nExt && !szFile[nExt]) {
  1270.             // no extension
  1271.             lstrcat(szFile, ".bmp");
  1272.         }
  1273.         pszFile = szFile;
  1274.     }
  1275.  
  1276.     result = -2;
  1277.     fh = OpenFile(pszFile , &ofs, OF_CREATE | OF_WRITE | OF_SHARE_EXCLUSIVE);
  1278.     if (fh != HFILE_ERROR) {
  1279.         result = TWAIN_WriteNativeToFile(hdib, fh);
  1280.         _lclose(fh);
  1281.     }
  1282.     return result;
  1283. } // TWAIN_WriteNativeToFilename
  1284.  
  1285.  
  1286. int EZTAPI TWAIN_WriteNativeToFile(HANDLE hdib, HFILE fh)
  1287. // Writes a DIB to a file in .BMP format.
  1288. //
  1289. // hdib        = DIB handle, as returned by TWAIN_AcquireNative
  1290. // fh        = file handle, as returned by C _open or Windows _lopen or OpenFile
  1291. //
  1292. // Return value as for TWAIN_WriteNativeToFilename
  1293. {
  1294.     int result = -3;
  1295.     LPBITMAPINFOHEADER lpbmi = (LPBITMAPINFOHEADER)GlobalLock(hdib);
  1296.     if (lpbmi) {
  1297.         result = -4;
  1298.         if (TWAIN_WriteDibToFile(lpbmi, fh)) {
  1299.             result = 0;            // success
  1300.         }
  1301.         GlobalUnlock(hdib);
  1302.     }
  1303.     return result;
  1304. } //  TWAIN_WriteNativeToFile
  1305.  
  1306.  
  1307. int EZTAPI TWAIN_WriteDibToFile(LPBITMAPINFOHEADER lpDIB, HFILE fh)
  1308. {
  1309.     BITMAPFILEHEADER        bfh;
  1310.     int                        fOk = FALSE;
  1311.     int                        nBPP = lpDIB->biBitCount;
  1312.     int                        nColors = (int)lpDIB->biClrUsed;
  1313.  
  1314.     // figure out actual size of color table
  1315.     if (nColors == 0 && nBPP <= 8) {
  1316.         nColors = (1 << nBPP);
  1317.     }
  1318.     if (lpDIB->biCompression == BI_RGB) {
  1319.         // uncompressed bitmap, image size might not be set
  1320.         DWORD dwBytesPerRow = (((lpDIB->biWidth * nBPP) + 31) / 32) * 4;
  1321.         lpDIB->biSizeImage = dwBytesPerRow * lpDIB->biHeight;
  1322.     } else if (lpDIB->biSizeImage == 0) {
  1323.         // compressed bitmap, image size had damn well better be set!
  1324.         return FALSE;
  1325.         // This could be hacked around with something like this:
  1326.         //lpDIB->biSizeImage = GlobalSize((HANDLE)GlobalHandle(HIWORD(lpDIB)));
  1327.     }
  1328.  
  1329.     // Set up BMP header.
  1330.     bfh.bfType = 0x4d42;                // "BM"
  1331.     bfh.bfReserved1 = 0;
  1332.     bfh.bfReserved2 = 0;
  1333.     bfh.bfOffBits = sizeof(BITMAPFILEHEADER) +
  1334.                     sizeof(BITMAPINFOHEADER) +
  1335.                     sizeof(RGBQUAD) * nColors;
  1336.     bfh.bfSize = bfh.bfOffBits + lpDIB->biSizeImage;
  1337.  
  1338.     if (_lwrite(fh, (LPCSTR)&bfh, sizeof bfh) == sizeof bfh) {
  1339.  
  1340.         INT32 towrite = bfh.bfSize - (INT32)sizeof bfh;
  1341.  
  1342.         if (HUGEWRITE(fh, (LPCSTR)lpDIB, towrite) == towrite) {
  1343.             fOk = TRUE;
  1344.         }
  1345.     }
  1346.  
  1347.     return fOk;
  1348.  
  1349. } // TWAIN_WriteDibToFile
  1350.  
  1351.  
  1352. HANDLE EZTAPI TWAIN_LoadNativeFromFilename(LPCSTR pszFile)
  1353. // Load a .BMP file and return a DIB handle (as from AcquireNative.)
  1354. //
  1355. // pszFile    = far pointer to NUL-terminated filename
  1356. // If pszFile is NULL or points to a null string, prompts the user
  1357. // for the filename with a standard file-open dialog.
  1358. //
  1359. // Return value:
  1360. //    handle to a DIB if successful, otherwise NULL (0).
  1361. {
  1362.     HANDLE hdib = NULL;
  1363.     char szFile[256];
  1364.     HFILE fh;
  1365.     OFSTRUCT ofs;
  1366.  
  1367.     if (!pszFile || !*pszFile) {
  1368.         // prompt for filename
  1369.         OPENFILENAME ofn;
  1370.         int nExt;
  1371.  
  1372.         FMEMSET(&ofn, 0, sizeof ofn);
  1373.         szFile[0] = '\0';
  1374.         ofn.lStructSize = sizeof(OPENFILENAME);
  1375.         ofn.hwndOwner = NULL;
  1376.         ofn.lpstrFilter = "Windows Bitmaps (*.bmp)\0*.bmp\0\0";
  1377.         ofn.lpstrFile= szFile;
  1378.         ofn.nMaxFile = sizeof(szFile) - 5;
  1379.         ofn.Flags = OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY |
  1380.                     OFN_NOREADONLYRETURN;
  1381.  
  1382.         if (!GetOpenFileName(&ofn)) {
  1383.             return NULL;                    // user cancelled dialog
  1384.         }
  1385.         // supply default extension - GetOpenFileName doesn't seem to do it!
  1386.         nExt = ofn.nFileExtension;
  1387.         if (nExt && !szFile[nExt]) {
  1388.             // no extension
  1389.             lstrcat(szFile, ".bmp");
  1390.         }
  1391.         pszFile = szFile;
  1392.     }
  1393.  
  1394.     fh = OpenFile(pszFile, &ofs, OF_READ | OF_SHARE_DENY_WRITE);
  1395.     if (fh != HFILE_ERROR) {
  1396.         hdib = TWAIN_LoadNativeFromFile(fh);
  1397.         _lclose(fh);
  1398.     }
  1399.     return hdib;
  1400. } // TWAIN_LoadNativeFromFilename
  1401.  
  1402.  
  1403. HANDLE EZTAPI TWAIN_LoadNativeFromFile(HFILE fh)
  1404. // Like LoadNativeFromFilename, but takes an already open file handle.
  1405. {
  1406.     HANDLE hdib;
  1407.     LPBYTE pbi;
  1408.     BITMAPFILEHEADER bmh;
  1409.     INT32 dibSize;
  1410.     // Read BMP file header and validate
  1411.     if (_lread(fh, &bmh, sizeof bmh) != sizeof bmh ||
  1412.         bmh.bfType != 0x4d42) {
  1413.         return NULL;
  1414.     }
  1415.     // Allocate global block for DIB
  1416.     dibSize = bmh.bfSize - sizeof bmh;
  1417.     hdib = GlobalAlloc(0, dibSize);
  1418.     pbi = (LPBYTE)GlobalLock(hdib);
  1419.     if (!hdib || !pbi) {
  1420.         return NULL;
  1421.     }
  1422.  
  1423.     // Read DIB from file
  1424.     if (_hread(fh, pbi, dibSize) != dibSize) {
  1425.         GlobalUnlock(hdib);
  1426.         GlobalFree(hdib);
  1427.         return NULL;
  1428.     }
  1429.     GlobalUnlock(hdib);
  1430.     return hdib;
  1431. } // TWAIN_LoadNativeFromFile
  1432.  
  1433. ///////////////////////////////////////////////////////////////////////
  1434. // TWAIN State 4 Negotiation Functions
  1435.  
  1436. int EZTAPI TWAIN_NegotiateXferCount(int nXfers)
  1437. {
  1438.     return TWAIN_SetCapOneValue(CAP_XFERCOUNT, TWTY_INT16, nXfers);
  1439. } // TWAIN_NegotiateXferCount
  1440.  
  1441.  
  1442. int EZTAPI TWAIN_NegotiatePixelTypes(unsigned wPixTypes)
  1443. {
  1444.     TW_CAPABILITY         cap;
  1445.     void far *            pv;
  1446.     int                    fSuccess = FALSE;
  1447.  
  1448.     if (nState != TWAIN_SOURCE_OPEN) {
  1449.         return RecordError(ED_NOT_STATE_4);
  1450.     }
  1451.  
  1452.     if (TWAIN_ANYTYPE == wPixTypes) {
  1453.         return TRUE;            // that was easy!
  1454.     }
  1455.                                                                            
  1456.                                                                            
  1457.     // Fill in capability structure
  1458.     cap.Cap = ICAP_PIXELTYPE;            // capability id
  1459.     cap.ConType = TWON_ENUMERATION;        // favorite type of container (should be ignored...)
  1460.  
  1461.     if (!TWAIN_DS(DG_CONTROL, DAT_CAPABILITY, MSG_GET, (TW_MEMREF)&cap)) {
  1462.         return RecordError(ED_CAP_GET);
  1463.     }
  1464.     if (!cap.hContainer) {
  1465.         return RecordError(ED_NULL_HCON);
  1466.     }
  1467.     if (!(pv = GlobalLock(cap.hContainer))) {
  1468.         // this source is invalid, further negotiation is unlikely to succeed
  1469.         return RecordError(ED_BAD_HCON);
  1470.     }
  1471.  
  1472.     switch (cap.ConType) {
  1473.  
  1474.         case TWON_ENUMERATION: {
  1475.             TW_ENUMERATION far *pcon = (TW_ENUMERATION far *)pv;
  1476.             if (pcon->NumItems < 1) {
  1477.                 RecordError(ED_CAP_GET_EMPTY);
  1478.             } else if (pcon->ItemType != TWTY_UINT16 && pcon->ItemType != TWTY_INT16) {
  1479.                 RecordError(ED_BAD_ITEMTYPE);
  1480.             } else {
  1481.                 pcon->CurrentIndex = TWON_DONTCARE32;    // don't change current value
  1482.                 pcon->DefaultIndex = TWON_DONTCARE32;    // don't change default value
  1483.                 pcon->NumItems = Intersect16(wPixTypes, (unsigned)pcon->NumItems, (TW_UINT16 far *)pcon->ItemList);
  1484.                 fSuccess = (pcon->NumItems != 0);
  1485.                 if (!fSuccess) RecordError(ED_CAP_SET_EMPTY);
  1486.             }
  1487.             break;
  1488.         }
  1489.         
  1490.         case TWON_ARRAY: {
  1491.             // this is technically illegal - TWAIN 1.5, p9-30, Containers for MSG_GET: TW_ENUMERATION, TW_ONEVALUE
  1492.             TW_ARRAY far *pcon = (TW_ARRAY far *)pv;
  1493.             if (pcon->NumItems < 1) {
  1494.                 RecordError(ED_CAP_GET_EMPTY);
  1495.             } else if (pcon->ItemType != TWTY_UINT16 && pcon->ItemType != TWTY_INT16) {
  1496.                 RecordError(ED_BAD_ITEMTYPE);
  1497.             } else {
  1498.                 pcon->NumItems = Intersect16(wPixTypes, (unsigned)pcon->NumItems, (TW_UINT16 far *)pcon->ItemList);
  1499.                 fSuccess = (pcon->NumItems != 0);
  1500.                 if (!fSuccess) RecordError(ED_CAP_SET_EMPTY);
  1501.             }
  1502.             break;
  1503.         }
  1504.  
  1505.         case TWON_ONEVALUE: {
  1506.             TW_ONEVALUE far *pcon = (TW_ONEVALUE far *)pv;
  1507.             fSuccess = ((1 << pcon->Item) & wPixTypes);
  1508.             if (!fSuccess) RecordError(ED_CAP_SET_EMPTY);
  1509.             break;
  1510.         }
  1511.         
  1512.         default:
  1513.             // something we don't understand, abandon negotiations
  1514.             RecordError(ED_BAD_CONTYPE);
  1515.             break;
  1516.     } // switch
  1517.  
  1518.     GlobalUnlock(cap.hContainer);
  1519.  
  1520.     if (fSuccess) {
  1521.         // For enums (and arrays) send intersection back, to restrict it.
  1522.         // For one vals, don't bother - could only cause confusion.
  1523.         if (cap.ConType != TWON_ONEVALUE) {
  1524.             fSuccess = TWAIN_DS(DG_CONTROL, DAT_CAPABILITY, MSG_SET, (TW_MEMREF)&cap);
  1525.             if (!fSuccess) RecordError(ED_CAP_SET);
  1526.         }
  1527.     }
  1528.     GlobalFree(cap.hContainer);
  1529.     
  1530.     return fSuccess;
  1531. } // TWAIN_NegotiatePixelTypes
  1532.  
  1533.  
  1534. int EZTAPI TWAIN_GetCurrentUnits(void)
  1535. {
  1536.     int nUnits = TWUN_INCHES;
  1537.     TWAIN_GetCapCurrent(ICAP_UNITS, TWTY_UINT16, &nUnits);
  1538.     return nUnits;
  1539. } // TWAIN_GetCurrentUnits
  1540.  
  1541.  
  1542. int EZTAPI TWAIN_SetCurrentUnits(int nUnits)
  1543. // Negotiate the current pixel type for acquisition.
  1544. // Negotiation is only allowed in State 4 (TWAIN_SOURCE_OPEN)
  1545. // The source may select this pixel type, but don't assume it will.
  1546. {
  1547.     return TWAIN_SetCapOneValue(ICAP_UNITS, TWTY_UINT16, (TW_UINT16)nUnits);
  1548. } // TWAIN_SetCurrentUnits
  1549.  
  1550.  
  1551. int EZTAPI TWAIN_GetBitDepth(void)
  1552. // Ask the source for the current bitdepth.
  1553. // This value depends on the current PixelType.
  1554. // Bit depth is per color channel e.g. 24-bit RGB has bit depth 8.
  1555. // If anything goes wrong, this function returns 0.
  1556. {
  1557.     int nBits = 0;
  1558.     TWAIN_GetCapCurrent(ICAP_BITDEPTH, TWTY_UINT16, &nBits);
  1559.     return nBits;
  1560. } // TWAIN_GetBitDepth
  1561.  
  1562. int EZTAPI TWAIN_SetBitDepth(int nBits)
  1563. // (Try to) set the current bitdepth (for the current pixel type).
  1564. {
  1565.     return TWAIN_SetCapOneValue(ICAP_BITDEPTH, TWTY_UINT16, (TW_UINT16)nBits);
  1566. } // TWAIN_SetBitDepth
  1567.  
  1568.  
  1569. int EZTAPI TWAIN_GetPixelType(void)
  1570. // Ask the source for the current pixel type.
  1571. // If anything goes wrong (it shouldn't!), this function returns 0 (TWPT_BW).
  1572. {
  1573.     int nPixType = 0;
  1574.     TWAIN_GetCapCurrent(ICAP_PIXELTYPE, TWTY_UINT16, &nPixType);
  1575.     return nPixType;
  1576. } // TWAIN_GetPixelType
  1577.  
  1578. int EZTAPI TWAIN_SetCurrentPixelType(int nPixType)
  1579. // Negotiate the current pixel type for acquisition.
  1580. // Negotiation is only allowed in State 4 (TWAIN_SOURCE_OPEN)
  1581. // The source may select this pixel type, but don't assume it will.
  1582. {
  1583.     return TWAIN_SetCapOneValue(ICAP_PIXELTYPE, TWTY_UINT16, (TW_UINT16)nPixType);
  1584. } // TWAIN_SetCurrentPixelType
  1585.  
  1586.  
  1587. /*double EZTAPI TWAIN_GetCurrentResolution(void)
  1588. {
  1589.     TW_FIX32 res;
  1590.     TWAIN_GetCapCurrent(ICAP_XRESOLUTION, TWTY_FIX32, &res);
  1591.  
  1592.     return Fix32ToFloat(res);
  1593. } // TWAIN_GetCurrentResolution
  1594.  
  1595. int EZTAPI TWAIN_SetCurrentResolution(double dRes)
  1596. // Negotiate the current resolution for acquisition.
  1597. // Negotiation is only allowed in State 4 (TWAIN_SOURCE_OPEN)
  1598. // The source may select this resolution, but don't assume it will.
  1599. {
  1600.     return TWAIN_SetCapOneValue(ICAP_XRESOLUTION, TWTY_FIX32, ToFix32(dRes));
  1601. } // TWAIN_SetCurrentResolution
  1602.  
  1603. */
  1604.  
  1605. int EZTAPI TWAIN_SetCapOneValue(unsigned Cap, unsigned ItemType, long ItemVal)
  1606. {
  1607.     TW_CAPABILITY    cap;
  1608.     pTW_ONEVALUE    pv;
  1609.     BOOL            bSuccess;
  1610.  
  1611.     if (nState != TWAIN_SOURCE_OPEN) {
  1612.         TWAIN_ErrorBox("Attempt to set capability outside State 4.");
  1613.         return FALSE;
  1614.     }
  1615.  
  1616.     cap.Cap = Cap;            // capability id
  1617.     cap.ConType = TWON_ONEVALUE;        // container type
  1618.     cap.hContainer = GlobalAlloc(GHND, sizeof (TW_ONEVALUE));
  1619.     if (!cap.hContainer) {
  1620.         TWAIN_ErrorBox(szInsuffMem);
  1621.         return FALSE;
  1622.     }
  1623.     pv = (pTW_ONEVALUE)GlobalLock(cap.hContainer);
  1624.     pv->ItemType = ItemType;
  1625.     pv->Item = ItemVal;
  1626.     GlobalUnlock(cap.hContainer);
  1627.     bSuccess = TWAIN_DS(DG_CONTROL, DAT_CAPABILITY, MSG_SET, (TW_MEMREF)&cap);
  1628.     GlobalFree(cap.hContainer);
  1629.     return bSuccess;
  1630. } // TWAIN_SetCapOneValue
  1631.  
  1632.  
  1633. const size_t nTypeSize[13] =
  1634.     {    sizeof (TW_INT8),
  1635.         sizeof (TW_INT16),
  1636.         sizeof (TW_INT32),
  1637.         sizeof (TW_UINT8),
  1638.         sizeof (TW_UINT16),
  1639.         sizeof (TW_UINT32),
  1640.         sizeof (TW_BOOL),
  1641.         sizeof (TW_FIX32),
  1642.         sizeof (TW_FRAME),
  1643.         sizeof (TW_STR32),
  1644.         sizeof (TW_STR64),
  1645.         sizeof (TW_STR128),
  1646.         sizeof (TW_STR255),
  1647.     };
  1648.  
  1649. // helper function:
  1650. int TypeMatch(unsigned nTypeA, unsigned nTypeB)
  1651. {
  1652.     // Integral types match if they are the same size.
  1653.     // All other types match only if they are equal
  1654.     return nTypeA == nTypeB ||
  1655.            (nTypeA <= TWTY_UINT32 &&
  1656.             nTypeB <= TWTY_UINT32 &&
  1657.             nTypeSize[nTypeA] == nTypeSize[nTypeB]);
  1658. } // TypeMatch
  1659.  
  1660.  
  1661.  
  1662. int EZTAPI TWAIN_GetCapCurrent(unsigned Cap, unsigned ItemType, void FAR *pVal)
  1663. {
  1664.     TW_CAPABILITY     cap;
  1665.     void far *        pv = NULL;
  1666.     BOOL            bSuccess = FALSE;
  1667.  
  1668.     assert(pVal != NULL);
  1669.  
  1670.     if (nState < TWAIN_SOURCE_OPEN) {
  1671.         TWAIN_ErrorBox("Attempt to get capability value below State 4.");
  1672.         return FALSE;
  1673.     }
  1674.  
  1675.     // Fill in capability structure
  1676.     cap.Cap = Cap;                    // capability id
  1677.     cap.ConType = TWON_ONEVALUE;    // favorite type of container (should be ignored...)
  1678.     cap.hContainer = NULL;
  1679.  
  1680.     if (TWAIN_DS(DG_CONTROL, DAT_CAPABILITY, MSG_GETCURRENT, (TW_MEMREF)&cap) &&
  1681.         cap.hContainer &&
  1682.         (pv = GlobalLock(cap.hContainer))) {
  1683.  
  1684.         if (cap.ConType == TWON_ENUMERATION) {
  1685.             TW_ENUMERATION far *pcon = (TW_ENUMERATION far *)pv;
  1686.             TW_UINT32 index = pcon->CurrentIndex;
  1687.             if (index < pcon->NumItems && TypeMatch(pcon->ItemType, ItemType)) {
  1688.                 LPSTR pitem = (LPSTR)pcon->ItemList + index*nTypeSize[ItemType];
  1689.                 FMEMCPY(pVal, pitem, nTypeSize[ItemType]);
  1690.                 bSuccess = TRUE;
  1691.             }
  1692.         } else if (cap.ConType == TWON_ONEVALUE) {
  1693.             TW_ONEVALUE far *pcon = (TW_ONEVALUE far *)pv;
  1694.             if (TypeMatch(pcon->ItemType, ItemType)) {
  1695.                 FMEMCPY(pVal, &pcon->Item, nTypeSize[ItemType]);
  1696.                 bSuccess = TRUE;
  1697.             }
  1698.         }
  1699.     }
  1700.  
  1701.     if (pv) GlobalUnlock(cap.hContainer);
  1702.     if (cap.hContainer) GlobalFree(cap.hContainer);
  1703.  
  1704.     return bSuccess;
  1705.  
  1706. //-------------------------- The primitive functions
  1707.  
  1708.  
  1709. int EZTAPI TWAIN_DS(unsigned long dg, unsigned dat, unsigned msg, void FAR *pd)
  1710. // Call the current source with a triplet
  1711. {
  1712.     assert(nState >= 4);
  1713.     rc = TWRC_FAILURE;
  1714.     if (pDSM_Entry) {
  1715.         rc = (*pDSM_Entry)(&AppId, &SourceId,
  1716.                            (TW_UINT32)dg,
  1717.                            (TW_UINT16)dat,
  1718.                            (TW_UINT16)msg,
  1719.                            (TW_MEMREF)pd);
  1720.     }
  1721.     return (rc == TWRC_SUCCESS);
  1722. } // TWAIN_DS
  1723.  
  1724.  
  1725.  
  1726. int EZTAPI TWAIN_Mgr(unsigned long dg, unsigned dat, unsigned msg, void FAR *pd)
  1727. // Call the Source Manager with a triplet
  1728. {
  1729.     rc = TWRC_FAILURE;
  1730.     if (pDSM_Entry) {
  1731.         rc = (*pDSM_Entry)(&AppId, NULL,
  1732.                            (TW_UINT32)dg,
  1733.                            (TW_UINT16)dat,
  1734.                            (TW_UINT16)msg,
  1735.                            (TW_MEMREF)pd);
  1736.     }
  1737.     return (rc == TWRC_SUCCESS);
  1738. } // TWAIN_Mgr
  1739.  
  1740.  
  1741.  
  1742. unsigned EZTAPI TWAIN_GetResultCode(void)
  1743. {
  1744.     return rc;
  1745. } // TWAIN_GetResultCode
  1746.  
  1747.  
  1748.  
  1749. unsigned EZTAPI TWAIN_GetConditionCode(void)
  1750. {
  1751.     TW_STATUS    twStatus;
  1752.  
  1753.     if (nState >= 4) {
  1754.         // get source status if open
  1755.         TWAIN_DS(DG_CONTROL, DAT_STATUS, MSG_GET, (TW_MEMREF)&twStatus);
  1756.     } else if (nState == 3) {
  1757.         // otherwise get source manager status
  1758.         TWAIN_Mgr(DG_CONTROL, DAT_STATUS, MSG_GET, (TW_MEMREF)&twStatus);
  1759.     } else {
  1760.         // nothing open, not a good time to get condition code!
  1761.         return TWCC_SEQERROR;
  1762.     }
  1763.     if (rc == TWRC_SUCCESS) {
  1764.         return twStatus.ConditionCode;
  1765.     } else {
  1766.         return TWCC_BUMMER;            // what can I say. 
  1767.     }
  1768. } // TWAIN_GetConditionCode
  1769.  
  1770.  
  1771. //------------ Private functions
  1772.  
  1773.  
  1774. HWND CreateProxyWindow(void)
  1775. {
  1776.     HWND hwnd;
  1777.     hwnd = CreateWindow("STATIC",                        // class
  1778.                         "Acquire Proxy",                // title
  1779.                         WS_POPUPWINDOW | WS_VISIBLE,    // style
  1780.                         CW_USEDEFAULT, CW_USEDEFAULT,    // x, y
  1781.                         CW_USEDEFAULT, CW_USEDEFAULT,    // width, height
  1782.                         HWND_DESKTOP,                    // parent window
  1783.                         NULL,                            // hmenu
  1784.                         hinstLib,                        // hinst
  1785.                         NULL);                            // lpvparam
  1786.     return hwnd;
  1787. } // CreateProxyWindow
  1788.  
  1789.  
  1790. int RecordError(ErrorDetail ed)
  1791. {
  1792.     if (nErrDetail == ED_NONE) {
  1793.         nErrDetail = ed;
  1794.         if (ed > ED_START_TRIPLET_ERRS && ed < ED_END_TRIPLET_ERRS) {
  1795.             nErrRC = TWAIN_GetResultCode();
  1796.             nErrCC = TWAIN_GetConditionCode();
  1797.         } else {
  1798.             nErrRC = 0;
  1799.             nErrCC = 0;
  1800.         }
  1801.     }
  1802.     return FALSE;
  1803. } // RecordError
  1804.  
  1805.  
  1806. void ClearError(void)
  1807. {
  1808.     nErrDetail = ED_NONE;
  1809. } // ClearError
  1810.  
  1811.  
  1812. void TWAIN_ReportLastError(LPSTR lpzGeneral)
  1813. {
  1814. /*    if (nErrDetail > ED_START_TRIPLET_ERRS && nErrDetail < ED_END_TRIPLET_ERRS) {
  1815.         wvsprintf(szMsg, "%s\n%s\nRC:   %s\nCC:   %s",
  1816.             lpzGeneral, (LPSTR)pszErrDescrip[nErrDetail],
  1817.             (LPSTR)pszRC[nErrRC], (LPSTR)pszCC[nErrCC]);
  1818.     } else {
  1819.         wvsprintf(szMsg, "%s\n%s", lpzGeneral, (LPSTR)pszErrDescrip[nErrDetail]);
  1820.     }*/
  1821.     TWAIN_ErrorBox("TWAIN_ReportLastError: an error occurred");
  1822. } // ReportLastError; stripped down by dsn to avoid using C RTL
  1823.  
  1824.  
  1825. void TWAIN_ErrorBox(const char *szMsg)
  1826. {
  1827.     MessageBox(NULL, (LPSTR)szMsg, "TWAIN Error", MB_ICONEXCLAMATION | MB_OK);
  1828. } // TWAIN_ErrorBox
  1829.  
  1830.  
  1831. unsigned BitCount(unsigned W)
  1832. {
  1833.     unsigned n = 0;
  1834.  
  1835.     while (W) {
  1836.         n += (W & 1);
  1837.         W >>= 1;
  1838.     } // while
  1839.     return n;
  1840. } // BitCount
  1841.  
  1842.  
  1843. unsigned Intersect16(unsigned wMask, unsigned nItems, TW_UINT16 far *pItem)
  1844. {
  1845.     unsigned    wSet;
  1846.     unsigned    i;
  1847.  
  1848.     // In wSet, construct set of available items.
  1849.     // Note that items that cannot be represented in wMask are also
  1850.     // unrepresentable in wSet so are implicitly discarded
  1851.     for (i = wSet = 0 ; i < nItems; i++) {
  1852.         wSet |= 1 << pItem[i];
  1853.     } // for
  1854.  
  1855.     // Discard anything in wMask that isn't in wSet
  1856.     wMask &= wSet;
  1857.  
  1858.     // Re-fill the item table with intersection set
  1859.     for (i = nItems = 0; wMask ; wMask>>=1,i++) {
  1860.         if (wMask & 1) {
  1861.             pItem[nItems++] = i;
  1862.         }
  1863.     } // for
  1864.  
  1865.     return nItems;
  1866. }
  1867.  
  1868. /*
  1869. TW_UINT32 ToFix32(double r)
  1870. {
  1871.     TW_FIX32 fix;
  1872.     TW_INT32 val = (TW_INT32)(r * 65536.0 + 0.5);
  1873.     fix.Whole = (TW_INT16)(val >> 16);            // most significant 16 bits
  1874.     fix.Frac = (TW_UINT16)(val & 0xffff);        // least
  1875.     assert(sizeof (TW_FIX32) == sizeof (TW_UINT32));
  1876.     return *(TW_UINT32*)&fix;
  1877. } // ToFix32
  1878.  
  1879. double Fix32ToFloat(TW_FIX32 fix)
  1880. {
  1881.     TW_INT32 val = ((TW_INT32)fix.Whole << 16) | ((TW_UINT32)fix.Frac & 0xffff);
  1882.     return val / 65536.0;
  1883. } // Fix32ToFloat
  1884. */
  1885.  
  1886. // The routine below is a modified version of code posted by Zafir Anjum
  1887. // on www.codeguru.com.  The original code was designed for MFC; below it
  1888. // has been translated into straight C.  Also, one other change is that rather
  1889. // than dynamically allocate only the memory needed for pLP, I fix the size of
  1890. // the array at the beginning so that it's sufficient for whatever might come
  1891. // along so as to eliminate any dependence on the C runtime library.
  1892.  
  1893. /*HBITMAP EZTAPI DIBToDDB( HANDLE hDIB )
  1894. {
  1895.       LPBITMAPINFOHEADER      lpbi;
  1896.       HBITMAP                 hbm;
  1897.       HPALETTE                pal;
  1898.       HPALETTE                pOldPal;
  1899.       HDC                     dc;
  1900.  
  1901.       UINT                          nSize;
  1902.       LOGPALETTE                  *pLP;
  1903.       BYTE                          logpalbuffer[5012];
  1904.               // max size = sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) *256 colors
  1905.               //          = 2 + 2 + 1024 = 1028; theoretically only need this much
  1906.               // overshoot just in case; above size ought to be PLENTY
  1907.       int                     nColors;
  1908.       int                     i;
  1909.       LPVOID                  lpDIBBits;
  1910.       BITMAPINFO              *bmInfo;
  1911.  
  1912.       bmInfo = (LPBITMAPINFO) (&hDIB);
  1913.  
  1914.       if (hDIB == NULL)
  1915.              return NULL;
  1916.  
  1917.       dc = GetDC(NULL);  // stuff normally taken care of when MFC is used
  1918.       pal = NULL;
  1919.  
  1920.       lpbi = (LPBITMAPINFOHEADER)hDIB;
  1921.  
  1922.       nColors = lpbi->biClrUsed ? lpbi->biClrUsed :
  1923.                                                                 1 << lpbi->biBitCount;
  1924.  
  1925.       if( bmInfo->bmiHeader.biBitCount > 8 )
  1926.               lpDIBBits = (LPVOID)((LPDWORD)(bmInfo->bmiColors +
  1927.                                 bmInfo->bmiHeader.biClrUsed) +
  1928.                                 ((bmInfo->bmiHeader.biCompression == BI_BITFIELDS) ? 3 : 0));
  1929.       else
  1930.              lpDIBBits = (LPVOID)(bmInfo->bmiColors + nColors);
  1931.  
  1932.           // Create and select a logical palette if needed
  1933.       if( nColors <= 256 && GetDeviceCaps(dc, RASTERCAPS) & RC_PALETTE)
  1934.       {
  1935.                     nSize = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * nColors);
  1936.                     pLP = (LOGPALETTE *) logpalbuffer; //new BYTE[nSize];
  1937.  
  1938.                     pLP->palVersion = 0x300;
  1939.                     pLP->palNumEntries = nColors;
  1940.  
  1941.                     for(i=0; i < nColors; i++)
  1942.                     {
  1943.                           pLP->palPalEntry[i].peRed = bmInfo->bmiColors[i].rgbRed;
  1944.                           pLP->palPalEntry[i].peGreen = bmInfo->bmiColors[i].rgbGreen;
  1945.                           pLP->palPalEntry[i].peBlue = bmInfo->bmiColors[i].rgbBlue;
  1946.                           pLP->palPalEntry[i].peFlags = 0;
  1947.                     }
  1948.  
  1949.                     pal = CreatePalette( pLP );
  1950.  
  1951.                     // Select and realize the palette
  1952.                     pOldPal = SelectPalette( dc, &pal, FALSE );
  1953.                     RealizePalette(dc);
  1954.       }
  1955.  
  1956.  
  1957.       hbm = CreateDIBitmap(dc,           // handle to device context
  1958.                                 (LPBITMAPINFOHEADER)lpbi,       // pointer to bitmap info header
  1959.                                 (LONG)CBM_INIT,                 // initialization flag
  1960.                                 lpDIBBits,                      // pointer to initialization data
  1961.                                 (LPBITMAPINFO)lpbi,             // pointer to bitmap info
  1962.                                 DIB_RGB_COLORS );               // color-data usage
  1963.  
  1964.       if (pal)
  1965.              SelectPalette(dc, pOldPal,FALSE);
  1966.  
  1967.       ReleaseDC(NULL, dc);
  1968.       return hbm;
  1969. }*/
  1970.