1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <osl/diagnose.h>
21 #include "ImplHelper.hxx"
22 #include <rtl/tencinfo.h>
23 #include <o3tl/char16_t2wchar_t.hxx>
27 #if !defined WIN32_LEAN_AND_MEAN
28 # define WIN32_LEAN_AND_MEAN
34 #define FORMATETC_EXACT_MATCH 1
35 #define FORMATETC_PARTIAL_MATCH -1
36 #define FORMATETC_NO_MATCH 0
38 // returns a windows codepage appropriate to the
39 // given mime charset parameter value
41 sal_uInt32
getWinCPFromMimeCharset( const OUString
& charset
)
43 sal_uInt32 winCP
= GetACP( );
45 if ( charset
.getLength( ) )
48 charset
.getStr( ), charset
.getLength( ), RTL_TEXTENCODING_ASCII_US
);
50 rtl_TextEncoding txtEnc
=
51 rtl_getTextEncodingFromMimeCharset( osCharset
.getStr( ) );
53 sal_uIntPtr winChrs
= rtl_getBestWindowsCharsetFromTextEncoding( txtEnc
);
56 bool bRet
= TranslateCharsetInfo( reinterpret_cast<DWORD
*>(winChrs
), &chrsInf
, TCI_SRCCHARSET
);
58 // if one of the above functions fails
59 // we will return the current ANSI codepage
62 winCP
= chrsInf
.ciACP
;
68 // returns a windows codepage appropriate to the
69 // given locale and locale type
71 OUString
getWinCPFromLocaleId( LCID lcid
, LCTYPE lctype
)
73 OSL_ASSERT( IsValidLocale( lcid
, LCID_SUPPORTED
) );
75 // we set a default value
78 // set a default value
79 if ( LOCALE_IDEFAULTCODEPAGE
== lctype
)
81 winCP
= OUString::number( static_cast<sal_Int32
>(GetOEMCP( )) );
83 else if ( LOCALE_IDEFAULTANSICODEPAGE
== lctype
)
85 winCP
= OUString::number( static_cast<sal_Int32
>(GetACP( )) );
90 // First, get required buffer size, in characters
91 int nResult
= GetLocaleInfoW(
92 lcid
, lctype
, nullptr, 0 );
94 OSL_ASSERT( nResult
);
98 std::unique_ptr
<wchar_t[]> buff( new wchar_t[nResult
] );
99 // Now get the actual data
100 nResult
= GetLocaleInfoW( lcid
, lctype
, buff
.get(), nResult
);
105 winCP
= o3tl::toU( buff
.get() );
112 // returns a mime charset parameter value appropriate
113 // to the given codepage, optional a prefix can be
114 // given, e.g. "windows-" or "cp"
116 OUString
getMimeCharsetFromWinCP( sal_uInt32 cp
, const OUString
& aPrefix
)
118 return aPrefix
+ cptostr( cp
);
121 // returns a mime charset parameter value appropriate
122 // to the given locale id and locale type, optional a
123 // prefix can be given, e.g. "windows-" or "cp"
125 OUString
getMimeCharsetFromLocaleId( LCID lcid
, LCTYPE lctype
, const OUString
& aPrefix
)
127 OUString charset
= getWinCPFromLocaleId( lcid
, lctype
);
128 return aPrefix
+ charset
;
133 bool IsOEMCP( sal_uInt32 codepage
)
135 OSL_ASSERT( IsValidCodePage( codepage
) );
137 sal_uInt32 arrOEMCP
[] = { 437, 708, 709, 710, 720, 737,
138 775, 850, 852, 855, 857, 860,
139 861, 862, 863, 864, 865, 866,
140 869, 874, 932, 936, 949, 950, 1361 };
142 for ( size_t i
= 0; i
< SAL_N_ELEMENTS( arrOEMCP
); ++i
)
143 if ( arrOEMCP
[i
] == codepage
)
149 // converts a codepage into its string representation
151 OUString
cptostr( sal_uInt32 codepage
)
153 OSL_ASSERT( IsValidCodePage( codepage
) );
155 return OUString::number( static_cast<sal_Int64
>( codepage
) );
158 // OleStdDeleteTargetDevice()
165 // SCODE - S_OK if successful
166 void DeleteTargetDevice( DVTARGETDEVICE
* ptd
)
170 CoTaskMemFree( ptd
);
172 __except( EXCEPTION_EXECUTE_HANDLER
)
174 OSL_FAIL( "Error DeleteTargetDevice" );
178 // OleStdCopyTargetDevice()
181 // duplicate a TARGETDEVICE struct. this function allocates memory for
182 // the copy. the caller MUST free the allocated copy when done with it
183 // using the standard allocator returned from CoGetMalloc.
184 // (OleStdFree can be used to free the copy).
187 // ptdSrc pointer to source TARGETDEVICE
190 // pointer to allocated copy of ptdSrc
191 // if ptdSrc==NULL then returns NULL is returned.
192 // if ptdSrc!=NULL and memory allocation fails, then NULL is returned
193 DVTARGETDEVICE
* CopyTargetDevice( DVTARGETDEVICE
* ptdSrc
)
195 DVTARGETDEVICE
* ptdDest
= nullptr;
199 if ( nullptr != ptdSrc
)
201 ptdDest
= static_cast< DVTARGETDEVICE
* >( CoTaskMemAlloc( ptdSrc
->tdSize
) );
202 memcpy( ptdDest
, ptdSrc
, static_cast< size_t >( ptdSrc
->tdSize
) );
205 __except( EXCEPTION_EXECUTE_HANDLER
)
212 // OleStdCopyFormatEtc()
215 // Copies the contents of a FORMATETC structure. this function takes
216 // special care to copy correctly copying the pointer to the TARGETDEVICE
217 // contained within the source FORMATETC structure.
218 // if the source FORMATETC has a non-NULL TARGETDEVICE, then a copy
219 // of the TARGETDEVICE will be allocated for the destination of the
220 // FORMATETC (petcDest).
222 // NOTE: the caller MUST free the allocated copy of the TARGETDEVICE
223 // within the destination FORMATETC when done with it
224 // using the standard allocator returned from CoGetMalloc.
225 // (OleStdFree can be used to free the copy).
228 // petcDest pointer to destination FORMATETC
229 // petcSrc pointer to source FORMATETC
232 // returns TRUE if copy was successful;
233 // returns FALSE if not successful, e.g. one or both of the pointers
234 // were invalid or the pointers were equal
235 bool CopyFormatEtc( LPFORMATETC petcDest
, LPFORMATETC petcSrc
)
241 if ( petcDest
!= petcSrc
)
244 petcDest
->cfFormat
= petcSrc
->cfFormat
;
246 petcDest
->ptd
= nullptr;
247 if ( nullptr != petcSrc
->ptd
)
248 petcDest
->ptd
= CopyTargetDevice(petcSrc
->ptd
);
250 petcDest
->dwAspect
= petcSrc
->dwAspect
;
251 petcDest
->lindex
= petcSrc
->lindex
;
252 petcDest
->tymed
= petcSrc
->tymed
;
257 __except( EXCEPTION_EXECUTE_HANDLER
)
259 OSL_FAIL( "Error CopyFormatEtc" );
266 // 1 for exact match,
268 // -1 for partial match (which is defined to mean the left is a subset
269 // of the right: fewer aspects, null target device, fewer medium).
271 sal_Int32
CompareFormatEtc( const FORMATETC
* pFetcLhs
, const FORMATETC
* pFetcRhs
)
273 sal_Int32 nMatch
= FORMATETC_EXACT_MATCH
;
277 if ( pFetcLhs
!= pFetcRhs
)
279 if ( ( pFetcLhs
->cfFormat
!= pFetcRhs
->cfFormat
) ||
280 ( pFetcLhs
->lindex
!= pFetcRhs
->lindex
) ||
281 !CompareTargetDevice( pFetcLhs
->ptd
, pFetcRhs
->ptd
) )
283 nMatch
= FORMATETC_NO_MATCH
;
286 else if ( pFetcLhs
->dwAspect
== pFetcRhs
->dwAspect
)
287 // same aspects; equal
289 else if ( ( pFetcLhs
->dwAspect
& ~pFetcRhs
->dwAspect
) != 0 )
291 // left not subset of aspects of right; not equal
292 nMatch
= FORMATETC_NO_MATCH
;
295 // left subset of right
296 nMatch
= FORMATETC_PARTIAL_MATCH
;
298 if ( nMatch
== FORMATETC_EXACT_MATCH
|| nMatch
== FORMATETC_PARTIAL_MATCH
)
300 if ( pFetcLhs
->tymed
== pFetcRhs
->tymed
)
301 // same medium flags; equal
303 else if ( ( pFetcLhs
->tymed
& ~pFetcRhs
->tymed
) != 0 )
305 // left not subset of medium flags of right; not equal
306 nMatch
= FORMATETC_NO_MATCH
;
309 // left subset of right
310 nMatch
= FORMATETC_PARTIAL_MATCH
;
314 __except( EXCEPTION_EXECUTE_HANDLER
)
316 OSL_FAIL( "Error CompareFormatEtc" );
317 nMatch
= FORMATETC_NO_MATCH
;
323 bool CompareTargetDevice( DVTARGETDEVICE
* ptdLeft
, DVTARGETDEVICE
const * ptdRight
)
329 if ( ptdLeft
== ptdRight
)
331 // same address of td; must be same (handles NULL case)
335 // one of the two is NULL
336 else if ( ( nullptr != ptdRight
) && ( nullptr != ptdLeft
) )
338 if ( ptdLeft
->tdSize
== ptdRight
->tdSize
)
340 if ( memcmp( ptdLeft
, ptdRight
, ptdLeft
->tdSize
) == 0 )
343 __except( EXCEPTION_EXECUTE_HANDLER
)
345 OSL_FAIL( "Error CompareTargetDevice" );
352 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */