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