update credits
[LibreOffice.git] / extensions / source / scanner / sanedlg.cxx
blob2ccd4d94d432bc568d67d942769f3f6a63e49085
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <tools/config.hxx>
25 #include <vcl/msgbox.hxx>
26 #include <sanedlg.hxx>
27 #include <sanedlg.hrc>
28 #include <grid.hxx>
29 #include <math.h>
30 #include <sal/macros.h>
31 #include <rtl/strbuf.hxx>
33 ResId SaneResId( sal_uInt32 nID )
35 static ResMgr* pResMgr = ResMgr::CreateResMgr( "scn" );
36 return ResId( nID, *pResMgr );
39 SaneDlg::SaneDlg( Window* pParent, Sane& rSane, bool bScanEnabled ) :
40 ModalDialog( pParent, SaneResId( RID_SANE_DIALOG ) ),
41 mrSane( rSane ),
42 mbIsDragging( sal_False ),
43 mbScanEnabled( bScanEnabled ),
44 mbDragDrawn( sal_False ),
45 maMapMode( MAP_APPFONT ),
46 maOKButton( this, SaneResId( RID_SCAN_OK ) ),
47 maCancelButton( this, SaneResId( RID_SCAN_CANCEL ) ),
48 maDeviceInfoButton( this, SaneResId( RID_DEVICEINFO_BTN ) ),
49 maPreviewButton( this, SaneResId( RID_PREVIEW_BTN ) ),
50 maScanButton( this, SaneResId( RID_SCAN_BTN ) ),
51 maButtonOption( this, SaneResId( RID_SCAN_BUTTON_OPTION_BTN ) ),
52 maOptionsTxt( this, SaneResId( RID_SCAN_OPTION_TXT ) ),
53 maOptionTitle( this, SaneResId( RID_SCAN_OPTIONTITLE_TXT ) ),
54 maOptionDescTxt( this, SaneResId( RID_SCAN_OPTION_DESC_TXT ) ),
55 maVectorTxt( this, SaneResId( RID_SCAN_NUMERIC_VECTOR_TXT ) ),
56 maScanLeftTxt( this, SaneResId( RID_SCAN_LEFT_TXT ) ),
57 maLeftField( this, SaneResId( RID_SCAN_LEFT_BOX ) ),
58 maScanTopTxt( this, SaneResId( RID_SCAN_TOP_TXT ) ),
59 maTopField( this, SaneResId( RID_SCAN_TOP_BOX ) ),
60 maRightTxt( this, SaneResId( RID_SCAN_RIGHT_TXT ) ),
61 maRightField( this, SaneResId( RID_SCAN_RIGHT_BOX ) ),
62 maBottomTxt( this, SaneResId( RID_SCAN_BOTTOM_TXT ) ),
63 maBottomField( this, SaneResId( RID_SCAN_BOTTOM_BOX ) ),
64 maDeviceBoxTxt( this, SaneResId( RID_DEVICE_BOX_TXT ) ),
65 maDeviceBox( this, SaneResId( RID_DEVICE_BOX ) ),
66 maReslTxt( this, SaneResId( RID_SCAN_RESOLUTION_TXT ) ),
67 maReslBox( this, SaneResId( RID_SCAN_RESOLUTION_BOX ) ),
68 maAdvancedTxt( this, SaneResId( RID_SCAN_ADVANCED_TXT ) ),
69 maAdvancedBox( this, SaneResId( RID_SCAN_ADVANCED_BOX ) ),
70 maVectorBox( this, SaneResId( RID_SCAN_NUMERIC_VECTOR_BOX ) ),
71 maQuantumRangeBox( this, SaneResId( RID_SCAN_QUANTUM_RANGE_BOX ) ),
72 maStringRangeBox( this, SaneResId( RID_SCAN_STRING_RANGE_BOX ) ),
73 maPreviewBox( this, SaneResId( RID_PREVIEW_BOX ) ),
74 maAreaBox( this, SaneResId( RID_SCANAREA_BOX ) ),
75 maBoolCheckBox( this, SaneResId( RID_SCAN_BOOL_OPTION_BOX ) ),
76 maStringEdit( this, SaneResId( RID_SCAN_STRING_OPTION_EDT ) ),
77 maNumericEdit( this, SaneResId( RID_SCAN_NUMERIC_OPTION_EDT ) ),
78 maOptionBox( this, SaneResId( RID_SCAN_OPTION_BOX ) ),
79 mpRange( 0 ),
80 doScan( false )
82 if( Sane::IsSane() )
84 InitDevices(); // opens first sane device
85 DisableOption();
86 InitFields();
89 maDeviceInfoButton.SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) );
90 maPreviewButton.SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) );
91 maScanButton.SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) );
92 maButtonOption.SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) );
93 maDeviceBox.SetSelectHdl( LINK( this, SaneDlg, SelectHdl ) );
94 maOptionBox.SetSelectHdl( LINK( this, SaneDlg, OptionsBoxSelectHdl ) );
95 maOKButton.SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) );
96 maCancelButton.SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) );
97 maBoolCheckBox.SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) );
98 maStringEdit.SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) );
99 maNumericEdit.SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) );
100 maVectorBox.SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) );
101 maReslBox.SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) );
102 maStringRangeBox.SetSelectHdl( LINK( this, SaneDlg, SelectHdl ) );
103 maQuantumRangeBox.SetSelectHdl( LINK( this, SaneDlg, SelectHdl ) );
104 maLeftField.SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) );
105 maRightField.SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) );
106 maTopField.SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) );
107 maBottomField.SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) );
108 maAdvancedBox.SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) );
110 maOldLink = mrSane.SetReloadOptionsHdl( LINK( this, SaneDlg, ReloadSaneOptionsHdl ) );
112 maOptionBox.SetNodeBitmaps(
113 Bitmap( SaneResId( RID_SCAN_BITMAP_PLUS ) ),
114 Bitmap( SaneResId( RID_SCAN_BITMAP_MINUS ) )
116 maOptionBox.SetStyle( maOptionBox.GetStyle()|
117 WB_HASLINES |
118 WB_HASBUTTONS |
119 WB_NOINITIALSELECTION |
120 WB_HASBUTTONSATROOT |
121 WB_HASLINESATROOT
123 FreeResource();
126 SaneDlg::~SaneDlg()
128 mrSane.SetReloadOptionsHdl( maOldLink );
131 short SaneDlg::Execute()
133 if( ! Sane::IsSane() )
135 ErrorBox aErrorBox( NULL, WB_OK | WB_DEF_OK,
136 String( SaneResId( RID_SANE_NOSANELIB_TXT ) ) );
137 aErrorBox.Execute();
138 return sal_False;
140 LoadState();
141 return ModalDialog::Execute();
144 void SaneDlg::InitDevices()
146 if( ! Sane::IsSane() )
147 return;
149 if( mrSane.IsOpen() )
150 mrSane.Close();
151 mrSane.ReloadDevices();
152 maDeviceBox.Clear();
153 for( int i = 0; i < Sane::CountDevices(); i++ )
154 maDeviceBox.InsertEntry( Sane::GetName( i ) );
155 if( Sane::CountDevices() )
157 mrSane.Open( 0 );
158 maDeviceBox.SelectEntry( Sane::GetName( 0 ) );
163 void SaneDlg::InitFields()
165 if( ! Sane::IsSane() )
166 return;
168 int nOption, i, nValue;
169 double fValue;
170 sal_Bool bSuccess = sal_False;
171 const char *ppSpecialOptions[] = {
172 "resolution",
173 "tl-x",
174 "tl-y",
175 "br-x",
176 "br-y",
177 "preview"
180 mbDragEnable = sal_True;
181 maReslBox.Clear();
182 maMinTopLeft = Point( 0, 0 );
183 maMaxBottomRight = Point( PREVIEW_WIDTH, PREVIEW_HEIGHT );
184 maScanButton.Show( mbScanEnabled );
186 if( ! mrSane.IsOpen() )
187 return;
189 // set Resolution
190 nOption = mrSane.GetOptionByName( "resolution" );
191 if( nOption != -1 )
193 double fRes;
195 bSuccess = mrSane.GetOptionValue( nOption, fRes );
196 if( bSuccess )
198 maReslBox.Enable( sal_True );
200 maReslBox.SetValue( (long)fRes );
201 double *pDouble = NULL;
202 nValue = mrSane.GetRange( nOption, pDouble );
203 if( nValue > -1 )
205 if( nValue )
207 maReslBox.SetMin( (long)pDouble[0] );
208 maReslBox.SetMax( (long)pDouble[ nValue-1 ] );
209 for( i=0; i<nValue; i++ )
211 if( i == 0 || i == nValue-1 || ! ( ((int)pDouble[i]) % 20) )
212 maReslBox.InsertValue( (long)pDouble[i] );
215 else
217 maReslBox.SetMin( (long)pDouble[0] );
218 maReslBox.SetMax( (long)pDouble[1] );
219 maReslBox.InsertValue( (long)pDouble[0] );
220 // Can only select 75 and 2400 dpi in Scanner dialogue
221 // scanner allows random setting of dpi resolution, a slider might be useful
222 // support that
223 // workaround: offer at least some more standard dpi resolution between
224 // min and max value
225 int bGot300 = 0;
226 for ( int nRes = (long) pDouble[0] * 2; nRes < (long) pDouble[1]; nRes = nRes * 2 )
228 if ( !bGot300 && nRes > 300 ) {
229 nRes = 300; bGot300 = 1;
231 maReslBox.InsertValue(nRes);
233 maReslBox.InsertValue( (long)pDouble[1] );
235 if( pDouble )
236 delete [] pDouble;
238 else
239 maReslBox.Enable( sal_False );
242 else
243 maReslBox.Enable( sal_False );
245 // set scan area
246 for( i = 0; i < 4; i++ )
248 char const *pOptionName = NULL;
249 MetricField* pField = NULL;
250 switch( i )
252 case 0:
253 pOptionName = "tl-x";
254 pField = &maLeftField;
255 break;
256 case 1:
257 pOptionName = "tl-y";
258 pField = &maTopField;
259 break;
260 case 2:
261 pOptionName = "br-x";
262 pField = &maRightField;
263 break;
264 case 3:
265 pOptionName = "br-y";
266 pField = &maBottomField;
268 nOption = pOptionName ? mrSane.GetOptionByName( pOptionName ) : -1;
269 bSuccess = sal_False;
270 if( nOption != -1 )
272 bSuccess = mrSane.GetOptionValue( nOption, fValue, 0 );
273 if( bSuccess )
275 if( mrSane.GetOptionUnit( nOption ) == SANE_UNIT_MM )
277 pField->SetUnit( FUNIT_MM );
278 pField->SetValue( (int)fValue, FUNIT_MM );
280 else // SANE_UNIT_PIXEL
282 pField->SetValue( (int)fValue, FUNIT_CUSTOM );
283 pField->SetCustomUnitText(OUString("Pixel"));
285 switch( i ) {
286 case 0: maTopLeft.X() = (int)fValue;break;
287 case 1: maTopLeft.Y() = (int)fValue;break;
288 case 2: maBottomRight.X() = (int)fValue;break;
289 case 3: maBottomRight.Y() = (int)fValue;break;
292 double *pDouble = NULL;
293 nValue = mrSane.GetRange( nOption, pDouble );
294 if( nValue > -1 )
296 if( pDouble )
298 pField->SetMin( (long)pDouble[0] );
299 if( nValue )
300 pField->SetMax( (long)pDouble[ nValue-1 ] );
301 else
302 pField->SetMax( (long)pDouble[ 1 ] );
303 delete [] pDouble;
305 switch( i ) {
306 case 0: maMinTopLeft.X() = pField->GetMin();break;
307 case 1: maMinTopLeft.Y() = pField->GetMin();break;
308 case 2: maMaxBottomRight.X() = pField->GetMax();break;
309 case 3: maMaxBottomRight.Y() = pField->GetMax();break;
312 else
314 switch( i ) {
315 case 0: maMinTopLeft.X() = (int)fValue;break;
316 case 1: maMinTopLeft.Y() = (int)fValue;break;
317 case 2: maMaxBottomRight.X() = (int)fValue;break;
318 case 3: maMaxBottomRight.Y() = (int)fValue;break;
321 pField->Enable( sal_True );
323 else
325 mbDragEnable = sal_False;
326 pField->SetMin( 0 );
327 switch( i ) {
328 case 0:
329 maMinTopLeft.X() = 0;
330 maTopLeft.X() = 0;
331 pField->SetMax( PREVIEW_WIDTH );
332 pField->SetValue( 0 );
333 break;
334 case 1:
335 maMinTopLeft.Y() = 0;
336 maTopLeft.Y() = 0;
337 pField->SetMax( PREVIEW_HEIGHT );
338 pField->SetValue( 0 );
339 break;
340 case 2:
341 maMaxBottomRight.X() = PREVIEW_WIDTH;
342 maBottomRight.X() = PREVIEW_WIDTH;
343 pField->SetMax( PREVIEW_WIDTH );
344 pField->SetValue( PREVIEW_WIDTH );
345 break;
346 case 3:
347 maMaxBottomRight.Y() = PREVIEW_HEIGHT;
348 maBottomRight.Y() = PREVIEW_HEIGHT;
349 pField->SetMax( PREVIEW_HEIGHT );
350 pField->SetValue( PREVIEW_HEIGHT );
351 break;
353 pField->Enable( sal_False );
356 maTopLeft = GetPixelPos( maTopLeft );
357 maBottomRight = GetPixelPos( maBottomRight );
358 maPreviewRect = Rectangle( maTopLeft,
359 Size( maBottomRight.X() - maTopLeft.X(),
360 maBottomRight.Y() - maTopLeft.Y() )
362 // fill OptionBox
363 maOptionBox.Clear();
364 SvTreeListEntry* pParentEntry = 0;
365 sal_Bool bGroupRejected = sal_False;
366 for( i = 1; i < mrSane.CountOptions(); i++ )
368 String aOption=mrSane.GetOptionName( i );
369 sal_Bool bInsertAdvanced =
370 mrSane.GetOptionCap( i ) & SANE_CAP_ADVANCED &&
371 ! maAdvancedBox.IsChecked() ? sal_False : sal_True;
372 if( mrSane.GetOptionType( i ) == SANE_TYPE_GROUP )
374 if( bInsertAdvanced )
376 aOption = mrSane.GetOptionTitle( i );
377 pParentEntry = maOptionBox.InsertEntry( aOption );
378 bGroupRejected = sal_False;
380 else
381 bGroupRejected = sal_True;
383 else if( aOption.Len() &&
384 ! ( mrSane.GetOptionCap( i ) &
386 SANE_CAP_HARD_SELECT |
387 SANE_CAP_INACTIVE
388 ) ) &&
389 bInsertAdvanced && ! bGroupRejected )
391 sal_Bool bIsSpecial = sal_False;
392 for( size_t n = 0; !bIsSpecial &&
393 n < SAL_N_ELEMENTS(ppSpecialOptions); n++ )
395 if( aOption.EqualsAscii( ppSpecialOptions[n] ) )
396 bIsSpecial=sal_True;
398 if( ! bIsSpecial )
400 if( pParentEntry )
401 maOptionBox.InsertEntry( aOption, pParentEntry );
402 else
403 maOptionBox.InsertEntry( aOption );
409 IMPL_LINK( SaneDlg, ClickBtnHdl, Button*, pButton )
411 if( mrSane.IsOpen() )
413 if( pButton == &maDeviceInfoButton )
415 String aString( SaneResId( RID_SANE_DEVICEINFO_TXT ) );
416 String aSR( RTL_CONSTASCII_USTRINGPARAM( "%s" ) );
417 aString.SearchAndReplace( aSR, Sane::GetName( mrSane.GetDeviceNumber() ) );
418 aString.SearchAndReplace( aSR, Sane::GetVendor( mrSane.GetDeviceNumber() ) );
419 aString.SearchAndReplace( aSR, Sane::GetModel( mrSane.GetDeviceNumber() ) );
420 aString.SearchAndReplace( aSR, Sane::GetType( mrSane.GetDeviceNumber() ) );
421 InfoBox aInfoBox( this, aString );
422 aInfoBox.Execute();
424 else if( pButton == &maPreviewButton )
425 AcquirePreview();
426 else if( pButton == &maBoolCheckBox )
428 mrSane.SetOptionValue( mnCurrentOption,
429 maBoolCheckBox.IsChecked() ?
430 (sal_Bool)sal_True : (sal_Bool)sal_False );
432 else if( pButton == &maButtonOption )
435 SANE_Value_Type nType = mrSane.GetOptionType( mnCurrentOption );
436 switch( nType )
438 case SANE_TYPE_BUTTON:
439 mrSane.ActivateButtonOption( mnCurrentOption );
440 break;
441 case SANE_TYPE_FIXED:
442 case SANE_TYPE_INT:
444 int nElements = mrSane.GetOptionElements( mnCurrentOption );
445 double* x = new double[ nElements ];
446 double* y = new double[ nElements ];
447 for( int i = 0; i < nElements; i++ )
448 x[ i ] = (double)i;
449 mrSane.GetOptionValue( mnCurrentOption, y );
451 GridWindow aGrid( x, y, nElements, this );
452 aGrid.SetText( mrSane.GetOptionName( mnCurrentOption ) );
453 aGrid.setBoundings( 0, mfMin, nElements, mfMax );
454 if( aGrid.Execute() && aGrid.getNewYValues() )
455 mrSane.SetOptionValue( mnCurrentOption, aGrid.getNewYValues() );
457 delete [] x;
458 delete [] y;
460 break;
461 case SANE_TYPE_BOOL:
462 case SANE_TYPE_STRING:
463 case SANE_TYPE_GROUP:
464 break;
467 else if( pButton == &maAdvancedBox )
469 ReloadSaneOptionsHdl( NULL );
472 if( pButton == &maOKButton || pButton == &maScanButton )
474 double fRes = (double)maReslBox.GetValue();
475 SetAdjustedNumericalValue( "resolution", fRes );
476 UpdateScanArea( sal_True );
477 SaveState();
478 EndDialog( mrSane.IsOpen() ? 1 : 0 );
479 doScan = (pButton == &maScanButton);
481 else if( pButton == &maCancelButton )
483 mrSane.Close();
484 EndDialog( 0 );
486 return 0;
489 IMPL_LINK( SaneDlg, SelectHdl, ListBox*, pListBox )
491 if( pListBox == &maDeviceBox && Sane::IsSane() && Sane::CountDevices() )
493 String aNewDevice = maDeviceBox.GetSelectEntry();
494 int nNumber;
495 if( aNewDevice.Equals( Sane::GetName( nNumber = mrSane.GetDeviceNumber() ) ) )
497 mrSane.Close();
498 mrSane.Open( nNumber );
499 InitFields();
502 if( mrSane.IsOpen() )
504 if( pListBox == &maQuantumRangeBox )
506 OString aValue(OUStringToOString(maQuantumRangeBox.GetSelectEntry(),
507 osl_getThreadTextEncoding()));
508 double fValue = atof(aValue.getStr());
509 mrSane.SetOptionValue( mnCurrentOption, fValue, mnCurrentElement );
511 else if( pListBox == &maStringRangeBox )
513 mrSane.SetOptionValue( mnCurrentOption, maStringRangeBox.GetSelectEntry() );
516 return 0;
519 IMPL_LINK( SaneDlg, OptionsBoxSelectHdl, SvTreeListBox*, pBox )
521 if( pBox == &maOptionBox && Sane::IsSane() )
523 String aOption =
524 maOptionBox.GetEntryText( maOptionBox.FirstSelected() );
525 int nOption = mrSane.GetOptionByName(OUStringToOString(aOption,
526 osl_getThreadTextEncoding()).getStr());
527 if( nOption != -1 && nOption != mnCurrentOption )
529 DisableOption();
530 mnCurrentOption = nOption;
531 maOptionTitle.SetText( mrSane.GetOptionTitle( mnCurrentOption ) );
532 SANE_Value_Type nType = mrSane.GetOptionType( mnCurrentOption );
533 SANE_Constraint_Type nConstraint;
534 switch( nType )
536 case SANE_TYPE_BOOL: EstablishBoolOption();break;
537 case SANE_TYPE_STRING:
538 nConstraint = mrSane.GetOptionConstraintType( mnCurrentOption );
539 if( nConstraint == SANE_CONSTRAINT_STRING_LIST )
540 EstablishStringRange();
541 else
542 EstablishStringOption();
543 break;
544 case SANE_TYPE_FIXED:
545 case SANE_TYPE_INT:
547 nConstraint = mrSane.GetOptionConstraintType( mnCurrentOption );
548 int nElements = mrSane.GetOptionElements( mnCurrentOption );
549 mnCurrentElement = 0;
550 if( nConstraint == SANE_CONSTRAINT_RANGE ||
551 nConstraint == SANE_CONSTRAINT_WORD_LIST )
552 EstablishQuantumRange();
553 else
555 mfMin = mfMax = 0.0;
556 EstablishNumericOption();
558 if( nElements > 1 )
560 if( nElements <= 10 )
562 maVectorBox.SetValue( 1 );
563 maVectorBox.SetMin( 1 );
564 maVectorBox.SetMax(
565 mrSane.GetOptionElements( mnCurrentOption ) );
566 maVectorBox.Show( sal_True );
567 maVectorTxt.Show( sal_True );
569 else
571 DisableOption();
572 // bring up dialog only on button click
573 EstablishButtonOption();
577 break;
578 case SANE_TYPE_BUTTON:
579 EstablishButtonOption();
580 break;
581 default: break;
585 return 0;
588 IMPL_LINK( SaneDlg, ModifyHdl, Edit*, pEdit )
590 if( mrSane.IsOpen() )
592 if( pEdit == &maStringEdit )
594 mrSane.SetOptionValue( mnCurrentOption, maStringEdit.GetText() );
596 else if( pEdit == &maReslBox )
598 double fRes = (double)maReslBox.GetValue();
599 int nOption = mrSane.GetOptionByName( "resolution" );
600 if( nOption != -1 )
602 double* pDouble = NULL;
603 int nValues = mrSane.GetRange( nOption, pDouble );
604 if( nValues > 0 )
606 int i;
607 for( i = 0; i < nValues; i++ )
609 if( fRes == pDouble[i] )
610 break;
612 if( i >= nValues )
613 fRes = pDouble[0];
615 else if( nValues == 0 )
617 if( fRes < pDouble[ 0 ] )
618 fRes = pDouble[ 0 ];
619 if( fRes > pDouble[ 1 ] )
620 fRes = pDouble[ 1 ];
622 delete[] pDouble;
623 maReslBox.SetValue( (sal_uLong)fRes );
626 else if( pEdit == &maNumericEdit )
628 double fValue;
629 OString aContents(OUStringToOString(maNumericEdit.GetText(),
630 osl_getThreadTextEncoding()));
631 fValue = atof(aContents.getStr());
632 if( mfMin != mfMax && ( fValue < mfMin || fValue > mfMax ) )
634 char pBuf[256];
635 if( fValue < mfMin )
636 fValue = mfMin;
637 else if( fValue > mfMax )
638 fValue = mfMax;
639 sprintf( pBuf, "%g", fValue );
640 maNumericEdit.SetText( String( pBuf, osl_getThreadTextEncoding() ) );
642 mrSane.SetOptionValue( mnCurrentOption, fValue, mnCurrentElement );
644 else if( pEdit == &maVectorBox )
646 char pBuf[256];
647 mnCurrentElement = maVectorBox.GetValue()-1;
648 double fValue;
649 mrSane.GetOptionValue( mnCurrentOption, fValue, mnCurrentElement );
650 sprintf( pBuf, "%g", fValue );
651 String aValue( pBuf, osl_getThreadTextEncoding() );
652 maNumericEdit.SetText( aValue );
653 maQuantumRangeBox.SelectEntry( aValue );
655 else if( pEdit == &maTopField )
657 Point aPoint( 0, maTopField.GetValue() );
658 aPoint = GetPixelPos( aPoint );
659 maTopLeft.Y() = aPoint.Y();
660 DrawDrag();
662 else if( pEdit == &maLeftField )
664 Point aPoint( maLeftField.GetValue(), 0 );
665 aPoint = GetPixelPos( aPoint );
666 maTopLeft.X() = aPoint.X();
667 DrawDrag();
669 else if( pEdit == &maBottomField )
671 Point aPoint( 0, maBottomField.GetValue() );
672 aPoint = GetPixelPos( aPoint );
673 maBottomRight.Y() = aPoint.Y();
674 DrawDrag();
676 else if( pEdit == &maRightField )
678 Point aPoint( maRightField.GetValue(), 0 );
679 aPoint = GetPixelPos( aPoint );
680 maBottomRight.X() = aPoint.X();
681 DrawDrag();
684 return 0;
687 IMPL_LINK( SaneDlg, ReloadSaneOptionsHdl, Sane*, /*pSane*/ )
689 mnCurrentOption = -1;
690 mnCurrentElement = 0;
691 DisableOption();
692 // #92024# preserve preview rect, should only be set
693 // initially or in AcquirePreview
694 Rectangle aPreviewRect = maPreviewRect;
695 InitFields();
696 maPreviewRect = aPreviewRect;
697 Rectangle aDummyRect( Point( 0, 0 ), GetSizePixel() );
698 Paint( aDummyRect );
699 return 0;
702 void SaneDlg::AcquirePreview()
704 if( ! mrSane.IsOpen() )
705 return;
707 UpdateScanArea( sal_True );
708 // set small resolution for preview
709 double fResl = (double)maReslBox.GetValue();
710 SetAdjustedNumericalValue( "resolution", 30.0 );
712 int nOption = mrSane.GetOptionByName( "preview" );
713 if( nOption == -1 )
715 String aString( SaneResId( RID_SANE_NORESOLUTIONOPTION_TXT ) );
716 WarningBox aBox( this, WB_OK_CANCEL | WB_DEF_OK, aString );
717 if( aBox.Execute() == RET_CANCEL )
718 return;
720 else
721 mrSane.SetOptionValue( nOption, (sal_Bool)sal_True );
723 BitmapTransporter aTransporter;
724 if( ! mrSane.Start( aTransporter ) )
726 ErrorBox aErrorBox( this, WB_OK | WB_DEF_OK,
727 String( SaneResId( RID_SANE_SCANERROR_TXT ) ) );
728 aErrorBox.Execute();
730 else
732 #if OSL_DEBUG_LEVEL > 1
733 aTransporter.getStream().Seek( STREAM_SEEK_TO_END );
734 fprintf( stderr, "Previewbitmapstream contains %d bytes\n", (int)aTransporter.getStream().Tell() );
735 #endif
736 aTransporter.getStream().Seek( STREAM_SEEK_TO_BEGIN );
737 maPreviewBitmap.Read( aTransporter.getStream(), sal_True );
740 SetAdjustedNumericalValue( "resolution", fResl );
741 maReslBox.SetValue( (sal_uLong)fResl );
743 if( mbDragEnable )
745 maPreviewRect = Rectangle( maTopLeft,
746 Size( maBottomRight.X() - maTopLeft.X(),
747 maBottomRight.Y() - maTopLeft.Y() )
750 else
752 Size aBMSize( maPreviewBitmap.GetSizePixel() );
753 if( aBMSize.Width() > aBMSize.Height() && aBMSize.Width() )
755 int nVHeight = (maBottomRight.X() - maTopLeft.X()) * aBMSize.Height() / aBMSize.Width();
756 maPreviewRect = Rectangle( Point( maTopLeft.X(), ( maTopLeft.Y() + maBottomRight.Y() )/2 - nVHeight/2 ),
757 Size( maBottomRight.X() - maTopLeft.X(),
758 nVHeight ) );
760 else if (aBMSize.Height())
762 int nVWidth = (maBottomRight.Y() - maTopLeft.Y()) * aBMSize.Width() / aBMSize.Height();
763 maPreviewRect = Rectangle( Point( ( maTopLeft.X() + maBottomRight.X() )/2 - nVWidth/2, maTopLeft.Y() ),
764 Size( nVWidth,
765 maBottomRight.Y() - maTopLeft.Y() ) );
769 Paint( Rectangle( Point( 0, 0 ), GetSizePixel() ) );
772 void SaneDlg::Paint( const Rectangle& rRect )
774 SetMapMode( maMapMode );
775 SetFillColor( Color( COL_WHITE ) );
776 SetLineColor( Color( COL_WHITE ) );
777 DrawRect( Rectangle( Point( PREVIEW_UPPER_LEFT, PREVIEW_UPPER_TOP ),
778 Size( PREVIEW_WIDTH, PREVIEW_HEIGHT ) ) );
779 SetMapMode( MapMode( MAP_PIXEL ) );
780 // check for sane values
781 DrawBitmap( maPreviewRect.TopLeft(), maPreviewRect.GetSize(),
782 maPreviewBitmap );
784 mbDragDrawn = sal_False;
785 DrawDrag();
787 ModalDialog::Paint( rRect );
790 void SaneDlg::DisableOption()
792 maBoolCheckBox.Show( sal_False );
793 maStringEdit.Show( sal_False );
794 maNumericEdit.Show( sal_False );
795 maQuantumRangeBox.Show( sal_False );
796 maStringRangeBox.Show( sal_False );
797 maButtonOption.Show( sal_False );
798 maVectorBox.Show( sal_False );
799 maVectorTxt.Show( sal_False );
800 maOptionDescTxt.Show( sal_False );
803 void SaneDlg::EstablishBoolOption()
805 sal_Bool bSuccess, bValue;
807 bSuccess = mrSane.GetOptionValue( mnCurrentOption, bValue );
808 if( bSuccess )
810 maOptionDescTxt.SetText( mrSane.GetOptionName( mnCurrentOption ) );
811 maOptionDescTxt.Show( sal_True );
812 maBoolCheckBox.Check( bValue );
813 maBoolCheckBox.Show( sal_True );
817 void SaneDlg::EstablishStringOption()
819 sal_Bool bSuccess;
820 OString aValue;
822 bSuccess = mrSane.GetOptionValue( mnCurrentOption, aValue );
823 if( bSuccess )
825 maOptionDescTxt.SetText( mrSane.GetOptionName( mnCurrentOption ) );
826 maOptionDescTxt.Show( sal_True );
827 maStringEdit.SetText(OStringToOUString(aValue, osl_getThreadTextEncoding()));
828 maStringEdit.Show( sal_True );
832 void SaneDlg::EstablishStringRange()
834 const char** ppStrings = mrSane.GetStringConstraint( mnCurrentOption );
835 maStringRangeBox.Clear();
836 for( int i = 0; ppStrings[i] != 0; i++ )
837 maStringRangeBox.InsertEntry( String( ppStrings[i], osl_getThreadTextEncoding() ) );
838 OString aValue;
839 mrSane.GetOptionValue( mnCurrentOption, aValue );
840 maStringRangeBox.SelectEntry(OStringToOUString(aValue, osl_getThreadTextEncoding()));
841 maStringRangeBox.Show( sal_True );
842 maOptionDescTxt.SetText( mrSane.GetOptionName( mnCurrentOption ) );
843 maOptionDescTxt.Show( sal_True );
846 void SaneDlg::EstablishQuantumRange()
848 if( mpRange )
850 delete [] mpRange;
851 mpRange = 0;
853 int nValues = mrSane.GetRange( mnCurrentOption, mpRange );
854 if( nValues == 0 )
856 mfMin = mpRange[ 0 ];
857 mfMax = mpRange[ 1 ];
858 delete [] mpRange;
859 mpRange = 0;
860 EstablishNumericOption();
862 else if( nValues > 0 )
864 char pBuf[ 256 ];
865 maQuantumRangeBox.Clear();
866 mfMin = mpRange[ 0 ];
867 mfMax = mpRange[ nValues-1 ];
868 for( int i = 0; i < nValues; i++ )
870 sprintf( pBuf, "%g", mpRange[ i ] );
871 maQuantumRangeBox.InsertEntry( String( pBuf, osl_getThreadTextEncoding() ) );
873 double fValue;
874 if( mrSane.GetOptionValue( mnCurrentOption, fValue, mnCurrentElement ) )
876 sprintf( pBuf, "%g", fValue );
877 maQuantumRangeBox.SelectEntry( String( pBuf, osl_getThreadTextEncoding() ) );
879 maQuantumRangeBox.Show( sal_True );
880 String aText( mrSane.GetOptionName( mnCurrentOption ) );
881 aText += ' ';
882 aText += mrSane.GetOptionUnitName( mnCurrentOption );
883 maOptionDescTxt.SetText( aText );
884 maOptionDescTxt.Show( sal_True );
888 void SaneDlg::EstablishNumericOption()
890 sal_Bool bSuccess;
891 double fValue;
893 bSuccess = mrSane.GetOptionValue( mnCurrentOption, fValue );
894 if( ! bSuccess )
895 return;
897 char pBuf[256];
898 String aText( mrSane.GetOptionName( mnCurrentOption ) );
899 aText += ' ';
900 aText += mrSane.GetOptionUnitName( mnCurrentOption );
901 if( mfMin != mfMax )
903 sprintf( pBuf, " < %g ; %g >", mfMin, mfMax );
904 aText += String( pBuf, osl_getThreadTextEncoding() );
906 maOptionDescTxt.SetText( aText );
907 maOptionDescTxt.Show( sal_True );
908 sprintf( pBuf, "%g", fValue );
909 maNumericEdit.SetText( String( pBuf, osl_getThreadTextEncoding() ) );
910 maNumericEdit.Show( sal_True );
913 void SaneDlg::EstablishButtonOption()
915 maOptionDescTxt.SetText( mrSane.GetOptionName( mnCurrentOption ) );
916 maOptionDescTxt.Show( sal_True );
917 maButtonOption.Show( sal_True );
920 #define RECT_SIZE_PIX 7
922 void SaneDlg::MouseMove( const MouseEvent& rMEvt )
924 if( mbIsDragging )
926 Point aMousePos = rMEvt.GetPosPixel();
927 // move into valid area
928 Point aLogicPos = GetLogicPos( aMousePos );
929 aMousePos = GetPixelPos( aLogicPos );
930 switch( meDragDirection )
932 case TopLeft: maTopLeft = aMousePos; break;
933 case Top: maTopLeft.Y() = aMousePos.Y(); break;
934 case TopRight:
935 maTopLeft.Y() = aMousePos.Y();
936 maBottomRight.X() = aMousePos.X();
937 break;
938 case Right: maBottomRight.X() = aMousePos.X(); break;
939 case BottomRight: maBottomRight = aMousePos; break;
940 case Bottom: maBottomRight.Y() = aMousePos.Y(); break;
941 case BottomLeft:
942 maTopLeft.X() = aMousePos.X();
943 maBottomRight.Y() = aMousePos.Y();
944 break;
945 case Left: maTopLeft.X() = aMousePos.X(); break;
946 default: break;
948 int nSwap;
949 if( maTopLeft.X() > maBottomRight.X() )
951 nSwap = maTopLeft.X();
952 maTopLeft.X() = maBottomRight.X();
953 maBottomRight.X() = nSwap;
955 if( maTopLeft.Y() > maBottomRight.Y() )
957 nSwap = maTopLeft.Y();
958 maTopLeft.Y() = maBottomRight.Y();
959 maBottomRight.Y() = nSwap;
961 DrawDrag();
962 UpdateScanArea( sal_False );
964 ModalDialog::MouseMove( rMEvt );
967 void SaneDlg::MouseButtonDown( const MouseEvent& rMEvt )
969 Point aMousePixel = rMEvt.GetPosPixel();
971 if( ! mbIsDragging && mbDragEnable )
973 int nMiddleX = ( maBottomRight.X() - maTopLeft.X() ) / 2 - RECT_SIZE_PIX/2 + maTopLeft.X();
974 int nMiddleY = ( maBottomRight.Y() - maTopLeft.Y() ) / 2 - RECT_SIZE_PIX/2 + maTopLeft.Y();
975 if( aMousePixel.Y() >= maTopLeft.Y() &&
976 aMousePixel.Y() < maTopLeft.Y() + RECT_SIZE_PIX )
978 if( aMousePixel.X() >= maTopLeft.X() &&
979 aMousePixel.X() < maTopLeft.X() + RECT_SIZE_PIX )
981 meDragDirection = TopLeft;
982 aMousePixel = maTopLeft;
983 mbIsDragging = sal_True;
985 else if( aMousePixel.X() >= nMiddleX &&
986 aMousePixel.X() < nMiddleX + RECT_SIZE_PIX )
988 meDragDirection = Top;
989 aMousePixel.Y() = maTopLeft.Y();
990 mbIsDragging = sal_True;
992 else if( aMousePixel.X() > maBottomRight.X() - RECT_SIZE_PIX &&
993 aMousePixel.X() <= maBottomRight.X() )
995 meDragDirection = TopRight;
996 aMousePixel = Point( maBottomRight.X(), maTopLeft.Y() );
997 mbIsDragging = sal_True;
1000 else if( aMousePixel.Y() >= nMiddleY &&
1001 aMousePixel.Y() < nMiddleY + RECT_SIZE_PIX )
1003 if( aMousePixel.X() >= maTopLeft.X() &&
1004 aMousePixel.X() < maTopLeft.X() + RECT_SIZE_PIX )
1006 meDragDirection = Left;
1007 aMousePixel.X() = maTopLeft.X();
1008 mbIsDragging = sal_True;
1010 else if( aMousePixel.X() > maBottomRight.X() - RECT_SIZE_PIX &&
1011 aMousePixel.X() <= maBottomRight.X() )
1013 meDragDirection = Right;
1014 aMousePixel.X() = maBottomRight.X();
1015 mbIsDragging = sal_True;
1018 else if( aMousePixel.Y() <= maBottomRight.Y() &&
1019 aMousePixel.Y() > maBottomRight.Y() - RECT_SIZE_PIX )
1021 if( aMousePixel.X() >= maTopLeft.X() &&
1022 aMousePixel.X() < maTopLeft.X() + RECT_SIZE_PIX )
1024 meDragDirection = BottomLeft;
1025 aMousePixel = Point( maTopLeft.X(), maBottomRight.Y() );
1026 mbIsDragging = sal_True;
1028 else if( aMousePixel.X() >= nMiddleX &&
1029 aMousePixel.X() < nMiddleX + RECT_SIZE_PIX )
1031 meDragDirection = Bottom;
1032 aMousePixel.Y() = maBottomRight.Y();
1033 mbIsDragging = sal_True;
1035 else if( aMousePixel.X() > maBottomRight.X() - RECT_SIZE_PIX &&
1036 aMousePixel.X() <= maBottomRight.X() )
1038 meDragDirection = BottomRight;
1039 aMousePixel = maBottomRight;
1040 mbIsDragging = sal_True;
1044 if( mbIsDragging )
1046 SetPointerPosPixel( aMousePixel );
1047 DrawDrag();
1049 ModalDialog::MouseButtonDown( rMEvt );
1052 void SaneDlg::MouseButtonUp( const MouseEvent& rMEvt )
1054 if( mbIsDragging )
1056 UpdateScanArea( sal_True );
1058 mbIsDragging = sal_False;
1060 ModalDialog::MouseButtonUp( rMEvt );
1063 void SaneDlg::DrawRectangles( Point& rUL, Point& rBR )
1065 int nMiddleX, nMiddleY;
1066 Point aBL, aUR;
1068 aUR = Point( rBR.X(), rUL.Y() );
1069 aBL = Point( rUL.X(), rBR.Y() );
1070 nMiddleX = ( rBR.X() - rUL.X() ) / 2 + rUL.X();
1071 nMiddleY = ( rBR.Y() - rUL.Y() ) / 2 + rUL.Y();
1073 DrawLine( rUL, aBL );
1074 DrawLine( aBL, rBR );
1075 DrawLine( rBR, aUR );
1076 DrawLine( aUR, rUL );
1077 DrawRect( Rectangle( rUL, Size( RECT_SIZE_PIX,RECT_SIZE_PIX ) ) );
1078 DrawRect( Rectangle( aBL, Size( RECT_SIZE_PIX, -RECT_SIZE_PIX ) ) );
1079 DrawRect( Rectangle( rBR, Size( -RECT_SIZE_PIX, -RECT_SIZE_PIX ) ) );
1080 DrawRect( Rectangle( aUR, Size( -RECT_SIZE_PIX, RECT_SIZE_PIX ) ) );
1081 DrawRect( Rectangle( Point( nMiddleX - RECT_SIZE_PIX/2, rUL.Y() ), Size( RECT_SIZE_PIX, RECT_SIZE_PIX ) ) );
1082 DrawRect( Rectangle( Point( nMiddleX - RECT_SIZE_PIX/2, rBR.Y() ), Size( RECT_SIZE_PIX, -RECT_SIZE_PIX ) ) );
1083 DrawRect( Rectangle( Point( rUL.X(), nMiddleY - RECT_SIZE_PIX/2 ), Size( RECT_SIZE_PIX, RECT_SIZE_PIX ) ) );
1084 DrawRect( Rectangle( Point( rBR.X(), nMiddleY - RECT_SIZE_PIX/2 ), Size( -RECT_SIZE_PIX, RECT_SIZE_PIX ) ) );
1087 void SaneDlg::DrawDrag()
1089 static Point aLastUL, aLastBR;
1091 if( ! mbDragEnable )
1092 return;
1094 RasterOp eROP = GetRasterOp();
1095 SetRasterOp( ROP_INVERT );
1096 SetMapMode( MapMode( MAP_PIXEL ) );
1098 if( mbDragDrawn )
1099 DrawRectangles( aLastUL, aLastBR );
1101 aLastUL = maTopLeft;
1102 aLastBR = maBottomRight;
1103 DrawRectangles( maTopLeft, maBottomRight );
1105 mbDragDrawn = sal_True;
1106 SetRasterOp( eROP );
1107 SetMapMode( maMapMode );
1110 Point SaneDlg::GetPixelPos( const Point& rIn )
1112 Point aConvert(
1113 ( ( rIn.X() * PREVIEW_WIDTH ) /
1114 ( maMaxBottomRight.X() - maMinTopLeft.X() ) )
1115 + PREVIEW_UPPER_LEFT,
1116 ( ( rIn.Y() * PREVIEW_HEIGHT )
1117 / ( maMaxBottomRight.Y() - maMinTopLeft.Y() ) )
1118 + PREVIEW_UPPER_TOP );
1120 return LogicToPixel( aConvert, maMapMode );
1123 Point SaneDlg::GetLogicPos( const Point& rIn )
1125 Point aConvert = PixelToLogic( rIn, maMapMode );
1126 aConvert.X() -= PREVIEW_UPPER_LEFT;
1127 aConvert.Y() -= PREVIEW_UPPER_TOP;
1128 if( aConvert.X() < 0 )
1129 aConvert.X() = 0;
1130 if( aConvert.X() >= PREVIEW_WIDTH )
1131 aConvert.X() = PREVIEW_WIDTH-1;
1132 if( aConvert.Y() < 0 )
1133 aConvert.Y() = 0;
1134 if( aConvert.Y() >= PREVIEW_HEIGHT )
1135 aConvert.Y() = PREVIEW_HEIGHT-1;
1137 aConvert.X() *= ( maMaxBottomRight.X() - maMinTopLeft.X() );
1138 aConvert.X() /= PREVIEW_WIDTH;
1139 aConvert.Y() *= ( maMaxBottomRight.Y() - maMinTopLeft.Y() );
1140 aConvert.Y() /= PREVIEW_HEIGHT;
1141 return aConvert;
1144 void SaneDlg::UpdateScanArea( sal_Bool bSend )
1146 if( ! mbDragEnable )
1147 return;
1149 Point aUL = GetLogicPos( maTopLeft );
1150 Point aBR = GetLogicPos( maBottomRight );
1152 maLeftField.SetValue( aUL.X() );
1153 maTopField.SetValue( aUL.Y() );
1154 maRightField.SetValue( aBR.X() );
1155 maBottomField.SetValue( aBR.Y() );
1157 if( ! bSend )
1158 return;
1160 if( mrSane.IsOpen() )
1162 SetAdjustedNumericalValue( "tl-x", (double)aUL.X() );
1163 SetAdjustedNumericalValue( "tl-y", (double)aUL.Y() );
1164 SetAdjustedNumericalValue( "br-x", (double)aBR.X() );
1165 SetAdjustedNumericalValue( "br-y", (double)aBR.Y() );
1169 sal_Bool SaneDlg::LoadState()
1171 int i;
1173 if( ! Sane::IsSane() )
1174 return sal_False;
1176 const char* pEnv = getenv("HOME");
1177 String aFileName( pEnv ? pEnv : "", osl_getThreadTextEncoding() );
1178 aFileName += String( RTL_CONSTASCII_USTRINGPARAM( "/.so_sane_state" ) );
1179 Config aConfig( aFileName );
1180 if( ! aConfig.HasGroup( "SANE" ) )
1181 return sal_False;
1183 aConfig.SetGroup( "SANE" );
1184 OString aString = aConfig.ReadKey( "SO_LastSaneDevice" );
1185 for( i = 0; i < Sane::CountDevices() && !aString.equals(OUStringToOString(Sane::GetName(i), osl_getThreadTextEncoding())); i++ ) ;
1186 if( i == Sane::CountDevices() )
1187 return sal_False;
1189 mrSane.Close();
1190 mrSane.Open( aString.getStr() );
1192 DisableOption();
1193 InitFields();
1195 if( mrSane.IsOpen() )
1197 int iMax = aConfig.GetKeyCount();
1198 for (i = 0; i < iMax; ++i)
1200 aString = aConfig.GetKeyName( i );
1201 OString aValue = aConfig.ReadKey( i );
1202 int nOption = mrSane.GetOptionByName( aString.getStr() );
1203 if( nOption == -1 )
1204 continue;
1206 if (aValue.matchL(RTL_CONSTASCII_STRINGPARAM("BOOL=")))
1208 aValue = aValue.copy(RTL_CONSTASCII_LENGTH("BOOL="));
1209 sal_Bool aBOOL = (sal_Bool)aValue.toInt32();
1210 mrSane.SetOptionValue( nOption, aBOOL );
1212 else if (aValue.matchL(RTL_CONSTASCII_STRINGPARAM("STRING=")))
1214 aValue = aValue.copy(RTL_CONSTASCII_LENGTH("STRING="));
1215 mrSane.SetOptionValue(nOption,OStringToOUString(aValue, osl_getThreadTextEncoding()) );
1217 else if (aValue.matchL(RTL_CONSTASCII_STRINGPARAM("NUMERIC=")))
1219 aValue = aValue.copy(RTL_CONSTASCII_LENGTH("NUMERIC="));
1221 sal_Int32 nIndex = 0;
1222 int n = 0;
1225 OString aSub = aValue.getToken(0, ':', nIndex);
1226 double fValue=0.0;
1227 sscanf(aSub.getStr(), "%lg", &fValue);
1228 SetAdjustedNumericalValue(aString.getStr(), fValue, n++);
1230 while ( nIndex >= 0 );
1235 DisableOption();
1236 InitFields();
1238 return sal_True;
1241 void SaneDlg::SaveState()
1243 if( ! Sane::IsSane() )
1244 return;
1246 const char* pEnv = getenv( "HOME" );
1247 String aFileName( pEnv ? pEnv : "", osl_getThreadTextEncoding() );
1248 aFileName.AppendAscii( "/.so_sane_state" );
1250 Config aConfig( aFileName );
1251 aConfig.DeleteGroup( "SANE" );
1252 aConfig.SetGroup( "SANE" );
1253 aConfig.WriteKey( "SO_LastSANEDevice",
1254 OUStringToOString(maDeviceBox.GetSelectEntry(), RTL_TEXTENCODING_UTF8) );
1256 static char const* pSaveOptions[] = {
1257 "resolution",
1258 "tl-x",
1259 "tl-y",
1260 "br-x",
1261 "br-y"
1263 for( size_t i = 0; i < SAL_N_ELEMENTS(pSaveOptions); ++i )
1265 OString aOption = pSaveOptions[i];
1266 int nOption = mrSane.GetOptionByName( pSaveOptions[i] );
1267 if( nOption > -1 )
1269 SANE_Value_Type nType = mrSane.GetOptionType( nOption );
1270 switch( nType )
1272 case SANE_TYPE_BOOL:
1274 sal_Bool bValue;
1275 if( mrSane.GetOptionValue( nOption, bValue ) )
1277 OStringBuffer aString(RTL_CONSTASCII_STRINGPARAM(
1278 "BOOL="));
1279 aString.append(static_cast<sal_Int32>(bValue));
1280 aConfig.WriteKey(aOption, aString.makeStringAndClear());
1283 break;
1284 case SANE_TYPE_STRING:
1286 OString aValue;
1287 if( mrSane.GetOptionValue( nOption, aValue ) )
1289 OStringBuffer aString(RTL_CONSTASCII_STRINGPARAM("STRING="));
1290 aString.append(aValue);
1291 aConfig.WriteKey( aOption, aString.makeStringAndClear() );
1294 break;
1295 case SANE_TYPE_FIXED:
1296 case SANE_TYPE_INT:
1298 OStringBuffer aString(RTL_CONSTASCII_STRINGPARAM("NUMERIC="));
1299 double fValue;
1300 char buf[256];
1301 int n;
1303 for( n = 0; n < mrSane.GetOptionElements( nOption ); n++ )
1305 if( ! mrSane.GetOptionValue( nOption, fValue, n ) )
1306 break;
1307 if( n > 0 )
1308 aString.append(':');
1309 sprintf( buf, "%lg", fValue );
1310 aString.append(buf);
1312 if( n >= mrSane.GetOptionElements( nOption ) )
1313 aConfig.WriteKey( aOption, aString.makeStringAndClear() );
1315 break;
1316 default:
1317 break;
1323 sal_Bool SaneDlg::SetAdjustedNumericalValue(
1324 const char* pOption,
1325 double fValue,
1326 int nElement )
1328 int nOption;
1329 if( ! Sane::IsSane() || ! mrSane.IsOpen() || ( nOption = mrSane.GetOptionByName( pOption ) ) == -1 )
1330 return sal_False;
1332 if( nElement < 0 || nElement >= mrSane.GetOptionElements( nOption ) )
1333 return sal_False;
1335 double* pValues = NULL;
1336 int nValues;
1337 if( ( nValues = mrSane.GetRange( nOption, pValues ) ) < 0 )
1338 return sal_False;
1340 #if OSL_DEBUG_LEVEL > 1
1341 fprintf( stderr, "SaneDlg::SetAdjustedNumericalValue( \"%s\", %lg ) ",
1342 pOption, fValue );
1343 #endif
1345 if( nValues )
1347 int nNearest = 0;
1348 double fNearest = 1e6;
1349 for( int i = 0; i < nValues; i++ )
1351 if( fabs( fValue - pValues[ i ] ) < fNearest )
1353 fNearest = fabs( fValue - pValues[ i ] );
1354 nNearest = i;
1357 fValue = pValues[ nNearest ];
1359 else
1361 if( fValue < pValues[0] )
1362 fValue = pValues[0];
1363 if( fValue > pValues[1] )
1364 fValue = pValues[1];
1366 delete [] pValues;
1367 mrSane.SetOptionValue( nOption, fValue, nElement );
1368 #if OSL_DEBUG_LEVEL > 1
1369 fprintf( stderr, "yields %lg\n", fValue );
1370 #endif
1373 return sal_True;
1376 bool SaneDlg::getDoScan()
1378 return doScan;
1381 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */