- Timestamp:
- Apr 13, 2004, 4:17:01 PM (21 years ago)
- Location:
- trunk/src/user32
- Files:
-
- 2 added
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/user32/Makefile
r10379 r10578 1 # $Id: Makefile,v 1.1 09 2004-01-11 12:03:12sandervl Exp $1 # $Id: Makefile,v 1.110 2004-04-13 14:16:41 sandervl Exp $ 2 2 3 3 # … … 113 113 $(OBJDIR)\dragdrop.obj \ 114 114 $(OBJDIR)\oslibdnd.obj \ 115 $(OBJDIR)\oslibclipbrd.obj \ 115 116 !ifdef DEBUG 116 117 $(OBJDIR)\dbgwrap.obj \ -
trunk/src/user32/clipboard.cpp
r10195 r10578 1 /* $Id: clipboard.cpp,v 1.1 7 2003-07-31 16:07:56sandervl Exp $ */1 /* $Id: clipboard.cpp,v 1.18 2004-04-13 14:16:42 sandervl Exp $ */ 2 2 3 3 /* … … 7 7 * Copyright 1998 Patrick Haller 8 8 * Copyright 1998 Peter Fitzsimmons 9 * 9 * Copyright 2004 InnoTek Systemberatung GmbH 10 10 * 11 11 * NOTE: Use OS/2 frame handles for Open32 functions … … 15 15 */ 16 16 17 /** @page user32_clipboard Clipboard 18 * 19 * The clipboard implemenation is based on using the OS/2 clipboard, sharing 20 * the few compatible formats while registering private formats for the rest. 21 * 22 * The OS/2 and Windows clipboards are very similar although the Windows one 23 * have evolved a bit further than the OS/2 one. Still, they send basically 24 * the same window messages to the clipboard owner and viewer. They both support 25 * having multiple formats present at the same time. 26 * 27 * Windows however, have a feature for automatic synthesizing of alternative 28 * data formats. For instance if there is one of the CF_TEXT, CF_UNICODETEXT, 29 * CF_OEMTEXT formats put onto the clipboard, the other two will be synthesized. 30 * Similar for CF_BITMAP, CF_DIB and CF_DIBV5. CF_DIB and CF_DIBV5 also causes 31 * CF_PALETTE to be synthesized. CF_METAFILEPICT and CF_ENHMETAFILE are also 32 * synthesized when the other is present. 33 * 34 * The Odin32 clipboard implementation will support synthesizing all but the 35 * metafiles and palette in it's current incarnation. 36 * 37 * CF_LOCALE is a special format which is generated when text is put onto the 38 * clipboard. It contains a MAKELCID DWORD. It's will be generated when the 39 * clipboard is closed since no other process (or thread for that matter) can 40 * access the clipboard when it's opened by someone else. CF_LOCALE will be 41 * faked if OS/2 put some text onto the clipboard. 42 * 43 * The ranges of private and gdi formats are registered with PM on demand 44 * to limit resource waste and minimize startup penalty. 45 * 46 * The synthesized format are reported, and we store a special fake handle 47 * for those which haven't yet been converted. This can of course only be 48 * done for formats which we do not share with PM; CF_TEXT, CF_BITMAP, 49 * and CF_PALETTE. 50 * 51 * When data is retrieved from the clipboard a copy is made for the calling 52 * process. In windows EmptyClipboard() will cleanup only in the global 53 * data and the local copies in the calling process. That means other 54 * processes which have retrieved data from the clipboard will not have 55 * their data invalidated till they them self call EmptyClipboard(). 56 * 57 */ 58 59 60 /******************************************************************************* 61 * Header Files * 62 *******************************************************************************/ 17 63 #include <os2win.h> 18 64 #include <string.h> 19 65 #include "win32wbase.h" 20 66 #include <unicode.h> 67 #include <stdio.h> 68 #include <ctype.h> 69 #include "oslibclipbrd.h" 70 #include "oslibutil.h" 71 #include "oslibwin.h" 72 73 /* missing somewhere */ 74 #ifndef LCS_sRGB 75 #define LCS_sRGB 0x73524742 //'RGBs' 76 #endif 21 77 22 78 #define DBG_LOCALLOG DBG_clipboard 23 79 #include "dbglocal.h" 24 80 25 //****************************************************************************** 26 //****************************************************************************** 27 BOOL WIN32API ChangeClipboardChain( HWND hwndRemove, HWND hwndNext) 28 { 29 Win32BaseWindow *wndRemove, *wndNext; 30 HWND hwndOS2Remove, hwndOS2Next = 0; 31 32 wndRemove = Win32BaseWindow::GetWindowFromHandle(hwndRemove); 33 if(!wndRemove) { 34 dprintf(("ChangeClipboardChain, window %x not found", hwndRemove)); 81 82 83 /******************************************************************************* 84 * Defined Constants And Macros * 85 *******************************************************************************/ 86 87 /** Define this to return the V5 DIB headers to the application. 88 * If not defined we will not convert anything to DIBV5 headers, but we'll still 89 * accept DIBV5 headers from the application. 90 */ 91 #define USE_DIBV5 1 92 93 94 /** 95 * Debug assertion macro. 96 * @param expr Assert that this expression is true. 97 * @param msg Message to print if expr isn't true. It's given to dprintf, 98 * and must be inclosed in paratheses. 99 * @todo move this to some header in /include. 100 */ 101 #ifdef DEBUG 102 #define DebugAssert(expr, msg) \ 103 do { if (expr) break; \ 104 dprintf(("!!!ASSERTION FAILED!!!\nFILE=%s\nLINE=%d\nFUNCTION=%s\n", __FILE__, __LINE__, __FUNCTION__)); \ 105 dprintf(msg); DebugInt3(); \ 106 } while (0) 107 #else 108 #define DebugAssert(expr, msg) do {} while (0) 109 #endif 110 111 /** 112 * Debug assertion failed macro. 113 * @param msg Message to print if expr isn't true. It's given to dprintf, 114 * and must be inclosed in paratheses. 115 * @todo move this to some header in /include. 116 */ 117 #ifdef DEBUG 118 #define DebugAssertFailed(msg) \ 119 do { dprintf(("!!!ASSERTION FAILED!!!\nFILE=%s\nLINE=%d\nFUNCTION=%s\n", __FILE__, __LINE__, __FUNCTION__)); \ 120 dprintf(msg); DebugInt3(); \ 121 } while (0) 122 #else 123 #define DebugAssertFailed(msg) do {} while (0) 124 #endif 125 126 127 /** Format name strings. 128 * @{ */ 129 #define SZFMT_PRIVATE_PREFIX "Odin32 Private #" 130 #define SZFMT_GDIOBJ_PREFIX "Odin32 GDI Object #" 131 /** @} */ 132 133 /** Dummy handle used for synthesized formats. */ 134 #define DUMMY_HANDLE 0xbeef0001 135 136 137 /******************************************************************************* 138 * Structures and Typedefs * 139 *******************************************************************************/ 140 /** Dynamically registered formats, and the PRIVATE and GDI predefined ranges. */ 141 typedef struct _ClipboardDynamicFormatMapping 142 { 143 /** Odin32 Format. */ 144 UINT uOdin; 145 /** OS/2 format. */ 146 ULONG ulPM; 147 /** Name for registered formats. (NULL for predefined) */ 148 const char *pszName; 149 /** Pointer to the next in the list. */ 150 struct _ClipboardDynamicFormatMapping *pNext; 151 } CLIPDYNFORMMAP, *PCLIPDYNFORMMAP; 152 153 /** Node in the list of local clipboard data. (the get-cache) */ 154 typedef struct _ClipboardLocalData 155 { 156 /** Data type. */ 157 enum 158 { 159 /** GlobalAlloc'ed object. */ 160 enmGlobalMem, 161 /** GDI data - bitmap or palette. */ 162 enmGDI, 163 /** Private data owner cleans up. */ 164 enmPrivate 165 } enmType; 166 /** Clipboard format Format. */ 167 UINT uFormat; 168 /** Handle / pointer to data. */ 169 HANDLE h; 170 /** Pointer to the next node in the list. */ 171 struct _ClipboardLocalData *pNext; 172 } CLIPLOCALDATA, *PCLIPLOCALDATA; 173 174 175 /** Header for Odin32 specific clipboard entries. 176 * (Used to get the correct size of the data.) 177 */ 178 typedef struct _Odin32ClipboardHeader 179 { 180 /** magic number */ 181 char achMagic[8]; 182 /** Size of the following data. 183 * (The interpretation depends on the type.) */ 184 unsigned cbData; 185 /** Odin32 format number. */ 186 unsigned uFormat; 187 } CLIPHEADER, *PCLIPHEADER; 188 189 #define CLIPHEADER_MAGIC "Odin\1\0\1" 190 191 192 /******************************************************************************* 193 * Global Variables * 194 *******************************************************************************/ 195 /** Static mappings. */ 196 static struct 197 { 198 /** Odin32 Format. */ 199 UINT uOdin; 200 /** OS/2 format. */ 201 ULONG ulPM; 202 /** Format name for registration. */ 203 const char *pszRegString; 204 /** Description. (debug) */ 205 const char *pszDescr; 206 } gaFormats[] = 207 { 208 { CF_TEXT , OSLIB_CF_TEXT , NULL , "CF_TEXT"}, 209 { CF_BITMAP , OSLIB_CF_BITMAP , NULL , "CF_BITMAP"}, 210 { CF_PALETTE , OSLIB_CF_PALETTE , NULL , "CF_PALETTE"}, 211 { CF_LOCALE , ~0 , "Odin32 Locale" , "CF_LOCALE"}, 212 { CF_UNICODETEXT , ~0 , "Odin32 UnicodeText" , "CF_UNICODETEXT"}, 213 { CF_OEMTEXT , ~0 , "Odin32 OEM Text" , "CF_OEMTEXT"}, 214 { CF_DIB , ~0 , "Odin32 Device Independent Bitmap (DIB)" , "CF_DIB"}, 215 { CF_DIBV5 , ~0 , "Odin32 Device Independent Bitmap V5 (DIBV5)" , "CF_DIBV5"}, 216 { CF_METAFILEPICT , ~0 , "Odin32 MetaFilePict" , "CF_METAFILEPICT"}, 217 { CF_ENHMETAFILE , ~0 , "Odin32 Enh. MetaFile" , "CF_ENHMETAFILE"}, 218 { CF_TIFF , ~0 , "Odin32 Tagged Image Format (TIFF)" , "CF_TIFF"}, 219 { CF_DIF , ~0 , "Odin32 Data Interchange Format (SYLK)" , "CF_DIF"}, 220 { CF_HDROP , ~0 , "Odin32 HDROP" , "CF_HDROP"}, 221 { CF_OWNERDISPLAY , ~0 , "Odin32 OwnerDisplay" , "CF_OWNERDISPLAY"}, 222 { CF_PENDATA , ~0 , "Odin32 PenData" , "CF_PENDATA"}, 223 { CF_SYLK , ~0 , "Odin32 Symlink Format" , "CF_SYLK"}, 224 { CF_RIFF , ~0 , "Odin32 RIFF" , "CF_RIFF"}, 225 { CF_WAVE , ~0 , "Odin32 Wave" , "CF_WAVE"}, 226 { CF_DSPMETAFILEPICT, ~0 , "Odin32 DSP MetaFilePict" , "CF_DSPMETAFILEPICT"}, 227 { CF_DSPENHMETAFILE , ~0 , "Odin32 DSP Enh. MetaFile" , "CF_DSPENHMETAFILE"}, 228 { CF_DSPTEXT , OSLIB_CF_DSPTEXT , NULL , "CF_DSPTEXT"}, 229 { CF_DSPBITMAP , OSLIB_CF_DSPBITMAP, NULL , "CF_DSPBITMAP"}, 230 }; 231 232 /** List of dynamically registered formats. (should perhaps be protected for updates...) 233 * This is used for the CF_PRIVATE, CF_GDIOBJ and registered formats. */ 234 PCLIPDYNFORMMAP gpDynFormats; 235 236 /** List of locally allocated objects. 237 * SetClipboardData and GetClipboardData adds to this list. 238 * This list is freed by EmptyClipboard. 239 * (Access to this list is serialized by the clipboard semaphore in PM.) 240 */ 241 PCLIPLOCALDATA gpLocalData; 242 243 /** The Odin window handle for the last OpenClipboard() call. 244 * We need to keep this around for the EmptyClipboard() so we can set 245 * the correct clipboard owner. 246 */ 247 HWND ghwndOpenClipboard; 248 /** The OS/2 PM Window handle for ghwndOpenClipboard. */ 249 HWND ghwndOS2OpenClipboard; 250 /** The Odin TID of the current clipboard (Odin only) Read/Write Owner. 251 * OpenClipboard and CloseClipboard updates while being behind the PM Clipboard 252 * sempahore. If ASSUMES noone calls Open32 or PM apis directly to close the 253 * clipboard. */ 254 DWORD gtidOpenClipboardThreadId; 255 256 /** Whether or not the current OpenClipboard session have changed the clipboard. 257 * Used by CloseClipboard(). */ 258 BOOL gfClipboardChanged; 259 260 /** Whether or not the current OpenClipboard session have put text onto the clipboard. 261 * Used to determin if CF_LOCALE can be generated correctly or not. 262 */ 263 BOOL gfClipboardChangedText; 264 265 266 /******************************************************************************* 267 * Internal Functions * 268 *******************************************************************************/ 269 #ifdef DEBUG_LOGGING 270 static const char *dbgGetFormatName(UINT uFormat); 271 static void dbgDumpClipboardData(const char *pszPrefix, UINT uFormat, HANDLE hData); 272 #else 273 #define dbgGetFormatName(uFormat) \ 274 ("<!non debug logging mode!>") 275 #define dbgDumpClipboardData(pszPrefix, uFormat, hClibObj) \ 276 do { } while(0) 277 #endif 278 UINT clipboardPMToOdinFormat(ULONG ulPMFormat); 279 static ULONG clipboardOdinToPMFormat(UINT uOdinFormat); 280 static ULONG clipboardAddDynFormat(UINT uFormat, const char *pszFormatName); 281 static BOOL clipboardIsRWOwner(void); 282 static BOOL clipboardAddPM(UINT uOdinFormat, void *pv, unsigned cb); 283 static BOOL clipboardAddPMHeader(UINT uOdinFormat, void *pv, unsigned cb); 284 static BOOL clipboardAddPMHandle(UINT uOdinFormat, HANDLE h); 285 static void * clipboardAllocPMBuffer(unsigned cb); 286 static BOOL clipboardAddPMDummy(UINT uOdinFormat); 287 static ULONG clipboardGetPMDataSize(void *pvData); 288 static BOOL clipboardIsAvailable(UINT uFormat); 289 static BOOL clipboardIsAvailableReal(UINT uFormat); 290 static void clipboardSynthesize(BOOL fHaveModifiedIt); 291 static BOOL clipboardShouldBeSynthesized(UINT uFormat); 292 static HANDLE clipboardSynthesizeText(UINT uFormat); 293 static HANDLE clipboardSynthesizeLocale(UINT uFormat); 294 static HANDLE clipboardSynthesizeBitmap(UINT uFormat); 295 static HANDLE clipboardSynthesizeDIB(UINT uFormat); 296 #if 0 // not implemented yet 297 static HANDLE clipboardSynthesizePalette(UINT uFormat); 298 static HANDLE clipboardSynthesizeMetaFile(UINT uFormat); 299 static HANDLE clipboardSynthesizeEnhMetaFile(UINT uFormat); 300 #endif 301 static unsigned clipboardTextCalcSize(void *pvData, unsigned cb); 302 unsigned clipboardGetCodepage(UINT uType); 303 static HANDLE clipboardCacheAllocGlobalDup(UINT uFormat, const void *pv, unsigned cb, PCLIPLOCALDATA *ppClip); 304 static HANDLE clipboardCacheAllocGlobalAlloc(UINT uFormat, unsigned cb, PCLIPLOCALDATA *ppClip); 305 static BOOL clipboardCacheAllocGlobalMem(UINT uFormat, HANDLE hMem, PCLIPLOCALDATA *ppLocalClip); 306 static BOOL clipboardCacheAllocGDI(UINT uFormat, HANDLE hGDI, PCLIPLOCALDATA *ppLocalClip); 307 //static HANDLE clipboardCacheAllocPrivate(UINT uFormat, HANDLE hPrivate); 308 static HANDLE clipboardCacheInsertNode(PCLIPLOCALDATA p); 309 static void clipboardCacheDeleteNode(PCLIPLOCALDATA p); 310 static void clipboardPMBitmapDelete(HBITMAP hbmp); 311 static HBITMAP clipboardPMBitmapDuplicate(HBITMAP hbmp); 312 static UINT clipboardEnumClipboardFormats(UINT uFormat); 313 314 315 316 /** 317 * Converts a PM clipboard format number to an Odin format. 318 * 319 * @returns Odin format number on success. 320 * @returns 0 on failure. 321 * @param ulPMFormat PM Clipboard format number. 322 */ 323 UINT clipboardPMToOdinFormat(ULONG ulPMFormat) 324 { 325 for (int i = 0; i < sizeof(gaFormats) / sizeof(gaFormats[0]); i++) 326 if (gaFormats[i].ulPM == ulPMFormat) 327 return gaFormats[i].uOdin; 328 for (PCLIPDYNFORMMAP p = gpDynFormats; p; p = p->pNext) 329 if (p->ulPM == ulPMFormat) 330 return p->uOdin; 331 332 /* 333 * Now this becomes interesting. 334 * 335 * We need to check if this is one of the dynamically registered 336 * GDI formats or private formats. Another odin process can have 337 * started using it and we should see it. 338 * 339 * We can tell by the atom name. 340 */ 341 char szAtomName[64]; 342 ULONG cch; 343 cch = OSLibWinQueryAtomName(OSLibWinQuerySystemAtomTable(), ulPMFormat, &szAtomName[0], sizeof(szAtomName)); 344 if (cch > 0) 345 { 346 char *psz; 347 if (!strncmp(szAtomName, SZFMT_GDIOBJ_PREFIX, sizeof(SZFMT_GDIOBJ_PREFIX) - 1)) 348 psz = szAtomName + sizeof(SZFMT_GDIOBJ_PREFIX) - 1; 349 else if (!strncmp(szAtomName, SZFMT_PRIVATE_PREFIX, sizeof(SZFMT_PRIVATE_PREFIX) - 1)) 350 psz = szAtomName + sizeof(SZFMT_PRIVATE_PREFIX) - 1; 351 else 352 return 0; /* not found! */ 353 /* parse the number. */ 354 UINT uRet = atoi(psz); 355 if (uRet >= CF_PRIVATEFIRST && uRet <= CF_GDIOBJLAST) 356 { 357 ULONG ulPMAdded = clipboardAddDynFormat(uRet, NULL); 358 DebugAssert(ulPMAdded == ulPMFormat, 359 ("ARG! Didn't get the same value for the same atoms! odin32=%d pm=%d pmadd=%d name='%s'\n", 360 uRet, ulPMFormat, ulPMAdded, szAtomName)); 361 return uRet; 362 } 363 } 364 365 return 0; /* not found. */ 366 } 367 368 369 /** 370 * Adds a dynamicly managed Odin clipboard format to the internal list. 371 * 372 * @returns PM format number. 373 * @returns 0 on failure. 374 * @param uFormat Odin clipboard format number. 375 * @param pszFormatName The format name. 376 * For the two predefined ranges this argument is NULL. 377 * @todo serialize this! 378 */ 379 ULONG clipboardAddDynFormat(UINT uFormat, const char *pszFormatName) 380 { 381 char szFormat[64]; 382 383 /* 384 * Generate name for the predefined ones. 385 */ 386 if (!pszFormatName) 387 { 388 if (uFormat >= CF_PRIVATEFIRST && uFormat <= CF_PRIVATELAST) 389 sprintf(szFormat, SZFMT_PRIVATE_PREFIX "%u", uFormat); 390 else if (uFormat >= CF_GDIOBJFIRST && uFormat <= CF_GDIOBJLAST) 391 sprintf(szFormat, SZFMT_GDIOBJ_PREFIX "%u", uFormat); 392 else 393 { 394 DebugAssertFailed(("Invalid format range %u\n", uFormat)); 395 return 0; 396 } 397 pszFormatName = szFormat; 398 } 399 400 /* 401 * Register atom 402 */ 403 ULONG ulPMFormat = OSLibWinAddAtom(OSLibWinQuerySystemAtomTable(), pszFormatName); 404 if (ulPMFormat == 0) 405 { 406 DebugAssertFailed(("Faild to add atom '%s'. last error=%d\n", pszFormatName, OSLibWinGetLastError())); 407 return 0; 408 } 409 410 /* 411 * Create a dynamic structure and insert it into the LIFO. 412 */ 413 PCLIPDYNFORMMAP p = (PCLIPDYNFORMMAP)malloc(sizeof(*p)); 414 if (!p) 415 return 0; 416 p->pszName = pszFormatName != szFormat ? strdup(pszFormatName) : NULL; 417 p->ulPM = ulPMFormat; 418 p->uOdin = uFormat; 419 p->pNext = gpDynFormats; 420 gpDynFormats = p; 421 422 dprintf(("USER32: clipboardAddDynFormat: Added odin=%d pm=%d name='%s'\n", uFormat, ulPMFormat, pszFormatName)); 423 return ulPMFormat; 424 } 425 426 427 /** 428 * Converts a PM clipboard format number to an Odin format. 429 * 430 * @returns Odin format number on success. 431 * @returns 0 on failure. 432 * @param ulPMFormat PM Clipboard format number. 433 */ 434 ULONG clipboardOdinToPMFormat(UINT uOdinFormat) 435 { 436 if (uOdinFormat == 0) 437 return 0; 438 for (int i = 0; i < sizeof(gaFormats) / sizeof(gaFormats[0]); i++) 439 if (gaFormats[i].uOdin == uOdinFormat) 440 return gaFormats[i].ulPM; 441 for (PCLIPDYNFORMMAP p = gpDynFormats; p; p = p->pNext) 442 if (p->uOdin == uOdinFormat) 443 return p->ulPM; 444 445 /* 446 * Now this becomes interesting. 447 * 448 * A format showed up which we don't know yet. It could be one 449 * of the built in GDIOBJ or PRIVATE ones, if so we should 450 * register them in the dynamic list. 451 */ 452 if (uOdinFormat >= CF_PRIVATEFIRST && uOdinFormat <= CF_GDIOBJLAST) 453 return clipboardAddDynFormat(uOdinFormat, NULL); 454 return 0; /* not found. */ 455 } 456 457 458 #ifdef DEBUG_LOGGING 459 /** 460 * Gets the name of a format. 461 * 462 * @returns Pointer to const 463 * @param uFormat Format number. 464 * @remark Note that for non standard formats a pointer to a static buffer is 465 * returned. This may be messed up if several threads are doing this 466 * at the same time. (fat chance) 467 */ 468 const char *dbgGetFormatName(UINT uFormat) 469 { 470 static char szBuffer[256]; 471 for (int i = 0; i < sizeof(gaFormats) / sizeof(gaFormats[0]); i++) 472 if (gaFormats[i].uOdin == uFormat) 473 return gaFormats[i].pszDescr; 474 475 for (PCLIPDYNFORMMAP p = gpDynFormats; p; p = p->pNext) 476 if (p->uOdin == uFormat) 477 { 478 if (p->pszName) 479 return p->pszName; /* registered */ 480 if (uFormat >= CF_PRIVATEFIRST && uFormat <= CF_PRIVATELAST) 481 sprintf(szBuffer, "CF_PRIVATE no.%d", uFormat - CF_PRIVATEFIRST); 482 else if (uFormat >= CF_GDIOBJFIRST && uFormat <= CF_GDIOBJLAST) 483 sprintf(szBuffer, "CF_PRIVATE no.%d", uFormat - CF_GDIOBJFIRST); 484 DebugInt3(); 485 break; 486 } 487 488 sprintf(szBuffer, "Unknown format %#x", uFormat); 489 return szBuffer; 490 } 491 492 /** 493 * Debug helper which dumps clipboard data. 494 * 495 * @param pszPrefix Message prefix. 496 * @param uFormat Data format of hData. 497 * @param hData Global memory handle. 498 */ 499 void dbgDumpClipboardData(const char *pszPrefix, UINT uFormat, HANDLE hData) 500 { 501 LPVOID pv = NULL; 502 DWORD cb = 0; 503 504 /* 505 * Get the data. 506 */ 507 switch (uFormat) 508 { 509 /* handles */ 510 case CF_BITMAP: 511 case CF_METAFILEPICT: 512 case CF_DSPBITMAP: 513 case CF_DSPMETAFILEPICT: 514 case CF_ENHMETAFILE: 515 case CF_HDROP: 516 case CF_PALETTE: 517 pv = NULL; 518 break; 519 520 /* all the rest */ 521 default: 522 if (uFormat >= CF_PRIVATEFIRST && uFormat <= CF_PRIVATELAST) 523 pv = NULL; 524 else 525 { 526 if (hData) 527 { 528 pv = GlobalLock(hData); 529 cb = GlobalSize(hData); 530 } 531 else 532 pv = NULL; 533 } 534 break; 535 } 536 dprintf(("%s: uFormat=%#x (%s) hData=%#x {locked=%p size=%d}\n", 537 pszPrefix, uFormat, dbgGetFormatName(uFormat), hData, pv, cb)); 538 539 /* 540 * Dump the data. 541 */ 542 if (pv) 543 { 544 switch (uFormat) 545 { 546 case CF_TEXT: 547 case CF_DSPTEXT: 548 dprintf(("%s: '%s'", pszPrefix, (char*)pv)); 549 if (strlen((char *)pv) + 1 != cb) 550 dprintf(("%s: not properly null terminated? strlen()->%d", pszPrefix, strlen((char *)pv))); 551 break; 552 case CF_UNICODETEXT: 553 dprintf(("%s: '%ls'", pszPrefix, (wchar_t*)pv)); 554 if (lstrlenW((LPCWSTR)pv) + 1 != cb / sizeof(wchar_t)) 555 dprintf(("%s: not properly null terminated? wcslen()->%d", pszPrefix, lstrlenW((LPCWSTR)pv))); 556 break; 557 558 default: 559 { 560 /* quick and somewhat ugly memory dump routine. */ 561 LPBYTE pb; 562 DWORD off; 563 for (off = 0, pb = (LPBYTE)pv; off < cb; off += 16, pb += 16) 564 { 565 char sz[80]; 566 char *pszHex = &sz[sprintf(sz, "%08x ", off)]; 567 char *pszBin = pszHex + 16*3 + 2; 568 for (int i = 0; i < 16; i++, pszHex += 3, pszBin++) 569 { 570 if (i + off < cb) 571 { 572 static const char szHexDigits[17] = "0123456789abcdef"; 573 pszHex[0] = szHexDigits[pb[i] >> 4]; 574 pszHex[1] = szHexDigits[pb[i] & 0xf]; 575 pszHex[2] = i != 7 ? ' ' : '-'; 576 if (isprint(pb[i])) 577 *pszBin = pb[i]; 578 else 579 *pszBin = '.'; 580 } 581 else 582 { 583 memset(pszHex, ' ', 3); 584 *pszBin = '\0'; 585 } 586 } 587 pszHex[0] = ' '; 588 pszHex[1] = ' '; 589 *pszBin = '\0'; 590 dprintf(("%s\n", sz)); 591 } 592 break; 593 } 594 } 595 } 596 } 597 #endif 598 599 600 /** 601 * Initalizes the clipboard formats Odin32 uses. 602 * 603 * These are not the same as the Open32 ones because Odin will put 604 * different data out on the clipboard (the CLIPHEADER header). 605 * 606 * @returns Success indicator. 607 */ 608 BOOL WIN32API InitClipboardFormats(void) 609 { 610 dprintf2(("USER32: InitClipboardFormats\n")); 611 BOOL fRc = TRUE; 612 HANDLE hSysAtomTable = OSLibWinQuerySystemAtomTable(); 613 for (int i = 0; i < sizeof(gaFormats) / sizeof(gaFormats[0]); i++) 614 { 615 if (gaFormats[i].pszRegString) 616 { 617 gaFormats[i].ulPM = OSLibWinAddAtom(hSysAtomTable, gaFormats[i].pszRegString); 618 DebugAssert(gaFormats[i].ulPM > 20 /* MAX OS/2 predefined format */, 619 ("WinAddAtom failed or returns to low value, %d, for '%s'.\n", 620 gaFormats[i].ulPM, gaFormats[i].pszRegString)); 621 if (gaFormats[i].ulPM <= 20) 622 fRc = FALSE; 623 } 624 dprintf2(("odin=0x%04x os2=0x%04x %s\n", gaFormats[i].uOdin, gaFormats[i].ulPM, gaFormats[i].pszDescr)); 625 } 626 return fRc; 627 } 628 629 630 631 //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\// 632 // 633 // 634 // C L I P B O A R D V I E W E R S 635 // 636 // 637 //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\// 638 639 640 641 /** 642 * Adds a window to the clipboard viewer list. 643 * 644 * @returns HWND of the next window. 645 * @returns 0 on failure, last error set. 646 * @param hwndNewViewer Window to add. 647 * @status partially implemented 648 * @author knut st. osmundsen <bird-srcspam@anduin.net> 649 * @remark PM manages the list, not the caller, therefor the return is allways NULL. 650 */ 651 HWND WIN32API SetClipboardViewer(HWND hwndNewViewer) 652 { 653 /* 654 * Validate and translate hwndNewViewer to an OS/2 handle. 655 */ 656 HWND hwndOS2 = OSLIB_HWND_DESKTOP; /* open32 does this it seems. */ 657 if (hwndNewViewer) 658 { 659 Win32BaseWindow * pWnd = Win32BaseWindow::GetWindowFromHandle(hwndNewViewer); 660 if (!pWnd) 661 { 662 SetLastError(ERROR_INVALID_WINDOW_HANDLE); 663 dprintf(("USER32: SetClipboardViewer: returns 0 (invalid window)\n")); 664 return NULL; 665 } 666 hwndOS2 = pWnd->getOS2WindowHandle(); 667 RELEASE_WNDOBJ(pWnd); 668 } 669 670 /* 671 * Add the viewer. 672 */ 673 if (!OSLibWin32AddClipbrdViewer(hwndOS2)) 674 { 675 SetLastError(ERROR_NOT_ENOUGH_MEMORY); // just something. 676 dprintf(("USER32: Win32AddClipbrdViwer failed. lasterr=%#x\n", OSLibWinGetLastError())); 677 } 678 dprintf(("USER32: SetClipboardViewer returns 0 (allways)\n")); 679 return NULL; 680 } 681 682 683 /** 684 * Gets the current clipboard viewer. 685 * 686 * @returns Window handle of the clipboard viewer. 687 * @returns NULL if no viewer or non odin window. 688 * @status partially implemented. 689 * @author knut st. osmundsen <bird-srcspam@anduin.net> 690 * @remark Hides OS/2 windows. 691 */ 692 HWND WIN32API GetClipboardViewer(void) 693 { 694 /* 695 * Query the viewer from PM and translate it to an Odin window handle. 696 */ 697 HWND hwnd = NULL; 698 HWND hwndOS2 = OSLibWin32QueryClipbrdViewerChain(); 699 if (hwndOS2) 700 { 701 Win32BaseWindow *pWnd = Win32BaseWindow::GetWindowFromOS2Handle(hwndOS2); 702 if (pWnd) 703 { 704 hwnd = pWnd->getWindowHandle(); 705 RELEASE_WNDOBJ(pWnd); 706 } 707 } 708 dprintf(("USER32: GetClipboardViewer: returns %# (os2=%#x)\n", hwnd, hwndOS2)); 709 return hwnd; 710 } 711 712 713 /** 714 * Removes a specific window from the chain of clipboard viewers. 715 * 716 * @returns Success indicator. Last error set on failure. 717 * @param hwndRemove Handle of viewer window to remove. 718 * @param hwndNext Handle to the next window in the chain. 719 * OS/2 doesn't support this, so we ignore it. 720 * @status partially implemented. 721 * @author knut st. osmundsen <bird-srcspam@anduin.net> 722 */ 723 BOOL WIN32API ChangeClipboardChain(HWND hwndRemove, HWND hwndNext) 724 { 725 dprintf(("USER32: ChangeClipboardChain: hwndRemove=%#x hwndNext=%#x\n", hwndRemove, hwndNext)); 726 727 /* 728 * Validate input handles and translate them to OS/2 windows. 729 */ 730 Win32BaseWindow *pWnd = Win32BaseWindow::GetWindowFromHandle(hwndRemove); 731 if (!pWnd) 732 { 733 dprintf(("USER32: ChangeClipboardChain: window %x not found\n", hwndRemove)); 35 734 SetLastError(ERROR_INVALID_WINDOW_HANDLE); 735 return FALSE; 736 } 737 HWND hwndOS2Remove = pWnd->getOS2WindowHandle(); 738 RELEASE_WNDOBJ(pWnd); 739 740 if (hwndNext) 741 { 742 /* 743 * SetClipboardViewer never returns a hwndNext, so this must 744 * be an program trying to alter things in a way other than we like... 745 * We might find that we have to support this using the Wn32AddClipbrdViewer 746 * or something later, but for now we fail. 747 */ 748 749 /* validate it, to come up with a more believable story. */ 750 pWnd = Win32BaseWindow::GetWindowFromHandle(hwndNext); 751 if (!pWnd) 752 { 753 dprintf(("USER32: ChangeClipboardChain: window %x not found\n", hwndNext)); 754 SetLastError(ERROR_INVALID_WINDOW_HANDLE); 755 return FALSE; 756 } 757 HWND hwndOS2Next = pWnd->getOS2WindowHandle(); 758 RELEASE_WNDOBJ(pWnd); 759 DebugAssertFailed(("USER32: ChangeClipboardChain: hwndNext=%#x/%#x is not supported!!!\n", hwndNext, hwndOS2Next)); 760 SetLastError(ERROR_INVALID_PARAMETER); 761 return FALSE; 762 } 763 764 /* 765 * Change the chain. 766 */ 767 BOOL fRc = OSLibWin32RemoveClipbrdViewer(hwndOS2Remove); 768 dprintf(("USER32: ChangeClipboardChain returns %d\n", fRc)); 769 return fRc; 770 } 771 772 773 774 775 //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\// 776 // 777 // 778 // C L I P B O A R D N O N - O P E N O P E R A T I O N S 779 // 780 // 781 //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\// 782 783 /** 784 * Checks if a format is available on the PM clipboard. 785 * 786 * @returns TRUE if it's there, FALSE if it isn't 787 * @param uFormat Odin format number. 788 */ 789 BOOL clipboardIsAvailable(UINT uFormat) 790 { 791 ULONG ulPMFormat = clipboardOdinToPMFormat(uFormat); 792 if (!ulPMFormat) 793 return FALSE; 794 ULONG flInfo; 795 return OSLibWinQueryClipbrdFmtInfo(GetThreadHAB(), ulPMFormat, &flInfo); 796 } 797 798 799 /** 800 * Checks if a real representation of a format is available on the PM 801 * clipboard. (Real representation means ignoring dummy entries.) 802 * 803 * @returns TRUE if it's there, FALSE if it isn't 804 * @param uFormat Odin format number. 805 */ 806 BOOL clipboardIsAvailableReal(UINT uFormat) 807 { 808 ULONG ulPMFormat = clipboardOdinToPMFormat(uFormat); 809 if (!ulPMFormat) 810 return FALSE; 811 ULONG flInfo = 0; 812 HANDLE hab = GetThreadHAB(); 813 if (!OSLibWinQueryClipbrdFmtInfo(hab, ulPMFormat, &flInfo)) 814 return FALSE; 815 if (!(flInfo & OSLIB_CFI_HANDLE)) 816 return TRUE; 817 return OSLibWinQueryClipbrdData(hab, ulPMFormat) != DUMMY_HANDLE; 818 } 819 820 821 /** 822 * Count the number of available clipboard formats. 823 * 824 * @returns Number of clipboard forats on the clipboard. 825 * @status completely implemented. 826 * @author knut st. osmundsen <bird-srcspam@anduin.net> 827 * @remark This call can be done without opening the clipboard. 828 */ 829 int WIN32API CountClipboardFormats(void) 830 { 831 int cRet = 0; 832 UINT uFormat = 0; 833 HANDLE hab = GetThreadHAB(); 834 835 while ((uFormat = clipboardEnumClipboardFormats(uFormat)) != 0) 836 cRet++; 837 838 dprintf(("USER32: CountClipboardFormats: returns %d\n", cRet)); 839 return cRet; 840 } 841 842 843 /** 844 * Checks if a given format is available on the clipboard. 845 * 846 * @returns TRUE if it's availble, else false. 847 * @param uFormat Format to check for. 848 * @status completely implemented. 849 * @author knut st. osmundsen <bird-srcspam@anduin.net> 850 */ 851 BOOL WIN32API IsClipboardFormatAvailable(UINT uFormat) 852 { 853 ULONG ulPMFormat = clipboardOdinToPMFormat(uFormat); 854 if (!ulPMFormat) 855 { 856 dprintf(("USER32: IsClipboardFormatAvailable: uFormat=%d returns FALSE (unknown format)\n", uFormat)); 857 return FALSE; 858 } 859 860 ULONG flInfo; 861 BOOL fRc = OSLibWinQueryClipbrdFmtInfo(GetThreadHAB(), ulPMFormat, &flInfo); 862 if (!fRc && (!clipboardIsRWOwner() || !gfClipboardChanged)) 863 fRc = clipboardShouldBeSynthesized(uFormat); 864 dprintf(("USER32: IsClipboardFormatAvailable: %x (%s) returning %d\n", 865 uFormat, dbgGetFormatName(uFormat), fRc)); 866 return fRc; 867 } 868 869 870 /** 871 * Get the format with the lowest index in the passed in list. 872 * 873 * @returns format number with highest priority. 874 * @returns 0 if no formats in the list. 875 * @returns 0 if no data on the clipboard. 876 * @returns -1 if non of the formats was found. 877 * @param paFormatPriorityList 878 * @param cFormats 879 * @status partially implemented 880 * @author knut st. osmundsen <bird-srcspam@anduin.net> 881 * @todo We don't check if the thread is owning the clipboard. 882 */ 883 int WIN32API GetPriorityClipboardFormat(UINT *paFormatPriorityList, int cFormats) 884 { 885 int i; 886 dprintf(("USER32: GetPriorityClipboardFormat: paFormatPriorityList=%p cFormat=%d\n", 887 paFormatPriorityList, cFormats)); 888 /* 889 * Validate input. 890 */ 891 if ((paFormatPriorityList == NULL && cFormats > 0) || cFormats < 0) 892 { 893 SetLastError(ERROR_NOACCESS); 894 dprintf(("USER32: GetPriorityClipboardFormat: returns 0 (bad list pointer)\n")); 36 895 return 0; 37 896 } 38 hwndOS2Remove = wndRemove->getOS2WindowHandle(); 39 RELEASE_WNDOBJ(wndRemove); 40 41 if(hwndNext) { 42 wndNext = Win32BaseWindow::GetWindowFromHandle(hwndNext); 43 if(!wndNext) { 44 dprintf(("ChangeClipboardChain, window %x not found", hwndNext)); 897 #ifdef DEBUG_LOGGING 898 for (i = 0; i < cFormats; i++) 899 dprintf2((" %d - %#x (%s)\n", i, paFormatPriorityList[i], 900 dbgGetFormatName(paFormatPriorityList[i]))); 901 #endif 902 903 /* 904 * Check if list is empty. 905 */ 906 if (cFormats <= 0) 907 { 908 dprintf(("USER32: GetPriorityClipboardFormat: return -1 (list is empty)\n")); 909 return -1; 910 } 911 912 /* 913 * Check if clipboard is empty. 914 */ 915 HANDLE hab = GetThreadHAB(); 916 if (!OSLibWinEnumClipbrdFmts(hab, 0)) 917 { 918 dprintf(("USER32: GetPriorityClipboardFormat: return 0 (clipboard is empty)\n")); 919 return 0; 920 } 921 922 /* 923 * Walk the list. 924 */ 925 for (i = 0; i < cFormats; i++) 926 { 927 if (IsClipboardFormatAvailable(paFormatPriorityList[i])) 928 { 929 dprintf(("USER32: GetPriorityClipboardFormat: return %d (%s), index %d\n", 930 paFormatPriorityList[i], dbgGetFormatName(paFormatPriorityList[i]), i)); 931 return paFormatPriorityList[i]; 932 } 933 } 934 935 dprintf(("USER32: GetPriorityClipboardFormat: return -1 (not found)\n")); 936 return -1; 937 } 938 939 /** 940 * Gets the format name of a registered clipboard format. 941 * 942 * @returns number of bytes in lpszFormatName which was used not counting the terminator. 943 * @returns 0 on failure, last error set. 944 * @param uFormat Format number. 945 * @param lpszFormatName Where to store the name. 946 * @param cchMaxCount Size of the buffer. 947 * @status completely implemented. 948 * @author knut st. osmundsen <bird-srcspam@anduin.net> 949 */ 950 int WIN32API GetClipboardFormatNameA(UINT uFormat, LPSTR lpszFormatName, int cchMaxCount) 951 { 952 dprintf(("USER32: GetClipboardFormatNameA: uFormat=%d buf=%p cchBuf=%d\n", 953 uFormat, lpszFormatName, cchMaxCount)); 954 955 /* 956 * Validate input. 957 */ 958 if (uFormat < MAXINTATOM) 959 { 960 SetLastError(ERROR_INVALID_PARAMETER); 961 dprintf(("USER32: GetClipboardFormatNameA: returns 0 (builtin format)\n")); 962 return 0; 963 } 964 965 /* 966 * Do work. 967 */ 968 int rc = GetAtomNameA((ATOM)uFormat, lpszFormatName, cchMaxCount); 969 dprintf(("USER32: GetClipboardFormatNameA: returns %d (%s)\n", rc, rc > 0 ? lpszFormatName : NULL)); 970 return rc; 971 } 972 973 974 /** 975 * Gets the format name of a registered clipboard format. 976 * 977 * @returns number of bytes in lpszFormatName which was used not counting the terminator. 978 * @returns 0 on failure, last error set. 979 * @param uFormat Format number. 980 * @param lpszFormatName Where to store the name. 981 * @param cchMaxCount Size of the buffer. 982 * @status completely implemented. 983 * @author knut st. osmundsen <bird-srcspam@anduin.net> 984 */ 985 int WIN32API GetClipboardFormatNameW(UINT uFormat, LPWSTR lpszFormatName, int cchMaxCount) 986 { 987 dprintf(("USER32: GetClipboardFormatNameW: uFormat=%d buf=%p cchBuf=%d\n", 988 uFormat, lpszFormatName, cchMaxCount)); 989 990 /* 991 * Validate input. 992 */ 993 if (uFormat < MAXINTATOM) 994 { 995 SetLastError(ERROR_INVALID_PARAMETER); 996 dprintf(("USER32: GetClipboardFormatNameW: returns 0 (builtin format)\n")); 997 return 0; 998 } 999 1000 /* 1001 * Do work. 1002 */ 1003 int rc = GetAtomNameW((ATOM)uFormat, lpszFormatName, cchMaxCount); 1004 dprintf(("USER32: GetClipboardFormatNameW: returns %d (%ls)\n", rc, rc > 0 ? lpszFormatName : NULL)); 1005 return rc; 1006 } 1007 1008 1009 /** 1010 * Register a name application specific clipboard format. 1011 * 1012 * @returns The clipboard number for the format. 1013 * @returns 0 on failure, last error set. 1014 * @param pszName Clipboard format name. 1015 * @status completely implemented. 1016 * @author knut st. osmundsen <bird-srcspam@anduin.net> 1017 */ 1018 UINT WIN32API RegisterClipboardFormatA(LPCSTR pszName) 1019 { 1020 dprintf(("USER32: RegisterClipboardFormatA: pszName=%s\n", pszName)); 1021 1022 /* 1023 * Custom formats are atoms. 1024 * And for some reason which isn't too obvious to me, they are local 1025 * atoms, not global atoms like in OS/2. I might be wrong here... 1026 */ 1027 UINT uFormat = AddAtomA(pszName); 1028 if (uFormat) 1029 { 1030 char szName[256]; 1031 sprintf(szName, "odin32 dyn: %.242s", pszName); 1032 clipboardAddDynFormat(uFormat, szName); 1033 } 1034 dprintf(("USER32: RegisterClipboardFormatA: returns %u\n", uFormat)); 1035 return uFormat; 1036 } 1037 1038 1039 /** 1040 * Register a name application specific clipboard format. 1041 * 1042 * @returns The clipboard number for the format. 1043 * @returns 0 on failure, last error set. 1044 * @param pszName Clipboard format name. 1045 * @status completely implemented. 1046 * @author knut st. osmundsen <bird-srcspam@anduin.net> 1047 */ 1048 UINT WIN32API RegisterClipboardFormatW(LPCWSTR pszName) 1049 { 1050 dprintf(("USER32: RegisterClipboardFormatW: pszName=%ls\n", pszName)); 1051 1052 /* 1053 * Custom formats are atoms. 1054 * And for some reason which isn't too obvious to me, they are local 1055 * atoms, not global atoms like in OS/2. I might be wrong here... 1056 */ 1057 UINT uFormat = AddAtomW(pszName); 1058 if (uFormat) 1059 { 1060 char szName[256]; 1061 sprintf(szName, "odin32 dyn: %.242ls", pszName); /* bogus to use crt for unicode->ascii conversion? */ 1062 clipboardAddDynFormat(uFormat, szName); 1063 } 1064 dprintf(("USER32: RegisterClipboardFormatW: returns %u\n", uFormat)); 1065 return uFormat; 1066 } 1067 1068 1069 /** 1070 * Gets the window handle of the current clipboard owner. 1071 * 1072 * @returns HWND of current owner. 1073 * @returns NULL if no owner. 1074 * @status partially implemented. 1075 * @author knut st. osmundsen <bird-srcspam@anduin.net> 1076 * @remark We do not report back any OS/2 windows. 1077 */ 1078 HWND WIN32API GetClipboardOwner(void) 1079 { 1080 /* 1081 * Query the owner from PM and translate it to an Odin window handle. 1082 */ 1083 HWND hwnd = NULL; 1084 HWND hwndOS2 = OSLibWinQueryClipbrdOwner(GetThreadHAB()); 1085 if (hwndOS2) 1086 { 1087 Win32BaseWindow *pWnd = Win32BaseWindow::GetWindowFromOS2Handle(hwndOS2); 1088 if (pWnd) 1089 { 1090 hwnd = pWnd->getWindowHandle(); 1091 RELEASE_WNDOBJ(pWnd); 1092 } 1093 } 1094 1095 dprintf(("USER32: GetClipboardOwner: returns %#x (os2=%#x)\n", hwnd, hwndOS2)); 1096 return hwnd; 1097 } 1098 1099 1100 /** 1101 * Gets the hwnd of the window which currently have the clipboard open. 1102 * 1103 * @returns the HWND of the window. 1104 * @returns NULL if the clipboard is not opened by anyone or the open 1105 * didn't supply a window handle (like PM). 1106 * @status completely implemented. 1107 * @author knut st. osmundsen <bird-srcspam@anduin.net> 1108 */ 1109 HWND WIN32API GetOpenClipboardWindow(void) 1110 { 1111 /* 1112 * Get the open windown handle and translate it. 1113 */ 1114 HWND hwnd = NULL; 1115 HWND hwndOS2 = OSLibWin32QueryOpenClipbrdWindow(); 1116 if (hwndOS2) 1117 { 1118 Win32BaseWindow *pWnd = Win32BaseWindow::GetWindowFromOS2Handle(hwndOS2); 1119 if (pWnd) 1120 { 1121 hwnd = pWnd->getWindowHandle(); 1122 RELEASE_WNDOBJ(pWnd); 1123 } 1124 } 1125 DebugAssert(ghwndOpenClipboard == hwnd, ("ghwndOpenClipboard=%#x actual=%#x\n", ghwndOpenClipboard, hwnd)); 1126 DebugAssert((!hwnd && !ghwndOS2OpenClipboard) || (hwnd && ghwndOS2OpenClipboard != hwndOS2), 1127 ("ghwndOS2OpenClipboard=%#x actual=%#x\n", ghwndOS2OpenClipboard, hwndOS2)); 1128 dprintf(("USER32: GetOpenCliboardWindow: returning %#x (os2=%#x)\n", hwnd, hwndOS2)); 1129 return hwnd; 1130 } 1131 1132 1133 1134 1135 1136 1137 //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\// 1138 // 1139 // 1140 // C L I P B O A R D O P E N E D O P E R A T I O N S 1141 // 1142 // 1143 //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\// 1144 1145 1146 /** 1147 * Checks if the current thread is the clipboard owner with read/write access. 1148 * 1149 * @returns TRUE if we're the owner, FALSE if not. 1150 */ 1151 BOOL clipboardIsRWOwner(void) 1152 { 1153 #if 1 1154 /* 1155 * The simple way. 1156 */ 1157 return gtidOpenClipboardThreadId == GetCurrentThreadId(); 1158 #else 1159 /* 1160 * This is gonna be a bit hacky. 1161 * We'll try to open the clipboard and then determin whether or not 1162 * we already owned it by the return code and such. 1163 */ 1164 BOOL fRc = FALSE; 1165 HAB hab = GetThreadHAB(); 1166 OSLibWinSetErrorInfo(0, 0); 1167 OSLibWinGetLastError(); 1168 if (!OSLib_OpenClipbrd(hab, (HWND)0xdeadface)) 1169 { 1170 /* check why we failed. */ 1171 if ((OSLibWinGetLastError() & 0xffff) == OSLIB_PMERR_CALL_FROM_WRONG_THREAD) 1172 fRc = TRUE; 1173 } 1174 else 1175 { 1176 /* we might have to close it ... */ 1177 ULONG ulRc = OSLibWinGetLastError(); 1178 if ((ulRc & 0xffff) == OSLIB_PMERR_CALL_FROM_WRONG_THREAD) 1179 { 1180 fRc = TRUE; 1181 DebugAssertFailed(("Open returned TRUE while last error was PMERR_CALL_FROM_WRONG_THREAD. bad heuristics!!!\n")); 1182 } 1183 else 1184 { 1185 DebugAssert(ulRc == 0, ("Last error is %#x and not 0x0 as we expected!!!\n", ulRc)); 1186 OSLibWinCloseClipbrd(hab); 1187 } 1188 } 1189 return fRc; 1190 #endif 1191 } 1192 1193 1194 /** 1195 * Adds an item to the PM clipboard. 1196 * 1197 * @returns success indicator. 1198 * @param uOdinFormat Odin format number. 1199 * @param pv Pointer to a buffer containing the data. 1200 * If fAllocate is clear this is a buffer allocated 1201 * using clipboardAllocPMBuffer() 1202 * @param cb Size of the data in the buffer. 1203 */ 1204 BOOL clipboardAddPM(UINT uOdinFormat, void *pv, unsigned cb) 1205 { 1206 DebugAssert(uOdinFormat == CF_TEXT || uOdinFormat == CF_BITMAP || uOdinFormat == CF_PALETTE, 1207 ("%d should have a header. fixme!!!\n", uOdinFormat)); 1208 /* 1209 * Validate and translate the format number. 1210 */ 1211 ULONG ulPMFormat = clipboardOdinToPMFormat(uOdinFormat); 1212 DebugAssert(ulPMFormat > 0, ("failed to convert odin format %d to PM!!!\n", uOdinFormat)); 1213 if (ulPMFormat == 0) 1214 return FALSE; 1215 1216 /* 1217 * Allocate PM Clipboard buffer. 1218 */ 1219 void *pvBuf = (PCLIPHEADER)clipboardAllocPMBuffer(cb); 1220 if (!pvBuf) 1221 return FALSE; 1222 pv = memcpy(pvBuf, pv, cb); 1223 1224 /* 1225 * Place it on the clipboard. 1226 */ 1227 if (OSLibWinSetClipbrdData(GetThreadHAB(),(ULONG)pvBuf, ulPMFormat, OSLIB_CFI_POINTER)) 1228 return TRUE; 1229 DebugAssertFailed(("WinSetClipbrdData failed!!! lasterr=%#x\n", OSLibWinGetLastError())); 1230 return FALSE; 1231 } 1232 1233 1234 /** 1235 * Adds an item to the PM clipboard. 1236 * 1237 * @returns success indicator. 1238 * @param uOdinFormat Odin format number. 1239 * @param pv Pointer to a buffer containing the data. 1240 * If fAllocate is clear this is a buffer allocated 1241 * using clipboardAllocPMBuffer() 1242 * @param cb Size of the data in the buffer. 1243 */ 1244 BOOL clipboardAddPMHeader(UINT uOdinFormat, void *pv, unsigned cb) 1245 { 1246 DebugAssert(uOdinFormat != CF_TEXT && uOdinFormat != CF_BITMAP && uOdinFormat != CF_PALETTE, 1247 ("%d should not have a header. fixme!!!\n", uOdinFormat)); 1248 /* 1249 * Validate and translate the format number. 1250 */ 1251 ULONG ulPMFormat = clipboardOdinToPMFormat(uOdinFormat); 1252 DebugAssert(ulPMFormat > 0, ("failed to convert odin format %d to PM!!!\n", uOdinFormat)); 1253 if (ulPMFormat == 0) 1254 return FALSE; 1255 1256 /* 1257 * Allocate PM Clipboard buffer. 1258 */ 1259 PCLIPHEADER pClip = (PCLIPHEADER)clipboardAllocPMBuffer(cb + sizeof(CLIPHEADER)); 1260 if (!pClip) 1261 return FALSE; 1262 memcpy(pClip->achMagic, CLIPHEADER_MAGIC, sizeof(CLIPHEADER_MAGIC)); 1263 pClip->cbData = cb; 1264 pClip->uFormat = uOdinFormat; 1265 pv = memcpy(pClip + 1, pv, cb); 1266 1267 /* 1268 * Place it on the clipboard. 1269 */ 1270 if (OSLibWinSetClipbrdData(GetThreadHAB(),(ULONG)pClip, ulPMFormat, OSLIB_CFI_POINTER)) 1271 return TRUE; 1272 DebugAssertFailed(("WinSetClipbrdData failed!!! lasterr=%#x\n", OSLibWinGetLastError())); 1273 return FALSE; 1274 } 1275 1276 1277 /** 1278 * Adds an item to the PM clipboard. 1279 * 1280 * @returns success indicator. 1281 * @param uOdinFormat Odin format number. 1282 * @param h Handle. 1283 */ 1284 BOOL clipboardAddPMHandle(UINT uOdinFormat, HANDLE h) 1285 { 1286 DebugAssert(uOdinFormat == CF_TEXT || uOdinFormat == CF_BITMAP || uOdinFormat == CF_PALETTE, 1287 ("%d should have a header. fixme!!!\n", uOdinFormat)); 1288 /* 1289 * Validate and translate the format number. 1290 */ 1291 ULONG ulPMFormat = clipboardOdinToPMFormat(uOdinFormat); 1292 DebugAssert(ulPMFormat > 0, ("failed to convert odin format %d to PM!!!\n", uOdinFormat)); 1293 if (ulPMFormat == 0) 1294 return FALSE; 1295 1296 /* 1297 * Place it on the clipboard. 1298 */ 1299 if (OSLibWinSetClipbrdData(GetThreadHAB(),(ULONG)h, ulPMFormat, OSLIB_CFI_HANDLE)) 1300 return TRUE; 1301 DebugAssertFailed(("WinSetClipbrdData failed!!! lasterr=%#x\n", OSLibWinGetLastError())); 1302 return FALSE; 1303 } 1304 1305 1306 /** 1307 * Allocates a buffer for use with the PM clipboard. 1308 * 1309 * @returns Pointer to buffer. 1310 * @returns NULL on failure. 1311 * @param cb Size of buffer. 1312 */ 1313 void * clipboardAllocPMBuffer(unsigned cb) 1314 { 1315 /* 1316 * Dos alloc a shared buffer. 1317 */ 1318 PVOID pv = NULL; 1319 ULONG rc = OSLibDosAllocSharedMem(&pv, NULL, (cb + 0xfff) & ~0xfff, OSLIB_PAG_READ | OSLIB_PAG_WRITE | OSLIB_PAG_COMMIT | OSLIB_OBJ_GIVEABLE); 1320 if (rc) 1321 return NULL; 1322 return pv; 1323 } 1324 1325 1326 1327 /** 1328 * Inserts a dummy placeholder in the clipboard. 1329 * 1330 * @returns Success indicator. 1331 * @param uOdinFormat Odin clipboard format number. 1332 * @remark The few other applications using the Open32 defined 1333 * format names may not like this... 1334 */ 1335 BOOL clipboardAddPMDummy(UINT uOdinFormat) 1336 { 1337 /* 1338 * Validate and translate the format number. 1339 */ 1340 ULONG ulPMFormat = clipboardOdinToPMFormat(uOdinFormat); 1341 DebugAssert(ulPMFormat > 0, ("failed to convert odin format %d to PM!!!\n", uOdinFormat)); 1342 if (ulPMFormat == 0) 1343 return FALSE; 1344 1345 /* 1346 * Insert a dummy handle. 1347 */ 1348 BOOL fRc = OSLibWinSetClipbrdData(GetThreadHAB(), DUMMY_HANDLE, ulPMFormat, OSLIB_CFI_HANDLE); 1349 DebugAssert(fRc, ("WinSetClipbrdData failed. lasterr=%#x\n", OSLibWinGetLastError())); 1350 return fRc; 1351 } 1352 1353 1354 /** 1355 * Tries to figure out the size of the data retrieved from the clipboard. 1356 * 1357 * @returns 0 on failure. 1358 * @returns size in bytes of the data. 1359 * @param pvData Data retrieved from the clipboard. 1360 */ 1361 ULONG clipboardGetPMDataSize(void *pvData) 1362 { 1363 ULONG fl = ~0; 1364 ULONG cb = ~0; 1365 ULONG ulRc = OSLibDosQueryMem(pvData, &cb, &fl); 1366 if (ulRc) 1367 { /* retry */ 1368 fl = ~0; 1369 cb = 512*1024*1024; 1370 ulRc = OSLibDosQueryMem(pvData, &cb, &fl); 1371 } 1372 if (ulRc) 1373 { 1374 DebugAssertFailed(("DosQueryMem(%#x,,) failed with rc=%d\n", pvData, ulRc)); 1375 return 0; 1376 } 1377 1378 dprintf2(("data: %#x size: %d flags: %#x\n", pvData, cb, fl)); 1379 return cb; 1380 } 1381 1382 1383 /** 1384 * Opens the clipboard. 1385 * 1386 * @returns Success indicator. 1387 * @param hwnd Handle to window which is to become owner 1388 * when EmptyClipboard is called. 1389 * If NULL the clipboard is to be associated with 1390 * the current thread. 1391 * @status completely implemented 1392 * @author knut st. osmundsen <bird-srcspam@anduin.net> 1393 * @remark This should not block, although there is a possiblity that a competing 1394 * thread may cause us to block. This is PM's fault. 1395 */ 1396 BOOL WIN32API OpenClipboard(HWND hwnd) 1397 { 1398 HWND hwndOS2 = NULL; 1399 1400 /* 1401 * Validate input and translate window handle. 1402 */ 1403 if (hwnd) 1404 { 1405 Win32BaseWindow *pWnd = Win32BaseWindow::GetWindowFromHandle(hwnd); 1406 if (!pWnd) 1407 { 1408 dprintf(("USER32: OpenClipboard: window %x not found", hwnd)); 45 1409 SetLastError(ERROR_INVALID_WINDOW_HANDLE); 46 1410 return 0; 47 1411 } 48 hwndOS2Next = wndNext->getOS2WindowHandle(); 49 RELEASE_WNDOBJ(wndNext); 50 } 51 52 dprintf(("USER32: ChangeClipboardChain\n")); 53 return O32_ChangeClipboardChain(hwndOS2Remove, hwndOS2Next); 54 } 55 //****************************************************************************** 56 //****************************************************************************** 57 int WIN32API CountClipboardFormats(void) 58 { 59 return O32_CountClipboardFormats(); 60 } 61 //****************************************************************************** 62 //****************************************************************************** 1412 hwndOS2 = pWnd->getOS2WindowHandle(); 1413 RELEASE_WNDOBJ(pWnd); 1414 } 1415 1416 /* 1417 * Open the clipboard. 1418 */ 1419 dprintf(("USER32: OpenClipboard(%#x/%#x)\n", hwnd, hwndOS2)); 1420 BOOL fRc = OSLib_OpenClipbrd(GetThreadHAB(), hwndOS2); 1421 if (fRc) 1422 { 1423 ghwndOpenClipboard = hwnd; 1424 ghwndOS2OpenClipboard = hwndOS2; 1425 gtidOpenClipboardThreadId = GetCurrentThreadId(); 1426 gfClipboardChanged = FALSE; 1427 gfClipboardChangedText= FALSE; 1428 } 1429 dprintf(("USER32: OpenClipboard: returning %d\n", fRc)); 1430 return fRc; 1431 } 1432 1433 1434 /** 1435 * Empty the clipboard. 1436 * 1437 * This will empty the clipboard freeing all global resources. 1438 * It will further free all local resources associated with the 1439 * clipboard. 1440 * 1441 * The window specified in the OpenClipboard() call will become 1442 * the owner of the clipboard upon successful return from this 1443 * call. 1444 * 1445 * @returns Success indicator. 1446 * @status completely implemented. 1447 * @author knut st. osmundsen <bird-srcspam@anduin.net> 1448 */ 63 1449 BOOL WIN32API EmptyClipboard(void) 64 1450 { 65 return O32_EmptyClipboard(); 66 } 67 //****************************************************************************** 68 //****************************************************************************** 1451 dprintf(("USER32: EmptyClipboard. ghwndOpenClipboard=%#x/%#x\n", ghwndOpenClipboard, ghwndOS2OpenClipboard)); 1452 BOOL fRc = OSLibWinEmptyClipbrd(GetThreadHAB()); 1453 if (!fRc) 1454 { 1455 ULONG ulRc = OSLibWinGetLastError(); 1456 if ((ulRc & 0xffff) == OSLIB_PMERR_CALL_FROM_WRONG_THREAD) 1457 SetLastError(ERROR_CLIPBOARD_NOT_OPEN); 1458 else 1459 SetLastError(ERROR_GEN_FAILURE); 1460 dprintf(("USER32: EmptyClipboard: WinEmptyClipbrd failed. lasterr=%#x\n", ulRc)); 1461 return FALSE; 1462 } 1463 1464 /* 1465 * Take clipboard ownership. 1466 */ 1467 if (!OSLibWinSetClipbrdOwner(GetThreadHAB(), ghwndOS2OpenClipboard)) 1468 { 1469 DebugAssertFailed(("WinSetClipbrdOwner failed!! lasterr=%#x\n", OSLibWinGetLastError())); 1470 #if 0 /* Not sure what kind of action which makes most sense. */ 1471 SetLastError(ERROR_INVALID_WINDOW_HANDLE); 1472 return FALSE; 1473 #else 1474 OSLibWinSetClipbrdOwner(GetThreadHAB(), NULL); 1475 #endif 1476 } 1477 1478 /* 1479 * Free per process resources. 1480 */ 1481 for (PCLIPLOCALDATA p = gpLocalData, pNext = NULL; p; p = pNext) 1482 { 1483 pNext = p->pNext; 1484 clipboardCacheDeleteNode(p); 1485 } 1486 gpLocalData = NULL; 1487 gfClipboardChanged = TRUE; 1488 gfClipboardChangedText = FALSE; 1489 1490 dprintf(("USER32: EmptyClipboard: returns successfully\n")); 1491 return TRUE; 1492 } 1493 1494 1495 /** 1496 * Puts data onto the clipboard. 1497 * 1498 * @returns hCliObj on success. 1499 * @returns NULL on failure, last error may be set. 1500 * @param uFormat The format of hClipObj. 1501 * @param hClipObj Handle to data to put on the clipboard. 1502 * @status partially implemented. 1503 * @author knut st. osmundsen <bird-srcspam@anduin.net> 1504 * @todo Checkup last errors! 1505 */ 1506 HANDLE WIN32API SetClipboardData(UINT uFormat, HANDLE hClipObj) 1507 { 1508 dprintf(("SetClipboardData uFormat=%#x (%s) hClipObj=%#x", uFormat, dbgGetFormatName(uFormat), hClipObj)); 1509 dbgDumpClipboardData("SetClipboardData", uFormat, hClipObj); 1510 1511 /* 1512 * Validate that the thread have opened the clipboard. 1513 */ 1514 if (/* !clipboardIsRWOwner() - must allow rendering. PM catches it. ||*/ !uFormat) 1515 { 1516 SetLastError(ERROR_CLIPBOARD_NOT_OPEN); 1517 dprintf(("USER32: SetClipboardData: returns NULL (no openclipboard)\n")); 1518 return NULL; 1519 } 1520 1521 /* 1522 * Validate format. 1523 */ 1524 ULONG ulPMFormat = clipboardOdinToPMFormat(uFormat); 1525 DebugAssert(!uFormat || ulPMFormat > 0, ("failed to convert odin format %d to PM!!!\n", uFormat)); 1526 if (!ulPMFormat) 1527 { 1528 //last error? 1529 dprintf(("USER32: SetClipboardData: return NULL (invalid format %d)\n", uFormat)); 1530 return NULL; 1531 } 1532 1533 /* 1534 * For some formats we just put out OS/2 handles, for the 1535 * others we duplicate the memory buffer passed in to us. 1536 */ 1537 PCLIPLOCALDATA pLocalClip = NULL; /* Cache node for per process data. */ 1538 ULONG flPMData = 0; 1539 ULONG ulPMData = 0; 1540 BOOL fHeader = TRUE; /* Whether or not to prepend an odin clip data header. */ 1541 switch (uFormat) 1542 { 1543 /* 1544 * Make a duplication of the PM handle for the PM clipboard and 1545 * put the Odin32 handle in the cache. 1546 */ 1547 case CF_BITMAP: 1548 case CF_DSPBITMAP: 1549 case CF_PALETTE: 1550 flPMData = OSLIB_CFI_HANDLE; 1551 if (hClipObj) 1552 { 1553 ulPMData = O32_GetPMHandleFromGDIHandle(hClipObj); 1554 if (!ulPMData) 1555 { 1556 dprintf(("USER32: SetClipboardData: return NULL. Failed to get PM handle from Odin32 %s handle %#x\n", 1557 dbgGetFormatName(uFormat), hClipObj)); 1558 return NULL; 1559 } 1560 1561 /* 1562 * Duplicate the PM handle. 1563 */ 1564 switch (uFormat) 1565 { 1566 case CF_BITMAP: 1567 case CF_DSPBITMAP: 1568 ulPMData = (ULONG)OSLibClipboardPMBitmapDuplicate((HBITMAP)ulPMData); 1569 break; 1570 case CF_PALETTE: 1571 ulPMData = (ULONG)OSLibClipboardPMPaletteDuplicate((HPALETTE)ulPMData); 1572 break; 1573 } 1574 if (!ulPMData) 1575 { 1576 dprintf(("USER32: SetClipboardData: return NULL. Failed to duplicate PM handle!\n")); 1577 return NULL; 1578 } 1579 1580 /* 1581 * Allocate cache node. 1582 */ 1583 if (!clipboardCacheAllocGDI(uFormat, hClipObj, &pLocalClip)) 1584 DebugAssertFailed(("out of memory")); 1585 } 1586 break; 1587 1588 /* 1589 * Put the metafile bits onto the clipboard. 1590 * Put hClipObj in cache for delayed freeing. 1591 */ 1592 case CF_METAFILEPICT: 1593 case CF_DSPMETAFILEPICT: 1594 { 1595 #if 0 //todo implement get code. 1596 flPMData = OSLIB_CFI_POINTER; 1597 if (hClipObj) 1598 { 1599 /* get the data */ 1600 LPMETAFILEPICT pMeta = (LPMETAFILEPICT)GlobalLock(hClipObj); 1601 if (!pMeta) 1602 { 1603 SetLastError(ERROR_INVALID_PARAMETER); 1604 dprintf(("USER32: SetClipboardData: returns NULL (metafilepict lock)\n")); 1605 return NULL; 1606 } 1607 /* get size */ 1608 DWORD cb = GetMetaFileBitsEx(pMeta->hMF, 0, NULL); 1609 dprintf2(("GetMetaFileBitsEx -> %d\n", cb)); 1610 if (!cb) 1611 { /* ?? */ 1612 SetLastError(ERROR_INVALID_PARAMETER); 1613 dprintf(("USER32: SetClipboardData: returns NULL (metafilepict handle)\n")); 1614 return NULL; 1615 } 1616 /* allocate shared */ 1617 DWORD cbTotal = sizeof(CLIPHEADER) + sizeof(METAFILEPICT) + cb; 1618 PCLIPHEADER pClip = (PCLIPHEADER)clipboardAllocPMBuffer(cbTotal); 1619 if (!pClip) 1620 { 1621 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 1622 dprintf(("USER32: SetClipboardData: returns NULL (metafilepict mem)\n")); 1623 return NULL; 1624 } 1625 /* make block */ 1626 memcpy(pClip->achMagic, CLIPHEADER_MAGIC, sizeof(CLIPHEADER_MAGIC)); 1627 pClip->cbData = cbTotal; /* bits + metafilepict */ 1628 pClip->uFormat = uFormat; 1629 *(LPMETAFILEPICT)(pClip + 1) = *pMeta; 1630 /* (ASSUMES it's not be touched since last call to this api.) */ 1631 GetMetaFileBitsEx(pMeta->hMF, cb, (char*)(pClip + 1) + sizeof(*pMeta)); 1632 } 1633 break; 1634 #else 1635 DebugAssertFailed(("metafile support not enabled")); 1636 return NULL; 1637 #endif 1638 } 1639 1640 /* 1641 * Put the enh. metafile bits onto the clipboard. 1642 * Put hClipObj in cache for delayed freeing. 1643 */ 1644 case CF_ENHMETAFILE: 1645 case CF_DSPENHMETAFILE: 1646 { 1647 #if 0 //todo implement get code. 1648 flPMData = OSLIB_CFI_POINTER; 1649 if (hClipObj) 1650 { 1651 /* get size */ 1652 DWORD cb = GetEnhMetaFileBits(hClipObj, 0, NULL); 1653 dprintf2(("GetEnhMetaFileBits -> %d\n", cb)); 1654 if (!cb) 1655 { /* ?? */ 1656 SetLastError(ERROR_INVALID_PARAMETER); 1657 dprintf(("USER32: SetClipboardData: returns NULL (enhmetafile handle)\n")); 1658 return NULL; 1659 } 1660 /* allocate shared */ 1661 DWORD cbTotal = sizeof(CLIPHEADER) + cb; 1662 PCLIPHEADER pClip = (PCLIPHEADER)clipboardAllocPMBuffer(cbTotal); 1663 if (!pClip) 1664 { 1665 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 1666 dprintf(("USER32: SetClipboardData: returns NULL (enhmetafile mem)\n")); 1667 return NULL; 1668 } 1669 /* make block */ 1670 pClip->cbData = cbTotal; /* bits */ 1671 pClip->uFormat = uFormat; 1672 /* (ASSUMES it's not be touched since last call to this api.) */ 1673 GetEnhMetaFileBits(hClipObj, cb, (LPBYTE)(pClip + 1)); 1674 } 1675 break; 1676 #else 1677 DebugAssertFailed(("metafile support not enabled")); 1678 return NULL; 1679 #endif 1680 } 1681 1682 /* 1683 * The Owner display, the data must be NULL. 1684 */ 1685 case CF_OWNERDISPLAY: 1686 { 1687 flPMData = OSLIB_CFI_OWNERDISPLAY | OSLIB_CFI_HANDLE; 1688 if (hClipObj) 1689 { 1690 SetLastError(ERROR_INVALID_PARAMETER); /** @todo check this last error */ 1691 dprintf(("USER32: SetClipboardData: returns NULL (owner display data)\n")); 1692 return NULL; 1693 } 1694 break; 1695 } 1696 1697 /* 1698 * Allocate shared data. 1699 */ 1700 case CF_TEXT: 1701 case CF_DSPTEXT: 1702 /* these are shared with OS/2 and shall have no header */ 1703 fHeader = FALSE; 1704 /* fallthru */ 1705 case CF_UNICODETEXT: 1706 case CF_OEMTEXT: 1707 case CF_LOCALE: 1708 case CF_DIB: 1709 case CF_DIBV5: 1710 case CF_HDROP: 1711 case CF_SYLK: 1712 case CF_DIF: 1713 case CF_TIFF: 1714 case CF_PENDATA: 1715 case CF_RIFF: 1716 case CF_WAVE: 1717 flPMData = OSLIB_CFI_POINTER; 1718 /* fall thru */ 1719 default: 1720 if (uFormat >= CF_GDIOBJFIRST && uFormat <= CF_GDIOBJFIRST) 1721 { 1722 DebugAssertFailed(("CF_GDIOBJ* is not implemented!!!\n")); 1723 SetLastError(ERROR_GEN_FAILURE); 1724 dprintf(("USER32: SetClipboardData: returns NULL (gdiobj)\n")); 1725 return NULL; 1726 } 1727 1728 /* 1729 * We assume the rest is global handles, if not we'll check treat 1730 * them as handles we don't care to much about. 1731 */ 1732 if (hClipObj) 1733 { 1734 PVOID pv = GlobalLock(hClipObj); 1735 if (pv) 1736 { 1737 /* 1738 * Global memory object. 1739 * Duplicate it and put hClipObj in the cache for delayed deletion. 1740 */ 1741 DWORD cb = GlobalSize(hClipObj); 1742 ulPMData = (ULONG)clipboardAllocPMBuffer(cb + (fHeader ? sizeof(CLIPHEADER) : 0)); 1743 if (!ulPMData) 1744 { 1745 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 1746 GlobalUnlock(hClipObj); 1747 dprintf(("USER32: SetClipboardData: returns NULL (shared alloc failed)\n")); 1748 return NULL; 1749 } 1750 if (fHeader) 1751 { 1752 PCLIPHEADER pClip = (PCLIPHEADER)(void*)ulPMData; 1753 memcpy(pClip->achMagic, CLIPHEADER_MAGIC, sizeof(CLIPHEADER_MAGIC)); 1754 pClip->cbData = cb; 1755 pClip->uFormat = uFormat; 1756 memcpy((void*)(ulPMData + sizeof(CLIPHEADER)), pv, cb); 1757 } 1758 else 1759 memcpy((void*)ulPMData, pv, cb); 1760 GlobalUnlock(hClipObj); 1761 flPMData = OSLIB_CFI_POINTER; 1762 1763 /* Allocate a cache node. */ 1764 if (!clipboardCacheAllocGlobalMem(uFormat, hClipObj, &pLocalClip)) 1765 DebugAssertFailed(("out of memory")); 1766 } 1767 else 1768 { /* 1769 * Handle of some other kind? 1770 * Check if it's supposed to be a pointer. 1771 */ 1772 if (flPMData) 1773 { /* it's a predefined format which is supposed to be a global memory handle. */ 1774 SetLastError(ERROR_INVALID_PARAMETER); /** @todo check this last error */ 1775 DebugAssertFailed(("expected GlobalAlloc handle, got %#x!! format=%d (%s)\n", 1776 hClipObj, uFormat, dbgGetFormatName(uFormat))); /* (for application debugging.) */ 1777 dprintf(("USER32: SetClipboardData: returns NULL (bad global handle)\n")); 1778 return NULL; 1779 } 1780 1781 /* some kind of handle, this might not work to well... */ 1782 flPMData = OSLIB_CFI_HANDLE; 1783 dprintf(("USER32: SetClipboardData: Warning: format %d data %#x is not a Global memory handle!!!\n", 1784 uFormat, hClipObj)); 1785 } 1786 } 1787 else 1788 { 1789 /* 1790 * To be rendered. 1791 */ 1792 if (!flPMData) 1793 flPMData = OSLIB_CFI_POINTER; /* must be set to something, and pointer is a safe bet. */ 1794 } 1795 break; 1796 } 1797 1798 /* 1799 * Put it onto the PM clipboard. 1800 */ 1801 dprintf2(("calling OSLibWinSetClipbrdData(%#x, %#x, %d, %#x)\n", GetThreadHAB(), ulPMData, ulPMFormat, flPMData)); 1802 if (!OSLibWinSetClipbrdData(GetThreadHAB(), ulPMData, ulPMFormat, flPMData)) 1803 { 1804 /* 1805 * Failed! 1806 */ 1807 if ((OSLibWinGetLastError() & 0xffff) == OSLIB_PMERR_CALL_FROM_WRONG_THREAD) 1808 SetLastError(ERROR_CLIPBOARD_NOT_OPEN); 1809 else 1810 DebugAssertFailed(("OSLibWinSetClipbrdData(%#x, %#x, %d, %#x) failed last error=%d\n", 1811 GetThreadHAB(), ulPMData, ulPMFormat, flPMData, OSLibWinGetLastError())); 1812 1813 /* cleanup */ 1814 if ((flPMData & OSLIB_CFI_POINTER) && ulPMData) 1815 OSLibDosFreeMem((void*)ulPMData); 1816 else 1817 switch (uFormat) 1818 { 1819 case CF_BITMAP: 1820 case CF_DSPBITMAP: 1821 OSLibClipboardPMBitmapDelete(ulPMData); 1822 break; 1823 case CF_PALETTE: 1824 OSLibClipboardPMPaletteDelete(ulPMData); 1825 break; 1826 } 1827 1828 if (pLocalClip) 1829 free(pLocalClip); /* Do not free the data suplied! */ 1830 1831 dprintf(("USER32: SetClipboardData: returns NULL (set clipboard failed)\n")); 1832 return NULL; 1833 } 1834 1835 /* 1836 * Success! 1837 */ 1838 /* update globals */ 1839 gfClipboardChanged = TRUE; 1840 switch (uFormat) 1841 { 1842 case CF_TEXT: 1843 case CF_OEMTEXT: 1844 case CF_UNICODETEXT: 1845 gfClipboardChangedText = TRUE; 1846 break; 1847 } 1848 1849 /* insert node into cache if required. */ 1850 if (pLocalClip) 1851 hClipObj = clipboardCacheInsertNode(pLocalClip); 1852 1853 dprintf(("USER32: SetClipboardData: returns %#x\n", hClipObj)); 1854 return hClipObj; 1855 } 1856 1857 1858 /** 1859 * Gets a specific form of the clipboard if it's there. 1860 * 1861 * @returns handle to clipboard data on success. 1862 * @returns NULL on failure. Last error may be set, depends on the failure. 1863 * @param uFormat The clipboard format to get off the clipboard. 1864 * @status partially implemented. 1865 * @author knut st. osmundsen <bird-srcspam@anduin.net> 1866 * @remark we don't like metafiles at the present. 1867 * @remark we never return the same hMem for the same data, this is mentioned as a @todo in the code. 1868 */ 1869 HANDLE WIN32API GetClipboardData(UINT uFormat) 1870 { 1871 dprintf(("USER32: GetClipboardData: uFormat=%u (%s)\n", uFormat, dbgGetFormatName(uFormat))); 1872 1873 /* 1874 * Validate that the thread have opened the clipboard. 1875 */ 1876 if (!clipboardIsRWOwner()) 1877 { 1878 SetLastError(ERROR_CLIPBOARD_NOT_OPEN); 1879 dprintf(("USER32: GetClipboardData: returns NULL (no openclipboard)\n")); 1880 return NULL; 1881 } 1882 1883 /* 1884 * Validate and translate the format number. 1885 */ 1886 ULONG ulPMFormat = clipboardOdinToPMFormat(uFormat); 1887 DebugAssert(!uFormat || ulPMFormat > 0, ("failed to convert odin format %d to PM!!!\n", uFormat)); 1888 if (ulPMFormat == 0) 1889 { 1890 //no last error? 1891 dprintf(("USER32: GetClipboardData: returns NULL (invalid format!!!)\n")); 1892 return NULL; 1893 } 1894 1895 /* 1896 * We need to synthesize formats in case OS/2 were the one 1897 * which put stuff on the clipboard. 1898 */ 1899 if (!gfClipboardChanged) 1900 clipboardSynthesize(gfClipboardChangedText); 1901 1902 /* 1903 * Get the data. 1904 */ 1905 HANDLE hab = GetThreadHAB(); 1906 ULONG ulPMInfo; 1907 if (!OSLibWinQueryClipbrdFmtInfo(hab, ulPMFormat, &ulPMInfo)) 1908 { 1909 //no last error? 1910 dprintf(("USER32: GetClipboardData: returns NULL (format not present)\n")); 1911 return NULL; 1912 } 1913 ULONG ulPMData = OSLibWinQueryClipbrdData(hab, ulPMFormat); 1914 if (!ulPMData) 1915 { 1916 //no last error? 1917 dprintf(("USER32: GetClipboardData: returns NULL (format not present)\n")); 1918 return NULL; 1919 } 1920 1921 /* 1922 * Allocate local copies of the data like Odin expects. 1923 * 1924 * In this process we'll synthesize formats and convert 1925 * from OS/2 PM formats to Odin formats. 1926 */ 1927 /* dummy handle? */ 1928 if ( (ulPMInfo & (OSLIB_CFI_HANDLE | OSLIB_CFI_POINTER | OSLIB_CFI_OWNERDISPLAY | OSLIB_CFI_OWNERFREE)) 1929 == OSLIB_CFI_HANDLE 1930 && ulPMData == DUMMY_HANDLE) 1931 { /* synthesized */ 1932 /** @todo check if we've done this operation on this data before. */ 1933 HANDLE hRet; 1934 switch (uFormat) 1935 { 1936 case CF_TEXT: 1937 case CF_UNICODETEXT: 1938 case CF_OEMTEXT: 1939 hRet = clipboardSynthesizeText(uFormat); 1940 break; 1941 1942 case CF_LOCALE: 1943 hRet = clipboardSynthesizeLocale(uFormat); 1944 break; 1945 1946 case CF_BITMAP: 1947 hRet = clipboardSynthesizeBitmap(uFormat); 1948 break; 1949 1950 case CF_DIB: 1951 case CF_DIBV5: 1952 hRet = clipboardSynthesizeDIB(uFormat); 1953 break; 1954 1955 #if 0 // not implemented yet. 1956 case CF_PALETTE: 1957 hRet = clipboardSynthesizePalette(uFormat); 1958 break; 1959 1960 case CF_METAFILEPICT: 1961 hRet = clipboardSynthesizeMetaFile(uFormat); 1962 break; 1963 case CF_ENHMETAFILE: 1964 hRet = clipboardSynthesizeEnhMetaFile(uFormat); 1965 break; 1966 #endif 1967 1968 default: 1969 DebugAssertFailed(("Format %d doesn't do dummy handles!\n", uFormat)); 1970 dprintf(("USER32: GetClipboardData: returns NULL (internal error!!!)\n")); 1971 return NULL; 1972 } 1973 dprintf(("USER32: GetClipboardData: returns %#x (synthesized)\n", hRet)); 1974 return hRet; 1975 } 1976 else if (ulPMInfo & OSLIB_CFI_POINTER) 1977 { /* pointers: text */ 1978 /* Sanity check. */ 1979 switch (uFormat) 1980 { 1981 case CF_BITMAP: 1982 case CF_DSPBITMAP: 1983 case CF_PALETTE: 1984 dprintf(("USER32: GetClipboardData: return NULL (format/data mismatch)\n")); 1985 return NULL; 1986 1987 case CF_ENHMETAFILE: 1988 case CF_DSPENHMETAFILE: 1989 case CF_METAFILEPICT: 1990 case CF_DSPMETAFILEPICT: 1991 DebugAssertFailed(("Metafile support isn't enabled\n")); 1992 return NULL; 1993 } 1994 1995 /** @todo check if we've done this operation on this data before. */ 1996 1997 /* 1998 * Duplicate the data raw in a GlobalAlloc'ed block local to the calling process. 1999 */ 2000 /* Figure out the size of the data */ 2001 ULONG cbOdin; 2002 void *pvOdin; 2003 if (uFormat != CF_TEXT && uFormat != CF_BITMAP && uFormat != CF_PALETTE 2004 && !memcmp(((PCLIPHEADER)ulPMData)->achMagic, CLIPHEADER_MAGIC, sizeof(CLIPHEADER_MAGIC))) 2005 { /* Have Odin header */ 2006 PCLIPHEADER pClip = (PCLIPHEADER)ulPMData; 2007 DebugAssert(pClip->uFormat == uFormat, ("Format mismatch %d != %d\n", pClip->uFormat, uFormat)); 2008 cbOdin = pClip->cbData; 2009 pvOdin = (void*)(pClip + 1); 2010 } 2011 else 2012 { 2013 DebugAssert(uFormat == CF_TEXT || uFormat == CF_BITMAP || uFormat == CF_PALETTE, 2014 ("%d should have a header!!!\n", uFormat)); 2015 pvOdin = (void*)ulPMData; 2016 ULONG cb = clipboardGetPMDataSize(pvOdin); 2017 if (!cb) 2018 { 2019 dprintf(("USER32: GetClipboardData: return NULL (cannot determin size of data)\n")); 2020 return NULL; 2021 } 2022 2023 /* find the size of the odin data. */ 2024 cbOdin = cb; 2025 switch (uFormat) 2026 { 2027 case CF_TEXT: 2028 cbOdin = clipboardTextCalcSize(pvOdin, cb); 2029 break; 2030 } 2031 } 2032 2033 /* allocate object. */ 2034 PCLIPLOCALDATA pLocalClip; 2035 HANDLE hMem = clipboardCacheAllocGlobalDup(uFormat, pvOdin, cbOdin, &pLocalClip); 2036 if (!hMem) 2037 { 2038 dprintf(("USER32: GetClipboardData: returns NULL (GlobalAlloc(,%d) failed)\n", cbOdin)); 2039 return NULL; 2040 } 2041 2042 /* insert cache object. */ 2043 hMem = clipboardCacheInsertNode(pLocalClip); 2044 2045 dprintf(("USER32: GetClipboardData: return %#x (%d bytes)\n", hMem, cbOdin)); 2046 return hMem; 2047 } 2048 else if (ulPMInfo & OSLIB_CFI_HANDLE) 2049 { /* handles: palette or bitmap */ 2050 HANDLE hGDI; 2051 switch (uFormat) 2052 { 2053 case CF_BITMAP: 2054 case CF_DSPBITMAP: 2055 hGDI = O32_CreateBitmapFromPMHandle((HBITMAP)ulPMData); 2056 break; 2057 2058 case CF_PALETTE: 2059 hGDI = O32_CreateBitmapFromPMHandle((HPALETTE)ulPMData); 2060 break; 2061 2062 /** @todo make cases for the other which are defined as handles. */ 2063 /* (for now we assume that everything else is Odin handles.) */ 2064 default: 2065 dprintf(("USER32: GetClipboardData: returns NULL (funny stuff on clipboard)\n")); 2066 return (HANDLE)ulPMData; 2067 } 2068 2069 /* allocate and insert cache node. */ 2070 PCLIPLOCALDATA pLocalClip; 2071 if (clipboardCacheAllocGDI(uFormat, hGDI, &pLocalClip)) 2072 hGDI = clipboardCacheInsertNode(pLocalClip); 2073 2074 dprintf(("USER32: GetClipboardData: returns %#x (translated OS/2 handle)\n", hGDI)); 2075 return hGDI; 2076 } 2077 else 2078 { 2079 DebugAssertFailed(("Something is on the clipboard without any understandable attributes!! ulInfo=%#x ulPMData=%#x\n", 2080 ulPMInfo, ulPMData)); 2081 dprintf(("USER32: GetClipboardData: returns NULL (funny stuff on clipboard)\n")); 2082 return NULL; 2083 } 2084 } 2085 2086 2087 /** 2088 * Enumerate clipboard formats. 2089 * 2090 * Must be RW owner of clipboard (i.e. OpenClipboard()). 2091 * 2092 * @returns next clipboard format. 2093 * @returns 0 if no more formats in the clipboard. 2094 * @param uFormat Current format. Use 0 for the starting 2095 * the enumeration. 2096 * @status completely implemented. 2097 * @author knut st. osmundsen <bird-srcspam@anduin.net> 2098 */ 69 2099 UINT WIN32API EnumClipboardFormats(UINT uFormat) 70 2100 { 71 return O32_EnumClipboardFormats(uFormat); 72 } 73 //****************************************************************************** 74 //****************************************************************************** 75 int WIN32API GetClipboardFormatNameA(UINT format,LPSTR lpszFormatName,int cchMaxCount) 76 { 77 dprintf(("USER32: GetClipboardFormatNameA %d\n",format)); 78 return O32_GetClipboardFormatName(format,lpszFormatName,cchMaxCount); 79 } 80 //****************************************************************************** 81 //****************************************************************************** 82 int WIN32API GetClipboardFormatNameW(UINT format,LPWSTR lpszFormatName,int cchMaxCount) 83 { 84 int rc; 85 char *astring = (CHAR*)malloc(cchMaxCount); 86 87 rc = GetClipboardFormatNameA(format,astring,cchMaxCount); 88 if (rc) AsciiToUnicode(astring,lpszFormatName); 89 free(astring); 90 return(rc); 91 } 92 //****************************************************************************** 93 //****************************************************************************** 94 HWND WIN32API GetClipboardOwner(void) 95 { 96 HWND hwndOwner; 97 Win32BaseWindow *window; 98 99 dprintf(("USER32: GetClipboardOwner\n")); 100 hwndOwner = O32_GetClipboardOwner(); 101 102 window = Win32BaseWindow::GetWindowFromOS2Handle(hwndOwner); 103 if(!window) { 104 //an OS/2 window probably owns the clipboard, we pretend nobody owns it 2101 dprintf(("USER32: EnumClipboardFormats: uFormat=%d (%s)\n", uFormat, 2102 uFormat ? dbgGetFormatName(uFormat) : "start enum")); 2103 2104 /* 2105 * Validate that the thread have opened the clipboard. 2106 */ 2107 if (!clipboardIsRWOwner()) 2108 { 2109 SetLastError(ERROR_CLIPBOARD_NOT_OPEN); 2110 dprintf(("USER32: EnumClipboardFormats: returns 0 (no openclipboard)\n")); 2111 return 0; 2112 } 2113 2114 UINT rc = clipboardEnumClipboardFormats(uFormat); 2115 dprintf(("USER32: EnumClipboardFormats: returns %d\n")); 2116 return rc; 2117 } 2118 2119 2120 /** 2121 * Internal worker for EnumClipboardFormats. 2122 * Also used by CountClipboardFormats(); 2123 * 2124 * @returns next clipboard format. 2125 * @returns 0 if no more formats in the clipboard. 2126 * @param uFormat Current format. Use 0 for the starting 2127 * the enumeration. 2128 * @status completely implemented. 2129 * @author knut st. osmundsen <bird-srcspam@anduin.net> 2130 */ 2131 UINT clipboardEnumClipboardFormats(UINT uFormat) 2132 { 2133 dprintf(("USER32: clipboardEnumClipboardFormats: uFormat=%d (%s)\n", uFormat, 2134 uFormat ? dbgGetFormatName(uFormat) : "start enum")); 2135 2136 /* 2137 * Validate/translate input. 2138 */ 2139 ULONG ulPMFormat = 0; 2140 if (uFormat) 2141 { 2142 ulPMFormat = clipboardOdinToPMFormat(uFormat); 2143 if (!ulPMFormat) 2144 { 2145 dprintf(("USER32: clipboardEnumClipboardFormats: invalid uFormat(=%u)!!\n", uFormat)); 2146 return 0; 2147 } 2148 } 2149 2150 /* 2151 * Enumerate next OS/2 format. 2152 */ 2153 HANDLE hab = GetThreadHAB(); 2154 while ((ulPMFormat = OSLibWinEnumClipbrdFmts(GetThreadHAB(), ulPMFormat)) != 0) 2155 { 2156 UINT uNextFormat = clipboardPMToOdinFormat(ulPMFormat); 2157 if (uNextFormat) 2158 { 2159 dprintf(("USER32: clipboardEnumClipboardFormats: returning %u (%s)\n", uNextFormat, dbgGetFormatName(uNextFormat))); 2160 return uNextFormat; 2161 } 2162 dprintf2(("USER32: clipboardEnumClipboardFormats: skipping OS/2 only format %lu\n", ulPMFormat)); 2163 } 2164 2165 /* 2166 * Since we cannot know what non Odin applications are doing, 2167 * we will have to check for synthesized formats here. 2168 * 2169 * We're not doing this if we're the clipboard owner and have changed 2170 * the clipboard in any way. This is to not synthesize stuff to early 2171 * compared to W2K. See GetClipboardFormat. 2172 */ 2173 if (uFormat && (!clipboardIsRWOwner() || !gfClipboardChanged)) 2174 { 2175 static UINT auSeq[] = { CF_TEXT, CF_UNICODETEXT, CF_OEMTEXT, CF_DIB, CF_DIBV5, CF_BITMAP, 0 }; /** @todo complete and check this. */ 2176 ULONG flInfo; 2177 2178 /* find starting index */ 2179 int i = 0; 2180 if (!clipboardIsAvailable(uFormat)) 2181 { 2182 for (i = 0; auSeq[i]; i++) 2183 if (auSeq[i] == uFormat) 2184 { 2185 i++; 2186 break; 2187 } 2188 } 2189 2190 /* 2191 * Find the next synthesized format. 2192 */ 2193 while ((uFormat = auSeq[i]) != 0) 2194 { 2195 if (clipboardShouldBeSynthesized(uFormat)) 2196 { /* not there, potentially synthesized format. */ 2197 dprintf(("USER32: clipboardEnumClipboardFormats: returning %u (%s)\n", uFormat, dbgGetFormatName(uFormat))); 2198 return uFormat; 2199 } 2200 /* next */ 2201 i++; 2202 } 2203 2204 } 2205 2206 dprintf(("USER32: clipboardEnumClipboardFormats: returning 0\n")); 2207 return 0; 2208 } 2209 2210 2211 2212 /** 2213 * Closes the clipboard. 2214 * 2215 * @returns Success indicator. 2216 * @status completely implemented. 2217 * @author knut st. osmundsen <bird-srcspam@anduin.net> 2218 */ 2219 BOOL WIN32API CloseClipboard(void) 2220 { 2221 dprintf(("USER32: CloseClipboard")); 2222 2223 /* 2224 * Check that we're owning the clipboard. 2225 */ 2226 if (!clipboardIsRWOwner()) 2227 { 2228 SetLastError(ERROR_CLIPBOARD_NOT_OPEN); 2229 dprintf(("USER32: CloseClipboard returns FALSE (clipboard not open!!)\n")); 2230 return FALSE; 2231 } 2232 2233 HAB hab = GetThreadHAB(); 2234 2235 /* 2236 * Synthesize formats. 2237 */ 2238 if (gfClipboardChanged) 2239 clipboardSynthesize(gfClipboardChangedText); 2240 2241 /* 2242 * Actually close it. 2243 */ 2244 if (gtidOpenClipboardThreadId == GetCurrentThreadId()) /* paranoia */ 2245 gtidOpenClipboardThreadId = 0; 2246 BOOL fRc = OSLibWinCloseClipbrd(hab); 2247 DebugAssert(fRc, ("WinCloseClipbrd failed!!! lasterr=%#x\n", OSLibWinGetLastError())); 2248 dprintf(("USER32: CloseClipboard: returning %s\n", fRc ? "TRUE" : "FALSE")); 2249 return fRc; 2250 } 2251 2252 2253 /** 2254 * Makes dummies for synthesized formats. 2255 * 2256 * This is called by CloseClipboard() and GetClipboardData(). The latter 2257 * because Odin32 might not have been the one to put data on the clipboard. 2258 */ 2259 void clipboardSynthesize(BOOL fHaveAddedText) 2260 { 2261 dprintf2(("USER32: clipboardSynthesize: fHaveAddedText=%d\n", fHaveAddedText)); 2262 /* text */ 2263 BOOL fCF_OEMTEXT = clipboardIsAvailable(CF_OEMTEXT); 2264 BOOL fCF_UNICODETEXT = clipboardIsAvailable(CF_UNICODETEXT); 2265 BOOL fCF_TEXT = clipboardIsAvailable(CF_TEXT); 2266 if (fCF_TEXT || fCF_UNICODETEXT || fCF_OEMTEXT) 2267 { 2268 /* 2269 * Add the CF_LOCALE if we have modified the clipboard. 2270 */ 2271 if (!clipboardIsAvailable(CF_LOCALE)) 2272 { 2273 if (!fHaveAddedText) 2274 clipboardAddPMDummy(CF_LOCALE); 2275 else 2276 { 2277 LCID lcid = GetThreadLocale(); 2278 clipboardAddPMHeader(CF_LOCALE, &lcid, sizeof(lcid)); 2279 } 2280 } 2281 2282 /* 2283 * Add dummies. 2284 */ 2285 if (!fCF_TEXT) 2286 { 2287 /* CT_TEXT must be synthesized so PM can see the text. */ 2288 HANDLE hMem = clipboardSynthesizeText(CF_TEXT); 2289 if (hMem) 2290 { 2291 void *pv = GlobalLock(hMem); 2292 clipboardAddPM(CF_TEXT, pv, GlobalSize(hMem)); 2293 GlobalUnlock(hMem); 2294 } 2295 } 2296 if (!fCF_UNICODETEXT) 2297 clipboardAddPMDummy(CF_UNICODETEXT); 2298 if (!fCF_OEMTEXT) 2299 clipboardAddPMDummy(CF_OEMTEXT); 2300 } 2301 else 2302 { 2303 /* DIBs */ 2304 BOOL fCF_DIBV5 = clipboardIsAvailable(CF_DIBV5); 2305 BOOL fCF_DIB = clipboardIsAvailable(CF_DIB); 2306 BOOL fCF_BITMAP = clipboardIsAvailable(CF_BITMAP); 2307 if (fCF_BITMAP || fCF_DIB || fCF_DIBV5) 2308 { 2309 /* 2310 * Add dummies. 2311 */ 2312 if (!fCF_BITMAP) 2313 { /* CT_BITMAP must be synthesized so PM can understand it. */ 2314 HANDLE hbm = clipboardSynthesizeBitmap(CF_BITMAP); 2315 if (hbm) 2316 { 2317 if (!SetClipboardData(CF_BITMAP, hbm)) 2318 DebugAssertFailed(("SetClipboardData for synthesized bitmap %#x failed!\n", hbm)); 2319 } 2320 } 2321 if (!fCF_DIB) 2322 clipboardAddPMDummy(CF_DIB); 2323 if (!fCF_DIBV5) 2324 clipboardAddPMDummy(CF_DIBV5); 2325 } 2326 else 2327 { 2328 /** @todo metafiles and palettes */ 2329 } 2330 } 2331 2332 } 2333 2334 2335 2336 /** 2337 * Checks whether or not a given format will be synthesized by GetClipboardData 2338 * in the current clipboard state. 2339 * 2340 * @returns TRUE if it will be synthesized, FALSE if not. 2341 * @param uFormat Odin format number 2342 */ 2343 BOOL clipboardShouldBeSynthesized(UINT uFormat) 2344 { 2345 /* Should be, that means to be done in GetClipboardData. */ 2346 if (clipboardIsAvailable(uFormat)) 2347 return FALSE; 2348 2349 switch (uFormat) 2350 { 2351 case CF_TEXT: 2352 return clipboardIsAvailable(CF_OEMTEXT) 2353 || clipboardIsAvailable(CF_UNICODETEXT); 2354 case CF_OEMTEXT: 2355 return clipboardIsAvailable(CF_TEXT) 2356 || clipboardIsAvailable(CF_UNICODETEXT); 2357 case CF_UNICODETEXT: 2358 return clipboardIsAvailable(CF_TEXT) 2359 || clipboardIsAvailable(CF_OEMTEXT); 2360 2361 case CF_LOCALE: 2362 return clipboardIsAvailable(CF_TEXT) 2363 || clipboardIsAvailable(CF_OEMTEXT) 2364 || clipboardIsAvailable(CF_UNICODETEXT); 2365 2366 case CF_BITMAP: 2367 return clipboardIsAvailable(CF_DIB) 2368 || clipboardIsAvailable(CF_DIBV5); 2369 case CF_DIB: 2370 return clipboardIsAvailable(CF_BITMAP) 2371 || clipboardIsAvailable(CF_DIBV5); 2372 case CF_DIBV5: 2373 return clipboardIsAvailable(CF_BITMAP) 2374 || clipboardIsAvailable(CF_DIB); 2375 2376 #if 0 2377 case CF_PALETTE: 2378 return clipboardIsAvailable(CF_BITMAP) 2379 || clipboardIsAvailable(CF_DIB) 2380 || clipboardIsAvailable(CF_DIBV5); 2381 /* metafiles */ 2382 #endif 2383 2384 default: 2385 return FALSE; 2386 } 2387 } 2388 2389 2390 /** 2391 * Synthesizes the given text format from the available text format 2392 * on the clipboard. 2393 * 2394 * @returns Handle to global memory object containing the synthesized text. 2395 * @returns NULL on failure. 2396 * @param uFormat Format to synthesize. 2397 */ 2398 HANDLE clipboardSynthesizeText(UINT uFormat) 2399 { 2400 dprintf2(("USER32: clipboardSynthesizeText: uFormat=%d (%s)\n", uFormat, dbgGetFormatName(uFormat))); 2401 DebugAssert(uFormat == CF_TEXT || uFormat == CF_OEMTEXT || uFormat == CF_UNICODETEXT, 2402 ("invalid format %d\n", uFormat)); 2403 2404 /* 2405 * Check what's available. 2406 */ 2407 BOOL fCF_TEXT = clipboardIsAvailableReal(CF_TEXT); 2408 BOOL fCF_UNICODETEXT= clipboardIsAvailableReal(CF_UNICODETEXT); 2409 BOOL fCF_OEMTEXT = clipboardIsAvailableReal(CF_OEMTEXT); 2410 DebugAssert(fCF_TEXT || fCF_UNICODETEXT || fCF_OEMTEXT, ("no text is available!!!")); 2411 2412 /* 2413 * Figure out format to convert from. 2414 */ 2415 UINT uSrcFormat; 2416 switch (uFormat) 2417 { 2418 case CF_TEXT: 2419 uSrcFormat = fCF_UNICODETEXT ? CF_UNICODETEXT : fCF_OEMTEXT ? CF_OEMTEXT : 0; 2420 break; 2421 case CF_OEMTEXT: 2422 uSrcFormat = fCF_UNICODETEXT ? CF_UNICODETEXT : fCF_TEXT ? CF_TEXT : 0; 2423 break; 2424 case CF_UNICODETEXT: 2425 uSrcFormat = fCF_TEXT ? CF_TEXT : fCF_OEMTEXT ? CF_OEMTEXT : 0; 2426 break; 2427 } 2428 dprintf2(("USER32: clipboardSynthesizeText: uSrcFormat=%d (%s)\n", uSrcFormat, dbgGetFormatName(uSrcFormat))); 2429 2430 /* 2431 * Get the data. 2432 */ 2433 HANDLE hRet = NULL; 2434 HANDLE hMem = GetClipboardData(uSrcFormat); 2435 if (hMem) 2436 { 2437 const void *pv = GlobalLock(hMem); 2438 if (pv) 2439 { 2440 DWORD cb = GlobalSize(hMem); 2441 2442 /* 2443 * determin size of converted text 2444 */ 2445 unsigned cbRet; 2446 unsigned uCp; 2447 switch (uSrcFormat) 2448 { 2449 case CF_TEXT: 2450 case CF_OEMTEXT: 2451 cbRet = strlen((char*)pv) + 1; /* OEM better not bet multibyte/dbcs. */ 2452 if (uFormat == CF_UNICODETEXT) 2453 cbRet *= sizeof(WCHAR); 2454 break; 2455 case CF_UNICODETEXT: 2456 uCp = clipboardGetCodepage(uFormat == CF_TEXT ? LOCALE_IDEFAULTANSICODEPAGE : LOCALE_IDEFAULTCODEPAGE); 2457 cbRet = WideCharToMultiByte(uCp, 0, (LPCWSTR)pv, cb / sizeof(WCHAR), NULL, 0, NULL, NULL); 2458 break; 2459 } 2460 2461 /* 2462 * Allocate memory. 2463 */ 2464 PCLIPLOCALDATA pLocalClip; 2465 hRet = clipboardCacheAllocGlobalAlloc(uFormat, cbRet, &pLocalClip); 2466 if (hRet) 2467 { 2468 void * pvRet = GlobalLock(hRet); 2469 2470 /* 2471 * Do the convertion. 2472 */ 2473 switch (uFormat) 2474 { 2475 case CF_TEXT: 2476 switch (uSrcFormat) 2477 { 2478 case CF_OEMTEXT: 2479 OemToCharBuffA((LPCSTR)pv, (LPSTR)pvRet, cbRet); 2480 break; 2481 case CF_UNICODETEXT: 2482 WideCharToMultiByte(uCp, 0, (LPCWSTR)pv, cb / sizeof(WCHAR), (LPSTR)pvRet, cb, NULL, NULL); 2483 break; 2484 } 2485 break; 2486 2487 case CF_OEMTEXT: 2488 switch (uSrcFormat) 2489 { 2490 case CF_TEXT: 2491 CharToOemBuffA((LPCSTR)pv, (LPSTR)pvRet, cbRet); 2492 break; 2493 case CF_UNICODETEXT: 2494 WideCharToMultiByte(uCp, 0, (LPCWSTR)pv, cb / sizeof(WCHAR), (LPSTR)pvRet, cb, NULL, NULL); 2495 break; 2496 } 2497 break; 2498 2499 case CF_UNICODETEXT: 2500 uCp = clipboardGetCodepage(uFormat == CF_TEXT ? LOCALE_IDEFAULTANSICODEPAGE : LOCALE_IDEFAULTCODEPAGE); 2501 MultiByteToWideChar(uCp, MB_PRECOMPOSED, (LPCSTR)pv, cb, (LPWSTR)pvRet, cbRet / sizeof(WCHAR)); 2502 break; 2503 } 2504 GlobalUnlock(hRet); 2505 2506 hRet = clipboardCacheInsertNode(pLocalClip); 2507 } 2508 GlobalUnlock(hMem); 2509 } 2510 else 2511 DebugAssertFailed(("Failed to lock object %#x format %d!!!\n", hMem, uSrcFormat)); 2512 } 2513 else 2514 DebugAssertFailed(("now why isn't %d on the clipboard????\n", uSrcFormat)); 2515 2516 return hRet; 2517 } 2518 2519 2520 /** 2521 * Synthesizes a locale structure. 2522 * 2523 * @returns Handle to global memory object containing the synthesized locale. 2524 * @returns NULL on failure. 2525 * @param uFormat Format to synthesize. 2526 */ 2527 HANDLE clipboardSynthesizeLocale(UINT uFormat) 2528 { 2529 dprintf2(("USER32: clipboardSynthesizeLocale: uFormat=%d (%s)\n", uFormat, dbgGetFormatName(uFormat))); 2530 DebugAssert(uFormat == CF_LOCALE, ("invalid format %d\n", uFormat)); 2531 2532 /* 2533 * Guess an appropriate Locale. 2534 */ 2535 LCID lcid = GetSystemDefaultLCID(); 2536 2537 /* 2538 * Allocate a block in the 'cache'. 2539 */ 2540 PCLIPLOCALDATA pLocalClip; 2541 HANDLE hMem = clipboardCacheAllocGlobalDup(uFormat, &lcid, sizeof(LCID), &pLocalClip); 2542 if (!hMem) 105 2543 return NULL; 106 } 107 hwndOwner = window->getWindowHandle(); 108 RELEASE_WNDOBJ(window); 109 return hwndOwner; 110 } 111 //****************************************************************************** 112 //****************************************************************************** 113 HWND WIN32API GetClipboardViewer(void) 114 { 115 Win32BaseWindow *window; 116 HWND hwndViewer; 117 118 dprintf(("USER32: GetClipboardViewer")); 119 hwndViewer = O32_GetClipboardViewer(); 120 121 window = Win32BaseWindow::GetWindowFromOS2Handle(hwndViewer); 122 if(!window) { 123 //probably an OS/2 window, we pretend it's nobody 2544 2545 /* insert */ 2546 hMem = clipboardCacheInsertNode(pLocalClip); 2547 2548 dprintf2(("USER32: clipboardSynthesizeLocale: returning %#x (lcid=%#x)\n", hMem, lcid)); 2549 return hMem; 2550 } 2551 2552 2553 /** 2554 * Synthesizes a bitmap from the avilable DIB format on the clipboard 2555 * 2556 * @returns Handle to GDI bitmap. 2557 * @returns NULL on failure. 2558 * @param uFormat Format to synthesize. (CF_BITMAP) 2559 */ 2560 HANDLE clipboardSynthesizeBitmap(UINT uFormat) 2561 { 2562 dprintf2(("USER32: clipboardSynthesizeBitmap: uFormat=%d (%s)\n", uFormat, dbgGetFormatName(uFormat))); 2563 DebugAssert(uFormat == CF_BITMAP, ("invalid format %d\n", uFormat)); 2564 2565 /* 2566 * Find DIB format to convert from. 2567 */ 2568 UINT uSrcFormat = CF_DIB; 2569 if (!clipboardIsAvailableReal(uSrcFormat)) 2570 { 2571 uSrcFormat = CF_DIBV5; 2572 if (!clipboardIsAvailableReal(uSrcFormat)) 2573 { 2574 DebugAssertFailed(("no DIB data avilable!\n")); 2575 return NULL; 2576 } 2577 } 2578 dprintf2(("USER32: clipboardSynthesizeBitmap: uSrcFormat=%d (%s)\n", uSrcFormat, dbgGetFormatName(uSrcFormat))); 2579 2580 /* 2581 * Get the data. 2582 */ 2583 PCLIPHEADER pClip = (PCLIPHEADER)OSLibWinQueryClipbrdData(GetThreadHAB(), clipboardOdinToPMFormat(uSrcFormat)); 2584 if ( !pClip 2585 || pClip == (PCLIPHEADER)DUMMY_HANDLE 2586 || memcmp(pClip->achMagic, CLIPHEADER_MAGIC, sizeof(CLIPHEADER_MAGIC))) 2587 { 2588 DebugAssertFailed(("invalid clipboard data for format %d\n", uSrcFormat)); 124 2589 return NULL; 125 2590 } 126 hwndViewer = window->getWindowHandle(); 127 RELEASE_WNDOBJ(window); 128 return hwndViewer; 129 } 130 //****************************************************************************** 131 //****************************************************************************** 132 HWND WIN32API SetClipboardViewer( HWND hwndNew) 133 { 134 Win32BaseWindow *wndnew, *wndold; 135 HWND hwndOld; 136 HWND hwndOS2New; 137 138 wndnew = Win32BaseWindow::GetWindowFromHandle(hwndNew); 139 if(!wndnew) { 140 dprintf(("SetClipboardViewer, window %x not found", hwndNew)); 141 SetLastError(ERROR_INVALID_WINDOW_HANDLE); 142 return 0; 143 } 144 dprintf(("USER32: SetClipboardViewer %x", hwndNew)); 145 hwndOS2New = wndnew->getOS2WindowHandle(); 146 RELEASE_WNDOBJ(wndnew); 147 148 hwndOld = O32_SetClipboardViewer(hwndOS2New); 149 150 wndold = Win32BaseWindow::GetWindowFromOS2Handle(hwndOld); 151 if(!wndold) { 152 //probably an OS/2 window, so pretend it's nobody 153 return 0; 154 } 155 hwndOld = wndold->getWindowHandle(); 156 RELEASE_WNDOBJ(wndold); 157 return hwndOld; 158 } 159 //****************************************************************************** 160 //****************************************************************************** 161 HWND WIN32API GetOpenClipboardWindow(void) 162 { 163 Win32BaseWindow *window; 164 HWND hwnd; 165 166 hwnd = O32_GetOpenClipboardWindow(); 167 168 window = Win32BaseWindow::GetWindowFromOS2Handle(hwnd); 169 if(!window) { 170 //probably an OS/2 window, we pretend it's nobody 2591 2592 /* 2593 * Check the content a little bit. 2594 */ 2595 union u 2596 { 2597 PVOID pv; 2598 char * pch; 2599 LPBITMAPINFOHEADER pHdr; 2600 LPBITMAPV5HEADER pHdrV5; 2601 } u = { (void*)(pClip + 1) }; 2602 if (u.pHdr->biSize < sizeof(BITMAPCOREHEADER) || u.pHdr->biSize > sizeof(BITMAPV5HEADER)) 2603 { 2604 DebugAssertFailed(("invalid clipboard DIB data: biSize=%d\n", u.pHdr->biSize)); 171 2605 return NULL; 172 2606 } 173 hwnd = window->getWindowHandle(); 174 RELEASE_WNDOBJ(window); 175 return hwnd; 176 } 177 //****************************************************************************** 178 //****************************************************************************** 179 int WIN32API GetPriorityClipboardFormat( PUINT arg1, int arg2) 180 { 181 dprintf(("USER32: GetPriorityClipboardFormat")); 182 return O32_GetPriorityClipboardFormat(arg1, arg2); 183 } 184 //****************************************************************************** 185 //****************************************************************************** 186 BOOL WIN32API IsClipboardFormatAvailable( UINT arg1) 187 { 188 dprintf(("USER32: IsClipboardFormatAvailable %x", arg1)); 189 return O32_IsClipboardFormatAvailable(arg1); 190 } 191 //****************************************************************************** 192 //****************************************************************************** 193 BOOL WIN32API OpenClipboard( HWND hwnd) 194 { 195 Win32BaseWindow *window; 196 197 if (hwnd) { 198 window = Win32BaseWindow::GetWindowFromHandle(hwnd); 199 if(!window) { 200 dprintf(("OpenClipboard, window %x not found", hwnd)); 201 SetLastError(ERROR_INVALID_WINDOW_HANDLE); 202 return 0; 203 } 204 hwnd = window->getOS2WindowHandle(); 205 RELEASE_WNDOBJ(window); 206 } 207 dprintf(("USER32: OpenClipboard %x", hwnd)); 208 return O32_OpenClipboard(hwnd); 209 } 210 //****************************************************************************** 211 //****************************************************************************** 212 BOOL WIN32API CloseClipboard(void) 213 { 214 return O32_CloseClipboard(); 215 } 216 //****************************************************************************** 217 //****************************************************************************** 218 UINT WIN32API RegisterClipboardFormatA( LPCSTR arg1) 219 { 220 dprintf(("USER32: RegisterClipboardFormatA %s", arg1)); 221 return O32_RegisterClipboardFormat(arg1); 222 } 223 //****************************************************************************** 224 //****************************************************************************** 225 UINT WIN32API RegisterClipboardFormatW(LPCWSTR arg1) 226 { 227 UINT rc; 228 char *astring = UnicodeToAsciiString((LPWSTR)arg1); 229 230 dprintf(("USER32: RegisterClipboardFormatW %s\n", astring)); 231 rc = O32_RegisterClipboardFormat(astring); 232 FreeAsciiString(astring); 233 dprintf(("USER32: RegisterClipboardFormatW returned %d\n", rc)); 234 return(rc); 235 } 236 //****************************************************************************** 237 //****************************************************************************** 238 HANDLE WIN32API GetClipboardData(UINT uFormat) 239 { 240 HANDLE hRet = O32_GetClipboardData(uFormat); 241 dprintf(("GetClipboardData %x returned %x", uFormat, hRet)); 242 #ifdef DEBUG 243 if(hRet) { 244 if(uFormat == CF_TEXT || uFormat == CF_DSPTEXT) { 245 char *lpszText = (char *)GlobalLock(hRet); 246 if(lpszText) dprintf(("GetClipboardData %s", lpszText)); 247 GlobalUnlock(hRet); 248 } 249 if(uFormat == CF_UNICODETEXT) { 250 LPWSTR lpszText = (LPWSTR)GlobalLock(hRet); 251 if(lpszText) dprintf(("GetClipboardData %ls", lpszText)); 252 GlobalUnlock(hRet); 253 } 254 } 2607 switch (u.pHdr->biBitCount) 2608 { 2609 case 1: 2610 case 2: 2611 case 4: 2612 case 8: 2613 case 16: 2614 case 24: 2615 case 32: 2616 break; 2617 default: 2618 DebugAssertFailed(("invalid clipboard DIB data: biBitCount=%d\n", u.pHdr->biBitCount)); 2619 return NULL; 2620 } 2621 if ( u.pHdrV5->bV5Size == sizeof(BITMAPV5HEADER) 2622 && u.pHdrV5->bV5CSType != LCS_sRGB) 2623 { 2624 DebugAssertFailed(("unexpected clipboard DIBV5 data: bV5CSType=%#x\n", u.pHdrV5->bV5CSType)); 2625 return NULL; 2626 } 2627 /* todo more checking. */ 2628 2629 /* 2630 * Calc start of bits. 2631 */ 2632 void *pvBits = (char*)u.pv + u.pHdr->biSize; 2633 if (u.pHdr->biBitCount <= 8) 2634 pvBits = (char*)pvBits + sizeof(RGBQUAD) * (1 << u.pHdr->biBitCount); 2635 2636 /* 2637 * Create the bitmap. 2638 */ 2639 HBITMAP hbm; 2640 HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL); 2641 if (hdc) 2642 { 2643 hbm = CreateDIBitmap(hdc, u.pHdr, CBM_INIT, pvBits, (PBITMAPINFO)u.pHdr, DIB_RGB_COLORS); 2644 if (hbm) 2645 { 2646 /* allocate and insert it into the cache. */ 2647 PCLIPLOCALDATA pLocalClip; 2648 if (clipboardCacheAllocGDI(uFormat, hbm, &pLocalClip)) 2649 hbm = clipboardCacheInsertNode(pLocalClip); 2650 dprintf(("synthesized bitmap %#x\n", hbm)); 2651 } 2652 else 2653 DebugAssertFailed(("CreateBitmapIndirect failed\n")); 2654 DeleteDC(hdc); 2655 } 2656 2657 return hbm; 2658 } 2659 2660 /** 2661 * Synthesizes the given DIB format from the available DIB or bitmap 2662 * on the clipboard. 2663 * 2664 * @returns Handle to global memory object containing the synthesized DIB. 2665 * @returns NULL on failure. 2666 * @param uFormat Format to synthesize. (CF_BITMAP) 2667 */ 2668 HANDLE clipboardSynthesizeDIB(UINT uFormat) 2669 { 2670 dprintf2(("USER32: clipboardSynthesizeDIB: uFormat=%d (%s)\n", uFormat, dbgGetFormatName(uFormat))); 2671 OSLIB_BITMAPINFOHEADER2 bih2; 2672 DebugAssert(uFormat == CF_DIB || uFormat == CF_DIBV5, ("invalid format %d\n", uFormat)); 2673 2674 /* 2675 * Find convert format and calculate the size of the converted bitmap. 2676 */ 2677 UINT uSrcFormat = CF_DIB; 2678 if (!clipboardIsAvailableReal(uSrcFormat)) 2679 { 2680 uSrcFormat = CF_DIBV5; 2681 if (!clipboardIsAvailableReal(uSrcFormat)) 2682 { 2683 uSrcFormat = CF_BITMAP; 2684 if (!clipboardIsAvailableReal(uSrcFormat)) 2685 { 2686 DebugAssertFailed(("no bitmap or DIB available on the clipboard\n")); 2687 return NULL; 2688 } 2689 } 2690 } 2691 dprintf2(("USER32: clipboardSynthesizeDIB: uSrcFormat=%d (%s)\n", uSrcFormat, dbgGetFormatName(uSrcFormat))); 2692 2693 /* 2694 * Get the data. 2695 */ 2696 void *pv = (void*)OSLibWinQueryClipbrdData(GetThreadHAB(), clipboardOdinToPMFormat(uSrcFormat)); 2697 if ( !pv 2698 || pv == (void*)DUMMY_HANDLE 2699 || ( uSrcFormat != CF_BITMAP 2700 && memcmp(pv, CLIPHEADER_MAGIC, sizeof(CLIPHEADER_MAGIC)) 2701 ) 2702 ) 2703 { 2704 DebugAssertFailed(("invalid clipboard data for format %d\n", uSrcFormat)); 2705 return NULL; 2706 } 2707 2708 2709 /* 2710 * Do the conversion. 2711 */ 2712 switch (uSrcFormat) 2713 { 2714 /* 2715 * Convert an OS/2 bitmap to a DIB or DIBV5. 2716 */ 2717 case CF_BITMAP: 2718 { 2719 /* We're letting GPI do the major bit of the work actually. */ 2720 HBITMAP hbm = O32_CreateBitmapFromPMHandle((HBITMAP)pv); 2721 if (!hbm) 2722 { 2723 DebugAssertFailed(("invalid OS/2 hbitmap %#x on clipboard\n", (unsigned)pv)); 2724 return NULL; 2725 } 2726 2727 HANDLE hMem = NULL; 2728 HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL); 2729 if (hdc) 2730 { 2731 SelectObject(hdc, hbm); 2732 2733 /* 2734 * Figure out the sizes. 2735 */ 2736 unsigned cbTrgHeader = uFormat == CF_DIB ? sizeof(BITMAPINFOHEADER) : sizeof(BITMAPV5HEADER); 2737 BITMAPINFOHEADER hdr = {sizeof(BITMAPINFOHEADER), 0}; 2738 if (GetDIBits(hdc, hbm, 0, 0, NULL, (PBITMAPINFO)&hdr, DIB_RGB_COLORS)) 2739 { /* we've got the header now */ 2740 unsigned cbTrgColorTable = 0; 2741 switch (hdr.biBitCount) 2742 { 2743 case 1: 2744 case 2: 2745 case 4: 2746 case 8: 2747 cbTrgColorTable = (1 << hdr.biBitCount) * sizeof(RGBQUAD); 2748 break; 2749 } 2750 2751 unsigned cbTrgBits = hdr.biSizeImage; 2752 if (!cbTrgBits) 2753 { 2754 cbTrgBits = ((hdr.biWidth * hdr.biBitCount + 31) >> 5) << 2; 2755 cbTrgBits *= abs(hdr.biHeight); 2756 } 2757 2758 unsigned cbTotal = cbTrgHeader + cbTrgColorTable + cbTrgBits; 2759 2760 /* 2761 * Allocate a cache object. 2762 */ 2763 PCLIPLOCALDATA pLocalClip; 2764 hMem = clipboardCacheAllocGlobalAlloc(uFormat, cbTotal, &pLocalClip); 2765 if (hMem) 2766 { 2767 union u 2768 { 2769 PVOID pv; 2770 char * pch; 2771 LPBITMAPINFOHEADER pHdr; 2772 LPBITMAPV5HEADER pHdrV5; 2773 } uTrg; 2774 uTrg.pv = GlobalLock(hMem); 2775 2776 /* 2777 * Get the bitmap bits and pieces. 2778 */ 2779 memcpy(uTrg.pv, &hdr, sizeof(hdr)); 2780 if (GetDIBits(hdc, hbm, 0, hdr.biHeight, 2781 uTrg.pch + cbTrgHeader + cbTrgColorTable, 2782 (PBITMAPINFO)uTrg.pv, 2783 DIB_RGB_COLORS)) 2784 { 2785 /* adjust the header+color table for CF_DIBV5 */ 2786 #ifdef USE_DIBV5 2787 if (uFormat == CF_DIBV5) 2788 { 2789 if (cbTrgColorTable) 2790 memmove(uTrg.pch + sizeof(BITMAPV5HEADER), uTrg.pch + sizeof(hdr), cbTrgColorTable); 2791 memset(uTrg.pch + sizeof(hdr), 0, sizeof(BITMAPV5HEADER) - sizeof(hdr)); 2792 uTrg.pHdrV5->bV5Size = sizeof(BITMAPV5HEADER); 2793 uTrg.pHdrV5->bV5CSType = LCS_sRGB; 2794 } 2795 #endif 2796 if (!uTrg.pHdr->biClrImportant) 2797 uTrg.pHdr->biClrImportant = uTrg.pHdr->biClrUsed; 2798 2799 DeleteDC(hdc); 2800 HANDLE hRet = clipboardCacheInsertNode(pLocalClip); 2801 dprintf2(("USER32: clipboardSynthesizeDIB: returning %#x\n", hRet)); 2802 return hRet; 2803 } 2804 else 2805 DebugAssertFailed(("GetDIBits failed lasterr=%d\n", GetLastError())); 2806 2807 /* failure */ 2808 clipboardCacheDeleteNode(pLocalClip); 2809 } 2810 else 2811 DebugAssertFailed(("GlobalAlloc failed lasterr=%d\n", GetLastError())); 2812 } 2813 else 2814 DebugAssertFailed(("GetDIBits (header) failed lasterr=%d\n", GetLastError())); 2815 DeleteDC(hdc); 2816 } 2817 else 2818 DebugAssertFailed(("CreateDCA failed lasterr=%d\n", GetLastError())); 2819 return NULL; 2820 } 2821 2822 /* 2823 * DIB <-> DIBV5: basically only header adjustments 2824 * (We do not yet support advanced DIBV5 formats.) 2825 */ 2826 case CF_DIB: 2827 case CF_DIBV5: 2828 { 2829 union u 2830 { 2831 PVOID pv; 2832 char * pch; 2833 LPBITMAPINFOHEADER pHdr; 2834 LPBITMAPV5HEADER pHdrV5; 2835 } uSrc, uTrg; 2836 uSrc.pv = (char*)pv + sizeof(CLIPHEADER); 2837 unsigned cbSrc = ((PCLIPHEADER)pv)->cbData; 2838 2839 /* 2840 * Validate the bitmap data a little bit. 2841 */ 2842 if (uSrc.pHdr->biSize < sizeof(BITMAPCOREHEADER) || uSrc.pHdr->biSize > sizeof(BITMAPV5HEADER)) 2843 { 2844 DebugAssertFailed(("Unknown header size %d\n", uSrc.pHdr->biSize)); 2845 return NULL; 2846 } 2847 switch (uSrc.pHdr->biBitCount) 2848 { 2849 case 1: 2850 case 2: 2851 case 4: 2852 case 8: 2853 case 16: 2854 case 24: 2855 case 32: 2856 break; 2857 default: 2858 DebugAssertFailed(("invalid clipboard DIB data: biBitCount=%d\n", uSrc.pHdr->biBitCount)); 2859 return NULL; 2860 } 2861 if ( uSrc.pHdrV5->bV5Size == sizeof(BITMAPV5HEADER) 2862 && uSrc.pHdrV5->bV5CSType != LCS_sRGB) 2863 { 2864 DebugAssertFailed(("unexpected clipboard DIBV5 data: bV5CSType=%#x\n", uSrc.pHdrV5->bV5CSType)); 2865 return NULL; 2866 } 2867 2868 /* 2869 * Figure out the size of the target bitmap and allocate memory for this. 2870 */ 2871 unsigned cbTrgHeader = uFormat == CF_DIB ? sizeof(BITMAPINFOHEADER) : sizeof(BITMAPV5HEADER); 2872 unsigned cbTotal = cbSrc + (cbTrgHeader - uSrc.pHdr->biSize); 2873 PCLIPLOCALDATA pLocalClip; 2874 HANDLE hMem = clipboardCacheAllocGlobalAlloc(uFormat, cbTotal, &pLocalClip); 2875 if (!hMem) 2876 return NULL; 2877 uTrg.pv = GlobalLock(hMem); 2878 2879 /* 2880 * Convert the bitmap data. 2881 * Note that the source and target DIB data might be in the same format. 2882 */ 2883 if (cbTrgHeader != uTrg.pHdr->biSize) 2884 { 2885 /** @todo Only a subset of DIB V5 bitmaps are supported, implement it fully all around Odin32. */ 2886 switch (uFormat) 2887 { 2888 case CF_DIBV5: 2889 #ifdef USE_DIBV5 2890 memcpy(uTrg.pv, uSrc.pv, uSrc.pHdr->biSize); 2891 memset(uTrg.pch + uSrc.pHdr->biSize, 0, sizeof(BITMAPV5HEADER) - uSrc.pHdr->biSize); 2892 uTrg.pHdrV5->bV5Size = sizeof(BITMAPV5HEADER); 2893 uTrg.pHdrV5->bV5CSType = LCS_sRGB; 2894 memcpy(uTrg.pch + sizeof(BITMAPV5HEADER), uSrc.pch + uSrc.pHdr->biSize, cbSrc - uSrc.pHdr->biSize); 2895 break; 2896 #else 2897 //fallthru 2898 #endif 2899 case CF_DIB: 2900 memcpy(uTrg.pv, uSrc.pv, min(uSrc.pHdr->biSize, sizeof(BITMAPINFOHEADER))); 2901 if (uSrc.pHdr->biSize < sizeof(BITMAPINFOHEADER)) 2902 memset(uTrg.pch + uSrc.pHdr->biSize, 0, sizeof(BITMAPINFOHEADER) - uSrc.pHdr->biSize); 2903 memcpy(uTrg.pch + sizeof(BITMAPINFOHEADER), uSrc.pch + uSrc.pHdr->biSize, cbSrc - uSrc.pHdr->biSize); 2904 break; 2905 } 2906 } 2907 GlobalUnlock(hMem); 2908 /* done */ 2909 return hMem; 2910 } 2911 } 2912 2913 return NULL; 2914 } 2915 2916 #if 0 // not implemented yet 2917 HANDLE clipboardSynthesizePalette(UINT uFormat) 2918 { 2919 return NULL; 2920 } 2921 2922 HANDLE clipboardSynthesizeMetaFile(UINT uFormat) 2923 { 2924 return NULL; 2925 } 2926 2927 HANDLE clipboardSynthesizeEnhMetaFile(UINT uFormat) 2928 { 2929 return NULL; 2930 } 255 2931 #endif 256 return hRet; 257 } 258 //****************************************************************************** 259 //****************************************************************************** 260 HANDLE WIN32API SetClipboardData( UINT uFormat, HANDLE hClipObj) 261 { 262 dprintf(("SetClipboardData %x %x", uFormat, hClipObj)); 263 #ifdef DEBUG 264 if(hClipObj) { 265 if(uFormat == CF_TEXT || uFormat == CF_DSPTEXT) { 266 char *lpszText = (char *)GlobalLock(hClipObj); 267 if(lpszText) dprintf(("SetClipboardData %s", lpszText)); 268 GlobalUnlock(hClipObj); 269 } 270 if(uFormat == CF_UNICODETEXT) { 271 LPWSTR lpszText = (LPWSTR)GlobalLock(hClipObj); 272 if(lpszText) dprintf(("SetClipboardData %ls", lpszText)); 273 GlobalUnlock(hClipObj); 274 } 275 } 276 #endif 277 return O32_SetClipboardData(uFormat, hClipObj); 278 } 279 //****************************************************************************** 280 //****************************************************************************** 2932 2933 2934 /** 2935 * Get the length of a text on the clipboard. 2936 * 2937 * @returns up to cb. 2938 * @param pvData Data pointer. 2939 * @param cb Data size. 2940 */ 2941 unsigned clipboardTextCalcSize(void *pvData, unsigned cb) 2942 { 2943 const char *psz = (const char*)pvData; 2944 const char *pszEnd = psz + cb; 2945 while (psz + 1 < pszEnd) 2946 { 2947 if (!*psz && !psz[1]) /* Check for two '\0' to keep out of dbcs trouble. */ 2948 return psz - (char*)pvData + 1; 2949 psz++; 2950 } 2951 return cb; 2952 } 2953 2954 2955 /** 2956 * Gets the clipboad code page using the CF_LOCALE entry if present, if not 2957 * present the system default is used. 2958 * 2959 * @returns Codepage corresponding to uType. 2960 * @param uType Code page type. 2961 */ 2962 unsigned clipboardGetCodepage(UINT uType) 2963 { 2964 /* 2965 * Find the LCID to use. 2966 */ 2967 HANDLE hMem = GetClipboardData(CF_LOCALE); 2968 LCID lcid; 2969 LCID *plcid; 2970 if (hMem && (plcid = (LCID *)GlobalLock(hMem)) != NULL) 2971 { 2972 lcid = *plcid; 2973 GlobalUnlock(hMem); 2974 } 2975 else 2976 lcid = GetSystemDefaultLCID(); 2977 2978 char szCp[6]; 2979 if (GetLocaleInfoA(lcid, uType, szCp, sizeof(szCp))) 2980 return atoi(szCp); 2981 2982 switch (uType) 2983 { 2984 case LOCALE_IDEFAULTCODEPAGE : return CP_OEMCP; 2985 case LOCALE_IDEFAULTANSICODEPAGE: return CP_ACP; 2986 default : return CP_MACCP; 2987 } 2988 } 2989 2990 2991 /** 2992 * GlobalAllocs a block of memory for the cache initializing it from the 2993 * the memory block specified pv. 2994 * 2995 * @returns Handle to 'global' memory object. 2996 * @returns NULL on failure. 2997 * @param uFormat Odin format number. 2998 * @param pv Pointer to memory block to duplicate. 2999 * @param cb Number of bytes to allocate and duplicate. 3000 * @param ppLocalClip Where to put the cache structure. 3001 */ 3002 HANDLE clipboardCacheAllocGlobalDup(UINT uFormat, const void *pv, unsigned cb, PCLIPLOCALDATA *ppClip) 3003 { 3004 dprintf2(("USER32: clipboardCacheAllocGlobalDup: uFormat=%d (%s) pv=%p cb=%d\n", 3005 uFormat, dbgGetFormatName(uFormat), pv, cb)); 3006 3007 /* 3008 * Allocate cache block and copy data. 3009 */ 3010 HANDLE hMem = clipboardCacheAllocGlobalAlloc(uFormat, cb, ppClip); 3011 if (hMem) 3012 { 3013 PVOID pvMem = GlobalLock(hMem); 3014 memcpy(pvMem, pv, cb); 3015 GlobalUnlock(hMem); 3016 } 3017 3018 return hMem; 3019 } 3020 3021 3022 3023 /** 3024 * GlobalAllocs a block of memory for the cache. 3025 * 3026 * @returns Handle to 'global' memory object. 3027 * @returns NULL on failure. 3028 * @param uFormat Odin format number. 3029 * @param cb Number of bytes to allocate. 3030 * @param ppLocalClip Where to put the cache structure. 3031 */ 3032 HANDLE clipboardCacheAllocGlobalAlloc(UINT uFormat, unsigned cb, PCLIPLOCALDATA *ppLocalClip) 3033 { 3034 dprintf2(("USER32: clipboardCacheAllocGlobalAlloc: uFormat=%d (%s) cb=%d\n", 3035 uFormat, dbgGetFormatName(uFormat), cb)); 3036 /* 3037 * Allocate object. 3038 */ 3039 HANDLE hMem = GlobalAlloc(GMEM_MOVEABLE, cb); 3040 if (!hMem) 3041 { 3042 dprintf(("USER32: GetClipboardData: returns NULL (GlobalAlloc(,%d) failed)\n", cb)); 3043 return NULL; 3044 } 3045 3046 /* 3047 * Allocate and initialize cache node. 3048 */ 3049 if (clipboardCacheAllocGlobalMem(uFormat, hMem, ppLocalClip)) 3050 return hMem; 3051 3052 /* failed */ 3053 GlobalFree(hMem); 3054 return NULL; 3055 } 3056 3057 3058 /** 3059 * Allocates a cache node for a global memory handle. 3060 * 3061 * @returns Handle to 'global' memory object. 3062 * @returns NULL on failure. 3063 * @param uFormat Odin format number. 3064 * @param cb Number of bytes to allocate. 3065 * @param ppLocalClip Where to put the cache structure. 3066 */ 3067 BOOL clipboardCacheAllocGlobalMem(UINT uFormat, HANDLE hMem, PCLIPLOCALDATA *ppLocalClip) 3068 { 3069 dprintf2(("USER32: clipboardCacheAllocGlobalMem: uFormat=%d (%s) hMem=%#x\n", 3070 uFormat, dbgGetFormatName(uFormat), hMem)); 3071 3072 /* 3073 * Allocate and initialize cache node. 3074 */ 3075 PCLIPLOCALDATA pLocalClip = (PCLIPLOCALDATA)malloc(sizeof(*pLocalClip)); 3076 *ppLocalClip = pLocalClip; 3077 if (!pLocalClip) 3078 return FALSE; 3079 3080 pLocalClip->enmType = CLIPLOCALDATA::enmGlobalMem; 3081 pLocalClip->h = hMem; 3082 pLocalClip->uFormat = uFormat; 3083 pLocalClip->pNext = NULL; 3084 3085 return TRUE; 3086 } 3087 3088 3089 /** 3090 * Allocates a cache node for a GDI handle. 3091 * 3092 * @returns hGDI on success. 3093 * @returns NULL on failure. 3094 * @param uFormat Clipboard format number. 3095 * @param hGDI GDI handle. 3096 * @param ppLocalClip Where to store the pointer to the allocated cache node. 3097 */ 3098 BOOL clipboardCacheAllocGDI(UINT uFormat, HANDLE hGDI, PCLIPLOCALDATA *ppLocalClip) 3099 { 3100 dprintf2(("USER32: clipboardCacheAllocGDI: uFormat=%d (%s) hGdi=%#x\n", 3101 uFormat, dbgGetFormatName(uFormat), hGDI)); 3102 /* 3103 * Allocate and initialize cache node. 3104 */ 3105 PCLIPLOCALDATA pLocalClip = (PCLIPLOCALDATA)malloc(sizeof(*pLocalClip)); 3106 *ppLocalClip = pLocalClip; 3107 if (!pLocalClip) 3108 return FALSE; 3109 3110 pLocalClip->enmType = CLIPLOCALDATA::enmGDI; 3111 pLocalClip->h = hGDI; 3112 pLocalClip->uFormat = uFormat; 3113 pLocalClip->pNext = NULL; 3114 3115 return TRUE; 3116 } 3117 3118 3119 /** 3120 * Inserts a previously allocated local cache node. 3121 * 3122 * Since this is a cache, pNew might be rejected because of the data 3123 * already existing in the cache. Therefor always use the returned handle. 3124 * 3125 * @returns The handle in the cached node. 3126 * @param pNew Node to insert. 3127 */ 3128 HANDLE clipboardCacheInsertNode(PCLIPLOCALDATA pNew) 3129 { 3130 dprintf2(("USER32: clipboardCacheInsertNode: pNew=%p format=%d (%s) h=%#x\n", 3131 pNew, pNew->uFormat, dbgGetFormatName(pNew->uFormat), pNew->h)); 3132 /* 3133 * Find the previous node with the same format. 3134 */ 3135 PCLIPLOCALDATA p = gpLocalData; 3136 PCLIPLOCALDATA pPrev = NULL; 3137 while (p && p->uFormat != pNew->uFormat) 3138 p = p->pNext; 3139 if (p) 3140 { 3141 /* 3142 * If the old and new cache nodes are idendical we'll keep the old one. 3143 */ 3144 if (p->enmType == pNew->enmType) 3145 { 3146 switch (p->enmType) 3147 { 3148 case CLIPLOCALDATA::enmGlobalMem: 3149 { 3150 DWORD cb = GlobalSize(p->h); 3151 if (cb == GlobalSize(pNew->h)) 3152 { 3153 PVOID pv = GlobalLock(p->h); 3154 PVOID pvNew = GlobalLock(pNew->h); 3155 int diff = -1; 3156 if (pv && pvNew) 3157 diff = memcmp(pv, pvNew, cb); 3158 GlobalUnlock(pNew->h); 3159 GlobalUnlock(p->h); 3160 if (!diff) 3161 { 3162 clipboardCacheDeleteNode(pNew); 3163 dprintf2(("USER32: clipboardCacheInsertNode: returning existing node %#x (cache hit)\n", p->h)); 3164 return p->h; 3165 } 3166 } 3167 break; 3168 } 3169 3170 case CLIPLOCALDATA::enmGDI: 3171 /** @todo */ 3172 break; 3173 3174 case CLIPLOCALDATA::enmPrivate: 3175 default: 3176 DebugAssertFailed(("Don't know how to handle this type\n")); 3177 break; 3178 } 3179 3180 } 3181 3182 /* 3183 * Remove and delete the old node. 3184 */ 3185 dprintf2(("USER32: clipboardCacheInsertNode: removing old node %p h=%#x\n", p, p->h)); 3186 if (pPrev) 3187 pPrev->pNext = p->pNext; 3188 else 3189 gpLocalData = p->pNext; 3190 clipboardCacheDeleteNode(p); 3191 } 3192 3193 /* 3194 * Insert the new node. 3195 */ 3196 pNew->pNext = gpLocalData; 3197 gpLocalData = pNew; 3198 3199 return pNew->h; 3200 } 3201 3202 3203 /** 3204 * Delete Odin resources associated with a cache node. 3205 * 3206 * The node must be unlinked from the cache before this function is called. 3207 * 3208 * @param p Node to delete. 3209 */ 3210 void clipboardCacheDeleteNode(PCLIPLOCALDATA p) 3211 { 3212 dprintf2(("USER32: clipboardCacheDeleteNode: p=%p format=%d (%s) h=%#x\n", 3213 p, p->uFormat, dbgGetFormatName(p->uFormat), p->h)); 3214 switch (p->enmType) 3215 { 3216 case CLIPLOCALDATA::enmGlobalMem: 3217 if (GlobalFree(p->h)) 3218 DebugAssertFailed(("GlobalFree failed freeing %#x (format %d). lasterr=%d\n", 3219 p->h, p->uFormat, GetLastError())); 3220 p->h = NULL; 3221 break; 3222 3223 case CLIPLOCALDATA::enmGDI: 3224 if (!DeleteObject(p->h)) 3225 DebugAssertFailed(("DeleteObject failed freeing %#x (format %d). lasterr=%d\n", 3226 p->h, p->uFormat, GetLastError())); 3227 p->h = NULL; 3228 break; 3229 3230 case CLIPLOCALDATA::enmPrivate: 3231 DebugAssertFailed(("shit! don't know how to handle this cache type!")); 3232 break; 3233 default: 3234 DebugAssertFailed(("!cache corrupted! invalid type %d", p->enmType)); 3235 break; 3236 } 3237 free(p); 3238 } 3239 -
trunk/src/user32/oslibmsgtranslate.cpp
r10554 r10578 1 /* $Id: oslibmsgtranslate.cpp,v 1.12 2 2004-03-23 16:50:08sandervl Exp $ */1 /* $Id: oslibmsgtranslate.cpp,v 1.123 2004-04-13 14:16:43 sandervl Exp $ */ 2 2 /* 3 3 * Window message translation functions for OS/2
Note:
See TracChangeset
for help on using the changeset viewer.