diff options
author | Suren A. Chilingaryan <csa@dside.dyndns.org> | 2005-07-29 03:26:28 +0000 |
---|---|---|
committer | Suren A. Chilingaryan <csa@dside.dyndns.org> | 2005-07-29 03:26:28 +0000 |
commit | e3f702e83a26468ee44f3f342a7a40a252f4603c (patch) | |
tree | 5ff76e9d11a9fdbdb493683d0f0840f46c67b6f8 /external/rcclibtranslate.c | |
parent | cfaef1b6c9f33fbaa114628cf513d129bdff3c1c (diff) | |
download | librcc-e3f702e83a26468ee44f3f342a7a40a252f4603c.tar.gz librcc-e3f702e83a26468ee44f3f342a7a40a252f4603c.tar.bz2 librcc-e3f702e83a26468ee44f3f342a7a40a252f4603c.tar.xz librcc-e3f702e83a26468ee44f3f342a7a40a252f4603c.zip |
Translation
- Language Translation using libtranslate is implemented
- Autoengine sets current charset (option)
Diffstat (limited to 'external/rcclibtranslate.c')
-rw-r--r-- | external/rcclibtranslate.c | 286 |
1 files changed, 286 insertions, 0 deletions
diff --git a/external/rcclibtranslate.c b/external/rcclibtranslate.c new file mode 100644 index 0000000..56ce8a2 --- /dev/null +++ b/external/rcclibtranslate.c @@ -0,0 +1,286 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + + +#include "../config.h" + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif /* HAVE_UNISTD_H */ +#ifdef HAVE_SYS_TYPES_H +# include <sys/types.h> +#endif /* HAVE_SYS_TYPES_H */ +#ifdef HAVE_SYS_STAT_H +# include <sys/stat.h> +#endif /* HAVE_SYS_STAT_H */ + +#ifdef HAVE_LIBTRANSLATE +#include <translate.h> +#endif /* HAVE_LIBTRANSLATE */ + +#include "../src/rccexternal.h" +#include "../src/rcctranslate.h" +#include "../src/rccdb4.h" +#include "rcclibtranslate.h" + + +#ifdef HAVE_LIBTRANSLATE +static TranslateSession *session = NULL; +static db4_context db4ctx = NULL; + +static int exitflag = 0; +static GMutex *mutex = NULL; +static GCond *cond = NULL; +static GQueue *queue = NULL; +static GThread *thread = NULL; + + +static char *rccCreateKey(const char *from, const char *to, const char *data, size_t *keysize) { + char *res; + + *keysize = strlen(data) + 4; + res = (char*)malloc((*keysize+1)*sizeof(char)); + if (res) sprintf(res,"%s%s%s",from,to,data); + return res; +} + +static void *rccLibPostponed(void *info) { + char *result; + char *data; + char from[3]; + char to[3]; + + from[2] = 0; + to[2] = 0; + + g_mutex_lock(mutex); + while (!exitflag) { + data = (char*)g_queue_pop_head(queue); + if (data) { + g_mutex_unlock(mutex); + + memcpy(from, data, 2); + memcpy(to, data + 2, 2); + result = translate_session_translate_text(session, data + 4, from, to, NULL, NULL, NULL); + + if (result) { + rccDb4SetKey(db4ctx, data, strlen(data), result); + free(result); + } + + free(data); + g_mutex_lock(mutex); + } else { + g_cond_wait(cond, mutex); + } + } + g_mutex_unlock(mutex); + return NULL; +} + +#endif /* HAVE_LIBTRANSLATE */ + + +int rccLibTranslateInit(const char *rcc_home_dir) { +#ifdef HAVE_LIBTRANSLATE + size_t size; + char *dbname; + GSList *list = NULL; + + const char *http_proxy; + + if (!translate_init(NULL)) return -1; + + http_proxy = getenv("HTTP_PROXY"); + if (!http_proxy) http_proxy = getenv("http_proxy"); + translate_set_proxy(http_proxy); + + list = translate_get_services(); + + session = translate_session_new(list); + + g_slist_foreach(list, (GFunc) g_object_unref, NULL); + g_slist_free(list); + + + size = strlen(rcc_home_dir) + 32; + dbname = (char*)malloc(size*sizeof(char)); + if (dbname) { + sprintf(dbname,"%s/.rcc/",rcc_home_dir); + mkdir(dbname, 00644); + + sprintf(dbname,"%s/.rcc/libtranslate.db/",rcc_home_dir); + mkdir(dbname, 00644); + + db4ctx = rccDb4CreateContext(dbname, 0); + free(dbname); + } + if (db4ctx) { + mutex = g_mutex_new(); + cond = g_cond_new(); + if ((mutex)&&(cond)) + queue = g_queue_new(); + if (queue) + thread = g_thread_create(rccLibPostponed, NULL, TRUE, NULL); + } +#endif /* HAVE_LIBTRANSLATE */ + + return 0; +} + +void rccLibTranslateFree() { +#ifdef HAVE_LIBTRANSLATE + char *ptr; + if (session) { + if (thread) { + exitflag = 1; + g_cond_signal(cond); + g_thread_join(thread); + thread = NULL; + exitflag = 0; + } + if (queue) { + do { + ptr = g_queue_pop_head(queue); + if (ptr) free(ptr); + } while (ptr); + g_queue_free(queue); + queue = NULL; + } + if (mutex) { + g_mutex_free(mutex); + mutex = NULL; + } + if (cond) { + g_cond_free(cond); + cond = NULL; + } + if (db4ctx) rccDb4FreeContext(db4ctx); + g_object_unref(session); + session = NULL; + } +#endif /* HAVE_LIBTRANSLATE */ +} + + +static char *rccLibTranslateDo(const char *from, const char *to, const char *text, unsigned long timeout) { +#ifdef HAVE_LIBTRANSLATE + char *result; + char *key = NULL; + size_t keysize; + + if ((!session)||(!from)||(!to)||(!text)) return NULL; + if ((strlen(from)!=2)||(strlen(to)!=2)) return NULL; + + if (db4ctx) { + key = rccCreateKey(from,to,text,&keysize); + if (key) { + result = rccDb4GetKey(db4ctx, key, keysize); + if (result) { + free(key); + return result; + } + } + } +# ifdef HAVE_LIBTRANSLATE_TIMED_TRANSLATE + result = translate_session_timed_translate_text(session, text, from, to, timeout, NULL, NULL, NULL); +# else + result = translate_session_translate_text(session, text, from, to, NULL, NULL, NULL); +# endif /* HAVE_LIBTRANSLATE_TIMED_TRANSLATE */ + + if ((db4ctx)&&(key)) { + if (result) { + rccDb4SetKey(db4ctx, key, keysize, result); + free(key); + } + else { + g_mutex_lock(mutex); + g_queue_push_tail(queue, key); + g_mutex_unlock(mutex); + g_cond_signal(cond); + } + } + + return result; +#else + return NULL; +#endif /* HAVE_LIBTRANSLATE */ +} + + +void *rccLibTranslate(void *info) { + int s; +#ifdef HAVE_LIBTRANSLATE + unsigned char connected = 1; + rcc_translate_prefix_s prefix; + ssize_t readed, writed, res; + char *buffer; + size_t size; + char *translated = NULL; +#endif /* HAVE_LIBTRANSLATE */ + + if (!info) return NULL; + + s = ((rcc_external_info)info)->s; + free(info); + +#ifdef HAVE_LIBTRANSLATE + while (connected) { + readed = read(s, &prefix, sizeof(rcc_translate_prefix_s)-1); + if ((readed<=0)||(readed != (sizeof(rcc_translate_prefix_s)-1))) break; + + switch (prefix.cmd.cmd) { + case RCC_EXTERNAL_COMMAND_CLOSE: + connected = 0; + break; + case RCC_EXTERNAL_COMMAND_TRANSLATE: + size = 1 + prefix.cmd.size + sizeof(rcc_external_command_s) - sizeof(rcc_translate_prefix_s); + buffer = (char*)malloc(size); + if (buffer) { + for (readed = 0; (readed < size)&&(connected); readed += res) { + res = read(s, buffer + readed, size - readed); + if (res<=0) connected = 0; + } + + prefix.cmd.cmd = 0; + prefix.cmd.size = 0; + + if ((prefix.from[2])||(prefix.to[2])||(buffer[readed-1])) goto respond; + + translated = rccLibTranslateDo(prefix.from, prefix.to, buffer, prefix.timeout); + if (translated) { + prefix.cmd.cmd = RCC_EXTERNAL_COMMAND_TRANSLATE; + prefix.cmd.size = strlen(translated) + 1; + } + +respond: + res = write(s, &prefix.cmd, sizeof(rcc_external_command_s)); + if (res == sizeof(rcc_external_command_s)) { + for (writed = 0; (writed < prefix.cmd.size)&&(connected); writed += res) { + res = write(s, translated + writed, prefix.cmd.size - writed); + if (res<=0) connected = 0; + } + } else connected = 0; + + if (prefix.cmd.size) free(translated); + free(buffer); + } else connected = 0; + break; + default: + buffer = (char*)malloc(prefix.cmd.size); + if (buffer) { + for (readed = 0; (readed < prefix.cmd.size)&&(connected); readed += res) { + res = read(s, buffer + readed, prefix.cmd.size - readed); + if (res<=0) connected = 0; + } + free(buffer); + } else connected = 0; + } + } +#endif /* HAVE_LIBTRANSLATE */ + + close(s); + return NULL; +} + |