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
IsWindowsVersion(unsigned int PlatformId,unsigned int MajorVersion,int MinorVersion=-1)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
IsWindowsVistaOrNewer()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
IsWindows7()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
IsWindowsVista()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
IsWindowsXP()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
IsWindows2000()143 bool SAL_CALL IsWindows2000()
144 {
145 return IsWindowsVersion(VER_PLATFORM_WIN32_NT, 5, 0);
146 }
147
148 //------------------------------------------------------------
149 //
150 //------------------------------------------------------------
151
IsWindows98()152 bool SAL_CALL IsWindows98()
153 {
154 return IsWindowsVersion(VER_PLATFORM_WIN32_WINDOWS, 4, 10);
155 }
156
157 //------------------------------------------------------------
158 //
159 //------------------------------------------------------------
160
IsWindowsME()161 bool SAL_CALL IsWindowsME()
162 {
163 return IsWindowsVersion(VER_PLATFORM_WIN32_WINDOWS, 4, 90);
164 }
165
166 //------------------------------------------------------------
167 //
168 //------------------------------------------------------------
169
IsWindows2000Platform()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
ListboxAddString(HWND hwnd,const OUString & aString)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
ListboxGetString(HWND hwnd,sal_Int32 aPosition)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
ListboxAddItem(HWND hwnd,const Any & aItem,const Reference<XInterface> & rXInterface,sal_Int16 aArgPos)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
ListboxAddItems(HWND hwnd,const Any & aItemList,const Reference<XInterface> & rXInterface,sal_Int16 aArgPos)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
ListboxDeleteItem(HWND hwnd,const Any & aPosition,const Reference<XInterface> & rXInterface,sal_Int16 aArgPos)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
ListboxDeleteItems(HWND hwnd,const Any &,const Reference<XInterface> &,sal_Int16)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
ListboxSetSelectedItem(HWND hwnd,const Any & aPosition,const Reference<XInterface> & rXInterface,sal_Int16 aArgPos)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
ListboxGetItems(HWND hwnd)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
ListboxGetSelectedItem(HWND hwnd)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
ListboxGetSelectedItemIndex(HWND hwnd)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
CheckboxGetState(HWND hwnd)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
CheckboxSetState(HWND hwnd,const::com::sun::star::uno::Any & aState,const Reference<XInterface> & rXInterface,sal_Int16 aArgPos)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
_wcslenex(const sal_Unicode * pStr)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
Replace(const OUString & aLabel,sal_Unicode OldChar,sal_Unicode NewChar,OUStringBuffer & aBuffer)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
SOfficeToWindowsLabel(const rtl::OUString & aSOLabel)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 // normally(?)
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
WindowsToSOfficeLabel(const rtl::OUString & aWinLabel)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 // normally(?)
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