352 lines
9.8 KiB
C++
352 lines
9.8 KiB
C++
/* -*- 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 <osl/diagnose.h>
|
|
#include "ImplHelper.hxx"
|
|
#include <rtl/tencinfo.h>
|
|
#include <o3tl/char16_t2wchar_t.hxx>
|
|
#include <string.h>
|
|
#include <memory>
|
|
|
|
#if !defined WIN32_LEAN_AND_MEAN
|
|
# define WIN32_LEAN_AND_MEAN
|
|
#endif
|
|
#include <windows.h>
|
|
|
|
#include <vector>
|
|
|
|
#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<DWORD*>(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<sal_Int32>(GetOEMCP( )) );
|
|
}
|
|
else if ( LOCALE_IDEFAULTANSICODEPAGE == lctype )
|
|
{
|
|
winCP = OUString::number( static_cast<sal_Int32>(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<wchar_t[]> 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<sal_Int64>( 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: */
|