LibreOffice Module dtrans (master)  1
ImplHelper.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <osl/diagnose.h>
21 #include "ImplHelper.hxx"
22 #include <rtl/tencinfo.h>
24 #include <string.h>
25 #include <memory>
26 
27 #if !defined WIN32_LEAN_AND_MEAN
28 # define WIN32_LEAN_AND_MEAN
29 #endif
30 #include <windows.h>
31 
32 #include <vector>
33 
34 #define FORMATETC_EXACT_MATCH 1
35 #define FORMATETC_PARTIAL_MATCH -1
36 #define FORMATETC_NO_MATCH 0
37 
38 // returns a windows codepage appropriate to the
39 // given mime charset parameter value
40 
41 sal_uInt32 getWinCPFromMimeCharset( const OUString& charset )
42 {
43  sal_uInt32 winCP = GetACP( );
44 
45  if ( charset.getLength( ) )
46  {
47  OString osCharset(
48  charset.getStr( ), charset.getLength( ), RTL_TEXTENCODING_ASCII_US );
49 
50  rtl_TextEncoding txtEnc =
51  rtl_getTextEncodingFromMimeCharset( osCharset.getStr( ) );
52 
53  sal_uIntPtr winChrs = rtl_getBestWindowsCharsetFromTextEncoding( txtEnc );
54 
55  CHARSETINFO chrsInf;
56  bool bRet = TranslateCharsetInfo( reinterpret_cast<DWORD*>(winChrs), &chrsInf, TCI_SRCCHARSET );
57 
58  // if one of the above functions fails
59  // we will return the current ANSI codepage
60  // of this thread
61  if ( bRet )
62  winCP = chrsInf.ciACP;
63  }
64 
65  return winCP;
66 }
67 
68 // returns a windows codepage appropriate to the
69 // given locale and locale type
70 
71 OUString getWinCPFromLocaleId( LCID lcid, LCTYPE lctype )
72 {
73  OSL_ASSERT( IsValidLocale( lcid, LCID_SUPPORTED ) );
74 
75  // we set a default value
76  OUString winCP;
77 
78  // set a default value
79  if ( LOCALE_IDEFAULTCODEPAGE == lctype )
80  {
81  winCP = OUString::number( static_cast<sal_Int32>(GetOEMCP( )) );
82  }
83  else if ( LOCALE_IDEFAULTANSICODEPAGE == lctype )
84  {
85  winCP = OUString::number( static_cast<sal_Int32>(GetACP( )) );
86  }
87  else
88  OSL_ASSERT( false );
89 
90  // First, get required buffer size, in characters
91  int nResult = GetLocaleInfoW(
92  lcid, lctype, nullptr, 0 );
93 
94  OSL_ASSERT( nResult );
95 
96  if ( nResult )
97  {
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 );
101 
102  OSL_ASSERT(nResult);
103 
104  if (nResult)
105  winCP = o3tl::toU( buff.get() );
106 
107  }
108 
109  return winCP;
110 }
111 
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"
115 
116 OUString getMimeCharsetFromWinCP( sal_uInt32 cp, const OUString& aPrefix )
117 {
118  return aPrefix + cptostr( cp );
119 }
120 
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"
124 
125 OUString getMimeCharsetFromLocaleId( LCID lcid, LCTYPE lctype, const OUString& aPrefix )
126 {
127  OUString charset = getWinCPFromLocaleId( lcid, lctype );
128  return aPrefix + charset;
129 }
130 
131 // IsOEMCP
132 
133 bool IsOEMCP( sal_uInt32 codepage )
134 {
135  OSL_ASSERT( IsValidCodePage( codepage ) );
136 
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 };
141 
142  for ( size_t i = 0; i < SAL_N_ELEMENTS( arrOEMCP ); ++i )
143  if ( arrOEMCP[i] == codepage )
144  return true;
145 
146  return false;
147 }
148 
149 // converts a codepage into its string representation
150 
151 OUString cptostr( sal_uInt32 codepage )
152 {
153  OSL_ASSERT( IsValidCodePage( codepage ) );
154 
155  return OUString::number( static_cast<sal_Int64>( codepage ) );
156 }
157 
158 // OleStdDeleteTargetDevice()
159 //
160 // Purpose:
161 //
162 // Parameters:
163 //
164 // Return Value:
165 // SCODE - S_OK if successful
166 void DeleteTargetDevice( DVTARGETDEVICE* ptd )
167 {
168  __try
169  {
170  CoTaskMemFree( ptd );
171  }
172  __except( EXCEPTION_EXECUTE_HANDLER )
173  {
174  OSL_FAIL( "Error DeleteTargetDevice" );
175  }
176 }
177 
178 // OleStdCopyTargetDevice()
179 //
180 // Purpose:
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).
185 //
186 // Parameters:
187 // ptdSrc pointer to source TARGETDEVICE
188 //
189 // Return Value:
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 )
194 {
195  DVTARGETDEVICE* ptdDest = nullptr;
196 
197  __try
198  {
199  if ( nullptr != ptdSrc )
200  {
201  ptdDest = static_cast< DVTARGETDEVICE* >( CoTaskMemAlloc( ptdSrc->tdSize ) );
202  memcpy( ptdDest, ptdSrc, static_cast< size_t >( ptdSrc->tdSize ) );
203  }
204  }
205  __except( EXCEPTION_EXECUTE_HANDLER )
206  {
207  }
208 
209  return ptdDest;
210 }
211 
212 // OleStdCopyFormatEtc()
213 //
214 // Purpose:
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).
221 //
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).
226 //
227 // Parameters:
228 // petcDest pointer to destination FORMATETC
229 // petcSrc pointer to source FORMATETC
230 //
231 // Return Value:
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 )
236 {
237  bool bRet = false;
238 
239  __try
240  {
241  if ( petcDest != petcSrc )
242  {
243 
244  petcDest->cfFormat = petcSrc->cfFormat;
245 
246  petcDest->ptd = nullptr;
247  if ( nullptr != petcSrc->ptd )
248  petcDest->ptd = CopyTargetDevice(petcSrc->ptd);
249 
250  petcDest->dwAspect = petcSrc->dwAspect;
251  petcDest->lindex = petcSrc->lindex;
252  petcDest->tymed = petcSrc->tymed;
253 
254  bRet = true;
255  }
256  }
257  __except( EXCEPTION_EXECUTE_HANDLER )
258  {
259  OSL_FAIL( "Error CopyFormatEtc" );
260  }
261 
262  return bRet;
263 }
264 
265 // returns:
266 // 1 for exact match,
267 // 0 for no 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).
270 
271 sal_Int32 CompareFormatEtc( const FORMATETC* pFetcLhs, const FORMATETC* pFetcRhs )
272 {
273  sal_Int32 nMatch = FORMATETC_EXACT_MATCH;
274 
275  __try
276  {
277  if ( pFetcLhs != pFetcRhs )
278  {
279  if ( ( pFetcLhs->cfFormat != pFetcRhs->cfFormat ) ||
280  ( pFetcLhs->lindex != pFetcRhs->lindex ) ||
281  !CompareTargetDevice( pFetcLhs->ptd, pFetcRhs->ptd ) )
282  {
283  nMatch = FORMATETC_NO_MATCH;
284  }
285 
286  else if ( pFetcLhs->dwAspect == pFetcRhs->dwAspect )
287  // same aspects; equal
288  ;
289  else if ( ( pFetcLhs->dwAspect & ~pFetcRhs->dwAspect ) != 0 )
290  {
291  // left not subset of aspects of right; not equal
292  nMatch = FORMATETC_NO_MATCH;
293  }
294  else
295  // left subset of right
296  nMatch = FORMATETC_PARTIAL_MATCH;
297 
298  if ( nMatch == FORMATETC_EXACT_MATCH || nMatch == FORMATETC_PARTIAL_MATCH )
299  {
300  if ( pFetcLhs->tymed == pFetcRhs->tymed )
301  // same medium flags; equal
302  ;
303  else if ( ( pFetcLhs->tymed & ~pFetcRhs->tymed ) != 0 )
304  {
305  // left not subset of medium flags of right; not equal
306  nMatch = FORMATETC_NO_MATCH;
307  }
308  else
309  // left subset of right
310  nMatch = FORMATETC_PARTIAL_MATCH;
311  }
312  }
313  }
314  __except( EXCEPTION_EXECUTE_HANDLER )
315  {
316  OSL_FAIL( "Error CompareFormatEtc" );
317  nMatch = FORMATETC_NO_MATCH;
318  }
319 
320  return nMatch;
321 }
322 
323 bool CompareTargetDevice( DVTARGETDEVICE* ptdLeft, DVTARGETDEVICE const * ptdRight )
324 {
325  bool bRet = false;
326 
327  __try
328  {
329  if ( ptdLeft == ptdRight )
330  {
331  // same address of td; must be same (handles NULL case)
332  bRet = true;
333  }
334 
335  // one of the two is NULL
336  else if ( ( nullptr != ptdRight ) && ( nullptr != ptdLeft ) )
337 
338  if ( ptdLeft->tdSize == ptdRight->tdSize )
339 
340  if ( memcmp( ptdLeft, ptdRight, ptdLeft->tdSize ) == 0 )
341  bRet = true;
342  }
343  __except( EXCEPTION_EXECUTE_HANDLER )
344  {
345  OSL_FAIL( "Error CompareTargetDevice" );
346  bRet = false;
347  }
348 
349  return bRet;
350 }
351 
352 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal_Int32 CompareFormatEtc(const FORMATETC *pFetcLhs, const FORMATETC *pFetcRhs)
Definition: ImplHelper.cxx:271
bool IsOEMCP(sal_uInt32 codepage)
Definition: ImplHelper.cxx:133
#define FORMATETC_PARTIAL_MATCH
Definition: ImplHelper.cxx:35
OUString getMimeCharsetFromWinCP(sal_uInt32 cp, const OUString &aPrefix)
Definition: ImplHelper.cxx:116
bool CompareTargetDevice(DVTARGETDEVICE *ptdLeft, DVTARGETDEVICE const *ptdRight)
Definition: ImplHelper.cxx:323
#define FORMATETC_EXACT_MATCH
Definition: ImplHelper.cxx:34
OUString getWinCPFromLocaleId(LCID lcid, LCTYPE lctype)
Definition: ImplHelper.cxx:71
OUString cptostr(sal_uInt32 codepage)
Definition: ImplHelper.cxx:151
void DeleteTargetDevice(DVTARGETDEVICE *ptd)
Definition: ImplHelper.cxx:166
bool CopyFormatEtc(LPFORMATETC petcDest, LPFORMATETC petcSrc)
Definition: ImplHelper.cxx:235
#define SAL_N_ELEMENTS(arr)
OUString getMimeCharsetFromLocaleId(LCID lcid, LCTYPE lctype, const OUString &aPrefix)
Definition: ImplHelper.cxx:125
int i
DVTARGETDEVICE * CopyTargetDevice(DVTARGETDEVICE *ptdSrc)
Definition: ImplHelper.cxx:193
#define FORMATETC_NO_MATCH
Definition: ImplHelper.cxx:36
sal_uInt32 getWinCPFromMimeCharset(const OUString &charset)
Definition: ImplHelper.cxx:41