OSDN Git Service

* fhandler.h (fhandler_dev_clipboard): Extend to support writing.
authorcgf <cgf>
Thu, 22 Mar 2001 22:11:33 +0000 (22:11 +0000)
committercgf <cgf>
Thu, 22 Mar 2001 22:11:33 +0000 (22:11 +0000)
* 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.

winsup/cygwin/ChangeLog
winsup/cygwin/autoload.cc
winsup/cygwin/fhandler.h
winsup/cygwin/fhandler_clipboard.cc

index 53817be..814a876 100644 (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
index c4b3711..831414b 100644 (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)
 
index 90ded24..239aa86 100644 (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
index 7b6d053..2070037 100644 (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;
 }
 
+static int
+set_clipboard (const void *buf, size_t 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 *, size_t len)
+fhandler_dev_clipboard::write (const void *buf, size_t len)
 {
-  return 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;
-        }
-
-      ret = snprintf((char *) ptr, len, "%s", lpstr);
-      GlobalUnlock(hglb);
-      CloseClipboard();
-      set_errno (0);
-      clipboard_eof = true;
-      return ret;
+      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 =
+               ((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");
 }