1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_extensions.hxx" 30 31 #include <string.h> 32 #include <math.h> 33 34 #if defined( WNT ) 35 #include <tools/svwin.h> 36 #endif 37 #ifdef OS2 38 #include <svpm.h> 39 #endif // OS2 40 #include <vos/module.hxx> 41 #include <tools/stream.hxx> 42 #include <vcl/svapp.hxx> 43 #include <vcl/wrkwin.hxx> 44 #include <vcl/sysdata.hxx> 45 #include "twain.hxx" 46 47 // ----------- 48 // - Defines - 49 // ----------- 50 51 #define PFUNC (*pDSM) 52 #define FIXTODOUBLE( nFix ) ((double)nFix.Whole+(double)nFix.Frac/65536.) 53 #define FIXTOLONG( nFix ) ((long)floor(FIXTODOUBLE(nFix)+0.5)) 54 55 #if defined WNT 56 #define TWAIN_LIBNAME "TWAIN_32.DLL" 57 #define TWAIN_FUNCNAME "DSM_Entry" 58 #elif defined OS2 59 #define TWAIN_LIBNAME "twain" 60 #define TWAIN_FUNCNAME "DSM_ENTRY" 61 #endif 62 63 // ----------- 64 // - Statics - 65 // ----------- 66 67 static ImpTwain* pImpTwainInstance = NULL; 68 69 // --------- 70 // - Procs - 71 // --------- 72 73 #ifdef OS2 74 75 #define PTWAINMSG QMSG* 76 77 MRESULT EXPENTRY TwainWndProc( HWND hWnd, ULONG nMsg, MPARAM nParam1, MPARAM nParam2 ) 78 { 79 return (MRESULT) TRUE; 80 } 81 82 83 #else // OS2 84 85 #define PTWAINMSG MSG* 86 87 // ------------------------------------------------------------------------- 88 89 LRESULT CALLBACK TwainWndProc( HWND hWnd,UINT nMsg, WPARAM nPar1, LPARAM nPar2 ) 90 { 91 return DefWindowProc( hWnd, nMsg, nPar1, nPar2 ); 92 } 93 94 // ------------------------------------------------------------------------- 95 96 LRESULT CALLBACK TwainMsgProc( int nCode, WPARAM wParam, LPARAM lParam ) 97 { 98 MSG* pMsg = (MSG*) lParam; 99 100 if( ( nCode < 0 ) || 101 ( pImpTwainInstance->hTwainWnd != pMsg->hwnd ) || 102 !pImpTwainInstance->ImplHandleMsg( (void*) lParam ) ) 103 { 104 return CallNextHookEx( pImpTwainInstance->hTwainHook, nCode, wParam, lParam ); 105 } 106 else 107 { 108 pMsg->message = WM_USER; 109 pMsg->lParam = 0; 110 111 return 0; 112 } 113 } 114 115 #endif // OS2 116 117 // ------------ 118 // - ImpTwain - 119 // ------------ 120 121 ImpTwain::ImpTwain( const Link& rNotifyLink ) : 122 aNotifyLink ( rNotifyLink ), 123 pDSM ( NULL ), 124 pMod ( NULL ), 125 hTwainWnd ( 0 ), 126 hTwainHook ( 0 ), 127 nCurState ( 1 ) 128 { 129 pImpTwainInstance = this; 130 131 aAppIdent.Id = 0; 132 aAppIdent.Version.MajorNum = 1; 133 aAppIdent.Version.MinorNum = 0; 134 aAppIdent.Version.Language = TWLG_USA; 135 aAppIdent.Version.Country = TWCY_USA; 136 aAppIdent.ProtocolMajor = TWON_PROTOCOLMAJOR; 137 aAppIdent.ProtocolMinor = TWON_PROTOCOLMINOR; 138 aAppIdent.SupportedGroups = DG_IMAGE | DG_CONTROL; 139 strcpy( aAppIdent.Version.Info, "6.0" ); 140 strcpy( aAppIdent.Manufacturer, "Sun Microsystems"); 141 strcpy( aAppIdent.ProductFamily,"Office"); 142 strcpy( aAppIdent.ProductName, "Office"); 143 144 #ifdef OS2 145 146 hAB = Sysdepen::GethAB(); 147 ImplFallback( TWAIN_EVENT_QUIT ); 148 // hTwainWnd = WinCreateWindow( HWND_DESKTOP, WC_FRAME, "dummy", 0, 0, 0, 0, 0, HWND_DESKTOP, HWND_BOTTOM, 0, 0, 0 ); 149 150 #else 151 152 HWND hParentWnd = HWND_DESKTOP; 153 WNDCLASS aWc = { 0, &TwainWndProc, 0, sizeof( WNDCLASS ), GetModuleHandle( NULL ), 154 NULL, NULL, NULL, NULL, "TwainClass" }; 155 156 RegisterClass( &aWc ); 157 hTwainWnd = CreateWindowEx( WS_EX_TOPMOST, aWc.lpszClassName, "TWAIN", 0, 0, 0, 0, 0, hParentWnd, NULL, aWc.hInstance, 0 ); 158 hTwainHook = SetWindowsHookEx( WH_GETMESSAGE, &TwainMsgProc, NULL, GetCurrentThreadId() ); 159 160 #endif 161 } 162 163 // ----------------------------------------------------------------------------- 164 165 ImpTwain::~ImpTwain() 166 { 167 } 168 169 // ----------------------------------------------------------------------------- 170 171 void ImpTwain::Destroy() 172 { 173 ImplFallback( TWAIN_EVENT_NONE ); 174 Application::PostUserEvent( LINK( this, ImpTwain, ImplDestroyHdl ), NULL ); 175 } 176 177 // ----------------------------------------------------------------------------- 178 179 sal_Bool ImpTwain::SelectSource() 180 { 181 TW_UINT16 nRet = TWRC_FAILURE; 182 183 if( !!aBitmap ) 184 aBitmap = Bitmap(); 185 186 ImplOpenSourceManager(); 187 188 if( 3 == nCurState ) 189 { 190 TW_IDENTITY aIdent; 191 192 aIdent.Id = 0, aIdent.ProductName[ 0 ] = '\0'; 193 aNotifyLink.Call( (void*) TWAIN_EVENT_SCANNING ); 194 nRet = PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_IDENTITY, MSG_USERSELECT, &aIdent ); 195 } 196 197 ImplFallback( TWAIN_EVENT_QUIT ); 198 199 return( nRet == TWRC_SUCCESS || nRet == TWRC_CANCEL ); 200 } 201 202 // ----------------------------------------------------------------------------- 203 204 sal_Bool ImpTwain::InitXfer() 205 { 206 sal_Bool bRet = sal_False; 207 208 if( !!aBitmap ) 209 aBitmap = Bitmap(); 210 211 ImplOpenSourceManager(); 212 213 if( 3 == nCurState ) 214 { 215 ImplOpenSource(); 216 217 if( 4 == nCurState ) 218 bRet = ImplEnableSource(); 219 } 220 221 if( !bRet ) 222 ImplFallback( TWAIN_EVENT_QUIT ); 223 224 return bRet; 225 } 226 227 // ----------------------------------------------------------------------------- 228 229 Bitmap ImpTwain::GetXferBitmap() 230 { 231 Bitmap aRet( aBitmap ); 232 aBitmap = Bitmap(); 233 return aRet; 234 } 235 236 // ----------------------------------------------------------------------------- 237 238 void ImpTwain::ImplOpenSourceManager() 239 { 240 if( 1 == nCurState ) 241 { 242 pMod = new vos:: OModule (); 243 244 if( pMod->load( TWAIN_LIBNAME ) ) 245 { 246 nCurState = 2; 247 248 if( ( ( pDSM = (DSMENTRYPROC) pMod->getSymbol( TWAIN_FUNCNAME ) ) != NULL ) && 249 ( PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_PARENT, MSG_OPENDSM, &hTwainWnd ) == TWRC_SUCCESS ) ) 250 { 251 nCurState = 3; 252 } 253 } 254 else 255 { 256 delete pMod; 257 pMod = NULL; 258 } 259 } 260 } 261 262 // ----------------------------------------------------------------------------- 263 264 void ImpTwain::ImplOpenSource() 265 { 266 if( 3 == nCurState ) 267 { 268 if( ( PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_IDENTITY, MSG_GETDEFAULT, &aSrcIdent ) == TWRC_SUCCESS ) && 269 ( PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_IDENTITY, MSG_OPENDS, &aSrcIdent ) == TWRC_SUCCESS ) ) 270 { 271 #ifdef OS2 272 273 // negotiate capabilities 274 275 #else 276 277 TW_CAPABILITY aCap = { CAP_XFERCOUNT, TWON_ONEVALUE, GlobalAlloc( GHND, sizeof( TW_ONEVALUE ) ) }; 278 TW_ONEVALUE* pVal = (TW_ONEVALUE*) GlobalLock( aCap.hContainer ); 279 280 pVal->ItemType = TWTY_INT16, pVal->Item = 1; 281 GlobalUnlock( aCap.hContainer ); 282 PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_CAPABILITY, MSG_SET, &aCap ); 283 GlobalFree( aCap.hContainer ); 284 #endif 285 286 nCurState = 4; 287 } 288 } 289 } 290 291 // ----------------------------------------------------------------------------- 292 293 BOOL ImpTwain::ImplEnableSource() 294 { 295 BOOL bRet = FALSE; 296 297 if( 4 == nCurState ) 298 { 299 TW_USERINTERFACE aUI = { TRUE, TRUE, hTwainWnd }; 300 301 aNotifyLink.Call( (void*) TWAIN_EVENT_SCANNING ); 302 nCurState = 5; 303 304 if( PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_USERINTERFACE, MSG_ENABLEDS, &aUI ) == TWRC_SUCCESS ) 305 bRet = TRUE; 306 else 307 nCurState = 4; 308 } 309 310 return bRet; 311 } 312 313 // ----------------------------------------------------------------------------- 314 315 BOOL ImpTwain::ImplHandleMsg( void* pMsg ) 316 { 317 TW_UINT16 nRet; 318 PTWAINMSG pMess = (PTWAINMSG) pMsg; 319 TW_EVENT aEvt = { pMess, MSG_NULL }; 320 321 nRet = PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_EVENT, MSG_PROCESSEVENT, &aEvt ); 322 323 if( aEvt.TWMessage != MSG_NULL ) 324 { 325 switch( aEvt.TWMessage ) 326 { 327 case MSG_XFERREADY: 328 { 329 ULONG nEvent = TWAIN_EVENT_QUIT; 330 331 if( 5 == nCurState ) 332 { 333 nCurState = 6; 334 ImplXfer(); 335 336 if( !!aBitmap ) 337 nEvent = TWAIN_EVENT_XFER; 338 } 339 340 ImplFallback( nEvent ); 341 } 342 break; 343 344 case MSG_CLOSEDSREQ: 345 ImplFallback( TWAIN_EVENT_QUIT ); 346 break; 347 348 default: 349 break; 350 } 351 } 352 else 353 nRet = TWRC_NOTDSEVENT; 354 355 return( TWRC_DSEVENT == nRet ); 356 } 357 358 // ----------------------------------------------------------------------------- 359 360 void ImpTwain::ImplXfer() 361 { 362 if( nCurState == 6 ) 363 { 364 TW_IMAGEINFO aInfo; 365 TW_UINT32 hDIB = 0; 366 long nWidth = aInfo.ImageWidth; 367 long nHeight = aInfo.ImageLength; 368 long nXRes = FIXTOLONG( aInfo.XResolution ); 369 long nYRes = FIXTOLONG( aInfo.YResolution ); 370 371 if( PFUNC( &aAppIdent, &aSrcIdent, DG_IMAGE, DAT_IMAGEINFO, MSG_GET, &aInfo ) == TWRC_SUCCESS ) 372 { 373 nWidth = aInfo.ImageWidth; 374 nHeight = aInfo.ImageLength; 375 nXRes = FIXTOLONG( aInfo.XResolution ); 376 nYRes = FIXTOLONG( aInfo.YResolution ); 377 } 378 else 379 nWidth = nHeight = nXRes = nYRes = -1L; 380 381 switch( PFUNC( &aAppIdent, &aSrcIdent, DG_IMAGE, DAT_IMAGENATIVEXFER, MSG_GET, &hDIB ) ) 382 { 383 case( TWRC_CANCEL ): 384 nCurState = 7; 385 break; 386 387 case( TWRC_XFERDONE ): 388 { 389 #ifdef OS2 390 391 // get OS/2-Bitmap 392 393 #else // OS2 394 const ULONG nSize = GlobalSize( (HGLOBAL) hDIB ); 395 char* pBuf = (char*) GlobalLock( (HGLOBAL) hDIB ); 396 397 if( pBuf ) 398 { 399 SvMemoryStream aMemStm; 400 aMemStm.SetBuffer( pBuf, nSize, FALSE, nSize ); 401 aBitmap.Read( aMemStm, FALSE ); 402 GlobalUnlock( (HGLOBAL) hDIB ); 403 } 404 405 GlobalFree( (HGLOBAL) hDIB ); 406 #endif // OS2 407 408 // set resolution of bitmap if neccessary 409 if ( ( nXRes != -1 ) && ( nYRes != - 1 ) && ( nWidth != - 1 ) && ( nHeight != - 1 ) ) 410 { 411 const MapMode aMapMode( MAP_100TH_INCH, Point(), Fraction( 100, nXRes ), Fraction( 100, nYRes ) ); 412 aBitmap.SetPrefMapMode( aMapMode ); 413 aBitmap.SetPrefSize( Size( nWidth, nHeight ) ); 414 } 415 416 nCurState = 7; 417 } 418 break; 419 420 default: 421 break; 422 } 423 } 424 } 425 426 // ----------------------------------------------------------------------------- 427 428 void ImpTwain::ImplFallback( ULONG nEvent ) 429 { 430 Application::PostUserEvent( LINK( this, ImpTwain, ImplFallbackHdl ), (void*) nEvent ); 431 } 432 433 // ----------------------------------------------------------------------------- 434 435 IMPL_LINK( ImpTwain, ImplFallbackHdl, void*, pData ) 436 { 437 const ULONG nEvent = (ULONG) pData; 438 sal_Bool bFallback = sal_True; 439 440 switch( nCurState ) 441 { 442 case( 7 ): 443 case( 6 ): 444 { 445 TW_PENDINGXFERS aXfers; 446 447 if( PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER, &aXfers ) == TWRC_SUCCESS ) 448 { 449 if( aXfers.Count != 0 ) 450 PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_PENDINGXFERS, MSG_RESET, &aXfers ); 451 } 452 453 nCurState = 5; 454 } 455 break; 456 457 case( 5 ): 458 { 459 TW_USERINTERFACE aUI = { TRUE, TRUE, hTwainWnd }; 460 461 PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_USERINTERFACE, MSG_DISABLEDS, &aUI ); 462 nCurState = 4; 463 } 464 break; 465 466 case( 4 ): 467 { 468 PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_IDENTITY, MSG_CLOSEDS, &aSrcIdent ); 469 nCurState = 3; 470 } 471 break; 472 473 case( 3 ): 474 { 475 PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_PARENT, MSG_CLOSEDSM, &hTwainWnd ); 476 nCurState = 2; 477 } 478 break; 479 480 case( 2 ): 481 { 482 delete pMod; 483 pMod = NULL; 484 nCurState = 1; 485 } 486 break; 487 488 default: 489 { 490 if( nEvent != TWAIN_EVENT_NONE ) 491 aNotifyLink.Call( (void*) nEvent ); 492 493 bFallback = sal_False; 494 } 495 break; 496 } 497 498 if( bFallback ) 499 ImplFallback( nEvent ); 500 501 return 0L; 502 } 503 504 // ----------------------------------------------------------------------------- 505 506 IMPL_LINK( ImpTwain, ImplDestroyHdl, void*, p ) 507 { 508 #ifdef OS2 509 510 if( hWndTwain ) 511 WinDestroyWindow( hWndTwain ); 512 513 // unset hook 514 515 #else 516 517 if( hTwainWnd ) 518 DestroyWindow( hTwainWnd ); 519 520 if( hTwainHook ) 521 UnhookWindowsHookEx( hTwainHook ); 522 523 #endif 524 525 delete this; 526 pImpTwainInstance = NULL; 527 528 return 0L; 529 } 530