summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/luatexdir/unilib/ustring.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/unilib/ustring.c')
-rw-r--r--Build/source/texk/web2c/luatexdir/unilib/ustring.c965
1 files changed, 965 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/luatexdir/unilib/ustring.c b/Build/source/texk/web2c/luatexdir/unilib/ustring.c
new file mode 100644
index 00000000000..5ac9ce15c22
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/unilib/ustring.c
@@ -0,0 +1,965 @@
+/* Copyright (C) 2000-2012 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 "ustring.h"
+#include "utype.h"
+#include <stddef.h>
+
+long uc_strcmp(const unichar_t *str1,const char *str2) {
+ long ch1, ch2;
+ for (;;) {
+ ch1 = *str1++; ch2 = *(unsigned char *) str2++ ;
+ if ( ch1!=ch2 || ch1=='\0' )
+return(ch1-ch2);
+ }
+}
+
+long uc_strncmp(const unichar_t *str1,const char *str2,int n) {
+ long ch1, ch2;
+ while ( --n>=0 ) {
+ ch1 = *str1++; ch2 = *(unsigned char *) str2++ ;
+ if ( ch1!=ch2 || ch1=='\0' )
+return(ch1-ch2);
+ }
+return( 0 );
+}
+
+long uc_strmatch(const unichar_t *str1, const char *str2) {
+ long ch1, ch2;
+ for (;;) {
+ ch1 = *str1++; ch2 = *(unsigned char *) str2++ ;
+ ch1 = tolower(ch1);
+ ch2 = tolower(ch2);
+ if ( ch1!=ch2 || ch1=='\0' )
+return(ch1-ch2);
+ }
+}
+
+long uc_strnmatch(const unichar_t *str1, const char *str2, int len) {
+ long ch1, ch2;
+ for (;--len>=0;) {
+ ch1 = *str1++; ch2 = *(unsigned char *) str2++ ;
+ ch1 = tolower(ch1);
+ ch2 = tolower(ch2);
+ if ( ch1!=ch2 || ch1=='\0' || len<=0 )
+return(ch1-ch2);
+ }
+return( 0 );
+}
+
+long u_strnmatch(const unichar_t *str1, const unichar_t *str2, int len) {
+ long ch1, ch2;
+ for (;--len>=0;) {
+ ch1 = *str1++; ch2 = *str2++ ;
+ ch1 = tolower(ch1);
+ ch2 = tolower(ch2);
+ if ( ch1!=ch2 || ch1=='\0' || len<=0 )
+return(ch1-ch2);
+ }
+return( 0 );
+}
+
+long u_strcmp(const unichar_t *str1,const unichar_t *str2) {
+ long ch1, ch2;
+ for (;;) {
+ ch1 = *str1++; ch2 = *str2++ ;
+ if ( ch1!=ch2 || ch1=='\0' )
+return(ch1-ch2);
+ }
+}
+
+long u_strncmp(const unichar_t *str1,const unichar_t *str2,int n) {
+ long ch1, ch2;
+ while ( --n>=0 ) {
+ ch1 = *str1++; ch2 = *str2++ ;
+ if ( ch1!=ch2 || ch1=='\0' )
+return(ch1-ch2);
+ }
+return( 0 );
+}
+
+long u_strmatch(const unichar_t *str1, const unichar_t *str2) {
+ long ch1, ch2;
+ for (;;) {
+ ch1 = *str1++; ch2 = *str2++ ;
+ ch1 = tolower(ch1);
+ ch2 = tolower(ch2);
+ if ( ch1!=ch2 || ch1=='\0' )
+return(ch1-ch2);
+ }
+}
+
+void cu_strcpy(char *to, const unichar_t *from) {
+ register unichar_t ch;
+ while ( (ch = *from++) != '\0' )
+ *(to++) = ch;
+ *to = 0;
+}
+
+void uc_strcpy(unichar_t *to, const char *from) {
+ register unichar_t ch;
+ while ( (ch = *(unsigned char *) from++) != '\0' )
+ *(to++) = ch;
+ *to = 0;
+}
+
+void u_strcpy(unichar_t *to, const unichar_t *from) {
+ register unichar_t ch;
+ while ( (ch = *from++) != '\0' )
+ *(to++) = ch;
+ *to = 0;
+}
+
+void u_strncpy(register unichar_t *to, const unichar_t *from, int len) {
+ register unichar_t ch;
+ while ( (ch = *from++) != '\0' && --len>=0 )
+ *(to++) = ch;
+ *to = 0;
+}
+
+void cu_strncpy(register char *to, const unichar_t *from, int len) {
+ register unichar_t ch;
+ while ( (ch = *from++) != '\0' && --len>=0 )
+ *(to++) = ch;
+ *to = 0;
+}
+
+void uc_strncpy(register unichar_t *to, const char *from, int len) {
+ register unichar_t ch;
+ while ( (ch = *(unsigned char *) from++) != '\0' && --len>=0 )
+ *(to++) = ch;
+ *to = 0;
+}
+
+void uc_strcat(unichar_t *to, const char *from) {
+ uc_strcpy(to+u_strlen(to),from);
+}
+
+void uc_strncat(unichar_t *to, const char *from,int len) {
+ uc_strncpy(to+u_strlen(to),from,len);
+}
+
+void cu_strcat(char *to, const unichar_t *from) {
+ cu_strcpy(to+strlen(to),from);
+}
+
+void cu_strncat(char *to, const unichar_t *from, int len) {
+ cu_strncpy(to+strlen(to),from,len);
+}
+
+void u_strcat(unichar_t *to, const unichar_t *from) {
+ u_strcpy(to+u_strlen(to),from);
+}
+
+void u_strncat(unichar_t *to, const unichar_t *from, int len) {
+ u_strncpy(to+u_strlen(to),from,len);
+}
+
+int u_strlen(register const unichar_t *str) {
+ register int len = 0;
+
+ while ( *str++!='\0' )
+ ++len;
+return( len );
+}
+
+unichar_t *u_strchr(const unichar_t *str ,unichar_t ch) {
+ register unichar_t test;
+
+ while ( (test=*(str++))!='\0' )
+ if ( test==ch )
+return( (unichar_t *) str-1 );
+
+return( NULL );
+}
+
+unichar_t *u_strrchr(const unichar_t *str ,unichar_t ch) {
+ register unichar_t test, *last = NULL;
+
+ while ( (test=*(str++))!='\0' )
+ if ( test==ch )
+ last = (unichar_t *) str-1;
+
+return( last );
+}
+
+unichar_t *uc_strstr(const unichar_t *longer, const char *substr) {
+ long ch1, ch2;
+ const unichar_t *lpt, *str1; const char *str2;
+
+ for ( lpt=longer; *lpt!='\0'; ++lpt ) {
+ str1 = lpt; str2 = substr;
+ for (;;) {
+ ch1 = *str1++; ch2 = *(unsigned char *) str2++ ;
+ if ( ch2=='\0' )
+return((unichar_t *) lpt);
+ if ( ch1!=ch2 )
+ break;
+ }
+ }
+return( NULL );
+}
+
+unichar_t *u_strstr(const unichar_t *longer, const unichar_t *substr) {
+ long ch1, ch2;
+ const unichar_t *lpt, *str1, *str2;
+
+ for ( lpt=longer; *lpt!='\0'; ++lpt ) {
+ str1 = lpt; str2 = substr;
+ for (;;) {
+ ch1 = *str1++; ch2 = *str2++ ;
+ if ( ch2=='\0' )
+return((unichar_t *) lpt);
+ if ( ch1!=ch2 )
+ break;
+ }
+ }
+return( NULL );
+}
+
+unichar_t *uc_strstrmatch(const unichar_t *longer, const char *substr) {
+ long ch1, ch2;
+ const unichar_t *lpt, *str1; const unsigned char *str2;
+
+ for ( lpt=longer; *lpt!='\0'; ++lpt ) {
+ str1 = lpt; str2 = (unsigned char *) substr;
+ for (;;) {
+ ch1 = *str1++; ch2 = *str2++ ;
+ ch1 = tolower(ch1);
+ ch2 = tolower(ch2);
+ if ( ch2=='\0' )
+return((unichar_t *) lpt);
+ if ( ch1!=ch2 )
+ break;
+ }
+ }
+return( NULL );
+}
+
+unichar_t *u_strstrmatch(const unichar_t *longer, const unichar_t *substr) {
+ long ch1, ch2;
+ const unichar_t *lpt, *str1, *str2;
+
+ for ( lpt=longer; *lpt!='\0'; ++lpt ) {
+ str1 = lpt; str2 = substr;
+ for (;;) {
+ ch1 = *str1++; ch2 = *str2++ ;
+ ch1 = tolower(ch1);
+ ch2 = tolower(ch2);
+ if ( ch2=='\0' )
+return((unichar_t *) lpt);
+ if ( ch1!=ch2 )
+ break;
+ }
+ }
+return( NULL );
+}
+
+unichar_t *u_copyn(const unichar_t *pt, long n) {
+ unichar_t *res;
+#ifdef MEMORY_MASK
+ if ( n*sizeof(unichar_t)>=MEMORY_MASK )
+ n = MEMORY_MASK/sizeof(unichar_t)-1;
+#endif
+ res = (unichar_t *) xmalloc((n+1)*sizeof(unichar_t));
+ memcpy(res,pt,n*sizeof(unichar_t));
+ res[n]='\0';
+return(res);
+}
+
+unichar_t *u_copynallocm(const unichar_t *pt, long n, long m) {
+ unichar_t *res;
+#ifdef MEMORY_MASK
+ if ( n*sizeof(unichar_t)>=MEMORY_MASK )
+ n = MEMORY_MASK/sizeof(unichar_t)-1;
+#endif
+ res = xmalloc((m+1)*sizeof(unichar_t));
+ memcpy(res,pt,n*sizeof(unichar_t));
+ res[n]='\0';
+return(res);
+}
+
+unichar_t *u_copy(const unichar_t *pt) {
+ if(pt)
+return u_copyn(pt,u_strlen(pt));
+
+return((unichar_t *)0);
+}
+
+unichar_t *u_concat(const unichar_t *s1, const unichar_t *s2) {
+ long len1, len2;
+ unichar_t *pt;
+
+ if ( s1==NULL )
+return( u_copy( s2 ));
+ else if ( s2==NULL )
+return( u_copy( s1 ));
+ len1 = u_strlen(s1); len2 = u_strlen(s2);
+ pt = (unichar_t *) xmalloc((len1+len2+1)*sizeof(unichar_t));
+ u_strcpy(pt,s1);
+ u_strcpy(pt+len1,s2);
+return( pt );
+}
+
+unichar_t *uc_copyn(const char *pt,int len) {
+ unichar_t *res, *rpt;
+
+ if(!pt)
+return((unichar_t *)0);
+
+#ifdef MEMORY_MASK
+ if ( (len+1)*sizeof(unichar_t)>=MEMORY_MASK )
+ len = MEMORY_MASK/sizeof(unichar_t)-1;
+#endif
+ res = (unichar_t *) xmalloc((len+1)*sizeof(unichar_t));
+ for ( rpt=res; --len>=0 ; *rpt++ = *(unsigned char *) pt++ );
+ *rpt = '\0';
+return(res);
+}
+
+unichar_t *uc_copy(const char *pt) {
+ unichar_t *res, *rpt;
+ int n;
+
+ if(!pt)
+return((unichar_t *)0);
+
+ n = strlen(pt);
+#ifdef MEMORY_MASK
+ if ( (n+1)*sizeof(unichar_t)>=MEMORY_MASK )
+ n = MEMORY_MASK/sizeof(unichar_t)-1;
+#endif
+ res = (unichar_t *) xmalloc((n+1)*sizeof(unichar_t));
+ for ( rpt=res; --n>=0 ; *rpt++ = *(unsigned char *) pt++ );
+ *rpt = '\0';
+return(res);
+}
+
+char *cu_copyn(const unichar_t *pt,int len) {
+ char *res, *rpt;
+
+ if(!pt)
+return(NULL);
+
+#ifdef MEMORY_MASK
+ if ( (len+1)>=MEMORY_MASK )
+ len = MEMORY_MASK-1;
+#endif
+ res = (char *) xmalloc(len+1);
+ for ( rpt=res; --len>=0 ; *rpt++ = *pt++ );
+ *rpt = '\0';
+return(res);
+}
+
+char *cu_copy(const unichar_t *pt) {
+ char *res, *rpt;
+ int n;
+
+ if(!pt)
+return((char *)0);
+
+ n = u_strlen(pt);
+#ifdef MEMORY_MASK
+ if ( (n+1)>=MEMORY_MASK )
+ n = MEMORY_MASK/sizeof(unichar_t)-1;
+#endif
+ res = (char *) xmalloc(n+1);
+ for ( rpt=res; --n>=0 ; *rpt++ = *pt++ );
+ *rpt = '\0';
+return(res);
+}
+
+double u_strtod(const unichar_t *str, unichar_t **ptr) {
+ char buf[60], *pt, *ret;
+ const unichar_t *upt;
+ double val;
+ extern double strtod(); /* Please don't delete this, not all of us have good ansi headers */
+
+ for ( upt=str, pt=buf; *upt<128 && *upt!='\0' && pt-buf<sizeof(buf)-1; )
+ *pt++ = *upt++;
+ *pt = '\0';
+ val = strtod(buf,&ret);
+ if ( ptr!=NULL ) {
+ if ( pt==ret )
+ *ptr = (unichar_t *) upt;
+ else
+ *ptr = (unichar_t *) (str + (ret-buf));
+ }
+return( val );
+}
+
+long u_strtol(const unichar_t *str, unichar_t **ptr, int base) {
+ char buf[60], *pt, *ret;
+ const unichar_t *upt;
+ long val;
+ extern long strtol(); /* Please don't delete this, not all of us have good ansi headers */
+
+ for ( upt=str, pt=buf; *upt<128 && *upt!='\0' && pt<buf+sizeof(buf)-1; )
+ *pt++ = *upt++;
+ *pt = '\0';
+ val = strtol(buf,&ret,base);
+ if ( ptr!=NULL ) {
+ if ( pt==ret )
+ *ptr = (unichar_t *) upt;
+ else
+ *ptr = (unichar_t *) (str + (ret-buf));
+ }
+return( val );
+}
+
+unsigned long u_strtoul(const unichar_t *str, unichar_t **ptr, int base) {
+ char buf[60], *pt, *ret;
+ const unichar_t *upt;
+ unsigned long val;
+
+ for ( upt=str, pt=buf; *upt<128 && *upt!='\0' && pt<buf+sizeof(buf)-1; )
+ *pt++ = *upt++;
+ *pt = '\0';
+ val = strtoul(buf,&ret,base);
+ if ( ptr!=NULL ) {
+ if ( pt==ret )
+ *ptr = (unichar_t *) upt;
+ else
+ *ptr = (unichar_t *) (str + (ret-buf));
+ }
+return( val );
+}
+
+unichar_t *cu_strstartmatch(const char *key,const unichar_t *str) {
+ if ( key && str ) {
+ while( *key ) {
+ if(tolower(*key) != tolower(*str))
+return 0;
+ key++;
+ str++;
+ }
+ }
+return (unichar_t *)str;
+}
+
+unichar_t *u_strstartmatch(const unichar_t *initial, const unichar_t *full) {
+ int ch1, ch2;
+ for (;;) {
+ ch1 = *initial++; ch2 = *full++ ;
+ if ( ch1=='\0' )
+return( (unichar_t *) full );
+ ch1 = tolower(ch1);
+ ch2 = tolower(ch2);
+ if ( ch1!=ch2 || ch1=='\0' )
+return(NULL);
+ }
+}
+
+char *u_to_c(const unichar_t *ubuf) {
+ static char buf[400];
+ cu_strncpy(buf,ubuf,sizeof(buf));
+return( buf );
+}
+
+unichar_t *c_to_u(const char *buf) {
+ static unichar_t ubuf[400];
+ uc_strncpy(ubuf,buf,sizeof(ubuf));
+return( ubuf );
+}
+
+unichar_t *utf82u_strncpy(unichar_t *ubuf,const char *utf8buf,int len) {
+ unichar_t *upt=ubuf, *uend=ubuf+len-1;
+ const uint8 *pt = (const uint8 *) utf8buf, *end = pt+strlen(utf8buf);
+ int w, w2;
+
+ while ( pt<end && *pt!='\0' && upt<uend ) {
+ if ( *pt<=127 )
+ *upt = *pt++;
+ else if ( *pt<=0xdf ) {
+ *upt = ((*pt&0x1f)<<6) | (pt[1]&0x3f);
+ pt += 2;
+ } else if ( *pt<=0xef ) {
+ *upt = ((*pt&0xf)<<12) | ((pt[1]&0x3f)<<6) | (pt[2]&0x3f);
+ pt += 3;
+ } else {
+ w = ( ((*pt&0x7)<<2) | ((pt[1]&0x30)>>4) )-1;
+ w = (w<<6) | ((pt[1]&0xf)<<2) | ((pt[2]&0x30)>>4);
+ w2 = ((pt[2]&0xf)<<6) | (pt[3]&0x3f);
+ *upt = w*0x400 + w2 + 0x10000;
+ pt += 4;
+ }
+ ++upt;
+ }
+ *upt = '\0';
+return( ubuf );
+}
+
+unichar_t *utf82u_strcpy(unichar_t *ubuf,const char *utf8buf) {
+return( utf82u_strncpy(ubuf,utf8buf,strlen(utf8buf)+1));
+}
+
+unichar_t *utf82u_copyn(const char *utf8buf,int len) {
+ unichar_t *ubuf = (unichar_t *) xmalloc((len+1)*sizeof(unichar_t));
+return( utf82u_strncpy(ubuf,utf8buf,len+1));
+}
+
+unichar_t *utf82u_copy(const char *utf8buf) {
+ int len;
+ unichar_t *ubuf;
+
+ if ( utf8buf==NULL )
+return( NULL );
+
+ len = strlen(utf8buf);
+ ubuf = (unichar_t *) xmalloc((len+1)*sizeof(unichar_t));
+return( utf82u_strncpy(ubuf,utf8buf,len+1));
+}
+
+void utf82u_strcat(unichar_t *to,const char *from) {
+ utf82u_strcpy(to+u_strlen(to),from);
+}
+
+char *u2utf8_strcpy(char *utf8buf,const unichar_t *ubuf) {
+ char *pt = utf8buf;
+
+ while ( *ubuf ) {
+ if ( *ubuf<0x80 )
+ *pt++ = *ubuf;
+ else if ( *ubuf<0x800 ) {
+ *pt++ = 0xc0 | (*ubuf>>6);
+ *pt++ = 0x80 | (*ubuf&0x3f);
+ } else if ( *ubuf < 0x10000 ) {
+ *pt++ = 0xe0 | (*ubuf>>12);
+ *pt++ = 0x80 | ((*ubuf>>6)&0x3f);
+ *pt++ = 0x80 | (*ubuf&0x3f);
+ } else {
+ uint32 val = *ubuf-0x10000;
+ int u = ((val&0xf0000)>>16)+1, z=(val&0x0f000)>>12, y=(val&0x00fc0)>>6, x=val&0x0003f;
+ *pt++ = 0xf0 | (u>>2);
+ *pt++ = 0x80 | ((u&3)<<4) | z;
+ *pt++ = 0x80 | y;
+ *pt++ = 0x80 | x;
+ }
+ ++ubuf;
+ }
+ *pt = '\0';
+return( utf8buf );
+}
+
+char *utf8_strchr(const char *str, int search) {
+ int ch;
+ const char *old = str;
+
+ while ( (ch = utf8_ildb(&str))!=0 ) {
+ if ( ch==search )
+return( (char *) old );
+ old = str;
+ }
+return( NULL );
+}
+
+char *latin1_2_utf8_strcpy(char *utf8buf,const char *lbuf) {
+ char *pt = utf8buf;
+ const unsigned char *lpt = (const unsigned char *) lbuf;
+
+ while ( *lpt ) {
+ if ( *lpt<0x80 )
+ *pt++ = *lpt;
+ else {
+ *pt++ = 0xc0 | (*lpt>>6);
+ *pt++ = 0x80 | (*lpt&0x3f);
+ }
+ ++lpt;
+ }
+ *pt = '\0';
+return( utf8buf );
+}
+
+char *latin1_2_utf8_copy(const char *lbuf) {
+ int len;
+ char *utf8buf;
+
+ if ( lbuf==NULL )
+return( NULL );
+
+ len = strlen(lbuf);
+ utf8buf = (char *) xmalloc(2*len+1);
+return( latin1_2_utf8_strcpy(utf8buf,lbuf));
+}
+
+char *utf8_2_latin1_copy(const char *utf8buf) {
+ int len;
+ int ch;
+ char *lbuf, *pt; const char *upt;
+
+ if ( utf8buf==NULL )
+return( NULL );
+
+ len = strlen(utf8buf);
+ pt = lbuf = (char *) xmalloc(len+1);
+ for ( upt=utf8buf; (ch=utf8_ildb(&upt))!='\0'; )
+ if ( ch>=0xff )
+ *pt++ = '?';
+ else
+ *pt++ = ch;
+ *pt = '\0';
+return( lbuf );
+}
+
+char *u2utf8_copy(const unichar_t *ubuf) {
+ int len;
+ char *utf8buf;
+
+ if ( ubuf==NULL )
+return( NULL );
+
+ len = u_strlen(ubuf);
+ utf8buf = (char *) xmalloc((len+1)*4);
+return( u2utf8_strcpy(utf8buf,ubuf));
+}
+
+char *u2utf8_copyn(const unichar_t *ubuf,int len) {
+ int i;
+ char *utf8buf, *pt;
+
+ if ( ubuf==NULL )
+return( NULL );
+
+ utf8buf = pt = (char *) xmalloc((len+1)*4);
+ for ( i=0; i<len && *ubuf!='\0'; ++i )
+ pt = utf8_idpb(pt, *ubuf++);
+ *pt = '\0';
+return( utf8buf );
+}
+
+int32 utf8_ildb(const char **_text) {
+ int32 val= -1;
+ int ch;
+ const uint8 *text = (const uint8 *) *_text;
+ /* Increment and load character */
+
+ if ( (ch = *text++)<0x80 ) {
+ val = ch;
+ } else if ( ch<=0xbf ) {
+ /* error */
+ } else if ( ch<=0xdf ) {
+ if ( *text>=0x80 && *text<0xc0 )
+ val = ((ch&0x1f)<<6) | (*text++&0x3f);
+ } else if ( ch<=0xef ) {
+ if ( *text>=0x80 && *text<0xc0 && text[1]>=0x80 && text[1]<0xc0 ) {
+ val = ((ch&0xf)<<12) | ((text[0]&0x3f)<<6) | (text[1]&0x3f);
+ text += 2;
+ }
+ } else {
+ int w = ( ((ch&0x7)<<2) | ((text[0]&0x30)>>4) )-1, w2;
+ w = (w<<6) | ((text[0]&0xf)<<2) | ((text[1]&0x30)>>4);
+ w2 = ((text[1]&0xf)<<6) | (text[2]&0x3f);
+ val = w*0x400 + w2 + 0x10000;
+ if ( *text<0x80 || text[1]<0x80 || text[2]<0x80 ||
+ *text>=0xc0 || text[1]>=0xc0 || text[2]>=0xc0 )
+ val = -1;
+ else
+ text += 3;
+ }
+ *_text = (const char *) text;
+return( val );
+}
+
+char *utf8_idpb(char *utf8_text,uint32 ch) {
+ /* Increment and deposit character */
+ if ( ch>=17*65536 )
+return( utf8_text );
+
+ if ( ch<=127 )
+ *utf8_text++ = ch;
+ else if ( ch<=0x7ff ) {
+ *utf8_text++ = 0xc0 | (ch>>6);
+ *utf8_text++ = 0x80 | (ch&0x3f);
+ } else if ( ch<=0xffff ) {
+ *utf8_text++ = 0xe0 | (ch>>12);
+ *utf8_text++ = 0x80 | ((ch>>6)&0x3f);
+ *utf8_text++ = 0x80 | (ch&0x3f);
+ } else {
+ uint32 val = ch-0x10000;
+ int u = ((val&0xf0000)>>16)+1, z=(val&0x0f000)>>12, y=(val&0x00fc0)>>6, x=val&0x0003f;
+ *utf8_text++ = 0xf0 | (u>>2);
+ *utf8_text++ = 0x80 | ((u&3)<<4) | z;
+ *utf8_text++ = 0x80 | y;
+ *utf8_text++ = 0x80 | x;
+ }
+return( utf8_text );
+}
+
+
+char *utf8_ib(char *utf8_text) {
+ int ch;
+
+ /* Increment character */
+ if ( (ch = *utf8_text)=='\0' )
+return( utf8_text );
+ else if ( ch<=127 )
+return( utf8_text+1 );
+ else if ( ch<0xe0 )
+return( utf8_text+2 );
+ else if ( ch<0xf0 )
+return( utf8_text+3 );
+ else
+return( utf8_text+4 );
+}
+
+int utf8_valid(const char *str) {
+ /* Is this a valid utf8 string? */
+ int ch;
+
+ while ( (ch=utf8_ildb(&str))!='\0' )
+ if ( ch==-1 )
+return( false );
+
+return( true );
+}
+
+void utf8_truncatevalid(char *str) {
+ /* There are certain cases where we have a fixed amount of space to display */
+ /* something, and if it doesn't fit in that, then we truncate it. But... */
+ /* that can leave us with a half completed utf8 byte sequence. So truncate*/
+ /* again, right before the start of the bad sequence */
+ int ch;
+ char *old;
+
+ old = str;
+ while ( (ch=utf8_ildb((const char **) &str))!='\0' ) {
+ if ( ch==-1 ) {
+ *old = '\0';
+return;
+ }
+ old = str;
+ }
+}
+
+char *utf8_db(char *utf8_text) {
+ /* Decrement utf8 pointer */
+ unsigned char *pt = (unsigned char *) utf8_text;
+
+ --pt;
+ if ( *pt>=0xc0 )
+ /* This should never happen. The pointer was looking at an intermediate */
+ /* character. However, if it does happen then we are now properly */
+ /* positioned at the start of a new char */;
+ else if ( *pt>=0x80 ) {
+ --pt;
+ if ( *pt>=0xc0 )
+ /* Done */;
+ else if ( *pt>=0x80 ) {
+ --pt;
+ if ( *pt>=0xc0 )
+ /* Done */;
+ else if ( *pt>=0x80 )
+ --pt;
+ }
+ }
+return( (char *) pt );
+}
+
+int utf8_strlen(const char *utf8_str) {
+ /* how many characters in the string NOT bytes */
+ int len = 0;
+
+ while ( utf8_ildb(&utf8_str)>0 )
+ ++len;
+return( len );
+}
+
+int utf82u_strlen(const char *utf8_str) {
+ /* how many shorts needed to represent it in UCS2 */
+ int ch;
+ int len = 0;
+
+ while ( (ch = utf8_ildb(&utf8_str))>0 )
+ if ( ch>0x10000 )
+ len += 2;
+ else
+ ++len;
+return( len );
+}
+
+void utf8_strncpy(register char *to, const char *from, int len) {
+ /* copy n characters NOT bytes */
+ const char *old = from;
+ while ( len && *old ) {
+ utf8_ildb(&old);
+ len--;
+ }
+ strncpy(to, from, old-from);
+ to[old-from] = 0;
+}
+
+#include <chardata.h>
+char *StripToASCII(const char *utf8_str) {
+ /* Remove any non-ascii characters: Special case, convert the copyright symbol to (c) */
+ char *newcr, *pt, *end;
+ int len, ch;
+ const unichar_t *alt;
+
+ len = strlen(utf8_str);
+ pt = newcr = (char *) xmalloc(len+1);
+ end = pt+len;
+ while ( (ch= utf8_ildb(&utf8_str))!='\0' ) {
+ if ( pt>=end ) {
+ int off = pt-newcr;
+ newcr = (char *) xrealloc(newcr,(off+10)+1);
+ pt = newcr+off;
+ end = pt+10;
+ }
+ if ( (ch>=' ' && ch<'\177' ) || ch=='\n' || ch=='\t' )
+ *pt++ = ch;
+ else if ( ch=='\r' && *utf8_str!='\n' )
+ *pt++ = '\n';
+ else if ( ch==0xa9 /* Copyright sign */ ) {
+ char *str = "(c)";
+ if ( pt+strlen(str)>=end ) {
+ int off = pt-newcr;
+ newcr = (char *) xrealloc(newcr,(off+10+strlen(str))+1);
+ pt = newcr+off;
+ end = pt+10;
+ }
+ while ( *str )
+ *pt++ = *str++;
+ } else if ( unicode_alternates[ch>>8]!=NULL &&
+ (alt = unicode_alternates[ch>>8][ch&0xff])!=NULL ) {
+ while ( *alt!='\0' ) {
+ if ( pt>=end ) {
+ int off = pt-newcr;
+ newcr = (char *) xrealloc(newcr,(off+10)+1);
+ pt = newcr+off;
+ end = pt+10;
+ }
+ if ( *alt>=' ' && *alt<'\177' )
+ *pt++ = *alt;
+ else if ( *alt==0x300 )
+ *pt++ = '`';
+ else if ( *alt==0x301 )
+ *pt++ = '\'';
+ else if ( *alt==0x302 )
+ *pt++ = '^';
+ else if ( *alt==0x303 )
+ *pt++ = '~';
+ else if ( *alt==0x308 )
+ *pt++ = ':';
+ ++alt;
+ }
+ }
+ }
+ *pt = '\0';
+return( newcr );
+}
+
+int AllAscii(const char *txt) {
+ for ( ; *txt!='\0'; ++txt ) {
+ if ( *txt=='\t' || *txt=='\n' || *txt=='\r' )
+ /* All right */;
+ else if ( *txt<' ' || *txt>='\177' )
+return( false );
+ }
+return( true );
+}
+
+int uAllAscii(const unichar_t *txt) {
+ for ( ; *txt!='\0'; ++txt ) {
+ if ( *txt=='\t' || *txt=='\n' || *txt=='\r' )
+ /* All right */;
+ else if ( *txt<' ' || *txt>='\177' )
+return( false );
+ }
+return( true );
+}
+
+char* chomp( char* line ) {
+ if( !line )
+ return line;
+ if ( line[strlen(line)-1]=='\n' )
+ line[strlen(line)-1] = '\0';
+ if ( line[strlen(line)-1]=='\r' )
+ line[strlen(line)-1] = '\0';
+ return line;
+}
+
+char *copytolower(const char *input)
+{
+ char* ret = xstrdup(input);
+ char* p = ret;
+ for( ; *p; ++p ) {
+ *p = tolower(*p);
+ }
+ return ret;
+}
+
+
+int endswith(const char *haystack,const char *needle) {
+ int haylen = strlen( haystack );
+ int nedlen = strlen( needle );
+ char* p;
+ if( haylen < nedlen )
+ return 0;
+ p = strstr( haystack + haylen - nedlen, needle );
+ return p == ( haystack + haylen - nedlen );
+}
+
+int endswithi(const char *haystackZ,const char *needleZ) {
+ char* haystack = copytolower(haystackZ);
+ char* needle = copytolower(needleZ);
+ int ret = endswith( haystack, needle );
+ free( haystack );
+ free( needle );
+ return ret;
+}
+
+int endswithi_partialExtension( const char *haystackZ,const char *needleZ) {
+ int nedlen = strlen(needleZ);
+ char* haystack;
+ char* needle;
+ int ret;
+ int i;
+ if( nedlen == 0 ) {
+ return 0;
+ }
+ haystack = copytolower(haystackZ);
+ needle = copytolower(needleZ);
+ ret = 0;
+ i = nedlen-1;
+ ret |= endswith( haystack, needle );
+ for( ; i>=0 && !ret ; --i ) {
+ needle[i] = '\0';
+ ret |= endswith( haystack, needle );
+ }
+ free( haystack );
+ free( needle );
+ return ret;
+}
+
+int u_endswith(const unichar_t *haystack,const unichar_t *needle) {
+ int haylen = u_strlen( haystack );
+ int nedlen = u_strlen( needle );
+ unichar_t* p;
+ if( haylen < nedlen )
+ return 0;
+ p = u_strstr( haystack + haylen - nedlen, needle );
+ return p == ( haystack + haylen - nedlen );
+}