Blame SOURCES/0001-Add-wide-char-support-to-pinentry-curses.patch

b3bbd1
From e2b89cbdcba7475047ca3c46fc7d03825355b3ff Mon Sep 17 00:00:00 2001
b3bbd1
From: Daiki Ueno <ueno@unixuser.org>
b3bbd1
Date: Wed, 10 Aug 2011 12:50:43 +0900
b3bbd1
Subject: [PATCH] Add wide-char support to pinentry-curses.
b3bbd1
b3bbd1
---
b3bbd1
 configure.ac               |   2 +-
b3bbd1
 m4/curses.m4               |  20 +++++-
b3bbd1
 pinentry/pinentry-curses.c | 150 +++++++++++++++++++++++++++++++++++++--------
b3bbd1
 3 files changed, 143 insertions(+), 29 deletions(-)
b3bbd1
b3bbd1
diff --git a/configure.ac b/configure.ac
b3bbd1
index 4b8ed79..bcbe26e 100644
b3bbd1
--- a/configure.ac
b3bbd1
+++ b/configure.ac
b3bbd1
@@ -158,7 +158,7 @@ fi
b3bbd1
 
b3bbd1
 # Checks for header files.
b3bbd1
 AC_HEADER_STDC
b3bbd1
-AC_CHECK_HEADERS(string.h unistd.h langinfo.h termio.h locale.h utime.h)
b3bbd1
+AC_CHECK_HEADERS(string.h unistd.h langinfo.h termio.h locale.h utime.h wchar.h)
b3bbd1
 
b3bbd1
 dnl Checks for library functions.
b3bbd1
 AC_CHECK_FUNCS(seteuid stpcpy mmap)
b3bbd1
diff --git a/m4/curses.m4 b/m4/curses.m4
b3bbd1
index 1e1cb4f..3a01881 100644
b3bbd1
--- a/m4/curses.m4
b3bbd1
+++ b/m4/curses.m4
b3bbd1
@@ -28,7 +28,13 @@ AC_DEFUN([IU_LIB_NCURSES], [
b3bbd1
   AC_ARG_ENABLE(ncurses,    [  --disable-ncurses       don't prefer -lncurses over -lcurses],
b3bbd1
               , enable_ncurses=yes)
b3bbd1
   if test "$enable_ncurses" = yes; then
b3bbd1
-    AC_CHECK_LIB(ncurses, initscr, LIBNCURSES="-lncurses")
b3bbd1
+    AC_CHECK_LIB(ncursesw, initscr, LIBNCURSES="-lncursesw",
b3bbd1
+      AC_CHECK_LIB(ncurses, initscr, LIBNCURSES="-lncurses"))
b3bbd1
+    if test "$ac_cv_lib_ncursesw_initscr" = yes; then
b3bbd1
+      have_ncursesw=yes
b3bbd1
+    else
b3bbd1
+      have_ncursesw=no
b3bbd1
+    fi
b3bbd1
     if test "$LIBNCURSES"; then
b3bbd1
       # Use ncurses header files instead of the ordinary ones, if possible;
b3bbd1
       # is there a better way of doing this, that avoids looking in specific
b3bbd1
@@ -53,9 +59,14 @@ AC_DEFUN([IU_LIB_NCURSES], [
b3bbd1
       else
b3bbd1
 	AC_CACHE_CHECK(for ncurses include dir,
b3bbd1
 		       inetutils_cv_includedir_ncurses,
b3bbd1
+          if test "$have_ncursesw" = yes; then
b3bbd1
+            ncursesdir=ncursesw
b3bbd1
+          else
b3bbd1
+            ncursesdir=ncurses
b3bbd1
+          fi
b3bbd1
 	  for D in $includedir $prefix/include /local/include /usr/local/include /include /usr/include; do
b3bbd1
-	    if test -d $D/ncurses; then
b3bbd1
-	      inetutils_cv_includedir_ncurses="$D/ncurses"
b3bbd1
+	    if test -d $D/$ncursesdir; then
b3bbd1
+	      inetutils_cv_includedir_ncurses="$D/$ncursesdir"
b3bbd1
 	      break
b3bbd1
 	    fi
b3bbd1
 	    test "$inetutils_cv_includedir_ncurses" \
b3bbd1
@@ -68,6 +79,9 @@ AC_DEFUN([IU_LIB_NCURSES], [
b3bbd1
         NCURSES_INCLUDE="-I$inetutils_cv_includedir_ncurses"
b3bbd1
       fi
b3bbd1
     fi
b3bbd1
+    if test $have_ncursesw = yes; then
b3bbd1
+      AC_DEFINE(HAVE_NCURSESW, 1, [Define if you have working ncursesw])
b3bbd1
+    fi
b3bbd1
   fi
b3bbd1
   AC_SUBST(NCURSES_INCLUDE)
b3bbd1
   AC_SUBST(LIBNCURSES)])dnl
b3bbd1
diff --git a/pinentry/pinentry-curses.c b/pinentry/pinentry-curses.c
b3bbd1
index 76ddbdd..585059f 100644
b3bbd1
--- a/pinentry/pinentry-curses.c
b3bbd1
+++ b/pinentry/pinentry-curses.c
b3bbd1
@@ -42,6 +42,10 @@
b3bbd1
 
b3bbd1
 #include <memory.h>
b3bbd1
 
b3bbd1
+#ifdef HAVE_WCHAR_H
b3bbd1
+#include <wchar.h>
b3bbd1
+#endif /*HAVE_WCHAR_H*/
b3bbd1
+
b3bbd1
 #include "pinentry.h"
b3bbd1
 
b3bbd1
 /* FIXME: We should allow configuration of these button labels and in
b3bbd1
@@ -94,6 +98,24 @@ struct dialog
b3bbd1
 typedef struct dialog *dialog_t;
b3bbd1
 
b3bbd1
 
b3bbd1
+#ifdef HAVE_NCURSESW
b3bbd1
+typedef wchar_t CH;
b3bbd1
+#define STRLEN(x) wcslen (x)
b3bbd1
+#define ADDCH(x) addnwstr (&x, 1);
b3bbd1
+#define CHWIDTH(x) wcwidth (x)
b3bbd1
+#define NULLCH L'\0'
b3bbd1
+#define NLCH L'\n'
b3bbd1
+#define SPCH L' '
b3bbd1
+#else
b3bbd1
+typedef char CH;
b3bbd1
+#define STRLEN(x) strlen (x)
b3bbd1
+#define ADDCH(x) addch ((unsigned char) x)
b3bbd1
+#define CHWIDTH(x) 1
b3bbd1
+#define NULLCH '\0'
b3bbd1
+#define NLCH '\n'
b3bbd1
+#define SPCH ' '
b3bbd1
+#endif
b3bbd1
+
b3bbd1
 /* Return the next line up to MAXLEN columns wide in START and LEN.
b3bbd1
    The first invocation should have 0 as *LEN.  If the line ends with
b3bbd1
    a \n, it is a normal line that will be continued.  If it is a '\0'
b3bbd1
@@ -101,40 +123,95 @@ typedef struct dialog *dialog_t;
b3bbd1
    there is a forced line break.  A full line is returned and will be
b3bbd1
    continued in the next line.  */
b3bbd1
 static void
b3bbd1
-collect_line (int maxlen, char **start_p, int *len_p)
b3bbd1
+collect_line (int maxwidth, wchar_t **start_p, int *len_p)
b3bbd1
 {
b3bbd1
   int last_space = 0;
b3bbd1
   int len = *len_p;
b3bbd1
-  char *end;
b3bbd1
+  int width = 0;
b3bbd1
+  CH *end;
b3bbd1
 
b3bbd1
   /* Skip to next line.  */
b3bbd1
   *start_p += len;
b3bbd1
   /* Skip leading space.  */
b3bbd1
-  while (**start_p == ' ')
b3bbd1
+  while (**start_p == SPCH)
b3bbd1
     (*start_p)++;
b3bbd1
 
b3bbd1
   end = *start_p;
b3bbd1
   len = 0;
b3bbd1
 
b3bbd1
-  while (len < maxlen - 1 && *end && *end != '\n')
b3bbd1
+  while (width < maxwidth - 1 && *end != NULLCH && *end != NLCH)
b3bbd1
     {
b3bbd1
       len++;
b3bbd1
       end++;
b3bbd1
-      if (*end == ' ')
b3bbd1
+      if (*end == SPCH)
b3bbd1
 	last_space = len;
b3bbd1
+      width += CHWIDTH (*end);
b3bbd1
     }
b3bbd1
 
b3bbd1
-  if (*end && *end != '\n' && last_space != 0)
b3bbd1
+  if (*end != NULLCH && *end != NLCH && last_space != 0)
b3bbd1
     {
b3bbd1
       /* We reached the end of the available space, but still have
b3bbd1
 	 characters to go in this line.  We can break the line into
b3bbd1
 	 two parts at a space.  */
b3bbd1
       len = last_space;
b3bbd1
-      (*start_p)[len] = '\n';
b3bbd1
+      (*start_p)[len] = NLCH;
b3bbd1
     }
b3bbd1
   *len_p = len + 1;
b3bbd1
 }
b3bbd1
 
b3bbd1
+#ifdef HAVE_NCURSESW
b3bbd1
+static CH *
b3bbd1
+utf8_to_local (char *lc_ctype, char *string)
b3bbd1
+{
b3bbd1
+  mbstate_t ps;
b3bbd1
+  size_t len;
b3bbd1
+  char *local;
b3bbd1
+  const char *p;
b3bbd1
+  wchar_t *wcs = NULL;
b3bbd1
+  char *old_ctype = NULL;
b3bbd1
+
b3bbd1
+  local = pinentry_utf8_to_local (lc_ctype, string);
b3bbd1
+  if (!local)
b3bbd1
+    return NULL;
b3bbd1
+
b3bbd1
+  old_ctype = strdup (setlocale (LC_CTYPE, NULL));
b3bbd1
+  setlocale (LC_CTYPE, lc_ctype? lc_ctype : "");
b3bbd1
+
b3bbd1
+  p = local;
b3bbd1
+  memset (&ps, 0, sizeof(mbstate_t));
b3bbd1
+  len = mbsrtowcs (NULL, &p, strlen (string), &ps);
b3bbd1
+  if (len == (size_t)-1)
b3bbd1
+    {
b3bbd1
+      free (local);
b3bbd1
+      goto leave;
b3bbd1
+    }
b3bbd1
+  wcs = calloc (len + 1, sizeof(wchar_t));
b3bbd1
+  if (!wcs)
b3bbd1
+    {
b3bbd1
+      free (local);
b3bbd1
+      goto leave;
b3bbd1
+    }
b3bbd1
+
b3bbd1
+  p = local;
b3bbd1
+  memset (&ps, 0, sizeof(mbstate_t));
b3bbd1
+  mbsrtowcs (wcs, &p, len, &ps);
b3bbd1
+
b3bbd1
+ leave:
b3bbd1
+  if (old_ctype)
b3bbd1
+    {
b3bbd1
+      setlocale (LC_CTYPE, old_ctype);
b3bbd1
+      free (old_ctype);
b3bbd1
+    }
b3bbd1
+
b3bbd1
+  return wcs;
b3bbd1
+}
b3bbd1
+#else
b3bbd1
+static CH *
b3bbd1
+utf8_to_local (const char *lc_ctype, const char *string)
b3bbd1
+{
b3bbd1
+  return pinentry_utf8_to_local (lc_ctype, string);
b3bbd1
+}
b3bbd1
+#endif
b3bbd1
 
b3bbd1
 static int
b3bbd1
 dialog_create (pinentry_t pinentry, dialog_t dialog)
b3bbd1
@@ -148,16 +225,15 @@ dialog_create (pinentry_t pinentry, dialog_t dialog)
b3bbd1
   int xpos;
b3bbd1
   int description_x = 0;
b3bbd1
   int error_x = 0;
b3bbd1
-  char *description = NULL;
b3bbd1
-  char *error = NULL;
b3bbd1
-  char *prompt = NULL;
b3bbd1
+  CH *description = NULL;
b3bbd1
+  CH *error = NULL;
b3bbd1
+  CH *prompt = NULL;
b3bbd1
 
b3bbd1
 #define COPY_OUT(what)							\
b3bbd1
   do									\
b3bbd1
     if (pinentry->what)							\
b3bbd1
       {									\
b3bbd1
-        what = pinentry_utf8_to_local (pinentry->lc_ctype,		\
b3bbd1
-				       pinentry->what);			\
b3bbd1
+        what = utf8_to_local (pinentry->lc_ctype, pinentry->what);	\
b3bbd1
         if (!what)							\
b3bbd1
 	  {								\
b3bbd1
 	    err = 1;							\
b3bbd1
@@ -214,7 +290,7 @@ dialog_create (pinentry_t pinentry, dialog_t dialog)
b3bbd1
   y = 1;		/* Top frame.  */
b3bbd1
   if (description)
b3bbd1
     {
b3bbd1
-      char *start = description;
b3bbd1
+      CH *start = description;
b3bbd1
       int len = 0;
b3bbd1
 
b3bbd1
       do
b3bbd1
@@ -232,7 +308,7 @@ dialog_create (pinentry_t pinentry, dialog_t dialog)
b3bbd1
     {
b3bbd1
       if (error)
b3bbd1
 	{
b3bbd1
-	  char *p = error;
b3bbd1
+	  CH *p = error;
b3bbd1
 	  int err_x = 0;
b3bbd1
 
b3bbd1
 	  while (*p)
b3bbd1
@@ -287,7 +363,9 @@ dialog_create (pinentry_t pinentry, dialog_t dialog)
b3bbd1
 
b3bbd1
       new_x = MIN_PINENTRY_LENGTH;
b3bbd1
       if (prompt)
b3bbd1
-	new_x += strlen (prompt) + 1;	/* One space after prompt.  */
b3bbd1
+	{
b3bbd1
+	  new_x += STRLEN (prompt) + 1;	/* One space after prompt.  */
b3bbd1
+	}
b3bbd1
       if (new_x > size_x - 4)
b3bbd1
 	new_x = size_x - 4;
b3bbd1
       if (new_x > x)
b3bbd1
@@ -335,7 +413,7 @@ dialog_create (pinentry_t pinentry, dialog_t dialog)
b3bbd1
   ypos++;
b3bbd1
   if (description)
b3bbd1
     {
b3bbd1
-      char *start = description;
b3bbd1
+      CH *start = description;
b3bbd1
       int len = 0;
b3bbd1
 
b3bbd1
       do
b3bbd1
@@ -347,9 +425,11 @@ dialog_create (pinentry_t pinentry, dialog_t dialog)
b3bbd1
 	  addch (' ');
b3bbd1
 	  collect_line (size_x - 4, &start, &len;;
b3bbd1
 	  for (i = 0; i < len - 1; i++)
b3bbd1
-	    addch ((unsigned char) start[i]);
b3bbd1
-	  if (start[len - 1] && start[len - 1] != '\n')
b3bbd1
-	    addch ((unsigned char) start[len - 1]);
b3bbd1
+	    {
b3bbd1
+	      ADDCH (start[i]);
b3bbd1
+	    }
b3bbd1
+	  if (start[len - 1] != NULLCH && start[len - 1] != NLCH)
b3bbd1
+	    ADDCH (start[len - 1]);
b3bbd1
 	  ypos++;
b3bbd1
 	}
b3bbd1
       while (start[len - 1]);
b3bbd1
@@ -363,7 +443,7 @@ dialog_create (pinentry_t pinentry, dialog_t dialog)
b3bbd1
 
b3bbd1
       if (error)
b3bbd1
 	{
b3bbd1
-	  char *p = error;
b3bbd1
+	  CH *p = error;
b3bbd1
 	  i = 0;
b3bbd1
 
b3bbd1
 	  while (*p)
b3bbd1
@@ -378,11 +458,11 @@ dialog_create (pinentry_t pinentry, dialog_t dialog)
b3bbd1
 		}
b3bbd1
 	      else
b3bbd1
 		standout ();
b3bbd1
-	      for (;*p && *p != '\n'; p++)
b3bbd1
+	      for (;*p && *p != NLCH; p++)
b3bbd1
 		if (i < x - 4)
b3bbd1
 		  {
b3bbd1
 		    i++;
b3bbd1
-		    addch ((unsigned char) *p);
b3bbd1
+		    ADDCH (*p);
b3bbd1
 		  }
b3bbd1
 	      if (USE_COLORS && pinentry->color_so != PINENTRY_COLOR_NONE)
b3bbd1
 		{
b3bbd1
@@ -410,14 +490,16 @@ dialog_create (pinentry_t pinentry, dialog_t dialog)
b3bbd1
       dialog->pin_size = x - 4;
b3bbd1
       if (prompt)
b3bbd1
 	{
b3bbd1
-	  char *p = prompt;
b3bbd1
-	  i = strlen (prompt);
b3bbd1
+	  CH *p = prompt;
b3bbd1
+	  i = STRLEN (prompt);
b3bbd1
 	  if (i > x - 4 - MIN_PINENTRY_LENGTH)
b3bbd1
 	    i = x - 4 - MIN_PINENTRY_LENGTH;
b3bbd1
 	  dialog->pin_x += i + 1;
b3bbd1
 	  dialog->pin_size -= i + 1;
b3bbd1
 	  while (i-- > 0)
b3bbd1
-	    addch ((unsigned char) *(p++));
b3bbd1
+	    {
b3bbd1
+	      ADDCH (*(p++));
b3bbd1
+	    }
b3bbd1
 	  addch (' ');
b3bbd1
 	}
b3bbd1
       for (i = 0; i < dialog->pin_size; i++)
b3bbd1
@@ -631,6 +713,17 @@ dialog_run (pinentry_t pinentry, const char *tty_name, const char *tty_type)
b3bbd1
   SCREEN *screen = 0;
b3bbd1
   int done = 0;
b3bbd1
   char *pin_utf8;
b3bbd1
+#ifdef HAVE_NCURSESW
b3bbd1
+  char *old_ctype = NULL;
b3bbd1
+
b3bbd1
+  if (pinentry->lc_ctype)
b3bbd1
+    {
b3bbd1
+      old_ctype = strdup (setlocale (LC_CTYPE, NULL));
b3bbd1
+      setlocale (LC_CTYPE, pinentry->lc_ctype);
b3bbd1
+    }
b3bbd1
+  else
b3bbd1
+    setlocale (LC_CTYPE, "");
b3bbd1
+#endif
b3bbd1
 
b3bbd1
   /* Open the desired terminal if necessary.  */
b3bbd1
   if (tty_name)
b3bbd1
@@ -804,6 +897,13 @@ dialog_run (pinentry_t pinentry, const char *tty_name, const char *tty_type)
b3bbd1
   if (screen)
b3bbd1
     delscreen (screen);
b3bbd1
 
b3bbd1
+#ifdef HAVE_NCURSESW
b3bbd1
+  if (old_ctype)
b3bbd1
+    {
b3bbd1
+      setlocale (LC_CTYPE, old_ctype);
b3bbd1
+      free (old_ctype);
b3bbd1
+    }
b3bbd1
+#endif
b3bbd1
   if (ttyfi)
b3bbd1
     fclose (ttyfi);
b3bbd1
   if (ttyfo)
b3bbd1
-- 
b3bbd1
1.8.3.1
b3bbd1