clipboard.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712
  1. /*
  2. * WIN32 clipboard implementation
  3. *
  4. * Copyright 1994 Martin Ayotte
  5. * 1996 Alex Korobka
  6. * 1999 Noel Borthwick
  7. * 2003 Ulrich Czekalla for CodeWeavers
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation; either
  12. * version 2.1 of the License, or (at your option) any later version.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  22. *
  23. * NOTES:
  24. * This file contains the implementation for the WIN32 Clipboard API
  25. * and Wine's internal clipboard cache.
  26. * The actual contents of the clipboard are held in the clipboard cache.
  27. * The internal implementation talks to a "clipboard driver" to fill or
  28. * expose the cache to the native device. (Currently only the X11 and
  29. * TTY clipboard driver are available)
  30. */
  31. #include "config.h"
  32. #include "wine/port.h"
  33. #include <stdarg.h>
  34. #include <stdlib.h>
  35. #include <sys/types.h>
  36. #include <fcntl.h>
  37. #ifdef HAVE_UNISTD_H
  38. # include <unistd.h>
  39. #endif
  40. #include <string.h>
  41. #include "windef.h"
  42. #include "winbase.h"
  43. #include "wingdi.h"
  44. #include "winuser.h"
  45. #include "winerror.h"
  46. #include "wine/winuser16.h"
  47. #include "wine/winbase16.h"
  48. #include "user_private.h"
  49. #include "win.h"
  50. #include "wine/debug.h"
  51. #include "wine/unicode.h"
  52. #include "wine/server.h"
  53. WINE_DEFAULT_DEBUG_CHANNEL(clipboard);
  54. #define CF_REGFORMATBASE 0xC000
  55. typedef struct
  56. {
  57. HWND hWndOpen;
  58. HWND hWndOwner;
  59. HWND hWndViewer;
  60. UINT seqno;
  61. UINT flags;
  62. } CLIPBOARDINFO, *LPCLIPBOARDINFO;
  63. /*
  64. * Indicates if data has changed since open.
  65. */
  66. static BOOL bCBHasChanged = FALSE;
  67. /**************************************************************************
  68. * CLIPBOARD_SetClipboardOwner
  69. *
  70. * Set the global wineserver clipboard owner. The current process will
  71. * be the owner and <hWnd> will get the render notifications.
  72. */
  73. BOOL CLIPBOARD_SetClipboardOwner(HWND hWnd)
  74. {
  75. BOOL bRet = FALSE;
  76. TRACE(" hWnd(%p)\n", hWnd);
  77. SERVER_START_REQ( set_clipboard_info )
  78. {
  79. req->flags = SET_CB_OWNER;
  80. req->owner = WIN_GetFullHandle( hWnd );
  81. if (wine_server_call_err( req ))
  82. {
  83. ERR("Failed to set clipboard owner to %p\n", hWnd);
  84. }
  85. else
  86. {
  87. bRet = TRUE;
  88. }
  89. }
  90. SERVER_END_REQ;
  91. return bRet;
  92. }
  93. /**************************************************************************
  94. * CLIPBOARD_GetClipboardInfo
  95. */
  96. static BOOL CLIPBOARD_GetClipboardInfo(LPCLIPBOARDINFO cbInfo)
  97. {
  98. BOOL bRet = FALSE;
  99. SERVER_START_REQ( set_clipboard_info )
  100. {
  101. req->flags = 0;
  102. if (wine_server_call_err( req ))
  103. {
  104. ERR("Failed to get clipboard info\n");
  105. }
  106. else
  107. {
  108. cbInfo->hWndOpen = reply->old_clipboard;
  109. cbInfo->hWndOwner = reply->old_owner;
  110. cbInfo->hWndViewer = reply->old_viewer;
  111. cbInfo->seqno = reply->seqno;
  112. cbInfo->flags = reply->flags;
  113. bRet = TRUE;
  114. }
  115. }
  116. SERVER_END_REQ;
  117. return bRet;
  118. }
  119. /**************************************************************************
  120. * CLIPBOARD_ReleaseOwner
  121. */
  122. BOOL CLIPBOARD_ReleaseOwner(void)
  123. {
  124. BOOL bRet = FALSE;
  125. SERVER_START_REQ( set_clipboard_info )
  126. {
  127. req->flags = SET_CB_RELOWNER | SET_CB_SEQNO;
  128. if (wine_server_call_err( req ))
  129. {
  130. ERR("Failed to set clipboard.\n");
  131. }
  132. else
  133. {
  134. bRet = TRUE;
  135. }
  136. }
  137. SERVER_END_REQ;
  138. return bRet;
  139. }
  140. /**************************************************************************
  141. * CLIPBOARD_OpenClipboard
  142. */
  143. static BOOL CLIPBOARD_OpenClipboard(HWND hWnd)
  144. {
  145. BOOL bRet = FALSE;
  146. SERVER_START_REQ( set_clipboard_info )
  147. {
  148. req->flags = SET_CB_OPEN;
  149. req->clipboard = WIN_GetFullHandle( hWnd );
  150. if (!wine_server_call( req ))
  151. bRet = TRUE;
  152. }
  153. SERVER_END_REQ;
  154. return bRet;
  155. }
  156. /**************************************************************************
  157. * CLIPBOARD_CloseClipboard
  158. */
  159. static BOOL CLIPBOARD_CloseClipboard(void)
  160. {
  161. BOOL bRet = FALSE;
  162. TRACE(" Changed=%d\n", bCBHasChanged);
  163. SERVER_START_REQ( set_clipboard_info )
  164. {
  165. req->flags = SET_CB_CLOSE;
  166. if (bCBHasChanged)
  167. {
  168. req->flags |= SET_CB_SEQNO;
  169. TRACE("Clipboard data changed\n");
  170. }
  171. if (wine_server_call_err( req ))
  172. {
  173. ERR("Failed to set clipboard.\n");
  174. }
  175. else
  176. {
  177. bRet = TRUE;
  178. }
  179. }
  180. SERVER_END_REQ;
  181. return bRet;
  182. }
  183. /**************************************************************************
  184. * WIN32 Clipboard implementation
  185. **************************************************************************/
  186. /**************************************************************************
  187. * RegisterClipboardFormatW (USER32.@)
  188. */
  189. UINT WINAPI RegisterClipboardFormatW(LPCWSTR FormatName)
  190. {
  191. UINT wFormatID = 0;
  192. TRACE("%s\n", debugstr_w(FormatName));
  193. if (USER_Driver.pRegisterClipboardFormat)
  194. wFormatID = USER_Driver.pRegisterClipboardFormat(FormatName);
  195. return wFormatID;
  196. }
  197. /**************************************************************************
  198. * RegisterClipboardFormatA (USER32.@)
  199. */
  200. UINT WINAPI RegisterClipboardFormatA(LPCSTR formatName)
  201. {
  202. int len;
  203. LPWSTR wFormat;
  204. UINT ret;
  205. len = MultiByteToWideChar(CP_ACP, 0, formatName, -1, NULL, 0);
  206. wFormat = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
  207. MultiByteToWideChar(CP_ACP, 0, formatName, -1, wFormat, len);
  208. ret = RegisterClipboardFormatW(wFormat);
  209. HeapFree(GetProcessHeap(), 0, wFormat);
  210. return ret;
  211. }
  212. /**************************************************************************
  213. * GetClipboardFormatNameW (USER32.@)
  214. */
  215. INT WINAPI GetClipboardFormatNameW(UINT wFormat, LPWSTR retStr, INT maxlen)
  216. {
  217. INT len = 0;
  218. TRACE("%04x,%p,%d\n", wFormat, retStr, maxlen);
  219. if (USER_Driver.pGetClipboardFormatName)
  220. len = USER_Driver.pGetClipboardFormatName(wFormat, retStr, maxlen);
  221. return len;
  222. }
  223. /**************************************************************************
  224. * GetClipboardFormatNameA (USER32.@)
  225. */
  226. INT WINAPI GetClipboardFormatNameA(UINT wFormat, LPSTR retStr, INT maxlen)
  227. {
  228. INT ret;
  229. LPWSTR p = HeapAlloc( GetProcessHeap(), 0, maxlen*sizeof(WCHAR) );
  230. if(p == NULL) return 0; /* FIXME: is this the correct failure value? */
  231. ret = GetClipboardFormatNameW( wFormat, p, maxlen );
  232. if (maxlen > 0 && !WideCharToMultiByte( CP_ACP, 0, p, -1, retStr, maxlen, 0, 0))
  233. retStr[maxlen-1] = 0;
  234. HeapFree( GetProcessHeap(), 0, p );
  235. return ret;
  236. }
  237. /**************************************************************************
  238. * OpenClipboard (USER32.@)
  239. *
  240. * Note: Netscape uses NULL hWnd to open the clipboard.
  241. */
  242. BOOL WINAPI OpenClipboard( HWND hWnd )
  243. {
  244. BOOL bRet;
  245. TRACE("(%p)...\n", hWnd);
  246. bRet = CLIPBOARD_OpenClipboard(hWnd);
  247. TRACE(" returning %i\n", bRet);
  248. return bRet;
  249. }
  250. /**************************************************************************
  251. * CloseClipboard (USER32.@)
  252. */
  253. BOOL WINAPI CloseClipboard(void)
  254. {
  255. BOOL bRet = FALSE;
  256. TRACE("(%d)\n", bCBHasChanged);
  257. if (CLIPBOARD_CloseClipboard())
  258. {
  259. if (bCBHasChanged)
  260. {
  261. HWND hWndViewer = GetClipboardViewer();
  262. if (USER_Driver.pEndClipboardUpdate)
  263. USER_Driver.pEndClipboardUpdate();
  264. if (hWndViewer)
  265. SendMessageW(hWndViewer, WM_DRAWCLIPBOARD, 0, 0);
  266. bCBHasChanged = FALSE;
  267. }
  268. bRet = TRUE;
  269. }
  270. return bRet;
  271. }
  272. /**************************************************************************
  273. * EmptyClipboard (USER32.@)
  274. * Empties and acquires ownership of the clipboard
  275. */
  276. BOOL WINAPI EmptyClipboard(void)
  277. {
  278. CLIPBOARDINFO cbinfo;
  279. TRACE("()\n");
  280. if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
  281. ~cbinfo.flags & CB_OPEN)
  282. {
  283. WARN("Clipboard not opened by calling task!\n");
  284. SetLastError(ERROR_CLIPBOARD_NOT_OPEN);
  285. return FALSE;
  286. }
  287. /* Destroy private objects */
  288. if (cbinfo.hWndOwner)
  289. SendMessageW(cbinfo.hWndOwner, WM_DESTROYCLIPBOARD, 0, 0);
  290. /* Tell the driver to acquire the selection. The current owner
  291. * will be signaled to delete it's own cache. */
  292. /* Assign ownership of the clipboard to the current client. We do
  293. * this before acquiring the selection so that when we do acquire the
  294. * selection and the selection loser gets notified, it can check if
  295. * it has lost the Wine clipboard ownership. If it did then it knows
  296. * that a WM_DESTORYCLIPBOARD has already been sent. Otherwise it
  297. * lost the selection to a X app and it should send the
  298. * WM_DESTROYCLIPBOARD itself. */
  299. CLIPBOARD_SetClipboardOwner(cbinfo.hWndOpen);
  300. /* Acquire the selection. This will notify the previous owner
  301. * to clear it's cache. */
  302. if (USER_Driver.pAcquireClipboard)
  303. USER_Driver.pAcquireClipboard(cbinfo.hWndOpen);
  304. /* Empty the local cache */
  305. if (USER_Driver.pEmptyClipboard)
  306. USER_Driver.pEmptyClipboard(FALSE);
  307. bCBHasChanged = TRUE;
  308. return TRUE;
  309. }
  310. /**************************************************************************
  311. * GetClipboardOwner (USER32.@)
  312. * FIXME: Can't return the owner if the clipboard is owned by an external X-app
  313. */
  314. HWND WINAPI GetClipboardOwner(void)
  315. {
  316. HWND hWndOwner = 0;
  317. SERVER_START_REQ( set_clipboard_info )
  318. {
  319. req->flags = 0;
  320. if (!wine_server_call_err( req )) hWndOwner = reply->old_owner;
  321. }
  322. SERVER_END_REQ;
  323. TRACE(" hWndOwner(%p)\n", hWndOwner);
  324. return hWndOwner;
  325. }
  326. /**************************************************************************
  327. * GetOpenClipboardWindow (USER32.@)
  328. */
  329. HWND WINAPI GetOpenClipboardWindow(void)
  330. {
  331. HWND hWndOpen = 0;
  332. SERVER_START_REQ( set_clipboard_info )
  333. {
  334. req->flags = 0;
  335. if (!wine_server_call_err( req )) hWndOpen = reply->old_clipboard;
  336. }
  337. SERVER_END_REQ;
  338. TRACE(" hWndClipWindow(%p)\n", hWndOpen);
  339. return hWndOpen;
  340. }
  341. /**************************************************************************
  342. * SetClipboardViewer (USER32.@)
  343. */
  344. HWND WINAPI SetClipboardViewer( HWND hWnd )
  345. {
  346. HWND hwndPrev = 0;
  347. SERVER_START_REQ( set_clipboard_info )
  348. {
  349. req->flags = SET_CB_VIEWER;
  350. req->viewer = WIN_GetFullHandle(hWnd);
  351. if (wine_server_call_err( req ))
  352. {
  353. ERR("Failed to set clipboard.\n");
  354. }
  355. else
  356. {
  357. hwndPrev = reply->old_viewer;
  358. }
  359. }
  360. SERVER_END_REQ;
  361. TRACE("(%p): returning %p\n", hWnd, hwndPrev);
  362. return hwndPrev;
  363. }
  364. /**************************************************************************
  365. * GetClipboardViewer (USER32.@)
  366. */
  367. HWND WINAPI GetClipboardViewer(void)
  368. {
  369. HWND hWndViewer = 0;
  370. SERVER_START_REQ( set_clipboard_info )
  371. {
  372. req->flags = 0;
  373. if (!wine_server_call_err( req )) hWndViewer = reply->old_viewer;
  374. }
  375. SERVER_END_REQ;
  376. TRACE(" hWndViewer=%p\n", hWndViewer);
  377. return hWndViewer;
  378. }
  379. /**************************************************************************
  380. * ChangeClipboardChain (USER32.@)
  381. */
  382. BOOL WINAPI ChangeClipboardChain(HWND hWnd, HWND hWndNext)
  383. {
  384. BOOL bRet = TRUE;
  385. HWND hWndViewer = GetClipboardViewer();
  386. if (hWndViewer)
  387. {
  388. if (WIN_GetFullHandle(hWnd) == hWndViewer)
  389. SetClipboardViewer(WIN_GetFullHandle(hWndNext));
  390. else
  391. bRet = !SendMessageW(hWndViewer, WM_CHANGECBCHAIN, (WPARAM)hWnd, (LPARAM)hWndNext);
  392. }
  393. else
  394. ERR("hWndViewer is lost\n");
  395. return bRet;
  396. }
  397. /**************************************************************************
  398. * SetClipboardData (USER.141)
  399. */
  400. HANDLE16 WINAPI SetClipboardData16(UINT16 wFormat, HANDLE16 hData)
  401. {
  402. CLIPBOARDINFO cbinfo;
  403. HANDLE16 hResult = 0;
  404. TRACE("(%04X, %04x) !\n", wFormat, hData);
  405. /* If it's not owned, data can only be set if the format doesn't exists
  406. and its rendering is not delayed */
  407. if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
  408. (!(cbinfo.flags & CB_OWNER) && !hData))
  409. {
  410. WARN("Clipboard not owned by calling task. Operation failed.\n");
  411. return 0;
  412. }
  413. if (USER_Driver.pSetClipboardData &&
  414. USER_Driver.pSetClipboardData(wFormat, hData, 0, cbinfo.flags & CB_OWNER))
  415. {
  416. hResult = hData;
  417. bCBHasChanged = TRUE;
  418. }
  419. return hResult;
  420. }
  421. /**************************************************************************
  422. * SetClipboardData (USER32.@)
  423. */
  424. HANDLE WINAPI SetClipboardData(UINT wFormat, HANDLE hData)
  425. {
  426. CLIPBOARDINFO cbinfo;
  427. HANDLE hResult = 0;
  428. TRACE("(%04X, %p) !\n", wFormat, hData);
  429. /* If it's not owned, data can only be set if the format isn't
  430. available and its rendering is not delayed */
  431. if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
  432. (!(cbinfo.flags & CB_OWNER) && !hData))
  433. {
  434. WARN("Clipboard not owned by calling task. Operation failed.\n");
  435. return 0;
  436. }
  437. if (USER_Driver.pSetClipboardData &&
  438. USER_Driver.pSetClipboardData(wFormat, 0, hData, cbinfo.flags & CB_OWNER))
  439. {
  440. hResult = hData;
  441. bCBHasChanged = TRUE;
  442. }
  443. return hResult;
  444. }
  445. /**************************************************************************
  446. * CountClipboardFormats (USER32.@)
  447. */
  448. INT WINAPI CountClipboardFormats(void)
  449. {
  450. INT count = 0;
  451. if (USER_Driver.pCountClipboardFormats)
  452. count = USER_Driver.pCountClipboardFormats();
  453. TRACE("returning %d\n", count);
  454. return count;
  455. }
  456. /**************************************************************************
  457. * EnumClipboardFormats (USER32.@)
  458. */
  459. UINT WINAPI EnumClipboardFormats(UINT wFormat)
  460. {
  461. UINT wFmt = 0;
  462. CLIPBOARDINFO cbinfo;
  463. TRACE("(%04X)\n", wFormat);
  464. if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
  465. (~cbinfo.flags & CB_OPEN))
  466. {
  467. WARN("Clipboard not opened by calling task.\n");
  468. SetLastError(ERROR_CLIPBOARD_NOT_OPEN);
  469. return 0;
  470. }
  471. if (USER_Driver.pEnumClipboardFormats)
  472. wFmt = USER_Driver.pEnumClipboardFormats(wFormat);
  473. return wFmt;
  474. }
  475. /**************************************************************************
  476. * IsClipboardFormatAvailable (USER32.@)
  477. */
  478. BOOL WINAPI IsClipboardFormatAvailable(UINT wFormat)
  479. {
  480. BOOL bret = FALSE;
  481. if (USER_Driver.pIsClipboardFormatAvailable)
  482. bret = USER_Driver.pIsClipboardFormatAvailable(wFormat);
  483. TRACE("%04x, returning %d\n", wFormat, bret);
  484. return bret;
  485. }
  486. /**************************************************************************
  487. * GetClipboardData (USER.142)
  488. */
  489. HANDLE16 WINAPI GetClipboardData16(UINT16 wFormat)
  490. {
  491. HANDLE16 hData = 0;
  492. CLIPBOARDINFO cbinfo;
  493. if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
  494. (~cbinfo.flags & CB_OPEN))
  495. {
  496. WARN("Clipboard not opened by calling task.\n");
  497. SetLastError(ERROR_CLIPBOARD_NOT_OPEN);
  498. return 0;
  499. }
  500. if (USER_Driver.pGetClipboardData)
  501. USER_Driver.pGetClipboardData(wFormat, &hData, NULL);
  502. return hData;
  503. }
  504. /**************************************************************************
  505. * GetClipboardData (USER32.@)
  506. */
  507. HANDLE WINAPI GetClipboardData(UINT wFormat)
  508. {
  509. HANDLE hData = 0;
  510. CLIPBOARDINFO cbinfo;
  511. TRACE("%04x\n", wFormat);
  512. if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
  513. (~cbinfo.flags & CB_OPEN))
  514. {
  515. WARN("Clipboard not opened by calling task.\n");
  516. SetLastError(ERROR_CLIPBOARD_NOT_OPEN);
  517. return 0;
  518. }
  519. if (USER_Driver.pGetClipboardData)
  520. USER_Driver.pGetClipboardData(wFormat, NULL, &hData);
  521. TRACE("returning %p\n", hData);
  522. return hData;
  523. }
  524. /**************************************************************************
  525. * GetPriorityClipboardFormat (USER32.@)
  526. */
  527. INT WINAPI GetPriorityClipboardFormat(UINT *list, INT nCount)
  528. {
  529. int i;
  530. TRACE("()\n");
  531. if(CountClipboardFormats() == 0)
  532. return 0;
  533. for (i = 0; i < nCount; i++)
  534. if (IsClipboardFormatAvailable(list[i]))
  535. return list[i];
  536. return -1;
  537. }
  538. /**************************************************************************
  539. * GetClipboardSequenceNumber (USER32.@)
  540. * Supported on Win2k/Win98
  541. * MSDN: Windows clipboard code keeps a serial number for the clipboard
  542. * for each window station. The number is incremented whenever the
  543. * contents change or are emptied.
  544. * If you do not have WINSTA_ACCESSCLIPBOARD then the function returns 0
  545. */
  546. DWORD WINAPI GetClipboardSequenceNumber(VOID)
  547. {
  548. DWORD seqno = 0;
  549. SERVER_START_REQ( set_clipboard_info )
  550. {
  551. req->flags = 0;
  552. if (!wine_server_call_err( req )) seqno = reply->seqno;
  553. }
  554. SERVER_END_REQ;
  555. TRACE("returning %lx\n", seqno);
  556. return seqno;
  557. }