changeset 157:8fc887cb56d0

Implement iconv support for converting from PSID de-facto latin-1/ISO-8859-* to whatever we are using currently (default to UTF-8). Support for iconv can be turned off via compile-time define (see Makefile).
author Matti Hamalainen <ccr@tnsp.org>
date Thu, 26 Oct 2017 01:46:34 +0300
parents 717d143612e2
children a8c24f1f460f
files Makefile README.txt sidinfo.c
diffstat 3 files changed, 52 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Thu Oct 26 01:45:02 2017 +0300
+++ b/Makefile	Thu Oct 26 01:46:34 2017 +0300
@@ -11,6 +11,8 @@
 CFLAGS += -DHAVE_CONFIG_H
 LDFLAGS +=
 
+CFLAGS += -DHAVE_ICONV
+
 CFLAGS += -DHAVE_STRING_H
 CFLAGS += -DHAVE_STDINT_H
 #CFLAGS += -DHAVE_SYS_TYPES_H
--- a/README.txt	Thu Oct 26 01:45:02 2017 +0300
+++ b/README.txt	Thu Oct 26 01:46:34 2017 +0300
@@ -25,6 +25,11 @@
  - th-libs library (included in the tar/zip packages,
    for building from mercurial repo, see "how to build")
 
+ - libiconv (optional, for converting ISO-8859/Latin-1 encoded
+   text used in HVSC SID files and STIL database to whatever
+   character set your system is using, like UTF-8.)
+
+
 For Linux -> Win32/64 cross-compilation I have used the standard
 MinGW packages from Debian Testing (wheezy):
 
--- a/sidinfo.c	Thu Oct 26 01:45:02 2017 +0300
+++ b/sidinfo.c	Thu Oct 26 01:46:34 2017 +0300
@@ -8,7 +8,7 @@
 #include "th_file.h"
 #include "sidlib.h"
 #ifdef HAVE_ICONV
-#include <iconv.h>
+#  include <iconv.h>
 #endif
 
 
@@ -19,6 +19,7 @@
 
 enum
 {
+    OFMT_QUOTED    = 0x0001,
     OFMT_FORMAT    = 0x0002,
 };
 
@@ -276,6 +277,29 @@
 }
 
 
+#ifdef HAVE_ICONV
+char *siConvertCharset(iconv_t ctx, const char *src)
+{
+    size_t srcLeft = strlen(src) + 1;
+    size_t outLeft = srcLeft * 2;
+    char *outBuf, *outPtr;
+    char *srcPtr = (char *) src;
+
+    if ((outBuf = outPtr = th_malloc(outLeft + 1)) == NULL)
+        return NULL;
+
+    while (srcLeft > 0)
+    {
+        size_t ret = iconv(ctx, &srcPtr, &srcLeft, &outPtr, &outLeft);
+        if (ret == (size_t) -1)
+            break;
+    }
+
+    return outBuf;
+}
+#endif
+
+
 int siItemFormatStrPutInt(th_vprintf_ctx *ctx, th_vprintf_putch vputch,
     const int value, const int f_radix, int f_flags, int f_width, int f_prec,
     const BOOL f_unsig, char *(f_alt)(const char *buf, const size_t blen, const int vret, const int flags))
@@ -694,7 +718,7 @@
 }
 
 
-static void siPrintPSIDInfoLine(FILE *outFile, BOOL *shown, const PSFStackItem *item, const char *d_str, const int d_int)
+static void siPrintPSIDInfoLine(FILE *outFile, BOOL *shown, const PSFStackItem *item, const char *d_str, const int d_int, const BOOL useConv)
 {
     const PSFOption *opt = &optPSOptions[item->cmd];
     char *fmt, *str;
@@ -721,19 +745,36 @@
 
     siPrintFieldPrefix(outFile, opt);
 
+#ifdef HAVE_ICONV
+    char *tmp;
+
+    if (setUseChConv && d_str != NULL && useConv)
+        tmp = siConvertCharset(setChConv, d_str);
+    else
+        tmp = th_strdup(d_str);
+
+    str = siItemFormatStrPrint(fmt, opt, tmp, d_int);
+#else
+    (void) useConv;
     str = siItemFormatStrPrint(fmt, opt, d_str, d_int);
+#endif
+
     if (str != NULL)
         fputs(str, outFile);
 
     siPrintFieldSeparator(outFile);
     th_free(str);
 
+#ifdef HAVE_ICONV
+    th_free(tmp);
+#endif
+
     *shown = TRUE;
 }
 
 
-#define PRS(d_str, d_conv) siPrintPSIDInfoLine(outFile, shown, item, d_str, -1)
-#define PRI(d_int) siPrintPSIDInfoLine(outFile, shown, item, NULL, d_int)
+#define PRS(d_str, d_conv) siPrintPSIDInfoLine(outFile, shown, item, d_str, -1, d_conv)
+#define PRI(d_int) siPrintPSIDInfoLine(outFile, shown, item, NULL, d_int, FALSE)
 
 
 static void siPrintPSIDInformationField(FILE *outFile, const char *filename, const PSIDHeader *psid, BOOL *shown, const PSFStackItem *item)