xref: /trunk/main/fpicker/source/win32/misc/WinImplHelper.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956) !
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