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