[cygutils - Chuck Wilson's collection of Cygwin utilities] branch master, updated. v1_4_16-9-g6a2162a

Mark Geisert mgeisert@sourceware.org
Wed Nov 3 10:05:31 GMT 2021




https://sourceware.org/git/gitweb.cgi?p=cygwin-apps/cygutils.git;h=6a2162acab2e93a6fe9bf90907aa6656f084d19f

commit 6a2162acab2e93a6fe9bf90907aa6656f084d19f
Author: Mark Geisert <mark@maxrnd.com>
Date:   Wed Nov 3 03:05:24 2021 -0700

    Update to released 1.4.16-8 content


Diff:
---
 ChangeLog          |   8 +++
 NEWS               |   1 +
 src/clip/getclip.c |  88 +++++++++++++----------
 src/clip/putclip.c | 206 ++++++++++++++++++++++++-----------------------------
 4 files changed, 150 insertions(+), 153 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 921b9d0..98e8d40 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2021-11-03  Mark Geisert  <mark@maxrnd.com>  (1.4.16-8)
+
+	* src/clip/{get,put}clip.c: Replace use of Windows UTF-8 conversion
+	functions with corresponding POSIX functions. MultiByteToWideChar->
+	mbstowcs, WideCharToMultiByte->wcstombs. Thanks to Takashi Yano.
+	* src/putclip.c: Have putclip open the clipboard just once instead
+	of multiple times for multiple formats. Thanks to Takashi Yano.
+
 2021-09-23  Mark Geisert  <mark@maxrnd.com>  (1.4.16-7)
 
 	* src/readshortcut/readshortcut.c: Fix mbstowcs usage so no chance
diff --git a/NEWS b/NEWS
index fcfab44..f1cedc0 100644
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,7 @@
   * Unicode support added to getclip and putclip.
   * Fix mbstowcs bug in readshortcut causing "buffer overflow detected" from
     -fstack-protect at runtime.
+  * Support clipboard use between 32- and 64-bit Cygwin environments.
 
 1.4.15
   New maintainer Mark Geisert <mark@maxrnd.com>.
diff --git a/src/clip/getclip.c b/src/clip/getclip.c
index 82e7070..5cdb8f1 100644
--- a/src/clip/getclip.c
+++ b/src/clip/getclip.c
@@ -1,5 +1,5 @@
 /**
- * getclip.exe   Copy Windows clipboard to stdout  
+ * getclip.exe   Copy Windows clipboard to stdout
  *
  * Copyright 2001,2002,2009,2012 by Charles Wilson
  * All rights reserved.
@@ -31,7 +31,8 @@
 #include <io.h>
 #include <wchar.h>
 #include <sys/cygwin.h>
-#include <w32api/stringapiset.h>
+#include <sys/clipboard.h> // for cygcb_t and CYGWIN_NATIVE
+#include <locale.h>
 
 #define DEBUGGING 0 // Set 1 to display debug output on stderr
 
@@ -40,7 +41,9 @@ typedef struct
   struct timespec timestamp;
   size_t          len;
   char            data[1];
-} cygcb_t;
+} cygcb_old_t; // for cygNewFormat == 1
+
+// extern typedef struct cygcb_t is for cygNewFormat == 2
 
 typedef struct
 {
@@ -63,10 +66,10 @@ static const char copyrightID[] =
 
 typedef struct
 {
-  int endl_mode;                /* ENDLMODE_DOS  ENDLMODE_UNIX  ENDLMODE_NOCONV      */
-  int unixflag;                 /* indicates that the user specified -u or --unix    */
-  int dosflag;                  /* indicates that the user specified -d or --dos     */
-  int noconvflag;               /* indicates that the user specified -n or --no-conv */
+  int endl_mode;  /* ENDLMODE_DOS  ENDLMODE_UNIX  ENDLMODE_NOCONV      */
+  int unixflag;   /* indicates that the user specified -u or --unix    */
+  int dosflag;    /* indicates that the user specified -d or --dos     */
+  int noconvflag; /* indicates that the user specified -n or --no-conv */
 } flags_struct;
 
 static void printTopDescription (FILE * f, char *name);
@@ -198,6 +201,8 @@ main (int argc, const char **argv)
       goto exit;
     }
   rest = poptGetArgs (optCon);
+
+  setlocale (LC_ALL, "");
   if (rest == NULL)
     ec |= getclip (stdout, flags, stderr, program_name);
   else
@@ -308,9 +313,9 @@ static void getCygVer(cygwin_version_data* verInfo)
           break;
         if (strncasecmp (buf, "dll major:", 10) == 0)
           {
-	    char c = '\0';
-	    /* assumes 'p-(buf+11)' <= 7 */
-	    memcpy (dll_major, buf + 11, p - (buf + 11));
+            char c = '\0';
+            /* assumes 'p-(buf+11)' <= 7 */
+            memcpy (dll_major, buf + 11, p - (buf + 11));
             c = dll_major[1];
             dll_major[1] = '\0';
             verInfo->dll_major = atoi (dll_major);
@@ -321,18 +326,18 @@ static void getCygVer(cygwin_version_data* verInfo)
         if (strncasecmp (buf, "dll minor:", 10) == 0)
           {
             verInfo->dll_micro = atoi (buf + 11);
-	    continue;
-	  }
+            continue;
+          }
         if (strncasecmp (buf, "api major:", 10) == 0)
-	  {
+          {
             verInfo->api_major = atoi (buf + 11);
-	    continue;
-	  }
+            continue;
+          }
         if (strncasecmp (buf, "api minor:", 10) == 0)
-	  {
+          {
             verInfo->api_minor = atoi (buf + 11);
-	    continue;
-	  }
+            continue;
+          }
       }
 }
 
@@ -344,21 +349,25 @@ getclip (FILE * out, flags_struct flags, FILE * f, char *name)
   size_t len = 0;
   char *newStr = NULL;
   int origMode;
-  int cygNewFormat = 0;
+  int cygNewFormat;
+  int cygversion;
 
   cygwin_version_data verInfo;
   getCygVer(&verInfo);
-  if ((verInfo.dll_major > 1) ||
-      ((verInfo.dll_major == 1) && (verInfo.dll_minor > 7)) ||
-      ((verInfo.dll_major == 1) && (verInfo.dll_minor == 7) &&
-       (verInfo.dll_micro >= 13)))
+  cygversion  = verInfo.dll_micro;
+  cygversion += verInfo.dll_minor * 100;
+  cygversion += verInfo.dll_major * 100 * 100;
+  if (cygversion < 10713)
+    cygNewFormat = 0;
+  else if (cygversion < 30300)
     cygNewFormat = 1;
+  else
+    cygNewFormat = 2;
 
   origMode = setmode (fileno (out), O_BINARY);
 
   if (flags.endl_mode == ENDLMODE_NOCONV)
     {
-      const char *CYGWIN_NATIVE = "CYGWIN_NATIVE_CLIPBOARD";
       UINT cygnativeformat;
       UINT formatlist[3];
       UINT format;
@@ -378,7 +387,7 @@ getclip (FILE * out, flags_struct flags, FILE * f, char *name)
         fprintf (stderr, "\n");
       }
 #endif
-      cygnativeformat = RegisterClipboardFormat (CYGWIN_NATIVE);
+      cygnativeformat = RegisterClipboardFormatW (CYGWIN_NATIVE);
 
       formatlist[0] = cygnativeformat;
       formatlist[1] = CF_UNICODETEXT;
@@ -394,17 +403,21 @@ getclip (FILE * out, flags_struct flags, FILE * f, char *name)
 
       if (format == cygnativeformat)
         {
-	  if (cygNewFormat)
-	    {
+          if (cygNewFormat)
+            {
               cygcb_t *clipbuf = (cygcb_t *) GlobalLock (hglb);
+              cygcb_old_t *clipold = (cygcb_old_t *) clipbuf;
               if (clipbuf)
                 {
-                  fwrite (clipbuf->data, sizeof (char), clipbuf->len, out);
+                  if (cygNewFormat == 2)
+                    fwrite (&clipbuf[1], sizeof (char), clipbuf->cb_size, out);
+                  else
+                    fwrite (clipold->data, sizeof (char), clipold->len, out);
                   GlobalUnlock (hglb);
                 }
-	    }
-	  else
-	    {
+            }
+          else
+            {
               char *nativebuf = (char *) GlobalLock (hglb);
               if (nativebuf)
                 {
@@ -415,7 +428,7 @@ getclip (FILE * out, flags_struct flags, FILE * f, char *name)
                   fwrite (buf, sizeof (char), len, out);
                   GlobalUnlock (hglb);
                 }
-	    }
+            }
         }
       else if (format == CF_UNICODETEXT)
         {
@@ -423,18 +436,15 @@ getclip (FILE * out, flags_struct flags, FILE * f, char *name)
           if (lpwstr)
             {
               int srclen = wcslen (lpwstr); // wide-char count
-              int dstlen = srclen << 2; // byte count
+              int dstlen = srclen << 2; // heuristic for byte count
               LPSTR dst = (LPSTR) malloc (dstlen);
-              int res = WideCharToMultiByte (CP_UTF8, 0, lpwstr, srclen,
-                                             dst, dstlen, NULL, NULL);
+              int res = wcstombs (dst, lpwstr, dstlen);
               if (res > 0)
                 fwrite (dst, sizeof (char), res, out);
-              else if (res == 0)
+              else if (res == -1)
                 {
 #if DEBUGGING
-                  DWORD err = GetLastError ();
-                  /* look up error code displayed here in w32api/winerror.h */
-                  fprintf (stderr, "WideCharToMultiByte returns %ld\n", err);
+                  fprintf (stderr, "wcstombs: %s\n", strerror (errno));
 #endif
                 }
               free (dst);
diff --git a/src/clip/putclip.c b/src/clip/putclip.c
index 76bddeb..13158bd 100644
--- a/src/clip/putclip.c
+++ b/src/clip/putclip.c
@@ -31,7 +31,8 @@
 #include <io.h>
 #include <wchar.h>
 #include <sys/cygwin.h>
-#include <w32api/stringapiset.h>
+#include <sys/clipboard.h> // for cygcb_t and CYGWIN_NATIVE
+#include <locale.h>
 
 #define DEBUGGING 0 // Set 1 to display debug output on stderr
 
@@ -40,7 +41,9 @@ typedef struct
   struct timespec timestamp;
   size_t          len;
   char            data[1];
-} cygcb_t;
+} cygcb_old_t; // for cygNewFormat == 1
+
+// extern typedef struct cygcb_t is for cygNewFormat == 2
 
 typedef struct
 {
@@ -69,10 +72,10 @@ static const char copyrightID[] =
 
 typedef struct
 {
-  int endl_mode;                /* ENDLMODE_DOS  ENDLMODE_UNIX  ENDLMODE_NOCONV      */
-  int unixflag;                 /* indicates that the user specified -u or --unix    */
-  int dosflag;                  /* indicates that the user specified -d or --dos     */
-  int noconvflag;               /* indicates that the user specified -n or --no-conv */
+  int endl_mode;  /* ENDLMODE_DOS  ENDLMODE_UNIX  ENDLMODE_NOCONV      */
+  int unixflag;   /* indicates that the user specified -u or --unix    */
+  int dosflag;    /* indicates that the user specified -d or --dos     */
+  int noconvflag; /* indicates that the user specified -n or --no-conv */
 } flags_struct;
 
 static void printTopDescription (FILE * f, char *name);
@@ -198,6 +201,7 @@ main (int argc, const char **argv)
 
   rest = poptGetArgs (optCon);
 
+  setlocale (LC_ALL, "");
   if (rest == NULL)
     ec |= putclip (stdin, flags, stderr, program_name);
   else
@@ -348,19 +352,24 @@ putclip (FILE * in, flags_struct flags, FILE * f, char *name)
   int len = 0;
   int convlen = 0;
   int numread;
-  int cygNewFormat = 0;
+  int cygNewFormat;
+  int cygversion;
 
   cygwin_version_data verInfo;
   getCygVer(&verInfo);
-  if ((verInfo.dll_major > 1) ||
-      ((verInfo.dll_major == 1) && (verInfo.dll_minor > 7)) ||
-      ((verInfo.dll_major == 1) && (verInfo.dll_minor == 7) &&
-       (verInfo.dll_micro >= 13)))
+  cygversion  = verInfo.dll_micro;
+  cygversion += verInfo.dll_minor * 100;
+  cygversion += verInfo.dll_major * 100 * 100;
+  if (cygversion < 10713)
+    cygNewFormat = 0;
+  else if (cygversion < 30300)
     cygNewFormat = 1;
+  else
+    cygNewFormat = 2;
 
   /* Since we have to copy to the clipboard all in one step,
-     read entire stream into memory. However, let's try to 
-     do this using the minimum amount of memory, but keep 
+     read entire stream into memory. However, let's try to
+     do this using the minimum amount of memory, but keep
      allocating more if needed.
    */
   do
@@ -398,23 +407,9 @@ putclip (FILE * in, flags_struct flags, FILE * f, char *name)
   /* format the string according to flags */
   if (buf)
     {
-      const char *CYGWIN_NATIVE = "CYGWIN_NATIVE_CLIPBOARD";
       UINT cygnativeformat;
 
-      if (!OpenClipboard (0))
-        {
-          fprintf (stderr, "Unable to open the clipboard\n");
-#if DEBUGGING
-          DWORD err = GetLastError ();
-          /* look up error code displayed here in w32api/winerror.h */
-          fprintf (stderr, "OpenClipboard returns %ld\n", err);
-#endif
-          return (PUTCLIP_ERR);
-        }
-      cygnativeformat = RegisterClipboardFormat (CYGWIN_NATIVE);
-      CloseClipboard ();
-
-      // if flags.endl_mode == ENDLMODE_NOCONV 
+      // if flags.endl_mode == ENDLMODE_NOCONV
       convbuf = buf;
       convlen = len;
 
@@ -537,32 +532,44 @@ putclip (FILE * in, flags_struct flags, FILE * f, char *name)
           /* look up error code displayed here in w32api/winerror.h */
           fprintf (stderr, "OpenClipboard returns %ld\n", err);
 #endif
-          if (convbuf)
-            free (convbuf);
-          return (PUTCLIP_ERR);
+          goto failout2;
+        }
+      cygnativeformat = RegisterClipboardFormatW (CYGWIN_NATIVE);
+
+      switch (cygNewFormat)
+        {
+        case 2:
+          hData = GlobalAlloc (GMEM_MOVEABLE, convlen + sizeof (cygcb_t));
+          break;
+        case 1:
+          hData = GlobalAlloc (GMEM_MOVEABLE, convlen + sizeof (cygcb_old_t));
+          break;
+        case 0:
+          hData = GlobalAlloc (GMEM_MOVEABLE, convlen + sizeof (size_t));
+          break;
         }
-      if (cygNewFormat)
-	hData = GlobalAlloc (GMEM_MOVEABLE, convlen + sizeof (cygcb_t));
-      else
-	hData = GlobalAlloc (GMEM_MOVEABLE, convlen + sizeof (size_t));
 
       if (!hData)
         {
           fprintf (f, "Couldn't allocate global buffer for write.\n");
-          if (convbuf)
-            free (convbuf);
-          return (PUTCLIP_ERR);
+          goto failout;
         }
       if (!(clipbuf = (void *) GlobalLock (hData)))
         {
           fprintf (f, "Couldn't lock global buffer.\n");
-          free (convbuf);
-          return (PUTCLIP_ERR);
+          goto failout;
         }
 
-      if (cygNewFormat)
+      if (cygNewFormat == 2)
         {
           cygcb_t *clipbufX = (cygcb_t *) clipbuf;
+          clipbufX->cb_size = convlen;
+          clock_gettime (CLOCK_REALTIME, &clipbufX->ts);
+          memcpy (&clipbufX[1], convbuf, convlen);
+        }
+      else if (cygNewFormat == 1)
+        {
+          cygcb_old_t *clipbufX = (cygcb_old_t *) clipbuf;
           clipbufX->len = convlen;
           clock_gettime (CLOCK_REALTIME, &clipbufX->timestamp);
           memcpy (clipbufX->data, convbuf, convlen);
@@ -577,65 +584,47 @@ putclip (FILE * in, flags_struct flags, FILE * f, char *name)
       if (!SetClipboardData (cygnativeformat, hData))
         {
           fprintf (f,
-                   "Couldn't write native format to the clipboard %04x %x\n",
+                   "Couldn't write native format to the clipboard %04x %p\n",
                    cygnativeformat, hData);
 #if DEBUGGING
           DWORD err = GetLastError ();
           /* look up error code displayed here in w32api/winerror.h */
           fprintf (stderr, "SetClipboardData returns %ld\n", err);
 #endif
-          free (convbuf);
-          return (PUTCLIP_ERR);
+          goto failout;
         }
-      CloseClipboard ();
-#if 0 // Per MSDN, don't GlobalFree a handle successfully transferred to system
-      if (GlobalFree (hData))
-        {
-          fprintf (f,
-                   "Couldn't free global buffer after write to clipboard.\n");
-          free (convbuf);
-          return (PUTCLIP_ERR);
-        }
-#endif
+/* Per MSDN, don't GlobalFree a handle successfully transferred to system
+ *    if (GlobalFree (hData))
+ *      {
+ *        fprintf (f,
+ *                 "Couldn't free global buffer after write to clipboard.\n");
+ *        goto failout;
+ *      }
+ */
       hData = NULL;
       clipbuf = NULL;
 
       /* CF_UNICODETEXT format */
-      if (!OpenClipboard (0))
-        {
-          fprintf (f, "Unable to open the clipboard\n");
-#if DEBUGGING
-          DWORD err = GetLastError ();
-          /* look up error code displayed here in w32api/winerror.h */
-          fprintf (stderr, "OpenClipboard returns %ld\n", err);
-#endif
-          free (convbuf);
-          return (PUTCLIP_ERR);
-        }
       if (!(hData = GlobalAlloc (GMEM_MOVEABLE, sizeof (WCHAR) * convlen + 2)))
         {
           fprintf (f, "Couldn't allocate global buffer for write.\n");
-          free (convbuf);
-          return (PUTCLIP_ERR);
+          goto failout;
         }
       if (!(clipbuf = (void *) GlobalLock (hData)))
         {
           fprintf (f, "Couldn't lock global buffer.\n");
-          free (convbuf);
-          return (PUTCLIP_ERR);
+          goto failout;
         }
 
-      int res = MultiByteToWideChar (CP_UTF8, 0, convbuf, convlen,
-                                     (LPWSTR) clipbuf, convlen + 1);
-      if (res == 0)
+      convbuf[convlen] = '\0';
+      int res = mbstowcs (clipbuf, convbuf, convlen + 1);
+      if (res == -1)
         {
 #if DEBUGGING
-          DWORD err = GetLastError ();
-          /* look up error code displayed here in w32api/winerror.h */
-          fprintf (stderr, "MultiByteToWideChar returns %ld\n", err);
+          fprintf (stderr, "mbstowcs: %s\n", strerror (errno));
 #endif
         }
-      else /* res != 0 */
+      else /* res != -1 */
         {
           *((WCHAR *) clipbuf + res) = 0; /* NULL-terminate just in case */
 #if DEBUGGING
@@ -652,45 +641,29 @@ putclip (FILE * in, flags_struct flags, FILE * f, char *name)
           /* look up error code displayed here in w32api/winerror.h */
           fprintf (stderr, "SetClipboardData returns %ld\n", err);
 #endif
-          free (convbuf);
-          return (PUTCLIP_ERR);
+          goto failout;
         }
-      CloseClipboard ();
-#if 0 // Per MSDN, don't GlobalFree a handle successfully transferred to system
-      if (GlobalFree (hData))
-        {
-          fprintf (f,
-                   "Couldn't free global buffer after write to clipboard.\n");
-          free (convbuf);
-          return (PUTCLIP_ERR);
-        }
-#endif
+/* Per MSDN, don't GlobalFree a handle successfully transferred to system
+ *    if (GlobalFree (hData))
+ *      {
+ *        fprintf (f,
+ *                 "Couldn't free global buffer after write to clipboard.\n");
+ *        goto failout;
+ *      }
+ */
       hData = NULL;
       clipbuf = NULL;
 
       /* CF_TEXT format */
-      if (!OpenClipboard (0))
-        {
-          fprintf (f, "Unable to open the clipboard\n");
-#if DEBUGGING
-          DWORD err = GetLastError ();
-          /* look up error code displayed here in w32api/winerror.h */
-          fprintf (stderr, "OpenClipboard returns %ld\n", err);
-#endif
-          free (convbuf);
-          return (PUTCLIP_ERR);
-        }
       if (!(hData = GlobalAlloc (GMEM_MOVEABLE, convlen + 2)))
         {
           fprintf (f, "Couldn't allocate global buffer for write.\n");
-          free (convbuf);
-          return (PUTCLIP_ERR);
+          goto failout;
         }
       if (!(clipbuf = (void *) GlobalLock (hData)))
         {
           fprintf (f, "Couldn't lock global buffer.\n");
-          free (convbuf);
-          return (PUTCLIP_ERR);
+          goto failout;
         }
 
       memcpy (clipbuf, convbuf, convlen);
@@ -706,19 +679,17 @@ putclip (FILE * in, flags_struct flags, FILE * f, char *name)
           /* look up error code displayed here in w32api/winerror.h */
           fprintf (stderr, "SetClipboardData returns %ld\n", err);
 #endif
-          free (convbuf);
-          return (PUTCLIP_ERR);
+          goto failout;
         }
       CloseClipboard ();
-#if 0 // Per MSDN, don't GlobalFree a handle successfully transferred to system
-      if (GlobalFree (hData))
-        {
-          fprintf (f,
-                   "Couldn't free global buffer after write to clipboard.\n");
-          free (convbuf);
-          return (PUTCLIP_ERR);
-        }
-#endif
+/* Per MSDN, don't GlobalFree a handle successfully transferred to system
+ *    if (GlobalFree (hData))
+ *      {
+ *        fprintf (f,
+ *                 "Couldn't free global buffer after write to clipboard.\n");
+ *        goto failout;
+ *      }
+ */
       hData = NULL;
       clipbuf = NULL;
 
@@ -731,4 +702,11 @@ putclip (FILE * in, flags_struct flags, FILE * f, char *name)
       CloseClipboard ();
     }
   return (PUTCLIP_OK);
+
+failout:
+  CloseClipboard ();
+failout2:
+  if (convbuf)
+    free (convbuf);
+  return (PUTCLIP_ERR);
 }



More information about the Cygwin-apps-cvs mailing list