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