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