Update ooo320-m1
[ooovba.git] / extensions / source / scanner / sanedlg.cxx
blob528376793e305cacb676dfa4f306ea02b17abb2e
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: sanedlg.cxx,v $
10 * $Revision: 1.16 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_extensions.hxx"
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <tools/config.hxx>
38 #include <vcl/msgbox.hxx>
39 #include <sanedlg.hxx>
40 #include <sanedlg.hrc>
41 #include <grid.hxx>
42 #include <math.h>
44 #define USE_SAVE_STATE
45 #undef SAVE_ALL_STATES
47 ResId SaneResId( sal_uInt32 nID )
49 static ResMgr* pResMgr = ResMgr::CreateResMgr( "san" );
50 return ResId( nID, *pResMgr );
53 SaneDlg::SaneDlg( Window* pParent, Sane& rSane ) :
54 ModalDialog( pParent, SaneResId( RID_SANE_DIALOG ) ),
55 mrSane( rSane ),
56 mbIsDragging( FALSE ),
57 mbDragDrawn( FALSE ),
58 maMapMode( MAP_APPFONT ),
59 maOKButton( this, SaneResId( RID_SCAN_OK ) ),
60 maCancelButton( this, SaneResId( RID_SCAN_CANCEL ) ),
61 maDeviceInfoButton( this, SaneResId( RID_DEVICEINFO_BTN ) ),
62 maPreviewButton( this, SaneResId( RID_PREVIEW_BTN ) ),
63 maButtonOption( this, SaneResId( RID_SCAN_BUTTON_OPTION_BTN ) ),
64 maOptionsTxt( this, SaneResId( RID_SCAN_OPTION_TXT ) ),
65 maOptionTitle( this, SaneResId( RID_SCAN_OPTIONTITLE_TXT ) ),
66 maOptionDescTxt( this, SaneResId( RID_SCAN_OPTION_DESC_TXT ) ),
67 maVectorTxt( this, SaneResId( RID_SCAN_NUMERIC_VECTOR_TXT ) ),
68 maScanLeftTxt( this, SaneResId( RID_SCAN_LEFT_TXT ) ),
69 maLeftField( this, SaneResId( RID_SCAN_LEFT_BOX ) ),
70 maScanTopTxt( this, SaneResId( RID_SCAN_TOP_TXT ) ),
71 maTopField( this, SaneResId( RID_SCAN_TOP_BOX ) ),
72 maRightTxt( this, SaneResId( RID_SCAN_RIGHT_TXT ) ),
73 maRightField( this, SaneResId( RID_SCAN_RIGHT_BOX ) ),
74 maBottomTxt( this, SaneResId( RID_SCAN_BOTTOM_TXT ) ),
75 maBottomField( this, SaneResId( RID_SCAN_BOTTOM_BOX ) ),
76 maDeviceBoxTxt( this, SaneResId( RID_DEVICE_BOX_TXT ) ),
77 maDeviceBox( this, SaneResId( RID_DEVICE_BOX ) ),
78 maReslTxt( this, SaneResId( RID_SCAN_RESOLUTION_TXT ) ),
79 maReslBox( this, SaneResId( RID_SCAN_RESOLUTION_BOX ) ),
80 maAdvancedTxt( this, SaneResId( RID_SCAN_ADVANCED_TXT ) ),
81 maAdvancedBox( this, SaneResId( RID_SCAN_ADVANCED_BOX ) ),
82 maVectorBox( this, SaneResId( RID_SCAN_NUMERIC_VECTOR_BOX ) ),
83 maQuantumRangeBox( this, SaneResId( RID_SCAN_QUANTUM_RANGE_BOX ) ),
84 maStringRangeBox( this, SaneResId( RID_SCAN_STRING_RANGE_BOX ) ),
85 maPreviewBox( this, SaneResId( RID_PREVIEW_BOX ) ),
86 maAreaBox( this, SaneResId( RID_SCANAREA_BOX ) ),
87 maBoolCheckBox( this, SaneResId( RID_SCAN_BOOL_OPTION_BOX ) ),
88 maStringEdit( this, SaneResId( RID_SCAN_STRING_OPTION_EDT ) ),
89 maNumericEdit( this, SaneResId( RID_SCAN_NUMERIC_OPTION_EDT ) ),
90 maOptionBox( this, SaneResId( RID_SCAN_OPTION_BOX ) ),
91 mpRange( 0 )
93 if( Sane::IsSane() )
95 InitDevices(); // opens first sane device
96 DisableOption();
97 InitFields();
100 maDeviceInfoButton.SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) );
101 maPreviewButton.SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) );
102 maButtonOption.SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) );
103 maDeviceBox.SetSelectHdl( LINK( this, SaneDlg, SelectHdl ) );
104 maOptionBox.SetSelectHdl( LINK( this, SaneDlg, OptionsBoxSelectHdl ) );
105 maOKButton.SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) );
106 maCancelButton.SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) );
107 maBoolCheckBox.SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) );
108 maStringEdit.SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) );
109 maNumericEdit.SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) );
110 maVectorBox.SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) );
111 maReslBox.SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) );
112 maStringRangeBox.SetSelectHdl( LINK( this, SaneDlg, SelectHdl ) );
113 maQuantumRangeBox.SetSelectHdl( LINK( this, SaneDlg, SelectHdl ) );
114 maLeftField.SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) );
115 maRightField.SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) );
116 maTopField.SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) );
117 maBottomField.SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) );
118 maAdvancedBox.SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) );
120 maOldLink = mrSane.SetReloadOptionsHdl( LINK( this, SaneDlg, ReloadSaneOptionsHdl ) );
122 maOptionBox.SetNodeBitmaps(
123 Bitmap( SaneResId( RID_SCAN_BITMAP_PLUS ) ),
124 Bitmap( SaneResId( RID_SCAN_BITMAP_MINUS ) )
126 maOptionBox.SetWindowBits( WB_HASLINES |
127 WB_HASBUTTONS |
128 WB_NOINITIALSELECTION |
129 WB_HASBUTTONSATROOT |
130 WB_HASLINESATROOT
132 FreeResource();
135 SaneDlg::~SaneDlg()
139 short SaneDlg::Execute()
141 if( ! Sane::IsSane() )
143 ErrorBox aErrorBox( NULL, WB_OK | WB_DEF_OK,
144 String( SaneResId( RID_SANE_NOSANELIB_TXT ) ) );
145 aErrorBox.Execute();
146 return FALSE;
148 LoadState();
149 return ModalDialog::Execute();
152 void SaneDlg::InitDevices()
154 if( ! Sane::IsSane() )
155 return;
157 if( mrSane.IsOpen() )
158 mrSane.Close();
159 mrSane.ReloadDevices();
160 maDeviceBox.Clear();
161 for( int i = 0; i < Sane::CountDevices(); i++ )
162 maDeviceBox.InsertEntry( Sane::GetName( i ) );
163 if( Sane::CountDevices() )
165 mrSane.Open( 0 );
166 maDeviceBox.SelectEntry( Sane::GetName( 0 ) );
171 void SaneDlg::InitFields()
173 if( ! Sane::IsSane() )
174 return;
176 int nOption, i, nValue;
177 double fValue;
178 BOOL bSuccess = FALSE;
179 const char *ppSpecialOptions[] = {
180 "resolution",
181 "tl-x",
182 "tl-y",
183 "br-x",
184 "br-y",
185 "preview"
188 mbDragEnable = TRUE;
189 maReslBox.Clear();
190 maMinTopLeft = Point( 0, 0 );
191 maMaxBottomRight = Point( PREVIEW_WIDTH, PREVIEW_HEIGHT );
193 if( ! mrSane.IsOpen() )
194 return;
196 // set Resolution
197 nOption = mrSane.GetOptionByName( "resolution" );
198 if( nOption != -1 )
200 double fRes;
202 bSuccess = mrSane.GetOptionValue( nOption, fRes );
203 if( bSuccess )
205 maReslBox.Enable( TRUE );
207 maReslBox.SetValue( (long)fRes );
208 double *pDouble = NULL;
209 nValue = mrSane.GetRange( nOption, pDouble );
210 if( nValue > -1 )
212 if( nValue )
214 maReslBox.SetMin( (long)pDouble[0] );
215 maReslBox.SetMax( (long)pDouble[ nValue-1 ] );
216 for( i=0; i<nValue; i++ )
218 if( i == 0 || i == nValue-1 || ! ( ((int)pDouble[i]) % 20) )
219 maReslBox.InsertValue( (long)pDouble[i] );
222 else
224 maReslBox.SetMin( (long)pDouble[0] );
225 maReslBox.SetMax( (long)pDouble[1] );
226 maReslBox.InsertValue( (long)pDouble[0] );
227 // mh@openoffice.org: issue 68557: Can only select 75 and 2400 dpi in Scanner dialogue
228 // scanner allows random setting of dpi resolution, a slider might be useful
229 // support that
230 // workaround: offer at least some more standard dpi resolution between
231 // min and max value
232 int bGot300 = 0;
233 for ( int nRes = (long) pDouble[0] * 2; nRes < (long) pDouble[1]; nRes = nRes * 2 )
235 if ( !bGot300 && nRes > 300 ) {
236 nRes = 300; bGot300 = 1;
238 maReslBox.InsertValue(nRes);
240 maReslBox.InsertValue( (long)pDouble[1] );
242 if( pDouble )
243 delete [] pDouble;
245 else
246 maReslBox.Enable( FALSE );
249 else
250 maReslBox.Enable( FALSE );
252 // set scan area
253 for( i = 0; i < 4; i++ )
255 char const *pOptionName = NULL;
256 MetricField* pField = NULL;
257 switch( i )
259 case 0:
260 pOptionName = "tl-x";
261 pField = &maLeftField;
262 break;
263 case 1:
264 pOptionName = "tl-y";
265 pField = &maTopField;
266 break;
267 case 2:
268 pOptionName = "br-x";
269 pField = &maRightField;
270 break;
271 case 3:
272 pOptionName = "br-y";
273 pField = &maBottomField;
275 nOption = pOptionName ? mrSane.GetOptionByName( pOptionName ) : -1;
276 bSuccess = FALSE;
277 if( nOption != -1 )
279 bSuccess = mrSane.GetOptionValue( nOption, fValue, 0 );
280 if( bSuccess )
282 if( mrSane.GetOptionUnit( nOption ) == SANE_UNIT_MM )
284 pField->SetUnit( FUNIT_MM );
285 pField->SetValue( (int)fValue, FUNIT_MM );
287 else // SANE_UNIT_PIXEL
289 pField->SetValue( (int)fValue, FUNIT_CUSTOM );
290 pField->SetCustomUnitText( String::CreateFromAscii( "Pixel" ) );
292 switch( i ) {
293 case 0: maTopLeft.X() = (int)fValue;break;
294 case 1: maTopLeft.Y() = (int)fValue;break;
295 case 2: maBottomRight.X() = (int)fValue;break;
296 case 3: maBottomRight.Y() = (int)fValue;break;
299 double *pDouble = NULL;
300 nValue = mrSane.GetRange( nOption, pDouble );
301 if( nValue > -1 )
303 if( pDouble )
305 pField->SetMin( (long)pDouble[0] );
306 if( nValue )
307 pField->SetMax( (long)pDouble[ nValue-1 ] );
308 else
309 pField->SetMax( (long)pDouble[ 1 ] );
310 delete [] pDouble;
312 switch( i ) {
313 case 0: maMinTopLeft.X() = pField->GetMin();break;
314 case 1: maMinTopLeft.Y() = pField->GetMin();break;
315 case 2: maMaxBottomRight.X() = pField->GetMax();break;
316 case 3: maMaxBottomRight.Y() = pField->GetMax();break;
319 else
321 switch( i ) {
322 case 0: maMinTopLeft.X() = (int)fValue;break;
323 case 1: maMinTopLeft.Y() = (int)fValue;break;
324 case 2: maMaxBottomRight.X() = (int)fValue;break;
325 case 3: maMaxBottomRight.Y() = (int)fValue;break;
328 pField->Enable( TRUE );
330 else
332 mbDragEnable = FALSE;
333 pField->SetMin( 0 );
334 switch( i ) {
335 case 0:
336 maMinTopLeft.X() = 0;
337 maTopLeft.X() = 0;
338 pField->SetMax( PREVIEW_WIDTH );
339 pField->SetValue( 0 );
340 break;
341 case 1:
342 maMinTopLeft.Y() = 0;
343 maTopLeft.Y() = 0;
344 pField->SetMax( PREVIEW_HEIGHT );
345 pField->SetValue( 0 );
346 break;
347 case 2:
348 maMaxBottomRight.X() = PREVIEW_WIDTH;
349 maBottomRight.X() = PREVIEW_WIDTH;
350 pField->SetMax( PREVIEW_WIDTH );
351 pField->SetValue( PREVIEW_WIDTH );
352 break;
353 case 3:
354 maMaxBottomRight.Y() = PREVIEW_HEIGHT;
355 maBottomRight.Y() = PREVIEW_HEIGHT;
356 pField->SetMax( PREVIEW_HEIGHT );
357 pField->SetValue( PREVIEW_HEIGHT );
358 break;
360 pField->Enable( FALSE );
363 maTopLeft = GetPixelPos( maTopLeft );
364 maBottomRight = GetPixelPos( maBottomRight );
365 maPreviewRect = Rectangle( maTopLeft,
366 Size( maBottomRight.X() - maTopLeft.X(),
367 maBottomRight.Y() - maTopLeft.Y() )
369 // fill OptionBox
370 maOptionBox.Clear();
371 SvLBoxEntry* pParentEntry = 0;
372 BOOL bGroupRejected = FALSE;
373 for( i = 1; i < mrSane.CountOptions(); i++ )
375 String aOption=mrSane.GetOptionName( i );
376 BOOL bInsertAdvanced =
377 mrSane.GetOptionCap( i ) & SANE_CAP_ADVANCED &&
378 ! maAdvancedBox.IsChecked() ? FALSE : TRUE;
379 if( mrSane.GetOptionType( i ) == SANE_TYPE_GROUP )
381 if( bInsertAdvanced )
383 aOption = mrSane.GetOptionTitle( i );
384 pParentEntry = maOptionBox.InsertEntry( aOption );
385 bGroupRejected = FALSE;
387 else
388 bGroupRejected = TRUE;
390 else if( aOption.Len() &&
391 ! ( mrSane.GetOptionCap( i ) &
393 SANE_CAP_HARD_SELECT |
394 SANE_CAP_INACTIVE
395 ) ) &&
396 bInsertAdvanced && ! bGroupRejected )
398 BOOL bIsSpecial = FALSE;
399 for( size_t n = 0; !bIsSpecial &&
400 n < sizeof(ppSpecialOptions)/sizeof(ppSpecialOptions[0]); n++ )
402 if( aOption.EqualsAscii( ppSpecialOptions[n] ) )
403 bIsSpecial=TRUE;
405 if( ! bIsSpecial )
407 if( pParentEntry )
408 maOptionBox.InsertEntry( aOption, pParentEntry );
409 else
410 maOptionBox.InsertEntry( aOption );
416 IMPL_LINK( SaneDlg, ClickBtnHdl, Button*, pButton )
418 if( mrSane.IsOpen() )
420 if( pButton == &maDeviceInfoButton )
422 String aString( SaneResId( RID_SANE_DEVICEINFO_TXT ) );
423 String aSR( RTL_CONSTASCII_USTRINGPARAM( "%s" ) );
424 aString.SearchAndReplace( aSR, Sane::GetName( mrSane.GetDeviceNumber() ) );
425 aString.SearchAndReplace( aSR, Sane::GetVendor( mrSane.GetDeviceNumber() ) );
426 aString.SearchAndReplace( aSR, Sane::GetModel( mrSane.GetDeviceNumber() ) );
427 aString.SearchAndReplace( aSR, Sane::GetType( mrSane.GetDeviceNumber() ) );
428 InfoBox aInfoBox( this, aString );
429 aInfoBox.Execute();
431 else if( pButton == &maPreviewButton )
432 AcquirePreview();
433 else if( pButton == &maBoolCheckBox )
435 mrSane.SetOptionValue( mnCurrentOption,
436 maBoolCheckBox.IsChecked() ?
437 (BOOL)TRUE : (BOOL)FALSE );
439 else if( pButton == &maButtonOption )
442 SANE_Value_Type nType = mrSane.GetOptionType( mnCurrentOption );
443 switch( nType )
445 case SANE_TYPE_BUTTON:
446 mrSane.ActivateButtonOption( mnCurrentOption );
447 break;
448 case SANE_TYPE_FIXED:
449 case SANE_TYPE_INT:
451 int nElements = mrSane.GetOptionElements( mnCurrentOption );
452 double* x = new double[ nElements ];
453 double* y = new double[ nElements ];
454 for( int i = 0; i < nElements; i++ )
455 x[ i ] = (double)i;
456 mrSane.GetOptionValue( mnCurrentOption, y );
458 GridWindow aGrid( x, y, nElements, this );
459 aGrid.SetText( mrSane.GetOptionName( mnCurrentOption ) );
460 aGrid.setBoundings( 0, mfMin, nElements, mfMax );
461 if( aGrid.Execute() && aGrid.getNewYValues() )
462 mrSane.SetOptionValue( mnCurrentOption, aGrid.getNewYValues() );
464 delete [] x;
465 delete [] y;
467 break;
468 case SANE_TYPE_BOOL:
469 case SANE_TYPE_STRING:
470 case SANE_TYPE_GROUP:
471 break;
474 else if( pButton == &maAdvancedBox )
476 ReloadSaneOptionsHdl( NULL );
479 if( pButton == &maOKButton )
481 double fRes = (double)maReslBox.GetValue();
482 SetAdjustedNumericalValue( "resolution", fRes );
483 mrSane.SetReloadOptionsHdl( maOldLink );
484 UpdateScanArea( TRUE );
485 SaveState();
486 EndDialog( mrSane.IsOpen() ? 1 : 0 );
488 else if( pButton == &maCancelButton )
490 mrSane.SetReloadOptionsHdl( maOldLink );
491 mrSane.Close();
492 EndDialog( 0 );
494 return 0;
497 IMPL_LINK( SaneDlg, SelectHdl, ListBox*, pListBox )
499 if( pListBox == &maDeviceBox && Sane::IsSane() && Sane::CountDevices() )
501 String aNewDevice = maDeviceBox.GetSelectEntry();
502 int nNumber;
503 if( aNewDevice.Equals( Sane::GetName( nNumber = mrSane.GetDeviceNumber() ) ) )
505 mrSane.Close();
506 mrSane.Open( nNumber );
507 InitFields();
510 if( mrSane.IsOpen() )
512 if( pListBox == &maQuantumRangeBox )
514 ByteString aValue( maQuantumRangeBox.GetSelectEntry(), osl_getThreadTextEncoding() );
515 double fValue = atof( aValue.GetBuffer() );
516 mrSane.SetOptionValue( mnCurrentOption, fValue, mnCurrentElement );
518 else if( pListBox == &maStringRangeBox )
520 mrSane.SetOptionValue( mnCurrentOption, maStringRangeBox.GetSelectEntry() );
523 return 0;
526 IMPL_LINK( SaneDlg, OptionsBoxSelectHdl, SvTreeListBox*, pBox )
528 if( pBox == &maOptionBox && Sane::IsSane() )
530 String aOption =
531 maOptionBox.GetEntryText( maOptionBox.FirstSelected() );
532 int nOption = mrSane.GetOptionByName( ByteString( aOption, osl_getThreadTextEncoding() ).GetBuffer() );
533 if( nOption != -1 && nOption != mnCurrentOption )
535 DisableOption();
536 mnCurrentOption = nOption;
537 maOptionTitle.SetText( mrSane.GetOptionTitle( mnCurrentOption ) );
538 SANE_Value_Type nType = mrSane.GetOptionType( mnCurrentOption );
539 SANE_Constraint_Type nConstraint;
540 switch( nType )
542 case SANE_TYPE_BOOL: EstablishBoolOption();break;
543 case SANE_TYPE_STRING:
544 nConstraint = mrSane.GetOptionConstraintType( mnCurrentOption );
545 if( nConstraint == SANE_CONSTRAINT_STRING_LIST )
546 EstablishStringRange();
547 else
548 EstablishStringOption();
549 break;
550 case SANE_TYPE_FIXED:
551 case SANE_TYPE_INT:
553 nConstraint = mrSane.GetOptionConstraintType( mnCurrentOption );
554 int nElements = mrSane.GetOptionElements( mnCurrentOption );
555 mnCurrentElement = 0;
556 if( nConstraint == SANE_CONSTRAINT_RANGE ||
557 nConstraint == SANE_CONSTRAINT_WORD_LIST )
558 EstablishQuantumRange();
559 else
561 mfMin = mfMax = 0.0;
562 EstablishNumericOption();
564 if( nElements > 1 )
566 if( nElements <= 10 )
568 maVectorBox.SetValue( 1 );
569 maVectorBox.SetMin( 1 );
570 maVectorBox.SetMax(
571 mrSane.GetOptionElements( mnCurrentOption ) );
572 maVectorBox.Show( TRUE );
573 maVectorTxt.Show( TRUE );
575 else
577 DisableOption();
578 // bring up dialog only on button click
579 EstablishButtonOption();
583 break;
584 case SANE_TYPE_BUTTON:
585 EstablishButtonOption();
586 break;
587 default: break;
591 return 0;
594 IMPL_LINK( SaneDlg, ModifyHdl, Edit*, pEdit )
596 if( mrSane.IsOpen() )
598 if( pEdit == &maStringEdit )
600 mrSane.SetOptionValue( mnCurrentOption, maStringEdit.GetText() );
602 else if( pEdit == &maReslBox )
604 double fRes = (double)maReslBox.GetValue();
605 int nOption = mrSane.GetOptionByName( "resolution" );
606 if( nOption != -1 )
608 double* pDouble = NULL;
609 int nValues = mrSane.GetRange( nOption, pDouble );
610 if( nValues > 0 )
612 int i;
613 for( i = 0; i < nValues; i++ )
615 if( fRes == pDouble[i] )
616 break;
618 if( i >= nValues )
619 fRes = pDouble[0];
621 else if( nValues == 0 )
623 if( fRes < pDouble[ 0 ] )
624 fRes = pDouble[ 0 ];
625 if( fRes > pDouble[ 1 ] )
626 fRes = pDouble[ 1 ];
628 maReslBox.SetValue( (ULONG)fRes );
631 else if( pEdit == &maNumericEdit )
633 double fValue;
634 char pBuf[256];
635 ByteString aContents( maNumericEdit.GetText(), osl_getThreadTextEncoding() );
636 fValue = atof( aContents.GetBuffer() );
637 if( mfMin != mfMax && ( fValue < mfMin || fValue > mfMax ) )
639 if( fValue < mfMin )
640 fValue = mfMin;
641 else if( fValue > mfMax )
642 fValue = mfMax;
643 sprintf( pBuf, "%g", fValue );
644 maNumericEdit.SetText( String( pBuf, osl_getThreadTextEncoding() ) );
646 mrSane.SetOptionValue( mnCurrentOption, fValue, mnCurrentElement );
648 else if( pEdit == &maVectorBox )
650 char pBuf[256];
651 mnCurrentElement = maVectorBox.GetValue()-1;
652 double fValue;
653 mrSane.GetOptionValue( mnCurrentOption, fValue, mnCurrentElement );
654 sprintf( pBuf, "%g", fValue );
655 String aValue( pBuf, osl_getThreadTextEncoding() );
656 maNumericEdit.SetText( aValue );
657 maQuantumRangeBox.SelectEntry( aValue );
659 else if( pEdit == &maTopField )
661 Point aPoint( 0, maTopField.GetValue() );
662 aPoint = GetPixelPos( aPoint );
663 maTopLeft.Y() = aPoint.Y();
664 DrawDrag();
666 else if( pEdit == &maLeftField )
668 Point aPoint( maLeftField.GetValue(), 0 );
669 aPoint = GetPixelPos( aPoint );
670 maTopLeft.X() = aPoint.X();
671 DrawDrag();
673 else if( pEdit == &maBottomField )
675 Point aPoint( 0, maBottomField.GetValue() );
676 aPoint = GetPixelPos( aPoint );
677 maBottomRight.Y() = aPoint.Y();
678 DrawDrag();
680 else if( pEdit == &maRightField )
682 Point aPoint( maRightField.GetValue(), 0 );
683 aPoint = GetPixelPos( aPoint );
684 maBottomRight.X() = aPoint.X();
685 DrawDrag();
688 return 0;
691 IMPL_LINK( SaneDlg, ReloadSaneOptionsHdl, Sane*, /*pSane*/ )
693 mnCurrentOption = -1;
694 mnCurrentElement = 0;
695 DisableOption();
696 // #92024# preserve preview rect, should only be set
697 // initially or in AcquirePreview
698 Rectangle aPreviewRect = maPreviewRect;
699 InitFields();
700 maPreviewRect = aPreviewRect;
701 Rectangle aDummyRect( Point( 0, 0 ), GetSizePixel() );
702 Paint( aDummyRect );
703 return 0;
706 void SaneDlg::AcquirePreview()
708 if( ! mrSane.IsOpen() )
709 return;
711 UpdateScanArea( TRUE );
712 // set small resolution for preview
713 double fResl = (double)maReslBox.GetValue();
714 SetAdjustedNumericalValue( "resolution", 30.0 );
716 int nOption = mrSane.GetOptionByName( "preview" );
717 if( nOption == -1 )
719 String aString( SaneResId( RID_SANE_NORESOLUTIONOPTION_TXT ) );
720 WarningBox aBox( this, WB_OK_CANCEL | WB_DEF_OK, aString );
721 if( aBox.Execute() == RET_CANCEL )
722 return;
724 else
725 mrSane.SetOptionValue( nOption, (BOOL)TRUE );
727 BitmapTransporter aTransporter;
728 if( ! mrSane.Start( aTransporter ) )
730 ErrorBox aErrorBox( this, WB_OK | WB_DEF_OK,
731 String( SaneResId( RID_SANE_SCANERROR_TXT ) ) );
732 aErrorBox.Execute();
734 else
736 #if OSL_DEBUG_LEVEL > 1
737 aTransporter.getStream().Seek( STREAM_SEEK_TO_END );
738 fprintf( stderr, "Previewbitmapstream contains %d bytes\n", (int)aTransporter.getStream().Tell() );
739 #endif
740 aTransporter.getStream().Seek( STREAM_SEEK_TO_BEGIN );
741 maPreviewBitmap.Read( aTransporter.getStream(), TRUE );
744 SetAdjustedNumericalValue( "resolution", fResl );
745 maReslBox.SetValue( (ULONG)fResl );
747 if( mbDragEnable )
748 maPreviewRect = Rectangle( maTopLeft,
749 Size( maBottomRight.X() - maTopLeft.X(),
750 maBottomRight.Y() - maTopLeft.Y() )
752 else
754 Size aBMSize( maPreviewBitmap.GetSizePixel() );
755 if( aBMSize.Width() > aBMSize.Height() )
757 int nVHeight = (maBottomRight.X() - maTopLeft.X()) * aBMSize.Height() / aBMSize.Width();
758 maPreviewRect = Rectangle( Point( maTopLeft.X(), ( maTopLeft.Y() + maBottomRight.Y() )/2 - nVHeight/2 ),
759 Size( maBottomRight.X() - maTopLeft.X(),
760 nVHeight ) );
762 else
764 int nVWidth = (maBottomRight.Y() - maTopLeft.Y()) * aBMSize.Width() / aBMSize.Height();
765 maPreviewRect = Rectangle( Point( ( maTopLeft.X() + maBottomRight.X() )/2 - nVWidth/2, maTopLeft.Y() ),
766 Size( nVWidth,
767 maBottomRight.Y() - maTopLeft.Y() ) );
771 Paint( Rectangle( Point( 0, 0 ), GetSizePixel() ) );
774 void SaneDlg::Paint( const Rectangle& rRect )
776 SetMapMode( maMapMode );
777 SetFillColor( Color( COL_WHITE ) );
778 SetLineColor( Color( COL_WHITE ) );
779 DrawRect( Rectangle( Point( PREVIEW_UPPER_LEFT, PREVIEW_UPPER_TOP ),
780 Size( PREVIEW_WIDTH, PREVIEW_HEIGHT ) ) );
781 SetMapMode( MapMode( MAP_PIXEL ) );
782 // check for sane values
783 DrawBitmap( maPreviewRect.TopLeft(), maPreviewRect.GetSize(),
784 maPreviewBitmap );
786 mbDragDrawn = FALSE;
787 DrawDrag();
789 ModalDialog::Paint( rRect );
792 void SaneDlg::DisableOption()
794 maBoolCheckBox.Show( FALSE );
795 maStringEdit.Show( FALSE );
796 maNumericEdit.Show( FALSE );
797 maQuantumRangeBox.Show( FALSE );
798 maStringRangeBox.Show( FALSE );
799 maButtonOption.Show( FALSE );
800 maVectorBox.Show( FALSE );
801 maVectorTxt.Show( FALSE );
802 maOptionDescTxt.Show( FALSE );
805 void SaneDlg::EstablishBoolOption()
807 BOOL bSuccess, bValue;
809 bSuccess = mrSane.GetOptionValue( mnCurrentOption, bValue );
810 if( bSuccess )
812 maOptionDescTxt.SetText( mrSane.GetOptionName( mnCurrentOption ) );
813 maOptionDescTxt.Show( TRUE );
814 maBoolCheckBox.Check( bValue );
815 maBoolCheckBox.Show( TRUE );
819 void SaneDlg::EstablishStringOption()
821 BOOL bSuccess;
822 ByteString aValue;
824 bSuccess = mrSane.GetOptionValue( mnCurrentOption, aValue );
825 if( bSuccess )
827 maOptionDescTxt.SetText( mrSane.GetOptionName( mnCurrentOption ) );
828 maOptionDescTxt.Show( TRUE );
829 maStringEdit.SetText( String( aValue, osl_getThreadTextEncoding() ) );
830 maStringEdit.Show( TRUE );
834 void SaneDlg::EstablishStringRange()
836 const char** ppStrings = mrSane.GetStringConstraint( mnCurrentOption );
837 maStringRangeBox.Clear();
838 for( int i = 0; ppStrings[i] != 0; i++ )
839 maStringRangeBox.InsertEntry( String( ppStrings[i], osl_getThreadTextEncoding() ) );
840 ByteString aValue;
841 mrSane.GetOptionValue( mnCurrentOption, aValue );
842 maStringRangeBox.SelectEntry( String( aValue, osl_getThreadTextEncoding() ) );
843 maStringRangeBox.Show( TRUE );
844 maOptionDescTxt.SetText( mrSane.GetOptionName( mnCurrentOption ) );
845 maOptionDescTxt.Show( TRUE );
848 void SaneDlg::EstablishQuantumRange()
850 if( mpRange )
852 delete [] mpRange;
853 mpRange = 0;
855 int nValues = mrSane.GetRange( mnCurrentOption, mpRange );
856 if( nValues == 0 )
858 mfMin = mpRange[ 0 ];
859 mfMax = mpRange[ 1 ];
860 delete [] mpRange;
861 mpRange = 0;
862 EstablishNumericOption();
864 else if( nValues > 0 )
866 char pBuf[ 256 ];
867 maQuantumRangeBox.Clear();
868 mfMin = mpRange[ 0 ];
869 mfMax = mpRange[ nValues-1 ];
870 for( int i = 0; i < nValues; i++ )
872 sprintf( pBuf, "%g", mpRange[ i ] );
873 maQuantumRangeBox.InsertEntry( String( pBuf, osl_getThreadTextEncoding() ) );
875 double fValue;
876 if( mrSane.GetOptionValue( mnCurrentOption, fValue, mnCurrentElement ) )
878 sprintf( pBuf, "%g", fValue );
879 maQuantumRangeBox.SelectEntry( String( pBuf, osl_getThreadTextEncoding() ) );
881 maQuantumRangeBox.Show( TRUE );
882 String aText( mrSane.GetOptionName( mnCurrentOption ) );
883 aText += ' ';
884 aText += mrSane.GetOptionUnitName( mnCurrentOption );
885 maOptionDescTxt.SetText( aText );
886 maOptionDescTxt.Show( TRUE );
890 void SaneDlg::EstablishNumericOption()
892 BOOL bSuccess;
893 double fValue;
895 bSuccess = mrSane.GetOptionValue( mnCurrentOption, fValue );
896 if( ! bSuccess )
897 return;
899 char pBuf[256];
900 String aText( mrSane.GetOptionName( mnCurrentOption ) );
901 aText += ' ';
902 aText += mrSane.GetOptionUnitName( mnCurrentOption );
903 if( mfMin != mfMax )
905 sprintf( pBuf, " < %g ; %g >", mfMin, mfMax );
906 aText += String( pBuf, osl_getThreadTextEncoding() );
908 maOptionDescTxt.SetText( aText );
909 maOptionDescTxt.Show( TRUE );
910 sprintf( pBuf, "%g", fValue );
911 maNumericEdit.SetText( String( pBuf, osl_getThreadTextEncoding() ) );
912 maNumericEdit.Show( TRUE );
915 void SaneDlg::EstablishButtonOption()
917 maOptionDescTxt.SetText( mrSane.GetOptionName( mnCurrentOption ) );
918 maOptionDescTxt.Show( TRUE );
919 maButtonOption.Show( TRUE );
922 #define RECT_SIZE_PIX 7
924 void SaneDlg::MouseMove( const MouseEvent& rMEvt )
926 if( mbIsDragging )
928 Point aMousePos = rMEvt.GetPosPixel();
929 // move into valid area
930 Point aLogicPos = GetLogicPos( aMousePos );
931 aMousePos = GetPixelPos( aLogicPos );
932 switch( meDragDirection )
934 case TopLeft: maTopLeft = aMousePos; break;
935 case Top: maTopLeft.Y() = aMousePos.Y(); break;
936 case TopRight:
937 maTopLeft.Y() = aMousePos.Y();
938 maBottomRight.X() = aMousePos.X();
939 break;
940 case Right: maBottomRight.X() = aMousePos.X(); break;
941 case BottomRight: maBottomRight = aMousePos; break;
942 case Bottom: maBottomRight.Y() = aMousePos.Y(); break;
943 case BottomLeft:
944 maTopLeft.X() = aMousePos.X();
945 maBottomRight.Y() = aMousePos.Y();
946 break;
947 case Left: maTopLeft.X() = aMousePos.X(); break;
948 default: break;
950 int nSwap;
951 if( maTopLeft.X() > maBottomRight.X() )
953 nSwap = maTopLeft.X();
954 maTopLeft.X() = maBottomRight.X();
955 maBottomRight.X() = nSwap;
957 if( maTopLeft.Y() > maBottomRight.Y() )
959 nSwap = maTopLeft.Y();
960 maTopLeft.Y() = maBottomRight.Y();
961 maBottomRight.Y() = nSwap;
963 DrawDrag();
964 UpdateScanArea( FALSE );
966 ModalDialog::MouseMove( rMEvt );
969 void SaneDlg::MouseButtonDown( const MouseEvent& rMEvt )
971 Point aMousePixel = rMEvt.GetPosPixel();
973 if( ! mbIsDragging && mbDragEnable )
975 int nMiddleX = ( maBottomRight.X() - maTopLeft.X() ) / 2 - RECT_SIZE_PIX/2 + maTopLeft.X();
976 int nMiddleY = ( maBottomRight.Y() - maTopLeft.Y() ) / 2 - RECT_SIZE_PIX/2 + maTopLeft.Y();
977 if( aMousePixel.Y() >= maTopLeft.Y() &&
978 aMousePixel.Y() < maTopLeft.Y() + RECT_SIZE_PIX )
980 if( aMousePixel.X() >= maTopLeft.X() &&
981 aMousePixel.X() < maTopLeft.X() + RECT_SIZE_PIX )
983 meDragDirection = TopLeft;
984 aMousePixel = maTopLeft;
985 mbIsDragging = TRUE;
987 else if( aMousePixel.X() >= nMiddleX &&
988 aMousePixel.X() < nMiddleX + RECT_SIZE_PIX )
990 meDragDirection = Top;
991 aMousePixel.Y() = maTopLeft.Y();
992 mbIsDragging = TRUE;
994 else if( aMousePixel.X() > maBottomRight.X() - RECT_SIZE_PIX &&
995 aMousePixel.X() <= maBottomRight.X() )
997 meDragDirection = TopRight;
998 aMousePixel = Point( maBottomRight.X(), maTopLeft.Y() );
999 mbIsDragging = TRUE;
1002 else if( aMousePixel.Y() >= nMiddleY &&
1003 aMousePixel.Y() < nMiddleY + RECT_SIZE_PIX )
1005 if( aMousePixel.X() >= maTopLeft.X() &&
1006 aMousePixel.X() < maTopLeft.X() + RECT_SIZE_PIX )
1008 meDragDirection = Left;
1009 aMousePixel.X() = maTopLeft.X();
1010 mbIsDragging = TRUE;
1012 else if( aMousePixel.X() > maBottomRight.X() - RECT_SIZE_PIX &&
1013 aMousePixel.X() <= maBottomRight.X() )
1015 meDragDirection = Right;
1016 aMousePixel.X() = maBottomRight.X();
1017 mbIsDragging = TRUE;
1020 else if( aMousePixel.Y() <= maBottomRight.Y() &&
1021 aMousePixel.Y() > maBottomRight.Y() - RECT_SIZE_PIX )
1023 if( aMousePixel.X() >= maTopLeft.X() &&
1024 aMousePixel.X() < maTopLeft.X() + RECT_SIZE_PIX )
1026 meDragDirection = BottomLeft;
1027 aMousePixel = Point( maTopLeft.X(), maBottomRight.Y() );
1028 mbIsDragging = TRUE;
1030 else if( aMousePixel.X() >= nMiddleX &&
1031 aMousePixel.X() < nMiddleX + RECT_SIZE_PIX )
1033 meDragDirection = Bottom;
1034 aMousePixel.Y() = maBottomRight.Y();
1035 mbIsDragging = TRUE;
1037 else if( aMousePixel.X() > maBottomRight.X() - RECT_SIZE_PIX &&
1038 aMousePixel.X() <= maBottomRight.X() )
1040 meDragDirection = BottomRight;
1041 aMousePixel = maBottomRight;
1042 mbIsDragging = TRUE;
1046 if( mbIsDragging )
1048 SetPointerPosPixel( aMousePixel );
1049 DrawDrag();
1051 ModalDialog::MouseButtonDown( rMEvt );
1054 void SaneDlg::MouseButtonUp( const MouseEvent& rMEvt )
1056 if( mbIsDragging )
1058 UpdateScanArea( TRUE );
1060 mbIsDragging = FALSE;
1062 ModalDialog::MouseButtonUp( rMEvt );
1065 void SaneDlg::DrawRectangles( Point& rUL, Point& rBR )
1067 int nMiddleX, nMiddleY;
1068 Point aBL, aUR;
1070 aUR = Point( rBR.X(), rUL.Y() );
1071 aBL = Point( rUL.X(), rBR.Y() );
1072 nMiddleX = ( rBR.X() - rUL.X() ) / 2 + rUL.X();
1073 nMiddleY = ( rBR.Y() - rUL.Y() ) / 2 + rUL.Y();
1075 DrawLine( rUL, aBL );
1076 DrawLine( aBL, rBR );
1077 DrawLine( rBR, aUR );
1078 DrawLine( aUR, rUL );
1079 DrawRect( Rectangle( rUL, Size( RECT_SIZE_PIX,RECT_SIZE_PIX ) ) );
1080 DrawRect( Rectangle( aBL, Size( RECT_SIZE_PIX, -RECT_SIZE_PIX ) ) );
1081 DrawRect( Rectangle( rBR, Size( -RECT_SIZE_PIX, -RECT_SIZE_PIX ) ) );
1082 DrawRect( Rectangle( aUR, Size( -RECT_SIZE_PIX, RECT_SIZE_PIX ) ) );
1083 DrawRect( Rectangle( Point( nMiddleX - RECT_SIZE_PIX/2, rUL.Y() ), Size( RECT_SIZE_PIX, RECT_SIZE_PIX ) ) );
1084 DrawRect( Rectangle( Point( nMiddleX - RECT_SIZE_PIX/2, rBR.Y() ), Size( RECT_SIZE_PIX, -RECT_SIZE_PIX ) ) );
1085 DrawRect( Rectangle( Point( rUL.X(), nMiddleY - RECT_SIZE_PIX/2 ), Size( RECT_SIZE_PIX, RECT_SIZE_PIX ) ) );
1086 DrawRect( Rectangle( Point( rBR.X(), nMiddleY - RECT_SIZE_PIX/2 ), Size( -RECT_SIZE_PIX, RECT_SIZE_PIX ) ) );
1089 void SaneDlg::DrawDrag()
1091 static Point aLastUL, aLastBR;
1093 if( ! mbDragEnable )
1094 return;
1096 RasterOp eROP = GetRasterOp();
1097 SetRasterOp( ROP_INVERT );
1098 SetMapMode( MapMode( MAP_PIXEL ) );
1100 if( mbDragDrawn )
1101 DrawRectangles( aLastUL, aLastBR );
1103 aLastUL = maTopLeft;
1104 aLastBR = maBottomRight;
1105 DrawRectangles( maTopLeft, maBottomRight );
1107 mbDragDrawn = TRUE;
1108 SetRasterOp( eROP );
1109 SetMapMode( maMapMode );
1112 Point SaneDlg::GetPixelPos( const Point& rIn )
1114 Point aConvert(
1115 ( ( rIn.X() * PREVIEW_WIDTH ) /
1116 ( maMaxBottomRight.X() - maMinTopLeft.X() ) )
1117 + PREVIEW_UPPER_LEFT,
1118 ( ( rIn.Y() * PREVIEW_HEIGHT )
1119 / ( maMaxBottomRight.Y() - maMinTopLeft.Y() ) )
1120 + PREVIEW_UPPER_TOP );
1122 return LogicToPixel( aConvert, maMapMode );
1125 Point SaneDlg::GetLogicPos( const Point& rIn )
1127 Point aConvert = PixelToLogic( rIn, maMapMode );
1128 aConvert.X() -= PREVIEW_UPPER_LEFT;
1129 aConvert.Y() -= PREVIEW_UPPER_TOP;
1130 if( aConvert.X() < 0 )
1131 aConvert.X() = 0;
1132 if( aConvert.X() >= PREVIEW_WIDTH )
1133 aConvert.X() = PREVIEW_WIDTH-1;
1134 if( aConvert.Y() < 0 )
1135 aConvert.Y() = 0;
1136 if( aConvert.Y() >= PREVIEW_HEIGHT )
1137 aConvert.Y() = PREVIEW_HEIGHT-1;
1139 aConvert.X() *= ( maMaxBottomRight.X() - maMinTopLeft.X() );
1140 aConvert.X() /= PREVIEW_WIDTH;
1141 aConvert.Y() *= ( maMaxBottomRight.Y() - maMinTopLeft.Y() );
1142 aConvert.Y() /= PREVIEW_HEIGHT;
1143 return aConvert;
1146 void SaneDlg::UpdateScanArea( BOOL bSend )
1148 if( ! mbDragEnable )
1149 return;
1151 Point aUL = GetLogicPos( maTopLeft );
1152 Point aBR = GetLogicPos( maBottomRight );
1154 maLeftField.SetValue( aUL.X() );
1155 maTopField.SetValue( aUL.Y() );
1156 maRightField.SetValue( aBR.X() );
1157 maBottomField.SetValue( aBR.Y() );
1159 if( ! bSend )
1160 return;
1162 if( mrSane.IsOpen() )
1164 SetAdjustedNumericalValue( "tl-x", (double)aUL.X() );
1165 SetAdjustedNumericalValue( "tl-y", (double)aUL.Y() );
1166 SetAdjustedNumericalValue( "br-x", (double)aBR.X() );
1167 SetAdjustedNumericalValue( "br-y", (double)aBR.Y() );
1171 BOOL SaneDlg::LoadState()
1173 #ifdef USE_SAVE_STATE
1174 int i;
1176 if( ! Sane::IsSane() )
1177 return FALSE;
1179 const char* pEnv = getenv("HOME");
1180 String aFileName( pEnv ? pEnv : "", osl_getThreadTextEncoding() );
1181 aFileName += String( RTL_CONSTASCII_USTRINGPARAM( "/.so_sane_state" ) );
1182 Config aConfig( aFileName );
1183 if( ! aConfig.HasGroup( "SANE" ) )
1184 return FALSE;
1186 aConfig.SetGroup( "SANE" );
1187 ByteString aString = aConfig.ReadKey( "SO_LastSaneDevice" );
1188 for( i = 0; i < Sane::CountDevices() && ! aString.Equals( ByteString( Sane::GetName( i ), osl_getThreadTextEncoding() ) ); i++ ) ;
1189 if( i == Sane::CountDevices() )
1190 return FALSE;
1192 mrSane.Close();
1193 mrSane.Open( aString.GetBuffer() );
1195 DisableOption();
1196 InitFields();
1198 if( mrSane.IsOpen() )
1200 int iMax = aConfig.GetKeyCount();
1201 for( i = 0; i < iMax; i++ )
1203 aString = aConfig.GetKeyName( i );
1204 ByteString aValue = aConfig.ReadKey( i );
1205 int nOption = mrSane.GetOptionByName( aString.GetBuffer() );
1206 if( nOption != -1 )
1208 if( aValue.CompareTo( "BOOL=", 5 ) == COMPARE_EQUAL )
1210 aValue.Erase( 0, 5 );
1211 BOOL aBOOL = (BOOL)aValue.ToInt32();
1212 mrSane.SetOptionValue( nOption, aBOOL );
1214 else if( aValue.CompareTo( "STRING=", 7 ) == COMPARE_EQUAL )
1216 aValue.Erase( 0, 7 );
1217 mrSane.SetOptionValue( nOption, String( aValue, osl_getThreadTextEncoding() ) );
1219 else if( aValue.CompareTo( "NUMERIC=", 8 ) == COMPARE_EQUAL )
1221 aValue.Erase( 0, 8 );
1222 int nMax = aValue.GetTokenCount( ':' );
1223 double fValue=0.0;
1224 for( int n = 0; n < nMax ; n++ )
1226 ByteString aSub = aValue.GetToken( n, ':' );
1227 sscanf( aSub.GetBuffer(), "%lg", &fValue );
1228 SetAdjustedNumericalValue( aString.GetBuffer(), fValue, n );
1235 DisableOption();
1236 InitFields();
1238 return TRUE;
1239 #else
1240 return FALSE;
1241 #endif
1244 void SaneDlg::SaveState()
1246 #ifdef USE_SAVE_STATE
1247 if( ! Sane::IsSane() )
1248 return;
1250 const char* pEnv = getenv( "HOME" );
1251 String aFileName( pEnv ? pEnv : "", osl_getThreadTextEncoding() );
1252 aFileName.AppendAscii( "/.so_sane_state" );
1254 Config aConfig( aFileName );
1255 aConfig.DeleteGroup( "SANE" );
1256 aConfig.SetGroup( "SANE" );
1257 aConfig.WriteKey( "SO_LastSANEDevice", ByteString( maDeviceBox.GetSelectEntry(), RTL_TEXTENCODING_UTF8 ) );
1259 #ifdef SAVE_ALL_STATES
1260 for( int i = 1; i < mrSane.CountOptions(); i++ )
1262 String aOption=mrSane.GetOptionName( i );
1263 SANE_Value_Type nType = mrSane.GetOptionType( i );
1264 switch( nType )
1266 case SANE_TYPE_BOOL:
1268 BOOL bValue;
1269 if( mrSane.GetOptionValue( i, bValue ) )
1271 ByteString aString( "BOOL=" );
1272 aString += (ULONG)bValue;
1273 aConfig.WriteKey( aOption, aString );
1276 break;
1277 case SANE_TYPE_STRING:
1279 String aString( "STRING=" );
1280 String aValue;
1281 if( mrSane.GetOptionValue( i, aValue ) )
1283 aString += aValue;
1284 aConfig.WriteKey( aOption, aString );
1287 break;
1288 case SANE_TYPE_FIXED:
1289 case SANE_TYPE_INT:
1291 String aString( "NUMERIC=" );
1292 double fValue;
1293 char buf[256];
1294 for( int n = 0; n < mrSane.GetOptionElements( i ); n++ )
1296 if( ! mrSane.GetOptionValue( i, fValue, n ) )
1297 break;
1298 if( n > 0 )
1299 aString += ":";
1300 sprintf( buf, "%lg", fValue );
1301 aString += buf;
1303 if( n >= mrSane.GetOptionElements( i ) )
1304 aConfig.WriteKey( aOption, aString );
1306 break;
1307 default:
1308 break;
1311 #else
1312 static char const* pSaveOptions[] = {
1313 "resolution",
1314 "tl-x",
1315 "tl-y",
1316 "br-x",
1317 "br-y"
1319 for( size_t i = 0;
1320 i < (sizeof(pSaveOptions)/sizeof(pSaveOptions[0]));
1321 i++ )
1323 ByteString aOption = pSaveOptions[i];
1324 int nOption = mrSane.GetOptionByName( pSaveOptions[i] );
1325 if( nOption > -1 )
1327 SANE_Value_Type nType = mrSane.GetOptionType( nOption );
1328 switch( nType )
1330 case SANE_TYPE_BOOL:
1332 BOOL bValue;
1333 if( mrSane.GetOptionValue( nOption, bValue ) )
1335 ByteString aString( "BOOL=" );
1336 aString += ByteString::CreateFromInt32(bValue);
1337 aConfig.WriteKey( aOption, aString );
1340 break;
1341 case SANE_TYPE_STRING:
1343 ByteString aString( "STRING=" );
1344 ByteString aValue;
1345 if( mrSane.GetOptionValue( nOption, aValue ) )
1347 aString += aValue;
1348 aConfig.WriteKey( aOption, aString );
1351 break;
1352 case SANE_TYPE_FIXED:
1353 case SANE_TYPE_INT:
1355 ByteString aString( "NUMERIC=" );
1356 double fValue;
1357 char buf[256];
1358 int n;
1360 for( n = 0; n < mrSane.GetOptionElements( nOption ); n++ )
1362 if( ! mrSane.GetOptionValue( nOption, fValue, n ) )
1363 break;
1364 if( n > 0 )
1365 aString += ":";
1366 sprintf( buf, "%lg", fValue );
1367 aString += buf;
1369 if( n >= mrSane.GetOptionElements( nOption ) )
1370 aConfig.WriteKey( aOption, aString );
1372 break;
1373 default:
1374 break;
1378 #endif
1379 #endif
1382 BOOL SaneDlg::SetAdjustedNumericalValue(
1383 const char* pOption,
1384 double fValue,
1385 int nElement )
1387 int nOption;
1388 if( ! Sane::IsSane() || ! mrSane.IsOpen() || ( nOption = mrSane.GetOptionByName( pOption ) ) == -1 )
1389 return FALSE;
1391 if( nElement < 0 || nElement >= mrSane.GetOptionElements( nOption ) )
1392 return FALSE;
1394 double* pValues = NULL;
1395 int nValues;
1396 if( ( nValues = mrSane.GetRange( nOption, pValues ) ) < 0 )
1397 return FALSE;
1399 #if OSL_DEBUG_LEVEL > 1
1400 fprintf( stderr, "SaneDlg::SetAdjustedNumericalValue( \"%s\", %lg ) ",
1401 pOption, fValue );
1402 #endif
1404 if( nValues )
1406 int nNearest = 0;
1407 double fNearest = 1e6;
1408 for( int i = 0; i < nValues; i++ )
1410 if( fabs( fValue - pValues[ i ] ) < fNearest )
1412 fNearest = fabs( fValue - pValues[ i ] );
1413 nNearest = i;
1416 fValue = pValues[ nNearest ];
1418 else
1420 if( fValue < pValues[0] )
1421 fValue = pValues[0];
1422 if( fValue > pValues[1] )
1423 fValue = pValues[1];
1425 delete [] pValues;
1426 mrSane.SetOptionValue( nOption, fValue, nElement );
1427 #if OSL_DEBUG_LEVEL > 1
1428 fprintf( stderr, "yields %lg\n", fValue );
1429 #endif
1432 return TRUE;