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