mud/fluffos-2.23-ds03/fliconv.c
2020-09-06 05:43:07 -07:00

211 lines
4.2 KiB
C

#include "fliconv.h"
#include <errno.h>
#include "std.h"
#include "lpc_incl.h"
#include "comm.h"
#ifdef USE_ICONV
struct translation *head;
static struct translation *find_translator(const char *encoding){
struct translation *cur = head;
while(cur){
if(!strcmp(cur->name, encoding))
break;
cur = cur->next;
}
return cur;
}
struct translation *get_translator(const char *encoding){
struct translation *ret = find_translator(encoding);
if(ret)
return ret;
ret = (struct translation *)MALLOC(sizeof(struct translation));
char *name = (char *)MALLOC(strlen(encoding)+18+1);
strcpy(name, encoding);
#ifdef linux
strcat(name, "//TRANSLIT//IGNORE");
#endif
ret->name = name;
ret->incoming = iconv_open("UTF-8", encoding);
ret->outgoing = iconv_open(name, "UTF-8");
ret->next = 0;
if(ret->incoming == (iconv_t)-1 || ret->outgoing == (iconv_t)-1){
FREE(name);
FREE(ret);
return 0;
}
name[strlen(encoding)] = 0;
if(!head)
head = ret;
else {
struct translation *cur = head;
while(cur->next)
cur = cur->next;
cur->next = ret;
}
return ret;
}
char *translate(iconv_t tr, const char *mes, int inlen, int *outlen){
size_t len = inlen;
size_t len2;
unsigned char *tmp = (unsigned char *)mes;
static char *res = 0;
static size_t reslen = 0;
char *tmp2;
if(!res){
res = (char *)MALLOC(1);
reslen = 1;
}
tmp2 = res;
len2 = reslen;
while(len){
iconv(tr, (char **)&tmp, &len, &tmp2, &len2);
#ifdef PACKAGE_DWLIB
if(len > 1 && tmp[0] == 0xff && tmp[1] == 0xf9){
len -=2;
tmp +=2;
#else
if(0){
#endif
} else {
if(E2BIG == errno){
errno = 0;
tmp = (unsigned char *)mes;
len = strlen(mes)+1;
FREE(res);
reslen *= 2;
res = (char *)MALLOC(reslen);
tmp2 = res;
len2 = reslen;
continue;
}
tmp2[0] = 0;
*outlen = reslen - len2;
return res;
}
}
*outlen = reslen - len2;
return res;
}
#else
char *translate(iconv_t tr, const char *mes, int inlen, int *outlen){
*outlen = inlen;
return (char *)mes;
}
#endif
char *translate_easy(iconv_t tr, char *mes){
int dummy;
char *res = translate(tr, mes, strlen(mes)+1, &dummy);
return res;
}
#ifdef F_SET_ENCODING
void f_set_encoding(){
if(current_object->interactive){
struct translation *newt = get_translator((char *)sp->u.string);
if(newt){
current_object->interactive->trans = newt;
return;
}
}
pop_stack();
push_number(0);
}
#endif
#ifdef F_TO_UTF8
void f_to_utf8(){
struct translation *newt = get_translator((char *)sp->u.string);
pop_stack();
if(!newt)
error("unknown encoding");
char *text = (char *)sp->u.string;
char *translated = translate_easy(newt->incoming, text);
pop_stack();
copy_and_push_string(translated);
}
#endif
#ifdef F_UTF8_TO
void f_utf8_to(){
struct translation *newt = get_translator((char *)sp->u.string);
pop_stack();
if(!newt)
error("unknown encoding");
char *text = (char *)sp->u.string;
char *translated = translate_easy(newt->outgoing, text);
pop_stack();
copy_and_push_string(translated);
}
#endif
#ifdef F_STR_TO_ARR
void f_str_to_arr(){
static struct translation *newt = 0;
if(!newt){
newt = get_translator("UTF-32");
translate_easy(newt->outgoing, " ");
}
int len;
int *trans = (int *)translate(newt->outgoing, sp->u.string, SVALUE_STRLEN(sp)+1, &len);
len/=4;
array_t *arr = allocate_array(len);
while(len--)
arr->item[len].u.number = trans[len];
free_svalue(sp, "str_to_arr");
put_array(arr);
}
#endif
#ifdef F_ARR_TO_STR
void f_arr_to_str(){
static struct translation *newt = 0;
if(!newt){
newt = get_translator("UTF-32");
}
int len = sp->u.arr->size;
int *in = (int *)MALLOC(sizeof(int)*(len+1));
char *trans;
in[len] = 0;
while(len--)
in[len] = sp->u.arr->item[len].u.number;
trans = translate(newt->incoming, (char *)in, (sp->u.arr->size+1)*4, &len);
FREE(in);
pop_stack();
copy_and_push_string(trans);
}
#endif
#ifdef F_STRWIDTH
void f_strwidth(){
int len = SVALUE_STRLEN(sp);
int width = 0;
int i;
for(i=0; i<len; i++)
width += !(((sp->u.string[i]) & 0xc0) == 0x80);
pop_stack();
push_number(width);
}
#endif