1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 // MARKER(update_precomp.py): autogen include statement, do not remove
23 #include "precompiled_extensions.hxx"
24 
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <tools/config.hxx>
28 #include <vcl/msgbox.hxx>
29 #include <sanedlg.hxx>
30 #include <sanedlg.hrc>
31 #include <grid.hxx>
32 #include <math.h>
33 #include <vcl/dibtools.hxx>
34 
35 #define USE_SAVE_STATE
36 #undef  SAVE_ALL_STATES
37 
SaneResId(sal_uInt32 nID)38 ResId SaneResId( sal_uInt32 nID )
39 {
40 	static ResMgr* pResMgr = ResMgr::CreateResMgr( "san" );
41 	return ResId( nID, *pResMgr );
42 }
43 
SaneDlg(Window * pParent,Sane & rSane)44 SaneDlg::SaneDlg( Window* pParent, Sane& rSane ) :
45 		ModalDialog( pParent, SaneResId( RID_SANE_DIALOG ) ),
46 		mrSane( rSane ),
47 		mbIsDragging( sal_False ),
48 		mbDragDrawn( sal_False ),
49 		maMapMode( MAP_APPFONT ),
50 		maOKButton( this, SaneResId( RID_SCAN_OK ) ),
51 		maCancelButton( this, SaneResId( RID_SCAN_CANCEL ) ),
52 		maDeviceInfoButton( this, SaneResId( RID_DEVICEINFO_BTN ) ),
53 		maPreviewButton( this, SaneResId( RID_PREVIEW_BTN ) ),
54 		maButtonOption( this, SaneResId( RID_SCAN_BUTTON_OPTION_BTN ) ),
55 		maOptionsTxt( this, SaneResId( RID_SCAN_OPTION_TXT ) ),
56 		maOptionTitle( this, SaneResId( RID_SCAN_OPTIONTITLE_TXT ) ),
57 		maOptionDescTxt( this, SaneResId( RID_SCAN_OPTION_DESC_TXT ) ),
58 		maVectorTxt( this, SaneResId( RID_SCAN_NUMERIC_VECTOR_TXT ) ),
59 		maScanLeftTxt( this, SaneResId( RID_SCAN_LEFT_TXT ) ),
60 		maLeftField( this, SaneResId( RID_SCAN_LEFT_BOX ) ),
61 		maScanTopTxt( this, SaneResId( RID_SCAN_TOP_TXT ) ),
62 		maTopField( this, SaneResId( RID_SCAN_TOP_BOX ) ),
63 		maRightTxt( this, SaneResId( RID_SCAN_RIGHT_TXT ) ),
64 		maRightField( this, SaneResId( RID_SCAN_RIGHT_BOX ) ),
65 		maBottomTxt( this, SaneResId( RID_SCAN_BOTTOM_TXT ) ),
66 		maBottomField( this, SaneResId( RID_SCAN_BOTTOM_BOX ) ),
67 		maDeviceBoxTxt( this, SaneResId( RID_DEVICE_BOX_TXT ) ),
68 		maDeviceBox( this, SaneResId( RID_DEVICE_BOX ) ),
69 		maReslTxt( this, SaneResId( RID_SCAN_RESOLUTION_TXT ) ),
70 		maReslBox( this, SaneResId( RID_SCAN_RESOLUTION_BOX ) ),
71 		maAdvancedTxt( this, SaneResId( RID_SCAN_ADVANCED_TXT ) ),
72 		maAdvancedBox( this, SaneResId( RID_SCAN_ADVANCED_BOX ) ),
73 		maVectorBox( this, SaneResId( RID_SCAN_NUMERIC_VECTOR_BOX ) ),
74 		maQuantumRangeBox( this, SaneResId( RID_SCAN_QUANTUM_RANGE_BOX ) ),
75 		maStringRangeBox( this, SaneResId( RID_SCAN_STRING_RANGE_BOX ) ),
76 		maPreviewBox( this, SaneResId( RID_PREVIEW_BOX ) ),
77 		maAreaBox( this, SaneResId( RID_SCANAREA_BOX ) ),
78 		maBoolCheckBox( this, SaneResId( RID_SCAN_BOOL_OPTION_BOX ) ),
79 		maStringEdit( this, SaneResId( RID_SCAN_STRING_OPTION_EDT ) ),
80 		maNumericEdit( this, SaneResId( RID_SCAN_NUMERIC_OPTION_EDT ) ),
81 		maOptionBox( this, SaneResId( RID_SCAN_OPTION_BOX ) ),
82 		mpRange( 0 )
83 {
84 	if( Sane::IsSane() )
85 	{
86 		InitDevices(); // opens first sane device
87 		DisableOption();
88 		InitFields();
89 	}
90 
91 	maDeviceInfoButton.SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) );
92 	maPreviewButton.SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) );
93 	maButtonOption.SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) );
94 	maDeviceBox.SetSelectHdl( LINK( this, SaneDlg, SelectHdl ) );
95 	maOptionBox.SetSelectHdl( LINK( this, SaneDlg, OptionsBoxSelectHdl ) );
96 	maOKButton.SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) );
97 	maCancelButton.SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) );
98 	maBoolCheckBox.SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) );
99 	maStringEdit.SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) );
100 	maNumericEdit.SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) );
101 	maVectorBox.SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) );
102 	maReslBox.SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) );
103 	maStringRangeBox.SetSelectHdl( LINK( this, SaneDlg, SelectHdl ) );
104 	maQuantumRangeBox.SetSelectHdl( LINK( this, SaneDlg, SelectHdl ) );
105 	maLeftField.SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) );
106 	maRightField.SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) );
107 	maTopField.SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) );
108 	maBottomField.SetModifyHdl( LINK( this, SaneDlg, ModifyHdl ) );
109 	maAdvancedBox.SetClickHdl( LINK( this, SaneDlg, ClickBtnHdl ) );
110 
111 	maOldLink = mrSane.SetReloadOptionsHdl( LINK( this, SaneDlg, ReloadSaneOptionsHdl ) );
112 
113 	maOptionBox.SetNodeBitmaps(
114 		Bitmap( SaneResId( RID_SCAN_BITMAP_PLUS ) ),
115 		Bitmap( SaneResId( RID_SCAN_BITMAP_MINUS ) )
116 		);
117 	maOptionBox.SetStyle( maOptionBox.GetStyle()|
118                           WB_HASLINES           |
119 						  WB_HASBUTTONS         |
120 						  WB_NOINITIALSELECTION |
121 						  WB_HASBUTTONSATROOT   |
122 						  WB_HASLINESATROOT
123 						);
124 	FreeResource();
125 }
126 
~SaneDlg()127 SaneDlg::~SaneDlg()
128 {
129 }
130 
Execute()131 short SaneDlg::Execute()
132 {
133 	if( ! Sane::IsSane() )
134 	{
135 		ErrorBox aErrorBox( NULL, WB_OK | WB_DEF_OK,
136 							String( SaneResId( RID_SANE_NOSANELIB_TXT ) ) );
137 		aErrorBox.Execute();
138 		return sal_False;
139 	}
140 	LoadState();
141 	return ModalDialog::Execute();
142 }
143 
InitDevices()144 void SaneDlg::InitDevices()
145 {
146 	if( ! Sane::IsSane() )
147 		return;
148 
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() )
156 	{
157 		mrSane.Open( 0 );
158 		maDeviceBox.SelectEntry( Sane::GetName( 0 ) );
159 
160 	}
161 }
162 
InitFields()163 void SaneDlg::InitFields()
164 {
165 	if( ! Sane::IsSane() )
166 		return;
167 
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"
178 	};
179 
180     mbDragEnable = sal_True;
181 	maReslBox.Clear();
182 	maMinTopLeft = Point( 0, 0 );
183 	maMaxBottomRight = Point( PREVIEW_WIDTH,  PREVIEW_HEIGHT );
184 
185 	if( ! mrSane.IsOpen() )
186 		return;
187 
188 	// set Resolution
189 	nOption = mrSane.GetOptionByName( "resolution" );
190 	if( nOption != -1 )
191 	{
192 		double fRes;
193 
194 		bSuccess = mrSane.GetOptionValue( nOption, fRes );
195 		if( bSuccess )
196 		{
197 			maReslBox.Enable( sal_True );
198 
199 			maReslBox.SetValue( (long)fRes );
200 			double *pDouble = NULL;
201 			nValue = mrSane.GetRange( nOption, pDouble );
202 			if( nValue > -1 )
203 			{
204 				if( nValue )
205 				{
206 					maReslBox.SetMin( (long)pDouble[0] );
207 					maReslBox.SetMax( (long)pDouble[ nValue-1 ] );
208 					for( i=0; i<nValue; i++ )
209 					{
210 						if( i == 0 || i == nValue-1 || ! ( ((int)pDouble[i]) % 20) )
211 							maReslBox.InsertValue( (long)pDouble[i] );
212 					}
213 				}
214 				else
215 				{
216 					maReslBox.SetMin( (long)pDouble[0] );
217 					maReslBox.SetMax( (long)pDouble[1] );
218 					maReslBox.InsertValue( (long)pDouble[0] );
219 					// mh@openoffice.org: issue 68557: Can only select 75 and 2400 dpi in Scanner dialogue
220 					// scanner allows random setting of dpi resolution, a slider might be useful
221 					// support that
222 					// workaround: offer at least some more standard dpi resolution between
223 					// min and max value
224 					int bGot300 = 0;
225 					for ( int nRes = (long) pDouble[0] * 2; nRes < (long) pDouble[1]; nRes = nRes * 2 )
226 					{
227 						if ( !bGot300 && nRes > 300 ) {
228 							nRes = 300; bGot300 = 1;
229 						}
230 						maReslBox.InsertValue(nRes);
231 					}
232 					maReslBox.InsertValue( (long)pDouble[1] );
233 				}
234 				if( pDouble )
235 					delete [] pDouble;
236 			}
237 			else
238 				maReslBox.Enable( sal_False );
239 		}
240 	}
241 	else
242 		maReslBox.Enable( sal_False );
243 
244 	// set scan area
245 	for( i = 0; i < 4; i++ )
246 	{
247 		char const *pOptionName = NULL;
248 		MetricField* pField = NULL;
249 		switch( i )
250 		{
251 			case 0:
252 				pOptionName = "tl-x";
253 				pField = &maLeftField;
254 				break;
255 			case 1:
256 				pOptionName = "tl-y";
257 				pField = &maTopField;
258 				break;
259 			case 2:
260 				pOptionName = "br-x";
261 				pField = &maRightField;
262 				break;
263 			case 3:
264 				pOptionName = "br-y";
265 				pField = &maBottomField;
266 		}
267 		nOption = pOptionName ? mrSane.GetOptionByName( pOptionName ) : -1;
268 		bSuccess = sal_False;
269 		if( nOption != -1 )
270 		{
271 			bSuccess = mrSane.GetOptionValue( nOption, fValue, 0 );
272 			if( bSuccess )
273 			{
274 				if( mrSane.GetOptionUnit( nOption ) == SANE_UNIT_MM )
275 				{
276 					pField->SetUnit( FUNIT_MM );
277 					pField->SetValue( (int)fValue, FUNIT_MM );
278 				}
279 				else // SANE_UNIT_PIXEL
280 				{
281 					pField->SetValue( (int)fValue, FUNIT_CUSTOM );
282 					pField->SetCustomUnitText( String::CreateFromAscii( "Pixel" ) );
283 				}
284 				switch( i ) {
285 					case 0: maTopLeft.X() = (int)fValue;break;
286 					case 1:	maTopLeft.Y() = (int)fValue;break;
287 					case 2:	maBottomRight.X() = (int)fValue;break;
288 					case 3: maBottomRight.Y() = (int)fValue;break;
289 				}
290 			}
291 			double *pDouble = NULL;
292 			nValue = mrSane.GetRange( nOption, pDouble );
293 			if( nValue > -1 )
294 			{
295 				if( pDouble )
296 				{
297 					pField->SetMin( (long)pDouble[0] );
298 					if( nValue )
299 						pField->SetMax( (long)pDouble[ nValue-1 ] );
300 					else
301 						pField->SetMax( (long)pDouble[ 1 ] );
302 					delete [] pDouble;
303 				}
304 				switch( i ) {
305 					case 0: maMinTopLeft.X() = pField->GetMin();break;
306 					case 1: maMinTopLeft.Y() = pField->GetMin();break;
307 					case 2: maMaxBottomRight.X() = pField->GetMax();break;
308 					case 3: maMaxBottomRight.Y() = pField->GetMax();break;
309 				}
310 			}
311 			else
312 			{
313 				switch( i ) {
314 					case 0: maMinTopLeft.X() = (int)fValue;break;
315 					case 1: maMinTopLeft.Y() = (int)fValue;break;
316 					case 2: maMaxBottomRight.X() = (int)fValue;break;
317 					case 3: maMaxBottomRight.Y() = (int)fValue;break;
318 				}
319 			}
320 			pField->Enable( sal_True );
321 		}
322 		else
323         {
324             mbDragEnable = sal_False;
325             pField->SetMin( 0 );
326             switch( i ) {
327                 case 0:
328                     maMinTopLeft.X() = 0;
329                     maTopLeft.X() = 0;
330                     pField->SetMax( PREVIEW_WIDTH );
331                     pField->SetValue( 0 );
332                     break;
333                 case 1:
334                     maMinTopLeft.Y() = 0;
335                     maTopLeft.Y() = 0;
336                     pField->SetMax( PREVIEW_HEIGHT );
337                     pField->SetValue( 0 );
338                     break;
339                 case 2:
340                     maMaxBottomRight.X() = PREVIEW_WIDTH;
341                     maBottomRight.X() = PREVIEW_WIDTH;
342                     pField->SetMax( PREVIEW_WIDTH );
343                     pField->SetValue( PREVIEW_WIDTH );
344                     break;
345                 case 3:
346                     maMaxBottomRight.Y() = PREVIEW_HEIGHT;
347                     maBottomRight.Y() = PREVIEW_HEIGHT;
348                     pField->SetMax( PREVIEW_HEIGHT );
349                     pField->SetValue( PREVIEW_HEIGHT );
350                     break;
351             }
352 			pField->Enable( sal_False );
353         }
354 	}
355 	maTopLeft = GetPixelPos( maTopLeft );
356 	maBottomRight = GetPixelPos( maBottomRight );
357 	maPreviewRect = Rectangle( maTopLeft,
358 							   Size( maBottomRight.X() - maTopLeft.X(),
359 									 maBottomRight.Y() - maTopLeft.Y() )
360 							   );
361 	// fill OptionBox
362 	maOptionBox.Clear();
363 	SvLBoxEntry* pParentEntry = 0;
364 	sal_Bool bGroupRejected = sal_False;
365 	for( i = 1; i < mrSane.CountOptions(); i++ )
366 	{
367 		String aOption=mrSane.GetOptionName( i );
368 		sal_Bool bInsertAdvanced =
369 			mrSane.GetOptionCap( i ) & SANE_CAP_ADVANCED &&
370 			! maAdvancedBox.IsChecked() ? sal_False : sal_True;
371 		if( mrSane.GetOptionType( i ) == SANE_TYPE_GROUP )
372 		{
373 			if( bInsertAdvanced )
374 			{
375 				aOption = mrSane.GetOptionTitle( i );
376 				pParentEntry = maOptionBox.InsertEntry( aOption );
377 				bGroupRejected = sal_False;
378 			}
379 			else
380 				bGroupRejected = sal_True;
381 		}
382 		else if( aOption.Len() &&
383 				 ! ( mrSane.GetOptionCap( i ) &
384 					 (
385 						 SANE_CAP_HARD_SELECT |
386 						 SANE_CAP_INACTIVE
387 						 ) ) &&
388 				 bInsertAdvanced && ! bGroupRejected )
389 		{
390 			sal_Bool bIsSpecial = sal_False;
391 			for( size_t n = 0; !bIsSpecial &&
392 					 n < sizeof(ppSpecialOptions)/sizeof(ppSpecialOptions[0]); n++ )
393 			{
394 				if( aOption.EqualsAscii( ppSpecialOptions[n] ) )
395 					bIsSpecial=sal_True;
396 			}
397 			if( ! bIsSpecial )
398 			{
399 				if( pParentEntry )
400 					maOptionBox.InsertEntry( aOption, pParentEntry );
401 				else
402 					maOptionBox.InsertEntry( aOption );
403 			}
404 		}
405 	}
406 }
407 
IMPL_LINK(SaneDlg,ClickBtnHdl,Button *,pButton)408 IMPL_LINK( SaneDlg, ClickBtnHdl, Button*, pButton )
409 {
410 	if( mrSane.IsOpen() )
411 	{
412 		if( pButton == &maDeviceInfoButton )
413 		{
414 			String aString( SaneResId( RID_SANE_DEVICEINFO_TXT ) );
415 			String aSR( RTL_CONSTASCII_USTRINGPARAM( "%s" ) );
416 			aString.SearchAndReplace( aSR, Sane::GetName( mrSane.GetDeviceNumber() ) );
417 			aString.SearchAndReplace( aSR, Sane::GetVendor( mrSane.GetDeviceNumber() ) );
418 			aString.SearchAndReplace( aSR, Sane::GetModel( mrSane.GetDeviceNumber() ) );
419 			aString.SearchAndReplace( aSR, Sane::GetType( mrSane.GetDeviceNumber() ) );
420 			InfoBox aInfoBox( this, aString );
421 			aInfoBox.Execute();
422 		}
423 		else if( pButton == &maPreviewButton )
424 			AcquirePreview();
425 		else if( pButton == &maBoolCheckBox )
426 		{
427 			mrSane.SetOptionValue( mnCurrentOption,
428 								   maBoolCheckBox.IsChecked() ?
429 								   (sal_Bool)sal_True : (sal_Bool)sal_False );
430 		}
431 		else if( pButton == &maButtonOption )
432 		{
433 
434 			SANE_Value_Type nType = mrSane.GetOptionType( mnCurrentOption );
435             switch( nType )
436             {
437                 case SANE_TYPE_BUTTON:
438                     mrSane.ActivateButtonOption( mnCurrentOption );
439                     break;
440                 case SANE_TYPE_FIXED:
441                 case SANE_TYPE_INT:
442                 {
443 					int nElements = mrSane.GetOptionElements( mnCurrentOption );
444                     double* x = new double[ nElements ];
445                     double* y = new double[ nElements ];
446                     for( int i = 0; i < nElements; i++ )
447                         x[ i ] = (double)i;
448                     mrSane.GetOptionValue( mnCurrentOption, y );
449 
450                     GridWindow aGrid( x, y, nElements, this );
451                     aGrid.SetText( mrSane.GetOptionName( mnCurrentOption ) );
452                     aGrid.setBoundings( 0, mfMin, nElements, mfMax );
453                     if( aGrid.Execute() && aGrid.getNewYValues() )
454                         mrSane.SetOptionValue( mnCurrentOption, aGrid.getNewYValues() );
455 
456                     delete [] x;
457                     delete [] y;
458                 }
459                 break;
460                 case SANE_TYPE_BOOL:
461                 case SANE_TYPE_STRING:
462                 case SANE_TYPE_GROUP:
463                     break;
464             }
465 		}
466 		else if( pButton == &maAdvancedBox )
467 		{
468 			ReloadSaneOptionsHdl( NULL );
469 		}
470 	}
471 	if( pButton == &maOKButton )
472 	{
473 		double fRes = (double)maReslBox.GetValue();
474 		SetAdjustedNumericalValue( "resolution", fRes );
475 		mrSane.SetReloadOptionsHdl( maOldLink );
476 		UpdateScanArea( sal_True );
477 		SaveState();
478 		EndDialog( mrSane.IsOpen() ? 1 : 0 );
479 	}
480 	else if( pButton == &maCancelButton )
481 	{
482 		mrSane.SetReloadOptionsHdl( maOldLink );
483 		mrSane.Close();
484 		EndDialog( 0 );
485 	}
486 	return 0;
487 }
488 
IMPL_LINK(SaneDlg,SelectHdl,ListBox *,pListBox)489 IMPL_LINK( SaneDlg, SelectHdl, ListBox*, pListBox )
490 {
491 	if( pListBox == &maDeviceBox && Sane::IsSane() && Sane::CountDevices() )
492 	{
493 		String aNewDevice = maDeviceBox.GetSelectEntry();
494 		int nNumber;
495 		if( aNewDevice.Equals( Sane::GetName( nNumber = mrSane.GetDeviceNumber() ) ) )
496 		{
497 			mrSane.Close();
498 			mrSane.Open( nNumber );
499 			InitFields();
500 		}
501 	}
502 	if( mrSane.IsOpen() )
503 	{
504 		if( pListBox == &maQuantumRangeBox )
505 		{
506 			ByteString aValue( maQuantumRangeBox.GetSelectEntry(), osl_getThreadTextEncoding() );
507 			double fValue = atof( aValue.GetBuffer() );
508 			mrSane.SetOptionValue( mnCurrentOption, fValue, mnCurrentElement );
509 		}
510 		else if( pListBox == &maStringRangeBox )
511 		{
512 			mrSane.SetOptionValue( mnCurrentOption, maStringRangeBox.GetSelectEntry() );
513 		}
514 	}
515 	return 0;
516 }
517 
IMPL_LINK(SaneDlg,OptionsBoxSelectHdl,SvTreeListBox *,pBox)518 IMPL_LINK( SaneDlg, OptionsBoxSelectHdl, SvTreeListBox*, pBox )
519 {
520 	if( pBox == &maOptionBox && Sane::IsSane() )
521 	{
522 		String aOption =
523 			maOptionBox.GetEntryText( maOptionBox.FirstSelected() );
524 		int nOption = mrSane.GetOptionByName( ByteString( aOption, osl_getThreadTextEncoding() ).GetBuffer() );
525 		if( nOption != -1 && nOption != mnCurrentOption )
526 		{
527 			DisableOption();
528 			mnCurrentOption = nOption;
529 			maOptionTitle.SetText( mrSane.GetOptionTitle( mnCurrentOption ) );
530 			SANE_Value_Type nType = mrSane.GetOptionType( mnCurrentOption );
531 			SANE_Constraint_Type nConstraint;
532 			switch( nType )
533 			{
534 				case SANE_TYPE_BOOL:	EstablishBoolOption();break;
535 				case SANE_TYPE_STRING:
536 					nConstraint = mrSane.GetOptionConstraintType( mnCurrentOption );
537 					if( nConstraint == SANE_CONSTRAINT_STRING_LIST )
538 						EstablishStringRange();
539 					else
540 						EstablishStringOption();
541 					break;
542 				case SANE_TYPE_FIXED:
543 				case SANE_TYPE_INT:
544 				{
545 					nConstraint = mrSane.GetOptionConstraintType( mnCurrentOption );
546 					int nElements = mrSane.GetOptionElements( mnCurrentOption );
547 					mnCurrentElement = 0;
548                     if( nConstraint == SANE_CONSTRAINT_RANGE ||
549                         nConstraint == SANE_CONSTRAINT_WORD_LIST )
550                         EstablishQuantumRange();
551                     else
552                     {
553                         mfMin = mfMax = 0.0;
554                         EstablishNumericOption();
555                     }
556 					if( nElements > 1 )
557 					{
558 						if( nElements <= 10 )
559 						{
560 							maVectorBox.SetValue( 1 );
561 							maVectorBox.SetMin( 1 );
562 							maVectorBox.SetMax(
563 								mrSane.GetOptionElements( mnCurrentOption ) );
564 							maVectorBox.Show( sal_True );
565 							maVectorTxt.Show( sal_True );
566 						}
567 						else
568 						{
569                             DisableOption();
570                             // bring up dialog only on button click
571                             EstablishButtonOption();
572 						}
573 					}
574 				}
575 				break;
576 				case SANE_TYPE_BUTTON:
577 					EstablishButtonOption();
578 					break;
579 				default: break;
580 			}
581 		}
582 	}
583 	return 0;
584 }
585 
IMPL_LINK(SaneDlg,ModifyHdl,Edit *,pEdit)586 IMPL_LINK( SaneDlg, ModifyHdl, Edit*, pEdit )
587 {
588 	if( mrSane.IsOpen() )
589 	{
590 		if( pEdit == &maStringEdit )
591 		{
592 			mrSane.SetOptionValue( mnCurrentOption, maStringEdit.GetText() );
593 		}
594 		else if( pEdit == &maReslBox )
595 		{
596 			double fRes = (double)maReslBox.GetValue();
597 			int nOption = mrSane.GetOptionByName( "resolution" );
598 			if( nOption != -1 )
599 			{
600 				double* pDouble = NULL;
601 				int nValues = mrSane.GetRange( nOption, pDouble );
602 				if( nValues > 0 )
603 				{
604 					int i;
605 					for( i = 0; i < nValues; i++ )
606 					{
607 						if( fRes == pDouble[i] )
608 							break;
609 					}
610 					if( i >= nValues )
611 						fRes = pDouble[0];
612 				}
613 				else if( nValues == 0 )
614 				{
615 					if( fRes < pDouble[ 0 ] )
616 						fRes = pDouble[ 0 ];
617 					if( fRes > pDouble[ 1 ] )
618 						fRes = pDouble[ 1 ];
619 				}
620 				maReslBox.SetValue( (sal_uLong)fRes );
621 			}
622 		}
623 		else if( pEdit == &maNumericEdit )
624 		{
625 			double fValue;
626 			char pBuf[256];
627 			ByteString aContents( maNumericEdit.GetText(), osl_getThreadTextEncoding() );
628 			fValue = atof( aContents.GetBuffer() );
629 			if( mfMin != mfMax && ( fValue < mfMin || fValue > mfMax ) )
630 			{
631 				if( fValue < mfMin )
632 					fValue = mfMin;
633 				else if( fValue > mfMax )
634 				fValue = mfMax;
635 				sprintf( pBuf, "%g", fValue );
636 				maNumericEdit.SetText( String( pBuf, osl_getThreadTextEncoding() ) );
637 			}
638 			mrSane.SetOptionValue( mnCurrentOption, fValue, mnCurrentElement );
639 		}
640 		else if( pEdit == &maVectorBox )
641 		{
642 			char pBuf[256];
643 			mnCurrentElement = maVectorBox.GetValue()-1;
644 			double fValue;
645 			mrSane.GetOptionValue( mnCurrentOption, fValue, mnCurrentElement );
646 			sprintf( pBuf, "%g", fValue );
647 			String aValue( pBuf, osl_getThreadTextEncoding() );
648 			maNumericEdit.SetText( aValue );
649 			maQuantumRangeBox.SelectEntry( aValue );
650 		}
651 		else if( pEdit == &maTopField )
652 		{
653 			Point aPoint( 0, maTopField.GetValue() );
654 			aPoint = GetPixelPos( aPoint );
655 			maTopLeft.Y() = aPoint.Y();
656 			DrawDrag();
657 		}
658 		else if( pEdit == &maLeftField )
659 		{
660 			Point aPoint( maLeftField.GetValue(), 0 );
661 			aPoint = GetPixelPos( aPoint );
662 			maTopLeft.X() = aPoint.X();
663 			DrawDrag();
664 		}
665 		else if( pEdit == &maBottomField )
666 		{
667 			Point aPoint( 0, maBottomField.GetValue() );
668 			aPoint = GetPixelPos( aPoint );
669 			maBottomRight.Y() = aPoint.Y();
670 			DrawDrag();
671 		}
672 		else if( pEdit == &maRightField )
673 		{
674 			Point aPoint( maRightField.GetValue(), 0 );
675 			aPoint = GetPixelPos( aPoint );
676 			maBottomRight.X() = aPoint.X();
677 			DrawDrag();
678 		}
679 	}
680 	return 0;
681 }
682 
683 IMPL_LINK( SaneDlg, ReloadSaneOptionsHdl, Sane*, /*pSane*/ )
684 {
685  	mnCurrentOption = -1;
686  	mnCurrentElement = 0;
687  	DisableOption();
688     // #92024# preserve preview rect, should only be set
689     // initially or in AcquirePreview
690     Rectangle aPreviewRect = maPreviewRect;
691 	InitFields();
692     maPreviewRect = aPreviewRect;
693 	Rectangle aDummyRect( Point( 0, 0 ), GetSizePixel() );
694 	Paint( aDummyRect );
695 	return 0;
696 }
697 
AcquirePreview()698 void SaneDlg::AcquirePreview()
699 {
700 	if( ! mrSane.IsOpen() )
701 		return;
702 
703 	UpdateScanArea( sal_True );
704 	// set small resolution for preview
705 	double fResl = (double)maReslBox.GetValue();
706 	SetAdjustedNumericalValue( "resolution", 30.0 );
707 
708 	int nOption = mrSane.GetOptionByName( "preview" );
709 	if( nOption == -1 )
710 	{
711 		String aString( SaneResId( RID_SANE_NORESOLUTIONOPTION_TXT ) );
712 		WarningBox aBox( this, WB_OK_CANCEL | WB_DEF_OK, aString );
713 		if( aBox.Execute() == RET_CANCEL )
714 			return;
715 	}
716 	else
717 		mrSane.SetOptionValue( nOption, (sal_Bool)sal_True );
718 
719 	BitmapTransporter aTransporter;
720 	if( ! mrSane.Start( aTransporter ) )
721 	{
722 		ErrorBox aErrorBox( this, WB_OK | WB_DEF_OK,
723 							String( SaneResId( RID_SANE_SCANERROR_TXT ) ) );
724 		aErrorBox.Execute();
725 	}
726 	else
727 	{
728 #if OSL_DEBUG_LEVEL > 1
729 		aTransporter.getStream().Seek( STREAM_SEEK_TO_END );
730 		fprintf( stderr, "Previewbitmapstream contains %d bytes\n", (int)aTransporter.getStream().Tell() );
731 #endif
732 		aTransporter.getStream().Seek( STREAM_SEEK_TO_BEGIN );
733         ReadDIB(maPreviewBitmap, aTransporter.getStream(), true);
734 	}
735 
736 	SetAdjustedNumericalValue( "resolution", fResl );
737 	maReslBox.SetValue( (sal_uLong)fResl );
738 
739     if( mbDragEnable )
740         maPreviewRect = Rectangle( maTopLeft,
741                                    Size( maBottomRight.X() - maTopLeft.X(),
742                                          maBottomRight.Y() - maTopLeft.Y() )
743                                    );
744     else
745     {
746         Size aBMSize( maPreviewBitmap.GetSizePixel() );
747         if( aBMSize.Width() > aBMSize.Height() )
748         {
749             int nVHeight = (maBottomRight.X() - maTopLeft.X()) * aBMSize.Height() / aBMSize.Width();
750             maPreviewRect = Rectangle( Point( maTopLeft.X(), ( maTopLeft.Y() + maBottomRight.Y() )/2 - nVHeight/2 ),
751                                        Size( maBottomRight.X() - maTopLeft.X(),
752                                              nVHeight ) );
753         }
754         else
755         {
756             int nVWidth = (maBottomRight.Y() - maTopLeft.Y()) * aBMSize.Width() / aBMSize.Height();
757             maPreviewRect = Rectangle( Point( ( maTopLeft.X() + maBottomRight.X() )/2 - nVWidth/2, maTopLeft.Y() ),
758                                        Size( nVWidth,
759                                              maBottomRight.Y() - maTopLeft.Y() ) );
760         }
761     }
762 
763 	Paint( Rectangle( Point( 0, 0 ), GetSizePixel() ) );
764 }
765 
Paint(const Rectangle & rRect)766 void SaneDlg::Paint( const Rectangle& rRect )
767 {
768 	SetMapMode( maMapMode );
769 	SetFillColor( Color( COL_WHITE ) );
770 	SetLineColor( Color( COL_WHITE ) );
771 	DrawRect( Rectangle( Point( PREVIEW_UPPER_LEFT, PREVIEW_UPPER_TOP ),
772 						 Size( PREVIEW_WIDTH, PREVIEW_HEIGHT ) ) );
773 	SetMapMode( MapMode( MAP_PIXEL ) );
774 	// check for sane values
775 	DrawBitmap( maPreviewRect.TopLeft(), maPreviewRect.GetSize(),
776 				maPreviewBitmap );
777 
778 	mbDragDrawn = sal_False;
779 	DrawDrag();
780 
781 	ModalDialog::Paint( rRect );
782 }
783 
DisableOption()784 void SaneDlg::DisableOption()
785 {
786 	maBoolCheckBox.Show( sal_False );
787 	maStringEdit.Show( sal_False );
788 	maNumericEdit.Show( sal_False );
789 	maQuantumRangeBox.Show( sal_False );
790 	maStringRangeBox.Show( sal_False );
791 	maButtonOption.Show( sal_False );
792 	maVectorBox.Show( sal_False );
793 	maVectorTxt.Show( sal_False );
794 	maOptionDescTxt.Show( sal_False );
795 }
796 
EstablishBoolOption()797 void SaneDlg::EstablishBoolOption()
798 {
799 	sal_Bool bSuccess, bValue;
800 
801 	bSuccess = mrSane.GetOptionValue( mnCurrentOption, bValue );
802 	if( bSuccess )
803 	{
804 		maOptionDescTxt.SetText( mrSane.GetOptionName( mnCurrentOption ) );
805 		maOptionDescTxt.Show( sal_True );
806 		maBoolCheckBox.Check( bValue );
807 		maBoolCheckBox.Show( sal_True );
808 	}
809 }
810 
EstablishStringOption()811 void SaneDlg::EstablishStringOption()
812 {
813 	sal_Bool bSuccess;
814 	ByteString aValue;
815 
816 	bSuccess = mrSane.GetOptionValue( mnCurrentOption, aValue );
817 	if( bSuccess )
818 	{
819 		maOptionDescTxt.SetText( mrSane.GetOptionName( mnCurrentOption ) );
820 		maOptionDescTxt.Show( sal_True );
821 		maStringEdit.SetText( String( aValue, osl_getThreadTextEncoding() ) );
822 		maStringEdit.Show( sal_True );
823 	}
824 }
825 
EstablishStringRange()826 void SaneDlg::EstablishStringRange()
827 {
828 	const char** ppStrings = mrSane.GetStringConstraint( mnCurrentOption );
829 	maStringRangeBox.Clear();
830 	for( int i = 0; ppStrings[i] != 0; i++ )
831 		maStringRangeBox.InsertEntry( String( ppStrings[i], osl_getThreadTextEncoding() ) );
832 	ByteString aValue;
833 	mrSane.GetOptionValue( mnCurrentOption, aValue );
834 	maStringRangeBox.SelectEntry( String( aValue, osl_getThreadTextEncoding() ) );
835 	maStringRangeBox.Show( sal_True );
836 	maOptionDescTxt.SetText( mrSane.GetOptionName( mnCurrentOption ) );
837 	maOptionDescTxt.Show( sal_True );
838 }
839 
EstablishQuantumRange()840 void SaneDlg::EstablishQuantumRange()
841 {
842 	if( mpRange )
843 	{
844 		delete [] mpRange;
845 		mpRange = 0;
846 	}
847 	int nValues = mrSane.GetRange( mnCurrentOption, mpRange );
848 	if( nValues == 0 )
849 	{
850 		mfMin = mpRange[ 0 ];
851 		mfMax = mpRange[ 1 ];
852 		delete [] mpRange;
853 		mpRange = 0;
854 		EstablishNumericOption();
855 	}
856 	else if( nValues > 0 )
857 	{
858 		char pBuf[ 256 ];
859 		maQuantumRangeBox.Clear();
860 		mfMin = mpRange[ 0 ];
861 		mfMax = mpRange[ nValues-1 ];
862 		for( int i = 0; i < nValues; i++ )
863 		{
864 			sprintf( pBuf, "%g", mpRange[ i ] );
865 			maQuantumRangeBox.InsertEntry( String( pBuf, osl_getThreadTextEncoding() ) );
866 		}
867 		double fValue;
868 		if( mrSane.GetOptionValue( mnCurrentOption, fValue, mnCurrentElement ) )
869 		{
870 			sprintf( pBuf, "%g", fValue );
871 			maQuantumRangeBox.SelectEntry( String( pBuf, osl_getThreadTextEncoding() ) );
872 		}
873 		maQuantumRangeBox.Show( sal_True );
874 		String aText( mrSane.GetOptionName( mnCurrentOption ) );
875 		aText += ' ';
876 		aText += mrSane.GetOptionUnitName( mnCurrentOption );
877 		maOptionDescTxt.SetText( aText );
878 		maOptionDescTxt.Show( sal_True );
879 	}
880 }
881 
EstablishNumericOption()882 void SaneDlg::EstablishNumericOption()
883 {
884 	sal_Bool bSuccess;
885 	double fValue;
886 
887 	bSuccess = mrSane.GetOptionValue( mnCurrentOption, fValue );
888 	if( ! bSuccess )
889 		return;
890 
891 	char pBuf[256];
892 	String aText( mrSane.GetOptionName( mnCurrentOption ) );
893 	aText += ' ';
894 	aText += mrSane.GetOptionUnitName( mnCurrentOption );
895 	if( mfMin != mfMax )
896 	{
897 		sprintf( pBuf, " < %g ; %g >", mfMin, mfMax );
898 		aText += String( pBuf, osl_getThreadTextEncoding() );
899 	}
900 	maOptionDescTxt.SetText( aText );
901 	maOptionDescTxt.Show( sal_True );
902 	sprintf( pBuf, "%g", fValue );
903 	maNumericEdit.SetText( String( pBuf, osl_getThreadTextEncoding() ) );
904 	maNumericEdit.Show( sal_True );
905 }
906 
EstablishButtonOption()907 void SaneDlg::EstablishButtonOption()
908 {
909 	maOptionDescTxt.SetText( mrSane.GetOptionName( mnCurrentOption ) );
910 	maOptionDescTxt.Show( sal_True );
911 	maButtonOption.Show( sal_True );
912 }
913 
914 #define RECT_SIZE_PIX 7
915 
MouseMove(const MouseEvent & rMEvt)916 void SaneDlg::MouseMove( const MouseEvent& rMEvt )
917 {
918 	if( mbIsDragging )
919 	{
920 		Point aMousePos = rMEvt.GetPosPixel();
921 		// move into valid area
922 		Point aLogicPos = GetLogicPos( aMousePos );
923 		aMousePos = GetPixelPos( aLogicPos );
924 		switch( meDragDirection )
925 		{
926 			case TopLeft:		maTopLeft = aMousePos; break;
927 			case Top:			maTopLeft.Y() = aMousePos.Y(); break;
928 			case TopRight:
929 				maTopLeft.Y() = aMousePos.Y();
930 				maBottomRight.X() = aMousePos.X();
931 				break;
932 			case Right:			maBottomRight.X() = aMousePos.X(); break;
933 			case BottomRight:	maBottomRight = aMousePos; break;
934 			case Bottom:		maBottomRight.Y() = aMousePos.Y(); break;
935 			case BottomLeft:
936 				maTopLeft.X() = aMousePos.X();
937 				maBottomRight.Y() = aMousePos.Y();
938 				break;
939 			case Left:			maTopLeft.X() = aMousePos.X(); break;
940 			default: break;
941 		}
942 		int nSwap;
943 		if( maTopLeft.X() > maBottomRight.X() )
944 		{
945 			nSwap = maTopLeft.X();
946 			maTopLeft.X() = maBottomRight.X();
947 			maBottomRight.X() = nSwap;
948 		}
949 		if( maTopLeft.Y() > maBottomRight.Y() )
950 		{
951 			nSwap = maTopLeft.Y();
952 			maTopLeft.Y() = maBottomRight.Y();
953 			maBottomRight.Y() = nSwap;
954 		}
955 		DrawDrag();
956 		UpdateScanArea( sal_False );
957 	}
958 	ModalDialog::MouseMove( rMEvt );
959 }
960 
MouseButtonDown(const MouseEvent & rMEvt)961 void SaneDlg::MouseButtonDown( const MouseEvent& rMEvt )
962 {
963 	Point aMousePixel = rMEvt.GetPosPixel();
964 
965 	if( ! mbIsDragging  && mbDragEnable )
966 	{
967 		int nMiddleX = ( maBottomRight.X() - maTopLeft.X() ) / 2 - RECT_SIZE_PIX/2 + maTopLeft.X();
968 		int nMiddleY = ( maBottomRight.Y() - maTopLeft.Y() ) / 2 - RECT_SIZE_PIX/2 + maTopLeft.Y();
969 		if( aMousePixel.Y() >= maTopLeft.Y() &&
970 			aMousePixel.Y() < maTopLeft.Y() + RECT_SIZE_PIX )
971 		{
972 			if( aMousePixel.X() >= maTopLeft.X() &&
973 				aMousePixel.X() < maTopLeft.X() + RECT_SIZE_PIX )
974 			{
975 				meDragDirection = TopLeft;
976 				aMousePixel = maTopLeft;
977 				mbIsDragging = sal_True;
978 			}
979 			else if( aMousePixel.X() >= nMiddleX &&
980 					 aMousePixel.X() < nMiddleX + RECT_SIZE_PIX )
981 			{
982 				meDragDirection = Top;
983 				aMousePixel.Y() = maTopLeft.Y();
984 				mbIsDragging = sal_True;
985 			}
986 			else if( aMousePixel.X() > maBottomRight.X() - RECT_SIZE_PIX &&
987 					 aMousePixel.X() <= maBottomRight.X() )
988 			{
989 				meDragDirection = TopRight;
990 				aMousePixel = Point( maBottomRight.X(), maTopLeft.Y() );
991 				mbIsDragging = sal_True;
992 			}
993 		}
994 		else if( aMousePixel.Y() >= nMiddleY &&
995 				 aMousePixel.Y() < nMiddleY + RECT_SIZE_PIX )
996 		{
997 			if( aMousePixel.X() >= maTopLeft.X() &&
998 				aMousePixel.X() < maTopLeft.X() + RECT_SIZE_PIX )
999 			{
1000 				meDragDirection = Left;
1001 				aMousePixel.X() = maTopLeft.X();
1002 				mbIsDragging = sal_True;
1003 			}
1004 			else if( aMousePixel.X() > maBottomRight.X() - RECT_SIZE_PIX &&
1005 					 aMousePixel.X() <= maBottomRight.X() )
1006 			{
1007 				meDragDirection = Right;
1008 				aMousePixel.X() = maBottomRight.X();
1009 				mbIsDragging = sal_True;
1010 			}
1011 		}
1012 		else if( aMousePixel.Y() <= maBottomRight.Y() &&
1013 				 aMousePixel.Y() > maBottomRight.Y() - RECT_SIZE_PIX )
1014 		{
1015 			if( aMousePixel.X() >= maTopLeft.X() &&
1016 				aMousePixel.X() < maTopLeft.X() + RECT_SIZE_PIX )
1017 			{
1018 				meDragDirection = BottomLeft;
1019 				aMousePixel = Point( maTopLeft.X(), maBottomRight.Y() );
1020 				mbIsDragging = sal_True;
1021 			}
1022 			else if( aMousePixel.X() >= nMiddleX &&
1023 					 aMousePixel.X() < nMiddleX + RECT_SIZE_PIX )
1024 			{
1025 				meDragDirection = Bottom;
1026 				aMousePixel.Y() = maBottomRight.Y();
1027 				mbIsDragging = sal_True;
1028 			}
1029 			else if( aMousePixel.X() > maBottomRight.X() - RECT_SIZE_PIX &&
1030 					 aMousePixel.X() <= maBottomRight.X() )
1031 			{
1032 				meDragDirection = BottomRight;
1033 				aMousePixel = maBottomRight;
1034 				mbIsDragging = sal_True;
1035 			}
1036 		}
1037 	}
1038 	if( mbIsDragging )
1039 	{
1040 		SetPointerPosPixel( aMousePixel );
1041 		DrawDrag();
1042 	}
1043 	ModalDialog::MouseButtonDown( rMEvt );
1044 }
1045 
MouseButtonUp(const MouseEvent & rMEvt)1046 void SaneDlg::MouseButtonUp( const MouseEvent& rMEvt )
1047 {
1048 	if( mbIsDragging )
1049 	{
1050 		UpdateScanArea( sal_True );
1051 	}
1052 	mbIsDragging = sal_False;
1053 
1054 	ModalDialog::MouseButtonUp( rMEvt );
1055 }
1056 
DrawRectangles(Point & rUL,Point & rBR)1057 void SaneDlg::DrawRectangles( Point& rUL, Point& rBR )
1058 {
1059 	int nMiddleX, nMiddleY;
1060 	Point aBL, aUR;
1061 
1062 	aUR = Point( rBR.X(), rUL.Y() );
1063 	aBL = Point( rUL.X(), rBR.Y() );
1064 	nMiddleX = ( rBR.X() - rUL.X() ) / 2 + rUL.X();
1065 	nMiddleY = ( rBR.Y() - rUL.Y() ) / 2 + rUL.Y();
1066 
1067 	DrawLine( rUL, aBL );
1068 	DrawLine( aBL, rBR );
1069 	DrawLine( rBR, aUR );
1070 	DrawLine( aUR, rUL );
1071 	DrawRect( Rectangle( rUL, Size( RECT_SIZE_PIX,RECT_SIZE_PIX ) ) );
1072 	DrawRect( Rectangle( aBL, Size( RECT_SIZE_PIX, -RECT_SIZE_PIX ) ) );
1073 	DrawRect( Rectangle( rBR, Size( -RECT_SIZE_PIX, -RECT_SIZE_PIX ) ) );
1074 	DrawRect( Rectangle( aUR, Size( -RECT_SIZE_PIX, RECT_SIZE_PIX ) ) );
1075 	DrawRect( Rectangle( Point( nMiddleX - RECT_SIZE_PIX/2, rUL.Y() ), Size( RECT_SIZE_PIX, RECT_SIZE_PIX ) ) );
1076 	DrawRect( Rectangle( Point( nMiddleX - RECT_SIZE_PIX/2, rBR.Y() ), Size( RECT_SIZE_PIX, -RECT_SIZE_PIX ) ) );
1077 	DrawRect( Rectangle( Point( rUL.X(), nMiddleY - RECT_SIZE_PIX/2 ), Size( RECT_SIZE_PIX, RECT_SIZE_PIX ) ) );
1078 	DrawRect( Rectangle( Point( rBR.X(), nMiddleY - RECT_SIZE_PIX/2 ), Size( -RECT_SIZE_PIX, RECT_SIZE_PIX ) ) );
1079 }
1080 
DrawDrag()1081 void SaneDlg::DrawDrag()
1082 {
1083 	static Point aLastUL, aLastBR;
1084 
1085     if( ! mbDragEnable )
1086         return;
1087 
1088 	RasterOp eROP = GetRasterOp();
1089 	SetRasterOp( ROP_INVERT );
1090 	SetMapMode( MapMode( MAP_PIXEL ) );
1091 
1092 	if( mbDragDrawn )
1093 		DrawRectangles( aLastUL, aLastBR );
1094 
1095 	aLastUL = maTopLeft;
1096 	aLastBR = maBottomRight;
1097 	DrawRectangles( maTopLeft, maBottomRight );
1098 
1099 	mbDragDrawn = sal_True;
1100 	SetRasterOp( eROP );
1101 	SetMapMode( maMapMode );
1102 }
1103 
GetPixelPos(const Point & rIn)1104 Point SaneDlg::GetPixelPos( const Point& rIn )
1105 {
1106 	Point aConvert(
1107 		( ( rIn.X() * PREVIEW_WIDTH ) /
1108 		  ( maMaxBottomRight.X() - maMinTopLeft.X() ) )
1109 		+ PREVIEW_UPPER_LEFT,
1110 		( ( rIn.Y() * PREVIEW_HEIGHT )
1111 		  / ( maMaxBottomRight.Y() - maMinTopLeft.Y() ) )
1112 		+ PREVIEW_UPPER_TOP );
1113 
1114 	return LogicToPixel( aConvert, maMapMode );
1115 }
1116 
GetLogicPos(const Point & rIn)1117 Point SaneDlg::GetLogicPos( const Point& rIn )
1118 {
1119 	Point aConvert = PixelToLogic( rIn, maMapMode );
1120 	aConvert.X() -= PREVIEW_UPPER_LEFT;
1121 	aConvert.Y() -= PREVIEW_UPPER_TOP;
1122 	if( aConvert.X() < 0 )
1123 		aConvert.X() = 0;
1124 	if( aConvert.X() >= PREVIEW_WIDTH )
1125 		aConvert.X() = PREVIEW_WIDTH-1;
1126 	if( aConvert.Y() < 0 )
1127 		aConvert.Y() = 0;
1128 	if( aConvert.Y() >= PREVIEW_HEIGHT )
1129 		aConvert.Y() = PREVIEW_HEIGHT-1;
1130 
1131 	aConvert.X() *= ( maMaxBottomRight.X() - maMinTopLeft.X() );
1132 	aConvert.X() /= PREVIEW_WIDTH;
1133 	aConvert.Y() *= ( maMaxBottomRight.Y() - maMinTopLeft.Y() );
1134 	aConvert.Y() /= PREVIEW_HEIGHT;
1135 	return aConvert;
1136 }
1137 
UpdateScanArea(sal_Bool bSend)1138 void SaneDlg::UpdateScanArea( sal_Bool bSend )
1139 {
1140     if( ! mbDragEnable )
1141         return;
1142 
1143 	Point aUL = GetLogicPos( maTopLeft );
1144 	Point aBR = GetLogicPos( maBottomRight );
1145 
1146 	maLeftField.SetValue( aUL.X() );
1147 	maTopField.SetValue( aUL.Y() );
1148 	maRightField.SetValue( aBR.X() );
1149 	maBottomField.SetValue( aBR.Y() );
1150 
1151 	if( ! bSend )
1152 		return;
1153 
1154 	if( mrSane.IsOpen() )
1155 	{
1156 		SetAdjustedNumericalValue( "tl-x", (double)aUL.X() );
1157 		SetAdjustedNumericalValue( "tl-y", (double)aUL.Y() );
1158 		SetAdjustedNumericalValue( "br-x", (double)aBR.X() );
1159 		SetAdjustedNumericalValue( "br-y", (double)aBR.Y() );
1160 	}
1161 }
1162 
LoadState()1163 sal_Bool SaneDlg::LoadState()
1164 {
1165 #ifdef USE_SAVE_STATE
1166 	int i;
1167 
1168 	if( ! Sane::IsSane() )
1169 		return sal_False;
1170 
1171 	const char* pEnv = getenv("HOME");
1172 	String aFileName( pEnv ? pEnv : "", osl_getThreadTextEncoding() );
1173 	aFileName += String( RTL_CONSTASCII_USTRINGPARAM( "/.so_sane_state" ) );
1174 	Config aConfig( aFileName );
1175 	if( ! aConfig.HasGroup( "SANE" ) )
1176 		return sal_False;
1177 
1178 	aConfig.SetGroup( "SANE" );
1179 	ByteString aString = aConfig.ReadKey( "SO_LastSaneDevice" );
1180 	for( i = 0; i < Sane::CountDevices() && ! aString.Equals( ByteString( Sane::GetName( i ), osl_getThreadTextEncoding() ) ); i++ ) ;
1181 	if( i == Sane::CountDevices() )
1182 		return sal_False;
1183 
1184 	mrSane.Close();
1185 	mrSane.Open( aString.GetBuffer() );
1186 
1187 	DisableOption();
1188 	InitFields();
1189 
1190 	if( mrSane.IsOpen() )
1191 	{
1192 		int iMax = aConfig.GetKeyCount();
1193 		for( i = 0; i < iMax; i++ )
1194 		{
1195 			aString = aConfig.GetKeyName( i );
1196 			ByteString aValue = aConfig.ReadKey( i );
1197 			int nOption = mrSane.GetOptionByName( aString.GetBuffer() );
1198 			if( nOption != -1 )
1199 			{
1200 				if( aValue.CompareTo( "BOOL=", 5 ) == COMPARE_EQUAL )
1201 				{
1202 					aValue.Erase( 0, 5 );
1203 					sal_Bool aBOOL = (sal_Bool)aValue.ToInt32();
1204 					mrSane.SetOptionValue( nOption, aBOOL );
1205 				}
1206 				else if( aValue.CompareTo( "STRING=", 7 ) == COMPARE_EQUAL )
1207 				{
1208 					aValue.Erase( 0, 7 );
1209 					mrSane.SetOptionValue( nOption, String( aValue, osl_getThreadTextEncoding() ) );
1210 				}
1211 				else if( aValue.CompareTo( "NUMERIC=", 8 ) == COMPARE_EQUAL )
1212 				{
1213 					aValue.Erase( 0, 8 );
1214 					int nMax = aValue.GetTokenCount( ':' );
1215 					double fValue=0.0;
1216 					for( int n = 0; n < nMax ; n++ )
1217 					{
1218 						ByteString aSub = aValue.GetToken( n, ':' );
1219 						sscanf( aSub.GetBuffer(), "%lg", &fValue );
1220 						SetAdjustedNumericalValue( aString.GetBuffer(), fValue, n );
1221 					}
1222 				}
1223 			}
1224 		}
1225 	}
1226 
1227 	DisableOption();
1228 	InitFields();
1229 
1230 	return sal_True;
1231 #else
1232 	return sal_False;
1233 #endif
1234 }
1235 
SaveState()1236 void SaneDlg::SaveState()
1237 {
1238 #ifdef USE_SAVE_STATE
1239 	if( ! Sane::IsSane() )
1240 		return;
1241 
1242 	const char* pEnv = getenv( "HOME" );
1243 	String aFileName( pEnv ? pEnv : "", osl_getThreadTextEncoding() );
1244 	aFileName.AppendAscii( "/.so_sane_state" );
1245 
1246 	Config aConfig( aFileName );
1247 	aConfig.DeleteGroup( "SANE" );
1248 	aConfig.SetGroup( "SANE" );
1249 	aConfig.WriteKey( "SO_LastSANEDevice", ByteString( maDeviceBox.GetSelectEntry(), RTL_TEXTENCODING_UTF8 ) );
1250 
1251 #ifdef SAVE_ALL_STATES
1252 	for( int i = 1; i < mrSane.CountOptions(); i++ )
1253 	{
1254 		String aOption=mrSane.GetOptionName( i );
1255 		SANE_Value_Type nType = mrSane.GetOptionType( i );
1256 		switch( nType )
1257 		{
1258 			case SANE_TYPE_BOOL:
1259 			{
1260 				sal_Bool bValue;
1261 				if( mrSane.GetOptionValue( i, bValue ) )
1262 				{
1263 					ByteString aString( "BOOL=" );
1264 					aString += (sal_uLong)bValue;
1265 					aConfig.WriteKey( aOption, aString );
1266 				}
1267 			}
1268 			break;
1269 			case SANE_TYPE_STRING:
1270 			{
1271 				String aString( "STRING=" );
1272 				String aValue;
1273 				if( mrSane.GetOptionValue( i, aValue ) )
1274 				{
1275 					aString += aValue;
1276 					aConfig.WriteKey( aOption, aString );
1277 				}
1278 			}
1279 			break;
1280 			case SANE_TYPE_FIXED:
1281 			case SANE_TYPE_INT:
1282 			{
1283 				String aString( "NUMERIC=" );
1284 				double fValue;
1285 				char buf[256];
1286 				for( int n = 0; n < mrSane.GetOptionElements( i ); n++ )
1287 				{
1288 					if( ! mrSane.GetOptionValue( i, fValue, n ) )
1289 						break;
1290 					if( n > 0 )
1291 						aString += ":";
1292 					sprintf( buf, "%lg", fValue );
1293 					aString += buf;
1294 				}
1295 				if( n >= mrSane.GetOptionElements( i ) )
1296 					aConfig.WriteKey( aOption, aString );
1297 			}
1298 			break;
1299 			default:
1300 				break;
1301 		}
1302  	}
1303 #else
1304 	static char const* pSaveOptions[] = {
1305 		"resolution",
1306 		"tl-x",
1307 		"tl-y",
1308 		"br-x",
1309 		"br-y"
1310 	};
1311 	for( size_t i = 0;
1312 		 i < (sizeof(pSaveOptions)/sizeof(pSaveOptions[0]));
1313 		 i++ )
1314 	{
1315 		ByteString aOption = pSaveOptions[i];
1316 		int nOption = mrSane.GetOptionByName( pSaveOptions[i] );
1317 		if( nOption > -1 )
1318 		{
1319 			SANE_Value_Type nType = mrSane.GetOptionType( nOption );
1320 			switch( nType )
1321 			{
1322 				case SANE_TYPE_BOOL:
1323 				{
1324 					sal_Bool bValue;
1325 					if( mrSane.GetOptionValue( nOption, bValue ) )
1326 					{
1327 						ByteString aString( "BOOL=" );
1328 						aString += ByteString::CreateFromInt32(bValue);
1329 						aConfig.WriteKey( aOption, aString );
1330 					}
1331 				}
1332 				break;
1333 				case SANE_TYPE_STRING:
1334 				{
1335 					ByteString aString( "STRING=" );
1336 					ByteString aValue;
1337 					if( mrSane.GetOptionValue( nOption, aValue ) )
1338 					{
1339 						aString += aValue;
1340 						aConfig.WriteKey( aOption, aString );
1341 					}
1342 				}
1343 				break;
1344 				case SANE_TYPE_FIXED:
1345 				case SANE_TYPE_INT:
1346 				{
1347 					ByteString aString( "NUMERIC=" );
1348 					double fValue;
1349 					char buf[256];
1350 					int n;
1351 
1352 					for( n = 0; n < mrSane.GetOptionElements( nOption ); n++ )
1353 					{
1354 						if( ! mrSane.GetOptionValue( nOption, fValue, n ) )
1355 							break;
1356 						if( n > 0 )
1357 							aString += ":";
1358 						sprintf( buf, "%lg", fValue );
1359 						aString += buf;
1360 					}
1361 					if( n >= mrSane.GetOptionElements( nOption ) )
1362 						aConfig.WriteKey( aOption, aString );
1363 				}
1364 				break;
1365 				default:
1366 					break;
1367 			}
1368 		}
1369 	}
1370 #endif
1371 #endif
1372 }
1373 
SetAdjustedNumericalValue(const char * pOption,double fValue,int nElement)1374 sal_Bool SaneDlg::SetAdjustedNumericalValue(
1375 	const char* pOption,
1376 	double fValue,
1377 	int nElement )
1378 {
1379 	int nOption;
1380 	if( ! Sane::IsSane() || ! mrSane.IsOpen() || ( nOption = mrSane.GetOptionByName( pOption ) ) == -1 )
1381 		return sal_False;
1382 
1383 	if( nElement < 0 || nElement >= mrSane.GetOptionElements( nOption ) )
1384 		return sal_False;
1385 
1386 	double* pValues = NULL;
1387 	int nValues;
1388 	if( ( nValues = mrSane.GetRange( nOption, pValues ) ) < 0 )
1389 		return sal_False;
1390 
1391 #if OSL_DEBUG_LEVEL > 1
1392 	fprintf( stderr, "SaneDlg::SetAdjustedNumericalValue( \"%s\", %lg ) ",
1393 			 pOption, fValue );
1394 #endif
1395 
1396 	if( nValues )
1397 	{
1398 		int nNearest = 0;
1399 		double fNearest = 1e6;
1400 		for( int i = 0; i < nValues; i++ )
1401 		{
1402 			if( fabs( fValue - pValues[ i ] ) < fNearest )
1403 			{
1404 				fNearest = fabs( fValue - pValues[ i ] );
1405 				nNearest = i;
1406 			}
1407 		}
1408 		fValue = pValues[ nNearest ];
1409 	}
1410 	else
1411 	{
1412 		if( fValue < pValues[0] )
1413 			fValue = pValues[0];
1414 		if( fValue > pValues[1] )
1415 			fValue = pValues[1];
1416 	}
1417 	delete [] pValues;
1418 	mrSane.SetOptionValue( nOption, fValue, nElement );
1419 #if OSL_DEBUG_LEVEL > 1
1420 	fprintf( stderr, "yields %lg\n", fValue );
1421 #endif
1422 
1423 
1424 	return sal_True;
1425 }
1426