Added UTF-8 <-> UTF-16 <-> UTF-32 <-> UCS-2 <-> UCS-4 conversion capability
authorSam Lantinga <slouken@libsdl.org>
Mon, 13 Mar 2006 01:08:00 +0000
changeset 150173dc5d39bbf8
parent 1500 f58c88a4dff5
child 1502 d403a39389da
Added UTF-8 <-> UTF-16 <-> UTF-32 <-> UCS-2 <-> UCS-4 conversion capability
configure.in
include/SDL_config.h.in
include/SDL_stdinc.h
src/stdlib/SDL_iconv.c
src/stdlib/SDL_string.c
test/Makefile.in
test/testiconv.c
test/utf8.txt
     1.1 --- a/configure.in	Sun Mar 12 01:47:23 2006 +0000
     1.2 +++ b/configure.in	Mon Mar 13 01:08:00 2006 +0000
     1.3 @@ -94,7 +94,7 @@
     1.4  
     1.5      dnl Check for C library headers
     1.6      AC_HEADER_STDC
     1.7 -    AC_CHECK_HEADERS(sys/types.h stdio.h stdlib.h stddef.h stdarg.h malloc.h memory.h string.h strings.h inttypes.h stdint.h ctype.h math.h signal.h)
     1.8 +    AC_CHECK_HEADERS(sys/types.h stdio.h stdlib.h stddef.h stdarg.h malloc.h memory.h string.h strings.h inttypes.h stdint.h ctype.h math.h iconv.h signal.h)
     1.9  
    1.10      dnl Check for typedefs, structures, etc.
    1.11      AC_TYPE_SIZE_T
    1.12 @@ -116,7 +116,7 @@
    1.13      if test x$ac_cv_func_strtod = xyes; then
    1.14          AC_DEFINE(HAVE_STRTOD)
    1.15      fi
    1.16 -    AC_CHECK_FUNCS(malloc calloc realloc free getenv putenv unsetenv qsort abs bcopy memset memcpy memmove strlen strlcpy strlcat strdup _strrev _strupr _strlwr strchr strrchr strstr itoa _ltoa _uitoa _ultoa strtol strtoul _i64toa _ui64toa strtoll strtoull atoi atof strcmp strncmp stricmp strcasecmp sscanf snprintf vsnprintf sigaction setjmp nanosleep)
    1.17 +    AC_CHECK_FUNCS(malloc calloc realloc free getenv putenv unsetenv qsort abs bcopy memset memcpy memmove strlen strlcpy strlcat strdup _strrev _strupr _strlwr strchr strrchr strstr itoa _ltoa _uitoa _ultoa strtol strtoul _i64toa _ui64toa strtoll strtoull atoi atof strcmp strncmp stricmp strcasecmp strncasecmp sscanf snprintf vsnprintf iconv sigaction setjmp nanosleep)
    1.18  
    1.19      AC_CHECK_LIB(m, pow, [BUILD_LDFLAGS="$BUILD_LDFLAGS -lm"])
    1.20  fi
     2.1 --- a/include/SDL_config.h.in	Sun Mar 12 01:47:23 2006 +0000
     2.2 +++ b/include/SDL_config.h.in	Mon Mar 13 01:08:00 2006 +0000
     2.3 @@ -68,6 +68,7 @@
     2.4  #undef HAVE_STDINT_H
     2.5  #undef HAVE_CTYPE_H
     2.6  #undef HAVE_MATH_H
     2.7 +#undef HAVE_ICONV_H
     2.8  #undef HAVE_SIGNAL_H
     2.9  #undef HAVE_ALTIVEC_H
    2.10  
    2.11 @@ -118,9 +119,11 @@
    2.12  #undef HAVE_STRNCMP
    2.13  #undef HAVE_STRICMP
    2.14  #undef HAVE_STRCASECMP
    2.15 +#undef HAVE_STRNCASECMP
    2.16  #undef HAVE_SSCANF
    2.17  #undef HAVE_SNPRINTF
    2.18  #undef HAVE_VSNPRINTF
    2.19 +#undef HAVE_ICONV
    2.20  #undef HAVE_SIGACTION
    2.21  #undef HAVE_SETJMP
    2.22  #undef HAVE_NANOSLEEP
     3.1 --- a/include/SDL_stdinc.h	Sun Mar 12 01:47:23 2006 +0000
     3.2 +++ b/include/SDL_stdinc.h	Mon Mar 13 01:08:00 2006 +0000
     3.3 @@ -70,6 +70,9 @@
     3.4  #if HAVE_CTYPE_H
     3.5  # include <ctype.h>
     3.6  #endif
     3.7 +#if HAVE_ICONV_H
     3.8 +# include <iconv.h>
     3.9 +#endif
    3.10  
    3.11  /* The number of elements in an array */
    3.12  #define SDL_arraysize(array)	(sizeof(array)/sizeof(array[0]))
    3.13 @@ -518,6 +521,12 @@
    3.14  extern DECLSPEC int SDLCALL SDL_strcasecmp(const char *str1, const char *str2);
    3.15  #endif
    3.16  
    3.17 +#if HAVE_STRNCASECMP
    3.18 +#define SDL_strncasecmp strncasecmp
    3.19 +#else
    3.20 +extern DECLSPEC int SDLCALL SDL_strncasecmp(const char *str1, const char *str2, size_t maxlen);
    3.21 +#endif
    3.22 +
    3.23  #if HAVE_SSCANF
    3.24  #define SDL_sscanf      sscanf
    3.25  #else
    3.26 @@ -536,6 +545,32 @@
    3.27  extern DECLSPEC int SDLCALL SDL_vsnprintf(char *text, size_t maxlen, const char *fmt, va_list ap);
    3.28  #endif
    3.29  
    3.30 +/* The SDL implementation of iconv() returns these error codes */
    3.31 +#define SDL_ICONV_ERROR		(size_t)-1
    3.32 +#define SDL_ICONV_E2BIG		(size_t)-2
    3.33 +#define SDL_ICONV_EILSEQ	(size_t)-3
    3.34 +#define SDL_ICONV_EINVAL	(size_t)-4
    3.35 +
    3.36 +#if HAVE_ICONV
    3.37 +#define SDL_iconv_t     iconv_t
    3.38 +#define SDL_iconv_open  iconv_open
    3.39 +#define SDL_iconv_close iconv_close
    3.40 +extern DECLSPEC size_t SDLCALL SDL_iconv(SDL_iconv_t cd, char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft);
    3.41 +#else
    3.42 +typedef struct _SDL_iconv_t *SDL_iconv_t;
    3.43 +extern DECLSPEC SDL_iconv_t SDLCALL SDL_iconv_open(const char *tocode, const char *fromcode);
    3.44 +extern DECLSPEC int SDLCALL SDL_iconv_close(SDL_iconv_t cd);
    3.45 +extern DECLSPEC size_t SDLCALL SDL_iconv(SDL_iconv_t cd, char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft);
    3.46 +#endif
    3.47 +/* This function converts a string between encodings in one pass, returning a
    3.48 +   string that must be freed with SDL_free() or NULL on error.
    3.49 +*/
    3.50 +extern DECLSPEC char * SDLCALL SDL_iconv_string(const char *tocode, const char *fromcode, char *inbuf, size_t inbytesleft);
    3.51 +#define SDL_iconv_utf8_ascii(S)		SDL_iconv_string("ASCII", "UTF-8", S, SDL_strlen(S)+1)
    3.52 +#define SDL_iconv_utf8_latin1(S)	SDL_iconv_string("LATIN1", "UTF-8", S, SDL_strlen(S)+1)
    3.53 +#define SDL_iconv_utf8_ucs2(S)		(Uint16 *)SDL_iconv_string("UCS-2", "UTF-8", S, SDL_strlen(S)+1)
    3.54 +#define SDL_iconv_utf8_ucs4(S)		(Uint32 *)SDL_iconv_string("UCS-4", "UTF-8", S, SDL_strlen(S)+1)
    3.55 +
    3.56  /* Ends C function definitions when using C++ */
    3.57  #ifdef __cplusplus
    3.58  }
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/src/stdlib/SDL_iconv.c	Mon Mar 13 01:08:00 2006 +0000
     4.3 @@ -0,0 +1,809 @@
     4.4 +/*
     4.5 +    SDL - Simple DirectMedia Layer
     4.6 +    Copyright (C) 1997-2006 Sam Lantinga
     4.7 +
     4.8 +    This library is free software; you can redistribute it and/or
     4.9 +    modify it under the terms of the GNU Lesser General Public
    4.10 +    License as published by the Free Software Foundation; either
    4.11 +    version 2.1 of the License, or (at your option) any later version.
    4.12 +
    4.13 +    This library is distributed in the hope that it will be useful,
    4.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
    4.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    4.16 +    Lesser General Public License for more details.
    4.17 +
    4.18 +    You should have received a copy of the GNU Lesser General Public
    4.19 +    License along with this library; if not, write to the Free Software
    4.20 +    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    4.21 +
    4.22 +    Sam Lantinga
    4.23 +    slouken@libsdl.org
    4.24 +*/
    4.25 +#include "SDL_config.h"
    4.26 +
    4.27 +/* This file contains portable iconv functions for SDL */
    4.28 +
    4.29 +#include "SDL_stdinc.h"
    4.30 +#include "SDL_endian.h"
    4.31 +
    4.32 +#ifdef HAVE_ICONV
    4.33 +
    4.34 +#include <errno.h>
    4.35 +
    4.36 +size_t SDL_iconv(SDL_iconv_t cd,
    4.37 +                 char **inbuf, size_t *inbytesleft,
    4.38 +                 char **outbuf, size_t *outbytesleft)
    4.39 +{
    4.40 +	size_t retCode = iconv(cd, inbuf, inbytesleft, outbuf, outbytesleft);
    4.41 +	if ( retCode == (size_t)-1 ) {
    4.42 +		switch(errno) {
    4.43 +		    case E2BIG:
    4.44 +			return SDL_ICONV_E2BIG;
    4.45 +		    case EILSEQ:
    4.46 +			return SDL_ICONV_EILSEQ;
    4.47 +		    case EINVAL:
    4.48 +			return SDL_ICONV_EINVAL;
    4.49 +		    default:
    4.50 +			return SDL_ICONV_ERROR;
    4.51 +		}
    4.52 +	}
    4.53 +	return retCode;
    4.54 +}
    4.55 +
    4.56 +#else
    4.57 +
    4.58 +#define UNICODE_BOM	0xFEFF
    4.59 +
    4.60 +#define UNKNOWN_ASCII	'?'
    4.61 +#define UNKNOWN_UNICODE	0xFFFD
    4.62 +
    4.63 +enum {
    4.64 +	ENCODING_UNKNOWN,
    4.65 +	ENCODING_ASCII,
    4.66 +	ENCODING_LATIN1,
    4.67 +	ENCODING_UTF8,
    4.68 +	ENCODING_UTF16,		/* Needs byte order marker */
    4.69 +	ENCODING_UTF16BE,
    4.70 +	ENCODING_UTF16LE,
    4.71 +	ENCODING_UTF32,		/* Needs byte order marker */
    4.72 +	ENCODING_UTF32BE,
    4.73 +	ENCODING_UTF32LE,
    4.74 +	ENCODING_UCS2,		/* Native byte order assumed */
    4.75 +	ENCODING_UCS4,		/* Native byte order assumed */
    4.76 +};
    4.77 +#if SDL_BYTEORDER == SDL_BIG_ENDIAN
    4.78 +#define ENCODING_UTF16NATIVE	ENCODING_UTF16BE
    4.79 +#define ENCODING_UTF32NATIVE	ENCODING_UTF32BE
    4.80 +#else
    4.81 +#define ENCODING_UTF16NATIVE	ENCODING_UTF16LE
    4.82 +#define ENCODING_UTF32NATIVE	ENCODING_UTF32LE
    4.83 +#endif
    4.84 +
    4.85 +struct _SDL_iconv_t
    4.86 +{
    4.87 +	int src_fmt;
    4.88 +	int dst_fmt;
    4.89 +};
    4.90 +
    4.91 +static struct {
    4.92 +	const char *name;
    4.93 +	int format;
    4.94 +} encodings[] = {
    4.95 +	{ "ASCII",	ENCODING_ASCII },
    4.96 +	{ "US-ASCII",	ENCODING_ASCII },
    4.97 +	{ "LATIN1",	ENCODING_LATIN1 },
    4.98 +	{ "ISO-8859-1",	ENCODING_LATIN1 },
    4.99 +	{ "UTF8",	ENCODING_UTF8 },
   4.100 +	{ "UTF-8",	ENCODING_UTF8 },
   4.101 +	{ "UTF16",	ENCODING_UTF16 },
   4.102 +	{ "UTF-16",	ENCODING_UTF16 },
   4.103 +	{ "UTF16BE",	ENCODING_UTF16BE },
   4.104 +	{ "UTF-16BE",	ENCODING_UTF16BE },
   4.105 +	{ "UTF16LE",	ENCODING_UTF16LE },
   4.106 +	{ "UTF-16LE",	ENCODING_UTF16LE },
   4.107 +	{ "UTF32",	ENCODING_UTF32 },
   4.108 +	{ "UTF-32",	ENCODING_UTF32 },
   4.109 +	{ "UTF32BE",	ENCODING_UTF32BE },
   4.110 +	{ "UTF-32BE",	ENCODING_UTF32BE },
   4.111 +	{ "UTF32LE",	ENCODING_UTF32LE },
   4.112 +	{ "UTF-32LE",	ENCODING_UTF32LE },
   4.113 +	{ "UCS2",	ENCODING_UCS2 },
   4.114 +	{ "UCS-2",	ENCODING_UCS2 },
   4.115 +	{ "UCS4",	ENCODING_UCS4 },
   4.116 +	{ "UCS-4",	ENCODING_UCS4 },
   4.117 +};
   4.118 +
   4.119 +SDL_iconv_t SDL_iconv_open(const char *tocode, const char *fromcode)
   4.120 +{
   4.121 +	int src_fmt = ENCODING_UNKNOWN;
   4.122 +	int dst_fmt = ENCODING_UNKNOWN;
   4.123 +	int i;
   4.124 +
   4.125 +	for ( i = 0; i < SDL_arraysize(encodings); ++i ) {
   4.126 +		if ( SDL_strcasecmp(fromcode, encodings[i].name) == 0 ) {
   4.127 +			src_fmt = encodings[i].format;
   4.128 +			if ( dst_fmt != ENCODING_UNKNOWN ) {
   4.129 +				break;
   4.130 +			}
   4.131 +		}
   4.132 +		if ( SDL_strcasecmp(tocode, encodings[i].name) == 0 ) {
   4.133 +			dst_fmt = encodings[i].format;
   4.134 +			if ( src_fmt != ENCODING_UNKNOWN ) {
   4.135 +				break;
   4.136 +			}
   4.137 +		}
   4.138 +	}
   4.139 +	if ( src_fmt != ENCODING_UNKNOWN && dst_fmt != ENCODING_UNKNOWN ) {
   4.140 +		SDL_iconv_t cd = (SDL_iconv_t)SDL_malloc(sizeof(*cd));
   4.141 +		if ( cd ) {
   4.142 +			cd->src_fmt = src_fmt;
   4.143 +			cd->dst_fmt = dst_fmt;
   4.144 +			return cd;
   4.145 +		}
   4.146 +	}
   4.147 +	return (SDL_iconv_t)-1;
   4.148 +}
   4.149 +
   4.150 +size_t SDL_iconv(SDL_iconv_t cd,
   4.151 +                 char **inbuf, size_t *inbytesleft,
   4.152 +                 char **outbuf, size_t *outbytesleft)
   4.153 +{
   4.154 +	/* For simplicity, we'll convert everything to and from UCS-4 */
   4.155 +	char *src, *dst;
   4.156 +	size_t srclen, dstlen;
   4.157 +	Uint32 ch;
   4.158 +	size_t total;
   4.159 +
   4.160 +	if ( !inbuf || !*inbuf ) {
   4.161 +		/* Reset the context */
   4.162 +		return 0;
   4.163 +	}
   4.164 +	if ( !outbuf || !*outbuf || !outbytesleft || !*outbytesleft ) {
   4.165 +		return SDL_ICONV_E2BIG;
   4.166 +	}
   4.167 +	src = *inbuf;
   4.168 +	srclen = (inbytesleft ? *inbytesleft : 0);
   4.169 +	dst = *outbuf;
   4.170 +	dstlen = *outbytesleft;
   4.171 +
   4.172 +	switch ( cd->src_fmt ) {
   4.173 +	    case ENCODING_UTF16:
   4.174 +		/* Scan for a byte order marker */
   4.175 +		{
   4.176 +			Uint8 *p = (Uint8 *)src;
   4.177 +			size_t n = srclen / 2;
   4.178 +			while ( n ) {
   4.179 +				if ( p[0] == 0xFF && p[1] == 0xFE ) {
   4.180 +					cd->src_fmt = ENCODING_UTF16BE;
   4.181 +					break;
   4.182 +				} else if ( p[0] == 0xFE && p[1] == 0xFF ) {
   4.183 +					cd->src_fmt = ENCODING_UTF16LE;
   4.184 +					break;
   4.185 +				}
   4.186 +				p += 2;
   4.187 +				--n;
   4.188 +			}
   4.189 +			if ( n == 0 ) {
   4.190 +				/* We can't tell, default to host order */
   4.191 +				cd->src_fmt = ENCODING_UTF16NATIVE;
   4.192 +			}
   4.193 +		}
   4.194 +		break;
   4.195 +	    case ENCODING_UTF32:
   4.196 +		/* Scan for a byte order marker */
   4.197 +		{
   4.198 +			Uint8 *p = (Uint8 *)src;
   4.199 +			size_t n = srclen / 4;
   4.200 +			while ( n ) {
   4.201 +				if ( p[0] == 0xFF && p[1] == 0xFE &&
   4.202 +				     p[2] == 0x00 && p[3] == 0x00 ) {
   4.203 +					cd->src_fmt = ENCODING_UTF32BE;
   4.204 +					break;
   4.205 +				} else if ( p[0] == 0x00 && p[1] == 0x00 &&
   4.206 +				            p[2] == 0xFE && p[3] == 0xFF ) {
   4.207 +					cd->src_fmt = ENCODING_UTF32LE;
   4.208 +					break;
   4.209 +				}
   4.210 +				p += 4;
   4.211 +				--n;
   4.212 +			}
   4.213 +			if ( n == 0 ) {
   4.214 +				/* We can't tell, default to host order */
   4.215 +				cd->src_fmt = ENCODING_UTF32NATIVE;
   4.216 +			}
   4.217 +		}
   4.218 +		break;
   4.219 +	}
   4.220 +
   4.221 +	switch ( cd->dst_fmt ) {
   4.222 +	    case ENCODING_UTF16:
   4.223 +		/* Default to host order, need to add byte order marker */
   4.224 +		if ( dstlen < 2 ) {
   4.225 +			return SDL_ICONV_E2BIG;
   4.226 +		}
   4.227 +		*(Uint16 *)dst = UNICODE_BOM;
   4.228 +		dst += 2;
   4.229 +		dstlen -= 2;
   4.230 +		cd->dst_fmt = ENCODING_UTF16NATIVE;
   4.231 +		break;
   4.232 +	    case ENCODING_UTF32:
   4.233 +		/* Default to host order, need to add byte order marker */
   4.234 +		if ( dstlen < 4 ) {
   4.235 +			return SDL_ICONV_E2BIG;
   4.236 +		}
   4.237 +		*(Uint32 *)dst = UNICODE_BOM;
   4.238 +		dst += 4;
   4.239 +		dstlen -= 4;
   4.240 +		cd->dst_fmt = ENCODING_UTF32NATIVE;
   4.241 +		break;
   4.242 +	}
   4.243 +
   4.244 +	total = 0;
   4.245 +	while ( srclen > 0 ) {
   4.246 +		/* Decode a character */
   4.247 +		switch ( cd->src_fmt ) {
   4.248 +		    case ENCODING_ASCII:
   4.249 +			{
   4.250 +				Uint8 *p = (Uint8 *)src;
   4.251 +				ch = (Uint32)(p[0] & 0x7F);
   4.252 +				++src;
   4.253 +				--srclen;
   4.254 +			}
   4.255 +			break;
   4.256 +		    case ENCODING_LATIN1:
   4.257 +			{
   4.258 +				Uint8 *p = (Uint8 *)src;
   4.259 +				ch = (Uint32)p[0];
   4.260 +				++src;
   4.261 +				--srclen;
   4.262 +			}
   4.263 +			break;
   4.264 +		    case ENCODING_UTF8: /* RFC 3629 */
   4.265 +			{
   4.266 +				Uint8 *p = (Uint8 *)src;
   4.267 +				size_t left = 0;
   4.268 +				SDL_bool overlong = SDL_FALSE;
   4.269 +				if ( p[0] >= 0xFC ) {
   4.270 +					if ( (p[0] & 0xFE) != 0xFC ) {
   4.271 +						/* Skip illegal sequences
   4.272 +						return SDL_ICONV_EILSEQ;
   4.273 +						*/
   4.274 +						ch = UNKNOWN_UNICODE;
   4.275 +					} else {
   4.276 +						if ( p[0] == 0xFC ) {
   4.277 +							overlong = SDL_TRUE;
   4.278 +						}
   4.279 +						ch = (Uint32)(p[0] & 0x01);
   4.280 +						left = 5;
   4.281 +					}
   4.282 +				} else if ( p[0] >= 0xF8 ) {
   4.283 +					if ( (p[0] & 0xFC) != 0xF8 ) {
   4.284 +						/* Skip illegal sequences
   4.285 +						return SDL_ICONV_EILSEQ;
   4.286 +						*/
   4.287 +						ch = UNKNOWN_UNICODE;
   4.288 +					} else {
   4.289 +						if ( p[0] == 0xF8 ) {
   4.290 +							overlong = SDL_TRUE;
   4.291 +						}
   4.292 +						ch = (Uint32)(p[0] & 0x03);
   4.293 +						left = 4;
   4.294 +					}
   4.295 +				} else if ( p[0] >= 0xF0 ) {
   4.296 +					if ( (p[0] & 0xF8) != 0xF0 ) {
   4.297 +						/* Skip illegal sequences
   4.298 +						return SDL_ICONV_EILSEQ;
   4.299 +						*/
   4.300 +						ch = UNKNOWN_UNICODE;
   4.301 +					} else {
   4.302 +						if ( p[0] == 0xF0 ) {
   4.303 +							overlong = SDL_TRUE;
   4.304 +						}
   4.305 +						ch = (Uint32)(p[0] & 0x07);
   4.306 +						left = 3;
   4.307 +					}
   4.308 +				} else if ( p[0] >= 0xE0 ) {
   4.309 +					if ( (p[0] & 0xF0) != 0xE0 ) {
   4.310 +						/* Skip illegal sequences
   4.311 +						return SDL_ICONV_EILSEQ;
   4.312 +						*/
   4.313 +						ch = UNKNOWN_UNICODE;
   4.314 +					} else {
   4.315 +						if ( p[0] == 0xE0 ) {
   4.316 +							overlong = SDL_TRUE;
   4.317 +						}
   4.318 +						ch = (Uint32)(p[0] & 0x0F);
   4.319 +						left = 2;
   4.320 +					}
   4.321 +				} else if ( p[0] >= 0xC0 ) {
   4.322 +					if ( (p[0] & 0xE0) != 0xC0 ) {
   4.323 +						/* Skip illegal sequences
   4.324 +						return SDL_ICONV_EILSEQ;
   4.325 +						*/
   4.326 +						ch = UNKNOWN_UNICODE;
   4.327 +					} else {
   4.328 +						if ( (p[0] & 0xCE) == 0xC0 ) {
   4.329 +							overlong = SDL_TRUE;
   4.330 +						}
   4.331 +						ch = (Uint32)(p[0] & 0x1F);
   4.332 +						left = 1;
   4.333 +					}
   4.334 +				} else {
   4.335 +					if ( (p[0] & 0x80) != 0x00 ) {
   4.336 +						/* Skip illegal sequences
   4.337 +						return SDL_ICONV_EILSEQ;
   4.338 +						*/
   4.339 +						ch = UNKNOWN_UNICODE;
   4.340 +					} else {
   4.341 +						ch = (Uint32)p[0];
   4.342 +					}
   4.343 +				}
   4.344 +				++src;
   4.345 +				--srclen;
   4.346 +				if ( srclen < left ) {
   4.347 +					return SDL_ICONV_EINVAL;
   4.348 +				}
   4.349 +				while ( left-- ) {
   4.350 +					++p;
   4.351 +					if ( (p[0] & 0xC0) != 0x80 ) {
   4.352 +						/* Skip illegal sequences
   4.353 +						return SDL_ICONV_EILSEQ;
   4.354 +						*/
   4.355 +						ch = UNKNOWN_UNICODE;
   4.356 +						break;
   4.357 +					}
   4.358 +					ch <<= 6;
   4.359 +					ch |= (p[0] & 0x3F);
   4.360 +					++src;
   4.361 +					--srclen;
   4.362 +				}
   4.363 +				if ( overlong ) {
   4.364 +					/* Potential security risk
   4.365 +					return SDL_ICONV_EILSEQ;
   4.366 +					*/
   4.367 +					ch = UNKNOWN_UNICODE;
   4.368 +				}
   4.369 +				if ( (ch >= 0xD800 && ch <= 0xDFFF) ||
   4.370 +				     (ch == 0xFFFE || ch == 0xFFFF) ) {
   4.371 +					/* Skip illegal sequences
   4.372 +					return SDL_ICONV_EILSEQ;
   4.373 +					*/
   4.374 +					ch = UNKNOWN_UNICODE;
   4.375 +				}
   4.376 +			}
   4.377 +			break;
   4.378 +		    case ENCODING_UTF16BE: /* RFC 2781 */
   4.379 +			{
   4.380 +				Uint8 *p = (Uint8 *)src;
   4.381 +				Uint16 W1, W2;
   4.382 +				if ( srclen < 2 ) {
   4.383 +					return SDL_ICONV_EINVAL;
   4.384 +				}
   4.385 +				W1 = ((Uint32)p[0] << 8) |
   4.386 +				      (Uint32)p[1];
   4.387 +				src += 2;
   4.388 +				srclen -= 2;
   4.389 +				if ( W1 < 0xD800 || W1 > 0xDFFF ) {
   4.390 +					ch = (Uint32)W1;
   4.391 +					break;
   4.392 +				}
   4.393 +				if ( W1 > 0xDBFF ) {
   4.394 +					/* Skip illegal sequences
   4.395 +					return SDL_ICONV_EILSEQ;
   4.396 +					*/
   4.397 +					ch = UNKNOWN_UNICODE;
   4.398 +					break;
   4.399 +				}
   4.400 +				if ( srclen < 2 ) {
   4.401 +					return SDL_ICONV_EINVAL;
   4.402 +				}
   4.403 +				p = src;
   4.404 +				W2 = ((Uint32)p[0] << 8) |
   4.405 +				      (Uint32)p[1];
   4.406 +				src += 2;
   4.407 +				srclen -= 2;
   4.408 +				if ( W2 < 0xDC00 || W2 > 0xDFFF ) {
   4.409 +					/* Skip illegal sequences
   4.410 +					return SDL_ICONV_EILSEQ;
   4.411 +					*/
   4.412 +					ch = UNKNOWN_UNICODE;
   4.413 +					break;
   4.414 +				}
   4.415 +				ch = (((Uint32)(W1 & 0x3FF) << 10) |
   4.416 +				      (Uint32)(W2 & 0x3FF)) + 0x10000;
   4.417 +			}
   4.418 +			break;
   4.419 +		    case ENCODING_UTF16LE: /* RFC 2781 */
   4.420 +			{
   4.421 +				Uint8 *p = (Uint8 *)src;
   4.422 +				Uint16 W1, W2;
   4.423 +				if ( srclen < 2 ) {
   4.424 +					return SDL_ICONV_EINVAL;
   4.425 +				}
   4.426 +				W1 = ((Uint32)p[1] << 8) |
   4.427 +				      (Uint32)p[0];
   4.428 +				src += 2;
   4.429 +				srclen -= 2;
   4.430 +				if ( W1 < 0xD800 || W1 > 0xDFFF ) {
   4.431 +					ch = (Uint32)W1;
   4.432 +					break;
   4.433 +				}
   4.434 +				if ( W1 > 0xDBFF ) {
   4.435 +					/* Skip illegal sequences
   4.436 +					return SDL_ICONV_EILSEQ;
   4.437 +					*/
   4.438 +					ch = UNKNOWN_UNICODE;
   4.439 +					break;
   4.440 +				}
   4.441 +				if ( srclen < 2 ) {
   4.442 +					return SDL_ICONV_EINVAL;
   4.443 +				}
   4.444 +				p = src;
   4.445 +				W2 = ((Uint32)p[1] << 8) |
   4.446 +				      (Uint32)p[0];
   4.447 +				src += 2;
   4.448 +				srclen -= 2;
   4.449 +				if ( W2 < 0xDC00 || W2 > 0xDFFF ) {
   4.450 +					/* Skip illegal sequences
   4.451 +					return SDL_ICONV_EILSEQ;
   4.452 +					*/
   4.453 +					ch = UNKNOWN_UNICODE;
   4.454 +					break;
   4.455 +				}
   4.456 +				ch = (((Uint32)(W1 & 0x3FF) << 10) |
   4.457 +				      (Uint32)(W2 & 0x3FF)) + 0x10000;
   4.458 +			}
   4.459 +			break;
   4.460 +		    case ENCODING_UTF32BE:
   4.461 +			{
   4.462 +				Uint8 *p = (Uint8 *)src;
   4.463 +				if ( srclen < 4 ) {
   4.464 +					return SDL_ICONV_EINVAL;
   4.465 +				}
   4.466 +				ch = ((Uint32)p[0] << 24) |
   4.467 +				     ((Uint32)p[1] << 16) |
   4.468 +				     ((Uint32)p[2] << 8) |
   4.469 +				      (Uint32)p[3];
   4.470 +				src += 4;
   4.471 +				srclen -= 4;
   4.472 +			}
   4.473 +			break;
   4.474 +		    case ENCODING_UTF32LE:
   4.475 +			{
   4.476 +				Uint8 *p = (Uint8 *)src;
   4.477 +				if ( srclen < 4 ) {
   4.478 +					return SDL_ICONV_EINVAL;
   4.479 +				}
   4.480 +				ch = ((Uint32)p[3] << 24) |
   4.481 +				     ((Uint32)p[2] << 16) |
   4.482 +				     ((Uint32)p[1] << 8) |
   4.483 +				      (Uint32)p[0];
   4.484 +				src += 4;
   4.485 +				srclen -= 4;
   4.486 +			}
   4.487 +			break;
   4.488 +		    case ENCODING_UCS2:
   4.489 +			{
   4.490 +				Uint16 *p = (Uint16 *)src;
   4.491 +				if ( srclen < 2 ) {
   4.492 +					return SDL_ICONV_EINVAL;
   4.493 +				}
   4.494 +				ch = *p;
   4.495 +				src += 2;
   4.496 +				srclen -= 2;
   4.497 +			}
   4.498 +			break;
   4.499 +		    case ENCODING_UCS4:
   4.500 +			{
   4.501 +				Uint32 *p = (Uint32 *)src;
   4.502 +				if ( srclen < 4 ) {
   4.503 +					return SDL_ICONV_EINVAL;
   4.504 +				}
   4.505 +				ch = *p;
   4.506 +				src += 4;
   4.507 +				srclen -= 4;
   4.508 +			}
   4.509 +			break;
   4.510 +		}
   4.511 +
   4.512 +		/* Encode a character */
   4.513 +		switch ( cd->dst_fmt ) {
   4.514 +		    case ENCODING_ASCII:
   4.515 +			{
   4.516 +				Uint8 *p = (Uint8 *)dst;
   4.517 +				if ( dstlen < 1 ) {
   4.518 +					return SDL_ICONV_E2BIG;
   4.519 +				}
   4.520 +				if ( ch > 0x7F ) {
   4.521 +					*p = UNKNOWN_ASCII;
   4.522 +				} else {
   4.523 +					*p = (Uint8)ch;
   4.524 +				}
   4.525 +				++dst;
   4.526 +				--dstlen;
   4.527 +			}
   4.528 +			break;
   4.529 +		    case ENCODING_LATIN1:
   4.530 +			{
   4.531 +				Uint8 *p = (Uint8 *)dst;
   4.532 +				if ( dstlen < 1 ) {
   4.533 +					return SDL_ICONV_E2BIG;
   4.534 +				}
   4.535 +				if ( ch > 0xFF ) {
   4.536 +					*p = UNKNOWN_ASCII;
   4.537 +				} else {
   4.538 +					*p = (Uint8)ch;
   4.539 +				}
   4.540 +				++dst;
   4.541 +				--dstlen;
   4.542 +			}
   4.543 +			break;
   4.544 +		    case ENCODING_UTF8: /* RFC 3629 */
   4.545 +			{
   4.546 +				Uint8 *p = (Uint8 *)dst;
   4.547 +				if ( ch > 0x7FFFFFFF ) {
   4.548 +					ch = UNKNOWN_UNICODE;
   4.549 +				}
   4.550 +				if ( ch <= 0x7F ) {
   4.551 +					if ( dstlen < 1 ) {
   4.552 +						return SDL_ICONV_E2BIG;
   4.553 +					}
   4.554 +					*p = (Uint8)ch;
   4.555 +					++dst;
   4.556 +					--dstlen;
   4.557 +				} else if ( ch <= 0x7FF ) {
   4.558 +					if ( dstlen < 2 ) {
   4.559 +						return SDL_ICONV_E2BIG;
   4.560 +					}
   4.561 +					p[0] = 0xC0 | (Uint8)((ch >> 6) & 0x1F);
   4.562 +					p[1] = 0x80 | (Uint8)(ch & 0x3F);
   4.563 +					dst += 2;
   4.564 +					dstlen -= 2;
   4.565 +				} else if ( ch <= 0xFFFF ) {
   4.566 +					if ( dstlen < 3 ) {
   4.567 +						return SDL_ICONV_E2BIG;
   4.568 +					}
   4.569 +					p[0] = 0xE0 | (Uint8)((ch >> 12) & 0x0F);
   4.570 +					p[1] = 0x80 | (Uint8)((ch >> 6) & 0x3F);
   4.571 +					p[2] = 0x80 | (Uint8)(ch & 0x3F);
   4.572 +					dst += 3;
   4.573 +					dstlen -= 3;
   4.574 +				} else if ( ch <= 0x1FFFFF ) {
   4.575 +					if ( dstlen < 4 ) {
   4.576 +						return SDL_ICONV_E2BIG;
   4.577 +					}
   4.578 +					p[0] = 0xF0 | (Uint8)((ch >> 18) & 0x07);
   4.579 +					p[1] = 0x80 | (Uint8)((ch >> 12) & 0x3F);
   4.580 +					p[2] = 0x80 | (Uint8)((ch >> 6) & 0x3F);
   4.581 +					p[3] = 0x80 | (Uint8)(ch & 0x3F);
   4.582 +					dst += 4;
   4.583 +					dstlen -= 4;
   4.584 +				} else if ( ch <= 0x3FFFFFF ) {
   4.585 +					if ( dstlen < 5 ) {
   4.586 +						return SDL_ICONV_E2BIG;
   4.587 +					}
   4.588 +					p[0] = 0xF8 | (Uint8)((ch >> 24) & 0x03);
   4.589 +					p[1] = 0x80 | (Uint8)((ch >> 18) & 0x3F);
   4.590 +					p[2] = 0x80 | (Uint8)((ch >> 12) & 0x3F);
   4.591 +					p[3] = 0x80 | (Uint8)((ch >> 6) & 0x3F);
   4.592 +					p[4] = 0x80 | (Uint8)(ch & 0x3F);
   4.593 +					dst += 5;
   4.594 +					dstlen -= 5;
   4.595 +				} else {
   4.596 +					if ( dstlen < 6 ) {
   4.597 +						return SDL_ICONV_E2BIG;
   4.598 +					}
   4.599 +					p[0] = 0xFC | (Uint8)((ch >> 30) & 0x01);
   4.600 +					p[1] = 0x80 | (Uint8)((ch >> 24) & 0x3F);
   4.601 +					p[2] = 0x80 | (Uint8)((ch >> 18) & 0x3F);
   4.602 +					p[3] = 0x80 | (Uint8)((ch >> 12) & 0x3F);
   4.603 +					p[4] = 0x80 | (Uint8)((ch >> 6) & 0x3F);
   4.604 +					p[5] = 0x80 | (Uint8)(ch & 0x3F);
   4.605 +					dst += 6;
   4.606 +					dstlen -= 6;
   4.607 +				}
   4.608 +			}
   4.609 +			break;
   4.610 +		    case ENCODING_UTF16BE: /* RFC 2781 */
   4.611 +			{
   4.612 +				Uint8 *p = (Uint8 *)dst;
   4.613 +				if ( ch > 0x10FFFF ) {
   4.614 +					ch = UNKNOWN_UNICODE;
   4.615 +				}
   4.616 +				if ( ch < 0x10000 ) {
   4.617 +					if ( dstlen < 2 ) {
   4.618 +						return SDL_ICONV_E2BIG;
   4.619 +					}
   4.620 +					p[0] = (Uint8)(ch >> 8);
   4.621 +					p[1] = (Uint8)ch;
   4.622 +					dst += 2;
   4.623 +					dstlen -= 2;
   4.624 +				} else {
   4.625 +					Uint16 W1, W2;
   4.626 +					if ( dstlen < 4 ) {
   4.627 +						return SDL_ICONV_E2BIG;
   4.628 +					}
   4.629 +					ch = ch - 0x10000;
   4.630 +					W1 = 0xD800 | (Uint16)((ch >> 10) & 0x3FF);
   4.631 +					W2 = 0xDC00 | (Uint16)(ch & 0x3FF);
   4.632 +					p[0] = (Uint8)(W1 >> 8);
   4.633 +					p[1] = (Uint8)W1;
   4.634 +					p[2] = (Uint8)(W2 >> 8);
   4.635 +					p[3] = (Uint8)W2;
   4.636 +					dst += 4;
   4.637 +					dstlen -= 4;
   4.638 +				}
   4.639 +			}
   4.640 +			break;
   4.641 +		    case ENCODING_UTF16LE: /* RFC 2781 */
   4.642 +			{
   4.643 +				Uint8 *p = (Uint8 *)dst;
   4.644 +				if ( ch > 0x10FFFF ) {
   4.645 +					ch = UNKNOWN_UNICODE;
   4.646 +				}
   4.647 +				if ( ch < 0x10000 ) {
   4.648 +					if ( dstlen < 2 ) {
   4.649 +						return SDL_ICONV_E2BIG;
   4.650 +					}
   4.651 +					p[1] = (Uint8)(ch >> 8);
   4.652 +					p[0] = (Uint8)ch;
   4.653 +					dst += 2;
   4.654 +					dstlen -= 2;
   4.655 +				} else {
   4.656 +					Uint16 W1, W2;
   4.657 +					if ( dstlen < 4 ) {
   4.658 +						return SDL_ICONV_E2BIG;
   4.659 +					}
   4.660 +					ch = ch - 0x10000;
   4.661 +					W1 = 0xD800 | (Uint16)((ch >> 10) & 0x3FF);
   4.662 +					W2 = 0xDC00 | (Uint16)(ch & 0x3FF);
   4.663 +					p[1] = (Uint8)(W1 >> 8);
   4.664 +					p[0] = (Uint8)W1;
   4.665 +					p[3] = (Uint8)(W2 >> 8);
   4.666 +					p[2] = (Uint8)W2;
   4.667 +					dst += 4;
   4.668 +					dstlen -= 4;
   4.669 +				}
   4.670 +			}
   4.671 +			break;
   4.672 +		    case ENCODING_UTF32BE:
   4.673 +			{
   4.674 +				Uint8 *p = (Uint8 *)dst;
   4.675 +				if ( ch > 0x7FFFFFFF ) {
   4.676 +					ch = UNKNOWN_UNICODE;
   4.677 +				}
   4.678 +				if ( dstlen < 4 ) {
   4.679 +					return SDL_ICONV_E2BIG;
   4.680 +				}
   4.681 +				p[0] = (Uint8)(ch >> 24);
   4.682 +				p[1] = (Uint8)(ch >> 16);
   4.683 +				p[2] = (Uint8)(ch >> 8);
   4.684 +				p[3] = (Uint8)ch;
   4.685 +				dst += 4;
   4.686 +				dstlen -= 4;
   4.687 +			}
   4.688 +			break;
   4.689 +		    case ENCODING_UTF32LE:
   4.690 +			{
   4.691 +				Uint8 *p = (Uint8 *)dst;
   4.692 +				if ( ch > 0x7FFFFFFF ) {
   4.693 +					ch = UNKNOWN_UNICODE;
   4.694 +				}
   4.695 +				if ( dstlen < 4 ) {
   4.696 +					return SDL_ICONV_E2BIG;
   4.697 +				}
   4.698 +				p[3] = (Uint8)(ch >> 24);
   4.699 +				p[2] = (Uint8)(ch >> 16);
   4.700 +				p[1] = (Uint8)(ch >> 8);
   4.701 +				p[0] = (Uint8)ch;
   4.702 +				dst += 4;
   4.703 +				dstlen -= 4;
   4.704 +			}
   4.705 +			break;
   4.706 +		    case ENCODING_UCS2:
   4.707 +			{
   4.708 +				Uint16 *p = (Uint16 *)dst;
   4.709 +				if ( ch > 0xFFFF ) {
   4.710 +					ch = UNKNOWN_UNICODE;
   4.711 +				}
   4.712 +				if ( dstlen < 2 ) {
   4.713 +					return SDL_ICONV_E2BIG;
   4.714 +				}
   4.715 +				*p = (Uint16)ch;
   4.716 +				dst += 2;
   4.717 +				dstlen -= 2;
   4.718 +			}
   4.719 +			break;
   4.720 +		    case ENCODING_UCS4:
   4.721 +			{
   4.722 +				Uint32 *p = (Uint32 *)dst;
   4.723 +				if ( ch > 0x7FFFFFFF ) {
   4.724 +					ch = UNKNOWN_UNICODE;
   4.725 +				}
   4.726 +				if ( dstlen < 4 ) {
   4.727 +					return SDL_ICONV_E2BIG;
   4.728 +				}
   4.729 +				*p = ch;
   4.730 +				dst += 4;
   4.731 +				dstlen -= 4;
   4.732 +			}
   4.733 +			break;
   4.734 +		}
   4.735 +
   4.736 +		/* Update state */
   4.737 +		*inbuf = src;
   4.738 +		*inbytesleft = srclen;
   4.739 +		*outbuf = dst;
   4.740 +		*outbytesleft = dstlen;
   4.741 +		++total;
   4.742 +	}
   4.743 +	return total;
   4.744 +}
   4.745 +
   4.746 +int SDL_iconv_close(SDL_iconv_t cd)
   4.747 +{
   4.748 +	if ( cd && cd != (SDL_iconv_t)-1 ) {
   4.749 +		SDL_free(cd);
   4.750 +	}
   4.751 +	return 0;
   4.752 +}
   4.753 +
   4.754 +#endif /* !HAVE_ICONV */
   4.755 +
   4.756 +char *SDL_iconv_string(const char *tocode, const char *fromcode, char *inbuf, size_t inbytesleft)
   4.757 +{
   4.758 +	SDL_iconv_t cd;
   4.759 +	char *string;
   4.760 +	size_t stringsize;
   4.761 +	char *outbuf;
   4.762 +	size_t outbytesleft;
   4.763 +	size_t retCode = 0;
   4.764 +
   4.765 +	cd = SDL_iconv_open(tocode, fromcode);
   4.766 +	if ( cd == (SDL_iconv_t)-1 ) {
   4.767 +		return NULL;
   4.768 +	}
   4.769 +
   4.770 +	stringsize = inbytesleft > 4 ? inbytesleft : 4;
   4.771 +	string = SDL_malloc(stringsize);
   4.772 +	if ( !string ) {
   4.773 +		SDL_iconv_close(cd);
   4.774 +		return NULL;
   4.775 +	}
   4.776 +	outbuf = string;
   4.777 +	outbytesleft = stringsize;
   4.778 +	SDL_memset(outbuf, 0, 4);
   4.779 +
   4.780 +	while ( inbytesleft > 0 ) {
   4.781 +		retCode = SDL_iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
   4.782 +		switch (retCode) {
   4.783 +		    case SDL_ICONV_E2BIG:
   4.784 +			{
   4.785 +				char *oldstring = string;
   4.786 +				stringsize *= 2;
   4.787 +				string = SDL_realloc(string, stringsize);
   4.788 +				if ( !string ) {
   4.789 +					SDL_iconv_close(cd);
   4.790 +					return NULL;
   4.791 +				}
   4.792 +				outbuf = string + (outbuf - oldstring);
   4.793 +				outbytesleft = stringsize - (outbuf - string);
   4.794 +				SDL_memset(outbuf, 0, 4);
   4.795 +			}
   4.796 +			break;
   4.797 +		    case SDL_ICONV_EILSEQ:
   4.798 +			/* Try skipping some input data - not perfect, but... */
   4.799 +			++inbuf;
   4.800 +			--inbytesleft;
   4.801 +			break;
   4.802 +		    case SDL_ICONV_EINVAL:
   4.803 +		    case SDL_ICONV_ERROR:
   4.804 +			/* We can't continue... */
   4.805 +			inbytesleft = 0;
   4.806 +			break;
   4.807 +		}
   4.808 +	}
   4.809 +	SDL_iconv_close(cd);
   4.810 +
   4.811 +	return string;
   4.812 +}
     5.1 --- a/src/stdlib/SDL_string.c	Sun Mar 12 01:47:23 2006 +0000
     5.2 +++ b/src/stdlib/SDL_string.c	Mon Mar 13 01:08:00 2006 +0000
     5.3 @@ -661,12 +661,12 @@
     5.4  }
     5.5  #endif
     5.6  
     5.7 -#ifndef HAVE_STRCASECMP
     5.8 +#if !defined(HAVE_STRCASECMP) && !defined(HAVE_STRICMP)
     5.9  int SDL_strcasecmp(const char *str1, const char *str2)
    5.10  {
    5.11      char a = 0;
    5.12      char b = 0;
    5.13 -    while (*str1 && *str2) {
    5.14 +    while ( *str1 && *str2 ) {
    5.15          a = SDL_tolower(*str1);
    5.16          b = SDL_tolower(*str2);
    5.17          if ( a != b )
    5.18 @@ -678,6 +678,24 @@
    5.19  }
    5.20  #endif
    5.21  
    5.22 +#ifndef HAVE_STRNCASECMP
    5.23 +int SDL_strncasecmp(const char *str1, const char *str2, size_t maxlen)
    5.24 +{
    5.25 +    char a = 0;
    5.26 +    char b = 0;
    5.27 +    while ( *str1 && *str2 && maxlen ) {
    5.28 +        a = SDL_tolower(*str1);
    5.29 +        b = SDL_tolower(*str2);
    5.30 +        if ( a != b )
    5.31 +            break;
    5.32 +        ++str1;
    5.33 +        ++str2;
    5.34 +        --maxlen;
    5.35 +    }
    5.36 +    return (int)((unsigned char)a - (unsigned char)b);
    5.37 +}
    5.38 +#endif
    5.39 +
    5.40  #ifndef HAVE_SSCANF
    5.41  int SDL_sscanf(const char *text, const char *fmt, ...)
    5.42  {
     6.1 --- a/test/Makefile.in	Sun Mar 12 01:47:23 2006 +0000
     6.2 +++ b/test/Makefile.in	Mon Mar 13 01:08:00 2006 +0000
     6.3 @@ -7,7 +7,7 @@
     6.4  CFLAGS  = @CFLAGS@
     6.5  LIBS	= @LIBS@
     6.6  
     6.7 -TARGETS = checkkeys$(EXE) graywin$(EXE) loopwave$(EXE) testalpha$(EXE) testbitmap$(EXE) testblitspeed$(EXE) testcdrom$(EXE) testdyngl$(EXE) testerror$(EXE) testfile$(EXE) testgamma$(EXE) testgl$(EXE) testhread$(EXE) testjoystick$(EXE) testkeys$(EXE) testlock$(EXE) testoverlay2$(EXE) testoverlay$(EXE) testpalette$(EXE) testplatform$(EXE) testsem$(EXE) testsprite$(EXE) testtimer$(EXE) testver$(EXE) testvidinfo$(EXE) testwin$(EXE) testwm$(EXE) threadwin$(EXE) torturethread$(EXE)
     6.8 +TARGETS = checkkeys$(EXE) graywin$(EXE) loopwave$(EXE) testalpha$(EXE) testbitmap$(EXE) testblitspeed$(EXE) testcdrom$(EXE) testdyngl$(EXE) testerror$(EXE) testfile$(EXE) testgamma$(EXE) testgl$(EXE) testhread$(EXE) testiconv$(EXE) testjoystick$(EXE) testkeys$(EXE) testlock$(EXE) testoverlay2$(EXE) testoverlay$(EXE) testpalette$(EXE) testplatform$(EXE) testsem$(EXE) testsprite$(EXE) testtimer$(EXE) testver$(EXE) testvidinfo$(EXE) testwin$(EXE) testwm$(EXE) threadwin$(EXE) torturethread$(EXE)
     6.9  
    6.10  all: $(TARGETS)
    6.11  
    6.12 @@ -50,6 +50,9 @@
    6.13  testhread$(EXE): $(srcdir)/testhread.c
    6.14  	$(CC) -o $@ $? $(CFLAGS) $(LIBS)
    6.15  
    6.16 +testiconv$(EXE): $(srcdir)/testiconv.c
    6.17 +	$(CC) -o $@ $? $(CFLAGS) $(LIBS)
    6.18 +
    6.19  testjoystick$(EXE): $(srcdir)/testjoystick.c
    6.20  	$(CC) -o $@ $? $(CFLAGS) $(LIBS)
    6.21  
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/test/testiconv.c	Mon Mar 13 01:08:00 2006 +0000
     7.3 @@ -0,0 +1,85 @@
     7.4 +
     7.5 +#include <stdio.h>
     7.6 +
     7.7 +#include "SDL.h"
     7.8 +
     7.9 +static SDL_bool testutf16(char *data)
    7.10 +{
    7.11 +	Uint32 *p = (Uint32 *)data;
    7.12 +	while(*p) {
    7.13 +		if ( *p > 0x10FFFF ) {
    7.14 +			return SDL_FALSE;
    7.15 +		}
    7.16 +		++p;
    7.17 +	}
    7.18 +	return SDL_TRUE;
    7.19 +}
    7.20 +
    7.21 +static size_t widelen(char *data)
    7.22 +{
    7.23 +	size_t len = 0;
    7.24 +	Uint32 *p = (Uint32 *)data;
    7.25 +	while(*p++) {
    7.26 +		++len;
    7.27 +	}
    7.28 +	return len;
    7.29 +}
    7.30 +
    7.31 +int main(int argc, char *argv[])
    7.32 +{
    7.33 +	const char * formats[] = {
    7.34 +		"UTF8",
    7.35 +		"UTF-8",
    7.36 +		"UTF16BE",
    7.37 +		"UTF-16BE",
    7.38 +		"UTF16LE",
    7.39 +		"UTF-16LE",
    7.40 +		"UTF32BE",
    7.41 +		"UTF-32BE",
    7.42 +		"UTF32LE",
    7.43 +		"UTF-32LE",
    7.44 +		"UCS4",
    7.45 +		"UCS-4",
    7.46 +	};
    7.47 +	char buffer[BUFSIZ];
    7.48 +	char *ucs4;
    7.49 +	char *test[2];
    7.50 +	int i, j, index = 0;
    7.51 +	FILE *file;
    7.52 +	int errors = 0;
    7.53 +
    7.54 +	if ( !argv[1] ) {
    7.55 +		argv[1] = "utf8.txt";
    7.56 +	}
    7.57 +	file = fopen(argv[1], "rb");
    7.58 +	if ( !file ) {
    7.59 +		fprintf(stderr, "Unable to open %s\n", argv[1]);
    7.60 +		return (1);
    7.61 +	}
    7.62 +
    7.63 +	while ( fgets(buffer, sizeof(buffer), file) ) {
    7.64 +		/* Convert to UCS-4 */
    7.65 +		ucs4 = SDL_iconv_string("UCS-4", "UTF-8", buffer, SDL_strlen(buffer)+1);
    7.66 +		size_t len = (widelen(ucs4)+1)*4;
    7.67 +		for ( i = 0; i < SDL_arraysize(formats); ++i ) {
    7.68 +			if ( (SDL_strncasecmp(formats[i], "UTF16", 5) == 0 ||
    7.69 +			      SDL_strncasecmp(formats[i], "UTF-16", 6) == 0) &&
    7.70 +			      !testutf16(ucs4) ) {
    7.71 +				continue;
    7.72 +			}
    7.73 +			test[0] = SDL_iconv_string(formats[i], "UCS-4", ucs4, len);
    7.74 +			test[1] = SDL_iconv_string("UCS-4", formats[i], test[0], len);
    7.75 +			if ( SDL_memcmp(test[1], ucs4, len) != 0 ) {
    7.76 +				fprintf(stderr, "FAIL: %s\n", formats[i]);
    7.77 +				++errors;
    7.78 +			}
    7.79 +			SDL_free(test[0]);
    7.80 +			SDL_free(test[1]);
    7.81 +		}
    7.82 +		test[0] = SDL_iconv_string("UTF-8", "UCS-4", ucs4, len);
    7.83 +		SDL_free(ucs4);
    7.84 +		fputs(test[0], stdout);
    7.85 +		SDL_free(test[0]);
    7.86 +	}
    7.87 +	return (errors ? errors + 1 : 0);
    7.88 +}
     8.1 Binary file test/utf8.txt has changed