summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/luatexdir/luafontloader/fontforge/Unicode/ucharmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/luafontloader/fontforge/Unicode/ucharmap.c')
-rw-r--r--Build/source/texk/web2c/luatexdir/luafontloader/fontforge/Unicode/ucharmap.c675
1 files changed, 675 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/luatexdir/luafontloader/fontforge/Unicode/ucharmap.c b/Build/source/texk/web2c/luatexdir/luafontloader/fontforge/Unicode/ucharmap.c
new file mode 100644
index 00000000000..316234246a9
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/luafontloader/fontforge/Unicode/ucharmap.c
@@ -0,0 +1,675 @@
+/* Copyright (C) 2000-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.
+ */
+#ifdef VMS /* these three lines from Jacob Jansen, Open VMS port */
+# include <vms_jackets.h>
+#endif
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <gwwiconv.h>
+#include <stddef.h>
+#include <ustring.h>
+#include <utype.h>
+#include <charset.h>
+#include <chardata.h>
+
+int local_encoding = e_iso8859_1;
+#if HAVE_ICONV_H
+char *iconv_local_encoding_name = NULL;
+#endif
+
+static int bad_enc_warn = false;
+
+/* Does not handle conversions to Extended unix */
+
+unichar_t *encoding2u_strncpy(unichar_t *uto, const char *_from, int n, enum encoding cs) {
+ unichar_t *upt=uto;
+ const unichar_t *table;
+ int offset;
+ const unsigned char *from = (const unsigned char *) _from;
+
+ if ( cs<e_first2byte ) {
+ table = unicode_from_alphabets[cs];
+ if ( table==NULL ) {
+ while ( *from && n>0 ) {
+ *upt++ = *(unsigned char *) (from++);
+ --n;
+ }
+ } else {
+ while ( *from && n>0 ) {
+ *upt ++ = table[*(unsigned char *) (from++)];
+ --n;
+ }
+ }
+ } else if ( cs<e_unicode ) {
+ *uto = '\0';
+ switch ( cs ) {
+ default:
+ if ( !bad_enc_warn ) {
+ bad_enc_warn = true;
+ fprintf( stderr, "Unexpected encoding %d, I'll pretend it's latin1\n", cs );
+ }
+return( encoding2u_strncpy(uto,_from,n,e_iso8859_1));
+ case e_johab: case e_big5: case e_big5hkscs:
+ if ( cs==e_big5 ) {
+ offset = 0xa100;
+ table = unicode_from_big5;
+ } else if ( cs==e_big5hkscs ) {
+ offset = 0x8100;
+ table = unicode_from_big5hkscs;
+ } else {
+ offset = 0x8400;
+ table = unicode_from_johab;
+ }
+ while ( *from && n>0 ) {
+ if ( *from>=(offset>>8) && from[1]!='\0' ) {
+ *upt++ = table[ ((*from<<8) | from[1]) - offset ];
+ from += 2;
+ } else
+ *upt++ = *from++;
+ --n;
+ }
+ break;
+ case e_wansung:
+ while ( *from && n>0 ) {
+ if ( *from>=0xa1 && from[1]>=0xa1 ) {
+ *upt++ = unicode_from_ksc5601[ (*from-0xa1)*94+(from[1]-0xa1) ];
+ from += 2;
+ } else
+ *upt++ = *from++;
+ --n;
+ }
+ break;
+ case e_jisgb:
+ while ( *from && n>0 ) {
+ if ( *from>=0xa1 && from[1]>=0xa1 ) {
+ *upt++ = unicode_from_gb2312[ (*from-0xa1)*94+(from[1]-0xa1) ];
+ from += 2;
+ } else
+ *upt++ = *from++;
+ --n;
+ }
+ break;
+ case e_sjis:
+ while ( *from && n>0 ) {
+ if ( *from<127 || ( *from>=161 && *from<=223 )) {
+ *upt++ = unicode_from_jis201[*from++];
+ } else {
+ int ch1 = *from++;
+ int ch2 = *from++;
+ 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;
+ }
+ *upt++ = unicode_from_jis208[(ch1-0x21)*94+(ch2-0x21)];
+ }
+ --n;
+ }
+ break;
+ }
+ } else if ( cs==e_unicode ) {
+ unichar_t *ufrom = (unichar_t *) from;
+ while ( *ufrom && n>0 ) {
+ *upt++ = *ufrom++;
+ --n;
+ }
+ } else if ( cs==e_unicode_backwards ) {
+ unichar_t *ufrom = (unichar_t *) from;
+ while ( *ufrom && n>0 ) {
+ unichar_t ch = (*ufrom>>8)||((*ufrom&0xff)<<8);
+ *upt++ = ch;
+ ++ufrom;
+ --n;
+ }
+ } else if ( cs==e_utf8 ) {
+ while ( *from && n>0 ) {
+ if ( *from<=127 )
+ *upt = *from++;
+ else if ( *from<=0xdf ) {
+ if ( from[1]>=0x80 ) {
+ *upt = ((*from&0x1f)<<6) | (from[1]&0x3f);
+ from += 2;
+ } else {
+ ++from; /* Badly formed utf */
+ *upt = 0xfffd;
+ }
+ } else if ( *from<=0xef ) {
+ if ( from[1]>=0x80 && from[2]>=0x80 ) {
+ *upt = ((*from&0xf)<<12) | ((from[1]&0x3f)<<6) | (from[2]&0x3f);
+ from += 3;
+ } else {
+ ++from; /* Badly formed utf */
+ *upt = 0xfffd;
+ }
+ } else if ( n>2 ) {
+ if ( from[1]>=0x80 && from[2]>=0x80 && from[3]>=0x80 ) {
+ int w = ( ((*from&0x7)<<2) | ((from[1]&0x30)>>4) )-1;
+ *upt++ = 0xd800 | (w<<6) | ((from[1]&0xf)<<2) | ((from[2]&0x30)>>4);
+ *upt = 0xdc00 | ((from[2]&0xf)<<6) | (from[3]&0x3f);
+ from += 4;
+ } else {
+ ++from; /* Badly formed utf */
+ *upt = 0xfffd;
+ }
+ } else {
+ /* no space for surrogate */
+ from += 4;
+ }
+ ++upt;
+ }
+ } else {
+ if ( !bad_enc_warn ) {
+ bad_enc_warn = true;
+ fprintf( stderr, "Unexpected encoding %d, I'll pretend it's latin1\n", cs );
+ }
+return( encoding2u_strncpy(uto,_from,n,e_iso8859_1));
+ }
+
+ if ( n>0 )
+ *upt = '\0';
+
+return( uto );
+}
+
+char *u2encoding_strncpy(char *to, const unichar_t *ufrom, int n, enum encoding cs) {
+ char *pt = to;
+
+ /* we just ignore anything that doesn't fit in the encoding we look at */
+ if ( cs<e_first2byte ) {
+ struct charmap *table = NULL;
+ unsigned char *plane;
+ table = alphabets_from_unicode[cs];
+ if ( table==NULL ) { /* ASCII */
+ while ( *ufrom && n>0 ) {
+ int ch = *ufrom;
+ if ( ch<127 ) {
+ *pt++ = ch;
+ --n;
+ }
+ ++ufrom;
+ }
+ } else {
+ while ( *ufrom && n>0 ) {
+ int highch = *ufrom>>8, ch;
+ if ( highch>=table->first && highch<=table->last &&
+ (plane = table->table[highch])!=NULL &&
+ (ch=plane[*ufrom&0xff])!=0 ) {
+ *pt++ = ch;
+ --n;
+ }
+ ++ufrom;
+ }
+ }
+ if ( n>0 )
+ *pt = '\0';
+ } else if ( cs<e_unicode ) {
+ struct charmap2 *table;
+ unsigned short *plane;
+ unsigned char *plane1;
+
+ *to = '\0';
+ switch ( cs ) {
+ default:
+ if ( !bad_enc_warn ) {
+ bad_enc_warn = true;
+ fprintf( stderr, "Unexpected encoding %d, I'll pretend it's latin1\n", cs );
+ }
+return( u2encoding_strncpy(to,ufrom,n,e_iso8859_1));
+ case e_johab: case e_big5: case e_big5hkscs:
+ table = cs==e_big5 ? &big5_from_unicode :
+ cs==e_big5hkscs ? &big5hkscs_from_unicode :
+ &johab_from_unicode;
+ while ( *ufrom && n>0 ) {
+ int highch = *ufrom>>8, ch;
+ if ( *ufrom<0x80 ) {
+ *pt++ = *ufrom;
+ --n;
+ } else if ( highch>=table->first && highch<=table->last &&
+ (plane = table->table[highch-table->first])!=NULL &&
+ (ch=plane[*ufrom&0xff])!=0 ) {
+ *pt++ = ch>>8;
+ *pt++ = ch&0xff;
+ n -= 2;
+ }
+ ufrom ++;
+ }
+ break;
+ case e_wansung:
+ while ( *ufrom && n>0 ) {
+ int highch = *ufrom>>8, ch;
+ if ( *ufrom<0x80 ) {
+ *pt++ = *ufrom;
+ --n;
+ } else if ( highch>=ksc5601_from_unicode.first && highch<=ksc5601_from_unicode.last &&
+ (plane = ksc5601_from_unicode.table[highch-ksc5601_from_unicode.first])!=NULL &&
+ (ch=plane[*ufrom&0xff])!=0 ) {
+ *pt++ = (ch>>8) + 0x80;
+ *pt++ = (ch&0xff) + 0x80;
+ n -= 2;
+ }
+ ufrom ++;
+ }
+ break;
+ case e_jisgb:
+ while ( *ufrom && n>0 ) {
+ int highch = *ufrom>>8, ch;
+ if ( *ufrom<0x80 ) {
+ *pt++ = *ufrom;
+ --n;
+ } else if ( highch>=gb2312_from_unicode.first && highch<=gb2312_from_unicode.last &&
+ (plane = gb2312_from_unicode.table[highch-gb2312_from_unicode.first])!=NULL &&
+ (ch=plane[*ufrom&0xff])!=0 ) {
+ *pt++ = (ch>>8) + 0x80;
+ *pt++ = (ch&0xff) + 0x80;
+ n -= 2;
+ }
+ ufrom ++;
+ }
+ break;
+ case e_sjis:
+ while ( *ufrom && n>0 ) {
+ int highch = *ufrom>>8, ch;
+ if ( highch>=jis201_from_unicode.first && highch<=jis201_from_unicode.last &&
+ (plane1 = jis201_from_unicode.table[highch-jis201_from_unicode.first])!=NULL &&
+ (ch=plane1[*ufrom&0xff])!=0 ) {
+ *pt++ = ch;
+ --n;
+ } else if ( *ufrom<' ' ) { /* control chars */
+ *pt++ = *ufrom;
+ --n;
+ } 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[*ufrom&0xff])!=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;
+ *pt++ = ((j1+1)>>1)+ro;
+ *pt++ = j2+co;
+ n -= 2;
+ }
+ ++ufrom;
+ }
+ break;
+ }
+ if ( n>0 )
+ *pt = '\0';
+ } else if ( cs==e_unicode ) {
+ unichar_t *uto = (unichar_t *) to;
+ while ( *ufrom && n>1 ) {
+ *uto++ = *ufrom++;
+ n-=sizeof(unichar_t);
+ }
+ if ( n>1 )
+ *uto = '\0';
+ } else if ( cs==e_unicode_backwards ) {
+ unichar_t *uto = (unichar_t *) to;
+ while ( *ufrom && n>sizeof(unichar_t)-1 ) {
+#ifdef UNICHAR_16
+ unichar_t ch = (*ufrom>>8)|((*ufrom&0xff)<<8);
+#else
+ unichar_t ch = (*ufrom>>24)|((*ufrom>>8)&0xff00)|
+ ((*ufrom<<8)&0xff0000)|(*ufrom<<24);
+#endif
+ *uto++ = ch;
+ ++ufrom;
+ n-=sizeof(unichar_t);
+ }
+ if ( n>1 )
+ *uto = '\0';
+ } else if ( cs==e_utf8 ) {
+ while ( *ufrom ) {
+ if ( *ufrom<0x80 ) {
+ if ( n<=1 )
+ break;
+ *pt++ = *ufrom;
+ --n;
+ } else if ( *ufrom<0x800 ) {
+ if ( n<=2 )
+ break;
+ *pt++ = 0xc0 | (*ufrom>>6);
+ *pt++ = 0x80 | (*ufrom&0x3f);
+ n -= 2;
+ } else if ( *ufrom>=0xd800 && *ufrom<0xdc00 && ufrom[1]>=0xdc00 && ufrom[1]<0xe000 ) {
+ int u = ((*ufrom>>6)&0xf)+1, y = ((*ufrom&3)<<4) | ((ufrom[1]>>6)&0xf);
+ if ( n<=4 )
+ break;
+ *pt++ = 0xf0 | (u>>2);
+ *pt++ = 0x80 | ((u&3)<<4) | ((*ufrom>>2)&0xf);
+ *pt++ = 0x80 | y;
+ *pt++ = 0x80 | (ufrom[1]&0x3f);
+ n -= 4;
+ } else {
+ if ( n<=3 )
+ break;
+ *pt++ = 0xe0 | (*ufrom>>12);
+ *pt++ = 0x80 | ((*ufrom>>6)&0x3f);
+ *pt++ = 0x80 | (*ufrom&0x3f);
+ }
+ ++ufrom;
+ }
+ if ( n>1 )
+ *pt = '\0';
+ } else {
+ if ( !bad_enc_warn ) {
+ bad_enc_warn = true;
+ fprintf( stderr, "Unexpected encoding %d, I'll pretend it's latin1\n", cs );
+ }
+return( u2encoding_strncpy(to,ufrom,n,e_iso8859_1));
+ }
+
+return( to );
+}
+
+#if HAVE_ICONV_H
+static char *old_local_name=NULL;
+static iconv_t to_unicode=(iconv_t) (-1), from_unicode=(iconv_t) (-1);
+static iconv_t to_utf8=(iconv_t) (-1), from_utf8=(iconv_t) (-1);
+#ifdef UNICHAR_16
+static char *names[] = { "UCS-2-INTERNAL", "UCS-2", "UCS2", "ISO-10646/UCS2", "UNICODE", NULL };
+static char *namesle[] = { "UCS-2LE", "UNICODELITTLE", NULL };
+static char *namesbe[] = { "UCS-2BE", "UNICODEBIG", NULL };
+#else
+static char *names[] = { "UCS-4-INTERNAL", "UCS-4", "UCS4", "ISO-10646-UCS-4", "UTF-32", NULL };
+static char *namesle[] = { "UCS-4LE", "UTF-32LE", NULL };
+static char *namesbe[] = { "UCS-4BE", "UTF-32BE", NULL };
+#endif
+static char *unicode_name = NULL;
+static int byteswapped = false;
+
+static int BytesNormal(iconv_t latin1_2_unicode) {
+#ifdef UNICHAR_16
+ union {
+ short s;
+ char c[2];
+ } u[8];
+#else
+ union {
+ int s;
+ char c[4];
+ } u[8];
+#endif
+ char *from = "A", *to = &u[0].c[0];
+ size_t in_left = 1, out_left = sizeof(u);
+ memset(u,0,sizeof(u));
+ iconv( latin1_2_unicode, (iconv_arg2_t) &from, &in_left, &to, &out_left);
+ if ( u[0].s=='A' )
+return( true );
+
+return( false );
+}
+
+static int my_iconv_setup(void) {
+ char **testnames;
+ int i;
+ union {
+ short s;
+ char c[2];
+ } u;
+ iconv_t test;
+
+ if ( iconv_local_encoding_name==NULL ) {
+ if ( to_unicode!=(iconv_t) (-1) ) {
+ iconv_close(to_unicode);
+ iconv_close(from_unicode);
+ to_unicode = from_unicode = (iconv_t) (-1);
+ }
+return(false);
+ }
+ if ( old_local_name!=NULL && strcmp(old_local_name,iconv_local_encoding_name)==0 )
+return( to_unicode!=(iconv_t) (-1) );
+
+ free(old_local_name);
+ old_local_name = copy(iconv_local_encoding_name);
+ to_utf8 = iconv_open("UTF-8",iconv_local_encoding_name);
+ from_utf8 = iconv_open(iconv_local_encoding_name,"UTF-8");
+
+ if ( unicode_name==NULL ) {
+ u.c[0] = 0x1; u.c[1] = 0x2;
+ if ( u.s==0x201 ) { /* Little endian */
+ testnames = namesle;
+ } else {
+ testnames = namesbe;
+ }
+ for ( i=0; testnames[i]!=NULL; ++i ) {
+ test = iconv_open(testnames[i],"ISO-8859-1");
+ if ( test!=(iconv_t) -1 && test!=NULL ) {
+ iconv_close(test);
+ unicode_name = testnames[i];
+ break;
+ }
+ }
+ if ( unicode_name==NULL ) {
+ for ( i=0; names[i]!=NULL; ++i ) {
+ test = iconv_open(names[i],"ISO-8859-1");
+ if ( test!=(iconv_t) -1 && test!=NULL ) {
+ byteswapped = !BytesNormal(test);
+ iconv_close(test);
+ unicode_name = names[i];
+ break;
+ }
+ }
+ }
+ }
+ if ( unicode_name == NULL ) {
+ fprintf( stderr, "Could not find a name for Unicode which iconv could understand.\n" );
+return( false );
+ } else if ( byteswapped ) {
+ fprintf( stderr, "The only name for Unicode that iconv understood produced unexpected results.\nPerhaps %s was byte swapped.\n", unicode_name );
+return( false );
+ }
+
+ to_unicode = iconv_open(unicode_name,iconv_local_encoding_name);
+ from_unicode = iconv_open(iconv_local_encoding_name,unicode_name);
+ if ( to_unicode == (iconv_t) (-1) || to_utf8 == (iconv_t) (-1) ) {
+ fprintf( stderr, "iconv failed to understand encoding %s\n",
+ iconv_local_encoding_name);
+return( false );
+ }
+return( true );
+}
+#endif
+
+unichar_t *def2u_strncpy(unichar_t *uto, const char *from, int n) {
+#if HAVE_ICONV_H
+ if ( my_iconv_setup() ) {
+ size_t in_left = n, out_left = sizeof(unichar_t)*n;
+ char *cto = (char *) uto;
+ iconv(to_unicode, (iconv_arg2_t) &from, &in_left, &cto, &out_left);
+ if ( cto<((char *) uto)+2*n) *cto++ = '\0';
+ if ( cto<((char *) uto)+2*n) *cto++ = '\0';
+#ifndef UNICHAR_16
+ if ( cto<((char *) uto)+4*n) *cto++ = '\0';
+ if ( cto<((char *) uto)+4*n) *cto++ = '\0';
+#endif
+return( uto );
+ }
+#endif
+return( encoding2u_strncpy(uto,from,n,local_encoding));
+}
+
+char *u2def_strncpy(char *to, const unichar_t *ufrom, int n) {
+#if HAVE_ICONV_H
+ if ( my_iconv_setup() ) {
+ size_t in_left = sizeof(unichar_t)*n, out_left = n;
+ char *cfrom = (char *) ufrom, *cto=to;
+ iconv(from_unicode, (iconv_arg2_t) &cfrom, &in_left, &cto, &out_left);
+ if ( cto<to+n ) *cto++ = '\0';
+ if ( cto<to+n ) *cto++ = '\0';
+#ifndef UNICHAR_16
+ if ( cto<to+n ) *cto++ = '\0';
+ if ( cto<to+n ) *cto++ = '\0';
+#endif
+return( to );
+ }
+#endif
+return( u2encoding_strncpy(to,ufrom,n,local_encoding));
+}
+
+unichar_t *def2u_copy(const char *from) {
+ int len;
+ unichar_t *uto, *ret;
+
+ if ( from==NULL )
+return( NULL );
+ len = strlen(from);
+ uto = galloc((len+1)*sizeof(unichar_t));
+#if HAVE_ICONV_H
+ if ( my_iconv_setup() ) {
+ size_t in_left = len, out_left = sizeof(unichar_t)*len;
+ char *cto = (char *) uto;
+ iconv(to_unicode, (iconv_arg2_t) &from, &in_left, &cto, &out_left);
+ *cto++ = '\0';
+ *cto++ = '\0';
+#ifndef UNICHAR_16
+ *cto++ = '\0';
+ *cto++ = '\0';
+#endif
+return( uto );
+ }
+#endif
+ ret = encoding2u_strncpy(uto,from,len,local_encoding);
+ if ( ret==NULL )
+ free( uto );
+ else
+ uto[len] = '\0';
+return( ret );
+}
+
+char *u2def_copy(const unichar_t *ufrom) {
+ int len;
+ char *to, *ret;
+
+ if ( ufrom==NULL )
+return( NULL );
+ len = u_strlen(ufrom);
+#if HAVE_ICONV_H
+ if ( my_iconv_setup() ) {
+ size_t in_left = sizeof(unichar_t)*len, out_left = 3*len;
+ char *cfrom = (char *) ufrom, *cto;
+ cto = to = galloc(3*len+2);
+ iconv(from_unicode, (iconv_arg2_t) &cfrom, &in_left, &cto, &out_left);
+ *cto++ = '\0';
+ *cto++ = '\0';
+#ifndef UNICHAR_16
+ *cto++ = '\0';
+ *cto++ = '\0';
+#endif
+return( to );
+ }
+#endif
+ if ( local_encoding==e_utf8 )
+ len *= 3;
+ if ( local_encoding>=e_first2byte )
+ len *= 2;
+ to = galloc(len+sizeof(unichar_t));
+ ret = u2encoding_strncpy(to,ufrom,len,local_encoding);
+ if ( ret==NULL )
+ free( to );
+ else if ( local_encoding<e_first2byte )
+ to[len] = '\0';
+ else {
+ to[len] = '\0';
+ to[len+1] = '\0';
+ }
+return( ret );
+}
+
+char *def2utf8_copy(const char *from) {
+ int len;
+ char *ret;
+ unichar_t *temp, *uto;
+
+ if ( from==NULL )
+return( NULL );
+ len = strlen(from);
+#if HAVE_ICONV_H
+ if ( my_iconv_setup() ) {
+ size_t in_left = len, out_left = 3*(len+1);
+ char *cto = (char *) galloc(3*(len+1)), *cret = cto;
+ iconv(to_utf8, (iconv_arg2_t) &from, &in_left, &cto, &out_left);
+ *cto++ = '\0';
+ *cto++ = '\0';
+#ifndef UNICHAR_16
+ *cto++ = '\0';
+ *cto++ = '\0';
+#endif
+return( cret );
+ }
+#endif
+ uto = galloc(sizeof(unichar_t)*(len+1));
+ temp = encoding2u_strncpy(uto,from,len,local_encoding);
+ if ( temp==NULL ) {
+ free( uto );
+return( NULL );
+ }
+ uto[len] = '\0';
+ ret = u2utf8_copy(uto);
+ free(uto);
+return( ret );
+}
+
+char *utf82def_copy(const char *ufrom) {
+ int len;
+ char *ret;
+ unichar_t *u2from;
+
+ if ( ufrom==NULL )
+return( NULL );
+ len = strlen(ufrom);
+#if HAVE_ICONV_H
+ if ( my_iconv_setup() ) {
+ size_t in_left = len, out_left = 3*len;
+ char *cfrom = (char *) ufrom, *cto, *to;
+ cto = to = galloc(3*len+2);
+ iconv(from_utf8, (iconv_arg2_t) &cfrom, &in_left, &cto, &out_left);
+ *cto++ = '\0';
+ *cto++ = '\0';
+#ifndef UNICHAR_16
+ *cto++ = '\0';
+ *cto++ = '\0';
+#endif
+return( to );
+ }
+#endif
+ if ( local_encoding==e_utf8 )
+return( copy( ufrom )); /* Well that's easy */
+ u2from = utf82u_copy(ufrom);
+ ret = u2def_copy(u2from);
+ free(u2from);
+return( ret );
+}