xref: /trunk/main/extensions/source/scanner/sane.cxx (revision 93ed1f29)
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 #include <cstdarg>
27 #include <math.h>
28 #include <osl/file.h>
29 #include <tools/stream.hxx>
30 #include <sane.hxx>
31 #include <dlfcn.h>
32 #include <stdio.h>
33 #include <unistd.h>
34 #include <sys/time.h>
35 #include <sys/types.h>
36 #include <sal/config.h>
37 
38 #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
39 #include <stdarg.h>
40 #define dump_state( a, b, c, d ) fprintf( stderr, a, b, c, d );
41 #else
42 #define dump_state( a, b, c, d ) ;
43 #endif
dbg_msg(const char * pString,...)44 inline void dbg_msg( const char* pString, ... )
45 {
46 #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
47 	va_list ap;
48 	va_start( ap, pString );
49 	vfprintf( stderr, pString, ap );
50 	va_end( ap );
51 #else
52     (void)pString;
53 #endif
54 }
55 
56 #define FAIL_SHUTDOWN_STATE( x, y, z ) \
57 	if( x != SANE_STATUS_GOOD )								\
58 	{														\
59 		dump_state( "%s returned error %d (%s)\n",			\
60 				 y, x, p_strstatus( x ) );					\
61 		DeInit();											\
62 		return z;											\
63 	}
64 
65 #define FAIL_STATE( x, y, z ) \
66 	if( x != SANE_STATUS_GOOD )								\
67 	{														\
68 		dump_state( "%s returned error %d (%s)\n",			\
69 				 y, x, p_strstatus( x ) );					\
70 		return z;											\
71 	}
72 
73 #define DUMP_STATE( x, y ) \
74 	if( x != SANE_STATUS_GOOD )								\
75 	{														\
76 		dump_state( "%s returned error %d (%s)\n",			\
77 				 y, x, p_strstatus( x ) );					\
78 	}
79 
80 #define CHECK_STATE( x, y ) \
81 	if( x != SANE_STATUS_GOOD )								\
82 	{														\
83 		dump_state( "%s returned error %d (%s)\n",			\
84 				 y, x, p_strstatus( x ) );					\
85 	}														\
86 	else
87 
88 int				Sane::nRefCount = 0;
89 oslModule       Sane::pSaneLib = 0;
90 SANE_Int		Sane::nVersion = 0;
91 SANE_Device**	Sane::ppDevices = 0;
92 int				Sane::nDevices = 0;
93 
94 SANE_Status		(*Sane::p_init)( SANE_Int*,
95 								 SANE_Auth_Callback ) = 0;
96 void			(*Sane::p_exit)() = 0;
97 SANE_Status		(*Sane::p_get_devices)( const SANE_Device***,
98 										SANE_Bool ) = 0;
99 SANE_Status		(*Sane::p_open)( SANE_String_Const, SANE_Handle ) = 0;
100 void			(*Sane::p_close)( SANE_Handle ) = 0;
101 const SANE_Option_Descriptor* (*Sane::p_get_option_descriptor)(
102 	SANE_Handle, SANE_Int ) = 0;
103 SANE_Status		(*Sane::p_control_option)( SANE_Handle, SANE_Int,
104 										   SANE_Action, void*,
105 										   SANE_Int* ) = 0;
106 SANE_Status		(*Sane::p_get_parameters)( SANE_Handle,
107 										   SANE_Parameters* ) = 0;
108 SANE_Status		(*Sane::p_start)( SANE_Handle ) = 0;
109 SANE_Status		(*Sane::p_read)( SANE_Handle, SANE_Byte*, SANE_Int,
110 								 SANE_Int* ) = 0;
111 void			(*Sane::p_cancel)( SANE_Handle ) = 0;
112 SANE_Status		(*Sane::p_set_io_mode)( SANE_Handle, SANE_Bool ) = 0;
113 SANE_Status		(*Sane::p_get_select_fd)( SANE_Handle, SANE_Int* ) = 0;
114 SANE_String_Const (*Sane::p_strstatus)( SANE_Status ) = 0;
115 
116 static sal_Bool bSaneSymbolLoadFailed = sal_False;
117 
LoadSymbol(const char * pSymbolname)118 inline oslGenericFunction Sane::LoadSymbol( const char* pSymbolname )
119 {
120     oslGenericFunction pFunction = osl_getAsciiFunctionSymbol( pSaneLib, pSymbolname );
121 	if( ! pFunction )
122 	{
123 		fprintf( stderr, "Could not load symbol %s\n",
124 				 pSymbolname );
125 		bSaneSymbolLoadFailed = sal_True;
126 	}
127     return pFunction;
128 }
129 
ControlOption(int nOption,SANE_Action nAction,void * pData)130 SANE_Status Sane::ControlOption( int nOption, SANE_Action nAction,
131 								 void* pData )
132 {
133 	SANE_Status	nStatus = SANE_STATUS_GOOD;
134 	SANE_Int	nInfo = 0;
135 
136 	nStatus = p_control_option( maHandle, (SANE_Int)nOption,
137 								nAction, pData, &nInfo );
138 	DUMP_STATE( nStatus, "sane_control_option" );
139 #if OSL_DEBUG_LEVEL > 1
140 	if( nStatus != SANE_STATUS_GOOD )
141 	{
142 		const char* pAction = "Unknown";
143 		switch( nAction )
144 		{
145 			case SANE_ACTION_GET_VALUE:
146 				pAction = "SANE_ACTION_GET_VALUE";break;
147 			case SANE_ACTION_SET_VALUE:
148 				pAction = "SANE_ACTION_SET_VALUE";break;
149 			case SANE_ACTION_SET_AUTO:
150 				pAction = "SANE_ACTION_SET_AUTO";break;
151 		}
152 		dbg_msg( "Option: \"%s\" action: %s\n",
153 				 ByteString( GetOptionName( nOption ), gsl_getSystemTextEncoding() ).GetBuffer(),
154 				 pAction );
155 	}
156 #endif
157 //	if( nInfo & ( SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS ) )
158 	if( nInfo &  SANE_INFO_RELOAD_OPTIONS )
159 		ReloadOptions();
160 	return nStatus;
161 }
162 
Sane()163 Sane::Sane() :
164 		mppOptions( 0 ),
165 		mnOptions( 0 ),
166 		mnDevice( -1 ),
167 		maHandle( 0 )
168 {
169 	if( ! nRefCount || ! pSaneLib )
170 		Init();
171 	nRefCount++;
172 };
173 
~Sane()174 Sane::~Sane()
175 {
176 	if( IsOpen() )
177 		Close();
178 	nRefCount--;
179 	if( ! nRefCount && pSaneLib )
180 		DeInit();
181 }
182 
Init()183 void Sane::Init()
184 {
185     ::rtl::OUString sSaneLibName( ::rtl::OUString::createFromAscii( "libsane" SAL_DLLEXTENSION ) );
186     pSaneLib = osl_loadModule( sSaneLibName.pData, SAL_LOADMODULE_LAZY );
187     if( ! pSaneLib )
188     {
189         sSaneLibName = ::rtl::OUString::createFromAscii( "libsane" SAL_DLLEXTENSION ".1" );
190         pSaneLib = osl_loadModule( sSaneLibName.pData, SAL_LOADMODULE_LAZY );
191     }
192     // try reasonable places that might not be in the library search path
193 	if( ! pSaneLib )
194     {
195         ::rtl::OUString sSaneLibSystemPath( ::rtl::OUString::createFromAscii( "/usr/local/lib/libsane" SAL_DLLEXTENSION ) );
196         osl_getFileURLFromSystemPath( sSaneLibSystemPath.pData, &sSaneLibName.pData );
197         pSaneLib = osl_loadModule( sSaneLibName.pData, SAL_LOADMODULE_LAZY );
198     }
199 
200 	if( pSaneLib )
201 	{
202 		bSaneSymbolLoadFailed = sal_False;
203 		p_init = (SANE_Status(*)(SANE_Int*, SANE_Auth_Callback ))
204 			LoadSymbol( "sane_init" );
205 		p_exit = (void(*)())
206 			LoadSymbol( "sane_exit" );
207 		p_get_devices = (SANE_Status(*)(const SANE_Device***,
208 										SANE_Bool ))
209 			LoadSymbol( "sane_get_devices" );
210 		p_open = (SANE_Status(*)(SANE_String_Const, SANE_Handle ))
211 			LoadSymbol( "sane_open" );
212 		p_close = (void(*)(SANE_Handle))
213 			LoadSymbol( "sane_close" );
214 		p_get_option_descriptor = (const SANE_Option_Descriptor*(*)(SANE_Handle,
215 															  SANE_Int))
216 			LoadSymbol( "sane_get_option_descriptor" );
217 		p_control_option = (SANE_Status(*)(SANE_Handle, SANE_Int,
218 										   SANE_Action, void*, SANE_Int*))
219 			LoadSymbol( "sane_control_option" );
220 		p_get_parameters = (SANE_Status(*)(SANE_Handle,SANE_Parameters*))
221 			LoadSymbol( "sane_get_parameters" );
222 		p_start = (SANE_Status(*)(SANE_Handle))
223 			LoadSymbol( "sane_start" );
224 		p_read = (SANE_Status(*)(SANE_Handle, SANE_Byte*,
225 								 SANE_Int, SANE_Int* ))
226 			LoadSymbol( "sane_read" );
227 		p_cancel = (void(*)(SANE_Handle))
228 			LoadSymbol( "sane_cancel" );
229 		p_set_io_mode = (SANE_Status(*)(SANE_Handle, SANE_Bool))
230 			LoadSymbol( "sane_set_io_mode" );
231 		p_get_select_fd = (SANE_Status(*)(SANE_Handle, SANE_Int*))
232 			LoadSymbol( "sane_get_select_fd" );
233 		p_strstatus = (SANE_String_Const(*)(SANE_Status))
234 			LoadSymbol( "sane_strstatus" );
235 		if( bSaneSymbolLoadFailed )
236 			DeInit();
237 		else
238 		{
239 			SANE_Status nStatus = p_init( &nVersion, 0 );
240 			FAIL_SHUTDOWN_STATE( nStatus, "sane_init", );
241 			nStatus = p_get_devices( (const SANE_Device***)&ppDevices,
242 									 SANE_FALSE );
243 			FAIL_SHUTDOWN_STATE( nStatus, "sane_get_devices", );
244 			for( nDevices = 0 ; ppDevices[ nDevices ]; nDevices++ ) ;
245 		}
246 	}
247 #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
248 	else
249 		fprintf( stderr, "libsane%s could not be opened: %s\n", SAL_DLLEXTENSION,
250 				 dlerror() );
251 #endif
252 }
253 
DeInit()254 void Sane::DeInit()
255 {
256 	if( pSaneLib )
257 	{
258 		p_exit();
259         osl_unloadModule( pSaneLib );
260 		pSaneLib = 0;
261 	}
262 }
263 
ReloadDevices()264 void Sane::ReloadDevices()
265 {
266 	if( IsOpen() )
267 		Close();
268 	DeInit();
269 	Init();
270 }
271 
ReloadOptions()272 void Sane::ReloadOptions()
273 {
274 	if( ! IsOpen() )
275 		return;
276 
277 	SANE_Option_Descriptor* pZero = (SANE_Option_Descriptor*)
278 		p_get_option_descriptor( maHandle, 0 );
279 	SANE_Word pOptions[2];
280 	SANE_Status nStatus = p_control_option( maHandle, 0, SANE_ACTION_GET_VALUE,
281 											(void*)pOptions, NULL );
282 	if( nStatus != SANE_STATUS_GOOD )
283 		fprintf( stderr, "Error: sane driver returned %s while reading number of options !\n", p_strstatus( nStatus ) );
284 
285 	mnOptions = pOptions[ 0 ];
286 	if( (size_t)pZero->size > sizeof( SANE_Word ) )
287 		fprintf( stderr, "driver returned numer of options with larger size tha SANE_Word !!!\n" );
288 	if( mppOptions )
289 		delete [] mppOptions;
290 	mppOptions = (const SANE_Option_Descriptor**)new SANE_Option_Descriptor*[ mnOptions ];
291 	mppOptions[ 0 ] = (SANE_Option_Descriptor*)pZero;
292 	for( int i = 1; i < mnOptions; i++ )
293 		mppOptions[ i ] =  (SANE_Option_Descriptor*)
294 			p_get_option_descriptor( maHandle, i );
295 
296 	CheckConsistency( NULL, sal_True );
297 
298 	maReloadOptionsLink.Call( this );
299 }
300 
Open(const char * name)301 sal_Bool Sane::Open( const char* name )
302 {
303 	int i;
304 
305 	SANE_Status nStatus = p_open( (SANE_String_Const)name, &maHandle );
306 	FAIL_STATE( nStatus, "sane_open", sal_False );
307 
308 	ReloadOptions();
309 
310 	if( mnDevice == -1 )
311 	{
312 		ByteString aDevice( name );
313 		for( i = 0; i < nDevices; i++ )
314 		{
315 			if( aDevice.Equals( ppDevices[i]->name ) )
316 			{
317 				mnDevice = i;
318 				break;
319 			}
320 		}
321 	}
322 
323 	return sal_True;
324 }
325 
Open(int n)326 sal_Bool Sane::Open( int n )
327 {
328 	if( n >= 0 && n < nDevices )
329 	{
330 		mnDevice = n;
331 		return Open( (char*)ppDevices[n]->name );
332 	}
333 	return sal_False;
334 }
335 
Close()336 void Sane::Close()
337 {
338 	if( maHandle )
339 	{
340 		p_close( maHandle );
341 		delete [] mppOptions;
342 		mppOptions = 0;
343 		maHandle = 0;
344 		mnDevice = -1;
345 	}
346 }
347 
GetOptionByName(const char * rName)348 int Sane::GetOptionByName( const char* rName )
349 {
350 	int i;
351 	ByteString aOption( rName );
352 	for( i = 0; i < mnOptions; i++ )
353 	{
354 		if( mppOptions[i]->name && aOption.Equals( mppOptions[i]->name ) )
355 			return i;
356 	}
357 	return -1;
358 }
359 
GetOptionValue(int n,sal_Bool & rRet)360 sal_Bool Sane::GetOptionValue( int n, sal_Bool& rRet )
361 {
362 	if( ! maHandle  ||  mppOptions[n]->type != SANE_TYPE_BOOL )
363 		return sal_False;
364 	SANE_Word nRet;
365 	SANE_Status nStatus = ControlOption( n, SANE_ACTION_GET_VALUE, &nRet );
366 	if( nStatus != SANE_STATUS_GOOD )
367 		return sal_False;
368 
369 	rRet = nRet;
370 	return sal_True;
371 }
372 
GetOptionValue(int n,ByteString & rRet)373 sal_Bool Sane::GetOptionValue( int n, ByteString& rRet )
374 {
375 	sal_Bool bSuccess = sal_False;
376 	if( ! maHandle  ||  mppOptions[n]->type != SANE_TYPE_STRING )
377 		return sal_False;
378 	char* pRet = new char[mppOptions[n]->size+1];
379 	SANE_Status nStatus = ControlOption( n, SANE_ACTION_GET_VALUE, pRet );
380 	if( nStatus == SANE_STATUS_GOOD )
381 	{
382 		bSuccess = sal_True;
383 		rRet = pRet;
384 	}
385 	delete [] pRet;
386 	return bSuccess;
387 }
388 
GetOptionValue(int n,double & rRet,int nElement)389 sal_Bool Sane::GetOptionValue( int n, double& rRet, int nElement )
390 {
391 	sal_Bool bSuccess = sal_False;
392 
393 	if( ! maHandle  ||  ( mppOptions[n]->type != SANE_TYPE_INT &&
394 						  mppOptions[n]->type != SANE_TYPE_FIXED ) )
395 		return sal_False;
396 
397 	SANE_Word* pRet = new SANE_Word[mppOptions[n]->size/sizeof(SANE_Word)];
398 	SANE_Status nStatus = ControlOption( n, SANE_ACTION_GET_VALUE, pRet );
399 	if( nStatus == SANE_STATUS_GOOD )
400 	{
401 		bSuccess = sal_True;
402 		if( mppOptions[n]->type == SANE_TYPE_INT )
403 			rRet = (double)pRet[ nElement ];
404 		else
405 			rRet = SANE_UNFIX( pRet[nElement] );
406 	}
407 	delete [] pRet;
408 	return bSuccess;
409 }
410 
GetOptionValue(int n,double * pSet)411 sal_Bool Sane::GetOptionValue( int n, double* pSet )
412 {
413 	if( ! maHandle  || ! ( mppOptions[n]->type == SANE_TYPE_FIXED ||
414 						   mppOptions[n]->type == SANE_TYPE_INT ) )
415 		return sal_False;
416 
417 	SANE_Word* pFixedSet = new SANE_Word[mppOptions[n]->size/sizeof(SANE_Word)];
418 	SANE_Status nStatus = ControlOption( n, SANE_ACTION_GET_VALUE, pFixedSet );
419 	if( nStatus != SANE_STATUS_GOOD )
420 	{
421 		delete [] pFixedSet;
422 		return sal_False;
423 	}
424 	for( size_t i = 0; i <mppOptions[n]->size/sizeof(SANE_Word); i++ )
425 	{
426 		if( mppOptions[n]->type == SANE_TYPE_FIXED )
427 			pSet[i] = SANE_UNFIX( pFixedSet[i] );
428 		else
429 			pSet[i] = (double) pFixedSet[i];
430 	}
431 	delete [] pFixedSet;
432 	return sal_True;
433 }
434 
SetOptionValue(int n,sal_Bool bSet)435 sal_Bool Sane::SetOptionValue( int n, sal_Bool bSet )
436 {
437 	if( ! maHandle  ||  mppOptions[n]->type != SANE_TYPE_BOOL )
438 		return sal_False;
439 	SANE_Word nRet = bSet ? SANE_TRUE : SANE_FALSE;
440 	SANE_Status nStatus = ControlOption( n, SANE_ACTION_SET_VALUE, &nRet );
441 	if( nStatus != SANE_STATUS_GOOD )
442 		return sal_False;
443 	return sal_True;
444 }
445 
SetOptionValue(int n,const String & rSet)446 sal_Bool Sane::SetOptionValue( int n, const String& rSet )
447 {
448 	if( ! maHandle  ||  mppOptions[n]->type != SANE_TYPE_STRING )
449 		return sal_False;
450 	ByteString aSet( rSet, gsl_getSystemTextEncoding() );
451 	SANE_Status nStatus = ControlOption( n, SANE_ACTION_SET_VALUE, (void*)aSet.GetBuffer() );
452 	if( nStatus != SANE_STATUS_GOOD )
453 		return sal_False;
454 	return sal_True;
455 }
456 
SetOptionValue(int n,double fSet,int nElement)457 sal_Bool Sane::SetOptionValue( int n, double fSet, int nElement )
458 {
459 	sal_Bool bSuccess = sal_False;
460 
461 	if( ! maHandle  ||  ( mppOptions[n]->type != SANE_TYPE_INT &&
462 						  mppOptions[n]->type != SANE_TYPE_FIXED ) )
463 		return sal_False;
464 
465 	SANE_Status nStatus;
466 	if( mppOptions[n]->size/sizeof(SANE_Word) > 1 )
467 	{
468 		SANE_Word* pSet = new SANE_Word[mppOptions[n]->size/sizeof(SANE_Word)];
469 		nStatus = ControlOption( n, SANE_ACTION_GET_VALUE, pSet );
470 		if( nStatus == SANE_STATUS_GOOD )
471 		{
472 			pSet[nElement] = mppOptions[n]->type == SANE_TYPE_INT ?
473 				(SANE_Word)fSet : SANE_FIX( fSet );
474 			nStatus = ControlOption(  n, SANE_ACTION_SET_VALUE, pSet );
475 		}
476 		delete [] pSet;
477 	}
478 	else
479 	{
480 		SANE_Word nSetTo =
481 			mppOptions[n]->type == SANE_TYPE_INT ?
482 			(SANE_Word)fSet : SANE_FIX( fSet );
483 
484 		nStatus = ControlOption( n, SANE_ACTION_SET_VALUE, &nSetTo );
485 		if( nStatus == SANE_STATUS_GOOD )
486 			bSuccess = sal_True;
487 	}
488 	return bSuccess;
489 }
490 
SetOptionValue(int n,double * pSet)491 sal_Bool Sane::SetOptionValue( int n, double* pSet )
492 {
493 	if( ! maHandle  ||  ( mppOptions[n]->type != SANE_TYPE_INT &&
494 						  mppOptions[n]->type != SANE_TYPE_FIXED ) )
495 		return sal_False;
496 	SANE_Word* pFixedSet = new SANE_Word[mppOptions[n]->size/sizeof(SANE_Word)];
497 	for( size_t i = 0; i < mppOptions[n]->size/sizeof(SANE_Word); i++ )
498 	{
499 		if( mppOptions[n]->type == SANE_TYPE_FIXED )
500 			pFixedSet[i] = SANE_FIX( pSet[i] );
501 		else
502 			pFixedSet[i] = (SANE_Word)pSet[i];
503 	}
504 	SANE_Status nStatus = ControlOption( n, SANE_ACTION_SET_VALUE, pFixedSet );
505 	delete [] pFixedSet;
506 	if( nStatus != SANE_STATUS_GOOD )
507 		return sal_False;
508 	return sal_True;
509 }
510 
511 enum FrameStyleType {
512 	FrameStyle_BW, FrameStyle_Gray, FrameStyle_RGB, FrameStyle_Separated
513 };
514 
515 #define BYTE_BUFFER_SIZE 32768
516 
_ReadValue(FILE * fp,int depth)517 static inline sal_uInt8 _ReadValue( FILE* fp, int depth )
518 {
519 	if( depth == 16 )
520 	{
521 		sal_uInt16 nWord;
522 		// data always come in native byte order !
523 		// 16 bits is not really supported by backends as of now
524 		// e.g. UMAX Astra 1200S delivers 16 bit but in BIGENDIAN
525 		// against SANE documentation (xscanimage gets the same result
526 		// as we do
527 		fread( &nWord, 1, 2, fp );
528 		return (sal_uInt8)( nWord / 256 );
529 	}
530 	sal_uInt8 nByte;
531 	fread( &nByte, 1, 1, fp );
532 	return nByte;
533 }
534 
CheckConsistency(const char * pMes,sal_Bool bInit)535 sal_Bool Sane::CheckConsistency( const char* pMes, sal_Bool bInit )
536 {
537 	static SANE_Option_Descriptor** pDescArray = NULL;
538 	static SANE_Option_Descriptor*  pZero = NULL;
539 
540 	if( bInit )
541 	{
542 		pDescArray = (SANE_Option_Descriptor**)mppOptions;
543 		if( mppOptions )
544 			pZero = (SANE_Option_Descriptor*)mppOptions[0];
545 		return sal_True;
546 	}
547 
548 	sal_Bool bConsistent = sal_True;
549 
550 	if( pDescArray != mppOptions )
551 		bConsistent = sal_False;
552 	if( pZero != mppOptions[0] )
553 		bConsistent = sal_False;
554 
555 	if( ! bConsistent )
556 		dbg_msg( "Sane is not consistent. (%s)\n", pMes );
557 
558 	return bConsistent;
559 }
560 
Start(BitmapTransporter & rBitmap)561 sal_Bool Sane::Start( BitmapTransporter& rBitmap )
562 {
563 	int nStream = 0, nLine = 0, i = 0;
564 	SANE_Parameters	aParams;
565 	FrameStyleType eType = FrameStyle_Gray;
566 	sal_Bool bSuccess = sal_True;
567 	sal_Bool bWidthSet = sal_False;
568 
569 	if( ! maHandle )
570 		return sal_False;
571 
572     int nWidthMM	= 0;
573     int nHeightMM	= 0;
574     double fTLx, fTLy, fBRx, fBRy, fResl = 0.0;
575     int nOption;
576     if( ( nOption = GetOptionByName( "tl-x" ) ) != -1	&&
577         GetOptionValue( nOption, fTLx, 0 )				&&
578         GetOptionUnit( nOption ) == SANE_UNIT_MM )
579     {
580         if( ( nOption = GetOptionByName( "br-x" ) ) != -1	&&
581             GetOptionValue( nOption, fBRx, 0 )				&&
582             GetOptionUnit( nOption ) == SANE_UNIT_MM )
583         {
584             nWidthMM = (int)fabs(fBRx - fTLx);
585         }
586     }
587     if( ( nOption = GetOptionByName( "tl-y" ) ) != -1	&&
588         GetOptionValue( nOption, fTLy, 0 )				&&
589         GetOptionUnit( nOption ) == SANE_UNIT_MM )
590     {
591         if( ( nOption = GetOptionByName( "br-y" ) ) != -1	&&
592             GetOptionValue( nOption, fBRy, 0 )				&&
593             GetOptionUnit( nOption ) == SANE_UNIT_MM )
594         {
595             nHeightMM = (int)fabs(fBRy - fTLy);
596         }
597     }
598     if( ( nOption = GetOptionByName( "resolution" ) ) != -1 )
599         GetOptionValue( nOption, fResl );
600 
601 	sal_uInt8* pBuffer = NULL;
602 
603 	SANE_Status nStatus = SANE_STATUS_GOOD;
604 
605 	rBitmap.lock();
606 	SvMemoryStream& aConverter = rBitmap.getStream();
607 	aConverter.Seek( 0 );
608 	aConverter.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
609 
610 	// write bitmap stream header
611 	aConverter << 'B' << 'M';
612 	aConverter << (sal_uInt32) 0;
613 	aConverter << (sal_uInt32) 0;
614 	aConverter << (sal_uInt32) 60;
615 
616 	// write BITMAPINFOHEADER
617 	aConverter << (sal_uInt32)40;
618 	aConverter << (sal_uInt32)0; // fill in width later
619 	aConverter << (sal_uInt32)0; // fill in height later
620 	aConverter << (sal_uInt16)1;
621 	// create header for 24 bits
622 	// correct later if necessary
623 	aConverter << (sal_uInt16)24;
624 	aConverter << (sal_uInt32)0;
625 	aConverter << (sal_uInt32)0;
626 	aConverter << (sal_uInt32)0;
627 	aConverter << (sal_uInt32)0;
628 	aConverter << (sal_uInt32)0;
629 	aConverter << (sal_uInt32)0;
630 
631 	for( nStream=0; nStream < 3 && bSuccess ; nStream++ )
632 	{
633 		nStatus = p_start( maHandle );
634 		DUMP_STATE( nStatus, "sane_start" );
635 		CheckConsistency( "sane_start" );
636 		if( nStatus == SANE_STATUS_GOOD )
637 		{
638 			nStatus = p_get_parameters( maHandle, &aParams );
639 			DUMP_STATE( nStatus, "sane_get_parameters" );
640 			CheckConsistency( "sane_get_parameters" );
641 			if (nStatus != SANE_STATUS_GOOD || aParams.bytes_per_line == 0)
642 			{
643 				bSuccess = sal_False;
644 			    break;
645 			}
646 #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
647 			const char* ppFormats[] = { "SANE_FRAME_GRAY", "SANE_FRAME_RGB",
648 								  "SANE_FRAME_RED", "SANE_FRAME_GREEN",
649 								  "SANE_FRAME_BLUE", "Unknown !!!" };
650 			fprintf( stderr, "Parameters for frame %d:\n", nStream );
651 			if( aParams.format < 0 || aParams.format > 4 )
652 				aParams.format = (SANE_Frame)5;
653 			fprintf( stderr, "format:           %s\n", ppFormats[ (int)aParams.format ] );
654 			fprintf( stderr, "last_frame:       %s\n", aParams.last_frame ? "TRUE" : "FALSE" );
655 			fprintf( stderr, "depth:            %d\n", (int)aParams.depth );
656 			fprintf( stderr, "pixels_per_line:  %d\n", (int)aParams.pixels_per_line );
657 			fprintf( stderr, "bytes_per_line:   %d\n", (int)aParams.bytes_per_line );
658 #endif
659 			if( ! pBuffer )
660 			{
661 				pBuffer = new sal_uInt8[ BYTE_BUFFER_SIZE < 4*aParams.bytes_per_line ? 4*aParams.bytes_per_line : BYTE_BUFFER_SIZE ];
662 			}
663 
664 			if( aParams.last_frame )
665 				nStream=3;
666 
667 			switch( aParams.format )
668 			{
669 				case SANE_FRAME_GRAY:
670 					eType = FrameStyle_Gray;
671 					if( aParams.depth == 1 )
672 						eType = FrameStyle_BW;
673 					break;
674 				case SANE_FRAME_RGB:
675 					eType = FrameStyle_RGB;
676 					break;
677 				case SANE_FRAME_RED:
678 				case SANE_FRAME_GREEN:
679 				case SANE_FRAME_BLUE:
680 					eType = FrameStyle_Separated;
681 					break;
682 				default:
683 					fprintf( stderr, "Warning: unknown frame style !!!\n" );
684 			}
685 
686 			sal_Bool bSynchronousRead = sal_True;
687 
688 			// should be fail safe, but ... ??
689 			nStatus = p_set_io_mode( maHandle, SANE_FALSE );
690 			CheckConsistency( "sane_set_io_mode" );
691 			if( nStatus != SANE_STATUS_GOOD )
692 			{
693 				bSynchronousRead = sal_False;
694 				nStatus = p_set_io_mode( maHandle, SANE_TRUE );
695 				CheckConsistency( "sane_set_io_mode" );
696 #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
697 				if( nStatus != SANE_STATUS_GOOD )
698 					// what ?!?
699 					fprintf( stderr, "Sane::Start: driver is confused\n" );
700 #endif
701 			}
702 
703 			SANE_Int nLen=0;
704 			SANE_Int fd = 0;
705 
706 			if( ! bSynchronousRead )
707 			{
708 				nStatus = p_get_select_fd( maHandle, &fd );
709 				DUMP_STATE( nStatus, "sane_get_select_fd" );
710 				CheckConsistency( "sane_get_select_fd" );
711 				if( nStatus != SANE_STATUS_GOOD )
712 					bSynchronousRead = sal_True;
713 			}
714 			FILE* pFrame = tmpfile();
715 			if( ! pFrame )
716 			{
717 				bSuccess = sal_False;
718 				break;
719 			}
720 			do {
721 				if( ! bSynchronousRead )
722 				{
723 					fd_set fdset;
724 					struct timeval tv;
725 
726 					FD_ZERO( &fdset );
727 					FD_SET( (int)fd, &fdset );
728 					tv.tv_sec = 5;
729 					tv.tv_usec = 0;
730 					if( select( fd+1, &fdset, NULL, NULL, &tv ) == 0 )
731 						fprintf( stderr, "Timout on sane_read descriptor\n" );
732 				}
733 				nLen = 0;
734 				nStatus = p_read( maHandle, pBuffer, BYTE_BUFFER_SIZE, &nLen );
735 				CheckConsistency( "sane_read" );
736 				if( nLen && ( nStatus == SANE_STATUS_GOOD ||
737 							  nStatus == SANE_STATUS_EOF ) )
738 				{
739 					fwrite( pBuffer, 1, nLen, pFrame );
740 				}
741 				else
742 					DUMP_STATE( nStatus, "sane_read" );
743 			} while( nStatus == SANE_STATUS_GOOD );
744 			if( nStatus != SANE_STATUS_EOF )
745 			{
746 				fclose( pFrame );
747 				bSuccess = sal_False;
748 				break;
749 			}
750 
751 			int nFrameLength = ftell( pFrame );
752 			fseek( pFrame, 0, SEEK_SET );
753 			sal_uInt32 nWidth = (sal_uInt32) aParams.pixels_per_line;
754 			sal_uInt32 nHeight = (sal_uInt32) (nFrameLength / aParams.bytes_per_line);
755 			if( ! bWidthSet )
756 			{
757                 if( ! fResl )
758                     fResl = 300; // if all else fails that's a good guess
759                 if( ! nWidthMM )
760                     nWidthMM = (int)(((double)nWidth / fResl) * 25.4);
761                 if( ! nHeightMM )
762                     nHeightMM = (int)(((double)nHeight / fResl) * 25.4);
763 #if OSL_DEBUG_LEVEL > 1
764 				fprintf( stderr, "set dimensions to (%d, %d) Pixel, (%d, %d) mm, resolution is %lg\n", (int)nWidth, (int)nHeight, (int)nWidthMM, (int)nHeightMM, fResl );
765 #endif
766 
767 				aConverter.Seek( 18 );
768 				aConverter << (sal_uInt32)nWidth;
769 				aConverter << (sal_uInt32)nHeight;
770                 aConverter.Seek( 38 );
771                 aConverter << (sal_uInt32)(1000*nWidth/nWidthMM);
772                 aConverter << (sal_uInt32)(1000*nHeight/nHeightMM);
773 				bWidthSet = sal_True;
774 			}
775 			aConverter.Seek(60);
776 
777 			if( eType == FrameStyle_BW )
778 			{
779 				aConverter.Seek( 10 );
780 				aConverter << (sal_uInt32)64;
781 				aConverter.Seek( 28 );
782 				aConverter << (sal_uInt16) 1;
783 				aConverter.Seek( 54 );
784 				// write color table
785 				aConverter << (sal_uInt16)0xffff;
786 				aConverter << (sal_uInt8)0xff;
787 				aConverter << (sal_uInt8)0;
788 				aConverter << (sal_uInt32)0;
789 				aConverter.Seek( 64 );
790 			}
791 			else if( eType == FrameStyle_Gray )
792 			{
793  				aConverter.Seek( 10 );
794  				aConverter << (sal_uInt32)1084;
795 				aConverter.Seek( 28 );
796 				aConverter << (sal_uInt16) 8;
797 				aConverter.Seek( 54 );
798 				// write color table
799 				for( nLine = 0; nLine < 256; nLine++ )
800 				{
801 					aConverter << (sal_uInt8)nLine;
802 					aConverter << (sal_uInt8)nLine;
803 					aConverter << (sal_uInt8)nLine;
804 					aConverter << (sal_uInt8)0;
805 				}
806 				aConverter.Seek( 1084 );
807 			}
808 
809 			for( nLine = nHeight-1;
810 				 nLine >= 0; nLine-- )
811 			{
812 				fseek( pFrame, nLine * aParams.bytes_per_line, SEEK_SET );
813 				if( eType == FrameStyle_BW ||
814 					( eType == FrameStyle_Gray && aParams.depth == 8 )
815 					)
816 				{
817 					fread( pBuffer, 1, aParams.bytes_per_line, pFrame );
818 					aConverter.Write( pBuffer, aParams.bytes_per_line );
819 				}
820 				else if( eType == FrameStyle_Gray )
821 				{
822 					for( i = 0; i < (aParams.pixels_per_line); i++ )
823 					{
824 						sal_uInt8 nGray = _ReadValue( pFrame, aParams.depth );
825 						aConverter << nGray;
826 					}
827 				}
828 				else if( eType == FrameStyle_RGB )
829 				{
830 					for( i = 0; i < (aParams.pixels_per_line); i++ )
831 					{
832 						sal_uInt8 nRed, nGreen, nBlue;
833 						nRed	= _ReadValue( pFrame, aParams.depth );
834 						nGreen	= _ReadValue( pFrame, aParams.depth );
835 						nBlue	= _ReadValue( pFrame, aParams.depth );
836 						aConverter << nBlue;
837 						aConverter << nGreen;
838 						aConverter << nRed;
839 					}
840 				}
841 				else if( eType == FrameStyle_Separated )
842 				{
843 					for( i = 0; i < (aParams.pixels_per_line); i++ )
844 					{
845 						sal_uInt8 nValue = _ReadValue( pFrame, aParams.depth );
846 						switch( aParams.format )
847 						{
848 							case SANE_FRAME_RED:
849 								aConverter.SeekRel( 2 );
850 								aConverter << nValue;
851 								break;
852 							case SANE_FRAME_GREEN:
853 								aConverter.SeekRel( 1 );
854 								aConverter << nValue;
855 								aConverter.SeekRel( 1 );
856 								break;
857 							case SANE_FRAME_BLUE:
858 								aConverter << nValue;
859 								aConverter.SeekRel( 2 );
860 								break;
861                             case SANE_FRAME_GRAY:
862                             case SANE_FRAME_RGB:
863                                 break;
864 						}
865 					}
866 				}
867  				int nGap = aConverter.Tell() & 3;
868  				if( nGap )
869  					aConverter.SeekRel( 4-nGap );
870 			}
871 			fclose( pFrame ); // deletes tmpfile
872 			if( eType != FrameStyle_Separated )
873 				break;
874 		}
875 		else
876 			bSuccess = sal_False;
877 	}
878 	// get stream length
879 	aConverter.Seek( STREAM_SEEK_TO_END );
880 	int nPos = aConverter.Tell();
881 
882 	aConverter.Seek( 2 );
883 	aConverter << (sal_uInt32) nPos+1;
884 	aConverter.Seek( 0 );
885 
886 	rBitmap.unlock();
887 
888 	if( bSuccess )
889 	{
890 		// only cancel a successful operation
891 		// sane disrupts memory else
892 		p_cancel( maHandle );
893 		CheckConsistency( "sane_cancel" );
894 	}
895 	if( pBuffer )
896 		delete [] pBuffer;
897 
898 	ReloadOptions();
899 
900 
901 	dbg_msg( "Sane::Start returns with %s\n", bSuccess ? "TRUE" : "FALSE" );
902 
903 	return bSuccess;
904 }
905 
GetRange(int n,double * & rpDouble)906 int Sane::GetRange( int n, double*& rpDouble )
907 {
908 	if( mppOptions[n]->constraint_type != SANE_CONSTRAINT_RANGE &&
909 		mppOptions[n]->constraint_type != SANE_CONSTRAINT_WORD_LIST )
910 	{
911 		return -1;
912 	}
913 
914 	rpDouble = 0;
915 	int nItems, i;
916 	sal_Bool bIsFixed = mppOptions[n]->type == SANE_TYPE_FIXED ? sal_True : sal_False;
917 
918 	dbg_msg( "Sane::GetRange of option %s ", mppOptions[n]->name );
919 	if(mppOptions[n]->constraint_type == SANE_CONSTRAINT_RANGE )
920 	{
921 		double fMin, fMax, fQuant;
922 		if( bIsFixed )
923 		{
924 			fMin = SANE_UNFIX( mppOptions[n]->constraint.range->min );
925 			fMax = SANE_UNFIX( mppOptions[n]->constraint.range->max );
926 			fQuant = SANE_UNFIX( mppOptions[n]->constraint.range->quant );
927 		}
928 		else
929 		{
930 			fMin = (double)mppOptions[n]->constraint.range->min;
931 			fMax = (double)mppOptions[n]->constraint.range->max;
932 			fQuant = (double)mppOptions[n]->constraint.range->quant;
933 		}
934 		if( fQuant != 0.0 )
935 		{
936 			dbg_msg( "quantum range [ %lg ; %lg ; %lg ]\n",
937 					 fMin, fQuant, fMax );
938 			nItems = (int)((fMax - fMin)/fQuant)+1;
939 			rpDouble = new double[ nItems ];
940 			double fValue = fMin;
941 			for( i = 0; i < nItems; i++, fValue += fQuant )
942 				rpDouble[i] = fValue;
943 			rpDouble[ nItems-1 ] = fMax;
944 			return nItems;
945 		}
946 		else
947 		{
948 			dbg_msg( "normal range [ %lg %lg ]\n",
949 					 fMin, fMax );
950 			rpDouble = new double[2];
951 			rpDouble[0] = fMin;
952 			rpDouble[1] = fMax;
953 			return 0;
954 		}
955 	}
956 	else
957 	{
958 		nItems = mppOptions[n]->constraint.word_list[0];
959 		rpDouble = new double[nItems];
960 		for( i=0; i<nItems; i++ )
961 		{
962 			rpDouble[i] = bIsFixed ?
963 				SANE_UNFIX( mppOptions[n]->constraint.word_list[i+1] ) :
964 				(double)mppOptions[n]->constraint.word_list[i+1];
965 		}
966 		dbg_msg( "wordlist [ %lg ... %lg ]\n",
967 				 rpDouble[ 0 ], rpDouble[ nItems-1 ] );
968 		return nItems;
969 	}
970 }
971 
972 static const char *ppUnits[] = {
973 	"",
974 	"[Pixel]",
975 	"[Bit]",
976 	"[mm]",
977 	"[DPI]",
978 	"[%]",
979 	"[usec]"
980 };
981 
GetOptionUnitName(int n)982 String Sane::GetOptionUnitName( int n )
983 {
984 	String aText;
985 	SANE_Unit nUnit = mppOptions[n]->unit;
986     size_t nUnitAsSize = (size_t)nUnit;
987     if (nUnitAsSize >= sizeof(ppUnits)/sizeof(ppUnits[0]))
988 		aText = String::CreateFromAscii( "[unknown units]" );
989 	else
990 		aText = String( ppUnits[ nUnit ], gsl_getSystemTextEncoding() );
991 	return aText;
992 }
993 
ActivateButtonOption(int n)994 sal_Bool Sane::ActivateButtonOption( int n )
995 {
996 	SANE_Status nStatus = ControlOption( n, SANE_ACTION_SET_VALUE, NULL );
997 	if( nStatus != SANE_STATUS_GOOD )
998 		return sal_False;
999 	return sal_True;
1000 }
1001