merged tag ooo/OOO330_m14
[LibreOffice.git] / extensions / source / scanner / sanedlg.cxx
blob2889257a1f1c259782b36778782baa5b51a1d3bd
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
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.
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).
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.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_extensions.hxx"
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <tools/config.hxx>
35 #include <vcl/msgbox.hxx>
36 #include <sanedlg.hxx>
37 #include <sanedlg.hrc>
38 #include <grid.hxx>
39 #include <math.h>
41 #define USE_SAVE_STATE
42 #undef SAVE_ALL_STATES
44 ResId SaneResId( sal_uInt32 nID )
46 static ResMgr* pResMgr = ResMgr::CreateResMgr( "san" );
47 return ResId( nID, *pResMgr );
50 SaneDlg::SaneDlg( Window* pParent, Sane& rSane ) :
51 ModalDialog( pParent, SaneResId( RID_SANE_DIALOG ) ),
52 mrSane( rSane ),
53 mbIsDragging( FALSE ),
54 mbDragDrawn( FALSE ),
55 maMapMode( MAP_APPFONT ),
56 maOKButton( this, SaneResId( RID_SCAN_OK ) ),
57 maCancelButton( this, SaneResId( RID_SCAN_CANCEL ) ),
58 maDeviceInfoButton( this, SaneResId( RID_DEVICEINFO_BTN ) ),
59 maPreviewButton( this, SaneResId( RID_PREVIEW_BTN ) ),
60 maButtonOption( this, SaneResId( RID_SCAN_BUTTON_OPTION_BTN ) ),
61 maOptionsTxt( this, SaneResId( RID_SCAN_OPTION_TXT ) ),
62 maOptionTitle( this, SaneResId( RID_SCAN_OPTIONTITLE_TXT ) ),
63 maOptionDescTxt( this, SaneResId( RID_SCAN_OPTION_DESC_TXT ) ),
64 maVectorTxt( this, SaneResId( RID_SCAN_NUMERIC_VECTOR_TXT ) ),
65 maScanLeftTxt( this, SaneResId( RID_SCAN_LEFT_TXT ) ),
66 maLeftField( this, SaneResId( RID_SCAN_LEFT_BOX ) ),
67 maScanTopTxt( this, SaneResId( RID_SCAN_TOP_TXT ) ),
68 maTopField( this, SaneResId( RID_SCAN_TOP_BOX ) ),
69 maRightTxt( this, SaneResId( RID_SCAN_RIGHT_TXT ) ),
70 maRightField( this, SaneResId( RID_SCAN_RIGHT_BOX ) ),
71 maBottomTxt( this, SaneResId( RID_SCAN_BOTTOM_TXT ) ),
72 maBottomField( this, SaneResId( RID_SCAN_BOTTOM_BOX ) ),
73 maDeviceBoxTxt( this, SaneResId( RID_DEVICE_BOX_TXT ) ),
74 maDeviceBox( this, SaneResId( RID_DEVICE_BOX ) ),
75 maReslTxt( this, SaneResId( RID_SCAN_RESOLUTION_TXT ) ),
76 maReslBox( this, SaneResId( RID_SCAN_RESOLUTION_BOX ) ),
77 maAdvancedTxt( this, SaneResId( RID_SCAN_ADVANCED_TXT ) ),
78 maAdvancedBox( this, SaneResId( RID_SCAN_ADVANCED_BOX ) ),
79 maVectorBox( this, SaneResId( RID_SCAN_NUMERIC_VECTOR_BOX ) ),
80 maQuantumRangeBox( this, SaneResId( RID_SCAN_QUANTUM_RANGE_BOX ) ),
81 maStringRangeBox( this, SaneResId( RID_SCAN_STRING_RANGE_BOX ) ),
82 maPreviewBox( this, SaneResId( RID_PREVIEW_BOX ) ),
83 maAreaBox( this, SaneResId( RID_SCANAREA_BOX ) ),
84 maBoolCheckBox( this, SaneResId( RID_SCAN_BOOL_OPTION_BOX ) ),
85 maStringEdit( this, SaneResId( RID_SCAN_STRING_OPTION_EDT ) ),
86 maNumericEdit( this, SaneResId( RID_SCAN_NUMERIC_OPTION_EDT ) ),
87 maOptionBox( this, SaneResId( RID_SCAN_OPTION_BOX ) ),
88 mpRange( 0 )
90 if( Sane::IsSane() )
92 InitDevices(); // opens first sane device
93 DisableOption();
94 InitFields();
97 maDeviceInfoButton.SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) );
98 maPreviewButton.SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) );
99 maButtonOption.SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) );
100 maDeviceBox.SetSelectHdl( LINK( this, SaneDlg, SelectHdl ) );
101 maOptionBox.SetSelectHdl( LINK( this, SaneDlg, OptionsBoxSelectHdl ) );
102 maOKButton.SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) );
103 maCancelButton.SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) );
104 maBoolCheckBox.SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) );
105 maStringEdit.SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) );
106 maNumericEdit.SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) );
107 maVectorBox.SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) );
108 maReslBox.SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) );
109 maStringRangeBox.SetSelectHdl( LINK( this, SaneDlg, SelectHdl ) );
110 maQuantumRangeBox.SetSelectHdl( LINK( this, SaneDlg, SelectHdl ) );
111 maLeftField.SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) );
112 maRightField.SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) );
113 maTopField.SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) );
114 maBottomField.SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) );
115 maAdvancedBox.SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) );
117 maOldLink = mrSane.SetReloadOptionsHdl( LINK( this, SaneDlg, ReloadSaneOptionsHdl ) );
119 maOptionBox.SetNodeBitmaps(
120 Bitmap( SaneResId( RID_SCAN_BITMAP_PLUS ) ),
121 Bitmap( SaneResId( RID_SCAN_BITMAP_MINUS ) )
123 maOptionBox.SetWindowBits( WB_HASLINES |
124 WB_HASBUTTONS |
125 WB_NOINITIALSELECTION |
126 WB_HASBUTTONSATROOT |
127 WB_HASLINESATROOT
129 FreeResource();
132 SaneDlg::~SaneDlg()
136 short SaneDlg::Execute()
138 if( ! Sane::IsSane() )
140 ErrorBox aErrorBox( NULL, WB_OK | WB_DEF_OK,
141 String( SaneResId( RID_SANE_NOSANELIB_TXT ) ) );
142 aErrorBox.Execute();
143 return FALSE;
145 LoadState();
146 return ModalDialog::Execute();
149 void SaneDlg::InitDevices()
151 if( ! Sane::IsSane() )
152 return;
154 if( mrSane.IsOpen() )
155 mrSane.Close();
156 mrSane.ReloadDevices();
157 maDeviceBox.Clear();
158 for( int i = 0; i < Sane::CountDevices(); i++ )
159 maDeviceBox.InsertEntry( Sane::GetName( i ) );
160 if( Sane::CountDevices() )
162 mrSane.Open( 0 );
163 maDeviceBox.SelectEntry( Sane::GetName( 0 ) );
168 void SaneDlg::InitFields()
170 if( ! Sane::IsSane() )
171 return;
173 int nOption, i, nValue;
174 double fValue;
175 BOOL bSuccess = FALSE;
176 const char *ppSpecialOptions[] = {
177 "resolution",
178 "tl-x",
179 "tl-y",
180 "br-x",
181 "br-y",
182 "preview"
185 mbDragEnable = TRUE;
186 maReslBox.Clear();
187 maMinTopLeft = Point( 0, 0 );
188 maMaxBottomRight = Point( PREVIEW_WIDTH, PREVIEW_HEIGHT );
190 if( ! mrSane.IsOpen() )
191 return;
193 // set Resolution
194 nOption = mrSane.GetOptionByName( "resolution" );
195 if( nOption != -1 )
197 double fRes;
199 bSuccess = mrSane.GetOptionValue( nOption, fRes );
200 if( bSuccess )
202 maReslBox.Enable( TRUE );
204 maReslBox.SetValue( (long)fRes );
205 double *pDouble = NULL;
206 nValue = mrSane.GetRange( nOption, pDouble );
207 if( nValue > -1 )
209 if( nValue )
211 maReslBox.SetMin( (long)pDouble[0] );
212 maReslBox.SetMax( (long)pDouble[ nValue-1 ] );
213 for( i=0; i<nValue; i++ )
215 if( i == 0 || i == nValue-1 || ! ( ((int)pDouble[i]) % 20) )
216 maReslBox.InsertValue( (long)pDouble[i] );
219 else
221 maReslBox.SetMin( (long)pDouble[0] );
222 maReslBox.SetMax( (long)pDouble[1] );
223 maReslBox.InsertValue( (long)pDouble[0] );
224 // mh@openoffice.org: issue 68557: Can only select 75 and 2400 dpi in Scanner dialogue
225 // scanner allows random setting of dpi resolution, a slider might be useful
226 // support that
227 // workaround: offer at least some more standard dpi resolution between
228 // min and max value
229 int bGot300 = 0;
230 for ( int nRes = (long) pDouble[0] * 2; nRes < (long) pDouble[1]; nRes = nRes * 2 )
232 if ( !bGot300 && nRes > 300 ) {
233 nRes = 300; bGot300 = 1;
235 maReslBox.InsertValue(nRes);
237 maReslBox.InsertValue( (long)pDouble[1] );
239 if( pDouble )
240 delete [] pDouble;
242 else
243 maReslBox.Enable( FALSE );
246 else
247 maReslBox.Enable( FALSE );
249 // set scan area
250 for( i = 0; i < 4; i++ )
252 char const *pOptionName = NULL;
253 MetricField* pField = NULL;
254 switch( i )
256 case 0:
257 pOptionName = "tl-x";
258 pField = &maLeftField;
259 break;
260 case 1:
261 pOptionName = "tl-y";
262 pField = &maTopField;
263 break;
264 case 2:
265 pOptionName = "br-x";
266 pField = &maRightField;
267 break;
268 case 3:
269 pOptionName = "br-y";
270 pField = &maBottomField;
272 nOption = pOptionName ? mrSane.GetOptionByName( pOptionName ) : -1;
273 bSuccess = FALSE;
274 if( nOption != -1 )
276 bSuccess = mrSane.GetOptionValue( nOption, fValue, 0 );
277 if( bSuccess )
279 if( mrSane.GetOptionUnit( nOption ) == SANE_UNIT_MM )
281 pField->SetUnit( FUNIT_MM );
282 pField->SetValue( (int)fValue, FUNIT_MM );
284 else // SANE_UNIT_PIXEL
286 pField->SetValue( (int)fValue, FUNIT_CUSTOM );
287 pField->SetCustomUnitText( String::CreateFromAscii( "Pixel" ) );
289 switch( i ) {
290 case 0: maTopLeft.X() = (int)fValue;break;
291 case 1: maTopLeft.Y() = (int)fValue;break;
292 case 2: maBottomRight.X() = (int)fValue;break;
293 case 3: maBottomRight.Y() = (int)fValue;break;
296 double *pDouble = NULL;
297 nValue = mrSane.GetRange( nOption, pDouble );
298 if( nValue > -1 )
300 if( pDouble )
302 pField->SetMin( (long)pDouble[0] );
303 if( nValue )
304 pField->SetMax( (long)pDouble[ nValue-1 ] );
305 else
306 pField->SetMax( (long)pDouble[ 1 ] );
307 delete [] pDouble;
309 switch( i ) {
310 case 0: maMinTopLeft.X() = pField->GetMin();break;
311 case 1: maMinTopLeft.Y() = pField->GetMin();break;
312 case 2: maMaxBottomRight.X() = pField->GetMax();break;
313 case 3: maMaxBottomRight.Y() = pField->GetMax();break;
316 else
318 switch( i ) {
319 case 0: maMinTopLeft.X() = (int)fValue;break;
320 case 1: maMinTopLeft.Y() = (int)fValue;break;
321 case 2: maMaxBottomRight.X() = (int)fValue;break;
322 case 3: maMaxBottomRight.Y() = (int)fValue;break;
325 pField->Enable( TRUE );
327 else
329 mbDragEnable = FALSE;
330 pField->SetMin( 0 );
331 switch( i ) {
332 case 0:
333 maMinTopLeft.X() = 0;
334 maTopLeft.X() = 0;
335 pField->SetMax( PREVIEW_WIDTH );
336 pField->SetValue( 0 );
337 break;
338 case 1:
339 maMinTopLeft.Y() = 0;
340 maTopLeft.Y() = 0;
341 pField->SetMax( PREVIEW_HEIGHT );
342 pField->SetValue( 0 );
343 break;
344 case 2:
345 maMaxBottomRight.X() = PREVIEW_WIDTH;
346 maBottomRight.X() = PREVIEW_WIDTH;
347 pField->SetMax( PREVIEW_WIDTH );
348 pField->SetValue( PREVIEW_WIDTH );
349 break;
350 case 3:
351 maMaxBottomRight.Y() = PREVIEW_HEIGHT;
352 maBottomRight.Y() = PREVIEW_HEIGHT;
353 pField->SetMax( PREVIEW_HEIGHT );
354 pField->SetValue( PREVIEW_HEIGHT );
355 break;
357 pField->Enable( FALSE );
360 maTopLeft = GetPixelPos( maTopLeft );
361 maBottomRight = GetPixelPos( maBottomRight );
362 maPreviewRect = Rectangle( maTopLeft,
363 Size( maBottomRight.X() - maTopLeft.X(),
364 maBottomRight.Y() - maTopLeft.Y() )
366 // fill OptionBox
367 maOptionBox.Clear();
368 SvLBoxEntry* pParentEntry = 0;
369 BOOL bGroupRejected = FALSE;
370 for( i = 1; i < mrSane.CountOptions(); i++ )
372 String aOption=mrSane.GetOptionName( i );
373 BOOL bInsertAdvanced =
374 mrSane.GetOptionCap( i ) & SANE_CAP_ADVANCED &&
375 ! maAdvancedBox.IsChecked() ? FALSE : TRUE;
376 if( mrSane.GetOptionType( i ) == SANE_TYPE_GROUP )
378 if( bInsertAdvanced )
380 aOption = mrSane.GetOptionTitle( i );
381 pParentEntry = maOptionBox.InsertEntry( aOption );
382 bGroupRejected = FALSE;
384 else
385 bGroupRejected = TRUE;
387 else if( aOption.Len() &&
388 ! ( mrSane.GetOptionCap( i ) &
390 SANE_CAP_HARD_SELECT |
391 SANE_CAP_INACTIVE
392 ) ) &&
393 bInsertAdvanced && ! bGroupRejected )
395 BOOL bIsSpecial = FALSE;
396 for( size_t n = 0; !bIsSpecial &&
397 n < sizeof(ppSpecialOptions)/sizeof(ppSpecialOptions[0]); n++ )
399 if( aOption.EqualsAscii( ppSpecialOptions[n] ) )
400 bIsSpecial=TRUE;
402 if( ! bIsSpecial )
404 if( pParentEntry )
405 maOptionBox.InsertEntry( aOption, pParentEntry );
406 else
407 maOptionBox.InsertEntry( aOption );
413 IMPL_LINK( SaneDlg, ClickBtnHdl, Button*, pButton )
415 if( mrSane.IsOpen() )
417 if( pButton == &maDeviceInfoButton )
419 String aString( SaneResId( RID_SANE_DEVICEINFO_TXT ) );
420 String aSR( RTL_CONSTASCII_USTRINGPARAM( "%s" ) );
421 aString.SearchAndReplace( aSR, Sane::GetName( mrSane.GetDeviceNumber() ) );
422 aString.SearchAndReplace( aSR, Sane::GetVendor( mrSane.GetDeviceNumber() ) );
423 aString.SearchAndReplace( aSR, Sane::GetModel( mrSane.GetDeviceNumber() ) );
424 aString.SearchAndReplace( aSR, Sane::GetType( mrSane.GetDeviceNumber() ) );
425 InfoBox aInfoBox( this, aString );
426 aInfoBox.Execute();
428 else if( pButton == &maPreviewButton )
429 AcquirePreview();
430 else if( pButton == &maBoolCheckBox )
432 mrSane.SetOptionValue( mnCurrentOption,
433 maBoolCheckBox.IsChecked() ?
434 (BOOL)TRUE : (BOOL)FALSE );
436 else if( pButton == &maButtonOption )
439 SANE_Value_Type nType = mrSane.GetOptionType( mnCurrentOption );
440 switch( nType )
442 case SANE_TYPE_BUTTON:
443 mrSane.ActivateButtonOption( mnCurrentOption );
444 break;
445 case SANE_TYPE_FIXED:
446 case SANE_TYPE_INT:
448 int nElements = mrSane.GetOptionElements( mnCurrentOption );
449 double* x = new double[ nElements ];
450 double* y = new double[ nElements ];
451 for( int i = 0; i < nElements; i++ )
452 x[ i ] = (double)i;
453 mrSane.GetOptionValue( mnCurrentOption, y );
455 GridWindow aGrid( x, y, nElements, this );
456 aGrid.SetText( mrSane.GetOptionName( mnCurrentOption ) );
457 aGrid.setBoundings( 0, mfMin, nElements, mfMax );
458 if( aGrid.Execute() && aGrid.getNewYValues() )
459 mrSane.SetOptionValue( mnCurrentOption, aGrid.getNewYValues() );
461 delete [] x;
462 delete [] y;
464 break;
465 case SANE_TYPE_BOOL:
466 case SANE_TYPE_STRING:
467 case SANE_TYPE_GROUP:
468 break;
471 else if( pButton == &maAdvancedBox )
473 ReloadSaneOptionsHdl( NULL );
476 if( pButton == &maOKButton )
478 double fRes = (double)maReslBox.GetValue();
479 SetAdjustedNumericalValue( "resolution", fRes );
480 mrSane.SetReloadOptionsHdl( maOldLink );
481 UpdateScanArea( TRUE );
482 SaveState();
483 EndDialog( mrSane.IsOpen() ? 1 : 0 );
485 else if( pButton == &maCancelButton )
487 mrSane.SetReloadOptionsHdl( maOldLink );
488 mrSane.Close();
489 EndDialog( 0 );
491 return 0;
494 IMPL_LINK( SaneDlg, SelectHdl, ListBox*, pListBox )
496 if( pListBox == &maDeviceBox && Sane::IsSane() && Sane::CountDevices() )
498 String aNewDevice = maDeviceBox.GetSelectEntry();
499 int nNumber;
500 if( aNewDevice.Equals( Sane::GetName( nNumber = mrSane.GetDeviceNumber() ) ) )
502 mrSane.Close();
503 mrSane.Open( nNumber );
504 InitFields();
507 if( mrSane.IsOpen() )
509 if( pListBox == &maQuantumRangeBox )
511 ByteString aValue( maQuantumRangeBox.GetSelectEntry(), osl_getThreadTextEncoding() );
512 double fValue = atof( aValue.GetBuffer() );
513 mrSane.SetOptionValue( mnCurrentOption, fValue, mnCurrentElement );
515 else if( pListBox == &maStringRangeBox )
517 mrSane.SetOptionValue( mnCurrentOption, maStringRangeBox.GetSelectEntry() );
520 return 0;
523 IMPL_LINK( SaneDlg, OptionsBoxSelectHdl, SvTreeListBox*, pBox )
525 if( pBox == &maOptionBox && Sane::IsSane() )
527 String aOption =
528 maOptionBox.GetEntryText( maOptionBox.FirstSelected() );
529 int nOption = mrSane.GetOptionByName( ByteString( aOption, osl_getThreadTextEncoding() ).GetBuffer() );
530 if( nOption != -1 && nOption != mnCurrentOption )
532 DisableOption();
533 mnCurrentOption = nOption;
534 maOptionTitle.SetText( mrSane.GetOptionTitle( mnCurrentOption ) );
535 SANE_Value_Type nType = mrSane.GetOptionType( mnCurrentOption );
536 SANE_Constraint_Type nConstraint;
537 switch( nType )
539 case SANE_TYPE_BOOL: EstablishBoolOption();break;
540 case SANE_TYPE_STRING:
541 nConstraint = mrSane.GetOptionConstraintType( mnCurrentOption );
542 if( nConstraint == SANE_CONSTRAINT_STRING_LIST )
543 EstablishStringRange();
544 else
545 EstablishStringOption();
546 break;
547 case SANE_TYPE_FIXED:
548 case SANE_TYPE_INT:
550 nConstraint = mrSane.GetOptionConstraintType( mnCurrentOption );
551 int nElements = mrSane.GetOptionElements( mnCurrentOption );
552 mnCurrentElement = 0;
553 if( nConstraint == SANE_CONSTRAINT_RANGE ||
554 nConstraint == SANE_CONSTRAINT_WORD_LIST )
555 EstablishQuantumRange();
556 else
558 mfMin = mfMax = 0.0;
559 EstablishNumericOption();
561 if( nElements > 1 )
563 if( nElements <= 10 )
565 maVectorBox.SetValue( 1 );
566 maVectorBox.SetMin( 1 );
567 maVectorBox.SetMax(
568 mrSane.GetOptionElements( mnCurrentOption ) );
569 maVectorBox.Show( TRUE );
570 maVectorTxt.Show( TRUE );
572 else
574 DisableOption();
575 // bring up dialog only on button click
576 EstablishButtonOption();
580 break;
581 case SANE_TYPE_BUTTON:
582 EstablishButtonOption();
583 break;
584 default: break;
588 return 0;
591 IMPL_LINK( SaneDlg, ModifyHdl, Edit*, pEdit )
593 if( mrSane.IsOpen() )
595 if( pEdit == &maStringEdit )
597 mrSane.SetOptionValue( mnCurrentOption, maStringEdit.GetText() );
599 else if( pEdit == &maReslBox )
601 double fRes = (double)maReslBox.GetValue();
602 int nOption = mrSane.GetOptionByName( "resolution" );
603 if( nOption != -1 )
605 double* pDouble = NULL;
606 int nValues = mrSane.GetRange( nOption, pDouble );
607 if( nValues > 0 )
609 int i;
610 for( i = 0; i < nValues; i++ )
612 if( fRes == pDouble[i] )
613 break;
615 if( i >= nValues )
616 fRes = pDouble[0];
618 else if( nValues == 0 )
620 if( fRes < pDouble[ 0 ] )
621 fRes = pDouble[ 0 ];
622 if( fRes > pDouble[ 1 ] )
623 fRes = pDouble[ 1 ];
625 maReslBox.SetValue( (ULONG)fRes );
628 else if( pEdit == &maNumericEdit )
630 double fValue;
631 char pBuf[256];
632 ByteString aContents( maNumericEdit.GetText(), osl_getThreadTextEncoding() );
633 fValue = atof( aContents.GetBuffer() );
634 if( mfMin != mfMax && ( fValue < mfMin || fValue > mfMax ) )
636 if( fValue < mfMin )
637 fValue = mfMin;
638 else if( fValue > mfMax )
639 fValue = mfMax;
640 sprintf( pBuf, "%g", fValue );
641 maNumericEdit.SetText( String( pBuf, osl_getThreadTextEncoding() ) );
643 mrSane.SetOptionValue( mnCurrentOption, fValue, mnCurrentElement );
645 else if( pEdit == &maVectorBox )
647 char pBuf[256];
648 mnCurrentElement = maVectorBox.GetValue()-1;
649 double fValue;
650 mrSane.GetOptionValue( mnCurrentOption, fValue, mnCurrentElement );
651 sprintf( pBuf, "%g", fValue );
652 String aValue( pBuf, osl_getThreadTextEncoding() );
653 maNumericEdit.SetText( aValue );
654 maQuantumRangeBox.SelectEntry( aValue );
656 else if( pEdit == &maTopField )
658 Point aPoint( 0, maTopField.GetValue() );
659 aPoint = GetPixelPos( aPoint );
660 maTopLeft.Y() = aPoint.Y();
661 DrawDrag();
663 else if( pEdit == &maLeftField )
665 Point aPoint( maLeftField.GetValue(), 0 );
666 aPoint = GetPixelPos( aPoint );
667 maTopLeft.X() = aPoint.X();
668 DrawDrag();
670 else if( pEdit == &maBottomField )
672 Point aPoint( 0, maBottomField.GetValue() );
673 aPoint = GetPixelPos( aPoint );
674 maBottomRight.Y() = aPoint.Y();
675 DrawDrag();
677 else if( pEdit == &maRightField )
679 Point aPoint( maRightField.GetValue(), 0 );
680 aPoint = GetPixelPos( aPoint );
681 maBottomRight.X() = aPoint.X();
682 DrawDrag();
685 return 0;
688 IMPL_LINK( SaneDlg, ReloadSaneOptionsHdl, Sane*, /*pSane*/ )
690 mnCurrentOption = -1;
691 mnCurrentElement = 0;
692 DisableOption();
693 // #92024# preserve preview rect, should only be set
694 // initially or in AcquirePreview
695 Rectangle aPreviewRect = maPreviewRect;
696 InitFields();
697 maPreviewRect = aPreviewRect;
698 Rectangle aDummyRect( Point( 0, 0 ), GetSizePixel() );
699 Paint( aDummyRect );
700 return 0;
703 void SaneDlg::AcquirePreview()
705 if( ! mrSane.IsOpen() )
706 return;
708 UpdateScanArea( TRUE );
709 // set small resolution for preview
710 double fResl = (double)maReslBox.GetValue();
711 SetAdjustedNumericalValue( "resolution", 30.0 );
713 int nOption = mrSane.GetOptionByName( "preview" );
714 if( nOption == -1 )
716 String aString( SaneResId( RID_SANE_NORESOLUTIONOPTION_TXT ) );
717 WarningBox aBox( this, WB_OK_CANCEL | WB_DEF_OK, aString );
718 if( aBox.Execute() == RET_CANCEL )
719 return;
721 else
722 mrSane.SetOptionValue( nOption, (BOOL)TRUE );
724 BitmapTransporter aTransporter;
725 if( ! mrSane.Start( aTransporter ) )
727 ErrorBox aErrorBox( this, WB_OK | WB_DEF_OK,
728 String( SaneResId( RID_SANE_SCANERROR_TXT ) ) );
729 aErrorBox.Execute();
731 else
733 #if OSL_DEBUG_LEVEL > 1
734 aTransporter.getStream().Seek( STREAM_SEEK_TO_END );
735 fprintf( stderr, "Previewbitmapstream contains %d bytes\n", (int)aTransporter.getStream().Tell() );
736 #endif
737 aTransporter.getStream().Seek( STREAM_SEEK_TO_BEGIN );
738 maPreviewBitmap.Read( aTransporter.getStream(), TRUE );
741 SetAdjustedNumericalValue( "resolution", fResl );
742 maReslBox.SetValue( (ULONG)fResl );
744 if( mbDragEnable )
745 maPreviewRect = Rectangle( maTopLeft,
746 Size( maBottomRight.X() - maTopLeft.X(),
747 maBottomRight.Y() - maTopLeft.Y() )
749 else
751 Size aBMSize( maPreviewBitmap.GetSizePixel() );
752 if( aBMSize.Width() > aBMSize.Height() )
754 int nVHeight = (maBottomRight.X() - maTopLeft.X()) * aBMSize.Height() / aBMSize.Width();
755 maPreviewRect = Rectangle( Point( maTopLeft.X(), ( maTopLeft.Y() + maBottomRight.Y() )/2 - nVHeight/2 ),
756 Size( maBottomRight.X() - maTopLeft.X(),
757 nVHeight ) );
759 else
761 int nVWidth = (maBottomRight.Y() - maTopLeft.Y()) * aBMSize.Width() / aBMSize.Height();
762 maPreviewRect = Rectangle( Point( ( maTopLeft.X() + maBottomRight.X() )/2 - nVWidth/2, maTopLeft.Y() ),
763 Size( nVWidth,
764 maBottomRight.Y() - maTopLeft.Y() ) );
768 Paint( Rectangle( Point( 0, 0 ), GetSizePixel() ) );
771 void SaneDlg::Paint( const Rectangle& rRect )
773 SetMapMode( maMapMode );
774 SetFillColor( Color( COL_WHITE ) );
775 SetLineColor( Color( COL_WHITE ) );
776 DrawRect( Rectangle( Point( PREVIEW_UPPER_LEFT, PREVIEW_UPPER_TOP ),
777 Size( PREVIEW_WIDTH, PREVIEW_HEIGHT ) ) );
778 SetMapMode( MapMode( MAP_PIXEL ) );
779 // check for sane values
780 DrawBitmap( maPreviewRect.TopLeft(), maPreviewRect.GetSize(),
781 maPreviewBitmap );
783 mbDragDrawn = FALSE;
784 DrawDrag();
786 ModalDialog::Paint( rRect );
789 void SaneDlg::DisableOption()
791 maBoolCheckBox.Show( FALSE );
792 maStringEdit.Show( FALSE );
793 maNumericEdit.Show( FALSE );
794 maQuantumRangeBox.Show( FALSE );
795 maStringRangeBox.Show( FALSE );
796 maButtonOption.Show( FALSE );
797 maVectorBox.Show( FALSE );
798 maVectorTxt.Show( FALSE );
799 maOptionDescTxt.Show( FALSE );
802 void SaneDlg::EstablishBoolOption()
804 BOOL bSuccess, bValue;
806 bSuccess = mrSane.GetOptionValue( mnCurrentOption, bValue );
807 if( bSuccess )
809 maOptionDescTxt.SetText( mrSane.GetOptionName( mnCurrentOption ) );
810 maOptionDescTxt.Show( TRUE );
811 maBoolCheckBox.Check( bValue );
812 maBoolCheckBox.Show( TRUE );
816 void SaneDlg::EstablishStringOption()
818 BOOL bSuccess;
819 ByteString aValue;
821 bSuccess = mrSane.GetOptionValue( mnCurrentOption, aValue );
822 if( bSuccess )
824 maOptionDescTxt.SetText( mrSane.GetOptionName( mnCurrentOption ) );
825 maOptionDescTxt.Show( TRUE );
826 maStringEdit.SetText( String( aValue, osl_getThreadTextEncoding() ) );
827 maStringEdit.Show( TRUE );
831 void SaneDlg::EstablishStringRange()
833 const char** ppStrings = mrSane.GetStringConstraint( mnCurrentOption );
834 maStringRangeBox.Clear();
835 for( int i = 0; ppStrings[i] != 0; i++ )
836 maStringRangeBox.InsertEntry( String( ppStrings[i], osl_getThreadTextEncoding() ) );
837 ByteString aValue;
838 mrSane.GetOptionValue( mnCurrentOption, aValue );
839 maStringRangeBox.SelectEntry( String( aValue, osl_getThreadTextEncoding() ) );
840 maStringRangeBox.Show( TRUE );
841 maOptionDescTxt.SetText( mrSane.GetOptionName( mnCurrentOption ) );
842 maOptionDescTxt.Show( TRUE );
845 void SaneDlg::EstablishQuantumRange()
847 if( mpRange )
849 delete [] mpRange;
850 mpRange = 0;
852 int nValues = mrSane.GetRange( mnCurrentOption, mpRange );
853 if( nValues == 0 )
855 mfMin = mpRange[ 0 ];
856 mfMax = mpRange[ 1 ];
857 delete [] mpRange;
858 mpRange = 0;
859 EstablishNumericOption();
861 else if( nValues > 0 )
863 char pBuf[ 256 ];
864 maQuantumRangeBox.Clear();
865 mfMin = mpRange[ 0 ];
866 mfMax = mpRange[ nValues-1 ];
867 for( int i = 0; i < nValues; i++ )
869 sprintf( pBuf, "%g", mpRange[ i ] );
870 maQuantumRangeBox.InsertEntry( String( pBuf, osl_getThreadTextEncoding() ) );
872 double fValue;
873 if( mrSane.GetOptionValue( mnCurrentOption, fValue, mnCurrentElement ) )
875 sprintf( pBuf, "%g", fValue );
876 maQuantumRangeBox.SelectEntry( String( pBuf, osl_getThreadTextEncoding() ) );
878 maQuantumRangeBox.Show( TRUE );
879 String aText( mrSane.GetOptionName( mnCurrentOption ) );
880 aText += ' ';
881 aText += mrSane.GetOptionUnitName( mnCurrentOption );
882 maOptionDescTxt.SetText( aText );
883 maOptionDescTxt.Show( TRUE );
887 void SaneDlg::EstablishNumericOption()
889 BOOL bSuccess;
890 double fValue;
892 bSuccess = mrSane.GetOptionValue( mnCurrentOption, fValue );
893 if( ! bSuccess )
894 return;
896 char pBuf[256];
897 String aText( mrSane.GetOptionName( mnCurrentOption ) );
898 aText += ' ';
899 aText += mrSane.GetOptionUnitName( mnCurrentOption );
900 if( mfMin != mfMax )
902 sprintf( pBuf, " < %g ; %g >", mfMin, mfMax );
903 aText += String( pBuf, osl_getThreadTextEncoding() );
905 maOptionDescTxt.SetText( aText );
906 maOptionDescTxt.Show( TRUE );
907 sprintf( pBuf, "%g", fValue );
908 maNumericEdit.SetText( String( pBuf, osl_getThreadTextEncoding() ) );
909 maNumericEdit.Show( TRUE );
912 void SaneDlg::EstablishButtonOption()
914 maOptionDescTxt.SetText( mrSane.GetOptionName( mnCurrentOption ) );
915 maOptionDescTxt.Show( TRUE );
916 maButtonOption.Show( TRUE );
919 #define RECT_SIZE_PIX 7
921 void SaneDlg::MouseMove( const MouseEvent& rMEvt )
923 if( mbIsDragging )
925 Point aMousePos = rMEvt.GetPosPixel();
926 // move into valid area
927 Point aLogicPos = GetLogicPos( aMousePos );
928 aMousePos = GetPixelPos( aLogicPos );
929 switch( meDragDirection )
931 case TopLeft: maTopLeft = aMousePos; break;
932 case Top: maTopLeft.Y() = aMousePos.Y(); break;
933 case TopRight:
934 maTopLeft.Y() = aMousePos.Y();
935 maBottomRight.X() = aMousePos.X();
936 break;
937 case Right: maBottomRight.X() = aMousePos.X(); break;
938 case BottomRight: maBottomRight = aMousePos; break;
939 case Bottom: maBottomRight.Y() = aMousePos.Y(); break;
940 case BottomLeft:
941 maTopLeft.X() = aMousePos.X();
942 maBottomRight.Y() = aMousePos.Y();
943 break;
944 case Left: maTopLeft.X() = aMousePos.X(); break;
945 default: break;
947 int nSwap;
948 if( maTopLeft.X() > maBottomRight.X() )
950 nSwap = maTopLeft.X();
951 maTopLeft.X() = maBottomRight.X();
952 maBottomRight.X() = nSwap;
954 if( maTopLeft.Y() > maBottomRight.Y() )
956 nSwap = maTopLeft.Y();
957 maTopLeft.Y() = maBottomRight.Y();
958 maBottomRight.Y() = nSwap;
960 DrawDrag();
961 UpdateScanArea( FALSE );
963 ModalDialog::MouseMove( rMEvt );
966 void SaneDlg::MouseButtonDown( const MouseEvent& rMEvt )
968 Point aMousePixel = rMEvt.GetPosPixel();
970 if( ! mbIsDragging && mbDragEnable )
972 int nMiddleX = ( maBottomRight.X() - maTopLeft.X() ) / 2 - RECT_SIZE_PIX/2 + maTopLeft.X();
973 int nMiddleY = ( maBottomRight.Y() - maTopLeft.Y() ) / 2 - RECT_SIZE_PIX/2 + maTopLeft.Y();
974 if( aMousePixel.Y() >= maTopLeft.Y() &&
975 aMousePixel.Y() < maTopLeft.Y() + RECT_SIZE_PIX )
977 if( aMousePixel.X() >= maTopLeft.X() &&
978 aMousePixel.X() < maTopLeft.X() + RECT_SIZE_PIX )
980 meDragDirection = TopLeft;
981 aMousePixel = maTopLeft;
982 mbIsDragging = TRUE;
984 else if( aMousePixel.X() >= nMiddleX &&
985 aMousePixel.X() < nMiddleX + RECT_SIZE_PIX )
987 meDragDirection = Top;
988 aMousePixel.Y() = maTopLeft.Y();
989 mbIsDragging = TRUE;
991 else if( aMousePixel.X() > maBottomRight.X() - RECT_SIZE_PIX &&
992 aMousePixel.X() <= maBottomRight.X() )
994 meDragDirection = TopRight;
995 aMousePixel = Point( maBottomRight.X(), maTopLeft.Y() );
996 mbIsDragging = TRUE;
999 else if( aMousePixel.Y() >= nMiddleY &&
1000 aMousePixel.Y() < nMiddleY + RECT_SIZE_PIX )
1002 if( aMousePixel.X() >= maTopLeft.X() &&
1003 aMousePixel.X() < maTopLeft.X() + RECT_SIZE_PIX )
1005 meDragDirection = Left;
1006 aMousePixel.X() = maTopLeft.X();
1007 mbIsDragging = TRUE;
1009 else if( aMousePixel.X() > maBottomRight.X() - RECT_SIZE_PIX &&
1010 aMousePixel.X() <= maBottomRight.X() )
1012 meDragDirection = Right;
1013 aMousePixel.X() = maBottomRight.X();
1014 mbIsDragging = TRUE;
1017 else if( aMousePixel.Y() <= maBottomRight.Y() &&
1018 aMousePixel.Y() > maBottomRight.Y() - RECT_SIZE_PIX )
1020 if( aMousePixel.X() >= maTopLeft.X() &&
1021 aMousePixel.X() < maTopLeft.X() + RECT_SIZE_PIX )
1023 meDragDirection = BottomLeft;
1024 aMousePixel = Point( maTopLeft.X(), maBottomRight.Y() );
1025 mbIsDragging = TRUE;
1027 else if( aMousePixel.X() >= nMiddleX &&
1028 aMousePixel.X() < nMiddleX + RECT_SIZE_PIX )
1030 meDragDirection = Bottom;
1031 aMousePixel.Y() = maBottomRight.Y();
1032 mbIsDragging = TRUE;
1034 else if( aMousePixel.X() > maBottomRight.X() - RECT_SIZE_PIX &&
1035 aMousePixel.X() <= maBottomRight.X() )
1037 meDragDirection = BottomRight;
1038 aMousePixel = maBottomRight;
1039 mbIsDragging = TRUE;
1043 if( mbIsDragging )
1045 SetPointerPosPixel( aMousePixel );
1046 DrawDrag();
1048 ModalDialog::MouseButtonDown( rMEvt );
1051 void SaneDlg::MouseButtonUp( const MouseEvent& rMEvt )
1053 if( mbIsDragging )
1055 UpdateScanArea( TRUE );
1057 mbIsDragging = FALSE;
1059 ModalDialog::MouseButtonUp( rMEvt );
1062 void SaneDlg::DrawRectangles( Point& rUL, Point& rBR )
1064 int nMiddleX, nMiddleY;
1065 Point aBL, aUR;
1067 aUR = Point( rBR.X(), rUL.Y() );
1068 aBL = Point( rUL.X(), rBR.Y() );
1069 nMiddleX = ( rBR.X() - rUL.X() ) / 2 + rUL.X();
1070 nMiddleY = ( rBR.Y() - rUL.Y() ) / 2 + rUL.Y();
1072 DrawLine( rUL, aBL );
1073 DrawLine( aBL, rBR );
1074 DrawLine( rBR, aUR );
1075 DrawLine( aUR, rUL );
1076 DrawRect( Rectangle( rUL, Size( RECT_SIZE_PIX,RECT_SIZE_PIX ) ) );
1077 DrawRect( Rectangle( aBL, Size( RECT_SIZE_PIX, -RECT_SIZE_PIX ) ) );
1078 DrawRect( Rectangle( rBR, Size( -RECT_SIZE_PIX, -RECT_SIZE_PIX ) ) );
1079 DrawRect( Rectangle( aUR, Size( -RECT_SIZE_PIX, RECT_SIZE_PIX ) ) );
1080 DrawRect( Rectangle( Point( nMiddleX - RECT_SIZE_PIX/2, rUL.Y() ), Size( RECT_SIZE_PIX, RECT_SIZE_PIX ) ) );
1081 DrawRect( Rectangle( Point( nMiddleX - RECT_SIZE_PIX/2, rBR.Y() ), Size( RECT_SIZE_PIX, -RECT_SIZE_PIX ) ) );
1082 DrawRect( Rectangle( Point( rUL.X(), nMiddleY - RECT_SIZE_PIX/2 ), Size( RECT_SIZE_PIX, RECT_SIZE_PIX ) ) );
1083 DrawRect( Rectangle( Point( rBR.X(), nMiddleY - RECT_SIZE_PIX/2 ), Size( -RECT_SIZE_PIX, RECT_SIZE_PIX ) ) );
1086 void SaneDlg::DrawDrag()
1088 static Point aLastUL, aLastBR;
1090 if( ! mbDragEnable )
1091 return;
1093 RasterOp eROP = GetRasterOp();
1094 SetRasterOp( ROP_INVERT );
1095 SetMapMode( MapMode( MAP_PIXEL ) );
1097 if( mbDragDrawn )
1098 DrawRectangles( aLastUL, aLastBR );
1100 aLastUL = maTopLeft;
1101 aLastBR = maBottomRight;
1102 DrawRectangles( maTopLeft, maBottomRight );
1104 mbDragDrawn = TRUE;
1105 SetRasterOp( eROP );
1106 SetMapMode( maMapMode );
1109 Point SaneDlg::GetPixelPos( const Point& rIn )
1111 Point aConvert(
1112 ( ( rIn.X() * PREVIEW_WIDTH ) /
1113 ( maMaxBottomRight.X() - maMinTopLeft.X() ) )
1114 + PREVIEW_UPPER_LEFT,
1115 ( ( rIn.Y() * PREVIEW_HEIGHT )
1116 / ( maMaxBottomRight.Y() - maMinTopLeft.Y() ) )
1117 + PREVIEW_UPPER_TOP );
1119 return LogicToPixel( aConvert, maMapMode );
1122 Point SaneDlg::GetLogicPos( const Point& rIn )
1124 Point aConvert = PixelToLogic( rIn, maMapMode );
1125 aConvert.X() -= PREVIEW_UPPER_LEFT;
1126 aConvert.Y() -= PREVIEW_UPPER_TOP;
1127 if( aConvert.X() < 0 )
1128 aConvert.X() = 0;
1129 if( aConvert.X() >= PREVIEW_WIDTH )
1130 aConvert.X() = PREVIEW_WIDTH-1;
1131 if( aConvert.Y() < 0 )
1132 aConvert.Y() = 0;
1133 if( aConvert.Y() >= PREVIEW_HEIGHT )
1134 aConvert.Y() = PREVIEW_HEIGHT-1;
1136 aConvert.X() *= ( maMaxBottomRight.X() - maMinTopLeft.X() );
1137 aConvert.X() /= PREVIEW_WIDTH;
1138 aConvert.Y() *= ( maMaxBottomRight.Y() - maMinTopLeft.Y() );
1139 aConvert.Y() /= PREVIEW_HEIGHT;
1140 return aConvert;
1143 void SaneDlg::UpdateScanArea( BOOL bSend )
1145 if( ! mbDragEnable )
1146 return;
1148 Point aUL = GetLogicPos( maTopLeft );
1149 Point aBR = GetLogicPos( maBottomRight );
1151 maLeftField.SetValue( aUL.X() );
1152 maTopField.SetValue( aUL.Y() );
1153 maRightField.SetValue( aBR.X() );
1154 maBottomField.SetValue( aBR.Y() );
1156 if( ! bSend )
1157 return;
1159 if( mrSane.IsOpen() )
1161 SetAdjustedNumericalValue( "tl-x", (double)aUL.X() );
1162 SetAdjustedNumericalValue( "tl-y", (double)aUL.Y() );
1163 SetAdjustedNumericalValue( "br-x", (double)aBR.X() );
1164 SetAdjustedNumericalValue( "br-y", (double)aBR.Y() );
1168 BOOL SaneDlg::LoadState()
1170 #ifdef USE_SAVE_STATE
1171 int i;
1173 if( ! Sane::IsSane() )
1174 return FALSE;
1176 const char* pEnv = getenv("HOME");
1177 String aFileName( pEnv ? pEnv : "", osl_getThreadTextEncoding() );
1178 aFileName += String( RTL_CONSTASCII_USTRINGPARAM( "/.so_sane_state" ) );
1179 Config aConfig( aFileName );
1180 if( ! aConfig.HasGroup( "SANE" ) )
1181 return FALSE;
1183 aConfig.SetGroup( "SANE" );
1184 ByteString aString = aConfig.ReadKey( "SO_LastSaneDevice" );
1185 for( i = 0; i < Sane::CountDevices() && ! aString.Equals( ByteString( Sane::GetName( i ), osl_getThreadTextEncoding() ) ); i++ ) ;
1186 if( i == Sane::CountDevices() )
1187 return FALSE;
1189 mrSane.Close();
1190 mrSane.Open( aString.GetBuffer() );
1192 DisableOption();
1193 InitFields();
1195 if( mrSane.IsOpen() )
1197 int iMax = aConfig.GetKeyCount();
1198 for( i = 0; i < iMax; i++ )
1200 aString = aConfig.GetKeyName( i );
1201 ByteString aValue = aConfig.ReadKey( i );
1202 int nOption = mrSane.GetOptionByName( aString.GetBuffer() );
1203 if( nOption != -1 )
1205 if( aValue.CompareTo( "BOOL=", 5 ) == COMPARE_EQUAL )
1207 aValue.Erase( 0, 5 );
1208 BOOL aBOOL = (BOOL)aValue.ToInt32();
1209 mrSane.SetOptionValue( nOption, aBOOL );
1211 else if( aValue.CompareTo( "STRING=", 7 ) == COMPARE_EQUAL )
1213 aValue.Erase( 0, 7 );
1214 mrSane.SetOptionValue( nOption, String( aValue, osl_getThreadTextEncoding() ) );
1216 else if( aValue.CompareTo( "NUMERIC=", 8 ) == COMPARE_EQUAL )
1218 aValue.Erase( 0, 8 );
1219 int nMax = aValue.GetTokenCount( ':' );
1220 double fValue=0.0;
1221 for( int n = 0; n < nMax ; n++ )
1223 ByteString aSub = aValue.GetToken( n, ':' );
1224 sscanf( aSub.GetBuffer(), "%lg", &fValue );
1225 SetAdjustedNumericalValue( aString.GetBuffer(), fValue, n );
1232 DisableOption();
1233 InitFields();
1235 return TRUE;
1236 #else
1237 return FALSE;
1238 #endif
1241 void SaneDlg::SaveState()
1243 #ifdef USE_SAVE_STATE
1244 if( ! Sane::IsSane() )
1245 return;
1247 const char* pEnv = getenv( "HOME" );
1248 String aFileName( pEnv ? pEnv : "", osl_getThreadTextEncoding() );
1249 aFileName.AppendAscii( "/.so_sane_state" );
1251 Config aConfig( aFileName );
1252 aConfig.DeleteGroup( "SANE" );
1253 aConfig.SetGroup( "SANE" );
1254 aConfig.WriteKey( "SO_LastSANEDevice", ByteString( maDeviceBox.GetSelectEntry(), RTL_TEXTENCODING_UTF8 ) );
1256 #ifdef SAVE_ALL_STATES
1257 for( int i = 1; i < mrSane.CountOptions(); i++ )
1259 String aOption=mrSane.GetOptionName( i );
1260 SANE_Value_Type nType = mrSane.GetOptionType( i );
1261 switch( nType )
1263 case SANE_TYPE_BOOL:
1265 BOOL bValue;
1266 if( mrSane.GetOptionValue( i, bValue ) )
1268 ByteString aString( "BOOL=" );
1269 aString += (ULONG)bValue;
1270 aConfig.WriteKey( aOption, aString );
1273 break;
1274 case SANE_TYPE_STRING:
1276 String aString( "STRING=" );
1277 String aValue;
1278 if( mrSane.GetOptionValue( i, aValue ) )
1280 aString += aValue;
1281 aConfig.WriteKey( aOption, aString );
1284 break;
1285 case SANE_TYPE_FIXED:
1286 case SANE_TYPE_INT:
1288 String aString( "NUMERIC=" );
1289 double fValue;
1290 char buf[256];
1291 for( int n = 0; n < mrSane.GetOptionElements( i ); n++ )
1293 if( ! mrSane.GetOptionValue( i, fValue, n ) )
1294 break;
1295 if( n > 0 )
1296 aString += ":";
1297 sprintf( buf, "%lg", fValue );
1298 aString += buf;
1300 if( n >= mrSane.GetOptionElements( i ) )
1301 aConfig.WriteKey( aOption, aString );
1303 break;
1304 default:
1305 break;
1308 #else
1309 static char const* pSaveOptions[] = {
1310 "resolution",
1311 "tl-x",
1312 "tl-y",
1313 "br-x",
1314 "br-y"
1316 for( size_t i = 0;
1317 i < (sizeof(pSaveOptions)/sizeof(pSaveOptions[0]));
1318 i++ )
1320 ByteString aOption = pSaveOptions[i];
1321 int nOption = mrSane.GetOptionByName( pSaveOptions[i] );
1322 if( nOption > -1 )
1324 SANE_Value_Type nType = mrSane.GetOptionType( nOption );
1325 switch( nType )
1327 case SANE_TYPE_BOOL:
1329 BOOL bValue;
1330 if( mrSane.GetOptionValue( nOption, bValue ) )
1332 ByteString aString( "BOOL=" );
1333 aString += ByteString::CreateFromInt32(bValue);
1334 aConfig.WriteKey( aOption, aString );
1337 break;
1338 case SANE_TYPE_STRING:
1340 ByteString aString( "STRING=" );
1341 ByteString aValue;
1342 if( mrSane.GetOptionValue( nOption, aValue ) )
1344 aString += aValue;
1345 aConfig.WriteKey( aOption, aString );
1348 break;
1349 case SANE_TYPE_FIXED:
1350 case SANE_TYPE_INT:
1352 ByteString aString( "NUMERIC=" );
1353 double fValue;
1354 char buf[256];
1355 int n;
1357 for( n = 0; n < mrSane.GetOptionElements( nOption ); n++ )
1359 if( ! mrSane.GetOptionValue( nOption, fValue, n ) )
1360 break;
1361 if( n > 0 )
1362 aString += ":";
1363 sprintf( buf, "%lg", fValue );
1364 aString += buf;
1366 if( n >= mrSane.GetOptionElements( nOption ) )
1367 aConfig.WriteKey( aOption, aString );
1369 break;
1370 default:
1371 break;
1375 #endif
1376 #endif
1379 BOOL SaneDlg::SetAdjustedNumericalValue(
1380 const char* pOption,
1381 double fValue,
1382 int nElement )
1384 int nOption;
1385 if( ! Sane::IsSane() || ! mrSane.IsOpen() || ( nOption = mrSane.GetOptionByName( pOption ) ) == -1 )
1386 return FALSE;
1388 if( nElement < 0 || nElement >= mrSane.GetOptionElements( nOption ) )
1389 return FALSE;
1391 double* pValues = NULL;
1392 int nValues;
1393 if( ( nValues = mrSane.GetRange( nOption, pValues ) ) < 0 )
1394 return FALSE;
1396 #if OSL_DEBUG_LEVEL > 1
1397 fprintf( stderr, "SaneDlg::SetAdjustedNumericalValue( \"%s\", %lg ) ",
1398 pOption, fValue );
1399 #endif
1401 if( nValues )
1403 int nNearest = 0;
1404 double fNearest = 1e6;
1405 for( int i = 0; i < nValues; i++ )
1407 if( fabs( fValue - pValues[ i ] ) < fNearest )
1409 fNearest = fabs( fValue - pValues[ i ] );
1410 nNearest = i;
1413 fValue = pValues[ nNearest ];
1415 else
1417 if( fValue < pValues[0] )
1418 fValue = pValues[0];
1419 if( fValue > pValues[1] )
1420 fValue = pValues[1];
1422 delete [] pValues;
1423 mrSane.SetOptionValue( nOption, fValue, nElement );
1424 #if OSL_DEBUG_LEVEL > 1
1425 fprintf( stderr, "yields %lg\n", fValue );
1426 #endif
1429 return TRUE;