OSDN Git Service

Revert erroneous checkin.
[pf3gnuchains/sourceware.git] / winsup / cygwin / fhandler_clipboard.cc
1 /* fhandler_dev_clipboard: code to access /dev/clipboard
2
3    Copyright 2000, 2001, 2002, 2003, 2004, 2005 Red Hat, Inc
4
5    Written by Charles Wilson (cwilson@ece.gatech.edu)
6
7 This file is part of Cygwin.
8
9 This software is a copyrighted work licensed under the terms of the
10 Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
11 details. */
12
13 #include "winsup.h"
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <unistd.h>
17 #include <windows.h>
18 #include <wingdi.h>
19 #include <winuser.h>
20 #include "cygerrno.h"
21 #include "security.h"
22 #include "path.h"
23 #include "fhandler.h"
24
25 /*
26  * Robert Collins:
27  * FIXME: should we use GetClipboardSequenceNumber to tell if the clipboard has
28  * changed? How does /dev/clipboard operate under (say) linux?
29  */
30
31 static const NO_COPY char *CYGWIN_NATIVE = "CYGWIN_NATIVE_CLIPBOARD";
32 /* this is MT safe because windows format id's are atomic */
33 static int cygnativeformat;
34
35 fhandler_dev_clipboard::fhandler_dev_clipboard ()
36   : fhandler_base (), pos (0), membuffer (NULL), msize (0),
37   eof (true)
38 {
39   /* FIXME: check for errors and loop until we can open the clipboard */
40   OpenClipboard (NULL);
41   cygnativeformat = RegisterClipboardFormat (CYGWIN_NATIVE);
42   CloseClipboard ();
43 }
44
45 /*
46  * Special clipboard dup to duplicate input and output
47  * handles.
48  */
49
50 int
51 fhandler_dev_clipboard::dup (fhandler_base * child)
52 {
53   fhandler_dev_clipboard *fhc = (fhandler_dev_clipboard *) child;
54
55   if (!fhc->open (get_flags (), 0))
56     system_printf ("error opening clipboard, %E");
57
58   fhc->membuffer = membuffer;
59   fhc->pos = pos;
60   fhc->msize = msize;
61
62   return 0;
63 }
64
65 int
66 fhandler_dev_clipboard::open (int flags, mode_t)
67 {
68   set_flags (flags | O_TEXT);
69   eof = false;
70   pos = 0;
71   if (membuffer)
72     free (membuffer);
73   membuffer = NULL;
74   if (!cygnativeformat)
75     cygnativeformat = RegisterClipboardFormat (CYGWIN_NATIVE);
76   nohandle (true);
77   set_open_status ();
78   return 1;
79 }
80
81 static int
82 set_clipboard (const void *buf, size_t len)
83 {
84   HGLOBAL hmem;
85   unsigned char *clipbuf;
86   /* Native CYGWIN format */
87   OpenClipboard (0);
88   hmem = GlobalAlloc (GMEM_MOVEABLE, len + sizeof (size_t));
89   if (!hmem)
90     {
91       system_printf ("Couldn't allocate global buffer for write");
92       return -1;
93     }
94   clipbuf = (unsigned char *) GlobalLock (hmem);
95   memcpy (clipbuf + sizeof (size_t), buf, len);
96   *(size_t *) (clipbuf) = len;
97   GlobalUnlock (hmem);
98   EmptyClipboard ();
99   if (!cygnativeformat)
100     cygnativeformat = RegisterClipboardFormat (CYGWIN_NATIVE);
101   if (!SetClipboardData (cygnativeformat, hmem))
102     {
103       system_printf
104         ("Couldn't write native format to the clipboard %04x %x",
105          cygnativeformat, hmem);
106 /* FIXME: return an appriate error code &| set_errno(); */
107       return -1;
108     }
109   CloseClipboard ();
110   if (GlobalFree (hmem))
111     {
112       system_printf
113         ("Couldn't free global buffer after write to the clipboard");
114 /* FIXME: return an appriate error code &| set_errno(); */
115       return 0;
116     }
117
118   /* CF_TEXT/CF_OEMTEXT for copying to wordpad and the like */
119
120   OpenClipboard (0);
121   hmem = GlobalAlloc (GMEM_MOVEABLE, len + 2);
122   if (!hmem)
123     {
124       system_printf ("Couldn't allocate global buffer for write");
125       return -1;
126     }
127   clipbuf = (unsigned char *) GlobalLock (hmem);
128   memcpy (clipbuf, buf, len);
129   *(clipbuf + len) = '\0';
130   *(clipbuf + len + 1) = '\0';
131   GlobalUnlock (hmem);
132   if (!SetClipboardData
133       ((current_codepage == ansi_cp ? CF_TEXT : CF_OEMTEXT), hmem))
134     {
135       system_printf ("Couldn't write to the clipboard");
136 /* FIXME: return an appriate error code &| set_errno(); */
137       return -1;
138     }
139   CloseClipboard ();
140   if (GlobalFree (hmem))
141     {
142       system_printf
143         ("Couldn't free global buffer after write to the clipboard");
144 /* FIXME: return an appriate error code &| set_errno(); */
145     }
146   return 0;
147 }
148
149 /* FIXME: arbitrary seeking is not handled */
150 int
151 fhandler_dev_clipboard::write (const void *buf, size_t len)
152 {
153   if (!eof)
154     {
155       /* write to our membuffer */
156       size_t cursize = msize;
157       void *tempbuffer = realloc (membuffer, cursize + len);
158       if (!tempbuffer)
159         {
160           system_printf ("Couldn't realloc() clipboard buffer for write");
161           return -1;
162         }
163       membuffer = tempbuffer;
164       msize = cursize + len;
165       memcpy ((unsigned char *) membuffer + cursize, buf, len);
166
167       /* now pass to windows */
168       if (set_clipboard (membuffer, msize))
169         {
170           /* FIXME: membuffer is now out of sync with pos, but msize is used above */
171           set_errno (ENOSPC);
172           return -1;
173         }
174
175       pos = msize;
176
177       eof = false;
178       return len;
179     }
180   else
181     {
182       /* FIXME: return 0 bytes written, file not open */
183       return 0;
184     }
185 }
186
187 void __stdcall
188 fhandler_dev_clipboard::read (void *ptr, size_t& len)
189 {
190   HGLOBAL hglb;
191   size_t ret;
192   UINT formatlist[2];
193   int format;
194   if (eof)
195     len = 0;
196   else
197     {
198       formatlist[0] = cygnativeformat;
199       formatlist[1] = current_codepage == ansi_cp ? CF_TEXT : CF_OEMTEXT;
200       OpenClipboard (0);
201       if ((format = GetPriorityClipboardFormat (formatlist, 2)) <= 0)
202         {
203           CloseClipboard ();
204 #if 0
205           system_printf ("a non-accepted format! %d", format);
206 #endif
207           len = 0;
208         }
209       else
210         {
211           hglb = GetClipboardData (format);
212           if (format == cygnativeformat)
213             {
214               unsigned char *buf = (unsigned char *) GlobalLock (hglb);
215               size_t buflen = (*(size_t *) buf);
216               ret = ((len > (buflen - pos)) ? (buflen - pos) : len);
217               memcpy (ptr, buf + sizeof (size_t)+ pos , ret);
218               pos += ret;
219               if (pos + len - ret >= buflen)
220                 eof = true;
221               GlobalUnlock (hglb);
222             }
223           else
224             {
225               LPSTR lpstr;
226               lpstr = (LPSTR) GlobalLock (hglb);
227
228               ret = ((len > (strlen (lpstr) - pos)) ? (strlen (lpstr) - pos)
229                      : len);
230
231               memcpy (ptr, lpstr + pos, ret);
232               //ret = snprintf((char *) ptr, len, "%s", lpstr);//+pos);
233               pos += ret;
234               if (pos + len - ret >= strlen (lpstr))
235                 eof = true;
236               GlobalUnlock (hglb);
237             }
238           CloseClipboard ();
239           len = ret;
240         }
241     }
242 }
243
244 _off64_t
245 fhandler_dev_clipboard::lseek (_off64_t offset, int whence)
246 {
247   /* On reads we check this at read time, not seek time.
248    * On writes we use this to decide how to write - empty and write, or open, copy, empty
249    * and write
250    */
251   pos = offset;
252   /* treat seek like rewind */
253   if (membuffer)
254     free (membuffer);
255   msize = 0;
256   return 0;
257 }
258
259 int
260 fhandler_dev_clipboard::close ()
261 {
262   if (!hExeced)
263     {
264       eof = true;
265       pos = 0;
266       if (membuffer)
267         {
268           free (membuffer);
269           membuffer = NULL;
270         }
271       msize = 0;
272     }
273   return 0;
274 }
275
276 void
277 fhandler_dev_clipboard::fixup_after_exec ()
278 {
279   eof = false;
280   pos = msize = 0;
281   membuffer = NULL;
282 }