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 {
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
ListboxAddItems(HWND hwnd,const Any & aItemList,const Reference<XInterface> & rXInterface,sal_Int16 aArgPos)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
ListboxDeleteItem(HWND hwnd,const Any & aPosition,const Reference<XInterface> & rXInterface,sal_Int16 aArgPos)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
ListboxDeleteItems(HWND hwnd,const Any &,const Reference<XInterface> &,sal_Int16)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
ListboxSetSelectedItem(HWND hwnd,const Any & aPosition,const Reference<XInterface> & rXInterface,sal_Int16 aArgPos)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
ListboxGetItems(HWND hwnd)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
ListboxGetSelectedItem(HWND hwnd)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
ListboxGetSelectedItemIndex(HWND hwnd)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
CheckboxGetState(HWND hwnd)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
CheckboxSetState(HWND hwnd,const::com::sun::star::uno::Any & aState,const Reference<XInterface> & rXInterface,sal_Int16 aArgPos)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
_wcslenex(const sal_Unicode * pStr)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
Replace(const OUString & aLabel,sal_Unicode OldChar,sal_Unicode NewChar,OUStringBuffer & aBuffer)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
SOfficeToWindowsLabel(const rtl::OUString & aSOLabel)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
WindowsToSOfficeLabel(const rtl::OUString & aWinLabel)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