1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_fpicker.hxx" 30 31 //------------------------------------------------------------------------ 32 // includes 33 //------------------------------------------------------------------------ 34 #include <osl/diagnose.h> 35 #include <rtl/ustrbuf.hxx> 36 #include "AutoBuffer.hxx" 37 #include "WinImplHelper.hxx" 38 #include <com/sun/star/uno/Sequence.hxx> 39 40 //------------------------------------------------------------ 41 // namespace directives 42 //------------------------------------------------------------ 43 44 using rtl::OUString; 45 using rtl::OUStringBuffer; 46 using ::com::sun::star::lang::IllegalArgumentException; 47 using ::com::sun::star::uno::Reference; 48 using ::com::sun::star::uno::XInterface; 49 using ::com::sun::star::uno::Any; 50 using ::com::sun::star::uno::Sequence; 51 52 //------------------------------------------------------------ 53 // 54 //------------------------------------------------------------ 55 56 const rtl::OUString TILDE = OUString::createFromAscii( "~" ); 57 const sal_Unicode TILDE_SIGN = L'~'; 58 const rtl::OUString AMPERSAND = OUString::createFromAscii( "&" ); 59 const sal_Unicode AMPERSAND_SIGN = L'&'; 60 61 //------------------------------------------------------------ 62 // OS NAME Platform Major Minor 63 // 64 // Windows NT 3.51 VER_PLATFORM_WIN32_NT 3 51 65 // Windows NT 4.0 VER_PLATFORM_WIN32_NT 4 0 66 // Windows 2000 VER_PLATFORM_WIN32_NT 5 0 67 // Windows XP VER_PLATFORM_WIN32_NT 5 1 68 // Windows Vista VER_PLATFORM_WIN32_NT 6 0 69 // Windows 7 VER_PLATFORM_WIN32_NT 6 1 70 // Windows 95 VER_PLATFORM_WIN32_WINDOWS 4 0 71 // Windows 98 VER_PLATFORM_WIN32_WINDOWS 4 10 72 // Windows ME VER_PLATFORM_WIN32_WINDOWS 4 90 73 //------------------------------------------------------------ 74 75 bool SAL_CALL IsWindowsVersion(unsigned int PlatformId, unsigned int MajorVersion, int MinorVersion = -1) 76 { 77 OSVERSIONINFO osvi; 78 osvi.dwOSVersionInfoSize = sizeof(osvi); 79 80 if(!GetVersionEx(&osvi)) 81 return false; 82 83 bool bRet = (PlatformId == osvi.dwPlatformId) && 84 (MajorVersion == osvi.dwMajorVersion); 85 86 if (MinorVersion > -1) 87 bRet = bRet && 88 (sal::static_int_cast< unsigned int >(MinorVersion) == 89 osvi.dwMinorVersion); 90 91 return bRet; 92 } 93 94 //------------------------------------------------------------ 95 // determine if we are running under Vista or newer OS 96 //------------------------------------------------------------ 97 98 bool SAL_CALL IsWindowsVistaOrNewer() 99 { 100 OSVERSIONINFO osvi; 101 osvi.dwOSVersionInfoSize = sizeof(osvi); 102 103 if(!GetVersionEx(&osvi)) 104 return false; 105 106 bool bRet = (VER_PLATFORM_WIN32_NT == osvi.dwPlatformId) && 107 (osvi.dwMajorVersion >= 6); 108 109 bRet = bRet && 110 (osvi.dwMinorVersion >= 111 sal::static_int_cast< unsigned int >(0)); 112 113 return bRet; 114 } 115 116 //------------------------------------------------------------ 117 // determine if we are running under Windows 7 118 //------------------------------------------------------------ 119 120 bool SAL_CALL IsWindows7() 121 { 122 return IsWindowsVersion(VER_PLATFORM_WIN32_NT, 6, 1); 123 } 124 125 //------------------------------------------------------------ 126 // determine if we are running under Windows Vista 127 //------------------------------------------------------------ 128 129 bool SAL_CALL IsWindowsVista() 130 { 131 return IsWindowsVersion(VER_PLATFORM_WIN32_NT, 6, 0); 132 } 133 134 //------------------------------------------------------------ 135 // determine if we are running under Windows XP 136 //------------------------------------------------------------ 137 138 bool SAL_CALL IsWindowsXP() 139 { 140 return IsWindowsVersion(VER_PLATFORM_WIN32_NT, 5, 1); 141 } 142 143 //------------------------------------------------------------ 144 // determine if we are running under Windows 2000 145 //------------------------------------------------------------ 146 147 bool SAL_CALL IsWindows2000() 148 { 149 return IsWindowsVersion(VER_PLATFORM_WIN32_NT, 5, 0); 150 } 151 152 //------------------------------------------------------------ 153 // 154 //------------------------------------------------------------ 155 156 bool SAL_CALL IsWindows98() 157 { 158 return IsWindowsVersion(VER_PLATFORM_WIN32_WINDOWS, 4, 10); 159 } 160 161 //------------------------------------------------------------ 162 // 163 //------------------------------------------------------------ 164 165 bool SAL_CALL IsWindowsME() 166 { 167 return IsWindowsVersion(VER_PLATFORM_WIN32_WINDOWS, 4, 90); 168 } 169 170 //------------------------------------------------------------ 171 // 172 //------------------------------------------------------------ 173 174 bool SAL_CALL IsWindows2000Platform() 175 { 176 // POST: return true if we are at least on Windows 2000 177 178 // WRONG!: return IsWindowsVersion(VER_PLATFORM_WIN32_NT, 5); 179 180 OSVERSIONINFO osvi; 181 ZeroMemory(&osvi, sizeof(osvi)); 182 osvi.dwOSVersionInfoSize = sizeof(osvi); 183 GetVersionEx(&osvi); 184 if ( osvi.dwMajorVersion >= 5 ) 185 { 186 return true; 187 } 188 return false; 189 } 190 191 //------------------------------------------------------------ 192 // 193 //------------------------------------------------------------ 194 195 void SAL_CALL ListboxAddString( HWND hwnd, const OUString& aString ) 196 { 197 LRESULT rc = SendMessageW( 198 hwnd, CB_ADDSTRING, 0, reinterpret_cast< LPARAM >(aString.getStr( )) ); 199 (void) rc; // avoid warning 200 OSL_ASSERT( (CB_ERR != rc) && (CB_ERRSPACE != rc) ); 201 } 202 203 //------------------------------------------------------------ 204 // 205 //------------------------------------------------------------ 206 207 OUString SAL_CALL ListboxGetString( HWND hwnd, sal_Int32 aPosition ) 208 { 209 OSL_ASSERT( IsWindow( hwnd ) ); 210 211 OUString aString; 212 213 LRESULT lItem = 214 SendMessageW( hwnd, CB_GETLBTEXTLEN, aPosition, 0 ); 215 216 if ( (CB_ERR != lItem) && (lItem > 0) ) 217 { 218 // message returns the len of a combobox item 219 // without trailing '\0' that's why += 1 220 lItem++; 221 222 CAutoUnicodeBuffer aBuff( lItem ); 223 224 LRESULT lRet = 225 SendMessageW( 226 hwnd, CB_GETLBTEXT, aPosition, 227 reinterpret_cast<LPARAM>(&aBuff) ); 228 229 OSL_ASSERT( lRet != CB_ERR ); 230 231 if ( CB_ERR != lRet ) 232 aString = OUString( aBuff, lRet ); 233 } 234 235 return aString; 236 } 237 238 //------------------------------------------------------------ 239 // 240 //------------------------------------------------------------ 241 242 void SAL_CALL ListboxAddItem( HWND hwnd, const Any& aItem, const Reference< XInterface >& rXInterface, sal_Int16 aArgPos ) 243 throw( IllegalArgumentException ) 244 { 245 OSL_ASSERT( IsWindow( hwnd ) ); 246 247 if ( !aItem.hasValue( ) || 248 aItem.getValueType( ) != getCppuType((OUString*)0) ) 249 throw IllegalArgumentException( 250 OUString::createFromAscii( "invalid value type or any has no value" ), 251 rXInterface, 252 aArgPos ); 253 254 OUString cbItem; 255 aItem >>= cbItem; 256 257 ListboxAddString( hwnd, cbItem ); 258 } 259 260 //------------------------------------------------------------ 261 // 262 //------------------------------------------------------------ 263 264 void SAL_CALL ListboxAddItems( HWND hwnd, const Any& aItemList, const Reference< XInterface >& rXInterface, sal_Int16 aArgPos ) 265 throw( IllegalArgumentException ) 266 { 267 OSL_ASSERT( IsWindow( hwnd ) ); 268 269 if ( !aItemList.hasValue( ) || 270 aItemList.getValueType( ) != getCppuType((Sequence<OUString>*)0) ) 271 throw IllegalArgumentException( 272 OUString::createFromAscii( "invalid value type or any has no value" ), 273 rXInterface, 274 aArgPos ); 275 276 Sequence< OUString > aStringList; 277 aItemList >>= aStringList; 278 279 sal_Int32 nItemCount = aStringList.getLength( ); 280 for( sal_Int32 i = 0; i < nItemCount; i++ ) 281 { 282 ListboxAddString( hwnd, aStringList[i] ); 283 } 284 } 285 286 //------------------------------------------------------------ 287 // 288 //------------------------------------------------------------ 289 290 void SAL_CALL ListboxDeleteItem( HWND hwnd, const Any& aPosition, const Reference< XInterface >& rXInterface, sal_Int16 aArgPos ) 291 throw( IllegalArgumentException ) 292 { 293 OSL_ASSERT( IsWindow( hwnd ) ); 294 295 if ( !aPosition.hasValue( ) || 296 ( (aPosition.getValueType( ) != getCppuType((sal_Int32*)0)) && 297 (aPosition.getValueType( ) != getCppuType((sal_Int16*)0)) && 298 (aPosition.getValueType( ) != getCppuType((sal_Int8*)0)) ) ) 299 throw IllegalArgumentException( 300 OUString::createFromAscii( "invalid value type or any has no value" ), 301 rXInterface, 302 aArgPos ); 303 304 sal_Int32 nPos; 305 aPosition >>= nPos; 306 307 LRESULT lRet = SendMessage( hwnd, CB_DELETESTRING, nPos, 0 ); 308 309 // if the return value is CB_ERR the given 310 // index was not correct 311 if ( CB_ERR == lRet ) 312 throw IllegalArgumentException( 313 OUString::createFromAscii( "inavlid item position" ), 314 rXInterface, 315 aArgPos ); 316 } 317 318 //------------------------------------------------------------ 319 // 320 //------------------------------------------------------------ 321 322 void SAL_CALL ListboxDeleteItems( HWND hwnd, const Any&, const Reference< XInterface >&, sal_Int16 ) 323 throw( IllegalArgumentException ) 324 { 325 OSL_ASSERT( IsWindow( hwnd ) ); 326 327 LRESULT lRet = 0; 328 329 do 330 { 331 // the return value on success is the number 332 // of remaining elements in the listbox 333 lRet = SendMessageW( hwnd, CB_DELETESTRING, 0, 0 ); 334 } 335 while ( (lRet != CB_ERR) && (lRet > 0) ); 336 } 337 338 //------------------------------------------------------------ 339 // 340 //------------------------------------------------------------ 341 342 void SAL_CALL ListboxSetSelectedItem( HWND hwnd, const Any& aPosition, const Reference< XInterface >& rXInterface, sal_Int16 aArgPos ) 343 throw( IllegalArgumentException ) 344 { 345 OSL_ASSERT( IsWindow( hwnd ) ); 346 347 if ( !aPosition.hasValue( ) || 348 ( (aPosition.getValueType( ) != getCppuType((sal_Int32*)0)) && 349 (aPosition.getValueType( ) != getCppuType((sal_Int16*)0)) && 350 (aPosition.getValueType( ) != getCppuType((sal_Int8*)0)) ) ) 351 throw IllegalArgumentException( 352 OUString::createFromAscii( "invalid value type or any has no value" ), 353 rXInterface, 354 aArgPos ); 355 356 sal_Int32 nPos; 357 aPosition >>= nPos; 358 359 if ( nPos < -1 ) 360 throw IllegalArgumentException( 361 OUString::createFromAscii("invalid index"), 362 rXInterface, 363 aArgPos ); 364 365 LRESULT lRet = SendMessageW( hwnd, CB_SETCURSEL, nPos, 0 ); 366 367 if ( (CB_ERR == lRet) && (-1 != nPos) ) 368 throw IllegalArgumentException( 369 OUString::createFromAscii("invalid index"), 370 rXInterface, 371 aArgPos ); 372 } 373 374 //------------------------------------------------------------ 375 // 376 //------------------------------------------------------------ 377 378 Any SAL_CALL ListboxGetItems( HWND hwnd ) 379 { 380 OSL_ASSERT( IsWindow( hwnd ) ); 381 382 LRESULT nItemCount = SendMessageW( hwnd, CB_GETCOUNT, 0, 0 ); 383 384 Sequence< OUString > aItemList; 385 386 if ( CB_ERR != nItemCount ) 387 { 388 aItemList.realloc( nItemCount ); 389 390 for ( sal_Int32 i = 0; i < nItemCount; i++ ) 391 { 392 aItemList[i] = ListboxGetString( hwnd, i ); 393 } 394 } 395 396 Any aAny; 397 aAny <<= aItemList; 398 399 return aAny; 400 } 401 402 //------------------------------------------------------------ 403 // 404 //------------------------------------------------------------ 405 406 Any SAL_CALL ListboxGetSelectedItem( HWND hwnd ) 407 { 408 OSL_ASSERT( IsWindow( hwnd ) ); 409 410 LRESULT idxItem = SendMessageW( hwnd, CB_GETCURSEL, 0, 0 ); 411 412 Any aAny; 413 aAny <<= ListboxGetString( hwnd, idxItem ); 414 415 return aAny; 416 } 417 418 //------------------------------------------------------------ 419 // 420 //------------------------------------------------------------ 421 422 Any SAL_CALL ListboxGetSelectedItemIndex( HWND hwnd ) 423 { 424 OSL_ASSERT( IsWindow( hwnd ) ); 425 426 LRESULT idxItem = SendMessageW( hwnd, CB_GETCURSEL, 0, 0 ); 427 428 Any aAny; 429 aAny <<= static_cast< sal_Int32 >( idxItem ); 430 431 return aAny; 432 } 433 434 //------------------------------------------------------------ 435 // 436 //------------------------------------------------------------ 437 438 Any SAL_CALL CheckboxGetState( HWND hwnd ) 439 { 440 OSL_ASSERT( IsWindow( hwnd ) ); 441 442 LRESULT lChkState = SendMessageW( hwnd, BM_GETCHECK, 0, 0 ); 443 sal_Bool bChkState = (lChkState == BST_CHECKED) ? sal_True : sal_False; 444 Any aAny; 445 aAny.setValue( &bChkState, getCppuType((sal_Bool*)0) ); 446 return aAny; 447 } 448 449 //------------------------------------------------------------ 450 // 451 //------------------------------------------------------------ 452 453 void SAL_CALL CheckboxSetState( 454 HWND hwnd, const ::com::sun::star::uno::Any& aState, const Reference< XInterface >& rXInterface, sal_Int16 aArgPos ) 455 throw( IllegalArgumentException ) 456 { 457 OSL_ASSERT( IsWindow( hwnd ) ); 458 459 if ( !aState.hasValue( ) || 460 aState.getValueType( ) != getCppuType((sal_Bool*)0) ) 461 throw IllegalArgumentException( 462 OUString::createFromAscii( "invalid value type or any has no value" ), 463 rXInterface, 464 aArgPos ); 465 466 sal_Bool bCheckState = *reinterpret_cast< const sal_Bool* >( aState.getValue( ) ); 467 WPARAM wParam = bCheckState ? BST_CHECKED : BST_UNCHECKED; 468 SendMessageW( hwnd, BM_SETCHECK, wParam, 0 ); 469 } 470 471 //------------------------------------------------------------ 472 // 473 //------------------------------------------------------------ 474 475 sal_uInt32 SAL_CALL _wcslenex( const sal_Unicode* pStr ) 476 { 477 if ( !pStr ) 478 return 0; 479 480 const sal_Unicode* pTemp = pStr; 481 sal_uInt32 strLen = 0; 482 while( *pTemp || *(pTemp + 1) ) 483 { 484 pTemp++; 485 strLen++; 486 } 487 488 return strLen; 489 } 490 491 //------------------------------------------------------------ 492 // 493 //------------------------------------------------------------ 494 495 void Replace( const OUString& aLabel, sal_Unicode OldChar, sal_Unicode NewChar, OUStringBuffer& aBuffer ) 496 { 497 OSL_ASSERT( aLabel.getLength( ) ); 498 OSL_ASSERT( aBuffer.getCapacity( ) >= (aLabel.getLength( )) ); 499 500 sal_Int32 i = 0; 501 const sal_Unicode* pCurrent = aLabel.getStr( ); 502 const sal_Unicode* pNext = aLabel.getStr( ) + 1; 503 const sal_Unicode* pEnd = aLabel.getStr( ) + aLabel.getLength( ); 504 505 while( pCurrent < pEnd ) 506 { 507 OSL_ASSERT( pNext <= pEnd ); 508 OSL_ASSERT( (i >= 0) && (i < aBuffer.getCapacity( )) ); 509 510 if ( OldChar == *pCurrent ) 511 { 512 if ( OldChar == *pNext ) 513 { 514 // two OldChars in line will 515 // be replaced by one 516 // e.g. ~~ -> ~ 517 aBuffer.insert( i, *pCurrent ); 518 519 // skip the next one 520 pCurrent++; 521 pNext++; 522 } 523 else 524 { 525 // one OldChar will be replace 526 // by NexChar 527 aBuffer.insert( i, NewChar ); 528 } 529 } 530 else if ( *pCurrent == NewChar ) 531 { 532 // a NewChar will be replaced by 533 // two NewChars 534 // e.g. & -> && 535 aBuffer.insert( i++, *pCurrent ); 536 aBuffer.insert( i, *pCurrent ); 537 } 538 else 539 { 540 aBuffer.insert( i, *pCurrent ); 541 } 542 543 pCurrent++; 544 pNext++; 545 i++; 546 } 547 } 548 549 //------------------------------------------------------------ 550 // converts a soffice label to a windows label 551 // the following rules for character replacements 552 // will be done: 553 // '~' -> '&' 554 // '~~' -> '~' 555 // '&' -> '&&' 556 //------------------------------------------------------------ 557 558 OUString SOfficeToWindowsLabel( const rtl::OUString& aSOLabel ) 559 { 560 OUString aWinLabel = aSOLabel; 561 562 if ( (aWinLabel.indexOf( TILDE ) > -1) || (aWinLabel.indexOf( AMPERSAND ) > -1) ) 563 { 564 sal_Int32 nStrLen = aWinLabel.getLength( ); 565 566 // in the worst case the new string is 567 // doubled in length, maybe some waste 568 // of memory but how long is a label 569 // normaly(?) 570 rtl::OUStringBuffer aBuffer( nStrLen * 2 ); 571 572 Replace( aWinLabel, TILDE_SIGN, AMPERSAND_SIGN, aBuffer ); 573 574 aWinLabel = aBuffer.makeStringAndClear( ); 575 } 576 577 return aWinLabel; 578 } 579 580 //------------------------------------------------------------ 581 // converts a windows label to a soffice label 582 // the following rules for character replacements 583 // will be done: 584 // '&' -> '~' 585 // '&&' -> '&' 586 // '~' -> '~~' 587 //------------------------------------------------------------ 588 589 OUString WindowsToSOfficeLabel( const rtl::OUString& aWinLabel ) 590 { 591 OUString aSOLabel = aWinLabel; 592 593 if ( (aSOLabel.indexOf( TILDE ) > -1) || (aSOLabel.indexOf( AMPERSAND ) > -1) ) 594 { 595 sal_Int32 nStrLen = aSOLabel.getLength( ); 596 597 // in the worst case the new string is 598 // doubled in length, maybe some waste 599 // of memory but how long is a label 600 // normaly(?) 601 rtl::OUStringBuffer aBuffer( nStrLen * 2 ); 602 603 Replace( aSOLabel, AMPERSAND_SIGN, TILDE_SIGN, aBuffer ); 604 605 aSOLabel = aBuffer.makeStringAndClear( ); 606 } 607 608 return aSOLabel; 609 } 610 611