1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_dtrans.hxx" 26 27 28 //------------------------------------------------------------------------ 29 // includes 30 //------------------------------------------------------------------------ 31 #include <osl/diagnose.h> 32 #include "ImplHelper.hxx" 33 #include <rtl/tencinfo.h> 34 #include <rtl/memory.h> 35 36 #include <memory> 37 #if defined _MSC_VER 38 #pragma warning(push,1) 39 #endif 40 #include <windows.h> 41 #if defined _MSC_VER 42 #pragma warning(pop) 43 #endif 44 #ifdef __MINGW32__ 45 #include <excpt.h> 46 #endif 47 48 //------------------------------------------------------------------------ 49 // defines 50 //------------------------------------------------------------------------ 51 52 #define FORMATETC_EXACT_MATCH 1 53 #define FORMATETC_PARTIAL_MATCH -1 54 #define FORMATETC_NO_MATCH 0 55 56 //------------------------------------------------------------------------ 57 // namespace directives 58 //------------------------------------------------------------------------ 59 60 using ::rtl::OUString; 61 using ::rtl::OString; 62 63 //------------------------------------------------------------------------ 64 // returns a windows codepage appropriate to the 65 // given mime charset parameter value 66 //------------------------------------------------------------------------ 67 68 sal_uInt32 SAL_CALL getWinCPFromMimeCharset( const OUString& charset ) 69 { 70 sal_uInt32 winCP = GetACP( ); 71 72 if ( charset.getLength( ) ) 73 { 74 OString osCharset( 75 charset.getStr( ), charset.getLength( ), RTL_TEXTENCODING_ASCII_US ); 76 77 rtl_TextEncoding txtEnc = 78 rtl_getTextEncodingFromMimeCharset( osCharset.getStr( ) ); 79 80 sal_uInt32 winChrs = rtl_getBestWindowsCharsetFromTextEncoding( txtEnc ); 81 82 CHARSETINFO chrsInf; 83 sal_Bool bRet = TranslateCharsetInfo( (DWORD*)winChrs, &chrsInf, TCI_SRCCHARSET ) ? 84 sal_True : sal_False; 85 86 // if one of the above functions fails 87 // we will return the current ANSI codepage 88 // of this thread 89 if ( bRet ) 90 winCP = chrsInf.ciACP; 91 } 92 93 return winCP; 94 } 95 96 //-------------------------------------------------- 97 // returns a windows codepage appropriate to the 98 // given locale and locale type 99 //-------------------------------------------------- 100 101 OUString SAL_CALL getWinCPFromLocaleId( LCID lcid, LCTYPE lctype ) 102 { 103 OSL_ASSERT( IsValidLocale( lcid, LCID_SUPPORTED ) ); 104 105 // we set an default value 106 OUString winCP; 107 108 // set an default value 109 if ( LOCALE_IDEFAULTCODEPAGE == lctype ) 110 { 111 winCP = OUString::valueOf( static_cast<sal_Int32>(GetOEMCP( )), 10 ); 112 } 113 else if ( LOCALE_IDEFAULTANSICODEPAGE == lctype ) 114 { 115 winCP = OUString::valueOf( static_cast<sal_Int32>(GetACP( )), 10 ); 116 } 117 else 118 OSL_ASSERT( sal_False ); 119 120 // we use the GetLocaleInfoA because don't want to provide 121 // a unicode wrapper function for Win9x in sal/systools 122 char buff[6]; 123 sal_Int32 nResult = GetLocaleInfoA( 124 lcid, lctype | LOCALE_USE_CP_ACP, buff, sizeof( buff ) ); 125 126 OSL_ASSERT( nResult ); 127 128 if ( nResult ) 129 { 130 sal_Int32 len = MultiByteToWideChar( 131 CP_ACP, 0, buff, -1, NULL, 0 ); 132 133 OSL_ASSERT( len > 0 ); 134 135 std::auto_ptr< sal_Unicode > lpwchBuff( new sal_Unicode[len] ); 136 137 if ( NULL != lpwchBuff.get( ) ) 138 { 139 len = MultiByteToWideChar( 140 CP_ACP, 0, buff, -1, reinterpret_cast<LPWSTR>(lpwchBuff.get( )), len ); 141 142 winCP = OUString( lpwchBuff.get( ), (len - 1) ); 143 } 144 } 145 146 return winCP; 147 } 148 149 //-------------------------------------------------- 150 // returns a mime charset parameter value appropriate 151 // to the given codepage, optional a prefix can be 152 // given, e.g. "windows-" or "cp" 153 //-------------------------------------------------- 154 155 OUString SAL_CALL getMimeCharsetFromWinCP( sal_uInt32 cp, const OUString& aPrefix ) 156 { 157 return aPrefix + cptostr( cp ); 158 } 159 160 //-------------------------------------------------- 161 // returns a mime charset parameter value appropriate 162 // to the given locale id and locale type, optional a 163 // prefix can be given, e.g. "windows-" or "cp" 164 //-------------------------------------------------- 165 166 OUString SAL_CALL getMimeCharsetFromLocaleId( LCID lcid, LCTYPE lctype, const OUString& aPrefix ) 167 { 168 OUString charset = getWinCPFromLocaleId( lcid, lctype ); 169 return aPrefix + charset; 170 } 171 172 //------------------------------------------------------------------------ 173 // IsOEMCP 174 //------------------------------------------------------------------------ 175 176 sal_Bool SAL_CALL IsOEMCP( sal_uInt32 codepage ) 177 { 178 OSL_ASSERT( IsValidCodePage( codepage ) ); 179 180 sal_uInt32 arrOEMCP[] = { 437, 708, 709, 710, 720, 737, 181 775, 850, 852, 855, 857, 860, 182 861, 862, 863, 864, 865, 866, 183 869, 874, 932, 936, 949, 950, 1361 }; 184 185 for ( sal_Int8 i = 0; i < ( sizeof( arrOEMCP )/sizeof( sal_uInt32 ) ); ++i ) 186 if ( arrOEMCP[i] == codepage ) 187 return sal_True; 188 189 return sal_False; 190 } 191 192 //------------------------------------------------------------------------ 193 // converts a codepage into its string representation 194 //------------------------------------------------------------------------ 195 196 OUString SAL_CALL cptostr( sal_uInt32 codepage ) 197 { 198 OSL_ASSERT( IsValidCodePage( codepage ) ); 199 200 return OUString::valueOf( static_cast<sal_Int64>( codepage ), 10 ); 201 } 202 203 //------------------------------------------------------------------------- 204 // OleStdDeleteTargetDevice() 205 // 206 // Purpose: 207 // 208 // Parameters: 209 // 210 // Return Value: 211 // SCODE - S_OK if successful 212 //------------------------------------------------------------------------- 213 214 void SAL_CALL DeleteTargetDevice( DVTARGETDEVICE* ptd ) 215 { 216 #ifdef __MINGW32__ 217 jmp_buf jmpbuf; 218 __SEHandler han; 219 if (__builtin_setjmp(jmpbuf) == 0) 220 { 221 han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER); 222 #else 223 __try 224 { 225 #endif 226 CoTaskMemFree( ptd ); 227 } 228 #ifdef __MINGW32__ 229 else 230 #else 231 __except( EXCEPTION_EXECUTE_HANDLER ) 232 #endif 233 { 234 OSL_ENSURE( sal_False, "Error DeleteTargetDevice" ); 235 } 236 #ifdef __MINGW32__ 237 han.Reset(); 238 #endif 239 } 240 241 242 243 //------------------------------------------------------------------------- 244 // OleStdCopyTargetDevice() 245 // 246 // Purpose: 247 // duplicate a TARGETDEVICE struct. this function allocates memory for 248 // the copy. the caller MUST free the allocated copy when done with it 249 // using the standard allocator returned from CoGetMalloc. 250 // (OleStdFree can be used to free the copy). 251 // 252 // Parameters: 253 // ptdSrc pointer to source TARGETDEVICE 254 // 255 // Return Value: 256 // pointer to allocated copy of ptdSrc 257 // if ptdSrc==NULL then retuns NULL is returned. 258 // if ptdSrc!=NULL and memory allocation fails, then NULL is returned 259 //------------------------------------------------------------------------- 260 261 DVTARGETDEVICE* SAL_CALL CopyTargetDevice( DVTARGETDEVICE* ptdSrc ) 262 { 263 DVTARGETDEVICE* ptdDest = NULL; 264 265 #ifdef __MINGW32__ 266 jmp_buf jmpbuf; 267 __SEHandler han; 268 if (__builtin_setjmp(jmpbuf) == 0) 269 { 270 han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER); 271 #else 272 __try 273 { 274 #endif 275 if ( NULL != ptdSrc ) 276 { 277 ptdDest = static_cast< DVTARGETDEVICE* >( CoTaskMemAlloc( ptdSrc->tdSize ) ); 278 rtl_copyMemory( ptdDest, ptdSrc, static_cast< size_t >( ptdSrc->tdSize ) ); 279 } 280 } 281 #ifdef __MINGW32__ 282 han.Reset(); 283 #else 284 __except( EXCEPTION_EXECUTE_HANDLER ) 285 { 286 } 287 #endif 288 289 return ptdDest; 290 } 291 292 293 //------------------------------------------------------------------------- 294 // OleStdCopyFormatEtc() 295 // 296 // Purpose: 297 // Copies the contents of a FORMATETC structure. this function takes 298 // special care to copy correctly copying the pointer to the TARGETDEVICE 299 // contained within the source FORMATETC structure. 300 // if the source FORMATETC has a non-NULL TARGETDEVICE, then a copy 301 // of the TARGETDEVICE will be allocated for the destination of the 302 // FORMATETC (petcDest). 303 // 304 // NOTE: the caller MUST free the allocated copy of the TARGETDEVICE 305 // within the destination FORMATETC when done with it 306 // using the standard allocator returned from CoGetMalloc. 307 // (OleStdFree can be used to free the copy). 308 // 309 // Parameters: 310 // petcDest pointer to destination FORMATETC 311 // petcSrc pointer to source FORMATETC 312 // 313 // Return Value: 314 // returns TRUE if copy was successful; 315 // retuns FALSE if not successful, e.g. one or both of the pointers 316 // were invalid or the pointers were equal 317 //------------------------------------------------------------------------- 318 319 sal_Bool SAL_CALL CopyFormatEtc( LPFORMATETC petcDest, LPFORMATETC petcSrc ) 320 { 321 sal_Bool bRet = sal_False; 322 323 #ifdef __MINGW32__ 324 jmp_buf jmpbuf; 325 __SEHandler han; 326 if (__builtin_setjmp(jmpbuf) == 0) 327 { 328 han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER); 329 #else 330 __try 331 { 332 #endif 333 if ( petcDest != petcSrc ) 334 { 335 336 petcDest->cfFormat = petcSrc->cfFormat; 337 338 petcDest->ptd = NULL; 339 if ( NULL != petcSrc->ptd ) 340 petcDest->ptd = CopyTargetDevice(petcSrc->ptd); 341 342 petcDest->dwAspect = petcSrc->dwAspect; 343 petcDest->lindex = petcSrc->lindex; 344 petcDest->tymed = petcSrc->tymed; 345 346 bRet = sal_True; 347 } 348 } 349 #ifdef __MINGW32__ 350 else 351 #else 352 __except( EXCEPTION_EXECUTE_HANDLER ) 353 #endif 354 { 355 OSL_ENSURE( sal_False, "Error CopyFormatEtc" ); 356 } 357 #ifdef __MINGW32__ 358 han.Reset(); 359 #endif 360 361 return bRet; 362 } 363 364 //------------------------------------------------------------------------- 365 // returns: 366 // 1 for exact match, 367 // 0 for no match, 368 // -1 for partial match (which is defined to mean the left is a subset 369 // of the right: fewer aspects, null target device, fewer medium). 370 //------------------------------------------------------------------------- 371 372 sal_Int32 SAL_CALL CompareFormatEtc( const FORMATETC* pFetcLhs, const FORMATETC* pFetcRhs ) 373 { 374 sal_Int32 nMatch = FORMATETC_EXACT_MATCH; 375 376 #ifdef __MINGW32__ 377 jmp_buf jmpbuf; 378 __SEHandler han; 379 if (__builtin_setjmp(jmpbuf) == 0) 380 { 381 han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER); 382 #else 383 __try 384 { 385 #endif 386 if ( pFetcLhs != pFetcRhs ) 387 388 if ( ( pFetcLhs->cfFormat != pFetcRhs->cfFormat ) || 389 ( pFetcLhs->lindex != pFetcRhs->lindex ) || 390 !CompareTargetDevice( pFetcLhs->ptd, pFetcRhs->ptd ) ) 391 { 392 nMatch = FORMATETC_NO_MATCH; 393 } 394 395 else if ( pFetcLhs->dwAspect == pFetcRhs->dwAspect ) 396 // same aspects; equal 397 ; 398 else if ( ( pFetcLhs->dwAspect & ~pFetcRhs->dwAspect ) != 0 ) 399 { 400 // left not subset of aspects of right; not equal 401 nMatch = FORMATETC_NO_MATCH; 402 } 403 else 404 // left subset of right 405 nMatch = FORMATETC_PARTIAL_MATCH; 406 407 if ( nMatch == FORMATETC_EXACT_MATCH || nMatch == FORMATETC_PARTIAL_MATCH ) 408 { 409 if ( pFetcLhs->tymed == pFetcRhs->tymed ) 410 // same medium flags; equal 411 ; 412 else if ( ( pFetcLhs->tymed & ~pFetcRhs->tymed ) != 0 ) 413 { 414 // left not subset of medium flags of right; not equal 415 nMatch = FORMATETC_NO_MATCH; 416 } 417 else 418 // left subset of right 419 nMatch = FORMATETC_PARTIAL_MATCH; 420 } 421 } 422 #ifdef __MINGW32__ 423 else 424 #else 425 __except( EXCEPTION_EXECUTE_HANDLER ) 426 #endif 427 { 428 OSL_ENSURE( sal_False, "Error CompareFormatEtc" ); 429 nMatch = FORMATETC_NO_MATCH; 430 } 431 #ifdef __MINGW32__ 432 han.Reset(); 433 #endif 434 435 return nMatch; 436 } 437 438 439 //------------------------------------------------------------------------- 440 // 441 //------------------------------------------------------------------------- 442 443 sal_Bool SAL_CALL CompareTargetDevice( DVTARGETDEVICE* ptdLeft, DVTARGETDEVICE* ptdRight ) 444 { 445 sal_Bool bRet = sal_False; 446 447 #ifdef __MINGW32__ 448 jmp_buf jmpbuf; 449 __SEHandler han; 450 if (__builtin_setjmp(jmpbuf) == 0) 451 { 452 han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER); 453 #else 454 __try 455 { 456 #endif 457 if ( ptdLeft == ptdRight ) 458 { 459 // same address of td; must be same (handles NULL case) 460 bRet = sal_True; 461 } 462 463 // one ot the two is NULL 464 else if ( ( NULL != ptdRight ) && ( NULL != ptdLeft ) ) 465 466 if ( ptdLeft->tdSize == ptdRight->tdSize ) 467 468 if ( rtl_compareMemory( ptdLeft, ptdRight, ptdLeft->tdSize ) == 0 ) 469 bRet = sal_True; 470 } 471 #ifdef __MINGW32__ 472 else 473 #else 474 __except( EXCEPTION_EXECUTE_HANDLER ) 475 #endif 476 { 477 OSL_ENSURE( sal_False, "Error CompareTargetDevice" ); 478 bRet = sal_False; 479 } 480 #ifdef __MINGW32__ 481 han.Reset(); 482 #endif 483 484 return bRet; 485 } 486