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 { 240 OSL_ASSERT( IsWindow( hwnd ) ); 241 242 if ( !aItem.hasValue( ) || 243 aItem.getValueType( ) != getCppuType((OUString*)0) ) 244 throw IllegalArgumentException( 245 OUString::createFromAscii( "invalid value type or any has no value" ), 246 rXInterface, 247 aArgPos ); 248 249 OUString cbItem; 250 aItem >>= cbItem; 251 252 ListboxAddString( hwnd, cbItem ); 253 } 254 255 //------------------------------------------------------------ 256 // 257 //------------------------------------------------------------ 258 259 void SAL_CALL ListboxAddItems( HWND hwnd, const Any& aItemList, const Reference< XInterface >& rXInterface, sal_Int16 aArgPos ) 260 { 261 OSL_ASSERT( IsWindow( hwnd ) ); 262 263 if ( !aItemList.hasValue( ) || 264 aItemList.getValueType( ) != getCppuType((Sequence<OUString>*)0) ) 265 throw IllegalArgumentException( 266 OUString::createFromAscii( "invalid value type or any has no value" ), 267 rXInterface, 268 aArgPos ); 269 270 Sequence< OUString > aStringList; 271 aItemList >>= aStringList; 272 273 sal_Int32 nItemCount = aStringList.getLength( ); 274 for( sal_Int32 i = 0; i < nItemCount; i++ ) 275 { 276 ListboxAddString( hwnd, aStringList[i] ); 277 } 278 } 279 280 //------------------------------------------------------------ 281 // 282 //------------------------------------------------------------ 283 284 void SAL_CALL ListboxDeleteItem( HWND hwnd, const Any& aPosition, const Reference< XInterface >& rXInterface, sal_Int16 aArgPos ) 285 { 286 OSL_ASSERT( IsWindow( hwnd ) ); 287 288 if ( !aPosition.hasValue( ) || 289 ( (aPosition.getValueType( ) != getCppuType((sal_Int32*)0)) && 290 (aPosition.getValueType( ) != getCppuType((sal_Int16*)0)) && 291 (aPosition.getValueType( ) != getCppuType((sal_Int8*)0)) ) ) 292 throw IllegalArgumentException( 293 OUString::createFromAscii( "invalid value type or any has no value" ), 294 rXInterface, 295 aArgPos ); 296 297 sal_Int32 nPos; 298 aPosition >>= nPos; 299 300 LRESULT lRet = SendMessage( hwnd, CB_DELETESTRING, nPos, 0 ); 301 302 // if the return value is CB_ERR the given 303 // index was not correct 304 if ( CB_ERR == lRet ) 305 throw IllegalArgumentException( 306 OUString::createFromAscii( "invalid item position" ), 307 rXInterface, 308 aArgPos ); 309 } 310 311 //------------------------------------------------------------ 312 // 313 //------------------------------------------------------------ 314 315 void SAL_CALL ListboxDeleteItems( HWND hwnd, const Any&, const Reference< XInterface >&, sal_Int16 ) 316 { 317 OSL_ASSERT( IsWindow( hwnd ) ); 318 319 LRESULT lRet = 0; 320 321 do 322 { 323 // the return value on success is the number 324 // of remaining elements in the listbox 325 lRet = SendMessageW( hwnd, CB_DELETESTRING, 0, 0 ); 326 } 327 while ( (lRet != CB_ERR) && (lRet > 0) ); 328 } 329 330 //------------------------------------------------------------ 331 // 332 //------------------------------------------------------------ 333 334 void SAL_CALL ListboxSetSelectedItem( HWND hwnd, const Any& aPosition, const Reference< XInterface >& rXInterface, sal_Int16 aArgPos ) 335 { 336 OSL_ASSERT( IsWindow( hwnd ) ); 337 338 if ( !aPosition.hasValue( ) || 339 ( (aPosition.getValueType( ) != getCppuType((sal_Int32*)0)) && 340 (aPosition.getValueType( ) != getCppuType((sal_Int16*)0)) && 341 (aPosition.getValueType( ) != getCppuType((sal_Int8*)0)) ) ) 342 throw IllegalArgumentException( 343 OUString::createFromAscii( "invalid value type or any has no value" ), 344 rXInterface, 345 aArgPos ); 346 347 sal_Int32 nPos; 348 aPosition >>= nPos; 349 350 if ( nPos < -1 ) 351 throw IllegalArgumentException( 352 OUString::createFromAscii("invalid index"), 353 rXInterface, 354 aArgPos ); 355 356 LRESULT lRet = SendMessageW( hwnd, CB_SETCURSEL, nPos, 0 ); 357 358 if ( (CB_ERR == lRet) && (-1 != nPos) ) 359 throw IllegalArgumentException( 360 OUString::createFromAscii("invalid index"), 361 rXInterface, 362 aArgPos ); 363 } 364 365 //------------------------------------------------------------ 366 // 367 //------------------------------------------------------------ 368 369 Any SAL_CALL ListboxGetItems( HWND hwnd ) 370 { 371 OSL_ASSERT( IsWindow( hwnd ) ); 372 373 LRESULT nItemCount = SendMessageW( hwnd, CB_GETCOUNT, 0, 0 ); 374 375 Sequence< OUString > aItemList; 376 377 if ( CB_ERR != nItemCount ) 378 { 379 aItemList.realloc( nItemCount ); 380 381 for ( sal_Int32 i = 0; i < nItemCount; i++ ) 382 { 383 aItemList[i] = ListboxGetString( hwnd, i ); 384 } 385 } 386 387 Any aAny; 388 aAny <<= aItemList; 389 390 return aAny; 391 } 392 393 //------------------------------------------------------------ 394 // 395 //------------------------------------------------------------ 396 397 Any SAL_CALL ListboxGetSelectedItem( HWND hwnd ) 398 { 399 OSL_ASSERT( IsWindow( hwnd ) ); 400 401 LRESULT idxItem = SendMessageW( hwnd, CB_GETCURSEL, 0, 0 ); 402 403 Any aAny; 404 aAny <<= ListboxGetString( hwnd, idxItem ); 405 406 return aAny; 407 } 408 409 //------------------------------------------------------------ 410 // 411 //------------------------------------------------------------ 412 413 Any SAL_CALL ListboxGetSelectedItemIndex( HWND hwnd ) 414 { 415 OSL_ASSERT( IsWindow( hwnd ) ); 416 417 LRESULT idxItem = SendMessageW( hwnd, CB_GETCURSEL, 0, 0 ); 418 419 Any aAny; 420 aAny <<= static_cast< sal_Int32 >( idxItem ); 421 422 return aAny; 423 } 424 425 //------------------------------------------------------------ 426 // 427 //------------------------------------------------------------ 428 429 Any SAL_CALL CheckboxGetState( HWND hwnd ) 430 { 431 OSL_ASSERT( IsWindow( hwnd ) ); 432 433 LRESULT lChkState = SendMessageW( hwnd, BM_GETCHECK, 0, 0 ); 434 sal_Bool bChkState = (lChkState == BST_CHECKED) ? sal_True : sal_False; 435 Any aAny; 436 aAny.setValue( &bChkState, getCppuType((sal_Bool*)0) ); 437 return aAny; 438 } 439 440 //------------------------------------------------------------ 441 // 442 //------------------------------------------------------------ 443 444 void SAL_CALL CheckboxSetState( 445 HWND hwnd, const ::com::sun::star::uno::Any& aState, const Reference< XInterface >& rXInterface, sal_Int16 aArgPos ) 446 { 447 OSL_ASSERT( IsWindow( hwnd ) ); 448 449 if ( !aState.hasValue( ) || 450 aState.getValueType( ) != getCppuType((sal_Bool*)0) ) 451 throw IllegalArgumentException( 452 OUString::createFromAscii( "invalid value type or any has no value" ), 453 rXInterface, 454 aArgPos ); 455 456 sal_Bool bCheckState = *reinterpret_cast< const sal_Bool* >( aState.getValue( ) ); 457 WPARAM wParam = bCheckState ? BST_CHECKED : BST_UNCHECKED; 458 SendMessageW( hwnd, BM_SETCHECK, wParam, 0 ); 459 } 460 461 //------------------------------------------------------------ 462 // 463 //------------------------------------------------------------ 464 465 sal_uInt32 SAL_CALL _wcslenex( const sal_Unicode* pStr ) 466 { 467 if ( !pStr ) 468 return 0; 469 470 const sal_Unicode* pTemp = pStr; 471 sal_uInt32 strLen = 0; 472 while( *pTemp || *(pTemp + 1) ) 473 { 474 pTemp++; 475 strLen++; 476 } 477 478 return strLen; 479 } 480 481 //------------------------------------------------------------ 482 // 483 //------------------------------------------------------------ 484 485 void Replace( const OUString& aLabel, sal_Unicode OldChar, sal_Unicode NewChar, OUStringBuffer& aBuffer ) 486 { 487 OSL_ASSERT( aLabel.getLength( ) ); 488 OSL_ASSERT( aBuffer.getCapacity( ) >= (aLabel.getLength( )) ); 489 490 sal_Int32 i = 0; 491 const sal_Unicode* pCurrent = aLabel.getStr( ); 492 const sal_Unicode* pNext = aLabel.getStr( ) + 1; 493 const sal_Unicode* pEnd = aLabel.getStr( ) + aLabel.getLength( ); 494 495 while( pCurrent < pEnd ) 496 { 497 OSL_ASSERT( pNext <= pEnd ); 498 OSL_ASSERT( (i >= 0) && (i < aBuffer.getCapacity( )) ); 499 500 if ( OldChar == *pCurrent ) 501 { 502 if ( OldChar == *pNext ) 503 { 504 // two OldChars in line will 505 // be replaced by one 506 // e.g. ~~ -> ~ 507 aBuffer.insert( i, *pCurrent ); 508 509 // skip the next one 510 pCurrent++; 511 pNext++; 512 } 513 else 514 { 515 // one OldChar will be replace 516 // by NexChar 517 aBuffer.insert( i, NewChar ); 518 } 519 } 520 else if ( *pCurrent == NewChar ) 521 { 522 // a NewChar will be replaced by 523 // two NewChars 524 // e.g. & -> && 525 aBuffer.insert( i++, *pCurrent ); 526 aBuffer.insert( i, *pCurrent ); 527 } 528 else 529 { 530 aBuffer.insert( i, *pCurrent ); 531 } 532 533 pCurrent++; 534 pNext++; 535 i++; 536 } 537 } 538 539 //------------------------------------------------------------ 540 // converts a soffice label to a windows label 541 // the following rules for character replacements 542 // will be done: 543 // '~' -> '&' 544 // '~~' -> '~' 545 // '&' -> '&&' 546 //------------------------------------------------------------ 547 548 OUString SOfficeToWindowsLabel( const rtl::OUString& aSOLabel ) 549 { 550 OUString aWinLabel = aSOLabel; 551 552 if ( (aWinLabel.indexOf( TILDE ) > -1) || (aWinLabel.indexOf( AMPERSAND ) > -1) ) 553 { 554 sal_Int32 nStrLen = aWinLabel.getLength( ); 555 556 // in the worst case the new string is 557 // doubled in length, maybe some waste 558 // of memory but how long is a label 559 // normally(?) 560 rtl::OUStringBuffer aBuffer( nStrLen * 2 ); 561 562 Replace( aWinLabel, TILDE_SIGN, AMPERSAND_SIGN, aBuffer ); 563 564 aWinLabel = aBuffer.makeStringAndClear( ); 565 } 566 567 return aWinLabel; 568 } 569 570 //------------------------------------------------------------ 571 // converts a windows label to a soffice label 572 // the following rules for character replacements 573 // will be done: 574 // '&' -> '~' 575 // '&&' -> '&' 576 // '~' -> '~~' 577 //------------------------------------------------------------ 578 579 OUString WindowsToSOfficeLabel( const rtl::OUString& aWinLabel ) 580 { 581 OUString aSOLabel = aWinLabel; 582 583 if ( (aSOLabel.indexOf( TILDE ) > -1) || (aSOLabel.indexOf( AMPERSAND ) > -1) ) 584 { 585 sal_Int32 nStrLen = aSOLabel.getLength( ); 586 587 // in the worst case the new string is 588 // doubled in length, maybe some waste 589 // of memory but how long is a label 590 // normally(?) 591 rtl::OUStringBuffer aBuffer( nStrLen * 2 ); 592 593 Replace( aSOLabel, AMPERSAND_SIGN, TILDE_SIGN, aBuffer ); 594 595 aSOLabel = aBuffer.makeStringAndClear( ); 596 } 597 598 return aSOLabel; 599 } 600