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 38 ResId SaneResId( sal_uInt32 nID ) 39 { 40 static ResMgr* pResMgr = ResMgr::CreateResMgr( "san" ); 41 return ResId( nID, *pResMgr ); 42 } 43 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 127 SaneDlg::~SaneDlg() 128 { 129 } 130 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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