src/stdlib/SDL_iconv.c
branchSDL-1.3
changeset 1662 782fd950bd46
parent 1519 c99e7a9c9bc9
child 1668 4da1ee79c9af
equal deleted inserted replaced
1661:281d3f4870e5 1662:782fd950bd46
    28 
    28 
    29 #ifdef HAVE_ICONV
    29 #ifdef HAVE_ICONV
    30 
    30 
    31 #include <errno.h>
    31 #include <errno.h>
    32 
    32 
    33 size_t SDL_iconv(SDL_iconv_t cd,
    33 size_t
    34                  char **inbuf, size_t *inbytesleft,
    34 SDL_iconv (SDL_iconv_t cd,
    35                  char **outbuf, size_t *outbytesleft)
    35            char **inbuf, size_t * inbytesleft,
       
    36            char **outbuf, size_t * outbytesleft)
    36 {
    37 {
    37 	size_t retCode = iconv(cd, inbuf, inbytesleft, outbuf, outbytesleft);
    38     size_t retCode = iconv (cd, inbuf, inbytesleft, outbuf, outbytesleft);
    38 	if ( retCode == (size_t)-1 ) {
    39     if (retCode == (size_t) - 1) {
    39 		switch(errno) {
    40         switch (errno) {
    40 		    case E2BIG:
    41         case E2BIG:
    41 			return SDL_ICONV_E2BIG;
    42             return SDL_ICONV_E2BIG;
    42 		    case EILSEQ:
    43         case EILSEQ:
    43 			return SDL_ICONV_EILSEQ;
    44             return SDL_ICONV_EILSEQ;
    44 		    case EINVAL:
    45         case EINVAL:
    45 			return SDL_ICONV_EINVAL;
    46             return SDL_ICONV_EINVAL;
    46 		    default:
    47         default:
    47 			return SDL_ICONV_ERROR;
    48             return SDL_ICONV_ERROR;
    48 		}
    49         }
    49 	}
    50     }
    50 	return retCode;
    51     return retCode;
    51 }
    52 }
    52 
    53 
    53 #else
    54 #else
    54 
    55 
    55 /* Lots of useful information on Unicode at:
    56 /* Lots of useful information on Unicode at:
    59 #define UNICODE_BOM	0xFEFF
    60 #define UNICODE_BOM	0xFEFF
    60 
    61 
    61 #define UNKNOWN_ASCII	'?'
    62 #define UNKNOWN_ASCII	'?'
    62 #define UNKNOWN_UNICODE	0xFFFD
    63 #define UNKNOWN_UNICODE	0xFFFD
    63 
    64 
    64 enum {
    65 enum
    65 	ENCODING_UNKNOWN,
    66 {
    66 	ENCODING_ASCII,
    67     ENCODING_UNKNOWN,
    67 	ENCODING_LATIN1,
    68     ENCODING_ASCII,
    68 	ENCODING_UTF8,
    69     ENCODING_LATIN1,
    69 	ENCODING_UTF16,		/* Needs byte order marker */
    70     ENCODING_UTF8,
    70 	ENCODING_UTF16BE,
    71     ENCODING_UTF16,             /* Needs byte order marker */
    71 	ENCODING_UTF16LE,
    72     ENCODING_UTF16BE,
    72 	ENCODING_UTF32,		/* Needs byte order marker */
    73     ENCODING_UTF16LE,
    73 	ENCODING_UTF32BE,
    74     ENCODING_UTF32,             /* Needs byte order marker */
    74 	ENCODING_UTF32LE,
    75     ENCODING_UTF32BE,
    75 	ENCODING_UCS2,		/* Native byte order assumed */
    76     ENCODING_UTF32LE,
    76 	ENCODING_UCS4,		/* Native byte order assumed */
    77     ENCODING_UCS2,              /* Native byte order assumed */
       
    78     ENCODING_UCS4,              /* Native byte order assumed */
    77 };
    79 };
    78 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
    80 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
    79 #define ENCODING_UTF16NATIVE	ENCODING_UTF16BE
    81 #define ENCODING_UTF16NATIVE	ENCODING_UTF16BE
    80 #define ENCODING_UTF32NATIVE	ENCODING_UTF32BE
    82 #define ENCODING_UTF32NATIVE	ENCODING_UTF32BE
    81 #else
    83 #else
    83 #define ENCODING_UTF32NATIVE	ENCODING_UTF32LE
    85 #define ENCODING_UTF32NATIVE	ENCODING_UTF32LE
    84 #endif
    86 #endif
    85 
    87 
    86 struct _SDL_iconv_t
    88 struct _SDL_iconv_t
    87 {
    89 {
    88 	int src_fmt;
    90     int src_fmt;
    89 	int dst_fmt;
    91     int dst_fmt;
    90 };
    92 };
    91 
    93 
    92 static struct {
    94 static struct
    93 	const char *name;
    95 {
    94 	int format;
    96     const char *name;
       
    97     int format;
    95 } encodings[] = {
    98 } encodings[] = {
    96 	{ "ASCII",	ENCODING_ASCII },
    99     {
    97 	{ "US-ASCII",	ENCODING_ASCII },
   100     "ASCII", ENCODING_ASCII}, {
    98 	{ "LATIN1",	ENCODING_LATIN1 },
   101     "US-ASCII", ENCODING_ASCII}, {
    99 	{ "ISO-8859-1",	ENCODING_LATIN1 },
   102     "LATIN1", ENCODING_LATIN1}, {
   100 	{ "UTF8",	ENCODING_UTF8 },
   103     "ISO-8859-1", ENCODING_LATIN1}, {
   101 	{ "UTF-8",	ENCODING_UTF8 },
   104     "UTF8", ENCODING_UTF8}, {
   102 	{ "UTF16",	ENCODING_UTF16 },
   105     "UTF-8", ENCODING_UTF8}, {
   103 	{ "UTF-16",	ENCODING_UTF16 },
   106     "UTF16", ENCODING_UTF16}, {
   104 	{ "UTF16BE",	ENCODING_UTF16BE },
   107     "UTF-16", ENCODING_UTF16}, {
   105 	{ "UTF-16BE",	ENCODING_UTF16BE },
   108     "UTF16BE", ENCODING_UTF16BE}, {
   106 	{ "UTF16LE",	ENCODING_UTF16LE },
   109     "UTF-16BE", ENCODING_UTF16BE}, {
   107 	{ "UTF-16LE",	ENCODING_UTF16LE },
   110     "UTF16LE", ENCODING_UTF16LE}, {
   108 	{ "UTF32",	ENCODING_UTF32 },
   111     "UTF-16LE", ENCODING_UTF16LE}, {
   109 	{ "UTF-32",	ENCODING_UTF32 },
   112     "UTF32", ENCODING_UTF32}, {
   110 	{ "UTF32BE",	ENCODING_UTF32BE },
   113     "UTF-32", ENCODING_UTF32}, {
   111 	{ "UTF-32BE",	ENCODING_UTF32BE },
   114     "UTF32BE", ENCODING_UTF32BE}, {
   112 	{ "UTF32LE",	ENCODING_UTF32LE },
   115     "UTF-32BE", ENCODING_UTF32BE}, {
   113 	{ "UTF-32LE",	ENCODING_UTF32LE },
   116     "UTF32LE", ENCODING_UTF32LE}, {
   114 	{ "UCS2",	ENCODING_UCS2 },
   117     "UTF-32LE", ENCODING_UTF32LE}, {
   115 	{ "UCS-2",	ENCODING_UCS2 },
   118     "UCS2", ENCODING_UCS2}, {
   116 	{ "UCS4",	ENCODING_UCS4 },
   119     "UCS-2", ENCODING_UCS2}, {
   117 	{ "UCS-4",	ENCODING_UCS4 },
   120     "UCS4", ENCODING_UCS4}, {
   118 };
   121 "UCS-4", ENCODING_UCS4},};
   119 
   122 
   120 SDL_iconv_t SDL_iconv_open(const char *tocode, const char *fromcode)
   123 SDL_iconv_t
       
   124 SDL_iconv_open (const char *tocode, const char *fromcode)
   121 {
   125 {
   122 	int src_fmt = ENCODING_UNKNOWN;
   126     int src_fmt = ENCODING_UNKNOWN;
   123 	int dst_fmt = ENCODING_UNKNOWN;
   127     int dst_fmt = ENCODING_UNKNOWN;
   124 	int i;
   128     int i;
   125 
   129 
   126 	for ( i = 0; i < SDL_arraysize(encodings); ++i ) {
   130     for (i = 0; i < SDL_arraysize (encodings); ++i) {
   127 		if ( SDL_strcasecmp(fromcode, encodings[i].name) == 0 ) {
   131         if (SDL_strcasecmp (fromcode, encodings[i].name) == 0) {
   128 			src_fmt = encodings[i].format;
   132             src_fmt = encodings[i].format;
   129 			if ( dst_fmt != ENCODING_UNKNOWN ) {
   133             if (dst_fmt != ENCODING_UNKNOWN) {
   130 				break;
   134                 break;
   131 			}
   135             }
   132 		}
   136         }
   133 		if ( SDL_strcasecmp(tocode, encodings[i].name) == 0 ) {
   137         if (SDL_strcasecmp (tocode, encodings[i].name) == 0) {
   134 			dst_fmt = encodings[i].format;
   138             dst_fmt = encodings[i].format;
   135 			if ( src_fmt != ENCODING_UNKNOWN ) {
   139             if (src_fmt != ENCODING_UNKNOWN) {
   136 				break;
   140                 break;
   137 			}
   141             }
   138 		}
   142         }
   139 	}
   143     }
   140 	if ( src_fmt != ENCODING_UNKNOWN && dst_fmt != ENCODING_UNKNOWN ) {
   144     if (src_fmt != ENCODING_UNKNOWN && dst_fmt != ENCODING_UNKNOWN) {
   141 		SDL_iconv_t cd = (SDL_iconv_t)SDL_malloc(sizeof(*cd));
   145         SDL_iconv_t cd = (SDL_iconv_t) SDL_malloc (sizeof (*cd));
   142 		if ( cd ) {
   146         if (cd) {
   143 			cd->src_fmt = src_fmt;
   147             cd->src_fmt = src_fmt;
   144 			cd->dst_fmt = dst_fmt;
   148             cd->dst_fmt = dst_fmt;
   145 			return cd;
   149             return cd;
   146 		}
   150         }
   147 	}
   151     }
   148 	return (SDL_iconv_t)-1;
   152     return (SDL_iconv_t) - 1;
   149 }
   153 }
   150 
   154 
   151 size_t SDL_iconv(SDL_iconv_t cd,
   155 size_t
   152                  char **inbuf, size_t *inbytesleft,
   156 SDL_iconv (SDL_iconv_t cd,
   153                  char **outbuf, size_t *outbytesleft)
   157            char **inbuf, size_t * inbytesleft,
       
   158            char **outbuf, size_t * outbytesleft)
   154 {
   159 {
   155 	/* For simplicity, we'll convert everything to and from UCS-4 */
   160     /* For simplicity, we'll convert everything to and from UCS-4 */
   156 	char *src, *dst;
   161     char *src, *dst;
   157 	size_t srclen, dstlen;
   162     size_t srclen, dstlen;
   158 	Uint32 ch;
   163     Uint32 ch;
   159 	size_t total;
   164     size_t total;
   160 
   165 
   161 	if ( !inbuf || !*inbuf ) {
   166     if (!inbuf || !*inbuf) {
   162 		/* Reset the context */
   167         /* Reset the context */
   163 		return 0;
   168         return 0;
   164 	}
   169     }
   165 	if ( !outbuf || !*outbuf || !outbytesleft || !*outbytesleft ) {
   170     if (!outbuf || !*outbuf || !outbytesleft || !*outbytesleft) {
   166 		return SDL_ICONV_E2BIG;
   171         return SDL_ICONV_E2BIG;
   167 	}
   172     }
   168 	src = *inbuf;
   173     src = *inbuf;
   169 	srclen = (inbytesleft ? *inbytesleft : 0);
   174     srclen = (inbytesleft ? *inbytesleft : 0);
   170 	dst = *outbuf;
   175     dst = *outbuf;
   171 	dstlen = *outbytesleft;
   176     dstlen = *outbytesleft;
   172 
   177 
   173 	switch ( cd->src_fmt ) {
   178     switch (cd->src_fmt) {
   174 	    case ENCODING_UTF16:
   179     case ENCODING_UTF16:
   175 		/* Scan for a byte order marker */
   180         /* Scan for a byte order marker */
   176 		{
   181         {
   177 			Uint8 *p = (Uint8 *)src;
   182             Uint8 *p = (Uint8 *) src;
   178 			size_t n = srclen / 2;
   183             size_t n = srclen / 2;
   179 			while ( n ) {
   184             while (n) {
   180 				if ( p[0] == 0xFF && p[1] == 0xFE ) {
   185                 if (p[0] == 0xFF && p[1] == 0xFE) {
   181 					cd->src_fmt = ENCODING_UTF16BE;
   186                     cd->src_fmt = ENCODING_UTF16BE;
   182 					break;
   187                     break;
   183 				} else if ( p[0] == 0xFE && p[1] == 0xFF ) {
   188                 } else if (p[0] == 0xFE && p[1] == 0xFF) {
   184 					cd->src_fmt = ENCODING_UTF16LE;
   189                     cd->src_fmt = ENCODING_UTF16LE;
   185 					break;
   190                     break;
   186 				}
   191                 }
   187 				p += 2;
   192                 p += 2;
   188 				--n;
   193                 --n;
   189 			}
   194             }
   190 			if ( n == 0 ) {
   195             if (n == 0) {
   191 				/* We can't tell, default to host order */
   196                 /* We can't tell, default to host order */
   192 				cd->src_fmt = ENCODING_UTF16NATIVE;
   197                 cd->src_fmt = ENCODING_UTF16NATIVE;
   193 			}
   198             }
   194 		}
   199         }
   195 		break;
   200         break;
   196 	    case ENCODING_UTF32:
   201     case ENCODING_UTF32:
   197 		/* Scan for a byte order marker */
   202         /* Scan for a byte order marker */
   198 		{
   203         {
   199 			Uint8 *p = (Uint8 *)src;
   204             Uint8 *p = (Uint8 *) src;
   200 			size_t n = srclen / 4;
   205             size_t n = srclen / 4;
   201 			while ( n ) {
   206             while (n) {
   202 				if ( p[0] == 0xFF && p[1] == 0xFE &&
   207                 if (p[0] == 0xFF && p[1] == 0xFE &&
   203 				     p[2] == 0x00 && p[3] == 0x00 ) {
   208                     p[2] == 0x00 && p[3] == 0x00) {
   204 					cd->src_fmt = ENCODING_UTF32BE;
   209                     cd->src_fmt = ENCODING_UTF32BE;
   205 					break;
   210                     break;
   206 				} else if ( p[0] == 0x00 && p[1] == 0x00 &&
   211                 } else if (p[0] == 0x00 && p[1] == 0x00 &&
   207 				            p[2] == 0xFE && p[3] == 0xFF ) {
   212                            p[2] == 0xFE && p[3] == 0xFF) {
   208 					cd->src_fmt = ENCODING_UTF32LE;
   213                     cd->src_fmt = ENCODING_UTF32LE;
   209 					break;
   214                     break;
   210 				}
   215                 }
   211 				p += 4;
   216                 p += 4;
   212 				--n;
   217                 --n;
   213 			}
   218             }
   214 			if ( n == 0 ) {
   219             if (n == 0) {
   215 				/* We can't tell, default to host order */
   220                 /* We can't tell, default to host order */
   216 				cd->src_fmt = ENCODING_UTF32NATIVE;
   221                 cd->src_fmt = ENCODING_UTF32NATIVE;
   217 			}
   222             }
   218 		}
   223         }
   219 		break;
   224         break;
   220 	}
   225     }
   221 
   226 
   222 	switch ( cd->dst_fmt ) {
   227     switch (cd->dst_fmt) {
   223 	    case ENCODING_UTF16:
   228     case ENCODING_UTF16:
   224 		/* Default to host order, need to add byte order marker */
   229         /* Default to host order, need to add byte order marker */
   225 		if ( dstlen < 2 ) {
   230         if (dstlen < 2) {
   226 			return SDL_ICONV_E2BIG;
   231             return SDL_ICONV_E2BIG;
   227 		}
   232         }
   228 		*(Uint16 *)dst = UNICODE_BOM;
   233         *(Uint16 *) dst = UNICODE_BOM;
   229 		dst += 2;
   234         dst += 2;
   230 		dstlen -= 2;
   235         dstlen -= 2;
   231 		cd->dst_fmt = ENCODING_UTF16NATIVE;
   236         cd->dst_fmt = ENCODING_UTF16NATIVE;
   232 		break;
   237         break;
   233 	    case ENCODING_UTF32:
   238     case ENCODING_UTF32:
   234 		/* Default to host order, need to add byte order marker */
   239         /* Default to host order, need to add byte order marker */
   235 		if ( dstlen < 4 ) {
   240         if (dstlen < 4) {
   236 			return SDL_ICONV_E2BIG;
   241             return SDL_ICONV_E2BIG;
   237 		}
   242         }
   238 		*(Uint32 *)dst = UNICODE_BOM;
   243         *(Uint32 *) dst = UNICODE_BOM;
   239 		dst += 4;
   244         dst += 4;
   240 		dstlen -= 4;
   245         dstlen -= 4;
   241 		cd->dst_fmt = ENCODING_UTF32NATIVE;
   246         cd->dst_fmt = ENCODING_UTF32NATIVE;
   242 		break;
   247         break;
   243 	}
   248     }
   244 
   249 
   245 	total = 0;
   250     total = 0;
   246 	while ( srclen > 0 ) {
   251     while (srclen > 0) {
   247 		/* Decode a character */
   252         /* Decode a character */
   248 		switch ( cd->src_fmt ) {
   253         switch (cd->src_fmt) {
   249 		    case ENCODING_ASCII:
   254         case ENCODING_ASCII:
   250 			{
   255             {
   251 				Uint8 *p = (Uint8 *)src;
   256                 Uint8 *p = (Uint8 *) src;
   252 				ch = (Uint32)(p[0] & 0x7F);
   257                 ch = (Uint32) (p[0] & 0x7F);
   253 				++src;
   258                 ++src;
   254 				--srclen;
   259                 --srclen;
   255 			}
   260             }
   256 			break;
   261             break;
   257 		    case ENCODING_LATIN1:
   262         case ENCODING_LATIN1:
   258 			{
   263             {
   259 				Uint8 *p = (Uint8 *)src;
   264                 Uint8 *p = (Uint8 *) src;
   260 				ch = (Uint32)p[0];
   265                 ch = (Uint32) p[0];
   261 				++src;
   266                 ++src;
   262 				--srclen;
   267                 --srclen;
   263 			}
   268             }
   264 			break;
   269             break;
   265 		    case ENCODING_UTF8: /* RFC 3629 */
   270         case ENCODING_UTF8:    /* RFC 3629 */
   266 			{
   271             {
   267 				Uint8 *p = (Uint8 *)src;
   272                 Uint8 *p = (Uint8 *) src;
   268 				size_t left = 0;
   273                 size_t left = 0;
   269 				SDL_bool overlong = SDL_FALSE;
   274                 SDL_bool overlong = SDL_FALSE;
   270 				if ( p[0] >= 0xFC ) {
   275                 if (p[0] >= 0xFC) {
   271 					if ( (p[0] & 0xFE) != 0xFC ) {
   276                     if ((p[0] & 0xFE) != 0xFC) {
   272 						/* Skip illegal sequences
   277                         /* Skip illegal sequences
   273 						return SDL_ICONV_EILSEQ;
   278                            return SDL_ICONV_EILSEQ;
   274 						*/
   279                          */
   275 						ch = UNKNOWN_UNICODE;
   280                         ch = UNKNOWN_UNICODE;
   276 					} else {
   281                     } else {
   277 						if ( p[0] == 0xFC ) {
   282                         if (p[0] == 0xFC) {
   278 							overlong = SDL_TRUE;
   283                             overlong = SDL_TRUE;
   279 						}
   284                         }
   280 						ch = (Uint32)(p[0] & 0x01);
   285                         ch = (Uint32) (p[0] & 0x01);
   281 						left = 5;
   286                         left = 5;
   282 					}
   287                     }
   283 				} else if ( p[0] >= 0xF8 ) {
   288                 } else if (p[0] >= 0xF8) {
   284 					if ( (p[0] & 0xFC) != 0xF8 ) {
   289                     if ((p[0] & 0xFC) != 0xF8) {
   285 						/* Skip illegal sequences
   290                         /* Skip illegal sequences
   286 						return SDL_ICONV_EILSEQ;
   291                            return SDL_ICONV_EILSEQ;
   287 						*/
   292                          */
   288 						ch = UNKNOWN_UNICODE;
   293                         ch = UNKNOWN_UNICODE;
   289 					} else {
   294                     } else {
   290 						if ( p[0] == 0xF8 ) {
   295                         if (p[0] == 0xF8) {
   291 							overlong = SDL_TRUE;
   296                             overlong = SDL_TRUE;
   292 						}
   297                         }
   293 						ch = (Uint32)(p[0] & 0x03);
   298                         ch = (Uint32) (p[0] & 0x03);
   294 						left = 4;
   299                         left = 4;
   295 					}
   300                     }
   296 				} else if ( p[0] >= 0xF0 ) {
   301                 } else if (p[0] >= 0xF0) {
   297 					if ( (p[0] & 0xF8) != 0xF0 ) {
   302                     if ((p[0] & 0xF8) != 0xF0) {
   298 						/* Skip illegal sequences
   303                         /* Skip illegal sequences
   299 						return SDL_ICONV_EILSEQ;
   304                            return SDL_ICONV_EILSEQ;
   300 						*/
   305                          */
   301 						ch = UNKNOWN_UNICODE;
   306                         ch = UNKNOWN_UNICODE;
   302 					} else {
   307                     } else {
   303 						if ( p[0] == 0xF0 ) {
   308                         if (p[0] == 0xF0) {
   304 							overlong = SDL_TRUE;
   309                             overlong = SDL_TRUE;
   305 						}
   310                         }
   306 						ch = (Uint32)(p[0] & 0x07);
   311                         ch = (Uint32) (p[0] & 0x07);
   307 						left = 3;
   312                         left = 3;
   308 					}
   313                     }
   309 				} else if ( p[0] >= 0xE0 ) {
   314                 } else if (p[0] >= 0xE0) {
   310 					if ( (p[0] & 0xF0) != 0xE0 ) {
   315                     if ((p[0] & 0xF0) != 0xE0) {
   311 						/* Skip illegal sequences
   316                         /* Skip illegal sequences
   312 						return SDL_ICONV_EILSEQ;
   317                            return SDL_ICONV_EILSEQ;
   313 						*/
   318                          */
   314 						ch = UNKNOWN_UNICODE;
   319                         ch = UNKNOWN_UNICODE;
   315 					} else {
   320                     } else {
   316 						if ( p[0] == 0xE0 ) {
   321                         if (p[0] == 0xE0) {
   317 							overlong = SDL_TRUE;
   322                             overlong = SDL_TRUE;
   318 						}
   323                         }
   319 						ch = (Uint32)(p[0] & 0x0F);
   324                         ch = (Uint32) (p[0] & 0x0F);
   320 						left = 2;
   325                         left = 2;
   321 					}
   326                     }
   322 				} else if ( p[0] >= 0xC0 ) {
   327                 } else if (p[0] >= 0xC0) {
   323 					if ( (p[0] & 0xE0) != 0xC0 ) {
   328                     if ((p[0] & 0xE0) != 0xC0) {
   324 						/* Skip illegal sequences
   329                         /* Skip illegal sequences
   325 						return SDL_ICONV_EILSEQ;
   330                            return SDL_ICONV_EILSEQ;
   326 						*/
   331                          */
   327 						ch = UNKNOWN_UNICODE;
   332                         ch = UNKNOWN_UNICODE;
   328 					} else {
   333                     } else {
   329 						if ( (p[0] & 0xCE) == 0xC0 ) {
   334                         if ((p[0] & 0xCE) == 0xC0) {
   330 							overlong = SDL_TRUE;
   335                             overlong = SDL_TRUE;
   331 						}
   336                         }
   332 						ch = (Uint32)(p[0] & 0x1F);
   337                         ch = (Uint32) (p[0] & 0x1F);
   333 						left = 1;
   338                         left = 1;
   334 					}
   339                     }
   335 				} else {
   340                 } else {
   336 					if ( (p[0] & 0x80) != 0x00 ) {
   341                     if ((p[0] & 0x80) != 0x00) {
   337 						/* Skip illegal sequences
   342                         /* Skip illegal sequences
   338 						return SDL_ICONV_EILSEQ;
   343                            return SDL_ICONV_EILSEQ;
   339 						*/
   344                          */
   340 						ch = UNKNOWN_UNICODE;
   345                         ch = UNKNOWN_UNICODE;
   341 					} else {
   346                     } else {
   342 						ch = (Uint32)p[0];
   347                         ch = (Uint32) p[0];
   343 					}
   348                     }
   344 				}
   349                 }
   345 				++src;
   350                 ++src;
   346 				--srclen;
   351                 --srclen;
   347 				if ( srclen < left ) {
   352                 if (srclen < left) {
   348 					return SDL_ICONV_EINVAL;
   353                     return SDL_ICONV_EINVAL;
   349 				}
   354                 }
   350 				while ( left-- ) {
   355                 while (left--) {
   351 					++p;
   356                     ++p;
   352 					if ( (p[0] & 0xC0) != 0x80 ) {
   357                     if ((p[0] & 0xC0) != 0x80) {
   353 						/* Skip illegal sequences
   358                         /* Skip illegal sequences
   354 						return SDL_ICONV_EILSEQ;
   359                            return SDL_ICONV_EILSEQ;
   355 						*/
   360                          */
   356 						ch = UNKNOWN_UNICODE;
   361                         ch = UNKNOWN_UNICODE;
   357 						break;
   362                         break;
   358 					}
   363                     }
   359 					ch <<= 6;
   364                     ch <<= 6;
   360 					ch |= (p[0] & 0x3F);
   365                     ch |= (p[0] & 0x3F);
   361 					++src;
   366                     ++src;
   362 					--srclen;
   367                     --srclen;
   363 				}
   368                 }
   364 				if ( overlong ) {
   369                 if (overlong) {
   365 					/* Potential security risk
   370                     /* Potential security risk
   366 					return SDL_ICONV_EILSEQ;
   371                        return SDL_ICONV_EILSEQ;
   367 					*/
   372                      */
   368 					ch = UNKNOWN_UNICODE;
   373                     ch = UNKNOWN_UNICODE;
   369 				}
   374                 }
   370 				if ( (ch >= 0xD800 && ch <= 0xDFFF) ||
   375                 if ((ch >= 0xD800 && ch <= 0xDFFF) ||
   371 				     (ch == 0xFFFE || ch == 0xFFFF) ||
   376                     (ch == 0xFFFE || ch == 0xFFFF) || ch > 0x10FFFF) {
   372 				     ch > 0x10FFFF ) {
   377                     /* Skip illegal sequences
   373 					/* Skip illegal sequences
   378                        return SDL_ICONV_EILSEQ;
   374 					return SDL_ICONV_EILSEQ;
   379                      */
   375 					*/
   380                     ch = UNKNOWN_UNICODE;
   376 					ch = UNKNOWN_UNICODE;
   381                 }
   377 				}
   382             }
   378 			}
   383             break;
   379 			break;
   384         case ENCODING_UTF16BE: /* RFC 2781 */
   380 		    case ENCODING_UTF16BE: /* RFC 2781 */
   385             {
   381 			{
   386                 Uint8 *p = (Uint8 *) src;
   382 				Uint8 *p = (Uint8 *)src;
   387                 Uint16 W1, W2;
   383 				Uint16 W1, W2;
   388                 if (srclen < 2) {
   384 				if ( srclen < 2 ) {
   389                     return SDL_ICONV_EINVAL;
   385 					return SDL_ICONV_EINVAL;
   390                 }
   386 				}
   391                 W1 = ((Uint16) p[0] << 8) | (Uint16) p[1];
   387 				W1 = ((Uint16)p[0] << 8) |
   392                 src += 2;
   388 				      (Uint16)p[1];
   393                 srclen -= 2;
   389 				src += 2;
   394                 if (W1 < 0xD800 || W1 > 0xDFFF) {
   390 				srclen -= 2;
   395                     ch = (Uint32) W1;
   391 				if ( W1 < 0xD800 || W1 > 0xDFFF ) {
   396                     break;
   392 					ch = (Uint32)W1;
   397                 }
   393 					break;
   398                 if (W1 > 0xDBFF) {
   394 				}
   399                     /* Skip illegal sequences
   395 				if ( W1 > 0xDBFF ) {
   400                        return SDL_ICONV_EILSEQ;
   396 					/* Skip illegal sequences
   401                      */
   397 					return SDL_ICONV_EILSEQ;
   402                     ch = UNKNOWN_UNICODE;
   398 					*/
   403                     break;
   399 					ch = UNKNOWN_UNICODE;
   404                 }
   400 					break;
   405                 if (srclen < 2) {
   401 				}
   406                     return SDL_ICONV_EINVAL;
   402 				if ( srclen < 2 ) {
   407                 }
   403 					return SDL_ICONV_EINVAL;
   408                 p = (Uint8 *) src;
   404 				}
   409                 W2 = ((Uint16) p[0] << 8) | (Uint16) p[1];
   405 				p = (Uint8 *)src;
   410                 src += 2;
   406 				W2 = ((Uint16)p[0] << 8) |
   411                 srclen -= 2;
   407 				      (Uint16)p[1];
   412                 if (W2 < 0xDC00 || W2 > 0xDFFF) {
   408 				src += 2;
   413                     /* Skip illegal sequences
   409 				srclen -= 2;
   414                        return SDL_ICONV_EILSEQ;
   410 				if ( W2 < 0xDC00 || W2 > 0xDFFF ) {
   415                      */
   411 					/* Skip illegal sequences
   416                     ch = UNKNOWN_UNICODE;
   412 					return SDL_ICONV_EILSEQ;
   417                     break;
   413 					*/
   418                 }
   414 					ch = UNKNOWN_UNICODE;
   419                 ch = (((Uint32) (W1 & 0x3FF) << 10) |
   415 					break;
   420                       (Uint32) (W2 & 0x3FF)) + 0x10000;
   416 				}
   421             }
   417 				ch = (((Uint32)(W1 & 0x3FF) << 10) |
   422             break;
   418 				      (Uint32)(W2 & 0x3FF)) + 0x10000;
   423         case ENCODING_UTF16LE: /* RFC 2781 */
   419 			}
   424             {
   420 			break;
   425                 Uint8 *p = (Uint8 *) src;
   421 		    case ENCODING_UTF16LE: /* RFC 2781 */
   426                 Uint16 W1, W2;
   422 			{
   427                 if (srclen < 2) {
   423 				Uint8 *p = (Uint8 *)src;
   428                     return SDL_ICONV_EINVAL;
   424 				Uint16 W1, W2;
   429                 }
   425 				if ( srclen < 2 ) {
   430                 W1 = ((Uint16) p[1] << 8) | (Uint16) p[0];
   426 					return SDL_ICONV_EINVAL;
   431                 src += 2;
   427 				}
   432                 srclen -= 2;
   428 				W1 = ((Uint16)p[1] << 8) |
   433                 if (W1 < 0xD800 || W1 > 0xDFFF) {
   429 				      (Uint16)p[0];
   434                     ch = (Uint32) W1;
   430 				src += 2;
   435                     break;
   431 				srclen -= 2;
   436                 }
   432 				if ( W1 < 0xD800 || W1 > 0xDFFF ) {
   437                 if (W1 > 0xDBFF) {
   433 					ch = (Uint32)W1;
   438                     /* Skip illegal sequences
   434 					break;
   439                        return SDL_ICONV_EILSEQ;
   435 				}
   440                      */
   436 				if ( W1 > 0xDBFF ) {
   441                     ch = UNKNOWN_UNICODE;
   437 					/* Skip illegal sequences
   442                     break;
   438 					return SDL_ICONV_EILSEQ;
   443                 }
   439 					*/
   444                 if (srclen < 2) {
   440 					ch = UNKNOWN_UNICODE;
   445                     return SDL_ICONV_EINVAL;
   441 					break;
   446                 }
   442 				}
   447                 p = (Uint8 *) src;
   443 				if ( srclen < 2 ) {
   448                 W2 = ((Uint16) p[1] << 8) | (Uint16) p[0];
   444 					return SDL_ICONV_EINVAL;
   449                 src += 2;
   445 				}
   450                 srclen -= 2;
   446 				p = (Uint8 *)src;
   451                 if (W2 < 0xDC00 || W2 > 0xDFFF) {
   447 				W2 = ((Uint16)p[1] << 8) |
   452                     /* Skip illegal sequences
   448 				      (Uint16)p[0];
   453                        return SDL_ICONV_EILSEQ;
   449 				src += 2;
   454                      */
   450 				srclen -= 2;
   455                     ch = UNKNOWN_UNICODE;
   451 				if ( W2 < 0xDC00 || W2 > 0xDFFF ) {
   456                     break;
   452 					/* Skip illegal sequences
   457                 }
   453 					return SDL_ICONV_EILSEQ;
   458                 ch = (((Uint32) (W1 & 0x3FF) << 10) |
   454 					*/
   459                       (Uint32) (W2 & 0x3FF)) + 0x10000;
   455 					ch = UNKNOWN_UNICODE;
   460             }
   456 					break;
   461             break;
   457 				}
   462         case ENCODING_UTF32BE:
   458 				ch = (((Uint32)(W1 & 0x3FF) << 10) |
   463             {
   459 				      (Uint32)(W2 & 0x3FF)) + 0x10000;
   464                 Uint8 *p = (Uint8 *) src;
   460 			}
   465                 if (srclen < 4) {
   461 			break;
   466                     return SDL_ICONV_EINVAL;
   462 		    case ENCODING_UTF32BE:
   467                 }
   463 			{
   468                 ch = ((Uint32) p[0] << 24) |
   464 				Uint8 *p = (Uint8 *)src;
   469                     ((Uint32) p[1] << 16) |
   465 				if ( srclen < 4 ) {
   470                     ((Uint32) p[2] << 8) | (Uint32) p[3];
   466 					return SDL_ICONV_EINVAL;
   471                 src += 4;
   467 				}
   472                 srclen -= 4;
   468 				ch = ((Uint32)p[0] << 24) |
   473             }
   469 				     ((Uint32)p[1] << 16) |
   474             break;
   470 				     ((Uint32)p[2] << 8) |
   475         case ENCODING_UTF32LE:
   471 				      (Uint32)p[3];
   476             {
   472 				src += 4;
   477                 Uint8 *p = (Uint8 *) src;
   473 				srclen -= 4;
   478                 if (srclen < 4) {
   474 			}
   479                     return SDL_ICONV_EINVAL;
   475 			break;
   480                 }
   476 		    case ENCODING_UTF32LE:
   481                 ch = ((Uint32) p[3] << 24) |
   477 			{
   482                     ((Uint32) p[2] << 16) |
   478 				Uint8 *p = (Uint8 *)src;
   483                     ((Uint32) p[1] << 8) | (Uint32) p[0];
   479 				if ( srclen < 4 ) {
   484                 src += 4;
   480 					return SDL_ICONV_EINVAL;
   485                 srclen -= 4;
   481 				}
   486             }
   482 				ch = ((Uint32)p[3] << 24) |
   487             break;
   483 				     ((Uint32)p[2] << 16) |
   488         case ENCODING_UCS2:
   484 				     ((Uint32)p[1] << 8) |
   489             {
   485 				      (Uint32)p[0];
   490                 Uint16 *p = (Uint16 *) src;
   486 				src += 4;
   491                 if (srclen < 2) {
   487 				srclen -= 4;
   492                     return SDL_ICONV_EINVAL;
   488 			}
   493                 }
   489 			break;
   494                 ch = *p;
   490 		    case ENCODING_UCS2:
   495                 src += 2;
   491 			{
   496                 srclen -= 2;
   492 				Uint16 *p = (Uint16 *)src;
   497             }
   493 				if ( srclen < 2 ) {
   498             break;
   494 					return SDL_ICONV_EINVAL;
   499         case ENCODING_UCS4:
   495 				}
   500             {
   496 				ch = *p;
   501                 Uint32 *p = (Uint32 *) src;
   497 				src += 2;
   502                 if (srclen < 4) {
   498 				srclen -= 2;
   503                     return SDL_ICONV_EINVAL;
   499 			}
   504                 }
   500 			break;
   505                 ch = *p;
   501 		    case ENCODING_UCS4:
   506                 src += 4;
   502 			{
   507                 srclen -= 4;
   503 				Uint32 *p = (Uint32 *)src;
   508             }
   504 				if ( srclen < 4 ) {
   509             break;
   505 					return SDL_ICONV_EINVAL;
   510         }
   506 				}
   511 
   507 				ch = *p;
   512         /* Encode a character */
   508 				src += 4;
   513         switch (cd->dst_fmt) {
   509 				srclen -= 4;
   514         case ENCODING_ASCII:
   510 			}
   515             {
   511 			break;
   516                 Uint8 *p = (Uint8 *) dst;
   512 		}
   517                 if (dstlen < 1) {
   513 
   518                     return SDL_ICONV_E2BIG;
   514 		/* Encode a character */
   519                 }
   515 		switch ( cd->dst_fmt ) {
   520                 if (ch > 0x7F) {
   516 		    case ENCODING_ASCII:
   521                     *p = UNKNOWN_ASCII;
   517 			{
   522                 } else {
   518 				Uint8 *p = (Uint8 *)dst;
   523                     *p = (Uint8) ch;
   519 				if ( dstlen < 1 ) {
   524                 }
   520 					return SDL_ICONV_E2BIG;
   525                 ++dst;
   521 				}
   526                 --dstlen;
   522 				if ( ch > 0x7F ) {
   527             }
   523 					*p = UNKNOWN_ASCII;
   528             break;
   524 				} else {
   529         case ENCODING_LATIN1:
   525 					*p = (Uint8)ch;
   530             {
   526 				}
   531                 Uint8 *p = (Uint8 *) dst;
   527 				++dst;
   532                 if (dstlen < 1) {
   528 				--dstlen;
   533                     return SDL_ICONV_E2BIG;
   529 			}
   534                 }
   530 			break;
   535                 if (ch > 0xFF) {
   531 		    case ENCODING_LATIN1:
   536                     *p = UNKNOWN_ASCII;
   532 			{
   537                 } else {
   533 				Uint8 *p = (Uint8 *)dst;
   538                     *p = (Uint8) ch;
   534 				if ( dstlen < 1 ) {
   539                 }
   535 					return SDL_ICONV_E2BIG;
   540                 ++dst;
   536 				}
   541                 --dstlen;
   537 				if ( ch > 0xFF ) {
   542             }
   538 					*p = UNKNOWN_ASCII;
   543             break;
   539 				} else {
   544         case ENCODING_UTF8:    /* RFC 3629 */
   540 					*p = (Uint8)ch;
   545             {
   541 				}
   546                 Uint8 *p = (Uint8 *) dst;
   542 				++dst;
   547                 if (ch > 0x10FFFF) {
   543 				--dstlen;
   548                     ch = UNKNOWN_UNICODE;
   544 			}
   549                 }
   545 			break;
   550                 if (ch <= 0x7F) {
   546 		    case ENCODING_UTF8: /* RFC 3629 */
   551                     if (dstlen < 1) {
   547 			{
   552                         return SDL_ICONV_E2BIG;
   548 				Uint8 *p = (Uint8 *)dst;
   553                     }
   549 				if ( ch > 0x10FFFF ) {
   554                     *p = (Uint8) ch;
   550 					ch = UNKNOWN_UNICODE;
   555                     ++dst;
   551 				}
   556                     --dstlen;
   552 				if ( ch <= 0x7F ) {
   557                 } else if (ch <= 0x7FF) {
   553 					if ( dstlen < 1 ) {
   558                     if (dstlen < 2) {
   554 						return SDL_ICONV_E2BIG;
   559                         return SDL_ICONV_E2BIG;
   555 					}
   560                     }
   556 					*p = (Uint8)ch;
   561                     p[0] = 0xC0 | (Uint8) ((ch >> 6) & 0x1F);
   557 					++dst;
   562                     p[1] = 0x80 | (Uint8) (ch & 0x3F);
   558 					--dstlen;
   563                     dst += 2;
   559 				} else if ( ch <= 0x7FF ) {
   564                     dstlen -= 2;
   560 					if ( dstlen < 2 ) {
   565                 } else if (ch <= 0xFFFF) {
   561 						return SDL_ICONV_E2BIG;
   566                     if (dstlen < 3) {
   562 					}
   567                         return SDL_ICONV_E2BIG;
   563 					p[0] = 0xC0 | (Uint8)((ch >> 6) & 0x1F);
   568                     }
   564 					p[1] = 0x80 | (Uint8)(ch & 0x3F);
   569                     p[0] = 0xE0 | (Uint8) ((ch >> 12) & 0x0F);
   565 					dst += 2;
   570                     p[1] = 0x80 | (Uint8) ((ch >> 6) & 0x3F);
   566 					dstlen -= 2;
   571                     p[2] = 0x80 | (Uint8) (ch & 0x3F);
   567 				} else if ( ch <= 0xFFFF ) {
   572                     dst += 3;
   568 					if ( dstlen < 3 ) {
   573                     dstlen -= 3;
   569 						return SDL_ICONV_E2BIG;
   574                 } else if (ch <= 0x1FFFFF) {
   570 					}
   575                     if (dstlen < 4) {
   571 					p[0] = 0xE0 | (Uint8)((ch >> 12) & 0x0F);
   576                         return SDL_ICONV_E2BIG;
   572 					p[1] = 0x80 | (Uint8)((ch >> 6) & 0x3F);
   577                     }
   573 					p[2] = 0x80 | (Uint8)(ch & 0x3F);
   578                     p[0] = 0xF0 | (Uint8) ((ch >> 18) & 0x07);
   574 					dst += 3;
   579                     p[1] = 0x80 | (Uint8) ((ch >> 12) & 0x3F);
   575 					dstlen -= 3;
   580                     p[2] = 0x80 | (Uint8) ((ch >> 6) & 0x3F);
   576 				} else if ( ch <= 0x1FFFFF ) {
   581                     p[3] = 0x80 | (Uint8) (ch & 0x3F);
   577 					if ( dstlen < 4 ) {
   582                     dst += 4;
   578 						return SDL_ICONV_E2BIG;
   583                     dstlen -= 4;
   579 					}
   584                 } else if (ch <= 0x3FFFFFF) {
   580 					p[0] = 0xF0 | (Uint8)((ch >> 18) & 0x07);
   585                     if (dstlen < 5) {
   581 					p[1] = 0x80 | (Uint8)((ch >> 12) & 0x3F);
   586                         return SDL_ICONV_E2BIG;
   582 					p[2] = 0x80 | (Uint8)((ch >> 6) & 0x3F);
   587                     }
   583 					p[3] = 0x80 | (Uint8)(ch & 0x3F);
   588                     p[0] = 0xF8 | (Uint8) ((ch >> 24) & 0x03);
   584 					dst += 4;
   589                     p[1] = 0x80 | (Uint8) ((ch >> 18) & 0x3F);
   585 					dstlen -= 4;
   590                     p[2] = 0x80 | (Uint8) ((ch >> 12) & 0x3F);
   586 				} else if ( ch <= 0x3FFFFFF ) {
   591                     p[3] = 0x80 | (Uint8) ((ch >> 6) & 0x3F);
   587 					if ( dstlen < 5 ) {
   592                     p[4] = 0x80 | (Uint8) (ch & 0x3F);
   588 						return SDL_ICONV_E2BIG;
   593                     dst += 5;
   589 					}
   594                     dstlen -= 5;
   590 					p[0] = 0xF8 | (Uint8)((ch >> 24) & 0x03);
   595                 } else {
   591 					p[1] = 0x80 | (Uint8)((ch >> 18) & 0x3F);
   596                     if (dstlen < 6) {
   592 					p[2] = 0x80 | (Uint8)((ch >> 12) & 0x3F);
   597                         return SDL_ICONV_E2BIG;
   593 					p[3] = 0x80 | (Uint8)((ch >> 6) & 0x3F);
   598                     }
   594 					p[4] = 0x80 | (Uint8)(ch & 0x3F);
   599                     p[0] = 0xFC | (Uint8) ((ch >> 30) & 0x01);
   595 					dst += 5;
   600                     p[1] = 0x80 | (Uint8) ((ch >> 24) & 0x3F);
   596 					dstlen -= 5;
   601                     p[2] = 0x80 | (Uint8) ((ch >> 18) & 0x3F);
   597 				} else {
   602                     p[3] = 0x80 | (Uint8) ((ch >> 12) & 0x3F);
   598 					if ( dstlen < 6 ) {
   603                     p[4] = 0x80 | (Uint8) ((ch >> 6) & 0x3F);
   599 						return SDL_ICONV_E2BIG;
   604                     p[5] = 0x80 | (Uint8) (ch & 0x3F);
   600 					}
   605                     dst += 6;
   601 					p[0] = 0xFC | (Uint8)((ch >> 30) & 0x01);
   606                     dstlen -= 6;
   602 					p[1] = 0x80 | (Uint8)((ch >> 24) & 0x3F);
   607                 }
   603 					p[2] = 0x80 | (Uint8)((ch >> 18) & 0x3F);
   608             }
   604 					p[3] = 0x80 | (Uint8)((ch >> 12) & 0x3F);
   609             break;
   605 					p[4] = 0x80 | (Uint8)((ch >> 6) & 0x3F);
   610         case ENCODING_UTF16BE: /* RFC 2781 */
   606 					p[5] = 0x80 | (Uint8)(ch & 0x3F);
   611             {
   607 					dst += 6;
   612                 Uint8 *p = (Uint8 *) dst;
   608 					dstlen -= 6;
   613                 if (ch > 0x10FFFF) {
   609 				}
   614                     ch = UNKNOWN_UNICODE;
   610 			}
   615                 }
   611 			break;
   616                 if (ch < 0x10000) {
   612 		    case ENCODING_UTF16BE: /* RFC 2781 */
   617                     if (dstlen < 2) {
   613 			{
   618                         return SDL_ICONV_E2BIG;
   614 				Uint8 *p = (Uint8 *)dst;
   619                     }
   615 				if ( ch > 0x10FFFF ) {
   620                     p[0] = (Uint8) (ch >> 8);
   616 					ch = UNKNOWN_UNICODE;
   621                     p[1] = (Uint8) ch;
   617 				}
   622                     dst += 2;
   618 				if ( ch < 0x10000 ) {
   623                     dstlen -= 2;
   619 					if ( dstlen < 2 ) {
   624                 } else {
   620 						return SDL_ICONV_E2BIG;
   625                     Uint16 W1, W2;
   621 					}
   626                     if (dstlen < 4) {
   622 					p[0] = (Uint8)(ch >> 8);
   627                         return SDL_ICONV_E2BIG;
   623 					p[1] = (Uint8)ch;
   628                     }
   624 					dst += 2;
   629                     ch = ch - 0x10000;
   625 					dstlen -= 2;
   630                     W1 = 0xD800 | (Uint16) ((ch >> 10) & 0x3FF);
   626 				} else {
   631                     W2 = 0xDC00 | (Uint16) (ch & 0x3FF);
   627 					Uint16 W1, W2;
   632                     p[0] = (Uint8) (W1 >> 8);
   628 					if ( dstlen < 4 ) {
   633                     p[1] = (Uint8) W1;
   629 						return SDL_ICONV_E2BIG;
   634                     p[2] = (Uint8) (W2 >> 8);
   630 					}
   635                     p[3] = (Uint8) W2;
   631 					ch = ch - 0x10000;
   636                     dst += 4;
   632 					W1 = 0xD800 | (Uint16)((ch >> 10) & 0x3FF);
   637                     dstlen -= 4;
   633 					W2 = 0xDC00 | (Uint16)(ch & 0x3FF);
   638                 }
   634 					p[0] = (Uint8)(W1 >> 8);
   639             }
   635 					p[1] = (Uint8)W1;
   640             break;
   636 					p[2] = (Uint8)(W2 >> 8);
   641         case ENCODING_UTF16LE: /* RFC 2781 */
   637 					p[3] = (Uint8)W2;
   642             {
   638 					dst += 4;
   643                 Uint8 *p = (Uint8 *) dst;
   639 					dstlen -= 4;
   644                 if (ch > 0x10FFFF) {
   640 				}
   645                     ch = UNKNOWN_UNICODE;
   641 			}
   646                 }
   642 			break;
   647                 if (ch < 0x10000) {
   643 		    case ENCODING_UTF16LE: /* RFC 2781 */
   648                     if (dstlen < 2) {
   644 			{
   649                         return SDL_ICONV_E2BIG;
   645 				Uint8 *p = (Uint8 *)dst;
   650                     }
   646 				if ( ch > 0x10FFFF ) {
   651                     p[1] = (Uint8) (ch >> 8);
   647 					ch = UNKNOWN_UNICODE;
   652                     p[0] = (Uint8) ch;
   648 				}
   653                     dst += 2;
   649 				if ( ch < 0x10000 ) {
   654                     dstlen -= 2;
   650 					if ( dstlen < 2 ) {
   655                 } else {
   651 						return SDL_ICONV_E2BIG;
   656                     Uint16 W1, W2;
   652 					}
   657                     if (dstlen < 4) {
   653 					p[1] = (Uint8)(ch >> 8);
   658                         return SDL_ICONV_E2BIG;
   654 					p[0] = (Uint8)ch;
   659                     }
   655 					dst += 2;
   660                     ch = ch - 0x10000;
   656 					dstlen -= 2;
   661                     W1 = 0xD800 | (Uint16) ((ch >> 10) & 0x3FF);
   657 				} else {
   662                     W2 = 0xDC00 | (Uint16) (ch & 0x3FF);
   658 					Uint16 W1, W2;
   663                     p[1] = (Uint8) (W1 >> 8);
   659 					if ( dstlen < 4 ) {
   664                     p[0] = (Uint8) W1;
   660 						return SDL_ICONV_E2BIG;
   665                     p[3] = (Uint8) (W2 >> 8);
   661 					}
   666                     p[2] = (Uint8) W2;
   662 					ch = ch - 0x10000;
   667                     dst += 4;
   663 					W1 = 0xD800 | (Uint16)((ch >> 10) & 0x3FF);
   668                     dstlen -= 4;
   664 					W2 = 0xDC00 | (Uint16)(ch & 0x3FF);
   669                 }
   665 					p[1] = (Uint8)(W1 >> 8);
   670             }
   666 					p[0] = (Uint8)W1;
   671             break;
   667 					p[3] = (Uint8)(W2 >> 8);
   672         case ENCODING_UTF32BE:
   668 					p[2] = (Uint8)W2;
   673             {
   669 					dst += 4;
   674                 Uint8 *p = (Uint8 *) dst;
   670 					dstlen -= 4;
   675                 if (ch > 0x10FFFF) {
   671 				}
   676                     ch = UNKNOWN_UNICODE;
   672 			}
   677                 }
   673 			break;
   678                 if (dstlen < 4) {
   674 		    case ENCODING_UTF32BE:
   679                     return SDL_ICONV_E2BIG;
   675 			{
   680                 }
   676 				Uint8 *p = (Uint8 *)dst;
   681                 p[0] = (Uint8) (ch >> 24);
   677 				if ( ch > 0x10FFFF ) {
   682                 p[1] = (Uint8) (ch >> 16);
   678 					ch = UNKNOWN_UNICODE;
   683                 p[2] = (Uint8) (ch >> 8);
   679 				}
   684                 p[3] = (Uint8) ch;
   680 				if ( dstlen < 4 ) {
   685                 dst += 4;
   681 					return SDL_ICONV_E2BIG;
   686                 dstlen -= 4;
   682 				}
   687             }
   683 				p[0] = (Uint8)(ch >> 24);
   688             break;
   684 				p[1] = (Uint8)(ch >> 16);
   689         case ENCODING_UTF32LE:
   685 				p[2] = (Uint8)(ch >> 8);
   690             {
   686 				p[3] = (Uint8)ch;
   691                 Uint8 *p = (Uint8 *) dst;
   687 				dst += 4;
   692                 if (ch > 0x10FFFF) {
   688 				dstlen -= 4;
   693                     ch = UNKNOWN_UNICODE;
   689 			}
   694                 }
   690 			break;
   695                 if (dstlen < 4) {
   691 		    case ENCODING_UTF32LE:
   696                     return SDL_ICONV_E2BIG;
   692 			{
   697                 }
   693 				Uint8 *p = (Uint8 *)dst;
   698                 p[3] = (Uint8) (ch >> 24);
   694 				if ( ch > 0x10FFFF ) {
   699                 p[2] = (Uint8) (ch >> 16);
   695 					ch = UNKNOWN_UNICODE;
   700                 p[1] = (Uint8) (ch >> 8);
   696 				}
   701                 p[0] = (Uint8) ch;
   697 				if ( dstlen < 4 ) {
   702                 dst += 4;
   698 					return SDL_ICONV_E2BIG;
   703                 dstlen -= 4;
   699 				}
   704             }
   700 				p[3] = (Uint8)(ch >> 24);
   705             break;
   701 				p[2] = (Uint8)(ch >> 16);
   706         case ENCODING_UCS2:
   702 				p[1] = (Uint8)(ch >> 8);
   707             {
   703 				p[0] = (Uint8)ch;
   708                 Uint16 *p = (Uint16 *) dst;
   704 				dst += 4;
   709                 if (ch > 0xFFFF) {
   705 				dstlen -= 4;
   710                     ch = UNKNOWN_UNICODE;
   706 			}
   711                 }
   707 			break;
   712                 if (dstlen < 2) {
   708 		    case ENCODING_UCS2:
   713                     return SDL_ICONV_E2BIG;
   709 			{
   714                 }
   710 				Uint16 *p = (Uint16 *)dst;
   715                 *p = (Uint16) ch;
   711 				if ( ch > 0xFFFF ) {
   716                 dst += 2;
   712 					ch = UNKNOWN_UNICODE;
   717                 dstlen -= 2;
   713 				}
   718             }
   714 				if ( dstlen < 2 ) {
   719             break;
   715 					return SDL_ICONV_E2BIG;
   720         case ENCODING_UCS4:
   716 				}
   721             {
   717 				*p = (Uint16)ch;
   722                 Uint32 *p = (Uint32 *) dst;
   718 				dst += 2;
   723                 if (ch > 0x7FFFFFFF) {
   719 				dstlen -= 2;
   724                     ch = UNKNOWN_UNICODE;
   720 			}
   725                 }
   721 			break;
   726                 if (dstlen < 4) {
   722 		    case ENCODING_UCS4:
   727                     return SDL_ICONV_E2BIG;
   723 			{
   728                 }
   724 				Uint32 *p = (Uint32 *)dst;
   729                 *p = ch;
   725 				if ( ch > 0x7FFFFFFF ) {
   730                 dst += 4;
   726 					ch = UNKNOWN_UNICODE;
   731                 dstlen -= 4;
   727 				}
   732             }
   728 				if ( dstlen < 4 ) {
   733             break;
   729 					return SDL_ICONV_E2BIG;
   734         }
   730 				}
   735 
   731 				*p = ch;
   736         /* Update state */
   732 				dst += 4;
   737         *inbuf = src;
   733 				dstlen -= 4;
   738         *inbytesleft = srclen;
   734 			}
   739         *outbuf = dst;
   735 			break;
   740         *outbytesleft = dstlen;
   736 		}
   741         ++total;
   737 
   742     }
   738 		/* Update state */
   743     return total;
   739 		*inbuf = src;
       
   740 		*inbytesleft = srclen;
       
   741 		*outbuf = dst;
       
   742 		*outbytesleft = dstlen;
       
   743 		++total;
       
   744 	}
       
   745 	return total;
       
   746 }
   744 }
   747 
   745 
   748 int SDL_iconv_close(SDL_iconv_t cd)
   746 int
       
   747 SDL_iconv_close (SDL_iconv_t cd)
   749 {
   748 {
   750 	if ( cd && cd != (SDL_iconv_t)-1 ) {
   749     if (cd && cd != (SDL_iconv_t) - 1) {
   751 		SDL_free(cd);
   750         SDL_free (cd);
   752 	}
   751     }
   753 	return 0;
   752     return 0;
   754 }
   753 }
   755 
   754 
   756 #endif /* !HAVE_ICONV */
   755 #endif /* !HAVE_ICONV */
   757 
   756 
   758 char *SDL_iconv_string(const char *tocode, const char *fromcode, char *inbuf, size_t inbytesleft)
   757 char *
       
   758 SDL_iconv_string (const char *tocode, const char *fromcode, char *inbuf,
       
   759                   size_t inbytesleft)
   759 {
   760 {
   760 	SDL_iconv_t cd;
   761     SDL_iconv_t cd;
   761 	char *string;
   762     char *string;
   762 	size_t stringsize;
   763     size_t stringsize;
   763 	char *outbuf;
   764     char *outbuf;
   764 	size_t outbytesleft;
   765     size_t outbytesleft;
   765 	size_t retCode = 0;
   766     size_t retCode = 0;
   766 
   767 
   767 	cd = SDL_iconv_open(tocode, fromcode);
   768     cd = SDL_iconv_open (tocode, fromcode);
   768 	if ( cd == (SDL_iconv_t)-1 ) {
   769     if (cd == (SDL_iconv_t) - 1) {
   769 		return NULL;
   770         return NULL;
   770 	}
   771     }
   771 
   772 
   772 	stringsize = inbytesleft > 4 ? inbytesleft : 4;
   773     stringsize = inbytesleft > 4 ? inbytesleft : 4;
   773 	string = SDL_malloc(stringsize);
   774     string = SDL_malloc (stringsize);
   774 	if ( !string ) {
   775     if (!string) {
   775 		SDL_iconv_close(cd);
   776         SDL_iconv_close (cd);
   776 		return NULL;
   777         return NULL;
   777 	}
   778     }
   778 	outbuf = string;
   779     outbuf = string;
   779 	outbytesleft = stringsize;
   780     outbytesleft = stringsize;
   780 	SDL_memset(outbuf, 0, 4);
   781     SDL_memset (outbuf, 0, 4);
   781 
   782 
   782 	while ( inbytesleft > 0 ) {
   783     while (inbytesleft > 0) {
   783 		retCode = SDL_iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
   784         retCode =
   784 		switch (retCode) {
   785             SDL_iconv (cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
   785 		    case SDL_ICONV_E2BIG:
   786         switch (retCode) {
   786 			{
   787         case SDL_ICONV_E2BIG:
   787 				char *oldstring = string;
   788             {
   788 				stringsize *= 2;
   789                 char *oldstring = string;
   789 				string = SDL_realloc(string, stringsize);
   790                 stringsize *= 2;
   790 				if ( !string ) {
   791                 string = SDL_realloc (string, stringsize);
   791 					SDL_iconv_close(cd);
   792                 if (!string) {
   792 					return NULL;
   793                     SDL_iconv_close (cd);
   793 				}
   794                     return NULL;
   794 				outbuf = string + (outbuf - oldstring);
   795                 }
   795 				outbytesleft = stringsize - (outbuf - string);
   796                 outbuf = string + (outbuf - oldstring);
   796 				SDL_memset(outbuf, 0, 4);
   797                 outbytesleft = stringsize - (outbuf - string);
   797 			}
   798                 SDL_memset (outbuf, 0, 4);
   798 			break;
   799             }
   799 		    case SDL_ICONV_EILSEQ:
   800             break;
   800 			/* Try skipping some input data - not perfect, but... */
   801         case SDL_ICONV_EILSEQ:
   801 			++inbuf;
   802             /* Try skipping some input data - not perfect, but... */
   802 			--inbytesleft;
   803             ++inbuf;
   803 			break;
   804             --inbytesleft;
   804 		    case SDL_ICONV_EINVAL:
   805             break;
   805 		    case SDL_ICONV_ERROR:
   806         case SDL_ICONV_EINVAL:
   806 			/* We can't continue... */
   807         case SDL_ICONV_ERROR:
   807 			inbytesleft = 0;
   808             /* We can't continue... */
   808 			break;
   809             inbytesleft = 0;
   809 		}
   810             break;
   810 	}
   811         }
   811 	SDL_iconv_close(cd);
   812     }
   812 
   813     SDL_iconv_close (cd);
   813 	return string;
   814 
       
   815     return string;
   814 }
   816 }
       
   817 
       
   818 /* vi: set ts=4 sw=4 expandtab: */