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