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 
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 
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 
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 
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 
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 
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 
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