Package: mpg321
Version: 0.2.10.3
Severity: normal

mpg321 only works correctly in an ISO-8859-1 locale.
I've done a patch to make it work in UTF-8 locales, too.
You have to run aclocal, etc, because there are some new
configuration thingies.

diff -ru mpg321-0.2.10.1.orig/Makefile.am mpg321-0.2.10.1/Makefile.am
--- mpg321-0.2.10.1.orig/Makefile.am    2001-10-13 18:28:25.000000000 +0100
+++ mpg321-0.2.10.1/Makefile.am 2005-04-29 20:31:09.000000000 +0100
@@ -11,7 +11,8 @@
        getopt.h \
        remote.c \
        ao.c \
-       options.c
+       options.c \
+       ucs4width.c
 
 SUBDIRS = m4
 EXTRA_DIST = README.remote HACKING BUGS mpg321.sgml mpg321.1 $(srcdir)/debian/*
diff -ru mpg321-0.2.10.1.orig/configure.ac mpg321-0.2.10.1/configure.ac
--- mpg321-0.2.10.1.orig/configure.ac   2002-03-24 05:02:28.000000000 +0000
+++ mpg321-0.2.10.1/configure.ac        2005-04-29 21:47:33.000000000 +0100
@@ -44,7 +44,7 @@
 
 dnl Checks for header files.
 AC_HEADER_STDC
-AC_CHECK_HEADERS(fcntl.h sys/ioctl.h sys/time.h unistd.h)
+AC_CHECK_HEADERS(fcntl.h locale.h sys/ioctl.h sys/time.h unistd.h)
 AC_HEADER_TIME
 
 # Checks for typedefs, structures, and compiler characteristics.
@@ -67,7 +67,7 @@
 
 AC_TYPE_SOCKLEN_T
 
-AC_CHECK_FUNCS([gethostbyname memset munmap socket strchr strdup strerror 
strrchr strstr gettimeofday select getenv putenv setenv unsetenv strcasecmp])
+AC_CHECK_FUNCS([gethostbyname memset munmap socket strchr strdup strerror 
strrchr strstr gettimeofday select getenv putenv setenv unsetenv strcasecmp 
setlocale])
 
 AC_ARG_ENABLE(mpg123_symlink,
 [  --enable-mpg123-symlink Enable symlink of mpg123 to mpg321 [[default=yes]] 
],
@@ -98,5 +98,7 @@
     AC_DEFINE_UNQUOTED(AUDIO_DEFAULT, "the libao default", [Define the default 
libao output device.])
 fi
 
+AM_LANGINFO_CODESET
+
 AC_CONFIG_FILES([Makefile m4/Makefile])
 AC_OUTPUT
diff -ru mpg321-0.2.10.1.orig/mpg321.c mpg321-0.2.10.1/mpg321.c
--- mpg321-0.2.10.1.orig/mpg321.c       2004-01-04 19:51:13.000000000 +0000
+++ mpg321-0.2.10.1/mpg321.c    2005-04-29 21:43:42.000000000 +0100
@@ -46,6 +46,14 @@
 
 #include <id3tag.h>
 
+#ifdef HAVE_LANGINFO_CODESET
+#include <langinfo.h>
+#endif
+
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif
+
 int shuffle_play;
 int stop_playing_file = 0;
 int quit_now = 0;
@@ -56,6 +64,27 @@
 int status = MPG321_STOPPED;
 int file_change = 0;
 
+int utf8_mode = 0;
+
+void set_utf8_mode()
+{
+#if defined(HAVE_SETLOCALE) && defined(HAVE_LANGINFO_CODESET)
+    setlocale(LC_ALL, "");
+    utf8_mode = !strcmp(nl_langinfo(CODESET), "UTF-8");
+#else
+#if defined(HAVE_GETENV)
+    char *s;
+    if (((s = getenv("LC_ALL"))   && *s) ||
+        ((s = getenv("LC_CTYPE")) && *s) ||
+        ((s = getenv("LANG"))     && *s))
+    {
+        if (strstr(s, "UTF-8"))
+            utf8_mode = 1;
+    }
+#endif
+#endif
+}
+
 char *id3_get_tag (struct id3_tag const *tag, char const *what, unsigned int 
maxlen);
 
 void mpg123_boilerplate()
@@ -225,6 +254,8 @@
     
     struct mad_decoder decoder;
 
+    set_utf8_mode();
+
     old_dir[0] = '\0';
 
     playbuf.pl = pl = new_playlist();
@@ -559,22 +590,20 @@
  * It allocates a new string. Free it later.
  * NULL if no tag or error.
  */
-char *id3_get_tag (struct id3_tag const *tag, char const *what, unsigned int 
maxlen)
+char *id3_get_tag (struct id3_tag const *tag, char const *what, unsigned int 
width)
 {
     struct id3_frame const *frame = NULL;
     union id3_field const *field = NULL;
     int nstrings;
-    int avail;
-    int j;
-    int tocopy;
-    int len;
-    char printable [1024];
+    int j, w;
     char *retval = NULL;
     id3_ucs4_t const *ucs4 = NULL;
-    id3_latin1_t *latin1 = NULL;
 
-    memset (printable, '\0', 1024);
-    avail = 1024;
+    unsigned int bufmax1 = width * 3; /* Allow space for combining characters 
*/
+    unsigned int bufmax2 = bufmax1 + width; /* Allow space for padding */
+    id3_ucs4_t *buffer = malloc((bufmax2 + 1) * sizeof(id3_ucs4_t));
+    unsigned int bp = 0, ww;
+
     if (strcmp (what, ID3_FRAME_COMMENT) == 0)
     {
         /*There may be sth wrong. I did not fully understand how to use
@@ -584,17 +613,8 @@
         if (!frame) return (NULL);
         ucs4 = id3_field_getfullstring (&frame->fields[3]);
         if (!ucs4) return (NULL);
-        latin1 = id3_ucs4_latin1duplicate (ucs4);
-        if (!latin1 || strlen(latin1) == 0) return (NULL);
-        len = strlen(latin1);
-        if (avail > len)
-            tocopy = len;
-        else
-            tocopy = 0;
-        if (!tocopy) return (NULL);
-        avail-=tocopy;
-        strncat (printable, latin1, tocopy);
-        free (latin1);
+        while (*ucs4 && bp < bufmax1)
+            buffer[bp++] = *ucs4++;
     }
     
     else
@@ -609,30 +629,42 @@
             if (!ucs4) return (NULL);
             if (strcmp (what, ID3_FRAME_GENRE) == 0)
                 ucs4 = id3_genre_name(ucs4);
-            latin1 = id3_ucs4_latin1duplicate(ucs4);
-            if (!latin1) break;
-            len = strlen(latin1);
-            if (avail > len)
-                tocopy = len;
-            else
-                tocopy = 0;
-            if (!tocopy) break;
-            avail-=tocopy;
-            strncat (printable, latin1, tocopy);
-            free (latin1);
+            if (!ucs4) return (NULL);
+            while (*ucs4 && bp < bufmax1)
+                buffer[bp++] = *ucs4++;
         }
     }
-    retval = malloc (maxlen + 1);
-    if (!retval) return (NULL);
 
-    strncpy (retval, printable, maxlen);
-    retval[maxlen] = '\0';
+    /* If not in UTF-8 mode, replace high characters with U+00B7 */
+    if (!utf8_mode)
+        for (j = 0; j < bp; j++)
+            if (buffer[j] & ~0xff)
+                buffer[j] = 0xb7;
 
-    len = strlen(printable);
-    if (maxlen > len)
+    /* Replace non-printable characters and ensure required width is not 
exceeded */
+    ww = 0;
+    for (j = 0; j < bp; j++)
     {
-        memset (retval + len, ' ', maxlen - len);
+        if ((w = ucs4width(buffer[j])) < 0)
+        {
+            buffer[j] = ' ';
+            w = 1;
+        }
+        if (ww + w > width)
+            break;
+        ww += w;
     }
+    bp = j;
 
-    return (retval);
+    /* Pad to required width with spaces */
+    while (ww++ < width && bp < bufmax2)
+        buffer[bp++] = ' ';
+    buffer[bp] = 0;
+
+    /* Convert to UTF-8 or ISO-8859-1 */
+    retval = utf8_mode ?
+        (char *)id3_ucs4_utf8duplicate(buffer) :
+        (char *)id3_ucs4_latin1duplicate(buffer);
+    free(buffer);
+    return retval;
 }
diff -ru mpg321-0.2.10.1.orig/mpg321.h mpg321-0.2.10.1/mpg321.h
--- mpg321-0.2.10.1.orig/mpg321.h       2002-03-23 22:45:31.000000000 +0000
+++ mpg321-0.2.10.1/mpg321.h    2005-04-29 21:36:17.000000000 +0100
@@ -37,6 +37,7 @@
 #include <limits.h>
 #include <ao/ao.h>
 #include <mad.h>
+#include <id3tag.h>
 
 #define FAKEVERSION "0.59q"
 #define VERSIONDATE "2002/03/23"
@@ -195,4 +196,7 @@
 
 RETSIGTYPE handle_signals(int sig) ;
 
+/* UCS-only version of wcwidth */
+int ucs4width(id3_ucs4_t ucs);
+
 #endif /* _MPG321_H_ */
diff -ru mpg321-0.2.10.1.orig/ucs4width.c mpg321-0.2.10.1/ucs4width.c
--- mpg321-0.2.10.1.orig/ucs4width.c    2005-04-29 21:59:53.000000000 +0100
+++ mpg321-0.2.10.1/ucs4width.c 2005-04-29 20:31:09.000000000 +0100
@@ -0,0 +1,119 @@
+/*
+ * This is an implementation of wcwidth() and wcswidth() as defined in
+ * "The Single UNIX Specification, Version 2, The Open Group, 1997"
+ * <http://www.UNIX-systems.org/online.html>
+ *
+ * Markus Kuhn -- 2000-02-08 -- public domain
+ */
+
+/* Adapted for mpg321 by Edmund Grimley Evans.
+ */
+
+#include "mpg321.h"
+#include <id3tag.h>
+
+/* These functions define the column width of an ISO 10646 character
+ * as follows:
+ *
+ *    - The null character (U+0000) has a column width of 0.
+ *
+ *    - Other C0/C1 control characters and DEL will lead to a return
+ *      value of -1.
+ *
+ *    - Non-spacing and enclosing combining characters (general
+ *      category code Mn or Me in the Unicode database) have a
+ *      column width of 0.
+ *
+ *    - Spacing characters in the East Asian Wide (W) or East Asian
+ *      FullWidth (F) category as defined in Unicode Technical
+ *      Report #11 have a column width of 2.
+ *
+ *    - All remaining characters (including all printable
+ *      ISO 8859-1 and WGL4 characters, Unicode control characters,
+ *      etc.) have a column width of 1.
+ *
+ * This implementation assumes that wchar_t characters are encoded
+ * in ISO 10646.
+ */
+
+int ucs4width(id3_ucs4_t ucs)
+{
+  /* sorted list of non-overlapping intervals of non-spacing characters */
+  static const struct interval {
+    unsigned short first;
+    unsigned short last;
+  } combining[] = {
+    { 0x0300, 0x034E }, { 0x0360, 0x0362 }, { 0x0483, 0x0486 },
+    { 0x0488, 0x0489 }, { 0x0591, 0x05A1 }, { 0x05A3, 0x05B9 },
+    { 0x05BB, 0x05BD }, { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 },
+    { 0x05C4, 0x05C4 }, { 0x064B, 0x0655 }, { 0x0670, 0x0670 },
+    { 0x06D6, 0x06E4 }, { 0x06E7, 0x06E8 }, { 0x06EA, 0x06ED },
+    { 0x0711, 0x0711 }, { 0x0730, 0x074A }, { 0x07A6, 0x07B0 },
+    { 0x0901, 0x0902 }, { 0x093C, 0x093C }, { 0x0941, 0x0948 },
+    { 0x094D, 0x094D }, { 0x0951, 0x0954 }, { 0x0962, 0x0963 },
+    { 0x0981, 0x0981 }, { 0x09BC, 0x09BC }, { 0x09C1, 0x09C4 },
+    { 0x09CD, 0x09CD }, { 0x09E2, 0x09E3 }, { 0x0A02, 0x0A02 },
+    { 0x0A3C, 0x0A3C }, { 0x0A41, 0x0A42 }, { 0x0A47, 0x0A48 },
+    { 0x0A4B, 0x0A4D }, { 0x0A70, 0x0A71 }, { 0x0A81, 0x0A82 },
+    { 0x0ABC, 0x0ABC }, { 0x0AC1, 0x0AC5 }, { 0x0AC7, 0x0AC8 },
+    { 0x0ACD, 0x0ACD }, { 0x0B01, 0x0B01 }, { 0x0B3C, 0x0B3C },
+    { 0x0B3F, 0x0B3F }, { 0x0B41, 0x0B43 }, { 0x0B4D, 0x0B4D },
+    { 0x0B56, 0x0B56 }, { 0x0B82, 0x0B82 }, { 0x0BC0, 0x0BC0 },
+    { 0x0BCD, 0x0BCD }, { 0x0C3E, 0x0C40 }, { 0x0C46, 0x0C48 },
+    { 0x0C4A, 0x0C4D }, { 0x0C55, 0x0C56 }, { 0x0CBF, 0x0CBF },
+    { 0x0CC6, 0x0CC6 }, { 0x0CCC, 0x0CCD }, { 0x0D41, 0x0D43 },
+    { 0x0D4D, 0x0D4D }, { 0x0DCA, 0x0DCA }, { 0x0DD2, 0x0DD4 },
+    { 0x0DD6, 0x0DD6 }, { 0x0E31, 0x0E31 }, { 0x0E34, 0x0E3A },
+    { 0x0E47, 0x0E4E }, { 0x0EB1, 0x0EB1 }, { 0x0EB4, 0x0EB9 },
+    { 0x0EBB, 0x0EBC }, { 0x0EC8, 0x0ECD }, { 0x0F18, 0x0F19 },
+    { 0x0F35, 0x0F35 }, { 0x0F37, 0x0F37 }, { 0x0F39, 0x0F39 },
+    { 0x0F71, 0x0F7E }, { 0x0F80, 0x0F84 }, { 0x0F86, 0x0F87 },
+    { 0x0F90, 0x0F97 }, { 0x0F99, 0x0FBC }, { 0x0FC6, 0x0FC6 },
+    { 0x102D, 0x1030 }, { 0x1032, 0x1032 }, { 0x1036, 0x1037 },
+    { 0x1039, 0x1039 }, { 0x1058, 0x1059 }, { 0x17B7, 0x17BD },
+    { 0x17C6, 0x17C6 }, { 0x17C9, 0x17D3 }, { 0x18A9, 0x18A9 },
+    { 0x20D0, 0x20E3 }, { 0x302A, 0x302F }, { 0x3099, 0x309A },
+    { 0xFB1E, 0xFB1E }, { 0xFE20, 0xFE23 }
+  };
+  int min = 0;
+  int max = sizeof(combining) / sizeof(struct interval) - 1;
+  int mid;
+
+  if (ucs == 0)
+    return 0;
+
+  /* test for 8-bit control characters */
+  if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0))
+    return -1;
+
+  /* first quick check for Latin-1 etc. characters */
+  if (ucs < combining[0].first)
+    return 1;
+
+  /* binary search in table of non-spacing characters */
+  while (max >= min) {
+    mid = (min + max) / 2;
+    if (combining[mid].last < ucs)
+      min = mid + 1;
+    else if (combining[mid].first > ucs)
+      max = mid - 1;
+    else if (combining[mid].first <= ucs && combining[mid].last >= ucs)
+      return 0;
+  }
+
+  /* if we arrive here, ucs is not a combining or C0/C1 control character */
+
+  /* fast test for majority of non-wide scripts */
+  if (ucs < 0x1100)
+    return 1;
+
+  return 1 +
+    ((ucs >= 0x1100 && ucs <= 0x115f) || /* Hangul Jamo */
+     (ucs >= 0x2e80 && ucs <= 0xa4cf && (ucs & ~0x0011) != 0x300a &&
+      ucs != 0x303f) ||                  /* CJK ... Yi */
+     (ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */
+     (ucs >= 0xf900 && ucs <= 0xfaff) || /* CJK Compatibility Ideographs */
+     (ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */
+     (ucs >= 0xff00 && ucs <= 0xff5f) || /* Fullwidth Forms */
+     (ucs >= 0xffe0 && ucs <= 0xffe6));
+}

-- System Information:
Debian Release: 3.1
  APT prefers testing
  APT policy: (500, 'testing')
Architecture: i386 (i686)
Kernel: Linux 2.4.27-2-386
Locale: LANG=en_GB.UTF-8, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8)

Versions of packages mpg321 depends on:
ii  libao2                      0.8.6-1      Cross Platform Audio Output Librar
ii  libc6                       2.3.2.ds1-20 GNU C Library: Shared libraries an
ii  libid3tag0                  0.15.1b-4.1  ID3 tag reading library from the M
ii  libmad0                     0.15.1b-1.1  MPEG audio decoder library
ii  zlib1g                      1:1.2.2-3    compression library - runtime

-- no debconf information


-- 
To UNSUBSCRIBE, email to [EMAIL PROTECTED]
with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]

Reply via email to