summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/luatexdir/luafontloader/fontforge/Unicode/gwwiconv.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/luafontloader/fontforge/Unicode/gwwiconv.c')
-rw-r--r--Build/source/texk/web2c/luatexdir/luafontloader/fontforge/Unicode/gwwiconv.c1076
1 files changed, 1076 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/luatexdir/luafontloader/fontforge/Unicode/gwwiconv.c b/Build/source/texk/web2c/luatexdir/luafontloader/fontforge/Unicode/gwwiconv.c
new file mode 100644
index 00000000000..5576de5c18e
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/luafontloader/fontforge/Unicode/gwwiconv.c
@@ -0,0 +1,1076 @@
+/* Copyright (C) 2004-2008 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <basics.h>
+#include <gwwiconv.h>
+#include <charset.h>
+#include <chardata.h>
+#include <string.h>
+#include <ustring.h>
+#include <stdio.h>
+
+#ifdef LUA_FF_LIB
+extern void LUAUI_LogError(const char *fmt,...);
+#endif
+
+#ifndef HAVE_ICONV_H
+
+/* I have written an limited iconv which will convert either to or from unichar_t */
+/* (either UCS2 or UCS4) */
+/* it will not convert latin1 to latin2, but latin1->UCS2, UCS2->latin2 */
+/* it uses the encodings built into libgunicode for systems with no iconv */
+/* (ie. macs before 10.3, perhaps others) */
+
+struct gww_iconv_t {
+ enum encoding from;
+ enum encoding to;
+};
+
+enum extended_encoding { e_jisgbpk = e_encodingmax };
+
+static enum endian { end_big, end_little, end_unknown } endian = end_unknown;
+
+static void endian_detector(void) {
+ union { short s; char c[2]; } u;
+
+ u.s = 0x0102;
+ if ( u.c[0]==0x1 )
+ endian = end_big;
+ else
+ endian = end_little;
+}
+
+static enum encoding name_to_enc(const char *encname) {
+ struct { const char *name; enum encoding enc; } map[] = {
+ { "UCS-2-INTERNAL", e_unicode },
+ { "UCS2", e_unicode },
+ { "UCS-2", e_unicode },
+ { "UCS-2LE", e_unicode },
+ { "UCS-2BE", e_unicode },
+ { "UNICODELITTLE", e_unicode },
+ { "UNICODEBIG", e_unicode },
+ { "ISO-10646/UCS2", e_unicode },
+ { "ISO-10646/USC2", e_unicode }, /* Old typo */
+ { "UCS4", e_ucs4 },
+ { "UCS-4", e_ucs4 },
+ { "UCS-4LE", e_ucs4 },
+ { "UCS-4BE", e_ucs4 },
+ { "UCS-4-INTERNAL", e_ucs4 },
+ { "ISO-10646/UCS4", e_ucs4 },
+ { "iso8859-1", e_iso8859_1 },
+ { "iso8859-2", e_iso8859_2 },
+ { "iso8859-3", e_iso8859_3 },
+ { "iso8859-4", e_iso8859_4 },
+ { "iso8859-5", e_iso8859_5 },
+ { "iso8859-6", e_iso8859_6 },
+ { "iso8859-7", e_iso8859_7 },
+ { "iso8859-8", e_iso8859_8 },
+ { "iso8859-9", e_iso8859_9 },
+ { "iso8859-10", e_iso8859_10 },
+ { "iso8859-11", e_iso8859_11 },
+ { "iso8859-13", e_iso8859_13 },
+ { "iso8859-14", e_iso8859_14 },
+ { "iso8859-15", e_iso8859_15 },
+ { "iso-8859-1", e_iso8859_1 },
+ { "iso-8859-2", e_iso8859_2 },
+ { "iso-8859-3", e_iso8859_3 },
+ { "iso-8859-4", e_iso8859_4 },
+ { "iso-8859-5", e_iso8859_5 },
+ { "iso-8859-6", e_iso8859_6 },
+ { "iso-8859-7", e_iso8859_7 },
+ { "iso-8859-8", e_iso8859_8 },
+ { "iso-8859-9", e_iso8859_9 },
+ { "iso-8859-10", e_iso8859_10 },
+ { "iso-8859-11", e_iso8859_11 },
+ { "iso-8859-13", e_iso8859_13 },
+ { "iso-8859-14", e_iso8859_14 },
+ { "iso-8859-15", e_iso8859_15 },
+ { "koi8-r", e_koi8_r },
+ { "jis201", e_jis201 },
+ { "mac", e_mac },
+ { "Macintosh", e_mac },
+ { "MS-ANSI", e_win },
+ { "EUC-KR", e_wansung },
+ { "johab", e_johab },
+ { "ISO-2022-KR", e_jiskorean },
+ { "ISO-2022-CN", e_jisgb },
+ { "EUC-CN", e_jisgbpk },
+ { "big5", e_big5 },
+ { "big5hkscs", e_big5hkscs },
+ { "ISO-2022-JP", e_jis },
+ { "ISO-2022-JP-2", e_jis2 },
+ { "Sjis", e_sjis },
+ { "UTF-8", e_utf8 },
+ { "UTF8", e_utf8 },
+ { NULL }};
+ int i;
+
+ for ( i=0; map[i].name!=NULL; ++i )
+ if ( strmatch(map[i].name,encname)==0 )
+return( map[i].enc );
+
+return( -1 );
+}
+
+gww_iconv_t gww_iconv_open(const char *toenc,const char *fromenc) {
+ struct gww_iconv_t stuff, *ret;
+
+ if ( endian==end_unknown )
+ endian_detector();
+
+ stuff.from = name_to_enc(fromenc);
+ stuff.to = name_to_enc(toenc);
+ if ( stuff.from==(enum encoding) -1 || stuff.to==(enum encoding) -1 ) {
+ /*fprintf( stderr, "Unknown encoding\n" );*/
+return( (iconv_t)(-1) );
+#ifdef UNICHAR_16
+ } else if ( stuff.from!=e_unicode && stuff.to!=e_unicode ) {
+ fprintf( stderr, "Bad call to gww_iconv_open, neither arg is UCS2\n" );
+return( (iconv_t)(-1) );
+#else
+ } else if ( stuff.from!=e_ucs4 && stuff.to!=e_ucs4 ) {
+#ifdef LUA_FF_LIB
+ LUAUI_LogError("Bad call to gww_iconv_open, neither arg is UCS4 (%s->%s)", fromenc, toenc);
+#else
+ fprintf( stderr, "Bad call to gww_iconv_open, neither arg is UCS4\n" );
+#endif
+return( (iconv_t)(-1) );
+#endif
+ }
+
+ ret = galloc(sizeof(struct gww_iconv_t));
+ *ret = stuff;
+return( ret );
+}
+
+void gww_iconv_close( gww_iconv_t cd) {
+ free(cd);
+}
+
+size_t gww_iconv( gww_iconv_t _cd,
+ char **inbuf, size_t *inlen,
+ char **outbuf, size_t *outlen) {
+ struct gww_iconv_t *cd = _cd;
+ int char_cnt = 0;
+ unsigned char *plane;
+ int ch;
+
+ if ( inbuf==NULL || outbuf==NULL || inlen==NULL || outlen==NULL ||
+ *inbuf==NULL || *outbuf==NULL )
+return( 0 ); /* Legal, used to reset the state. As we don't do states, irrelevant */
+
+ if ( cd->from<0 || cd->from>e_encodingmax || cd->to<0 || cd->to>e_encodingmax ) {
+ fprintf( stderr, "Garbage encoding passed to gww_iconv()\n" );
+return( (size_t) -1 );
+ }
+
+ if ( cd->from==e_unicode ) {
+ if ( cd->to==e_unicode ) {
+ int min = *inlen < *outlen ? *inlen : *outlen;
+ min &= ~1;
+ memcpy(*inbuf,*outbuf,min);
+ char_cnt = min/sizeof(short);
+ *inbuf += min; *outbuf += min;
+ *inlen -= min; *outlen -= min;
+ if ( *inlen==1 && *outlen>0 )
+return( (size_t) -1 ); /* Incomplete multi-byte sequence */
+ } else if ( cd->to==e_ucs4 ) {
+ int min = *inlen/sizeof(short) < *outlen/sizeof(int32) ? *inlen/sizeof(short) : *outlen/sizeof(int32);
+ int highch, lowch;
+ if ( endian == end_little ) {
+ while ( *inlen>=sizeof(short) && *outlen>=sizeof(int32) ) {
+ highch = ((unsigned char *) *inbuf)[1], lowch = *(unsigned char *) *inbuf;
+ ((uint8 *) outbuf)[3] = 0; ((uint8 *) outbuf)[2] = 0;
+ ((uint8 *) outbuf)[1] = highch; ((uint8 *) outbuf)[0] = lowch;
+ outbuf += sizeof(int32); inbuf += sizeof(short);
+ *outlen -= sizeof(int32); *inlen -= sizeof(short);
+ }
+ } else {
+ while ( *inlen>=sizeof(short) && *outlen>=sizeof(int32) ) {
+ highch = ((unsigned char *) *inbuf)[0], lowch = ((unsigned char *) *inbuf)[1];
+ ((uint8 *) outbuf)[0] = 0; ((uint8 *) outbuf)[1] = 0;
+ ((uint8 *) outbuf)[2] = highch; ((uint8 *) outbuf)[3] = lowch;
+ outbuf += sizeof(int32); inbuf += sizeof(short);
+ *outlen -= sizeof(int32); *inlen -= sizeof(short);
+ }
+ }
+ char_cnt = min;
+ if ( *inlen==1 && *outlen>0 )
+return( (size_t) -1 ); /* Incomplete multi-byte sequence */
+ } else if ( cd->to<e_first2byte ) {
+ struct charmap *table = NULL;
+ table = alphabets_from_unicode[cd->to];
+ while ( *inlen>1 && *outlen>0 ) {
+ int highch, lowch;
+ if ( endian == end_little ) {
+ highch = ((unsigned char *) *inbuf)[1], lowch = *(unsigned char *) *inbuf;
+ } else {
+ highch = *(unsigned char *) *inbuf, lowch = ((unsigned char *) *inbuf)[1];
+ }
+ if ( highch>=table->first && highch<=table->last &&
+ (plane = table->table[highch])!=NULL &&
+ (ch=plane[lowch])!=0 ) {
+ *((*outbuf)++) = ch;
+ -- *outlen;
+ *inlen -= 2;
+ *inbuf += 2;
+ ++char_cnt;
+ } else
+return( (size_t) -1 );
+ }
+ } else if ( cd->to==e_johab || cd->to==e_big5 || cd->to==e_big5hkscs ) {
+ struct charmap2 *table = cd->to==e_johab ? &johab_from_unicode :
+ cd->to==e_big5 ? &big5_from_unicode :
+ &big5hkscs_from_unicode;
+ unsigned short *plane;
+ while ( *inlen>1 && *outlen>0 ) {
+ int highch, lowch;
+ if ( endian == end_little ) {
+ highch = ((unsigned char *) *inbuf)[1], lowch = *(unsigned char *) *inbuf;
+ } else {
+ highch = *(unsigned char *) *inbuf, lowch = ((unsigned char *) *inbuf)[1];
+ }
+ if ( highch==0 && lowch<=0x80 ) {
+ *((*outbuf)++) = highch;
+ --*outlen;
+ *inlen-=2;
+ *inbuf+=2;
+ ++char_cnt;
+ } else if ( *outlen==1 )
+return( (size_t) -1 );
+ else if ( highch>=table->first && highch<=table->last &&
+ (plane = table->table[highch])!=NULL &&
+ (ch=plane[lowch])!=0 ) {
+ *((*outbuf)++) = (ch>>8);
+ *((*outbuf)++) = (ch&0xff);
+ *outlen -= 2;
+ *inlen -= 2;
+ *inbuf += 2;
+ ++char_cnt;
+ } else
+return( (size_t) -1 );
+ }
+ } else if ( cd->to==e_wansung || cd->to==e_jisgbpk ) {
+ struct charmap2 *table = cd->to==e_wansung ? &ksc5601_from_unicode :
+ &gb2312_from_unicode;
+ unsigned short *plane;
+ while ( *inlen>1 && *outlen>0 ) {
+ int highch, lowch;
+ if ( endian == end_little ) {
+ highch = ((unsigned char *) *inbuf)[1], lowch = *(unsigned char *) *inbuf;
+ } else {
+ highch = *(unsigned char *) *inbuf, lowch = ((unsigned char *) *inbuf)[1];
+ }
+ if ( highch==0 && lowch<=0x80 ) {
+ *((*outbuf)++) = lowch;
+ --*outlen;
+ *inlen-=2;
+ *inbuf+=2;
+ ++char_cnt;
+ } else if ( *outlen==1 )
+return( (size_t) -1 );
+ else if ( highch>=table->first && highch<=table->last &&
+ (plane = table->table[highch])!=NULL &&
+ (ch=plane[lowch])!=0 ) {
+ *((*outbuf)++) = (ch>>8)+0x80;
+ *((*outbuf)++) = (ch&0xff)+0x80;
+ *outlen -= 2;
+ *inlen -= 2;
+ *inbuf += 2;
+ ++char_cnt;
+ } else
+return( (size_t) -1 );
+ }
+ } else if ( cd->to==e_sjis ) {
+ unsigned char *plane1;
+ unsigned short *plane;
+ while ( *inlen>1 && *outlen>0 ) {
+ int highch, lowch;
+ if ( endian == end_little ) {
+ highch = ((unsigned char *) *inbuf)[1], lowch = *(unsigned char *) *inbuf;
+ } else {
+ highch = *(unsigned char *) *inbuf, lowch = ((unsigned char *) *inbuf)[1];
+ }
+ if (( highch>=jis201_from_unicode.first && highch<=jis201_from_unicode.last &&
+ (plane1 = jis201_from_unicode.table[highch-jis201_from_unicode.first])!=NULL &&
+ (ch=plane1[lowch])!=0 ) ||
+ ( highch==0 && (ch=lowch)<' ' )) { /* control chars not mapped in jis201 */
+ *((*outbuf)++) = ch;
+ --*outlen;
+ *inlen-=2;
+ *inbuf+=2;
+ ++char_cnt;
+ } else if ( *outlen==1 )
+return( (size_t) -1 );
+ else if ( highch>=jis_from_unicode.first && highch<=jis_from_unicode.last &&
+ (plane = jis_from_unicode.table[highch-jis_from_unicode.first])!=NULL &&
+ (ch=plane[lowch])!=0 && ch<0x8000 ) { /* no jis212 */
+ int j1 = ch>>8, j2 = ch&0xff;
+ int ro = j1<95 ? 112 : 176;
+ int co = (j1&1) ? (j2>95?32:31) : 126;
+ *((*outbuf)++) = ((j1+1)>>1)+ro;
+ *((*outbuf)++) = j2+co;
+ *outlen -= 2;
+ *inlen -= 2;
+ *inbuf += 2;
+ ++char_cnt;
+ } else
+return( (size_t) -1 );
+ }
+ } else if ( cd->to==e_jis || cd->to==e_jis2 ||
+ cd->to==e_jiskorean || cd->to==e_jisgb ) {
+ struct charmap2 *table = cd->to==e_jisgb ? &gb2312_from_unicode :
+ cd->to==e_jiskorean ? &ksc5601_from_unicode :
+ &jis_from_unicode;
+ unsigned short *plane;
+ while ( *inlen>1 && *outlen>1 ) {
+ int highch, lowch;
+ if ( endian == end_little ) {
+ highch = ((unsigned char *) *inbuf)[1], lowch = *(unsigned char *) *inbuf;
+ } else {
+ highch = *(unsigned char *) *inbuf, lowch = ((unsigned char *) *inbuf)[1];
+ }
+ if ( highch>=table->first && highch<=table->last &&
+ (plane = table->table[highch])!=NULL &&
+ (ch=plane[lowch])!=0 ) {
+ if ( ch>=0x8000 ) {
+ if ( cd->to!=e_jis2 )
+return( (size_t) -1 );
+ ch -= 0x8000;
+ } else {
+ if ( cd->to==e_jis2 )
+return( (size_t) -1 );
+ }
+ *((*outbuf)++) = (ch>>8);
+ *((*outbuf)++) = (ch&0xff);
+ *outlen -= 2;
+ *inlen -= 2;
+ *inbuf += 2;
+ ++char_cnt;
+ } else
+return( (size_t) -1 );
+ }
+ } else if ( cd->to==e_utf8 ) {
+ while ( *inlen>1 && *outlen>0 ) {
+ unichar_t uch;
+ if ( endian == end_little ) {
+ uch = (((unsigned char *) *inbuf)[1]<<8) | (*((unsigned char *) *inbuf));
+ } else {
+ uch = (*((unsigned char *) *inbuf)<<8) | (((unsigned char *) *inbuf)[1]);
+ }
+ if ( uch < 0x80 ) {
+ *((*outbuf)++) = uch;
+ --*outlen;
+ } else if ( uch<0x800 ) {
+ if ( *outlen==1 )
+return( (size_t) -1 );
+ *((*outbuf)++) = 0xc0 | (uch>>6);
+ *((*outbuf)++) = 0x80 | (uch&0x3f);
+ *outlen-=2;
+ } else { /* I'm not dealing with */
+ if ( *outlen<=2 )
+return( (size_t) -1 );
+ *((*outbuf)++) = 0xe0 | (uch>>12);
+ *((*outbuf)++) = 0x80 | ((uch>>6)&0x3f);
+ *((*outbuf)++) = 0x80 | (uch&0x3f);
+ *outlen-=3;
+ }
+ *inbuf += 2;
+ *inlen -= 2;
+ ++char_cnt;
+ }
+ } else {
+ fprintf( stderr, "Unexpected encoding\n" );
+return( (size_t) -1 );
+ }
+ } else if ( cd->from==e_ucs4 ) {
+ if ( cd->to==e_unicode ) {
+ int min = *inlen/sizeof(int32) < *outlen/sizeof(int16) ? *inlen/sizeof(int32) : *outlen/sizeof(int16);
+ int highch, lowch;
+ if ( endian == end_little ) {
+ while ( *inlen>=sizeof(short) && *outlen>=sizeof(int32) ) {
+ highch = ((unsigned char *) *inbuf)[1], lowch = *(unsigned char *) *inbuf;
+ ((uint8 *) outbuf)[1] = highch; ((uint8 *) outbuf)[0] = lowch;
+ outbuf += sizeof(int16); inbuf += sizeof(int32);
+ *outlen -= sizeof(int16); *inlen -= sizeof(int32);
+ }
+ } else {
+ while ( *inlen>=sizeof(short) && *outlen>=sizeof(int32) ) {
+ highch = ((unsigned char *) *inbuf)[2], lowch = ((unsigned char *) *inbuf)[3];
+ ((uint8 *) outbuf)[0] = highch; ((uint8 *) outbuf)[1] = lowch;
+ outbuf += sizeof(int16); inbuf += sizeof(int32);
+ *outlen -= sizeof(int16); *inlen -= sizeof(int32);
+ }
+ }
+ char_cnt = min;
+ if ( *inlen>0 && *outlen>0 )
+return( (size_t) -1 ); /* Incomplete multi-byte sequence */
+ } else if ( cd->to<e_first2byte ) {
+ struct charmap *table = NULL;
+ table = alphabets_from_unicode[cd->to];
+ while ( *inlen>1 && *outlen>0 ) {
+ int highch, lowch;
+ if ( endian == end_little ) {
+ highch = ((unsigned char *) *inbuf)[1], lowch = *(unsigned char *) *inbuf;
+ } else {
+ highch = ((unsigned char *) *inbuf)[2], lowch = ((unsigned char *) *inbuf)[3];
+ }
+ if ( highch>=table->first && highch<=table->last &&
+ (plane = table->table[highch])!=NULL &&
+ (ch=plane[lowch])!=0 ) {
+ *((*outbuf)++) = ch;
+ -- *outlen;
+ *inlen -= 4;
+ *inbuf += 4;
+ ++char_cnt;
+ } else
+return( (size_t) -1 );
+ }
+ } else if ( cd->to==e_johab || cd->to==e_big5 || cd->to==e_big5hkscs ) {
+ struct charmap2 *table = cd->to==e_johab ? &johab_from_unicode :
+ cd->to==e_big5 ? &big5_from_unicode :
+ &big5hkscs_from_unicode;
+ unsigned short *plane;
+ while ( *inlen>1 && *outlen>0 ) {
+ int highch, lowch;
+ if ( endian == end_little ) {
+ highch = ((unsigned char *) *inbuf)[1], lowch = *(unsigned char *) *inbuf;
+ } else {
+ highch = ((unsigned char *) *inbuf)[2], lowch = ((unsigned char *) *inbuf)[3];
+ }
+ if ( highch==0 && lowch<=0x80 ) {
+ *((*outbuf)++) = highch;
+ --*outlen;
+ *inlen-=4;
+ *inbuf+=4;
+ ++char_cnt;
+ } else if ( *outlen==1 )
+return( (size_t) -1 );
+ else if ( highch>=table->first && highch<=table->last &&
+ (plane = table->table[highch])!=NULL &&
+ (ch=plane[lowch])!=0 ) {
+ *((*outbuf)++) = (ch>>8);
+ *((*outbuf)++) = (ch&0xff);
+ *outlen -= 2;
+ *inlen -= 4;
+ *inbuf += 4;
+ ++char_cnt;
+ } else
+return( (size_t) -1 );
+ }
+ } else if ( cd->to==e_wansung || cd->to==e_jisgbpk ) {
+ struct charmap2 *table = cd->to==e_wansung ? &ksc5601_from_unicode :
+ &gb2312_from_unicode;
+ unsigned short *plane;
+ while ( *inlen>1 && *outlen>0 ) {
+ int highch, lowch;
+ if ( endian == end_little ) {
+ highch = ((unsigned char *) *inbuf)[1], lowch = *(unsigned char *) *inbuf;
+ } else {
+ highch = ((unsigned char *) *inbuf)[2], lowch = ((unsigned char *) *inbuf)[3];
+ }
+ if ( highch==0 && lowch<=0x80 ) {
+ *((*outbuf)++) = lowch;
+ --*outlen;
+ *inlen-=4;
+ *inbuf+=4;
+ ++char_cnt;
+ } else if ( *outlen==1 )
+return( (size_t) -1 );
+ else if ( highch>=table->first && highch<=table->last &&
+ (plane = table->table[highch])!=NULL &&
+ (ch=plane[lowch])!=0 ) {
+ *((*outbuf)++) = (ch>>8)+0x80;
+ *((*outbuf)++) = (ch&0xff)+0x80;
+ *outlen -= 2;
+ *inlen -= 4;
+ *inbuf += 4;
+ ++char_cnt;
+ } else
+return( (size_t) -1 );
+ }
+ } else if ( cd->to==e_sjis ) {
+ unsigned char *plane1;
+ unsigned short *plane;
+ while ( *inlen>1 && *outlen>0 ) {
+ int highch, lowch;
+ if ( endian == end_little ) {
+ highch = ((unsigned char *) *inbuf)[1], lowch = *(unsigned char *) *inbuf;
+ } else {
+ highch = ((unsigned char *) *inbuf)[2], lowch = ((unsigned char *) *inbuf)[3];
+ }
+ if (( highch>=jis201_from_unicode.first && highch<=jis201_from_unicode.last &&
+ (plane1 = jis201_from_unicode.table[highch-jis201_from_unicode.first])!=NULL &&
+ (ch=plane1[lowch])!=0 ) ||
+ ( highch==0 && (ch=lowch)<' ' )) { /* control chars not mapped in jis201 */
+ *((*outbuf)++) = ch;
+ --*outlen;
+ *inlen-=4;
+ *inbuf+=4;
+ ++char_cnt;
+ } else if ( *outlen==1 )
+return( (size_t) -1 );
+ else if ( highch>=jis_from_unicode.first && highch<=jis_from_unicode.last &&
+ (plane = jis_from_unicode.table[highch-jis_from_unicode.first])!=NULL &&
+ (ch=plane[lowch])!=0 && ch<0x8000 ) { /* no jis212 */
+ int j1 = ch>>8, j2 = ch&0xff;
+ int ro = j1<95 ? 112 : 176;
+ int co = (j1&1) ? (j2>95?32:31) : 126;
+ *((*outbuf)++) = ((j1+1)>>1)+ro;
+ *((*outbuf)++) = j2+co;
+ *outlen -= 2;
+ *inlen -= 4;
+ *inbuf += 4;
+ ++char_cnt;
+ } else
+return( (size_t) -1 );
+ }
+ } else if ( cd->to==e_jis || cd->to==e_jis2 ||
+ cd->to==e_jiskorean || cd->to==e_jisgb ) {
+ struct charmap2 *table = cd->to==e_jisgb ? &gb2312_from_unicode :
+ cd->to==e_jiskorean ? &ksc5601_from_unicode :
+ &jis_from_unicode;
+ unsigned short *plane;
+ while ( *inlen>1 && *outlen>1 ) {
+ int highch, lowch;
+ if ( endian == end_little ) {
+ highch = ((unsigned char *) *inbuf)[1], lowch = *(unsigned char *) *inbuf;
+ } else {
+ highch = ((unsigned char *) *inbuf)[2], lowch = ((unsigned char *) *inbuf)[3];
+ }
+ if ( highch>=table->first && highch<=table->last &&
+ (plane = table->table[highch])!=NULL &&
+ (ch=plane[lowch])!=0 ) {
+ if ( ch>=0x8000 ) {
+ if ( cd->to!=e_jis2 )
+return( (size_t) -1 );
+ ch -= 0x8000;
+ } else {
+ if ( cd->to==e_jis2 )
+return( (size_t) -1 );
+ }
+ *((*outbuf)++) = (ch>>8);
+ *((*outbuf)++) = (ch&0xff);
+ *outlen -= 2;
+ *inlen -= 4;
+ *inbuf += 4;
+ ++char_cnt;
+ } else
+return( (size_t) -1 );
+ }
+ } else if ( cd->to==e_utf8 ) {
+ while ( *inlen>1 && *outlen>0 ) {
+ int uch;
+ if ( endian == end_little ) {
+ uch = (((unsigned char *) *inbuf)[3]<<24) |
+ (((unsigned char *) *inbuf)[2]<<16) |
+ (((unsigned char *) *inbuf)[1]<<8) |
+ (*((unsigned char *) *inbuf));
+ } else {
+ uch = (*((unsigned char *) *inbuf)<<24) |
+ (((unsigned char *) *inbuf)[1]<<16) |
+ (((unsigned char *) *inbuf)[2]<<8) |
+ (((unsigned char *) *inbuf)[3]);
+ }
+ if ( uch < 0x80 ) {
+ *((*outbuf)++) = uch;
+ --*outlen;
+ } else if ( uch<0x800 ) {
+ if ( *outlen==1 )
+return( (size_t) -1 );
+ *((*outbuf)++) = 0xc0 | (uch>>6);
+ *((*outbuf)++) = 0x80 | (uch&0x3f);
+ *outlen-=2;
+ } else if ( uch < 0x10000 ) {
+ if ( *outlen<=2 )
+return( (size_t) -1 );
+ *((*outbuf)++) = 0xe0 | (uch>>12);
+ *((*outbuf)++) = 0x80 | ((uch>>6)&0x3f);
+ *((*outbuf)++) = 0x80 | (uch&0x3f);
+ *outlen-=3;
+ } else {
+ uint32 val = uch-0x10000;
+ int u = ((val&0xf0000)>>16)+1, z=(val&0x0f000)>>12, y=(val&0x00fc0)>>6, x=val&0x0003f;
+ if ( *outlen<=3 )
+return( (size_t) -1 );
+ *(*outbuf)++ = 0xf0 | (u>>2);
+ *(*outbuf)++ = 0x80 | ((u&3)<<4) | z;
+ *(*outbuf)++ = 0x80 | y;
+ *(*outbuf)++ = 0x80 | x;
+ *outlen-=4;
+ }
+ *inbuf += 4;
+ *inlen -= 4;
+ ++char_cnt;
+ }
+ } else {
+ fprintf( stderr, "Unexpected encoding\n" );
+return( (size_t) -1 );
+ }
+ } else if ( cd->to==e_unicode ) {
+ const unichar_t *table;
+ if ( cd->from<e_first2byte ) {
+ table = unicode_from_alphabets[cd->from];
+ while ( *inlen>0 && *outlen>1 ) {
+ unichar_t ch = table[ *(unsigned char *) ((*inbuf)++)];
+ --*inlen;
+ if ( endian==end_little ) {
+ *((*outbuf)++) = ch&0xff;
+ *((*outbuf)++) = ch>>8;
+ } else {
+ *((*outbuf)++) = ch>>8;
+ *((*outbuf)++) = ch&0xff;
+ }
+ *outlen -= sizeof(unichar_t);
+ ++char_cnt;
+ }
+ } else if ( cd->from==e_jis || cd->from==e_jis2 ||
+ cd->from==e_jiskorean || cd->from==e_jisgb ) {
+ table = cd->from==e_jisgb ? unicode_from_gb2312 :
+ cd->from==e_jiskorean ? unicode_from_ksc5601 :
+ cd->from==e_jis ? unicode_from_jis208 :
+ unicode_from_jis212;
+ while ( *inlen>1 && *outlen>1 ) {
+ unsigned char *ipt = (unsigned char *) *inbuf;
+ int ch;
+ if ( *ipt<0x21 || *ipt>0x7e || ipt[1]<0x21 || ipt[1]>0x7e )
+return( (size_t) -1 );
+ ch = (*ipt-0x21)*94 + (ipt[1]-0x21);
+ ch = table[ch];
+ *inlen -= 2;
+ *inbuf = (char *) ipt+2;
+ if ( endian==end_little ) {
+ *((*outbuf)++) = ch&0xff;
+ *((*outbuf)++) = ch>>8;
+ } else {
+ *((*outbuf)++) = ch>>8;
+ *((*outbuf)++) = ch&0xff;
+ }
+ *outlen -= sizeof(unichar_t);
+ ++char_cnt;
+ }
+ if ( *inlen==1 && *outlen>0 )
+return( (size_t) -1 ); /* Incomplete multi-byte sequence */
+ } else if ( cd->from==e_wansung || cd->from==e_jisgbpk ) {
+ table = cd->from==e_jisgbpk ? unicode_from_gb2312 :
+ unicode_from_ksc5601 ;
+ while ( *inlen>0 && *outlen>1 ) {
+ unsigned char *ipt = (unsigned char *) *inbuf;
+ int ch;
+ if ( *ipt<0x7f ) {
+ ch = *ipt;
+ --*inlen;
+ *inbuf = (char *) ipt+1;
+ } else {
+ if ( *ipt<0xa1 || *ipt>0xfe || ipt[1]<0xa1 || ipt[1]>0xfe ||
+ *inlen==1 )
+return( (size_t) -1 );
+ ch = (*ipt-0xa1)*94 + (ipt[1]-0xa1);
+ ch = table[ch];
+ *inlen -= 2;;
+ *inbuf = (char *) ipt+2;
+ }
+ if ( endian==end_little ) {
+ *((*outbuf)++) = ch&0xff;
+ *((*outbuf)++) = ch>>8;
+ } else {
+ *((*outbuf)++) = ch>>8;
+ *((*outbuf)++) = ch&0xff;
+ }
+ *outlen -= sizeof(unichar_t);
+ ++char_cnt;
+ }
+ } else if ( cd->from==e_johab || cd->from==e_big5 || cd->from==e_big5hkscs ) {
+ int offset;
+ if ( cd->from==e_big5 ) {
+ offset = 0xa100;
+ table = unicode_from_big5;
+ } else if ( cd->from==e_big5hkscs ) {
+ offset = 0x8100;
+ table = unicode_from_big5hkscs;
+ } else {
+ offset = 0x8400;
+ table = unicode_from_johab;
+ }
+ while ( *inlen>0 && *outlen>1 ) {
+ unsigned char *ipt = (unsigned char *) *inbuf;
+ int ch;
+ if ( *ipt<0x7f ) {
+ ch = *ipt;
+ --*inlen;
+ *inbuf = (char *) ipt+1;
+ } else {
+ if ( *inlen==1 )
+return( (size_t) -1 );
+ ch = (*ipt<<8) | ipt[1];
+ if ( ch<offset )
+return( (size_t) -1 );
+ ch -= offset;
+ ch = table[ch];
+ *inlen -= 2;
+ *inbuf = (char *) ipt+2;
+ }
+ if ( endian==end_little ) {
+ *((*outbuf)++) = ch&0xff;
+ *((*outbuf)++) = ch>>8;
+ } else {
+ *((*outbuf)++) = ch>>8;
+ *((*outbuf)++) = ch&0xff;
+ }
+ *outlen -= sizeof(unichar_t);
+ ++char_cnt;
+ }
+ } else if ( cd->from==e_sjis ) {
+ while ( *inlen>0 && *outlen>1 ) {
+ unsigned char *ipt = (unsigned char *) *inbuf;
+ int ch1 = *ipt;
+ if ( ch1<127 || ( ch1>=161 && ch1<=223 )) {
+ ch = unicode_from_jis201[ch1];
+ *inbuf = (char *) ipt+1;
+ --*inlen;
+ } else if ( *inlen==1 )
+return( (size_t) -1 );
+ else {
+ int ch2 = ipt[1];
+ if ( ch1 >= 129 && ch1<= 159 )
+ ch1 -= 112;
+ else
+ ch1 -= 176;
+ ch1 <<= 1;
+ if ( ch2>=159 )
+ ch2-= 126;
+ else if ( ch2>127 ) {
+ --ch1;
+ ch2 -= 32;
+ } else {
+ --ch1;
+ ch2 -= 31;
+ }
+ if ( ch1-0x21>=94 || ch2-0x21>=94 )
+return( (size_t) -1 );
+ ch = unicode_from_jis208[(ch1-0x21)*94+(ch2-0x21)];
+ *inlen -= 2;
+ *inbuf = (char *) ipt+2;
+ }
+ if ( endian==end_little ) {
+ *((*outbuf)++) = ch&0xff;
+ *((*outbuf)++) = ch>>8;
+ } else {
+ *((*outbuf)++) = ch>>8;
+ *((*outbuf)++) = ch&0xff;
+ }
+ *outlen -= sizeof(unichar_t);
+ ++char_cnt;
+ }
+ } else if ( cd->from==e_utf8 ) {
+ while ( *inlen>0 && *outlen>sizeof(unichar_t) ) {
+ unsigned char *ipt = (unsigned char *) *inbuf;
+ int ch = *ipt;
+ if ( ch <= 127 ) {
+ *inbuf = (char *) ipt+1;
+ --*inlen;
+ } else if ( ch<=0xdf ) {
+ if ( *inlen<2 || ipt[1]<0x80 )
+return( (size_t) -1 );
+ ch = ((ch&0x1f)<<6) | (ipt[1] &0x3f);
+ *inlen -= 2;
+ *inbuf = (char *) ipt+2;
+ } else if ( ch<=0xef ) {
+ if ( *inlen<3 || ipt[1]<0x80 || ipt[2]<0x80 )
+return( (size_t) -1 );
+ ch = ((ch&0x1f)<<12) | ((ipt[1] &0x3f)<<6) | (ipt[2]&0x3f);
+ *inlen -= 3;
+ *inbuf = (char *) ipt+3;
+ } else {
+ int w;
+ if ( *inlen<4 || *outlen<4 || ipt[1]<0x80 || ipt[2]<0x80 || ipt[3]<0x80 )
+return( (size_t) -1 );
+ w = ( ((ch&0x7)<<2) | ((ipt[1]&0x30)>>4) )-1;
+ ch = 0xd800 | (w<<6) | ((ipt[1]&0xf)<<2) | ((ipt[2]&0x30)>>4);
+ if ( endian==end_little ) {
+ *((*outbuf)++) = ch&0xff;
+ *((*outbuf)++) = ch>>8;
+ } else {
+ *((*outbuf)++) = ch>>8;
+ *((*outbuf)++) = ch&0xff;
+ }
+ *outlen -= 2;
+ ch = 0xdc00 | ((ipt[2]&0xf)<<6) | (ipt[3]&0x3f);
+ }
+ if ( endian==end_little ) {
+ *((*outbuf)++) = ch&0xff;
+ *((*outbuf)++) = ch>>8;
+ } else {
+ *((*outbuf)++) = ch>>8;
+ *((*outbuf)++) = ch&0xff;
+ }
+ *outlen -= sizeof(unichar_t);
+ ++char_cnt;
+ }
+ } else {
+ fprintf( stderr, "Unexpected encoding\n" );
+return( (size_t) -1 );
+ }
+ } else if ( cd->to==e_ucs4 ) {
+ const unichar_t *table;
+ if ( cd->from<e_first2byte ) {
+ table = unicode_from_alphabets[cd->from];
+ while ( *inlen>0 && *outlen>1 ) {
+ unichar_t ch = table[ *(unsigned char *) ((*inbuf)++)];
+ --*inlen;
+ if ( endian==end_little ) {
+ *((*outbuf)++) = 0;
+ *((*outbuf)++) = 0;
+ *((*outbuf)++) = ch&0xff;
+ *((*outbuf)++) = ch>>8;
+ } else {
+ *((*outbuf)++) = ch>>8;
+ *((*outbuf)++) = ch&0xff;
+ *((*outbuf)++) = 0;
+ *((*outbuf)++) = 0;
+ }
+ *outlen -= sizeof(unichar_t);
+ ++char_cnt;
+ }
+ } else if ( cd->from==e_jis || cd->from==e_jis2 ||
+ cd->from==e_jiskorean || cd->from==e_jisgb ) {
+ table = cd->from==e_jisgb ? unicode_from_gb2312 :
+ cd->from==e_jiskorean ? unicode_from_ksc5601 :
+ cd->from==e_jis ? unicode_from_jis208 :
+ unicode_from_jis212;
+ while ( *inlen>1 && *outlen>1 ) {
+ unsigned char *ipt = (unsigned char *) *inbuf;
+ int ch;
+ if ( *ipt<0x21 || *ipt>0x7e || ipt[1]<0x21 || ipt[1]>0x7e )
+return( (size_t) -1 );
+ ch = (*ipt-0x21)*94 + (ipt[1]-0x21);
+ ch = table[ch];
+ *inlen -= 2;
+ *inbuf = (char *) ipt+2;
+ if ( endian==end_little ) {
+ *((*outbuf)++) = 0;
+ *((*outbuf)++) = 0;
+ *((*outbuf)++) = ch&0xff;
+ *((*outbuf)++) = ch>>8;
+ } else {
+ *((*outbuf)++) = ch>>8;
+ *((*outbuf)++) = ch&0xff;
+ *((*outbuf)++) = 0;
+ *((*outbuf)++) = 0;
+ }
+ *outlen -= sizeof(unichar_t);
+ ++char_cnt;
+ }
+ if ( *inlen==1 && *outlen>0 )
+return( (size_t) -1 ); /* Incomplete multi-byte sequence */
+ } else if ( cd->from==e_wansung || cd->from==e_jisgbpk ) {
+ table = cd->from==e_jisgbpk ? unicode_from_gb2312 :
+ unicode_from_ksc5601 ;
+ while ( *inlen>0 && *outlen>1 ) {
+ unsigned char *ipt = (unsigned char *) *inbuf;
+ int ch;
+ if ( *ipt<0x7f ) {
+ ch = *ipt;
+ --*inlen;
+ *inbuf = (char *) ipt+1;
+ } else {
+ if ( *ipt<0xa1 || *ipt>0xfe || ipt[1]<0xa1 || ipt[1]>0xfe ||
+ *inlen==1 )
+return( (size_t) -1 );
+ ch = (*ipt-0xa1)*94 + (ipt[1]-0xa1);
+ ch = table[ch];
+ *inlen -= 2;;
+ *inbuf = (char *) ipt+2;
+ }
+ if ( endian==end_little ) {
+ *((*outbuf)++) = 0;
+ *((*outbuf)++) = 0;
+ *((*outbuf)++) = ch&0xff;
+ *((*outbuf)++) = ch>>8;
+ } else {
+ *((*outbuf)++) = ch>>8;
+ *((*outbuf)++) = ch&0xff;
+ *((*outbuf)++) = 0;
+ *((*outbuf)++) = 0;
+ }
+ *outlen -= sizeof(unichar_t);
+ ++char_cnt;
+ }
+ } else if ( cd->from==e_johab || cd->from==e_big5 || cd->from==e_big5hkscs ) {
+ int offset;
+ if ( cd->from==e_big5 ) {
+ offset = 0xa100;
+ table = unicode_from_big5;
+ } else if ( cd->from==e_big5hkscs ) {
+ offset = 0x8100;
+ table = unicode_from_big5hkscs;
+ } else {
+ offset = 0x8400;
+ table = unicode_from_johab;
+ }
+ while ( *inlen>0 && *outlen>1 ) {
+ unsigned char *ipt = (unsigned char *) *inbuf;
+ int ch;
+ if ( *ipt<0x7f ) {
+ ch = *ipt;
+ --*inlen;
+ *inbuf = (char *) ipt+1;
+ } else {
+ if ( *inlen==1 )
+return( (size_t) -1 );
+ ch = (*ipt<<8) | ipt[1];
+ if ( ch<offset )
+return( (size_t) -1 );
+ ch -= offset;
+ ch = table[ch];
+ *inlen -= 2;
+ *inbuf = (char *) ipt+2;
+ }
+ if ( endian==end_little ) {
+ *((*outbuf)++) = 0;
+ *((*outbuf)++) = 0;
+ *((*outbuf)++) = ch&0xff;
+ *((*outbuf)++) = ch>>8;
+ } else {
+ *((*outbuf)++) = ch>>8;
+ *((*outbuf)++) = ch&0xff;
+ *((*outbuf)++) = 0;
+ *((*outbuf)++) = 0;
+ }
+ *outlen -= sizeof(unichar_t);
+ ++char_cnt;
+ }
+ } else if ( cd->from==e_sjis ) {
+ while ( *inlen>0 && *outlen>1 ) {
+ unsigned char *ipt = (unsigned char *) *inbuf;
+ int ch1 = *ipt;
+ if ( ch1<127 || ( ch1>=161 && ch1<=223 )) {
+ ch = unicode_from_jis201[ch1];
+ *inbuf = (char *) ipt+1;
+ --*inlen;
+ } else if ( *inlen==1 )
+return( (size_t) -1 );
+ else {
+ int ch2 = ipt[1];
+ if ( ch1 >= 129 && ch1<= 159 )
+ ch1 -= 112;
+ else
+ ch1 -= 176;
+ ch1 <<= 1;
+ if ( ch2>=159 )
+ ch2-= 126;
+ else if ( ch2>127 ) {
+ --ch1;
+ ch2 -= 32;
+ } else {
+ --ch1;
+ ch2 -= 31;
+ }
+ if ( ch1-0x21>=94 || ch2-0x21>=94 )
+return( (size_t) -1 );
+ ch = unicode_from_jis208[(ch1-0x21)*94+(ch2-0x21)];
+ *inlen -= 2;
+ *inbuf = (char *) ipt+2;
+ }
+ if ( endian==end_little ) {
+ *((*outbuf)++) = 0;
+ *((*outbuf)++) = 0;
+ *((*outbuf)++) = ch&0xff;
+ *((*outbuf)++) = ch>>8;
+ } else {
+ *((*outbuf)++) = ch>>8;
+ *((*outbuf)++) = ch&0xff;
+ *((*outbuf)++) = 0;
+ *((*outbuf)++) = 0;
+ }
+ *outlen -= sizeof(unichar_t);
+ ++char_cnt;
+ }
+ } else if ( cd->from==e_utf8 ) {
+ while ( *inlen>0 && *outlen>sizeof(unichar_t) ) {
+ unsigned char *ipt = (unsigned char *) *inbuf;
+ int ch = *ipt;
+ if ( ch <= 127 ) {
+ *inbuf = (char *) ipt+1;
+ --*inlen;
+ } else if ( ch<=0xdf ) {
+ if ( *inlen<2 || ipt[1]<0x80 )
+return( (size_t) -1 );
+ ch = ((ch&0x1f)<<6) | (ipt[1] &0x3f);
+ *inlen -= 2;
+ *inbuf = (char *) ipt+2;
+ } else if ( ch<=0xef ) {
+ if ( *inlen<3 || ipt[1]<0x80 || ipt[2]<0x80 )
+return( (size_t) -1 );
+ ch = ((ch&0x1f)<<12) | ((ipt[1] &0x3f)<<6) | (ipt[2]&0x3f);
+ *inlen -= 3;
+ *inbuf = (char *) ipt+3;
+ } else {
+ int w,w2;
+ w = ( ((*ipt&0x7)<<2) | ((ipt[1]&0x30)>>4) )-1;
+ w = (w<<6) | ((ipt[1]&0xf)<<2) | ((ipt[2]&0x30)>>4);
+ w2 = ((ipt[2]&0xf)<<6) | (ipt[3]&0x3f);
+ ch = w*0x400 + w2 + 0x10000;
+ *inbuf = (char *) ipt+4;
+ }
+ if ( endian==end_little ) {
+ *((*outbuf)++) = ch&0xff;
+ *((*outbuf)++) = ch>>8;
+ *((*outbuf)++) = ch>>16;
+ *((*outbuf)++) = ch>>24;
+ } else {
+ *((*outbuf)++) = ch>>24;
+ *((*outbuf)++) = ch>>16;
+ *((*outbuf)++) = ch>>8;
+ *((*outbuf)++) = ch&0xff;
+ }
+ *outlen -= sizeof(unichar_t);
+ ++char_cnt;
+ }
+ } else {
+ fprintf( stderr, "Unexpected encoding\n" );
+return( (size_t) -1 );
+ }
+ } else {
+ fprintf( stderr, "One of the two encodings must be UCS2 in gww_iconv()\n" );
+return( (size_t) -1 );
+ }
+
+ if ( *outlen>=1 ) {
+ **outbuf = '\0';
+ if ( *outlen>1 )
+ (*outbuf)[1] = '\0';
+ if ( cd->to==e_ucs4 && *outlen>3 ) {
+ (*outbuf)[2] = '\0';
+ (*outbuf)[3] = '\0';
+ }
+ }
+return( char_cnt );
+}
+#else
+static const int a_file_must_define_something=1;
+#endif /* HAVE_ICONV_H */