1 /* fhandler_dev_clipboard: code to access /dev/clipboard
3 Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009, 2011 Red Hat, Inc
5 Written by Charles Wilson (cwilson@ece.gatech.edu)
7 This file is part of Cygwin.
9 This software is a copyrighted work licensed under the terms of the
10 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
23 * FIXME: should we use GetClipboardSequenceNumber to tell if the clipboard has
24 * changed? How does /dev/clipboard operate under (say) linux?
27 static const NO_COPY WCHAR *CYGWIN_NATIVE = L"CYGWIN_NATIVE_CLIPBOARD";
28 /* this is MT safe because windows format id's are atomic */
29 static int cygnativeformat;
31 fhandler_dev_clipboard::fhandler_dev_clipboard ()
32 : fhandler_base (), pos (0), membuffer (NULL), msize (0),
35 /* FIXME: check for errors and loop until we can open the clipboard */
37 cygnativeformat = RegisterClipboardFormatW (CYGWIN_NATIVE);
42 * Special clipboard dup to duplicate input and output
47 fhandler_dev_clipboard::dup (fhandler_base * child, int)
49 fhandler_dev_clipboard *fhc = (fhandler_dev_clipboard *) child;
51 if (!fhc->open (get_flags (), 0))
52 system_printf ("error opening clipboard, %E");
57 fhandler_dev_clipboard::open (int flags, mode_t)
59 set_flags (flags | O_TEXT);
66 cygnativeformat = RegisterClipboardFormatW (CYGWIN_NATIVE);
73 set_clipboard (const void *buf, size_t len)
77 /* Native CYGWIN format */
78 if (OpenClipboard (NULL))
80 hmem = GlobalAlloc (GMEM_MOVEABLE, len + sizeof (size_t));
87 clipbuf = GlobalLock (hmem);
88 memcpy ((unsigned char *) clipbuf + sizeof (size_t), buf, len);
89 *(size_t *) (clipbuf) = len;
93 cygnativeformat = RegisterClipboardFormatW (CYGWIN_NATIVE);
94 HANDLE ret = SetClipboardData (cygnativeformat, hmem);
96 /* According to MSDN, hmem must not be free'd after transferring the
97 data to the clipboard via SetClipboardData. */
98 /* GlobalFree (hmem); */
106 /* CF_TEXT/CF_OEMTEXT for copying to wordpad and the like */
107 len = sys_mbstowcs (NULL, 0, (const char *) buf, len);
113 if (OpenClipboard (NULL))
115 hmem = GlobalAlloc (GMEM_MOVEABLE, (len + 1) * sizeof (WCHAR));
122 clipbuf = GlobalLock (hmem);
123 sys_mbstowcs ((PWCHAR) clipbuf, len + 1, (const char *) buf);
125 HANDLE ret = SetClipboardData (CF_UNICODETEXT, hmem);
127 /* According to MSDN, hmem must not be free'd after transferring the
128 data to the clipboard via SetClipboardData. */
129 /* GlobalFree (hmem); */
139 /* FIXME: arbitrary seeking is not handled */
141 fhandler_dev_clipboard::write (const void *buf, size_t len)
145 /* write to our membuffer */
146 size_t cursize = msize;
147 void *tempbuffer = realloc (membuffer, cursize + len);
150 debug_printf ("Couldn't realloc() clipboard buffer for write");
153 membuffer = tempbuffer;
154 msize = cursize + len;
155 memcpy ((unsigned char *) membuffer + cursize, buf, len);
157 /* now pass to windows */
158 if (set_clipboard (membuffer, msize))
160 /* FIXME: membuffer is now out of sync with pos, but msize
172 /* FIXME: return 0 bytes written, file not open */
178 fhandler_dev_clipboard::read (void *ptr, size_t& len)
189 if (!OpenClipboard (NULL))
191 formatlist[0] = cygnativeformat;
192 formatlist[1] = CF_UNICODETEXT;
193 if ((format = GetPriorityClipboardFormat (formatlist, 2)) <= 0)
198 if (!(hglb = GetClipboardData (format)))
203 if (format == cygnativeformat)
207 if (!(buf = (unsigned char *) GlobalLock (hglb)))
212 size_t buflen = (*(size_t *) buf);
213 ret = ((plen > (buflen - pos)) ? (buflen - pos) : plen);
214 memcpy (ptr, buf + sizeof (size_t)+ pos , ret);
216 if (pos + plen - ret >= buflen)
224 if (!(buf = (PWCHAR) GlobalLock (hglb)))
229 size_t glen = GlobalSize (hglb) / sizeof (WCHAR) - 1;
230 /* This loop is necessary because the number of bytes returned by
231 sys_wcstombs does not indicate the number of wide chars used for
232 it, so we could potentially drop wide chars. */
233 if (glen - pos > plen)
235 while ((wret = sys_wcstombs (NULL, 0, buf + pos, glen - pos)) != -1
236 && (size_t) wret > plen)
238 ret = sys_wcstombs ((char *) ptr, plen, buf + pos, glen - pos);
240 if (pos + plen - ret >= wcslen (buf))
249 fhandler_dev_clipboard::lseek (_off64_t offset, int whence)
251 /* On reads we check this at read time, not seek time.
252 * On writes we use this to decide how to write - empty and write, or open, copy, empty
256 /* treat seek like rewind */
264 fhandler_dev_clipboard::close ()
281 fhandler_dev_clipboard::fixup_after_exec ()
283 if (!close_on_exec ())