* fhandler.h (fhandler_dev_clipboard): Extend to support writing.

* fhandler_clipboard.cc (fhandler_dev_clipboard::fhandler_dev_clipboard):
Initialize new fields.  Open clipboard here.
(fhandler_dev_clipboard::dup): New method.
(fhandler_dev_clipboard::open): Accomodate new fields.  Register clipboard
here, if appropriate.
(set_clipboard): New function.  Moves buffer to clipboard.
(fhandler_dev_clipboard::write): Truly implement clipboard writing.
(fhandler_dev_clipboard::read): Reimplement to allow successive reads.
(fhandler_dev_clipboard::lseek): Truly implement seeks in clipboard.
(fhandler_dev_clipboard::close): Clear out new fields.  Support sequential
reads and sequential writes.  Support for binary data via a native clipboard
format.
This commit is contained in:
Christopher Faylor 2001-03-22 22:11:34 +00:00
parent 0b30bad456
commit db0421f6ec
4 changed files with 247 additions and 31 deletions

View File

@ -1,3 +1,21 @@
Thursday Mar 22 2001 Robert Collins <rbtcollins@hotmail.com>
* fhandler.h (fhandler_dev_clipboard): Extend to support writing.
* fhandler_clipboard.cc (fhandler_dev_clipboard::fhandler_dev_clipboard):
Initialize new fields. Open clipboard here.
(fhandler_dev_clipboard::dup): New method.
(fhandler_dev_clipboard::open): Accomodate new fields. Register
clipboard here, if appropriate.
(set_clipboard): New function. Moves buffer to clipboard.
(fhandler_dev_clipboard::write): Truly implement clipboard writing.
(fhandler_dev_clipboard::read): Reimplement to allow successive reads.
(fhandler_dev_clipboard::lseek): Truly implement seeks in clipboard.
(fhandler_dev_clipboard::close): Clear out new fields.
Support sequential
reads and sequential writes. Support for binary data via a native
clipboard format.
2001-03-22 Egor Duda <deo@logos-m.ru>
* fhandler_console.cc (fhandler_console::set_default_attr): Update

View File

@ -319,10 +319,12 @@ LoadDLLfunc (CloseClipboard, 0, user32)
LoadDLLfunc (CreateWindowExA, 48, user32)
LoadDLLfunc (DefWindowProcA, 16, user32)
LoadDLLfunc (DispatchMessageA, 4, user32)
LoadDLLfunc (EmptyClipboard, 0, user32)
LoadDLLfunc (FindWindowA, 8, user32)
LoadDLLfunc (GetClipboardData, 4, user32)
LoadDLLfunc (GetKeyboardLayout, 4, user32)
LoadDLLfunc (GetMessageA, 16, user32)
LoadDLLfunc (GetPriorityClipboardFormat, 8, user32)
LoadDLLfunc (GetProcessWindowStation, 0, user32)
LoadDLLfunc (GetThreadDesktop, 4, user32)
LoadDLLfunc (GetUserObjectInformationA, 20, user32)
@ -335,7 +337,9 @@ LoadDLLfunc (PeekMessageA, 20, user32)
LoadDLLfunc (PostMessageA, 16, user32)
LoadDLLfunc (PostQuitMessage, 4, user32)
LoadDLLfunc (RegisterClassA, 4, user32)
LoadDLLfunc (RegisterClipboardFormatA, 4, user32)
LoadDLLfunc (SendMessageA, 16, user32)
LoadDLLfunc (SetClipboardData, 8, user32)
LoadDLLfunc (SetTimer, 16, user32)
LoadDLLfunc (SetUserObjectSecurity, 12, user32)

View File

@ -895,7 +895,15 @@ public:
off_t lseek (off_t offset, int whence);
int close (void);
int dup (fhandler_base *child);
void dump ();
private:
off_t pos;
void *membuffer;
size_t msize;
BOOL eof;
};
class fhandler_windows: public fhandler_base

View File

@ -1,6 +1,6 @@
/* fhandler_dev_clipboard: code to access /dev/clipboard
Copyright 2000 Red Hat, Inc
Copyright 2000, 2001 Red Hat, Inc
Written by Charles Wilson (cwilson@ece.gatech.edu)
@ -12,62 +12,235 @@ details. */
#include "winsup.h"
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include "cygerrno.h"
#include "fhandler.h"
#include <windows.h>
#include <wingdi.h>
#include <winuser.h>
static BOOL clipboard_eof; // NOT THREAD-SAFE
/*
* Robert Collins:
* FIXME: should we use GetClipboardSequenceNumber to tell if the clipboard has
* changed? How does /dev/clipboard operate under (say) linux?
*/
fhandler_dev_clipboard::fhandler_dev_clipboard (const char *name)
: fhandler_base (FH_CLIPBOARD, name)
static const char *CYGWIN_NATIVE = "CYGWIN_NATIVE_CLIPBOARD";
/* this is MT safe because windows format id's are atomic */
static UINT cygnativeformat = 0;
fhandler_dev_clipboard::fhandler_dev_clipboard (const char *name):
fhandler_base (FH_CLIPBOARD, name)
{
set_cb (sizeof *this);
clipboard_eof = false;
eof = true;
pos = 0;
membuffer = NULL;
msize = 0;
/* FIXME: check for errors and loop until we can open the clipboard */
OpenClipboard (NULL);
cygnativeformat = RegisterClipboardFormat (CYGWIN_NATIVE);
CloseClipboard ();
}
/*
* Special clipboard dup to duplicate input and output
* handles.
*/
int
fhandler_dev_clipboard::dup (fhandler_base * child)
{
fhandler_dev_clipboard *fhc = (fhandler_dev_clipboard *) child;
if (!fhc->open (get_name (), get_flags (), 0))
system_printf ("error opening clipboard, %E");
fhc->membuffer = membuffer;
fhc->pos = pos;
fhc->msize = msize;
return 0;
}
int
fhandler_dev_clipboard::open (const char *, int flags, mode_t)
{
set_flags (flags);
clipboard_eof = false;
eof = false;
pos = 0;
if (membuffer)
free (membuffer);
membuffer = NULL;
if (!cygnativeformat)
cygnativeformat = RegisterClipboardFormat (CYGWIN_NATIVE);
return 1;
}
int
fhandler_dev_clipboard::write (const void *, size_t len)
static int
set_clipboard (const void *buf, size_t len)
{
return len;
HGLOBAL hmem;
unsigned char *clipbuf;
/* Native CYGWIN format */
OpenClipboard (0);
hmem = GlobalAlloc (GMEM_MOVEABLE, len + sizeof (size_t));
if (!hmem)
{
system_printf ("Couldn't allocate global buffer for write\n");
return -1;
}
clipbuf = (unsigned char *) GlobalLock (hmem);
memcpy (clipbuf + sizeof (size_t), buf, len);
*(size_t *) (clipbuf) = len;
GlobalUnlock (hmem);
EmptyClipboard ();
if (!cygnativeformat)
cygnativeformat = RegisterClipboardFormat (CYGWIN_NATIVE);
if (!SetClipboardData (cygnativeformat, hmem))
{
system_printf
("Couldn't write native format to the clipboard %04x %x\n",
cygnativeformat, hmem);
/* FIXME: return an appriate error code &| set_errno(); */
return -1;
}
CloseClipboard ();
if (GlobalFree (hmem))
{
system_printf
("Couldn't free global buffer after write to the clipboard\n");
/* FIXME: return an appriate error code &| set_errno(); */
return 0;
}
/* CF_TEXT/CF_OEMTEXT for copying to wordpad and the like */
OpenClipboard (0);
hmem = GlobalAlloc (GMEM_MOVEABLE, len + 2);
if (!hmem)
{
system_printf ("Couldn't allocate global buffer for write\n");
return -1;
}
clipbuf = (unsigned char *) GlobalLock (hmem);
memcpy (clipbuf, buf, len);
*(clipbuf + len) = '\0';
*(clipbuf + len + 1) = '\0';
GlobalUnlock (hmem);
if (!SetClipboardData
((current_codepage == ansi_cp ? CF_TEXT : CF_OEMTEXT), hmem))
{
system_printf ("Couldn't write to the clipboard\n");
/* FIXME: return an appriate error code &| set_errno(); */
return -1;
}
CloseClipboard ();
if (GlobalFree (hmem))
{
system_printf
("Couldn't free global buffer after write to the clipboard\n");
/* FIXME: return an appriate error code &| set_errno(); */
}
return 0;
}
/* FIXME: arbitrary seeking is not handled */
int
fhandler_dev_clipboard::write (const void *buf, size_t len)
{
if (!eof)
{
/* write to our membuffer */
size_t cursize = msize;
void *tempbuffer = realloc (membuffer, cursize + len);
if (!tempbuffer)
{
system_printf ("Couldn't realloc() clipboard buffer for write\n");
return -1;
}
membuffer = tempbuffer;
msize = cursize + len;
memcpy ((unsigned char *) membuffer + cursize, buf, len);
/* now pass to windows */
if (set_clipboard (membuffer, msize))
{
/* FIXME: membuffer is now out of sync with pos, but msize is used above */
set_errno (ENOSPC);
return -1;
}
pos = msize;
set_errno (0);
eof = false;
return len;
}
else
{
/* FIXME: return 0 bytes written, file not open */
return 0;
}
}
int
fhandler_dev_clipboard::read (void *ptr, size_t len)
{
HGLOBAL hglb;
LPSTR lpstr;
int ret;
if (!clipboard_eof)
size_t ret;
UINT formatlist[2];
UINT format;
if (!eof)
{
OpenClipboard(0);
hglb = GetClipboardData((current_codepage==ansi_cp ? CF_TEXT : CF_OEMTEXT));
lpstr = (LPSTR) GlobalLock(hglb);
if (len < sizeof (lpstr))
{
set_errno (EINVAL);
GlobalUnlock (hglb);
CloseClipboard ();
return -1;
}
formatlist[0] = cygnativeformat;
formatlist[1] = current_codepage == ansi_cp ? CF_TEXT : CF_OEMTEXT;
OpenClipboard (0);
if ((format = GetPriorityClipboardFormat (formatlist, 2)) > 0)
{
hglb = GetClipboardData (format);
if (format == cygnativeformat)
{
unsigned char *buf = (unsigned char *) GlobalLock (hglb);
size_t buflen = (*(size_t *) buf);
ret = ((len > (buflen - pos)) ? (buflen - pos) : len);
memcpy (ptr, buf + sizeof (size_t)+ pos , ret);
pos += ret;
if (pos + len - ret >= buflen)
eof = true;
GlobalUnlock (hglb);
}
else
{
LPSTR lpstr;
lpstr = (LPSTR) GlobalLock (hglb);
ret = snprintf((char *) ptr, len, "%s", lpstr);
GlobalUnlock(hglb);
CloseClipboard();
set_errno (0);
clipboard_eof = true;
return ret;
ret =
((len > (strlen (lpstr) - pos)) ? (strlen (lpstr) - pos) :
len);
memcpy (ptr, lpstr + pos, ret);
//ret = snprintf((char *) ptr, len, "%s", lpstr);//+pos);
pos += ret;
if (pos + len - ret >= strlen (lpstr))
eof = true;
GlobalUnlock (hglb);
}
CloseClipboard ();
set_errno (0);
return ret;
}
else
{
CloseClipboard ();
#if 0
system_printf ("a non-accepted format! %d\n", format);
#endif
set_errno (0);
return 0;
}
}
else
{
@ -78,18 +251,31 @@ fhandler_dev_clipboard::read (void *ptr, size_t len)
off_t
fhandler_dev_clipboard::lseek (off_t offset, int whence)
{
/* On reads we check this at read time, not seek time.
* On writes we use this to decide how to write - empty and write, or open, copy, empty
* and write
*/
pos = offset;
/* treat seek like rewind */
if (membuffer)
free (membuffer);
msize = 0;
return 0;
}
int
fhandler_dev_clipboard::close (void)
{
clipboard_eof = false;
eof = true;
pos = 0;
if (membuffer)
free (membuffer);
msize = 0;
return 0;
}
void
fhandler_dev_clipboard::dump ()
{
paranoid_printf("here, fhandler_dev_clipboard");
paranoid_printf ("here, fhandler_dev_clipboard");
}