]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - cups/transcode.c
Merge changes from CUPS 1.5svn-r9374.
[thirdparty/cups.git] / cups / transcode.c
index b0f895cd6a02fd3e226effe173583a80dbb13141..a24c8a851c66b68b350ade7f99fef8e127bd813c 100644 (file)
@@ -1,9 +1,9 @@
 /*
  * "$Id: transcode.c 7560 2008-05-13 06:34:04Z mike $"
  *
- *   Transcoding support for the Common UNIX Printing System (CUPS).
+ *   Transcoding support for CUPS.
  *
- *   Copyright 2007-2008 by Apple Inc.
+ *   Copyright 2007-2010 by Apple Inc.
  *   Copyright 1997-2007 by Easy Software Products.
  *
  *   These coded instructions, statements, and computer programs are the
  * Contents:
  *
  *   _cupsCharmapFlush() - Flush all character set maps out of cache.
- *   _cupsCharmapFree()  - Free a character set map.
- *   _cupsCharmapGet()   - Get a character set map.
  *   cupsCharsetToUTF8() - Convert legacy character set to UTF-8.
  *   cupsUTF8ToCharset() - Convert UTF-8 to legacy character set.
  *   cupsUTF8ToUTF32()   - Convert UTF-8 to UTF-32.
  *   cupsUTF32ToUTF8()   - Convert UTF-32 to UTF-8.
- *   compare_wide()      - Compare key for wide (VBCS) match.
- *   conv_sbcs_to_utf8() - Convert legacy SBCS to UTF-8.
- *   conv_utf8_to_sbcs() - Convert UTF-8 to legacy SBCS.
- *   conv_utf8_to_vbcs() - Convert UTF-8 to legacy DBCS/VBCS.
- *   conv_vbcs_to_utf8() - Convert legacy DBCS/VBCS to UTF-8.
- *   free_sbcs_charmap() - Free memory used by a single byte character set.
- *   free_vbcs_charmap() - Free memory used by a variable byte character set.
- *   get_charmap()       - Lookup or get a character set map (private).
- *   get_charmap_count() - Count lines in a charmap file.
- *   get_sbcs_charmap()  - Get SBCS Charmap.
- *   get_vbcs_charmap()  - Get DBCS/VBCS Charmap.
  */
 
 /*
  * Include necessary headers...
  */
 
-#include "globals.h"
-#include "debug.h"
+#include "cups-private.h"
 #include <limits.h>
-#include <stdlib.h>
-#include <errno.h>
 #include <time.h>
+#ifdef HAVE_ICONV_H
+#  include <iconv.h>
+#endif /* HAVE_ICONV_H */
 
 
 /*
  * Local globals...
  */
 
-#ifdef HAVE_PTHREAD_H
-static pthread_mutex_t map_mutex = PTHREAD_MUTEX_INITIALIZER;
+#ifdef HAVE_ICONV_H
+static _cups_mutex_t   map_mutex = _CUPS_MUTEX_INITIALIZER;
                                        /* Mutex to control access to maps */
-#endif /* HAVE_PTHREAD_H */
-static _cups_cmap_t    *cmap_cache = NULL;
-                                       /* SBCS Charmap Cache */
-static _cups_vmap_t    *vmap_cache = NULL;
-                                       /* VBCS Charmap Cache */
-
-
-/*
- * Local functions...
- */
-
-static int             compare_wide(const void *k1, const void *k2);
-static int             conv_sbcs_to_utf8(cups_utf8_t *dest,
-                                         const cups_sbcs_t *src,
-                                         int maxout,
-                                         const cups_encoding_t encoding);
-static int             conv_utf8_to_sbcs(cups_sbcs_t *dest,
-                                         const cups_utf8_t *src,
-                                         int maxout,
-                                         const cups_encoding_t encoding);
-static int             conv_utf8_to_vbcs(cups_sbcs_t *dest,
-                                         const cups_utf8_t *src,
-                                         int maxout,
-                                         const cups_encoding_t encoding);
-static int             conv_vbcs_to_utf8(cups_utf8_t *dest,
-                                         const cups_sbcs_t *src,
-                                         int maxout,
-                                         const cups_encoding_t encoding);
-static void            free_sbcs_charmap(_cups_cmap_t *sbcs);
-static void            free_vbcs_charmap(_cups_vmap_t *vbcs);
-static void            *get_charmap(const cups_encoding_t encoding);
-static int             get_charmap_count(cups_file_t *fp);
-static _cups_cmap_t    *get_sbcs_charmap(const cups_encoding_t encoding,
-                                         const char *filename);
-static _cups_vmap_t    *get_vbcs_charmap(const cups_encoding_t encoding,
-                                         const char *filename);
+static iconv_t         map_from_utf8 = (iconv_t)-1;
+                                       /* Convert from UTF-8 to charset */
+static iconv_t         map_to_utf8 = (iconv_t)-1;
+                                       /* Convert from charset to UTF-8 */
+static cups_encoding_t map_encoding = CUPS_AUTO_ENCODING;
+                                       /* Which charset is cached */
+#endif /* HAVE_ICONV_H */
 
 
 /*
@@ -100,178 +58,55 @@ static _cups_vmap_t       *get_vbcs_charmap(const cups_encoding_t encoding,
 void
 _cupsCharmapFlush(void)
 {
-  _cups_cmap_t *cmap,                  /* Legacy SBCS / Unicode Charset Map */
-               *cnext;                 /* Next Legacy SBCS Charset Map */
-  _cups_vmap_t *vmap,                  /* Legacy VBCS / Unicode Charset Map */
-               *vnext;                 /* Next Legacy VBCS Charset Map */
-
-
-#ifdef HAVE_PTHREAD_H
-  pthread_mutex_lock(&map_mutex);
-#endif /* HAVE_PTHREAD_H */
-
- /*
-  * Loop through SBCS charset map cache, free all memory...
-  */
-
-  for (cmap = cmap_cache; cmap; cmap = cnext)
-  {
-    cnext = cmap->next;
-
-    free_sbcs_charmap(cmap);
-  }
-
-  cmap_cache = NULL;
-
- /*
-  * Loop through DBCS/VBCS charset map cache, free all memory...
-  */
-
-  for (vmap = vmap_cache; vmap; vmap = vnext)
-  {
-    vnext = vmap->next;
-
-    free_vbcs_charmap(vmap);
-  }
-
-  vmap_cache = NULL;
-
-#ifdef HAVE_PTHREAD_H
-  pthread_mutex_unlock(&map_mutex);
-#endif /* HAVE_PTHREAD_H */
-}
-
-
-/*
- * '_cupsCharmapFree()' - Free a character set map.
- *
- * This does not actually free; use '_cupsCharmapFlush()' for that.
- */
-
-void
-_cupsCharmapFree(
-    const cups_encoding_t encoding)    /* I - Encoding */
-{
-  _cups_cmap_t *cmap;                  /* Legacy SBCS / Unicode Charset Map */
-  _cups_vmap_t *vmap;                  /* Legacy VBCS / Unicode Charset Map */
-
-
- /*
-  * See if we already have this SBCS charset map loaded...
-  */
-
-#ifdef HAVE_PTHREAD_H
-  pthread_mutex_lock(&map_mutex);
-#endif /* HAVE_PTHREAD_H */
-
-  for (cmap = cmap_cache; cmap; cmap = cmap->next)
+#ifdef HAVE_ICONV_H
+  if (map_from_utf8 != (iconv_t)-1)
   {
-    if (cmap->encoding == encoding)
-    {
-      if (cmap->used > 0)
-       cmap->used --;
-      break;
-    }
+    iconv_close(map_from_utf8);
+    map_from_utf8 = (iconv_t)-1;
   }
 
- /*
-  * See if we already have this DBCS/VBCS charset map loaded...
-  */
-
-  for (vmap = vmap_cache; vmap; vmap = vmap->next)
+  if (map_to_utf8 != (iconv_t)-1)
   {
-    if (vmap->encoding == encoding)
-    {
-      if (vmap->used > 0)
-       vmap->used --;
-      break;
-    }
+    iconv_close(map_to_utf8);
+    map_to_utf8 = (iconv_t)-1;
   }
 
-#ifdef HAVE_PTHREAD_H
-  pthread_mutex_unlock(&map_mutex);
-#endif /* HAVE_PTHREAD_H */
-}
-
-
-/*
- * '_cupsCharmapGet()' - Get a character set map.
- *
- * This code handles single-byte (SBCS), double-byte (DBCS), and
- * variable-byte (VBCS) character sets _without_ charset escapes...
- * This code does not handle multiple-byte character sets (MBCS)
- * (such as ISO-2022-JP) with charset switching via escapes...
- */
-
-void *                                 /* O - Charset map pointer */
-_cupsCharmapGet(
-    const cups_encoding_t encoding)    /* I - Encoding */
-{
-  void *charmap;                       /* Charset map pointer */
-
-
-  DEBUG_printf(("_cupsCharmapGet(encoding=%d)\n", encoding));
-
- /*
-  * Check for valid arguments...
-  */
-
-  if (encoding < 0 || encoding >= CUPS_ENCODING_VBCS_END)
-  {
-    DEBUG_puts("    Bad encoding, returning NULL!");
-    return (NULL);
-  }
-
- /*
-  * Lookup or get the charset map pointer and return...
-  */
-
-#ifdef HAVE_PTHREAD_H
-  pthread_mutex_lock(&map_mutex);
-#endif /* HAVE_PTHREAD_H */
-
-  charmap = get_charmap(encoding);
-
-#ifdef HAVE_PTHREAD_H
-  pthread_mutex_unlock(&map_mutex);
-#endif /* HAVE_PTHREAD_H */
-
-  return (charmap);
+  map_encoding = CUPS_AUTO_ENCODING;
+#endif /* HAVE_ICONV_H */
 }
 
 
 /*
  * 'cupsCharsetToUTF8()' - Convert legacy character set to UTF-8.
- *
- * This code handles single-byte (SBCS), double-byte (DBCS), and
- * variable-byte (VBCS) character sets _without_ charset escapes...
- * This code does not handle multiple-byte character sets (MBCS)
- * (such as ISO-2022-JP) with charset switching via escapes...
  */
 
 int                                    /* O - Count or -1 on error */
 cupsCharsetToUTF8(
-    cups_utf8_t *dest,                 /* O - Target string */
-    const char *src,                   /* I - Source string */
-    const int maxout,                  /* I - Max output */
+    cups_utf8_t           *dest,       /* O - Target string */
+    const char            *src,                /* I - Source string */
+    const int             maxout,      /* I - Max output */
     const cups_encoding_t encoding)    /* I - Encoding */
 {
-  int  bytes;                          /* Number of bytes converted */
+  cups_utf8_t  *destptr;               /* Pointer into UTF-8 buffer */
+#ifdef HAVE_ICONV_H 
+  size_t       srclen,                 /* Length of source string */
+               outBytesLeft;           /* Bytes remaining in output buffer */
+#endif /* HAVE_ICONV_H */
 
 
  /*
   * Check for valid arguments...
   */
 
-  DEBUG_printf(("cupsCharsetToUTF8(dest=%p, src=\"%s\", maxout=%d, encoding=%d)\n",
+  DEBUG_printf(("2cupsCharsetToUTF8(dest=%p, src=\"%s\", maxout=%d, encoding=%d)",
                dest, src, maxout, encoding));
 
-  if (dest)
-    *dest = '\0';
-
-  if (!dest || !src || maxout < 1 || maxout > CUPS_MAX_USTRING)
+  if (!dest || !src || maxout < 1)
   {
-    DEBUG_puts("    Bad arguments, returning -1");
+    if (dest)
+      *dest = '\0';
+
+    DEBUG_puts("3cupsCharsetToUTF8: Bad arguments, returning -1");
     return (-1);
   }
 
@@ -279,8 +114,8 @@ cupsCharsetToUTF8(
   * Handle identity conversions...
   */
 
-  if (encoding == CUPS_UTF8 ||
-      encoding < 0 || encoding >= CUPS_ENCODING_VBCS_END)
+  if (encoding == CUPS_UTF8 || encoding <= CUPS_US_ASCII ||
+      encoding >= CUPS_ENCODING_VBCS_END)
   {
     strlcpy((char *)dest, src, maxout);
     return ((int)strlen((char *)dest));
@@ -290,14 +125,14 @@ cupsCharsetToUTF8(
   * Handle ISO-8859-1 to UTF-8 directly...
   */
 
+  destptr = dest;
+
   if (encoding == CUPS_ISO8859_1)
   {
     int                ch;                     /* Character from string */
-    cups_utf8_t        *destptr,               /* Pointer into UTF-8 buffer */
-               *destend;               /* End of UTF-8 buffer */
+    cups_utf8_t        *destend;               /* End of UTF-8 buffer */
 
 
-    destptr = dest;
     destend = dest + maxout - 2;
 
     while (*src && destptr < destend)
@@ -322,30 +157,47 @@ cupsCharsetToUTF8(
   * Convert input legacy charset to UTF-8...
   */
 
-#ifdef HAVE_PTHREAD_H
-  pthread_mutex_lock(&map_mutex);
-#endif /* HAVE_PTHREAD_H */
+#ifdef HAVE_ICONV_H
+  _cupsMutexLock(&map_mutex);
 
-  if (encoding < CUPS_ENCODING_SBCS_END)
-    bytes = conv_sbcs_to_utf8(dest, (cups_sbcs_t *)src, maxout, encoding);
-  else
-    bytes = conv_vbcs_to_utf8(dest, (cups_sbcs_t *)src, maxout, encoding);
+  if (map_encoding != encoding)
+  {
+    _cupsCharmapFlush();
 
-#ifdef HAVE_PTHREAD_H
-  pthread_mutex_unlock(&map_mutex);
-#endif /* HAVE_PTHREAD_H */
+    map_from_utf8 = iconv_open(_cupsEncodingName(encoding), "UTF-8");
+    map_to_utf8   = iconv_open("UTF-8", _cupsEncodingName(encoding));
+    map_encoding     = encoding;
+  }
+
+  if (map_to_utf8 != (iconv_t)-1)
+  {
+    srclen       = strlen(src);
+    outBytesLeft = maxout - 1;
+
+    iconv(map_to_utf8, (char **)&src, &srclen, (char **)&destptr,
+         &outBytesLeft);
+    *destptr = '\0';
+
+    _cupsMutexUnlock(&map_mutex);
+
+    return ((int)(destptr - dest));
+  }
 
-  return (bytes);
+  _cupsMutexUnlock(&map_mutex);
+#endif /* HAVE_ICONV_H */
+
+ /*
+  * No iconv() support, so error out...
+  */
+
+  *destptr = '\0';
+
+  return (-1);
 }
 
 
 /*
  * 'cupsUTF8ToCharset()' - Convert UTF-8 to legacy character set.
- *
- * This code handles single-byte (SBCS), double-byte (DBCS), and
- * variable-byte (VBCS) character sets _without_ charset escapes...
- * This code does not handle multiple-byte character sets (MBCS)
- * (such as ISO-2022-JP) with charset switching via escapes...
  */
 
 int                                    /* O - Count or -1 on error */
@@ -355,14 +207,18 @@ cupsUTF8ToCharset(
     const int            maxout,       /* I - Max output */
     const cups_encoding_t encoding)    /* I - Encoding */
 {
-  int  bytes;                          /* Number of bytes converted */
+  char         *destptr;               /* Pointer into destination */
+#ifdef HAVE_ICONV_H 
+  size_t       srclen,                 /* Length of source string */
+               outBytesLeft;           /* Bytes remaining in output buffer */
+#endif /* HAVE_ICONV_H */
 
 
  /*
   * Check for valid arguments...
   */
 
-  if (!dest || !src || maxout < 1 || maxout > CUPS_MAX_USTRING)
+  if (!dest || !src || maxout < 1)
   {
     if (dest)
       *dest = '\0';
@@ -374,8 +230,8 @@ cupsUTF8ToCharset(
   * Handle identity conversions...
   */
 
-  if (encoding == CUPS_UTF8 ||
-      encoding < 0 || encoding >= CUPS_ENCODING_VBCS_END)
+  if (encoding == CUPS_UTF8 || encoding <= CUPS_US_ASCII ||
+      encoding >= CUPS_ENCODING_VBCS_END)
   {
     strlcpy(dest, (char *)src, maxout);
     return ((int)strlen(dest));
@@ -385,14 +241,14 @@ cupsUTF8ToCharset(
   * Handle UTF-8 to ISO-8859-1 directly...
   */
 
+  destptr = dest;
+
   if (encoding == CUPS_ISO8859_1)
   {
     int                ch;                     /* Character from string */
-    char       *destptr,               /* Pointer into ISO-8859-1 buffer */
-               *destend;               /* End of ISO-8859-1 buffer */
+    char       *destend;               /* End of ISO-8859-1 buffer */
 
 
-    destptr = dest;
     destend = dest + maxout - 1;
 
     while (*src && destptr < destend)
@@ -420,24 +276,45 @@ cupsUTF8ToCharset(
     return ((int)(destptr - dest));
   }
 
+#ifdef HAVE_ICONV_H
  /*
   * Convert input UTF-8 to legacy charset...
   */
 
-#ifdef HAVE_PTHREAD_H
-  pthread_mutex_lock(&map_mutex);
-#endif /* HAVE_PTHREAD_H */
+  _cupsMutexLock(&map_mutex);
 
-  if (encoding < CUPS_ENCODING_SBCS_END)
-    bytes = conv_utf8_to_sbcs((cups_sbcs_t *)dest, src, maxout, encoding);
-  else
-    bytes = conv_utf8_to_vbcs((cups_sbcs_t *)dest, src, maxout, encoding);
+  if (map_encoding != encoding)
+  {
+    _cupsCharmapFlush();
+
+    map_from_utf8 = iconv_open(_cupsEncodingName(encoding), "UTF-8");
+    map_to_utf8   = iconv_open("UTF-8", _cupsEncodingName(encoding));
+    map_encoding  = encoding;
+  }
 
-#ifdef HAVE_PTHREAD_H
-  pthread_mutex_unlock(&map_mutex);
-#endif /* HAVE_PTHREAD_H */
+  if (map_from_utf8 != (iconv_t)-1)
+  {
+    srclen       = strlen((char *)src);
+    outBytesLeft = maxout - 1;
 
-  return (bytes);
+    iconv(map_from_utf8, (char **)&src, &srclen, &destptr, &outBytesLeft);
+    *destptr = '\0';
+
+    _cupsMutexUnlock(&map_mutex);
+
+    return ((int)(destptr - dest));
+  }
+
+  _cupsMutexUnlock(&map_mutex);
+#endif /* HAVE_ICONV_H */
+
+ /*
+  * No iconv() support, so error out...
+  */
+
+  *destptr = '\0';
+
+  return (-1);
 }
 
 
@@ -473,25 +350,23 @@ cupsUTF8ToUTF32(
   * Check for valid arguments and clear output...
   */
 
-  DEBUG_printf(("cupsUTF8ToUTF32(dest=%p, src=\"%s\", maxout=%d)\n", dest,
-                src ? (const char *)src : "(null)", maxout));
+  DEBUG_printf(("2cupsUTF8ToUTF32(dest=%p, src=\"%s\", maxout=%d)", dest,
+                src, maxout));
 
   if (dest)
     *dest = 0;
 
   if (!dest || !src || maxout < 1 || maxout > CUPS_MAX_USTRING)
   {
-    DEBUG_puts("cupsUTF8ToUTF32: Returning -1 (bad arguments)");
+    DEBUG_puts("3cupsUTF8ToUTF32: Returning -1 (bad arguments)");
 
     return (-1);
   }
 
  /*
-  * Convert input UTF-8 to output UTF-32 (and insert BOM)...
+  * Convert input UTF-8 to output UTF-32...
   */
 
-  *dest++ = 0xfeff;
-
   for (i = maxout - 1; *src && i > 0; i --)
   {
     ch = *src++;
@@ -508,7 +383,7 @@ cupsUTF8ToUTF32(
 
       *dest++ = ch;
 
-      DEBUG_printf(("cupsUTF8ToUTF32: %02x => %08X\n", src[-1], ch));
+      DEBUG_printf(("4cupsUTF8ToUTF32: %02x => %08X", src[-1], ch));
       continue;
     }
     else if ((ch & 0xe0) == 0xc0)
@@ -520,7 +395,7 @@ cupsUTF8ToUTF32(
       next = *src++;
       if ((next & 0xc0) != 0x80)
       {
-        DEBUG_puts("cupsUTF8ToUTF32: Returning -1 (bad UTF-8 sequence)");
+        DEBUG_puts("3cupsUTF8ToUTF32: Returning -1 (bad UTF-8 sequence)");
 
        return (-1);
       }
@@ -533,14 +408,14 @@ cupsUTF8ToUTF32(
 
       if (ch32 < 0x80)
       {
-        DEBUG_puts("cupsUTF8ToUTF32: Returning -1 (bad UTF-8 sequence)");
+        DEBUG_puts("3cupsUTF8ToUTF32: Returning -1 (bad UTF-8 sequence)");
 
        return (-1);
       }
 
       *dest++ = ch32;
 
-      DEBUG_printf(("cupsUTF8ToUTF32: %02x %02x => %08X\n",
+      DEBUG_printf(("4cupsUTF8ToUTF32: %02x %02x => %08X",
                     src[-2], src[-1], (unsigned)ch32));
     }
     else if ((ch & 0xf0) == 0xe0)
@@ -552,7 +427,7 @@ cupsUTF8ToUTF32(
       next = *src++;
       if ((next & 0xc0) != 0x80)
       {
-        DEBUG_puts("cupsUTF8ToUTF32: Returning -1 (bad UTF-8 sequence)");
+        DEBUG_puts("3cupsUTF8ToUTF32: Returning -1 (bad UTF-8 sequence)");
 
        return (-1);
       }
@@ -562,7 +437,7 @@ cupsUTF8ToUTF32(
       next = *src++;
       if ((next & 0xc0) != 0x80)
       {
-        DEBUG_puts("cupsUTF8ToUTF32: Returning -1 (bad UTF-8 sequence)");
+        DEBUG_puts("3cupsUTF8ToUTF32: Returning -1 (bad UTF-8 sequence)");
 
        return (-1);
       }
@@ -575,14 +450,14 @@ cupsUTF8ToUTF32(
 
       if (ch32 < 0x800)
       {
-        DEBUG_puts("cupsUTF8ToUTF32: Returning -1 (bad UTF-8 sequence)");
+        DEBUG_puts("3cupsUTF8ToUTF32: Returning -1 (bad UTF-8 sequence)");
 
        return (-1);
       }
 
       *dest++ = ch32;
 
-      DEBUG_printf(("cupsUTF8ToUTF32: %02x %02x %02x => %08X\n",
+      DEBUG_printf(("4cupsUTF8ToUTF32: %02x %02x %02x => %08X",
                     src[-3], src[-2], src[-1], (unsigned)ch32));
     }
     else if ((ch & 0xf8) == 0xf0)
@@ -594,7 +469,7 @@ cupsUTF8ToUTF32(
       next = *src++;
       if ((next & 0xc0) != 0x80)
       {
-        DEBUG_puts("cupsUTF8ToUTF32: Returning -1 (bad UTF-8 sequence)");
+        DEBUG_puts("3cupsUTF8ToUTF32: Returning -1 (bad UTF-8 sequence)");
 
        return (-1);
       }
@@ -604,7 +479,7 @@ cupsUTF8ToUTF32(
       next = *src++;
       if ((next & 0xc0) != 0x80)
       {
-        DEBUG_puts("cupsUTF8ToUTF32: Returning -1 (bad UTF-8 sequence)");
+        DEBUG_puts("3cupsUTF8ToUTF32: Returning -1 (bad UTF-8 sequence)");
 
        return (-1);
       }
@@ -614,7 +489,7 @@ cupsUTF8ToUTF32(
       next = *src++;
       if ((next & 0xc0) != 0x80)
       {
-        DEBUG_puts("cupsUTF8ToUTF32: Returning -1 (bad UTF-8 sequence)");
+        DEBUG_puts("3cupsUTF8ToUTF32: Returning -1 (bad UTF-8 sequence)");
 
        return (-1);
       }
@@ -627,14 +502,14 @@ cupsUTF8ToUTF32(
 
       if (ch32 < 0x10000)
       {
-        DEBUG_puts("cupsUTF8ToUTF32: Returning -1 (bad UTF-8 sequence)");
+        DEBUG_puts("3cupsUTF8ToUTF32: Returning -1 (bad UTF-8 sequence)");
 
        return (-1);
       }
 
       *dest++ = ch32;
 
-      DEBUG_printf(("cupsUTF8ToUTF32: %02x %02x %02x %02x => %08X\n",
+      DEBUG_printf(("4cupsUTF8ToUTF32: %02x %02x %02x %02x => %08X",
                     src[-4], src[-3], src[-2], src[-1], (unsigned)ch32));
     }
     else
@@ -643,7 +518,7 @@ cupsUTF8ToUTF32(
       * More than 4-octet (invalid UTF-8 sequence)...
       */
 
-      DEBUG_puts("cupsUTF8ToUTF32: Returning -1 (bad UTF-8 sequence)");
+      DEBUG_puts("3cupsUTF8ToUTF32: Returning -1 (bad UTF-8 sequence)");
 
       return (-1);
     }
@@ -658,7 +533,7 @@ cupsUTF8ToUTF32(
 
   *dest = 0;
 
-  DEBUG_printf(("cupsUTF8ToUTF32: Returning %d characters\n", maxout - 1 - i));
+  DEBUG_printf(("3cupsUTF8ToUTF32: Returning %d characters", maxout - 1 - i));
 
   return (maxout - 1 - i);
 }
@@ -696,7 +571,7 @@ cupsUTF32ToUTF8(
   * Check for valid arguments and clear output...
   */
 
-  DEBUG_printf(("cupsUTF32ToUTF8(dest=%p, src=%p, maxout=%d)\n", dest, src,
+  DEBUG_printf(("2cupsUTF32ToUTF8(dest=%p, src=%p, maxout=%d)", dest, src,
                 maxout));
 
   if (dest)
@@ -704,7 +579,7 @@ cupsUTF32ToUTF8(
 
   if (!dest || !src || maxout < 1)
   {
-    DEBUG_puts("cupsUTF32ToUTF8: Returning -1 (bad args)");
+    DEBUG_puts("3cupsUTF32ToUTF8: Returning -1 (bad args)");
 
     return (-1);
   }
@@ -716,7 +591,7 @@ cupsUTF32ToUTF8(
   start = dest;
   swap  = *src == 0xfffe0000;
 
-  DEBUG_printf(("cupsUTF32ToUTF8: swap=%d\n", swap));
+  DEBUG_printf(("4cupsUTF32ToUTF8: swap=%d", swap));
 
   if (*src == 0xfffe0000 || *src == 0xfeff)
     src ++;
@@ -743,7 +618,7 @@ cupsUTF32ToUTF8(
 
     if (ch > 0x10ffff)
     {
-      DEBUG_puts("cupsUTF32ToUTF8: Returning -1 (character out of range)");
+      DEBUG_puts("3cupsUTF32ToUTF8: Returning -1 (character out of range)");
 
       return (-1);
     }
@@ -761,7 +636,7 @@ cupsUTF32ToUTF8(
       *dest++ = (cups_utf8_t)ch;
       i --;
 
-      DEBUG_printf(("cupsUTF32ToUTF8: %08x => %02x\n", (unsigned)ch, dest[-1]));
+      DEBUG_printf(("4cupsUTF32ToUTF8: %08x => %02x", (unsigned)ch, dest[-1]));
     }
     else if (ch < 0x800)
     {
@@ -771,7 +646,7 @@ cupsUTF32ToUTF8(
 
       if (i < 2)
       {
-        DEBUG_puts("cupsUTF32ToUTF8: Returning -1 (too long 2)");
+        DEBUG_puts("3cupsUTF32ToUTF8: Returning -1 (too long 2)");
 
         return (-1);
       }
@@ -780,7 +655,7 @@ cupsUTF32ToUTF8(
       *dest++ = (cups_utf8_t)(0x80 | (ch & 0x3f));
       i -= 2;
 
-      DEBUG_printf(("cupsUTF32ToUTF8: %08x => %02x %02x\n", (unsigned)ch,
+      DEBUG_printf(("4cupsUTF32ToUTF8: %08x => %02x %02x", (unsigned)ch,
                     dest[-2], dest[-1]));
     }
     else if (ch < 0x10000)
@@ -791,7 +666,7 @@ cupsUTF32ToUTF8(
 
       if (i < 3)
       {
-        DEBUG_puts("cupsUTF32ToUTF8: Returning -1 (too long 3)");
+        DEBUG_puts("3cupsUTF32ToUTF8: Returning -1 (too long 3)");
 
         return (-1);
       }
@@ -801,7 +676,7 @@ cupsUTF32ToUTF8(
       *dest++ = (cups_utf8_t)(0x80 | (ch & 0x3f));
       i -= 3;
 
-      DEBUG_printf(("cupsUTF32ToUTF8: %08x => %02x %02x %02x\n", (unsigned)ch,
+      DEBUG_printf(("4cupsUTF32ToUTF8: %08x => %02x %02x %02x", (unsigned)ch,
                     dest[-3], dest[-2], dest[-1]));
     }
     else
@@ -811,7 +686,11 @@ cupsUTF32ToUTF8(
       */
 
       if (i < 4)
+      {
+        DEBUG_puts("3cupsUTF32ToUTF8: Returning -1 (too long 4)");
+
         return (-1);
+      }
 
       *dest++ = (cups_utf8_t)(0xf0 | ((ch >> 18) & 0x07));
       *dest++ = (cups_utf8_t)(0x80 | ((ch >> 12) & 0x3f));
@@ -819,14 +698,14 @@ cupsUTF32ToUTF8(
       *dest++ = (cups_utf8_t)(0x80 | (ch & 0x3f));
       i -= 4;
 
-      DEBUG_printf(("cupsUTF32ToUTF8: %08x => %02x %02x %02x %02x\n",
+      DEBUG_printf(("4cupsUTF32ToUTF8: %08x => %02x %02x %02x %02x",
                     (unsigned)ch, dest[-4], dest[-3], dest[-2], dest[-1]));
     }
   }
 
   *dest = '\0';
 
-  DEBUG_printf(("cupsUTF32ToUTF8: Returning %d\n", (int)(dest - start)));
+  DEBUG_printf(("3cupsUTF32ToUTF8: Returning %d", (int)(dest - start)));
 
   return ((int)(dest - start));
 }
@@ -955,7 +834,7 @@ conv_utf8_to_sbcs(
   * Convert internal UCS-4 to SBCS legacy charset (and delete BOM)...
   */
 
-  for (workptr = work + 1, start = dest; *workptr && maxout > 1; maxout --)
+  for (workptr = work, start = dest; *workptr && maxout > 0; maxout --)
   {
     unichar = *workptr++;
     if (!unichar)
@@ -1014,8 +893,8 @@ conv_utf8_to_vbcs(
                *workptr;               /* Pointer into string */
 
 
-  DEBUG_printf(("conv_utf8_to_vbcs(dest=%p, src=\"%s\", maxout=%d, "
-                "encoding=%d)\n", dest, src, maxout, encoding));
+  DEBUG_printf(("7conv_utf8_to_vbcs(dest=%p, src=\"%s\", maxout=%d, "
+                "encoding=%d)", dest, src, maxout, encoding));
 
  /*
   * Find legacy charset map in cache...
@@ -1023,7 +902,7 @@ conv_utf8_to_vbcs(
 
   if ((vmap = (_cups_vmap_t *)get_charmap(encoding)) == NULL)
   {
-    DEBUG_puts("conv_utf8_to_vbcs: Returning -1 (no charmap)");
+    DEBUG_puts("8conv_utf8_to_vbcs: Returning -1 (no charmap)");
 
     return (-1);
   }
@@ -1034,7 +913,7 @@ conv_utf8_to_vbcs(
 
   if (cupsUTF8ToUTF32(work, src, CUPS_MAX_USTRING) < 0)
   {
-    DEBUG_puts("conv_utf8_to_vbcs: Returning -1 (Unable to convert to UTF-32)");
+    DEBUG_puts("8conv_utf8_to_vbcs: Returning -1 (Unable to convert to UTF-32)");
 
     return (-1);
   }
@@ -1043,7 +922,7 @@ conv_utf8_to_vbcs(
   * Convert internal UCS-4 to VBCS legacy charset (and delete BOM)...
   */
 
-  for (start = dest, workptr = work + 1; *workptr && maxout > 1; maxout --)
+  for (start = dest, workptr = work; *workptr && maxout > 0; maxout --)
   {
     unichar = *workptr++;
 
@@ -1055,7 +934,7 @@ conv_utf8_to_vbcs(
     {
       *dest++ = (cups_sbcs_t)unichar;
 
-      DEBUG_printf(("conv_utf8_to_vbcs: %08x => %02X\n", (unsigned)unichar,
+      DEBUG_printf(("9conv_utf8_to_vbcs: %08x => %02X", (unsigned)unichar,
                     dest[-1]));
 
       continue;
@@ -1083,7 +962,7 @@ conv_utf8_to_vbcs(
     {
       if (maxout < 5)
       {
-        DEBUG_puts("conv_utf8_to_vbcs: Returning -1 (out of space)");
+        DEBUG_puts("8conv_utf8_to_vbcs: Returning -1 (out of space)");
 
         return (-1);
       }
@@ -1095,14 +974,14 @@ conv_utf8_to_vbcs(
 
       maxout -= 3;
 
-      DEBUG_printf(("conv_utf8_to_vbcs: %08x => %02X %02X %02X %02X\n",
+      DEBUG_printf(("9conv_utf8_to_vbcs: %08x => %02X %02X %02X %02X",
                     (unsigned)unichar, dest[-4], dest[-3], dest[-2], dest[-1]));
     }
     else if (legchar > 0xffff)
     {
       if (maxout < 4)
       {
-        DEBUG_puts("conv_utf8_to_vbcs: Returning -1 (out of space)");
+        DEBUG_puts("8conv_utf8_to_vbcs: Returning -1 (out of space)");
 
         return (-1);
       }
@@ -1113,7 +992,7 @@ conv_utf8_to_vbcs(
 
       maxout -= 2;
 
-      DEBUG_printf(("conv_utf8_to_vbcs: %08x => %02X %02X %02X\n",
+      DEBUG_printf(("9conv_utf8_to_vbcs: %08x => %02X %02X %02X",
                     (unsigned)unichar, dest[-3], dest[-2], dest[-1]));
     }
     else if (legchar > 0xff)
@@ -1123,14 +1002,14 @@ conv_utf8_to_vbcs(
 
       maxout --;
 
-      DEBUG_printf(("conv_utf8_to_vbcs: %08x => %02X %02X\n",
+      DEBUG_printf(("9conv_utf8_to_vbcs: %08x => %02X %02X",
                     (unsigned)unichar, dest[-2], dest[-1]));
     }
     else
     {
-      *dest++ = legchar;
+      *dest++ = (cups_sbcs_t)legchar;
 
-      DEBUG_printf(("conv_utf8_to_vbcs: %08x => %02X\n",
+      DEBUG_printf(("9conv_utf8_to_vbcs: %08x => %02X",
                     (unsigned)unichar, dest[-1]));
     }
   }
@@ -1139,7 +1018,7 @@ conv_utf8_to_vbcs(
 
   vmap->used --;
 
-  DEBUG_printf(("conv_utf8_to_vbcs: Returning %d characters\n",
+  DEBUG_printf(("8conv_utf8_to_vbcs: Returning %d characters",
                 (int)(dest - start)));
 
   return ((int)(dest - start));
@@ -1170,12 +1049,12 @@ conv_vbcs_to_utf8(
   * Find legacy charset map in cache...
   */
 
-  DEBUG_printf(("conv_vbcs_to_utf8(dest=%p, src=%p, maxout=%d, encoding=%d)\n",
+  DEBUG_printf(("7conv_vbcs_to_utf8(dest=%p, src=%p, maxout=%d, encoding=%d)",
                 dest, src, maxout, encoding));
 
   if ((vmap = (_cups_vmap_t *)get_charmap(encoding)) == NULL)
   {
-    DEBUG_puts("conv_vbcs_to_utf8: Returning -1 (NULL vmap)");
+    DEBUG_puts("8conv_vbcs_to_utf8: Returning -1 (NULL vmap)");
 
     return (-1);
   }
@@ -1198,7 +1077,7 @@ conv_vbcs_to_utf8(
     {
       *workptr++ = (cups_utf32_t)legchar;
 
-      DEBUG_printf(("conv_vbcs_to_utf8: %02X => %08X\n", src[-1],
+      DEBUG_printf(("9conv_vbcs_to_utf8: %02X => %08X", src[-1],
                     (unsigned)legchar));
       continue;
     }
@@ -1211,7 +1090,7 @@ conv_vbcs_to_utf8(
     {
       if (!*src)
       {
-        DEBUG_puts("conv_vbcs_to_utf8: Returning -1 (short string)");
+        DEBUG_puts("8conv_vbcs_to_utf8: Returning -1 (short string)");
 
        return (-1);
       }
@@ -1231,7 +1110,7 @@ conv_vbcs_to_utf8(
       else
        *workptr++ = (cups_utf32_t)*crow;
 
-      DEBUG_printf(("conv_vbcs_to_utf8: %02X %02X => %08X\n",
+      DEBUG_printf(("9conv_vbcs_to_utf8: %02X %02X => %08X",
                     src[-2], src[-1], (unsigned)workptr[-1]));
       continue;
     }
@@ -1244,7 +1123,7 @@ conv_vbcs_to_utf8(
     {
       if (!*src || !src[1])
       {
-        DEBUG_puts("conv_vbcs_to_utf8: Returning -1 (short string 2)");
+        DEBUG_puts("8conv_vbcs_to_utf8: Returning -1 (short string 2)");
 
        return (-1);
       }
@@ -1256,7 +1135,7 @@ conv_vbcs_to_utf8(
     {
       if (!*src || !src[1] || !src[2])
       {
-        DEBUG_puts("conv_vbcs_to_utf8: Returning -1 (short string 3)");
+        DEBUG_puts("8conv_vbcs_to_utf8: Returning -1 (short string 3)");
 
        return (-1);
       }
@@ -1267,7 +1146,7 @@ conv_vbcs_to_utf8(
     }
     else
     {
-      DEBUG_puts("conv_vbcs_to_utf8: Returning -1 (bad character)");
+      DEBUG_puts("8conv_vbcs_to_utf8: Returning -1 (bad character)");
 
       return (-1);
     }
@@ -1292,10 +1171,10 @@ conv_vbcs_to_utf8(
       *workptr++ = wide2uni->unichar;
 
     if (vmap->lead3char[(int)leadchar] == leadchar)
-      DEBUG_printf(("conv_vbcs_to_utf8: %02X %02X %02X => %08X\n",
+      DEBUG_printf(("9conv_vbcs_to_utf8: %02X %02X %02X => %08X",
                    src[-3], src[-2], src[-1], (unsigned)workptr[-1]));
     else
-      DEBUG_printf(("conv_vbcs_to_utf8: %02X %02X %02X %02X => %08X\n",
+      DEBUG_printf(("9conv_vbcs_to_utf8: %02X %02X %02X %02X => %08X",
                    src[-4], src[-3], src[-2], src[-1], (unsigned)workptr[-1]));
   }
 
@@ -1303,7 +1182,7 @@ conv_vbcs_to_utf8(
 
   vmap->used --;
 
-  DEBUG_printf(("conv_vbcs_to_utf8: Converting %d UTF-32 characters to UTF-8\n",
+  DEBUG_printf(("9conv_vbcs_to_utf8: Converting %d UTF-32 characters to UTF-8",
                 (int)(workptr - work)));
 
  /*
@@ -1375,7 +1254,7 @@ get_charmap(
   _cups_globals_t *cg = _cupsGlobals();        /* Global data */
 
 
-  DEBUG_printf(("get_charmap(encoding=%d)\n", encoding));
+  DEBUG_printf(("7get_charmap(encoding=%d)", encoding));
 
  /*
   * Get the data directory and charset map name...
@@ -1384,7 +1263,7 @@ get_charmap(
   snprintf(filename, sizeof(filename), "%s/charmaps/%s.txt",
           cg->cups_datadir, _cupsEncodingName(encoding));
 
-  DEBUG_printf(("get_charmap: filename=\"%s\"\n", filename));
+  DEBUG_printf(("9get_charmap: filename=\"%s\"", filename));
 
  /*
   * Read charset map input file into cache...
@@ -1454,7 +1333,7 @@ get_sbcs_charmap(
   * See if we already have this SBCS charset map loaded...
   */
 
-  DEBUG_printf(("get_sbcs_charmap(encoding=%d, filename=\"%s\")\n", encoding,
+  DEBUG_printf(("7get_sbcs_charmap(encoding=%d, filename=\"%s\")", encoding,
                 filename));
 
   for (cmap = cmap_cache; cmap; cmap = cmap->next)
@@ -1462,7 +1341,7 @@ get_sbcs_charmap(
     if (cmap->encoding == encoding)
     {
       cmap->used ++;
-      DEBUG_printf(("get_sbcs_charmap: Returning existing cmap=%p\n", cmap));
+      DEBUG_printf(("8get_sbcs_charmap: Returning existing cmap=%p", cmap));
 
       return ((void *)cmap);
     }
@@ -1474,7 +1353,7 @@ get_sbcs_charmap(
 
   if ((fp = cupsFileOpen(filename, "r")) == NULL)
   {
-    DEBUG_printf(("get_sbcs_charmap: Returning NULL (%s)\n", strerror(errno)));
+    DEBUG_printf(("8get_sbcs_charmap: Returning NULL (%s)", strerror(errno)));
 
     return (NULL);
   }
@@ -1486,7 +1365,7 @@ get_sbcs_charmap(
   if ((cmap = (_cups_cmap_t *)calloc(1, sizeof(_cups_cmap_t))) == NULL)
   {
     cupsFileClose(fp);
-    DEBUG_puts("get_sbcs_charmap: Returning NULL (Unable to allocate memory)");
+    DEBUG_puts("8get_sbcs_charmap: Returning NULL (Unable to allocate memory)");
 
     return (NULL);
   }
@@ -1508,7 +1387,7 @@ get_sbcs_charmap(
       goto sbcs_error;
 
     unichar = strtol(s, NULL, 16);
-    if (unichar < 0 || unichar > 0xffff)
+    if (unichar < 0 || unichar > 0x10ffff)
       goto sbcs_error;
 
    /*
@@ -1558,7 +1437,7 @@ get_sbcs_charmap(
   cmap->next = cmap_cache;
   cmap_cache = cmap;
 
-  DEBUG_printf(("get_sbcs_charmap: Returning new cmap=%p\n", cmap));
+  DEBUG_printf(("8get_sbcs_charmap: Returning new cmap=%p", cmap));
 
   return (cmap);
 
@@ -1572,7 +1451,7 @@ get_sbcs_charmap(
 
   cupsFileClose(fp);
 
-  DEBUG_puts("get_sbcs_charmap: Returning NULL (Read/format error)");
+  DEBUG_puts("8get_sbcs_charmap: Returning NULL (Read/format error)");
 
   return (NULL);
 }
@@ -1602,7 +1481,7 @@ get_vbcs_charmap(
   int          legacy;                 /* 32-bit legacy char */
 
 
-  DEBUG_printf(("get_vbcs_charmap(encoding=%d, filename=\"%s\")\n",
+  DEBUG_printf(("7get_vbcs_charmap(encoding=%d, filename=\"%s\")\n",
                 encoding, filename));
 
  /*
@@ -1614,7 +1493,7 @@ get_vbcs_charmap(
     if (vmap->encoding == encoding)
     {
       vmap->used ++;
-      DEBUG_printf(("get_vbcs_charmap: Returning existing vmap=%p\n", vmap));
+      DEBUG_printf(("8get_vbcs_charmap: Returning existing vmap=%p", vmap));
 
       return ((void *)vmap);
     }
@@ -1626,7 +1505,7 @@ get_vbcs_charmap(
 
   if ((fp = cupsFileOpen(filename, "r")) == NULL)
   {
-    DEBUG_printf(("get_vbcs_charmap: Returning NULL (%s)\n", strerror(errno)));
+    DEBUG_printf(("8get_vbcs_charmap: Returning NULL (%s)", strerror(errno)));
 
     return (NULL);
   }
@@ -1637,14 +1516,14 @@ get_vbcs_charmap(
 
   if ((mapcount = get_charmap_count(fp)) <= 0)
   {
-    DEBUG_puts("get_vbcs_charmap: Unable to get charmap count!");
+    DEBUG_puts("8get_vbcs_charmap: Unable to get charmap count!");
 
     cupsFileClose(fp);
 
     return (NULL);
   }
 
-  DEBUG_printf(("get_vbcs_charmap: mapcount=%d\n", mapcount));
+  DEBUG_printf(("8get_vbcs_charmap: mapcount=%d", mapcount));
 
  /*
   * Allocate memory for DBCS/VBCS charset map...
@@ -1652,7 +1531,7 @@ get_vbcs_charmap(
 
   if ((vmap = (_cups_vmap_t *)calloc(1, sizeof(_cups_vmap_t))) == NULL)
   {
-    DEBUG_puts("get_vbcs_charmap: Unable to allocate memory!");
+    DEBUG_puts("8get_vbcs_charmap: Unable to allocate memory!");
 
     cupsFileClose(fp);
 
@@ -1666,7 +1545,6 @@ get_vbcs_charmap(
   * Save DBCS/VBCS charset map into memory for transcoding...
   */
 
-  leadchar = 0;
   wide2uni = NULL;
 
   cupsFileRewind(fp);
@@ -1684,13 +1562,13 @@ get_vbcs_charmap(
       goto vbcs_error;
 
     unichar = strtol(s, NULL, 16);
-    if (unichar < 0 || unichar > 0xffff)
+    if (unichar < 0 || unichar > 0x10ffff)
       goto vbcs_error;
 
     i ++;
 
-/*    DEBUG_printf(("    i=%d, legchar=0x%08lx, unichar=0x%04x\n", i,
-                  legchar, (unsigned)unichar)); */
+    DEBUG_printf(("9get_vbcs_charmap: i=%d, legchar=0x%08lx, unichar=0x%04x", i,
+                  legchar, (unsigned)unichar));
 
    /*
     * Save lead char of 2/3/4-byte legacy char...
@@ -1706,7 +1584,7 @@ get_vbcs_charmap(
       leadchar                  = (cups_sbcs_t)(legchar >> 16);
       vmap->lead3char[leadchar] = leadchar;
     }
-    else if (legchar > 0xff)
+    else
     {
       leadchar                  = (cups_sbcs_t)(legchar >> 8);
       vmap->lead2char[leadchar] = leadchar;
@@ -1799,7 +1677,7 @@ get_vbcs_charmap(
   vmap->next = vmap_cache;
   vmap_cache = vmap;
 
-  DEBUG_printf(("get_vbcs_charmap: Returning new vmap=%p\n", vmap));
+  DEBUG_printf(("8get_vbcs_charmap: Returning new vmap=%p", vmap));
 
   return (vmap);
 
@@ -1813,7 +1691,7 @@ get_vbcs_charmap(
 
   cupsFileClose(fp);
 
-  DEBUG_puts("get_vbcs_charmap: Returning NULL (Read/format error)");
+  DEBUG_puts("8get_vbcs_charmap: Returning NULL (Read/format error)");
 
   return (NULL);
 }