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

Mark Geisert via Cygwin-apps-cvs <[email protected]>
Newsgroups gmane.os.cygwin.cvs.apps
Message-ID <[email protected]>


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

commit 6a2162acab2e93a6fe9bf90907aa6656f084d19f
Author: Mark Geisert <[email protected]>
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  <[email protected]>  (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  <[email protected]>  (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 <[email protected]>.
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);
 }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.