/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include #include "ImplHelper.hxx" #include #include #include #include #if !defined WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN #endif #include #include #define FORMATETC_EXACT_MATCH 1 #define FORMATETC_PARTIAL_MATCH -1 #define FORMATETC_NO_MATCH 0 // returns a windows codepage appropriate to the // given mime charset parameter value sal_uInt32 getWinCPFromMimeCharset( const OUString& charset ) { sal_uInt32 winCP = GetACP( ); if ( charset.getLength( ) ) { OString osCharset( charset.getStr( ), charset.getLength( ), RTL_TEXTENCODING_ASCII_US ); rtl_TextEncoding txtEnc = rtl_getTextEncodingFromMimeCharset( osCharset.getStr( ) ); sal_uIntPtr winChrs = rtl_getBestWindowsCharsetFromTextEncoding( txtEnc ); CHARSETINFO chrsInf; bool bRet = TranslateCharsetInfo( reinterpret_cast(winChrs), &chrsInf, TCI_SRCCHARSET ); // if one of the above functions fails // we will return the current ANSI codepage // of this thread if ( bRet ) winCP = chrsInf.ciACP; } return winCP; } // returns a windows codepage appropriate to the // given locale and locale type OUString getWinCPFromLocaleId( LCID lcid, LCTYPE lctype ) { OSL_ASSERT( IsValidLocale( lcid, LCID_SUPPORTED ) ); // we set a default value OUString winCP; // set a default value if ( LOCALE_IDEFAULTCODEPAGE == lctype ) { winCP = OUString::number( static_cast(GetOEMCP( )) ); } else if ( LOCALE_IDEFAULTANSICODEPAGE == lctype ) { winCP = OUString::number( static_cast(GetACP( )) ); } else OSL_ASSERT( false ); // First, get required buffer size, in characters int nResult = GetLocaleInfoW( lcid, lctype, nullptr, 0 ); OSL_ASSERT( nResult ); if ( nResult ) { std::unique_ptr buff( new wchar_t[nResult] ); // Now get the actual data nResult = GetLocaleInfoW( lcid, lctype, buff.get(), nResult ); OSL_ASSERT(nResult); if (nResult) winCP = o3tl::toU( buff.get() ); } return winCP; } // returns a mime charset parameter value appropriate // to the given codepage, optional a prefix can be // given, e.g. "windows-" or "cp" OUString getMimeCharsetFromWinCP( sal_uInt32 cp, std::u16string_view aPrefix ) { return aPrefix + cptostr( cp ); } // returns a mime charset parameter value appropriate // to the given locale id and locale type, optional a // prefix can be given, e.g. "windows-" or "cp" OUString getMimeCharsetFromLocaleId( LCID lcid, LCTYPE lctype, std::u16string_view aPrefix ) { OUString charset = getWinCPFromLocaleId( lcid, lctype ); return aPrefix + charset; } // IsOEMCP bool IsOEMCP( sal_uInt32 codepage ) { OSL_ASSERT( IsValidCodePage( codepage ) ); sal_uInt32 arrOEMCP[] = { 437, 708, 709, 710, 720, 737, 775, 850, 852, 855, 857, 860, 861, 862, 863, 864, 865, 866, 869, 874, 932, 936, 949, 950, 1361 }; for ( size_t i = 0; i < SAL_N_ELEMENTS( arrOEMCP ); ++i ) if ( arrOEMCP[i] == codepage ) return true; return false; } // converts a codepage into its string representation OUString cptostr( sal_uInt32 codepage ) { OSL_ASSERT( IsValidCodePage( codepage ) ); return OUString::number( static_cast( codepage ) ); } // OleStdDeleteTargetDevice() // // Purpose: // // Parameters: // // Return Value: // SCODE - S_OK if successful void DeleteTargetDevice( DVTARGETDEVICE* ptd ) { __try { CoTaskMemFree( ptd ); } __except( EXCEPTION_EXECUTE_HANDLER ) { OSL_FAIL( "Error DeleteTargetDevice" ); } } // OleStdCopyTargetDevice() // // Purpose: // duplicate a TARGETDEVICE struct. this function allocates memory for // the copy. the caller MUST free the allocated copy when done with it // using the standard allocator returned from CoGetMalloc. // (OleStdFree can be used to free the copy). // // Parameters: // ptdSrc pointer to source TARGETDEVICE // // Return Value: // pointer to allocated copy of ptdSrc // if ptdSrc==NULL then returns NULL is returned. // if ptdSrc!=NULL and memory allocation fails, then NULL is returned DVTARGETDEVICE* CopyTargetDevice( DVTARGETDEVICE* ptdSrc ) { DVTARGETDEVICE* ptdDest = nullptr; __try { if ( nullptr != ptdSrc ) { ptdDest = static_cast< DVTARGETDEVICE* >( CoTaskMemAlloc( ptdSrc->tdSize ) ); memcpy( ptdDest, ptdSrc, static_cast< size_t >( ptdSrc->tdSize ) ); } } __except( EXCEPTION_EXECUTE_HANDLER ) { } return ptdDest; } // OleStdCopyFormatEtc() // // Purpose: // Copies the contents of a FORMATETC structure. this function takes // special care to copy correctly copying the pointer to the TARGETDEVICE // contained within the source FORMATETC structure. // if the source FORMATETC has a non-NULL TARGETDEVICE, then a copy // of the TARGETDEVICE will be allocated for the destination of the // FORMATETC (petcDest). // // NOTE: the caller MUST free the allocated copy of the TARGETDEVICE // within the destination FORMATETC when done with it // using the standard allocator returned from CoGetMalloc. // (OleStdFree can be used to free the copy). // // Parameters: // petcDest pointer to destination FORMATETC // petcSrc pointer to source FORMATETC // // Return Value: // returns TRUE if copy was successful; // returns FALSE if not successful, e.g. one or both of the pointers // were invalid or the pointers were equal bool CopyFormatEtc( LPFORMATETC petcDest, LPFORMATETC petcSrc ) { bool bRet = false; __try { if ( petcDest != petcSrc ) { petcDest->cfFormat = petcSrc->cfFormat; petcDest->ptd = nullptr; if ( nullptr != petcSrc->ptd ) petcDest->ptd = CopyTargetDevice(petcSrc->ptd); petcDest->dwAspect = petcSrc->dwAspect; petcDest->lindex = petcSrc->lindex; petcDest->tymed = petcSrc->tymed; bRet = true; } } __except( EXCEPTION_EXECUTE_HANDLER ) { OSL_FAIL( "Error CopyFormatEtc" ); } return bRet; } // returns: // 1 for exact match, // 0 for no match, // -1 for partial match (which is defined to mean the left is a subset // of the right: fewer aspects, null target device, fewer medium). sal_Int32 CompareFormatEtc( const FORMATETC* pFetcLhs, const FORMATETC* pFetcRhs ) { sal_Int32 nMatch = FORMATETC_EXACT_MATCH; __try { if ( pFetcLhs != pFetcRhs ) { if ( ( pFetcLhs->cfFormat != pFetcRhs->cfFormat ) || ( pFetcLhs->lindex != pFetcRhs->lindex ) || !CompareTargetDevice( pFetcLhs->ptd, pFetcRhs->ptd ) ) { nMatch = FORMATETC_NO_MATCH; } else if ( pFetcLhs->dwAspect == pFetcRhs->dwAspect ) // same aspects; equal ; else if ( ( pFetcLhs->dwAspect & ~pFetcRhs->dwAspect ) != 0 ) { // left not subset of aspects of right; not equal nMatch = FORMATETC_NO_MATCH; } else // left subset of right nMatch = FORMATETC_PARTIAL_MATCH; if ( nMatch == FORMATETC_EXACT_MATCH || nMatch == FORMATETC_PARTIAL_MATCH ) { if ( pFetcLhs->tymed == pFetcRhs->tymed ) // same medium flags; equal ; else if ( ( pFetcLhs->tymed & ~pFetcRhs->tymed ) != 0 ) { // left not subset of medium flags of right; not equal nMatch = FORMATETC_NO_MATCH; } else // left subset of right nMatch = FORMATETC_PARTIAL_MATCH; } } } __except( EXCEPTION_EXECUTE_HANDLER ) { OSL_FAIL( "Error CompareFormatEtc" ); nMatch = FORMATETC_NO_MATCH; } return nMatch; } bool CompareTargetDevice( DVTARGETDEVICE* ptdLeft, DVTARGETDEVICE const * ptdRight ) { bool bRet = false; __try { if ( ptdLeft == ptdRight ) { // same address of td; must be same (handles NULL case) bRet = true; } // one of the two is NULL else if ( ( nullptr != ptdRight ) && ( nullptr != ptdLeft ) ) if ( ptdLeft->tdSize == ptdRight->tdSize ) if ( memcmp( ptdLeft, ptdRight, ptdLeft->tdSize ) == 0 ) bRet = true; } __except( EXCEPTION_EXECUTE_HANDLER ) { OSL_FAIL( "Error CompareTargetDevice" ); bRet = false; } return bRet; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */