diff options
Diffstat (limited to 'plug-ins/twain/tw_win.c')
-rw-r--r-- | plug-ins/twain/tw_win.c | 452 |
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; +} + |