summaryrefslogtreecommitdiff
path: root/extensions/source/scanner/sanedlg.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/source/scanner/sanedlg.cxx')
-rw-r--r--extensions/source/scanner/sanedlg.cxx1371
1 files changed, 1371 insertions, 0 deletions
diff --git a/extensions/source/scanner/sanedlg.cxx b/extensions/source/scanner/sanedlg.cxx
new file mode 100644
index 000000000000..f90bb6c20492
--- /dev/null
+++ b/extensions/source/scanner/sanedlg.cxx
@@ -0,0 +1,1371 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_extensions.hxx"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <tools/config.hxx>
+
+#include <vcl/msgbox.hxx>
+#include <sanedlg.hxx>
+#include <sanedlg.hrc>
+#include <grid.hxx>
+#include <math.h>
+#include <sal/macros.h>
+
+ResId SaneResId( sal_uInt32 nID )
+{
+ static ResMgr* pResMgr = ResMgr::CreateResMgr( "san" );
+ return ResId( nID, *pResMgr );
+}
+
+SaneDlg::SaneDlg( Window* pParent, Sane& rSane ) :
+ ModalDialog( pParent, SaneResId( RID_SANE_DIALOG ) ),
+ mrSane( rSane ),
+ mbIsDragging( sal_False ),
+ mbDragDrawn( sal_False ),
+ maMapMode( MAP_APPFONT ),
+ maOKButton( this, SaneResId( RID_SCAN_OK ) ),
+ maCancelButton( this, SaneResId( RID_SCAN_CANCEL ) ),
+ maDeviceInfoButton( this, SaneResId( RID_DEVICEINFO_BTN ) ),
+ maPreviewButton( this, SaneResId( RID_PREVIEW_BTN ) ),
+ maButtonOption( this, SaneResId( RID_SCAN_BUTTON_OPTION_BTN ) ),
+ maOptionsTxt( this, SaneResId( RID_SCAN_OPTION_TXT ) ),
+ maOptionTitle( this, SaneResId( RID_SCAN_OPTIONTITLE_TXT ) ),
+ maOptionDescTxt( this, SaneResId( RID_SCAN_OPTION_DESC_TXT ) ),
+ maVectorTxt( this, SaneResId( RID_SCAN_NUMERIC_VECTOR_TXT ) ),
+ maScanLeftTxt( this, SaneResId( RID_SCAN_LEFT_TXT ) ),
+ maLeftField( this, SaneResId( RID_SCAN_LEFT_BOX ) ),
+ maScanTopTxt( this, SaneResId( RID_SCAN_TOP_TXT ) ),
+ maTopField( this, SaneResId( RID_SCAN_TOP_BOX ) ),
+ maRightTxt( this, SaneResId( RID_SCAN_RIGHT_TXT ) ),
+ maRightField( this, SaneResId( RID_SCAN_RIGHT_BOX ) ),
+ maBottomTxt( this, SaneResId( RID_SCAN_BOTTOM_TXT ) ),
+ maBottomField( this, SaneResId( RID_SCAN_BOTTOM_BOX ) ),
+ maDeviceBoxTxt( this, SaneResId( RID_DEVICE_BOX_TXT ) ),
+ maDeviceBox( this, SaneResId( RID_DEVICE_BOX ) ),
+ maReslTxt( this, SaneResId( RID_SCAN_RESOLUTION_TXT ) ),
+ maReslBox( this, SaneResId( RID_SCAN_RESOLUTION_BOX ) ),
+ maAdvancedTxt( this, SaneResId( RID_SCAN_ADVANCED_TXT ) ),
+ maAdvancedBox( this, SaneResId( RID_SCAN_ADVANCED_BOX ) ),
+ maVectorBox( this, SaneResId( RID_SCAN_NUMERIC_VECTOR_BOX ) ),
+ maQuantumRangeBox( this, SaneResId( RID_SCAN_QUANTUM_RANGE_BOX ) ),
+ maStringRangeBox( this, SaneResId( RID_SCAN_STRING_RANGE_BOX ) ),
+ maPreviewBox( this, SaneResId( RID_PREVIEW_BOX ) ),
+ maAreaBox( this, SaneResId( RID_SCANAREA_BOX ) ),
+ maBoolCheckBox( this, SaneResId( RID_SCAN_BOOL_OPTION_BOX ) ),
+ maStringEdit( this, SaneResId( RID_SCAN_STRING_OPTION_EDT ) ),
+ maNumericEdit( this, SaneResId( RID_SCAN_NUMERIC_OPTION_EDT ) ),
+ maOptionBox( this, SaneResId( RID_SCAN_OPTION_BOX ) ),
+ mpRange( 0 )
+{
+ 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.SetStyle( maOptionBox.GetStyle()|
+ WB_HASLINES |
+ WB_HASBUTTONS |
+ WB_NOINITIALSELECTION |
+ WB_HASBUTTONSATROOT |
+ WB_HASLINESATROOT
+ );
+ FreeResource();
+}
+
+SaneDlg::~SaneDlg()
+{
+ mrSane.SetReloadOptionsHdl( maOldLink );
+}
+
+short SaneDlg::Execute()
+{
+ if( ! Sane::IsSane() )
+ {
+ ErrorBox aErrorBox( NULL, WB_OK | WB_DEF_OK,
+ String( SaneResId( RID_SANE_NOSANELIB_TXT ) ) );
+ aErrorBox.Execute();
+ return sal_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, nValue;
+ double fValue;
+ sal_Bool bSuccess = sal_False;
+ const char *ppSpecialOptions[] = {
+ "resolution",
+ "tl-x",
+ "tl-y",
+ "br-x",
+ "br-y",
+ "preview"
+ };
+
+ mbDragEnable = sal_True;
+ 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( sal_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] );
+ // Can only select 75 and 2400 dpi in Scanner dialogue
+ // scanner allows random setting of dpi resolution, a slider might be useful
+ // support that
+ // workaround: offer at least some more standard dpi resolution between
+ // min and max value
+ int bGot300 = 0;
+ for ( int nRes = (long) pDouble[0] * 2; nRes < (long) pDouble[1]; nRes = nRes * 2 )
+ {
+ if ( !bGot300 && nRes > 300 ) {
+ nRes = 300; bGot300 = 1;
+ }
+ maReslBox.InsertValue(nRes);
+ }
+ maReslBox.InsertValue( (long)pDouble[1] );
+ }
+ if( pDouble )
+ delete [] pDouble;
+ }
+ else
+ maReslBox.Enable( sal_False );
+ }
+ }
+ else
+ maReslBox.Enable( sal_False );
+
+ // set scan area
+ for( i = 0; i < 4; i++ )
+ {
+ char const *pOptionName = NULL;
+ MetricField* pField = NULL;
+ 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 = pOptionName ? mrSane.GetOptionByName( pOptionName ) : -1;
+ bSuccess = sal_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( sal_True );
+ }
+ else
+ {
+ mbDragEnable = sal_False;
+ pField->SetMin( 0 );
+ switch( i ) {
+ case 0:
+ maMinTopLeft.X() = 0;
+ maTopLeft.X() = 0;
+ pField->SetMax( PREVIEW_WIDTH );
+ pField->SetValue( 0 );
+ break;
+ case 1:
+ maMinTopLeft.Y() = 0;
+ maTopLeft.Y() = 0;
+ pField->SetMax( PREVIEW_HEIGHT );
+ pField->SetValue( 0 );
+ break;
+ case 2:
+ maMaxBottomRight.X() = PREVIEW_WIDTH;
+ maBottomRight.X() = PREVIEW_WIDTH;
+ pField->SetMax( PREVIEW_WIDTH );
+ pField->SetValue( PREVIEW_WIDTH );
+ break;
+ case 3:
+ maMaxBottomRight.Y() = PREVIEW_HEIGHT;
+ maBottomRight.Y() = PREVIEW_HEIGHT;
+ pField->SetMax( PREVIEW_HEIGHT );
+ pField->SetValue( PREVIEW_HEIGHT );
+ break;
+ }
+ pField->Enable( sal_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;
+ sal_Bool bGroupRejected = sal_False;
+ for( i = 1; i < mrSane.CountOptions(); i++ )
+ {
+ String aOption=mrSane.GetOptionName( i );
+ sal_Bool bInsertAdvanced =
+ mrSane.GetOptionCap( i ) & SANE_CAP_ADVANCED &&
+ ! maAdvancedBox.IsChecked() ? sal_False : sal_True;
+ if( mrSane.GetOptionType( i ) == SANE_TYPE_GROUP )
+ {
+ if( bInsertAdvanced )
+ {
+ aOption = mrSane.GetOptionTitle( i );
+ pParentEntry = maOptionBox.InsertEntry( aOption );
+ bGroupRejected = sal_False;
+ }
+ else
+ bGroupRejected = sal_True;
+ }
+ else if( aOption.Len() &&
+ ! ( mrSane.GetOptionCap( i ) &
+ (
+ SANE_CAP_HARD_SELECT |
+ SANE_CAP_INACTIVE
+ ) ) &&
+ bInsertAdvanced && ! bGroupRejected )
+ {
+ sal_Bool bIsSpecial = sal_False;
+ for( size_t n = 0; !bIsSpecial &&
+ n < SAL_N_ELEMENTS(ppSpecialOptions); n++ )
+ {
+ if( aOption.EqualsAscii( ppSpecialOptions[n] ) )
+ bIsSpecial=sal_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() ?
+ (sal_Bool)sal_True : (sal_Bool)sal_False );
+ }
+ else if( pButton == &maButtonOption )
+ {
+
+ SANE_Value_Type nType = mrSane.GetOptionType( mnCurrentOption );
+ switch( nType )
+ {
+ case SANE_TYPE_BUTTON:
+ mrSane.ActivateButtonOption( mnCurrentOption );
+ break;
+ case SANE_TYPE_FIXED:
+ case SANE_TYPE_INT:
+ {
+ int nElements = mrSane.GetOptionElements( mnCurrentOption );
+ double* x = new double[ nElements ];
+ double* y = new double[ nElements ];
+ for( int i = 0; i < nElements; i++ )
+ x[ i ] = (double)i;
+ mrSane.GetOptionValue( mnCurrentOption, y );
+
+ GridWindow aGrid( x, y, nElements, this );
+ aGrid.SetText( mrSane.GetOptionName( mnCurrentOption ) );
+ aGrid.setBoundings( 0, mfMin, nElements, mfMax );
+ if( aGrid.Execute() && aGrid.getNewYValues() )
+ mrSane.SetOptionValue( mnCurrentOption, aGrid.getNewYValues() );
+
+ delete [] x;
+ delete [] y;
+ }
+ break;
+ case SANE_TYPE_BOOL:
+ case SANE_TYPE_STRING:
+ case SANE_TYPE_GROUP:
+ break;
+ }
+ }
+ else if( pButton == &maAdvancedBox )
+ {
+ ReloadSaneOptionsHdl( NULL );
+ }
+ }
+ if( pButton == &maOKButton )
+ {
+ double fRes = (double)maReslBox.GetValue();
+ SetAdjustedNumericalValue( "resolution", fRes );
+ UpdateScanArea( sal_True );
+ SaveState();
+ EndDialog( mrSane.IsOpen() ? 1 : 0 );
+ }
+ else if( pButton == &maCancelButton )
+ {
+ 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(), osl_getThreadTextEncoding() );
+ 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, osl_getThreadTextEncoding() ).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 );
+ int nElements = mrSane.GetOptionElements( mnCurrentOption );
+ mnCurrentElement = 0;
+ if( nConstraint == SANE_CONSTRAINT_RANGE ||
+ nConstraint == SANE_CONSTRAINT_WORD_LIST )
+ EstablishQuantumRange();
+ else
+ {
+ mfMin = mfMax = 0.0;
+ EstablishNumericOption();
+ }
+ if( nElements > 1 )
+ {
+ if( nElements <= 10 )
+ {
+ maVectorBox.SetValue( 1 );
+ maVectorBox.SetMin( 1 );
+ maVectorBox.SetMax(
+ mrSane.GetOptionElements( mnCurrentOption ) );
+ maVectorBox.Show( sal_True );
+ maVectorTxt.Show( sal_True );
+ }
+ else
+ {
+ DisableOption();
+ // bring up dialog only on button click
+ EstablishButtonOption();
+ }
+ }
+ }
+ 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( (sal_uLong)fRes );
+ }
+ }
+ else if( pEdit == &maNumericEdit )
+ {
+ double fValue;
+ char pBuf[256];
+ ByteString aContents( maNumericEdit.GetText(), osl_getThreadTextEncoding() );
+ 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, osl_getThreadTextEncoding() ) );
+ }
+ 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, osl_getThreadTextEncoding() );
+ 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();
+ // #92024# preserve preview rect, should only be set
+ // initially or in AcquirePreview
+ Rectangle aPreviewRect = maPreviewRect;
+ InitFields();
+ maPreviewRect = aPreviewRect;
+ Rectangle aDummyRect( Point( 0, 0 ), GetSizePixel() );
+ Paint( aDummyRect );
+ return 0;
+}
+
+void SaneDlg::AcquirePreview()
+{
+ if( ! mrSane.IsOpen() )
+ return;
+
+ UpdateScanArea( sal_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, (sal_Bool)sal_True );
+
+ BitmapTransporter aTransporter;
+ if( ! mrSane.Start( aTransporter ) )
+ {
+ ErrorBox aErrorBox( this, WB_OK | WB_DEF_OK,
+ String( SaneResId( RID_SANE_SCANERROR_TXT ) ) );
+ aErrorBox.Execute();
+ }
+ else
+ {
+#if OSL_DEBUG_LEVEL > 1
+ aTransporter.getStream().Seek( STREAM_SEEK_TO_END );
+ fprintf( stderr, "Previewbitmapstream contains %d bytes\n", (int)aTransporter.getStream().Tell() );
+#endif
+ aTransporter.getStream().Seek( STREAM_SEEK_TO_BEGIN );
+ maPreviewBitmap.Read( aTransporter.getStream(), sal_True );
+ }
+
+ SetAdjustedNumericalValue( "resolution", fResl );
+ maReslBox.SetValue( (sal_uLong)fResl );
+
+ if( mbDragEnable )
+ {
+ maPreviewRect = Rectangle( maTopLeft,
+ Size( maBottomRight.X() - maTopLeft.X(),
+ maBottomRight.Y() - maTopLeft.Y() )
+ );
+ }
+ else
+ {
+ Size aBMSize( maPreviewBitmap.GetSizePixel() );
+ if( aBMSize.Width() > aBMSize.Height() && aBMSize.Width() )
+ {
+ int nVHeight = (maBottomRight.X() - maTopLeft.X()) * aBMSize.Height() / aBMSize.Width();
+ maPreviewRect = Rectangle( Point( maTopLeft.X(), ( maTopLeft.Y() + maBottomRight.Y() )/2 - nVHeight/2 ),
+ Size( maBottomRight.X() - maTopLeft.X(),
+ nVHeight ) );
+ }
+ else if (aBMSize.Height())
+ {
+ int nVWidth = (maBottomRight.Y() - maTopLeft.Y()) * aBMSize.Width() / aBMSize.Height();
+ maPreviewRect = Rectangle( Point( ( maTopLeft.X() + maBottomRight.X() )/2 - nVWidth/2, maTopLeft.Y() ),
+ Size( nVWidth,
+ 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 = sal_False;
+ DrawDrag();
+
+ ModalDialog::Paint( rRect );
+}
+
+void SaneDlg::DisableOption()
+{
+ maBoolCheckBox.Show( sal_False );
+ maStringEdit.Show( sal_False );
+ maNumericEdit.Show( sal_False );
+ maQuantumRangeBox.Show( sal_False );
+ maStringRangeBox.Show( sal_False );
+ maButtonOption.Show( sal_False );
+ maVectorBox.Show( sal_False );
+ maVectorTxt.Show( sal_False );
+ maOptionDescTxt.Show( sal_False );
+}
+
+void SaneDlg::EstablishBoolOption()
+{
+ sal_Bool bSuccess, bValue;
+
+ bSuccess = mrSane.GetOptionValue( mnCurrentOption, bValue );
+ if( bSuccess )
+ {
+ maOptionDescTxt.SetText( mrSane.GetOptionName( mnCurrentOption ) );
+ maOptionDescTxt.Show( sal_True );
+ maBoolCheckBox.Check( bValue );
+ maBoolCheckBox.Show( sal_True );
+ }
+}
+
+void SaneDlg::EstablishStringOption()
+{
+ sal_Bool bSuccess;
+ ByteString aValue;
+
+ bSuccess = mrSane.GetOptionValue( mnCurrentOption, aValue );
+ if( bSuccess )
+ {
+ maOptionDescTxt.SetText( mrSane.GetOptionName( mnCurrentOption ) );
+ maOptionDescTxt.Show( sal_True );
+ maStringEdit.SetText( String( aValue, osl_getThreadTextEncoding() ) );
+ maStringEdit.Show( sal_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], osl_getThreadTextEncoding() ) );
+ ByteString aValue;
+ mrSane.GetOptionValue( mnCurrentOption, aValue );
+ maStringRangeBox.SelectEntry( String( aValue, osl_getThreadTextEncoding() ) );
+ maStringRangeBox.Show( sal_True );
+ maOptionDescTxt.SetText( mrSane.GetOptionName( mnCurrentOption ) );
+ maOptionDescTxt.Show( sal_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, osl_getThreadTextEncoding() ) );
+ }
+ double fValue;
+ if( mrSane.GetOptionValue( mnCurrentOption, fValue, mnCurrentElement ) )
+ {
+ sprintf( pBuf, "%g", fValue );
+ maQuantumRangeBox.SelectEntry( String( pBuf, osl_getThreadTextEncoding() ) );
+ }
+ maQuantumRangeBox.Show( sal_True );
+ String aText( mrSane.GetOptionName( mnCurrentOption ) );
+ aText += ' ';
+ aText += mrSane.GetOptionUnitName( mnCurrentOption );
+ maOptionDescTxt.SetText( aText );
+ maOptionDescTxt.Show( sal_True );
+ }
+}
+
+void SaneDlg::EstablishNumericOption()
+{
+ sal_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, osl_getThreadTextEncoding() );
+ }
+ maOptionDescTxt.SetText( aText );
+ maOptionDescTxt.Show( sal_True );
+ sprintf( pBuf, "%g", fValue );
+ maNumericEdit.SetText( String( pBuf, osl_getThreadTextEncoding() ) );
+ maNumericEdit.Show( sal_True );
+}
+
+void SaneDlg::EstablishButtonOption()
+{
+ maOptionDescTxt.SetText( mrSane.GetOptionName( mnCurrentOption ) );
+ maOptionDescTxt.Show( sal_True );
+ maButtonOption.Show( sal_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( sal_False );
+ }
+ ModalDialog::MouseMove( rMEvt );
+}
+
+void SaneDlg::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ Point aMousePixel = rMEvt.GetPosPixel();
+
+ if( ! mbIsDragging && mbDragEnable )
+ {
+ 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 = sal_True;
+ }
+ else if( aMousePixel.X() >= nMiddleX &&
+ aMousePixel.X() < nMiddleX + RECT_SIZE_PIX )
+ {
+ meDragDirection = Top;
+ aMousePixel.Y() = maTopLeft.Y();
+ mbIsDragging = sal_True;
+ }
+ else if( aMousePixel.X() > maBottomRight.X() - RECT_SIZE_PIX &&
+ aMousePixel.X() <= maBottomRight.X() )
+ {
+ meDragDirection = TopRight;
+ aMousePixel = Point( maBottomRight.X(), maTopLeft.Y() );
+ mbIsDragging = sal_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 = sal_True;
+ }
+ else if( aMousePixel.X() > maBottomRight.X() - RECT_SIZE_PIX &&
+ aMousePixel.X() <= maBottomRight.X() )
+ {
+ meDragDirection = Right;
+ aMousePixel.X() = maBottomRight.X();
+ mbIsDragging = sal_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 = sal_True;
+ }
+ else if( aMousePixel.X() >= nMiddleX &&
+ aMousePixel.X() < nMiddleX + RECT_SIZE_PIX )
+ {
+ meDragDirection = Bottom;
+ aMousePixel.Y() = maBottomRight.Y();
+ mbIsDragging = sal_True;
+ }
+ else if( aMousePixel.X() > maBottomRight.X() - RECT_SIZE_PIX &&
+ aMousePixel.X() <= maBottomRight.X() )
+ {
+ meDragDirection = BottomRight;
+ aMousePixel = maBottomRight;
+ mbIsDragging = sal_True;
+ }
+ }
+ }
+ if( mbIsDragging )
+ {
+ SetPointerPosPixel( aMousePixel );
+ DrawDrag();
+ }
+ ModalDialog::MouseButtonDown( rMEvt );
+}
+
+void SaneDlg::MouseButtonUp( const MouseEvent& rMEvt )
+{
+ if( mbIsDragging )
+ {
+ UpdateScanArea( sal_True );
+ }
+ mbIsDragging = sal_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;
+
+ if( ! mbDragEnable )
+ return;
+
+ RasterOp eROP = GetRasterOp();
+ SetRasterOp( ROP_INVERT );
+ SetMapMode( MapMode( MAP_PIXEL ) );
+
+ if( mbDragDrawn )
+ DrawRectangles( aLastUL, aLastBR );
+
+ aLastUL = maTopLeft;
+ aLastBR = maBottomRight;
+ DrawRectangles( maTopLeft, maBottomRight );
+
+ mbDragDrawn = sal_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( sal_Bool bSend )
+{
+ if( ! mbDragEnable )
+ return;
+
+ 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() );
+ }
+}
+
+sal_Bool SaneDlg::LoadState()
+{
+ int i;
+
+ if( ! Sane::IsSane() )
+ return sal_False;
+
+ const char* pEnv = getenv("HOME");
+ String aFileName( pEnv ? pEnv : "", osl_getThreadTextEncoding() );
+ aFileName += String( RTL_CONSTASCII_USTRINGPARAM( "/.so_sane_state" ) );
+ Config aConfig( aFileName );
+ if( ! aConfig.HasGroup( "SANE" ) )
+ return sal_False;
+
+ aConfig.SetGroup( "SANE" );
+ ByteString aString = aConfig.ReadKey( "SO_LastSaneDevice" );
+ for( i = 0; i < Sane::CountDevices() && ! aString.Equals( ByteString( Sane::GetName( i ), osl_getThreadTextEncoding() ) ); i++ ) ;
+ if( i == Sane::CountDevices() )
+ return sal_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 );
+ sal_Bool aBOOL = (sal_Bool)aValue.ToInt32();
+ mrSane.SetOptionValue( nOption, aBOOL );
+ }
+ else if( aValue.CompareTo( "STRING=", 7 ) == COMPARE_EQUAL )
+ {
+ aValue.Erase( 0, 7 );
+ mrSane.SetOptionValue( nOption, String( aValue, osl_getThreadTextEncoding() ) );
+ }
+ 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 sal_True;
+}
+
+void SaneDlg::SaveState()
+{
+ if( ! Sane::IsSane() )
+ return;
+
+ const char* pEnv = getenv( "HOME" );
+ String aFileName( pEnv ? pEnv : "", osl_getThreadTextEncoding() );
+ aFileName.AppendAscii( "/.so_sane_state" );
+
+ Config aConfig( aFileName );
+ aConfig.DeleteGroup( "SANE" );
+ aConfig.SetGroup( "SANE" );
+ aConfig.WriteKey( "SO_LastSANEDevice", ByteString( maDeviceBox.GetSelectEntry(), RTL_TEXTENCODING_UTF8 ) );
+
+ static char const* pSaveOptions[] = {
+ "resolution",
+ "tl-x",
+ "tl-y",
+ "br-x",
+ "br-y"
+ };
+ for( size_t i = 0; i < SAL_N_ELEMENTS(pSaveOptions); 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:
+ {
+ sal_Bool bValue;
+ if( mrSane.GetOptionValue( nOption, bValue ) )
+ {
+ ByteString aString( "BOOL=" );
+ aString += ByteString::CreateFromInt32(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];
+ int n;
+
+ for( 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;
+ }
+ }
+ }
+}
+
+sal_Bool SaneDlg::SetAdjustedNumericalValue(
+ const char* pOption,
+ double fValue,
+ int nElement )
+{
+ int nOption;
+ if( ! Sane::IsSane() || ! mrSane.IsOpen() || ( nOption = mrSane.GetOptionByName( pOption ) ) == -1 )
+ return sal_False;
+
+ if( nElement < 0 || nElement >= mrSane.GetOptionElements( nOption ) )
+ return sal_False;
+
+ double* pValues = NULL;
+ int nValues;
+ if( ( nValues = mrSane.GetRange( nOption, pValues ) ) < 0 )
+ return sal_False;
+
+#if OSL_DEBUG_LEVEL > 1
+ 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 );
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "yields %lg\n", fValue );
+#endif
+
+
+ return sal_True;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */