xref: /trunk/main/dtrans/source/win32/misc/ImplHelper.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_dtrans.hxx"
30 
31 
32 //------------------------------------------------------------------------
33 // includes
34 //------------------------------------------------------------------------
35 #include <osl/diagnose.h>
36 #include "ImplHelper.hxx"
37 #include <rtl/tencinfo.h>
38 #include <rtl/memory.h>
39 
40 #include <memory>
41 #if defined _MSC_VER
42 #pragma warning(push,1)
43 #endif
44 #include <windows.h>
45 #if defined _MSC_VER
46 #pragma warning(pop)
47 #endif
48 #ifdef __MINGW32__
49 #include <excpt.h>
50 #endif
51 
52 //------------------------------------------------------------------------
53 // defines
54 //------------------------------------------------------------------------
55 
56 #define FORMATETC_EXACT_MATCH    1
57 #define FORMATETC_PARTIAL_MATCH -1
58 #define FORMATETC_NO_MATCH       0
59 
60 //------------------------------------------------------------------------
61 // namespace directives
62 //------------------------------------------------------------------------
63 
64 using ::rtl::OUString;
65 using ::rtl::OString;
66 
67 //------------------------------------------------------------------------
68 // returns a windows codepage appropriate to the
69 // given mime charset parameter value
70 //------------------------------------------------------------------------
71 
72 sal_uInt32 SAL_CALL getWinCPFromMimeCharset( const OUString& charset )
73 {
74     sal_uInt32 winCP = GetACP( );
75 
76     if ( charset.getLength( ) )
77     {
78         OString osCharset(
79             charset.getStr( ), charset.getLength( ), RTL_TEXTENCODING_ASCII_US );
80 
81         rtl_TextEncoding txtEnc =
82             rtl_getTextEncodingFromMimeCharset( osCharset.getStr( ) );
83 
84         sal_uInt32 winChrs = rtl_getBestWindowsCharsetFromTextEncoding( txtEnc );
85 
86         CHARSETINFO chrsInf;
87         sal_Bool bRet = TranslateCharsetInfo( (DWORD*)winChrs, &chrsInf, TCI_SRCCHARSET ) ?
88                         sal_True : sal_False;
89 
90         // if one of the above functions fails
91         // we will return the current ANSI codepage
92         // of this thread
93         if ( bRet )
94             winCP = chrsInf.ciACP;
95     }
96 
97     return winCP;
98 }
99 
100 //--------------------------------------------------
101 // returns a windows codepage appropriate to the
102 // given locale and locale type
103 //--------------------------------------------------
104 
105 OUString SAL_CALL getWinCPFromLocaleId( LCID lcid, LCTYPE lctype )
106 {
107     OSL_ASSERT( IsValidLocale( lcid, LCID_SUPPORTED ) );
108 
109     // we set an default value
110     OUString winCP;
111 
112     // set an default value
113     if ( LOCALE_IDEFAULTCODEPAGE == lctype )
114     {
115         winCP = OUString::valueOf( static_cast<sal_Int32>(GetOEMCP( )), 10 );
116     }
117     else if ( LOCALE_IDEFAULTANSICODEPAGE == lctype )
118     {
119         winCP = OUString::valueOf( static_cast<sal_Int32>(GetACP( )), 10 );
120     }
121     else
122         OSL_ASSERT( sal_False );
123 
124     // we use the GetLocaleInfoA because don't want to provide
125     // a unicode wrapper function for Win9x in sal/systools
126     char buff[6];
127     sal_Int32 nResult = GetLocaleInfoA(
128         lcid, lctype | LOCALE_USE_CP_ACP, buff, sizeof( buff ) );
129 
130     OSL_ASSERT( nResult );
131 
132     if ( nResult )
133     {
134         sal_Int32 len = MultiByteToWideChar(
135             CP_ACP, 0, buff, -1, NULL, 0 );
136 
137         OSL_ASSERT( len > 0 );
138 
139         std::auto_ptr< sal_Unicode > lpwchBuff( new sal_Unicode[len] );
140 
141         if ( NULL != lpwchBuff.get( ) )
142         {
143             len = MultiByteToWideChar(
144                 CP_ACP, 0, buff, -1, reinterpret_cast<LPWSTR>(lpwchBuff.get( )), len );
145 
146             winCP = OUString( lpwchBuff.get( ), (len - 1) );
147         }
148     }
149 
150     return winCP;
151 }
152 
153 //--------------------------------------------------
154 // returns a mime charset parameter value appropriate
155 // to the given codepage, optional a prefix can be
156 // given, e.g. "windows-" or "cp"
157 //--------------------------------------------------
158 
159 OUString SAL_CALL getMimeCharsetFromWinCP( sal_uInt32 cp, const OUString& aPrefix )
160 {
161     return aPrefix + cptostr( cp );
162 }
163 
164 //--------------------------------------------------
165 // returns a mime charset parameter value appropriate
166 // to the given locale id and locale type, optional a
167 // prefix can be given, e.g. "windows-" or "cp"
168 //--------------------------------------------------
169 
170 OUString SAL_CALL getMimeCharsetFromLocaleId( LCID lcid, LCTYPE lctype, const OUString& aPrefix  )
171 {
172     OUString charset = getWinCPFromLocaleId( lcid, lctype );
173     return aPrefix + charset;
174 }
175 
176 //------------------------------------------------------------------------
177 // IsOEMCP
178 //------------------------------------------------------------------------
179 
180 sal_Bool SAL_CALL IsOEMCP( sal_uInt32 codepage )
181 {
182     OSL_ASSERT( IsValidCodePage( codepage ) );
183 
184     sal_uInt32 arrOEMCP[] = { 437, 708, 709, 710, 720, 737,
185                               775, 850, 852, 855, 857, 860,
186                               861, 862, 863, 864, 865, 866,
187                               869, 874, 932, 936, 949, 950, 1361 };
188 
189     for ( sal_Int8 i = 0; i < ( sizeof( arrOEMCP )/sizeof( sal_uInt32 ) ); ++i )
190         if ( arrOEMCP[i] == codepage )
191             return sal_True;
192 
193     return sal_False;
194 }
195 
196 //------------------------------------------------------------------------
197 // converts a codepage into its string representation
198 //------------------------------------------------------------------------
199 
200 OUString SAL_CALL cptostr( sal_uInt32 codepage )
201 {
202     OSL_ASSERT( IsValidCodePage( codepage ) );
203 
204     return OUString::valueOf( static_cast<sal_Int64>( codepage ), 10 );
205 }
206 
207 //-------------------------------------------------------------------------
208 // OleStdDeleteTargetDevice()
209 //
210 // Purpose:
211 //
212 // Parameters:
213 //
214 // Return Value:
215 //    SCODE  -  S_OK if successful
216 //-------------------------------------------------------------------------
217 
218 void SAL_CALL DeleteTargetDevice( DVTARGETDEVICE* ptd )
219 {
220 #ifdef __MINGW32__
221     jmp_buf jmpbuf;
222     __SEHandler han;
223     if (__builtin_setjmp(jmpbuf) == 0)
224     {
225         han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER);
226 #else
227     __try
228     {
229 #endif
230         CoTaskMemFree( ptd );
231     }
232 #ifdef __MINGW32__
233     else
234 #else
235     __except( EXCEPTION_EXECUTE_HANDLER )
236 #endif
237     {
238         OSL_ENSURE( sal_False, "Error DeleteTargetDevice" );
239     }
240 #ifdef __MINGW32__
241     han.Reset();
242 #endif
243 }
244 
245 
246 
247 //-------------------------------------------------------------------------
248 // OleStdCopyTargetDevice()
249 //
250 // Purpose:
251 //  duplicate a TARGETDEVICE struct. this function allocates memory for
252 //  the copy. the caller MUST free the allocated copy when done with it
253 //  using the standard allocator returned from CoGetMalloc.
254 //  (OleStdFree can be used to free the copy).
255 //
256 // Parameters:
257 //  ptdSrc      pointer to source TARGETDEVICE
258 //
259 // Return Value:
260 //    pointer to allocated copy of ptdSrc
261 //    if ptdSrc==NULL then retuns NULL is returned.
262 //    if ptdSrc!=NULL and memory allocation fails, then NULL is returned
263 //-------------------------------------------------------------------------
264 
265 DVTARGETDEVICE* SAL_CALL CopyTargetDevice( DVTARGETDEVICE* ptdSrc )
266 {
267     DVTARGETDEVICE* ptdDest = NULL;
268 
269 #ifdef __MINGW32__
270     jmp_buf jmpbuf;
271     __SEHandler han;
272     if (__builtin_setjmp(jmpbuf) == 0)
273     {
274         han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER);
275 #else
276     __try
277     {
278 #endif
279         if ( NULL != ptdSrc )
280         {
281             ptdDest = static_cast< DVTARGETDEVICE* >( CoTaskMemAlloc( ptdSrc->tdSize ) );
282             rtl_copyMemory( ptdDest, ptdSrc, static_cast< size_t >( ptdSrc->tdSize ) );
283         }
284     }
285 #ifdef __MINGW32__
286     han.Reset();
287 #else
288     __except( EXCEPTION_EXECUTE_HANDLER )
289     {
290     }
291 #endif
292 
293     return ptdDest;
294 }
295 
296 
297 //-------------------------------------------------------------------------
298 // OleStdCopyFormatEtc()
299 //
300 // Purpose:
301 //  Copies the contents of a FORMATETC structure. this function takes
302 //  special care to copy correctly copying the pointer to the TARGETDEVICE
303 //  contained within the source FORMATETC structure.
304 //  if the source FORMATETC has a non-NULL TARGETDEVICE, then a copy
305 //  of the TARGETDEVICE will be allocated for the destination of the
306 //  FORMATETC (petcDest).
307 //
308 //  NOTE: the caller MUST free the allocated copy of the TARGETDEVICE
309 //  within the destination FORMATETC when done with it
310 //  using the standard allocator returned from CoGetMalloc.
311 //  (OleStdFree can be used to free the copy).
312 //
313 // Parameters:
314 //  petcDest      pointer to destination FORMATETC
315 //  petcSrc       pointer to source FORMATETC
316 //
317 // Return Value:
318 //  returns TRUE if copy was successful;
319 //  retuns FALSE if not successful, e.g. one or both of the pointers
320 //  were invalid or the pointers were equal
321 //-------------------------------------------------------------------------
322 
323 sal_Bool SAL_CALL CopyFormatEtc( LPFORMATETC petcDest, LPFORMATETC petcSrc )
324 {
325     sal_Bool bRet = sal_False;
326 
327 #ifdef __MINGW32__
328     jmp_buf jmpbuf;
329     __SEHandler han;
330     if (__builtin_setjmp(jmpbuf) == 0)
331     {
332         han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER);
333 #else
334     __try
335     {
336 #endif
337         if ( petcDest != petcSrc )
338         {
339 
340         petcDest->cfFormat = petcSrc->cfFormat;
341 
342         petcDest->ptd      = NULL;
343         if ( NULL != petcSrc->ptd )
344             petcDest->ptd  = CopyTargetDevice(petcSrc->ptd);
345 
346         petcDest->dwAspect = petcSrc->dwAspect;
347         petcDest->lindex   = petcSrc->lindex;
348         petcDest->tymed    = petcSrc->tymed;
349 
350         bRet = sal_True;
351         }
352     }
353 #ifdef __MINGW32__
354     else
355 #else
356     __except( EXCEPTION_EXECUTE_HANDLER )
357 #endif
358     {
359         OSL_ENSURE( sal_False, "Error CopyFormatEtc" );
360     }
361 #ifdef __MINGW32__
362     han.Reset();
363 #endif
364 
365     return bRet;
366 }
367 
368 //-------------------------------------------------------------------------
369 // returns:
370 //  1 for exact match,
371 //  0 for no match,
372 // -1 for partial match (which is defined to mean the left is a subset
373 //    of the right: fewer aspects, null target device, fewer medium).
374 //-------------------------------------------------------------------------
375 
376 sal_Int32 SAL_CALL CompareFormatEtc( const FORMATETC* pFetcLhs, const FORMATETC* pFetcRhs )
377 {
378     sal_Int32 nMatch = FORMATETC_EXACT_MATCH;
379 
380 #ifdef __MINGW32__
381     jmp_buf jmpbuf;
382     __SEHandler han;
383     if (__builtin_setjmp(jmpbuf) == 0)
384     {
385         han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER);
386 #else
387     __try
388     {
389 #endif
390         if ( pFetcLhs != pFetcRhs )
391 
392         if ( ( pFetcLhs->cfFormat != pFetcRhs->cfFormat ) ||
393              ( pFetcLhs->lindex   != pFetcRhs->lindex ) ||
394              !CompareTargetDevice( pFetcLhs->ptd, pFetcRhs->ptd ) )
395         {
396             nMatch = FORMATETC_NO_MATCH;
397         }
398 
399         else if ( pFetcLhs->dwAspect == pFetcRhs->dwAspect )
400             // same aspects; equal
401             ;
402         else if ( ( pFetcLhs->dwAspect & ~pFetcRhs->dwAspect ) != 0 )
403         {
404             // left not subset of aspects of right; not equal
405             nMatch = FORMATETC_NO_MATCH;
406         }
407         else
408             // left subset of right
409             nMatch = FORMATETC_PARTIAL_MATCH;
410 
411         if ( nMatch == FORMATETC_EXACT_MATCH || nMatch == FORMATETC_PARTIAL_MATCH )
412         {
413         if ( pFetcLhs->tymed == pFetcRhs->tymed )
414             // same medium flags; equal
415             ;
416         else if ( ( pFetcLhs->tymed & ~pFetcRhs->tymed ) != 0 )
417         {
418             // left not subset of medium flags of right; not equal
419             nMatch = FORMATETC_NO_MATCH;
420         }
421         else
422             // left subset of right
423             nMatch = FORMATETC_PARTIAL_MATCH;
424         }
425     }
426 #ifdef __MINGW32__
427     else
428 #else
429     __except( EXCEPTION_EXECUTE_HANDLER )
430 #endif
431     {
432         OSL_ENSURE( sal_False, "Error CompareFormatEtc" );
433         nMatch = FORMATETC_NO_MATCH;
434     }
435 #ifdef __MINGW32__
436     han.Reset();
437 #endif
438 
439     return nMatch;
440 }
441 
442 
443 //-------------------------------------------------------------------------
444 //
445 //-------------------------------------------------------------------------
446 
447 sal_Bool SAL_CALL CompareTargetDevice( DVTARGETDEVICE* ptdLeft, DVTARGETDEVICE* ptdRight )
448 {
449     sal_Bool bRet = sal_False;
450 
451 #ifdef __MINGW32__
452     jmp_buf jmpbuf;
453     __SEHandler han;
454     if (__builtin_setjmp(jmpbuf) == 0)
455     {
456         han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER);
457 #else
458     __try
459     {
460 #endif
461         if ( ptdLeft == ptdRight )
462         {
463             // same address of td; must be same (handles NULL case)
464             bRet = sal_True;
465         }
466 
467         // one ot the two is NULL
468         else if ( ( NULL != ptdRight ) && ( NULL != ptdLeft ) )
469 
470         if ( ptdLeft->tdSize == ptdRight->tdSize )
471 
472         if ( rtl_compareMemory( ptdLeft, ptdRight, ptdLeft->tdSize ) == 0 )
473             bRet = sal_True;
474     }
475 #ifdef __MINGW32__
476     else
477 #else
478     __except( EXCEPTION_EXECUTE_HANDLER )
479 #endif
480     {
481         OSL_ENSURE( sal_False, "Error CompareTargetDevice" );
482         bRet = sal_False;
483     }
484 #ifdef __MINGW32__
485     han.Reset();
486 #endif
487 
488     return bRet;
489 }
490