OSDN Git Service

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