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