diff options
author | Jens-Heiner Rechtien <hr@openoffice.org> | 2000-09-18 15:18:56 +0000 |
---|---|---|
committer | Jens-Heiner Rechtien <hr@openoffice.org> | 2000-09-18 15:18:56 +0000 |
commit | fb25499be77b4b8d84d55bf18effe89012f39e07 (patch) | |
tree | ea38938af6dcdf95e45bf508f086b4a53c1aafbe /extensions/source/scanner/sanedlg.cxx |
initial import
Diffstat (limited to 'extensions/source/scanner/sanedlg.cxx')
-rw-r--r-- | extensions/source/scanner/sanedlg.cxx | 1364 |
1 files changed, 1364 insertions, 0 deletions
diff --git a/extensions/source/scanner/sanedlg.cxx b/extensions/source/scanner/sanedlg.cxx new file mode 100644 index 000000000..e929c42c7 --- /dev/null +++ b/extensions/source/scanner/sanedlg.cxx @@ -0,0 +1,1364 @@ +/************************************************************************* + * + * $RCSfile: sanedlg.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 16:16:52 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#include <stdio.h> +#include <stdlib.h> + +#include <vcl/config.hxx> +#include <vcl/msgbox.hxx> +#include <sanedlg.hxx> +#include <sanedlg.hrc> +#include <grid.hxx> + +#define USE_SAVE_STATE +#undef SAVE_ALL_STATES + +ResId SaneResId( ULONG nID ) +{ + static ResMgr* pResMgr = ResMgr::CreateResMgr( "san" MAKE_NUMSTR(SUPD) ); + return ResId( nID, pResMgr ); +} + +SaneDlg::SaneDlg( Window* pParent, Sane& rSane ) : + ModalDialog( pParent, SaneResId( RID_SANE_DIALOG ) ), + mrSane( rSane ), + mpRange( 0 ), + maMapMode( MAP_APPFONT ), + mbIsDragging( FALSE ), + mbDragDrawn( FALSE ), + maOKButton( this, SaneResId( RID_SCAN_OK ) ), + maCancelButton( this, SaneResId( RID_SCAN_CANCEL ) ), + maPreviewButton( this, SaneResId( RID_PREVIEW_BTN ) ), + maDeviceInfoButton( this, SaneResId( RID_DEVICEINFO_BTN ) ), + maPreviewBox( this, SaneResId( RID_PREVIEW_BOX ) ), + maAreaBox( this, SaneResId( RID_SCANAREA_BOX ) ), + maDeviceBoxTxt( this, SaneResId( RID_DEVICE_BOX_TXT ) ), + maScanLeftTxt( this, SaneResId( RID_SCAN_LEFT_TXT ) ), + maScanTopTxt( this, SaneResId( RID_SCAN_TOP_TXT ) ), + maRightTxt( this, SaneResId( RID_SCAN_RIGHT_TXT ) ), + maBottomTxt( this, SaneResId( RID_SCAN_BOTTOM_TXT ) ), + maReslTxt( this, SaneResId( RID_SCAN_RESOLUTION_TXT ) ), + maOptionTitle( this, SaneResId( RID_SCAN_OPTIONTITLE_TXT ) ), + maOptionsTxt( this, SaneResId( RID_SCAN_OPTION_TXT ) ), + maOptionDescTxt( this, SaneResId( RID_SCAN_OPTION_DESC_TXT ) ), + maVectorTxt( this, SaneResId( RID_SCAN_NUMERIC_VECTOR_TXT ) ), + maLeftField( this, SaneResId( RID_SCAN_LEFT_BOX ) ), + maTopField( this, SaneResId( RID_SCAN_TOP_BOX ) ), + maRightField( this, SaneResId( RID_SCAN_RIGHT_BOX ) ), + maBottomField( this, SaneResId( RID_SCAN_BOTTOM_BOX ) ), + maDeviceBox( this, SaneResId( RID_DEVICE_BOX ) ), + maOptionBox( this, SaneResId( RID_SCAN_OPTION_BOX ) ), + maReslBox( this, SaneResId( RID_SCAN_RESOLUTION_BOX ) ), + maBoolCheckBox( this, SaneResId( RID_SCAN_BOOL_OPTION_BOX ) ), + maStringEdit( this, SaneResId( RID_SCAN_STRING_OPTION_EDT ) ), + maQuantumRangeBox( this, SaneResId( RID_SCAN_QUANTUM_RANGE_BOX ) ), + maStringRangeBox( this, SaneResId( RID_SCAN_STRING_RANGE_BOX ) ), + maNumericEdit( this, SaneResId( RID_SCAN_NUMERIC_OPTION_EDT ) ), + maButtonOption( this, SaneResId( RID_SCAN_BUTTON_OPTION_BTN ) ), + maVectorBox( this, SaneResId( RID_SCAN_NUMERIC_VECTOR_BOX ) ), + maAdvancedBox( this, SaneResId( RID_SCAN_ADVANCED_BOX ) ), + maAdvancedTxt( this, SaneResId( RID_SCAN_ADVANCED_TXT ) ) +{ + if( Sane::IsSane() ) + { + InitDevices(); // opens first sane device + DisableOption(); + InitFields(); + } + + maDeviceInfoButton.SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) ); + maPreviewButton.SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) ); + maButtonOption.SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) ); + maDeviceBox.SetSelectHdl( LINK( this, SaneDlg, SelectHdl ) ); + maOptionBox.SetSelectHdl( LINK( this, SaneDlg, OptionsBoxSelectHdl ) ); + maOKButton.SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) ); + maCancelButton.SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) ); + maBoolCheckBox.SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) ); + maStringEdit.SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) ); + maNumericEdit.SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) ); + maVectorBox.SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) ); + maReslBox.SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) ); + maStringRangeBox.SetSelectHdl( LINK( this, SaneDlg, SelectHdl ) ); + maQuantumRangeBox.SetSelectHdl( LINK( this, SaneDlg, SelectHdl ) ); + maLeftField.SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) ); + maRightField.SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) ); + maTopField.SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) ); + maBottomField.SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) ); + maAdvancedBox.SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) ); + + maOldLink = mrSane.SetReloadOptionsHdl( LINK( this, SaneDlg, ReloadSaneOptionsHdl ) ); + + maOptionBox.SetNodeBitmaps( + Bitmap( SaneResId( RID_SCAN_BITMAP_PLUS ) ), + Bitmap( SaneResId( RID_SCAN_BITMAP_MINUS ) ) + ); + maOptionBox.SetWindowBits( WB_HASLINES | + WB_HASBUTTONS | + WB_NOINITIALSELECTION | + WB_HASBUTTONSATROOT | + WB_HASLINESATROOT + ); + FreeResource(); +} + +SaneDlg::~SaneDlg() +{ +} + +short SaneDlg::Execute() +{ + if( ! Sane::IsSane() ) + { + ErrorBox aErrorBox( NULL, WB_OK | WB_DEF_OK, + String( SaneResId( RID_SANE_NOSANELIB_TXT ) ) ); + aErrorBox.Execute(); + return FALSE; + } + LoadState(); + return ModalDialog::Execute(); +} + +void SaneDlg::InitDevices() +{ + if( ! Sane::IsSane() ) + return; + + if( mrSane.IsOpen() ) + mrSane.Close(); + mrSane.ReloadDevices(); + maDeviceBox.Clear(); + for( int i = 0; i < Sane::CountDevices(); i++ ) + maDeviceBox.InsertEntry( Sane::GetName( i ) ); + if( Sane::CountDevices() ) + { + mrSane.Open( 0 ); + maDeviceBox.SelectEntry( Sane::GetName( 0 ) ); + + } +} + +void SaneDlg::InitFields() +{ + if( ! Sane::IsSane() ) + return; + + int nOption, i, n, nValue; + double fValue; + BOOL bSuccess = FALSE; + char *ppSpecialOptions[] = { + "resolution", + "tl-x", + "tl-y", + "br-x", + "br-y", + "preview" + }; + + maReslBox.Clear(); + maMinTopLeft = Point( 0, 0 ); + maMaxBottomRight = Point( PREVIEW_WIDTH, PREVIEW_HEIGHT ); + + if( ! mrSane.IsOpen() ) + return; + + // set Resolution + nOption = mrSane.GetOptionByName( "resolution" ); + if( nOption != -1 ) + { + double fRes; + + bSuccess = mrSane.GetOptionValue( nOption, fRes ); + if( bSuccess ) + { + maReslBox.Enable( TRUE ); + + maReslBox.SetValue( (long)fRes ); + double *pDouble = NULL; + nValue = mrSane.GetRange( nOption, pDouble ); + if( nValue > -1 ) + { + if( nValue ) + { + maReslBox.SetMin( (long)pDouble[0] ); + maReslBox.SetMax( (long)pDouble[ nValue-1 ] ); + for( i=0; i<nValue; i++ ) + { + if( i == 0 || i == nValue-1 || ! ( ((int)pDouble[i]) % 20) ) + maReslBox.InsertValue( (long)pDouble[i] ); + } + } + else + { + maReslBox.SetMin( (long)pDouble[0] ); + maReslBox.SetMax( (long)pDouble[1] ); + maReslBox.InsertValue( (long)pDouble[0] ); + maReslBox.InsertValue( (long)pDouble[1] ); + } + if( pDouble ) + delete pDouble; + } + else + maReslBox.Enable( FALSE ); + } + } + else + maReslBox.Enable( FALSE ); + + // set scan area + for( i = 0; i < 4; i++ ) + { + char *pOptionName; + MetricField* pField; + switch( i ) + { + case 0: + pOptionName = "tl-x"; + pField = &maLeftField; + break; + case 1: + pOptionName = "tl-y"; + pField = &maTopField; + break; + case 2: + pOptionName = "br-x"; + pField = &maRightField; + break; + case 3: + pOptionName = "br-y"; + pField = &maBottomField; + } + nOption = mrSane.GetOptionByName( pOptionName ); + bSuccess = FALSE; + if( nOption != -1 ) + { + bSuccess = mrSane.GetOptionValue( nOption, fValue, 0 ); + if( bSuccess ) + { + if( mrSane.GetOptionUnit( nOption ) == SANE_UNIT_MM ) + { + pField->SetUnit( FUNIT_MM ); + pField->SetValue( (int)fValue, FUNIT_MM ); + } + else // SANE_UNIT_PIXEL + { + pField->SetValue( (int)fValue, FUNIT_CUSTOM ); + pField->SetCustomUnitText( String::CreateFromAscii( "Pixel" ) ); + } + switch( i ) { + case 0: maTopLeft.X() = (int)fValue;break; + case 1: maTopLeft.Y() = (int)fValue;break; + case 2: maBottomRight.X() = (int)fValue;break; + case 3: maBottomRight.Y() = (int)fValue;break; + } + } + double *pDouble = NULL; + nValue = mrSane.GetRange( nOption, pDouble ); + if( nValue > -1 ) + { + if( pDouble ) + { + pField->SetMin( (long)pDouble[0] ); + if( nValue ) + pField->SetMax( (long)pDouble[ nValue-1 ] ); + else + pField->SetMax( (long)pDouble[ 1 ] ); + delete pDouble; + } + switch( i ) { + case 0: maMinTopLeft.X() = pField->GetMin();break; + case 1: maMinTopLeft.Y() = pField->GetMin();break; + case 2: maMaxBottomRight.X() = pField->GetMax();break; + case 3: maMaxBottomRight.Y() = pField->GetMax();break; + } + } + else + { + switch( i ) { + case 0: maMinTopLeft.X() = (int)fValue;break; + case 1: maMinTopLeft.Y() = (int)fValue;break; + case 2: maMaxBottomRight.X() = (int)fValue;break; + case 3: maMaxBottomRight.Y() = (int)fValue;break; + } + } + pField->Enable( TRUE ); + } + else + pField->Enable( FALSE ); + } + maTopLeft = GetPixelPos( maTopLeft ); + maBottomRight = GetPixelPos( maBottomRight ); + maPreviewRect = Rectangle( maTopLeft, + Size( maBottomRight.X() - maTopLeft.X(), + maBottomRight.Y() - maTopLeft.Y() ) + ); + // fill OptionBox + maOptionBox.Clear(); + SvLBoxEntry* pParentEntry = 0; + BOOL bGroupRejected = FALSE; + for( i = 1; i < mrSane.CountOptions(); i++ ) + { + String aOption=mrSane.GetOptionName( i ); + BOOL bInsertAdvanced = + mrSane.GetOptionCap( i ) & SANE_CAP_ADVANCED && + ! maAdvancedBox.IsChecked() ? FALSE : TRUE; + if( mrSane.GetOptionType( i ) == SANE_TYPE_GROUP ) + { + if( bInsertAdvanced ) + { + aOption = mrSane.GetOptionTitle( i ); + pParentEntry = maOptionBox.InsertEntry( aOption ); + bGroupRejected = FALSE; + } + else + bGroupRejected = TRUE; + } + else if( aOption.Len() && + ! ( mrSane.GetOptionCap( i ) & + ( + SANE_CAP_HARD_SELECT | + SANE_CAP_INACTIVE + ) ) && + bInsertAdvanced && ! bGroupRejected ) + { + BOOL bIsSpecial = FALSE; + for( n = 0; !bIsSpecial && + n < sizeof(ppSpecialOptions)/sizeof(ppSpecialOptions[0]); n++ ) + { + if( aOption.EqualsAscii( ppSpecialOptions[n] ) ) + bIsSpecial=TRUE; + } + if( ! bIsSpecial ) + { + if( pParentEntry ) + maOptionBox.InsertEntry( aOption, pParentEntry ); + else + maOptionBox.InsertEntry( aOption ); + } + } + } +} + +IMPL_LINK( SaneDlg, ClickBtnHdl, Button*, pButton ) +{ + if( mrSane.IsOpen() ) + { + if( pButton == &maDeviceInfoButton ) + { + String aString( SaneResId( RID_SANE_DEVICEINFO_TXT ) ); + String aSR( RTL_CONSTASCII_USTRINGPARAM( "%s" ) ); + aString.SearchAndReplace( aSR, Sane::GetName( mrSane.GetDeviceNumber() ) ); + aString.SearchAndReplace( aSR, Sane::GetVendor( mrSane.GetDeviceNumber() ) ); + aString.SearchAndReplace( aSR, Sane::GetModel( mrSane.GetDeviceNumber() ) ); + aString.SearchAndReplace( aSR, Sane::GetType( mrSane.GetDeviceNumber() ) ); + InfoBox aInfoBox( this, aString ); + aInfoBox.Execute(); + } + else if( pButton == &maPreviewButton ) + AcquirePreview(); + else if( pButton == &maBoolCheckBox ) + { + mrSane.SetOptionValue( mnCurrentOption, + maBoolCheckBox.IsChecked() ? + (BOOL)TRUE : (BOOL)FALSE ); + } + else if( pButton == &maButtonOption ) + { + mrSane.ActivateButtonOption( mnCurrentOption ); + } + else if( pButton == &maAdvancedBox ) + { + ReloadSaneOptionsHdl( NULL ); + } + } + if( pButton == &maOKButton ) + { + double fRes = (double)maReslBox.GetValue(); + SetAdjustedNumericalValue( "resolution", fRes ); + mrSane.SetReloadOptionsHdl( maOldLink ); + UpdateScanArea( TRUE ); + SaveState(); + EndDialog( mrSane.IsOpen() ? 1 : 0 ); + } + else if( pButton == &maCancelButton ) + { + mrSane.SetReloadOptionsHdl( maOldLink ); + mrSane.Close(); + EndDialog( 0 ); + } + return 0; +} + +IMPL_LINK( SaneDlg, SelectHdl, ListBox*, pListBox ) +{ + if( pListBox == &maDeviceBox && Sane::IsSane() && Sane::CountDevices() ) + { + String aNewDevice = maDeviceBox.GetSelectEntry(); + int nNumber; + if( aNewDevice.Equals( Sane::GetName( nNumber = mrSane.GetDeviceNumber() ) ) ) + { + mrSane.Close(); + mrSane.Open( nNumber ); + InitFields(); + } + } + if( mrSane.IsOpen() ) + { + if( pListBox == &maQuantumRangeBox ) + { + ByteString aValue( maQuantumRangeBox.GetSelectEntry(), gsl_getSystemTextEncoding() ); + double fValue = atof( aValue.GetBuffer() ); + mrSane.SetOptionValue( mnCurrentOption, fValue, mnCurrentElement ); + } + else if( pListBox == &maStringRangeBox ) + { + mrSane.SetOptionValue( mnCurrentOption, maStringRangeBox.GetSelectEntry() ); + } + } + return 0; +} + +IMPL_LINK( SaneDlg, OptionsBoxSelectHdl, SvTreeListBox*, pBox ) +{ + if( pBox == &maOptionBox && Sane::IsSane() ) + { + String aOption = + maOptionBox.GetEntryText( maOptionBox.FirstSelected() ); + int nOption = mrSane.GetOptionByName( ByteString( aOption, gsl_getSystemTextEncoding() ).GetBuffer() ); + if( nOption != -1 && nOption != mnCurrentOption ) + { + DisableOption(); + mnCurrentOption = nOption; + maOptionTitle.SetText( mrSane.GetOptionTitle( mnCurrentOption ) ); + SANE_Value_Type nType = mrSane.GetOptionType( mnCurrentOption ); + SANE_Constraint_Type nConstraint; + switch( nType ) + { + case SANE_TYPE_BOOL: EstablishBoolOption();break; + case SANE_TYPE_STRING: + nConstraint = mrSane.GetOptionConstraintType( mnCurrentOption ); + if( nConstraint == SANE_CONSTRAINT_STRING_LIST ) + EstablishStringRange(); + else + EstablishStringOption(); + break; + case SANE_TYPE_FIXED: + case SANE_TYPE_INT: + { + nConstraint = mrSane.GetOptionConstraintType( mnCurrentOption ); + mnCurrentElement = 0; + if( nConstraint == SANE_CONSTRAINT_RANGE || + nConstraint == SANE_CONSTRAINT_WORD_LIST ) + EstablishQuantumRange(); + else + { + mfMin = mfMax = 0.0; + EstablishNumericOption(); + } + int nElements = mrSane.GetOptionElements( mnCurrentOption ); + if( nElements > 1 ) + { + if( nElements <= 10 ) + { + maVectorBox.SetValue( 1 ); + maVectorBox.SetMin( 1 ); + maVectorBox.SetMax( + mrSane.GetOptionElements( mnCurrentOption ) ); + maVectorBox.Show( TRUE ); + maVectorTxt.Show( TRUE ); + } + else + { + double* x = new double[ nElements ]; + double* y = new double[ nElements ]; + for( int i = 0; i < nElements; i++ ) + { + x[ i ] = (double)i; + mrSane.GetOptionValue( mnCurrentOption, x[i], i ); + } + GridWindow aGrid( x, y, nElements, this ); + aGrid.SetText( mrSane.GetOptionName( mnCurrentOption ) ); + aGrid.setBoundings( 0, mfMin, nElements, mfMax ); + aGrid.Execute(); + + delete x; + delete y; + } + } + } + break; + case SANE_TYPE_BUTTON: + EstablishButtonOption(); + break; + default: break; + } + } + } + return 0; +} + +IMPL_LINK( SaneDlg, ModifyHdl, Edit*, pEdit ) +{ + if( mrSane.IsOpen() ) + { + if( pEdit == &maStringEdit ) + { + mrSane.SetOptionValue( mnCurrentOption, maStringEdit.GetText() ); + } + else if( pEdit == &maReslBox ) + { + double fRes = (double)maReslBox.GetValue(); + int nOption = mrSane.GetOptionByName( "resolution" ); + if( nOption != -1 ) + { + double* pDouble = NULL; + int nValues = mrSane.GetRange( nOption, pDouble ); + if( nValues > 0 ) + { + int i; + for( i = 0; i < nValues; i++ ) + { + if( fRes == pDouble[i] ) + break; + } + if( i >= nValues ) + fRes = pDouble[0]; + } + else if( nValues == 0 ) + { + if( fRes < pDouble[ 0 ] ) + fRes = pDouble[ 0 ]; + if( fRes > pDouble[ 1 ] ) + fRes = pDouble[ 1 ]; + } + maReslBox.SetValue( (ULONG)fRes ); + } + } + else if( pEdit == &maNumericEdit ) + { + double fValue; + char pBuf[256]; + ByteString aContents( maNumericEdit.GetText(), gsl_getSystemTextEncoding() ); + fValue = atof( aContents.GetBuffer() ); + if( mfMin != mfMax && ( fValue < mfMin || fValue > mfMax ) ) + { + if( fValue < mfMin ) + fValue = mfMin; + else if( fValue > mfMax ) + fValue = mfMax; + sprintf( pBuf, "%g", fValue ); + maNumericEdit.SetText( String( pBuf, gsl_getSystemTextEncoding() ) ); + } + mrSane.SetOptionValue( mnCurrentOption, fValue, mnCurrentElement ); + } + else if( pEdit == &maVectorBox ) + { + char pBuf[256]; + mnCurrentElement = maVectorBox.GetValue()-1; + double fValue; + mrSane.GetOptionValue( mnCurrentOption, fValue, mnCurrentElement ); + sprintf( pBuf, "%g", fValue ); + String aValue( pBuf, gsl_getSystemTextEncoding() ); + maNumericEdit.SetText( aValue ); + maQuantumRangeBox.SelectEntry( aValue ); + } + else if( pEdit == &maTopField ) + { + Point aPoint( 0, maTopField.GetValue() ); + aPoint = GetPixelPos( aPoint ); + maTopLeft.Y() = aPoint.Y(); + DrawDrag(); + } + else if( pEdit == &maLeftField ) + { + Point aPoint( maLeftField.GetValue(), 0 ); + aPoint = GetPixelPos( aPoint ); + maTopLeft.X() = aPoint.X(); + DrawDrag(); + } + else if( pEdit == &maBottomField ) + { + Point aPoint( 0, maBottomField.GetValue() ); + aPoint = GetPixelPos( aPoint ); + maBottomRight.Y() = aPoint.Y(); + DrawDrag(); + } + else if( pEdit == &maRightField ) + { + Point aPoint( maRightField.GetValue(), 0 ); + aPoint = GetPixelPos( aPoint ); + maBottomRight.X() = aPoint.X(); + DrawDrag(); + } + } + return 0; +} + +IMPL_LINK( SaneDlg, ReloadSaneOptionsHdl, Sane*, pSane ) +{ + mnCurrentOption = -1; + mnCurrentElement = 0; + DisableOption(); + InitFields(); + Rectangle aDummyRect( Point( 0, 0 ), GetSizePixel() ); + Paint( aDummyRect ); + return 0; +} + +void SaneDlg::AcquirePreview() +{ + if( ! mrSane.IsOpen() ) + return; + + UpdateScanArea( TRUE ); + // set small resolution for preview + double fResl = (double)maReslBox.GetValue(); + SetAdjustedNumericalValue( "resolution", 30.0 ); + + int nOption = mrSane.GetOptionByName( "preview" ); + if( nOption == -1 ) + { + String aString( SaneResId( RID_SANE_NORESOLUTIONOPTION_TXT ) ); + WarningBox aBox( this, WB_OK_CANCEL | WB_DEF_OK, aString ); + if( aBox.Execute() == RET_CANCEL ) + return; + } + else + mrSane.SetOptionValue( nOption, (BOOL)TRUE ); + + BitmapTransporter aTransporter; + if( ! mrSane.Start( aTransporter ) ) + { + ErrorBox aErrorBox( this, WB_OK | WB_DEF_OK, + String( SaneResId( RID_SANE_SCANERROR_TXT ) ) ); + aErrorBox.Execute(); + } + else + { +#ifdef DEBUG + aTransporter.getStream().Seek( STREAM_SEEK_TO_END ); + fprintf( stderr, "Previewbitmapstream contains %d bytes\n", aTransporter.getStream().Tell() ); +#endif + aTransporter.getStream().Seek( STREAM_SEEK_TO_BEGIN ); + maPreviewBitmap.Read( aTransporter.getStream(), TRUE ); + } + + SetAdjustedNumericalValue( "resolution", fResl ); + maReslBox.SetValue( (ULONG)fResl ); + + maPreviewRect = Rectangle( maTopLeft, + Size( maBottomRight.X() - maTopLeft.X(), + maBottomRight.Y() - maTopLeft.Y() ) + ); + Paint( Rectangle( Point( 0, 0 ), GetSizePixel() ) ); +} + +void SaneDlg::Paint( const Rectangle& rRect ) +{ + SetMapMode( maMapMode ); + SetFillColor( Color( COL_WHITE ) ); + SetLineColor( Color( COL_WHITE ) ); + DrawRect( Rectangle( Point( PREVIEW_UPPER_LEFT, PREVIEW_UPPER_TOP ), + Size( PREVIEW_WIDTH, PREVIEW_HEIGHT ) ) ); + SetMapMode( MapMode( MAP_PIXEL ) ); + // check for sane values + DrawBitmap( maPreviewRect.TopLeft(), maPreviewRect.GetSize(), + maPreviewBitmap ); + + mbDragDrawn = FALSE; + DrawDrag(); + + ModalDialog::Paint( rRect ); +} + +void SaneDlg::DisableOption() +{ + maBoolCheckBox.Show( FALSE ); + maStringEdit.Show( FALSE ); + maNumericEdit.Show( FALSE ); + maQuantumRangeBox.Show( FALSE ); + maStringRangeBox.Show( FALSE ); + maButtonOption.Show( FALSE ); + maVectorBox.Show( FALSE ); + maVectorTxt.Show( FALSE ); + maOptionDescTxt.Show( FALSE ); +} + +void SaneDlg::EstablishBoolOption() +{ + BOOL bSuccess, bValue; + + bSuccess = mrSane.GetOptionValue( mnCurrentOption, bValue ); + if( bSuccess ) + { + maOptionDescTxt.SetText( mrSane.GetOptionName( mnCurrentOption ) ); + maOptionDescTxt.Show( TRUE ); + maBoolCheckBox.Check( bValue ); + maBoolCheckBox.Show( TRUE ); + } +} + +void SaneDlg::EstablishStringOption() +{ + BOOL bSuccess; + ByteString aValue; + + bSuccess = mrSane.GetOptionValue( mnCurrentOption, aValue ); + if( bSuccess ) + { + maOptionDescTxt.SetText( mrSane.GetOptionName( mnCurrentOption ) ); + maOptionDescTxt.Show( TRUE ); + maStringEdit.SetText( String( aValue, gsl_getSystemTextEncoding() ) ); + maStringEdit.Show( TRUE ); + } +} + +void SaneDlg::EstablishStringRange() +{ + const char** ppStrings = mrSane.GetStringConstraint( mnCurrentOption ); + maStringRangeBox.Clear(); + for( int i = 0; ppStrings[i] != 0; i++ ) + maStringRangeBox.InsertEntry( String( ppStrings[i], gsl_getSystemTextEncoding() ) ); + ByteString aValue; + mrSane.GetOptionValue( mnCurrentOption, aValue ); + maStringRangeBox.SelectEntry( String( aValue, gsl_getSystemTextEncoding() ) ); + maStringRangeBox.Show( TRUE ); + maOptionDescTxt.SetText( mrSane.GetOptionName( mnCurrentOption ) ); + maOptionDescTxt.Show( TRUE ); +} + +void SaneDlg::EstablishQuantumRange() +{ + if( mpRange ) + { + delete mpRange; + mpRange = 0; + } + int nValues = mrSane.GetRange( mnCurrentOption, mpRange ); + if( nValues == 0 ) + { + mfMin = mpRange[ 0 ]; + mfMax = mpRange[ 1 ]; + delete mpRange; + mpRange = 0; + EstablishNumericOption(); + } + else if( nValues > 0 ) + { + char pBuf[ 256 ]; + maQuantumRangeBox.Clear(); + mfMin = mpRange[ 0 ]; + mfMax = mpRange[ nValues-1 ]; + for( int i = 0; i < nValues; i++ ) + { + sprintf( pBuf, "%g", mpRange[ i ] ); + maQuantumRangeBox.InsertEntry( String( pBuf, gsl_getSystemTextEncoding() ) ); + } + double fValue; + if( mrSane.GetOptionValue( mnCurrentOption, fValue, mnCurrentElement ) ) + { + sprintf( pBuf, "%g", fValue ); + maQuantumRangeBox.SelectEntry( String( pBuf, gsl_getSystemTextEncoding() ) ); + } + maQuantumRangeBox.Show( TRUE ); + String aText( mrSane.GetOptionName( mnCurrentOption ) ); + aText += ' '; + aText += mrSane.GetOptionUnitName( mnCurrentOption ); + maOptionDescTxt.SetText( aText ); + maOptionDescTxt.Show( TRUE ); + } +} + +void SaneDlg::EstablishNumericOption() +{ + BOOL bSuccess; + double fValue; + + bSuccess = mrSane.GetOptionValue( mnCurrentOption, fValue ); + if( ! bSuccess ) + return; + + char pBuf[256]; + String aText( mrSane.GetOptionName( mnCurrentOption ) ); + aText += ' '; + aText += mrSane.GetOptionUnitName( mnCurrentOption ); + if( mfMin != mfMax ) + { + sprintf( pBuf, " < %g ; %g >", mfMin, mfMax ); + aText += String( pBuf, gsl_getSystemTextEncoding() ); + } + maOptionDescTxt.SetText( aText ); + maOptionDescTxt.Show( TRUE ); + sprintf( pBuf, "%g", fValue ); + maNumericEdit.SetText( String( pBuf, gsl_getSystemTextEncoding() ) ); + maNumericEdit.Show( TRUE ); +} + +void SaneDlg::EstablishButtonOption() +{ + maOptionDescTxt.SetText( mrSane.GetOptionName( mnCurrentOption ) ); + maOptionDescTxt.Show( TRUE ); + maButtonOption.Show( TRUE ); +} + +#define RECT_SIZE_PIX 7 + +void SaneDlg::MouseMove( const MouseEvent& rMEvt ) +{ + if( mbIsDragging ) + { + Point aMousePos = rMEvt.GetPosPixel(); + // move into valid area + Point aLogicPos = GetLogicPos( aMousePos ); + aMousePos = GetPixelPos( aLogicPos ); + switch( meDragDirection ) + { + case TopLeft: maTopLeft = aMousePos; break; + case Top: maTopLeft.Y() = aMousePos.Y(); break; + case TopRight: + maTopLeft.Y() = aMousePos.Y(); + maBottomRight.X() = aMousePos.X(); + break; + case Right: maBottomRight.X() = aMousePos.X(); break; + case BottomRight: maBottomRight = aMousePos; break; + case Bottom: maBottomRight.Y() = aMousePos.Y(); break; + case BottomLeft: + maTopLeft.X() = aMousePos.X(); + maBottomRight.Y() = aMousePos.Y(); + break; + case Left: maTopLeft.X() = aMousePos.X(); break; + default: break; + } + int nSwap; + if( maTopLeft.X() > maBottomRight.X() ) + { + nSwap = maTopLeft.X(); + maTopLeft.X() = maBottomRight.X(); + maBottomRight.X() = nSwap; + } + if( maTopLeft.Y() > maBottomRight.Y() ) + { + nSwap = maTopLeft.Y(); + maTopLeft.Y() = maBottomRight.Y(); + maBottomRight.Y() = nSwap; + } + DrawDrag(); + UpdateScanArea( FALSE ); + } + ModalDialog::MouseMove( rMEvt ); +} + +void SaneDlg::MouseButtonDown( const MouseEvent& rMEvt ) +{ + Point aMousePixel = rMEvt.GetPosPixel(); + + if( ! mbIsDragging ) + { + int nMiddleX = ( maBottomRight.X() - maTopLeft.X() ) / 2 - RECT_SIZE_PIX/2 + maTopLeft.X(); + int nMiddleY = ( maBottomRight.Y() - maTopLeft.Y() ) / 2 - RECT_SIZE_PIX/2 + maTopLeft.Y(); + if( aMousePixel.Y() >= maTopLeft.Y() && + aMousePixel.Y() < maTopLeft.Y() + RECT_SIZE_PIX ) + { + if( aMousePixel.X() >= maTopLeft.X() && + aMousePixel.X() < maTopLeft.X() + RECT_SIZE_PIX ) + { + meDragDirection = TopLeft; + aMousePixel = maTopLeft; + mbIsDragging = TRUE; + } + else if( aMousePixel.X() >= nMiddleX && + aMousePixel.X() < nMiddleX + RECT_SIZE_PIX ) + { + meDragDirection = Top; + aMousePixel.Y() = maTopLeft.Y(); + mbIsDragging = TRUE; + } + else if( aMousePixel.X() > maBottomRight.X() - RECT_SIZE_PIX && + aMousePixel.X() <= maBottomRight.X() ) + { + meDragDirection = TopRight; + aMousePixel = Point( maBottomRight.X(), maTopLeft.Y() ); + mbIsDragging = TRUE; + } + } + else if( aMousePixel.Y() >= nMiddleY && + aMousePixel.Y() < nMiddleY + RECT_SIZE_PIX ) + { + if( aMousePixel.X() >= maTopLeft.X() && + aMousePixel.X() < maTopLeft.X() + RECT_SIZE_PIX ) + { + meDragDirection = Left; + aMousePixel.X() = maTopLeft.X(); + mbIsDragging = TRUE; + } + else if( aMousePixel.X() > maBottomRight.X() - RECT_SIZE_PIX && + aMousePixel.X() <= maBottomRight.X() ) + { + meDragDirection = Right; + aMousePixel.X() = maBottomRight.X(); + mbIsDragging = TRUE; + } + } + else if( aMousePixel.Y() <= maBottomRight.Y() && + aMousePixel.Y() > maBottomRight.Y() - RECT_SIZE_PIX ) + { + if( aMousePixel.X() >= maTopLeft.X() && + aMousePixel.X() < maTopLeft.X() + RECT_SIZE_PIX ) + { + meDragDirection = BottomLeft; + aMousePixel = Point( maTopLeft.X(), maBottomRight.Y() ); + mbIsDragging = TRUE; + } + else if( aMousePixel.X() >= nMiddleX && + aMousePixel.X() < nMiddleX + RECT_SIZE_PIX ) + { + meDragDirection = Bottom; + aMousePixel.Y() = maBottomRight.Y(); + mbIsDragging = TRUE; + } + else if( aMousePixel.X() > maBottomRight.X() - RECT_SIZE_PIX && + aMousePixel.X() <= maBottomRight.X() ) + { + meDragDirection = BottomRight; + aMousePixel = maBottomRight; + mbIsDragging = TRUE; + } + } + } + if( mbIsDragging ) + { + SetPointerPosPixel( aMousePixel ); + DrawDrag(); + } + ModalDialog::MouseButtonDown( rMEvt ); +} + +void SaneDlg::MouseButtonUp( const MouseEvent& rMEvt ) +{ + if( mbIsDragging ) + { + UpdateScanArea( TRUE ); + } + mbIsDragging = FALSE; + + ModalDialog::MouseButtonUp( rMEvt ); +} + +void SaneDlg::DrawRectangles( Point& rUL, Point& rBR ) +{ + int nMiddleX, nMiddleY; + Point aBL, aUR; + + aUR = Point( rBR.X(), rUL.Y() ); + aBL = Point( rUL.X(), rBR.Y() ); + nMiddleX = ( rBR.X() - rUL.X() ) / 2 + rUL.X(); + nMiddleY = ( rBR.Y() - rUL.Y() ) / 2 + rUL.Y(); + + DrawLine( rUL, aBL ); + DrawLine( aBL, rBR ); + DrawLine( rBR, aUR ); + DrawLine( aUR, rUL ); + DrawRect( Rectangle( rUL, Size( RECT_SIZE_PIX,RECT_SIZE_PIX ) ) ); + DrawRect( Rectangle( aBL, Size( RECT_SIZE_PIX, -RECT_SIZE_PIX ) ) ); + DrawRect( Rectangle( rBR, Size( -RECT_SIZE_PIX, -RECT_SIZE_PIX ) ) ); + DrawRect( Rectangle( aUR, Size( -RECT_SIZE_PIX, RECT_SIZE_PIX ) ) ); + DrawRect( Rectangle( Point( nMiddleX - RECT_SIZE_PIX/2, rUL.Y() ), Size( RECT_SIZE_PIX, RECT_SIZE_PIX ) ) ); + DrawRect( Rectangle( Point( nMiddleX - RECT_SIZE_PIX/2, rBR.Y() ), Size( RECT_SIZE_PIX, -RECT_SIZE_PIX ) ) ); + DrawRect( Rectangle( Point( rUL.X(), nMiddleY - RECT_SIZE_PIX/2 ), Size( RECT_SIZE_PIX, RECT_SIZE_PIX ) ) ); + DrawRect( Rectangle( Point( rBR.X(), nMiddleY - RECT_SIZE_PIX/2 ), Size( -RECT_SIZE_PIX, RECT_SIZE_PIX ) ) ); +} + +void SaneDlg::DrawDrag() +{ + static Point aLastUL, aLastBR; + + RasterOp eROP = GetRasterOp(); + SetRasterOp( ROP_INVERT ); + SetMapMode( MapMode( MAP_PIXEL ) ); + + if( mbDragDrawn ) + DrawRectangles( aLastUL, aLastBR ); + + aLastUL = maTopLeft; + aLastBR = maBottomRight; + DrawRectangles( maTopLeft, maBottomRight ); + + mbDragDrawn = TRUE; + SetRasterOp( eROP ); + SetMapMode( maMapMode ); +} + +Point SaneDlg::GetPixelPos( const Point& rIn ) +{ + Point aConvert( + ( ( rIn.X() * PREVIEW_WIDTH ) / + ( maMaxBottomRight.X() - maMinTopLeft.X() ) ) + + PREVIEW_UPPER_LEFT, + ( ( rIn.Y() * PREVIEW_HEIGHT ) + / ( maMaxBottomRight.Y() - maMinTopLeft.Y() ) ) + + PREVIEW_UPPER_TOP ); + + return LogicToPixel( aConvert, maMapMode ); +} + +Point SaneDlg::GetLogicPos( const Point& rIn ) +{ + Point aConvert = PixelToLogic( rIn, maMapMode ); + aConvert.X() -= PREVIEW_UPPER_LEFT; + aConvert.Y() -= PREVIEW_UPPER_TOP; + if( aConvert.X() < 0 ) + aConvert.X() = 0; + if( aConvert.X() >= PREVIEW_WIDTH ) + aConvert.X() = PREVIEW_WIDTH-1; + if( aConvert.Y() < 0 ) + aConvert.Y() = 0; + if( aConvert.Y() >= PREVIEW_HEIGHT ) + aConvert.Y() = PREVIEW_HEIGHT-1; + + aConvert.X() *= ( maMaxBottomRight.X() - maMinTopLeft.X() ); + aConvert.X() /= PREVIEW_WIDTH; + aConvert.Y() *= ( maMaxBottomRight.Y() - maMinTopLeft.Y() ); + aConvert.Y() /= PREVIEW_HEIGHT; + return aConvert; +} + +void SaneDlg::UpdateScanArea( BOOL bSend ) +{ + Point aUL = GetLogicPos( maTopLeft ); + Point aBR = GetLogicPos( maBottomRight ); + + maLeftField.SetValue( aUL.X() ); + maTopField.SetValue( aUL.Y() ); + maRightField.SetValue( aBR.X() ); + maBottomField.SetValue( aBR.Y() ); + + if( ! bSend ) + return; + + if( mrSane.IsOpen() ) + { + SetAdjustedNumericalValue( "tl-x", (double)aUL.X() ); + SetAdjustedNumericalValue( "tl-y", (double)aUL.Y() ); + SetAdjustedNumericalValue( "br-x", (double)aBR.X() ); + SetAdjustedNumericalValue( "br-y", (double)aBR.Y() ); + } +} + +BOOL SaneDlg::LoadState() +{ +#ifdef USE_SAVE_STATE + int i; + + if( ! Sane::IsSane() ) + return FALSE; + + const char* pEnv = getenv("HOME"); + String aFileName( pEnv ? pEnv : "", gsl_getSystemTextEncoding() ); + aFileName += String( RTL_CONSTASCII_USTRINGPARAM( "/.so_sane_state" ) ); + Config aConfig( aFileName ); + if( ! aConfig.HasGroup( "SANE" ) ) + return FALSE; + + aConfig.SetGroup( "SANE" ); + ByteString aString = aConfig.ReadKey( "SO_LastSaneDevice" ); + for( i = 0; i < Sane::CountDevices() && ! aString.Equals( ByteString( Sane::GetName( i ), gsl_getSystemTextEncoding() ) ); i++ ) ; + if( i == Sane::CountDevices() ) + return FALSE; + + mrSane.Close(); + mrSane.Open( aString.GetBuffer() ); + + DisableOption(); + InitFields(); + + if( mrSane.IsOpen() ) + { + int iMax = aConfig.GetKeyCount(); + for( i = 0; i < iMax; i++ ) + { + aString = aConfig.GetKeyName( i ); + ByteString aValue = aConfig.ReadKey( i ); + int nOption = mrSane.GetOptionByName( aString.GetBuffer() ); + if( nOption != -1 ) + { + if( aValue.CompareTo( "BOOL=", 5 ) == COMPARE_EQUAL ) + { + aValue.Erase( 0, 5 ); + BOOL aBOOL = (BOOL)aValue.ToInt32(); + mrSane.SetOptionValue( nOption, aBOOL ); + } + else if( aValue.CompareTo( "STRING=", 7 ) == COMPARE_EQUAL ) + { + aValue.Erase( 0, 7 ); + mrSane.SetOptionValue( nOption, String( aValue, gsl_getSystemTextEncoding() ) ); + } + else if( aValue.CompareTo( "NUMERIC=", 8 ) == COMPARE_EQUAL ) + { + aValue.Erase( 0, 8 ); + int nMax = aValue.GetTokenCount( ':' ); + double fValue=0.0; + for( int n = 0; n < nMax ; n++ ) + { + ByteString aSub = aValue.GetToken( n, ':' ); + sscanf( aSub.GetBuffer(), "%lg", &fValue ); + SetAdjustedNumericalValue( aString.GetBuffer(), fValue, n ); + } + } + } + } + } + + DisableOption(); + InitFields(); + + return TRUE; +#else + return FALSE; +#endif +} + +void SaneDlg::SaveState() +{ +#ifdef USE_SAVE_STATE + if( ! Sane::IsSane() ) + return; + + const char* pEnv = getenv( "HOME" ); + String aFileName( pEnv ? pEnv : "", gsl_getSystemTextEncoding() ); + aFileName.AppendAscii( "/.so_sane_state" ); + + Config aConfig( aFileName ); + aConfig.DeleteGroup( "SANE" ); + aConfig.SetGroup( "SANE" ); + aConfig.WriteKey( "SO_LastSANEDevice", ByteString( maDeviceBox.GetSelectEntry(), RTL_TEXTENCODING_UTF8 ) ); + +#ifdef SAVE_ALL_STATES + for( int i = 1; i < mrSane.CountOptions(); i++ ) + { + String aOption=mrSane.GetOptionName( i ); + SANE_Value_Type nType = mrSane.GetOptionType( i ); + switch( nType ) + { + case SANE_TYPE_BOOL: + { + BOOL bValue; + if( mrSane.GetOptionValue( i, bValue ) ) + { + ByteString aString( "BOOL=" ); + aString += (ULONG)bValue; + aConfig.WriteKey( aOption, aString ); + } + } + break; + case SANE_TYPE_STRING: + { + String aString( "STRING=" ); + String aValue; + if( mrSane.GetOptionValue( i, aValue ) ) + { + aString += aValue; + aConfig.WriteKey( aOption, aString ); + } + } + break; + case SANE_TYPE_FIXED: + case SANE_TYPE_INT: + { + String aString( "NUMERIC=" ); + double fValue; + char buf[256]; + for( int n = 0; n < mrSane.GetOptionElements( i ); n++ ) + { + if( ! mrSane.GetOptionValue( i, fValue, n ) ) + break; + if( n > 0 ) + aString += ":"; + sprintf( buf, "%lg", fValue ); + aString += buf; + } + if( n >= mrSane.GetOptionElements( i ) ) + aConfig.WriteKey( aOption, aString ); + } + break; + default: + break; + } + } +#else + static char* pSaveOptions[] = { + "resolution", + "tl-x", + "tl-y", + "br-x", + "br-y" + }; + for( int i = 0; + i < (sizeof(pSaveOptions)/sizeof(pSaveOptions[0])); + i++ ) + { + ByteString aOption = pSaveOptions[i]; + int nOption = mrSane.GetOptionByName( pSaveOptions[i] ); + if( nOption > -1 ) + { + SANE_Value_Type nType = mrSane.GetOptionType( nOption ); + switch( nType ) + { + case SANE_TYPE_BOOL: + { + BOOL bValue; + if( mrSane.GetOptionValue( nOption, bValue ) ) + { + ByteString aString( "BOOL=" ); + aString += (ULONG)bValue; + aConfig.WriteKey( aOption, aString ); + } + } + break; + case SANE_TYPE_STRING: + { + ByteString aString( "STRING=" ); + ByteString aValue; + if( mrSane.GetOptionValue( nOption, aValue ) ) + { + aString += aValue; + aConfig.WriteKey( aOption, aString ); + } + } + break; + case SANE_TYPE_FIXED: + case SANE_TYPE_INT: + { + ByteString aString( "NUMERIC=" ); + double fValue; + char buf[256]; + for( int n = 0; n < mrSane.GetOptionElements( nOption ); n++ ) + { + if( ! mrSane.GetOptionValue( nOption, fValue, n ) ) + break; + if( n > 0 ) + aString += ":"; + sprintf( buf, "%lg", fValue ); + aString += buf; + } + if( n >= mrSane.GetOptionElements( nOption ) ) + aConfig.WriteKey( aOption, aString ); + } + break; + default: + break; + } + } + } +#endif +#endif +} + +BOOL SaneDlg::SetAdjustedNumericalValue( + const char* pOption, + double fValue, + int nElement ) +{ + int nOption; + if( ! Sane::IsSane() || ! mrSane.IsOpen() || ( nOption = mrSane.GetOptionByName( pOption ) ) == -1 ) + return FALSE; + + if( nElement < 0 || nElement >= mrSane.GetOptionElements( nOption ) ) + return FALSE; + + double* pValues = NULL; + int nValues; + if( ( nValues = mrSane.GetRange( nOption, pValues ) ) < 0 ) + return FALSE; + +#ifdef DEBUG + fprintf( stderr, "SaneDlg::SetAdjustedNumericalValue( \"%s\", %lg ) ", + pOption, fValue ); +#endif + + if( nValues ) + { + int nNearest = 0; + double fNearest = 1e6; + for( int i = 0; i < nValues; i++ ) + { + if( fabs( fValue - pValues[ i ] ) < fNearest ) + { + fNearest = fabs( fValue - pValues[ i ] ); + nNearest = i; + } + } + fValue = pValues[ nNearest ]; + } + else + { + if( fValue < pValues[0] ) + fValue = pValues[0]; + if( fValue > pValues[1] ) + fValue = pValues[1]; + } + delete pValues; + mrSane.SetOptionValue( nOption, fValue, nElement ); +#ifdef DEBUG + fprintf( stderr, "yields %lg\n", fValue ); +#endif + + + return TRUE; +} |