wmii

git clone git://oldgit.suckless.org/wmii/
Log | Files | Refs | README | LICENSE

utf.c (1317B)


      1 /* Public Domain --Kris Maglione */
      2 #include "dat.h"
      3 #include <errno.h>
      4 #include <iconv.h>
      5 #include <langinfo.h>
      6 #include <string.h>
      7 #include "fns.h"
      8 
      9 char*
     10 toutf8n(const char *str, size_t nstr) {
     11 	static iconv_t cd;
     12 	static bool haveiconv;
     13 	char *buf, *pos;
     14 	size_t nbuf, bsize;
     15 
     16 	if(cd == nil) {
     17 		cd = iconv_open("UTF-8", nl_langinfo(CODESET));
     18 		if((long)cd == -1)
     19 			warning("Can't convert from local character encoding to UTF-8");
     20 		else
     21 			haveiconv = true;
     22 	}
     23 	if(!haveiconv) {
     24 		buf = emalloc(nstr+1);
     25 		memcpy(buf, str, nstr);
     26 		buf[nstr+1] = '\0';
     27 		return buf;
     28 	}
     29 
     30 	iconv(cd, nil, nil, nil, nil);
     31 
     32 	bsize = (nstr+1) << 1;
     33 	buf = emalloc(bsize);
     34 	pos = buf;
     35 	nbuf = bsize-1;
     36 	/* The (void*) cast is because, while the BSDs declare:
     37 	 * size_t iconv(iconv_t, const char**, size_t*, char**, size_t*),
     38 	 * GNU/Linux and POSIX declare:
     39 	 * size_t iconv(iconv_t, char**, size_t*, char**, size_t*).
     40 	 * This just happens to be safer than declaring our own
     41 	 * prototype.
     42 	 */
     43 	while(iconv(cd, (void*)&str, &nstr, &pos, &nbuf) == -1)
     44 		if(errno == E2BIG) {
     45 			bsize <<= 1;
     46 			nbuf = pos - buf;
     47 			buf = erealloc(buf, bsize);
     48 			pos = buf + nbuf;
     49 			nbuf = bsize - nbuf - 1;
     50 		}else
     51 			break;
     52 	*pos++ = '\0';
     53 	return erealloc(buf, pos-buf);
     54 }
     55 
     56 char*
     57 toutf8(const char *str) {
     58 	return toutf8n(str, strlen(str));
     59 }
     60