summaryrefslogtreecommitdiffstats
path: root/plug-ins/twain/tw_win.c
diff options
context:
space:
mode:
Diffstat (limited to 'plug-ins/twain/tw_win.c')
-rw-r--r--plug-ins/twain/tw_win.c452
1 files changed, 452 insertions, 0 deletions
diff --git a/plug-ins/twain/tw_win.c b/plug-ins/twain/tw_win.c
new file mode 100644
index 0000000..726a45f
--- /dev/null
+++ b/plug-ins/twain/tw_win.c
@@ -0,0 +1,452 @@
+/*
+ * TWAIN Plug-in
+ * Copyright (C) 1999 Craig Setera
+ * Craig Setera <setera@home.com>
+ * 03/31/1999
+ *
+ * Updated for Mac OS X support
+ * Brion Vibber <brion@pobox.com>
+ * 07/22/2004
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Windows platform-specific code
+ */
+
+#include "config.h"
+
+#include <libgimp/gimp.h>
+
+#include "tw_platform.h"
+#include "tw_func.h"
+#include "tw_util.h"
+#include "tw_local.h"
+
+LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
+
+int twainMessageLoop(pTW_SESSION);
+int TwainProcessMessage(LPMSG lpMsg, pTW_SESSION twSession);
+
+extern GimpPlugInInfo PLUG_IN_INFO;
+extern pTW_SESSION initializeTwain ();
+#ifdef _DEBUG
+extern void setRunMode(char *argv[]);
+#endif
+
+
+#define APP_NAME "TWAIN"
+#define SHOW_WINDOW 0
+#define WM_TRANSFER_IMAGE (WM_USER + 100)
+
+/* main bits */
+static HWND hwnd = NULL;
+static HINSTANCE hInst = NULL;
+
+/* Storage for the DLL handle */
+static HINSTANCE hDLL = NULL;
+
+/* Storage for the entry point into the DSM */
+static DSMENTRYPROC dsmEntryPoint = NULL;
+
+
+/*
+ * callDSM
+ *
+ * Call the specified function on the data source manager.
+ */
+TW_UINT16
+callDSM(pTW_IDENTITY pOrigin,
+ pTW_IDENTITY pDest,
+ TW_UINT32 DG,
+ TW_UINT16 DAT,
+ TW_UINT16 MSG,
+ TW_MEMREF pData)
+{
+ /* Call the function */
+ return (*dsmEntryPoint) (pOrigin, pDest, DG, DAT, MSG, pData);
+}
+
+/*
+ * twainIsAvailable
+ *
+ * Return boolean indicating whether TWAIN is available
+ */
+int
+twainIsAvailable(void)
+{
+ /* Already loaded? */
+ if (dsmEntryPoint) {
+ return TRUE;
+ }
+
+ /* Attempt to load the library */
+ hDLL = LoadLibrary(TWAIN_DLL_NAME);
+ if (hDLL == NULL)
+ return FALSE;
+
+ /* Look up the entry point for use */
+ dsmEntryPoint = (DSMENTRYPROC) GetProcAddress(hDLL, "DSM_Entry");
+ if (dsmEntryPoint == NULL)
+ return FALSE;
+
+ return TRUE;
+}
+
+TW_HANDLE
+twainAllocHandle (size_t size)
+{
+ return GlobalAlloc(GHND, size);
+}
+
+TW_MEMREF
+twainLockHandle (TW_HANDLE handle)
+{
+ return GlobalLock (handle);
+}
+
+void
+twainUnlockHandle (TW_HANDLE handle)
+{
+ GlobalUnlock (handle);
+}
+
+void
+twainFreeHandle (TW_HANDLE handle)
+{
+ GlobalFree (handle);
+}
+
+gboolean
+twainSetupCallback (pTW_SESSION twSession)
+{
+ /* Callbacks go through the window messaging system */
+ return TRUE;
+}
+
+/*
+ * unloadTwainLibrary
+ *
+ * Unload the TWAIN dynamic link library
+ */
+int
+unloadTwainLibrary(pTW_SESSION twSession)
+{
+ /* Explicitly free the SM library */
+ if (hDLL) {
+ FreeLibrary(hDLL);
+ hDLL=NULL;
+ }
+
+ /* the data source id will no longer be valid after
+ * twain is killed. If the id is left around the
+ * data source can not be found or opened
+ */
+ DS_IDENTITY(twSession)->Id = 0;
+
+ /* We are now back at state 1 */
+ twSession->twainState = 1;
+ LogMessage("Source Manager successfully closed\n");
+
+ return TRUE;
+}
+
+/*
+ * TwainProcessMessage
+ *
+ * Returns TRUE if the application should process message as usual.
+ * Returns FALSE if the application should skip processing of this message
+ */
+int
+TwainProcessMessage(LPMSG lpMsg, pTW_SESSION twSession)
+{
+ TW_EVENT twEvent;
+
+ twSession->twRC = TWRC_NOTDSEVENT;
+
+ /* Only ask Source Manager to process event if there is a Source connected. */
+ if (DSM_IS_OPEN(twSession) && DS_IS_OPEN(twSession)) {
+ /*
+ * A Source provides a modeless dialog box as its user interface.
+ * The following call relays Windows messages down to the Source's
+ * UI that were intended for its dialog box. It also retrieves TWAIN
+ * messages sent from the Source to our Application.
+ */
+ twEvent.pEvent = (TW_MEMREF) lpMsg;
+ twSession->twRC = callDSM(APP_IDENTITY(twSession), DS_IDENTITY(twSession),
+ DG_CONTROL, DAT_EVENT, MSG_PROCESSEVENT,
+ (TW_MEMREF) &twEvent);
+
+ /* Check the return code */
+ if (twSession->twRC == TWRC_NOTDSEVENT) {
+ return FALSE;
+ }
+
+ /* Process the message as necessary */
+ processTwainMessage(twEvent.TWMessage, twSession);
+ }
+
+ /* tell the caller what happened */
+ return (twSession->twRC == TWRC_DSEVENT);
+}
+
+/*
+ * twainMessageLoop
+ *
+ * Process Win32 window messages and provide special handling
+ * of TWAIN specific messages. This loop will not exit until
+ * the application exits.
+ */
+int
+twainMessageLoop(pTW_SESSION twSession)
+{
+ MSG msg;
+
+ while (GetMessage(&msg, NULL, 0, 0)) {
+ if (DS_IS_CLOSED(twSession) || !TwainProcessMessage(&msg, twSession)) {
+ TranslateMessage((LPMSG)&msg);
+ DispatchMessage(&msg);
+ }
+ }
+
+ return msg.wParam;
+}
+
+/*
+ * LogLastWinError
+ *
+ * Log the last Windows error as returned by
+ * GetLastError.
+ */
+void
+LogLastWinError(void)
+{
+ LPVOID lpMsgBuf;
+
+ FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ GetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
+ (LPTSTR) &lpMsgBuf,
+ 0,
+ NULL
+ );
+
+ LogMessage("%s\n", lpMsgBuf);
+
+ /* Free the buffer. */
+ LocalFree( lpMsgBuf );
+}
+
+void twainQuitApplication ()
+{
+ PostQuitMessage (0);
+}
+
+
+/******************************************************************
+ * Win32 entry point and setup...
+ ******************************************************************/
+
+/*
+ * WinMain
+ *
+ * The standard gimp entry point won't quite cut it for
+ * this plug-in. This plug-in requires creation of a
+ * standard Win32 window (hidden) in order to receive
+ * and process window messages on behalf of the TWAIN
+ * datasource.
+ */
+int APIENTRY
+WinMain(HINSTANCE hInstance,
+ HINSTANCE hPrevInstance,
+ LPSTR lpCmdLine,
+ int nCmdShow)
+{
+
+ /*
+ * Normally, we would do all of the Windows-ish set up of
+ * the window classes and stuff here in WinMain. But,
+ * the only time we really need the window and message
+ * queues is during the plug-in run. So, all of that will
+ * be done during run(). This avoids all of the Windows
+ * setup stuff for the query(). Stash the instance handle now
+ * so it is available from the run() procedure.
+ */
+ hInst = hInstance;
+
+#ifdef _DEBUG
+ /* When in debug version, we allow different run modes...
+ * make sure that it is correctly set.
+ */
+ setRunMode(__argv);
+#endif /* _DEBUG */
+
+ /*
+ * Now, call gimp_main... This is what the MAIN() macro
+ * would usually do.
+ */
+ return gimp_main(&PLUG_IN_INFO, __argc, __argv);
+}
+
+/*
+ * main
+ *
+ * allow to build as console app as well
+ */
+int main (int argc, char *argv[])
+{
+#ifdef _DEBUG
+ /* When in debug version, we allow different run modes...
+ * make sure that it is correctly set.
+ */
+ setRunMode(__argv);
+#endif /* _DEBUG */
+
+ /*
+ * Now, call gimp_main... This is what the MAIN() macro
+ * would usually do.
+ */
+ return gimp_main(&PLUG_IN_INFO, __argc, __argv);
+}
+
+/*
+ * InitApplication
+ *
+ * Initialize window data and register the window class
+ */
+BOOL
+InitApplication(HINSTANCE hInstance)
+{
+ WNDCLASS wc;
+ BOOL retValue;
+
+ /*
+ * Fill in window class structure with parameters to describe
+ * the main window.
+ */
+ wc.style = CS_HREDRAW | CS_VREDRAW;
+ wc.lpfnWndProc = (WNDPROC) WndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = hInstance;
+ wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
+ wc.lpszClassName = APP_NAME;
+ wc.lpszMenuName = NULL;
+
+ /* Register the window class and stash success/failure code. */
+ retValue = RegisterClass(&wc);
+
+ /* Log error */
+ if (!retValue)
+ LogLastWinError();
+
+ return retValue;
+}
+
+/*
+ * InitInstance
+ *
+ * Create the main window for the application. Used to
+ * interface with the TWAIN datasource.
+ */
+BOOL
+InitInstance(HINSTANCE hInstance, int nCmdShow, pTW_SESSION twSession)
+{
+ /* Create our window */
+ hwnd = CreateWindow(APP_NAME, APP_NAME, WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
+ NULL, NULL, hInstance, NULL);
+
+ if (!hwnd) {
+ return (FALSE);
+ }
+
+ /* Register our window handle with the TWAIN
+ * support.
+ */
+ registerWindowHandle(twSession, hwnd);
+
+ /* Schedule the image transfer by posting a message */
+ PostMessage(hwnd, WM_TRANSFER_IMAGE, 0, 0);
+
+ ShowWindow(hwnd, nCmdShow);
+ UpdateWindow(hwnd);
+
+ return TRUE;
+}
+
+/*
+ * twainWinMain
+ *
+ * This is the function that represents the code that
+ * would normally reside in WinMain (see above). This
+ * function will get called during run() in order to set
+ * up the windowing environment necessary for TWAIN to
+ * operate.
+ */
+int
+twainMain()
+{
+ /* Initialize the twain information */
+ pTW_SESSION twSession = initializeTwain();
+
+ /* Perform instance initialization */
+ if (!InitApplication(hInst))
+ return (FALSE);
+
+ /* Perform application initialization */
+ if (!InitInstance(hInst, SHOW_WINDOW, twSession))
+ return (FALSE);
+
+ /*
+ * Call the main message processing loop...
+ * This call will not return until the application
+ * exits.
+ */
+ return twainMessageLoop(twSession);
+}
+
+/*
+ * WndProc
+ *
+ * Process window message for the main window.
+ */
+LRESULT CALLBACK
+WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch (message) {
+
+ case WM_TRANSFER_IMAGE:
+ /* Get an image */
+ scanImage ();
+ break;
+
+ case WM_DESTROY:
+ LogMessage("Exiting application\n");
+ PostQuitMessage(0);
+ break;
+
+ default:
+ return (DefWindowProc(hWnd, message, wParam, lParam));
+ }
+ return 0;
+}
+