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