xref: /AOO41X/main/extensions/source/scanner/sanedlg.cxx (revision 47148b3bc50811ceb41802e4cc50a5db21535900)
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