summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSuren A. Chilingaryan <csa@dside.dyndns.org>2005-07-29 03:26:28 +0000
committerSuren A. Chilingaryan <csa@dside.dyndns.org>2005-07-29 03:26:28 +0000
commite3f702e83a26468ee44f3f342a7a40a252f4603c (patch)
tree5ff76e9d11a9fdbdb493683d0f0840f46c67b6f8 /src
parentcfaef1b6c9f33fbaa114628cf513d129bdff3c1c (diff)
downloadlibrcc-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 'src')
-rw-r--r--src/Makefile.am2
-rw-r--r--src/fs.c2
-rw-r--r--src/librcc.c45
-rw-r--r--src/librcc.h58
-rw-r--r--src/lngconfig.c7
-rw-r--r--src/lngconfig.h4
-rw-r--r--src/rccconfig.c6
-rw-r--r--src/rccdb4.c41
-rw-r--r--src/rccdb4.h8
-rw-r--r--src/rccexternal.c210
-rw-r--r--src/rccexternal.h35
-rw-r--r--src/rcciconv.c23
-rw-r--r--src/rcciconv.h14
-rw-r--r--src/rcctranslate.c151
-rw-r--r--src/rcctranslate.h31
-rw-r--r--src/recode.c68
16 files changed, 642 insertions, 63 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 50c6836..baa08a4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -8,6 +8,7 @@ librcc_la_SOURCES = librcc.c \
rccconfig.c rccconfig.h \
rcclist.c rcclist.h \
plugin.c plugin.h \
+ rccexternal.c rccexternal.h \
fake_enca.h fake_rcd.h \
rccenca.c rccenca.h \
rccdb4.c rccdb4.h \
@@ -15,6 +16,7 @@ librcc_la_SOURCES = librcc.c \
rccstring.c rccstring.h \
rccxml.c rccxml.h \
rcciconv.c rcciconv.h \
+ rcctranslate.c rcctranslate.h \
fs.c fs.h \
recode.c recode.h \
internal.h
diff --git a/src/fs.c b/src/fs.c
index c378704..fb0a2bc 100644
--- a/src/fs.c
+++ b/src/fs.c
@@ -195,7 +195,7 @@ const char *rccFS2(rcc_language_config config, iconv_t icnv, const char *prefix,
char *tmpbuffer = config->ctx->tmpbuffer;
if (icnv) {
- size = rccIConv(config->ctx, icnv, name, 0);
+ size = rccIConvInternal(config->ctx, icnv, name, 0);
if (size == (size_t)-1) return NULL;
} else {
strncpy(tmpbuffer, name, RCC_MAX_STRING_CHARS);
diff --git a/src/librcc.c b/src/librcc.c
index ec2df39..c0112df 100644
--- a/src/librcc.c
+++ b/src/librcc.c
@@ -11,6 +11,9 @@
#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_PWD_H
# include <pwd.h>
@@ -23,6 +26,8 @@
#include "plugin.h"
#include "engine.h"
#include "rccxml.h"
+#include "rccexternal.h"
+#include "rcctranslate.h"
static int initialized = 0;
char *rcc_home_dir = NULL;
@@ -43,6 +48,9 @@ rcc_compiled_configuration rccGetCompiledConfiguration() {
#ifdef HAVE_DB_H
compiled_configuration.flags|=RCC_CC_FLAG_HAVE_BERKLEY_DB;
#endif /* HAVE_DB_H */
+#ifdef HAVE_LIBTRANSLATE
+ compiled_configuration.flags|=RCC_CC_FLAG_HAVE_LIBTRANSLATE;
+#endif /* HAVE_LIBTRANSLATE */
return &compiled_configuration;
}
@@ -72,7 +80,12 @@ int rccInit() {
memcpy(rcc_default_languages, rcc_default_languages_embeded, (RCC_MAX_LANGUAGES + 1)*sizeof(rcc_language));
memcpy(rcc_option_descriptions, rcc_option_descriptions_embeded, (RCC_MAX_OPTIONS + 1)*sizeof(rcc_option_description));
+#ifdef HAVE_LIBTRANSLATE
+ rccExternalInit();
+#endif /* HAVE_LIBTRANSLATE */
+
err = rccPluginInit();
+ if (!err) err = rccTranslateInit();
if (!err) err = rccXmlInit(1);
if (!err) err = rccEngineInit();
@@ -94,8 +107,11 @@ void rccFree() {
rccEngineFree();
rccXmlFree();
+ rccTranslateFree();
rccPluginFree();
+ rccExternalFree();
+
if (rcc_home_dir) {
free(rcc_home_dir);
rcc_home_dir = NULL;
@@ -274,6 +290,35 @@ void rccFreeContext(rcc_context ctx) {
}
}
+int rccInitDb4(rcc_context ctx, const char *name, rcc_db4_flags flags) {
+ size_t size;
+ char *dbname;
+
+ if (!ctx) {
+ if (rcc_default_ctx) ctx = rcc_default_ctx;
+ else return -1;
+ }
+
+ if (!name) name = "default";
+
+ size = strlen(rcc_home_dir) + strlen(name) + 32;
+ dbname = (char*)malloc(size*sizeof(char));
+ if (!dbname) return -1;
+
+ sprintf(dbname,"%s/.rcc/",rcc_home_dir);
+ mkdir(dbname, 00644);
+
+ sprintf(dbname,"%s/.rcc/%s.db/",rcc_home_dir,name);
+ mkdir(dbname, 00644);
+
+ ctx->db4ctx = rccDb4CreateContext(dbname, flags);
+ free(dbname);
+
+ if (!ctx->db4ctx) return -1;
+
+ return 0;
+}
+
int rccLockConfiguration(rcc_context ctx, unsigned int lock_code) {
if (!ctx) {
if (rcc_default_ctx) ctx = rcc_default_ctx;
diff --git a/src/librcc.h b/src/librcc.h
index a70d6df..52e6be4 100644
--- a/src/librcc.h
+++ b/src/librcc.h
@@ -371,6 +371,8 @@ typedef enum rcc_option_t {
RCC_OPTION_AUTODETECT_FS_TITLES, /**< Detect titles of #RCC_CLASS_FS classes */
RCC_OPTION_AUTODETECT_FS_NAMES, /**< Try to find encoding of #RCC_CLASS_FS by accessing fs */
RCC_OPTION_CONFIGURED_LANGUAGES_ONLY, /**< Use only configured languages or languages with auto-engines */
+ RCC_OPTION_TRANSLATE, /**< Translate #rcc_string if it's language differs from current one */
+ RCC_OPTION_AUTOENGINE_SET_CURRENT, /**< If enabled autodetection engine will set current charset */
RCC_MAX_OPTIONS
} rcc_option;
@@ -908,7 +910,6 @@ typedef struct rcc_iconv_t *rcc_iconv;
* @result
* - NULL if no recoding is required
* - Pointer on initialized context if successful
- * - Pointer on errnous context in the case of error
*/
rcc_iconv rccIConvOpen(const char *from, const char *to);
/**
@@ -920,13 +921,53 @@ void rccIConvClose(rcc_iconv icnv);
* Recodes chunk of data.
*
* @param icnv is recoding context
- * @param outbuf is preallocated output buffer
- * @param outsize is size of output buffer (striped string will be returned if buffer to small)
* @param buf is data for recoding
- * @param size is size of the data
- * @return number of recoded bytes in output buffer or -1 in the case of error
+ * @param len is size of the data
+ * @param rlen is size of recoded data
+ * @return recoded string or NULL in the case of error
*/
-size_t rccIConvRecode(rcc_iconv icnv, char *outbuf, size_t outsize, const char *buf, size_t size);
+char *rccIConv(rcc_iconv icnv, const char *buf, size_t len, size_t *rlen);
+
+/**
+ * translating context
+ */
+typedef struct rcc_translate_t *rcc_translate;
+
+/* rcctranslate.c */
+/**
+ * Open translating context.
+ *
+ * @param from is source language
+ * @param to is destination language
+ * @return
+ * - NULL if translation is not required or possible
+ * - Pointer on initialized context if successful
+ */
+rcc_translate rccTranslateOpen(const char *from, const char *to);
+/**
+ * Close translating context.
+ *
+ * @param translate is translating context
+ */
+void rccTranslateClose(rcc_translate translate);
+
+/*
+ * Set translation timeout
+ *
+ * @param translate is translating context
+ * @param us is timeout in microseconds (0 - no timeout)
+ * @return non-zero value is returned in the case of errror
+ */
+int rccTranslateSetTimeout(rcc_translate translate, unsigned long us);
+
+/**
+ * Translate string.
+ *
+ * @param translate is translating context
+ * @param buf is UTF-8 encoded string for translating
+ * @return recoded string or NULL in the case of error
+ */
+char *rccTranslate(rcc_translate translate, const char *buf);
/* recode.c */
/**
@@ -1119,6 +1160,11 @@ rcc_context rccEngineGetRccContext(rcc_engine_context ctx);
*/
#define RCC_CC_FLAG_HAVE_RCD 0x08
/**
+ * Libtranslate translation engine compiled in
+ */
+#define RCC_CC_FLAG_HAVE_LIBTRANSLATE 0x10
+
+/**
* The library build environment is represented by this structure
*/
struct rcc_compiled_configuration_t {
diff --git a/src/lngconfig.c b/src/lngconfig.c
index efb2c1a..c50ee74 100644
--- a/src/lngconfig.c
+++ b/src/lngconfig.c
@@ -164,6 +164,7 @@ int rccConfigInit(rcc_language_config config, rcc_context ctx) {
}
config->fsiconv = NULL;
+ config->trans = NULL;
config->ctx = ctx;
config->language = NULL;
@@ -199,6 +200,10 @@ void rccConfigFreeIConv(rcc_language_config config) {
void rccConfigClear(rcc_language_config config) {
if ((config)&&(config->charset)) {
rccConfigFreeIConv(config);
+ if (config->trans) {
+ rccTranslateClose(config->trans);
+ config->trans = NULL;
+ }
if (config->iconv_to) {
free(config->iconv_to);
config->iconv_to = NULL;
@@ -521,7 +526,7 @@ int rccConfigConfigure(rcc_language_config config) {
if ((!charset)||(rccIsUTF8(charset))) continue;
config->iconv_to[i] = rccIConvOpen(charset, "UTF-8");
}
-
+
config->configure = 0;
return 0;
diff --git a/src/lngconfig.h b/src/lngconfig.h
index b136905..92cc050 100644
--- a/src/lngconfig.h
+++ b/src/lngconfig.h
@@ -2,6 +2,7 @@
#define _RCC_LNGCONFIG_H
#include "rcciconv.h"
+#include "rcctranslate.h"
struct rcc_language_config_t {
rcc_context ctx;
@@ -16,6 +17,9 @@ struct rcc_language_config_t {
unsigned char configured;
+ rcc_translate trans;
+ rcc_language_id translang;
+
rcc_iconv fsiconv;
};
typedef struct rcc_language_config_t rcc_language_config_s;
diff --git a/src/rccconfig.c b/src/rccconfig.c
index 57d38c3..ed6d30a 100644
--- a/src/rccconfig.c
+++ b/src/rccconfig.c
@@ -40,6 +40,10 @@ rcc_language rcc_default_languages_embeded[RCC_MAX_LANGUAGES + 1] = {
&rcc_default_engine,
NULL
}},
+{"en", {rcc_default_charset, rcc_utf8_charset, NULL}, {
+ &rcc_default_engine,
+ NULL
+}},
{"ru", {rcc_default_charset,"KOI8-R","CP1251",rcc_utf8_charset,"IBM866","MACCYRILLIC","ISO8859-5", NULL}, {
&rcc_default_engine,
#ifdef RCC_RCD_SUPPORT
@@ -115,6 +119,8 @@ rcc_option_description rcc_option_descriptions_embeded[RCC_MAX_OPTIONS+1] = {
{RCC_OPTION_AUTODETECT_FS_NAMES, 1, { RCC_OPTION_RANGE_TYPE_BOOLEAN, 0, 0, 0}, RCC_OPTION_TYPE_STANDARD, "AUTODETECT_FS_NAMES", rcc_sn_boolean},
{RCC_OPTION_AUTODETECT_FS_TITLES, 1, { RCC_OPTION_RANGE_TYPE_BOOLEAN, 0, 0, 0}, RCC_OPTION_TYPE_INVISIBLE, "AUTODETECT_FS_TITLES", rcc_sn_boolean},
{RCC_OPTION_CONFIGURED_LANGUAGES_ONLY, 1, { RCC_OPTION_RANGE_TYPE_MENU, 0, 2, 1}, RCC_OPTION_TYPE_INVISIBLE, "CONFIGURED_LANGUAGES_ONLY", rcc_sn_clo},
+ {RCC_OPTION_TRANSLATE, 0, { RCC_OPTION_RANGE_TYPE_BOOLEAN, 0, 0, 0}, RCC_OPTION_TYPE_STANDARD, "TRANSLATE", rcc_sn_boolean },
+ {RCC_OPTION_AUTOENGINE_SET_CURRENT, 0, { RCC_OPTION_RANGE_TYPE_BOOLEAN, 0, 0, 0}, RCC_OPTION_TYPE_STANDARD, "AUTOENGINE_SET_CURRENT", rcc_sn_boolean },
{RCC_MAX_OPTIONS}
};
diff --git a/src/rccdb4.c b/src/rccdb4.c
index d3e8cab..9c21477 100644
--- a/src/rccdb4.c
+++ b/src/rccdb4.c
@@ -4,48 +4,11 @@
#include "../config.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 */
-
#include "internal.h"
#include "rccdb4.h"
#define DATABASE "autolearn.db"
-int rccInitDb4(rcc_context ctx, const char *name, rcc_db4_flags flags) {
- size_t size;
- char *dbname;
-
- if (!ctx) {
- if (rcc_default_ctx) ctx = rcc_default_ctx;
- else return -1;
- }
-
- if (!name) name = "default";
-
- size = strlen(rcc_home_dir) + strlen(name) + 32;
- dbname = (char*)malloc(size*sizeof(char));
- if (!dbname) return -1;
-
- sprintf(dbname,"%s/.rcc/",rcc_home_dir);
- mkdir(dbname, 00644);
-
- sprintf(dbname,"%s/.rcc/%s.db/",rcc_home_dir,name);
- mkdir(dbname, 00644);
-
- ctx->db4ctx = rccDb4CreateContext(dbname, flags);
- free(dbname);
-
- if (!ctx->db4ctx) return -1;
-
- return 0;
-}
-
db4_context rccDb4CreateContext(const char *dbpath, rcc_db4_flags flags) {
int err;
db4_context ctx;
@@ -124,7 +87,7 @@ static void rccDb4Strip(DBT *key) {
}
#endif /* HAVE_DB_H */
-int rccDb4SetKey(db4_context ctx, const char *orig, size_t olen, const rcc_string string) {
+int rccDb4SetKey(db4_context ctx, const char *orig, size_t olen, const char *string) {
#ifdef HAVE_DB_H
DBT key, data;
#endif /* HAVE_DB_H */
@@ -149,7 +112,7 @@ int rccDb4SetKey(db4_context ctx, const char *orig, size_t olen, const rcc_strin
return 1;
}
-rcc_string rccDb4GetKey(db4_context ctx, const char *orig, size_t olen) {
+char *rccDb4GetKey(db4_context ctx, const char *orig, size_t olen) {
#ifdef HAVE_DB_H
DBT key, data;
#endif /* HAVE_DB_H */
diff --git a/src/rccdb4.h b/src/rccdb4.h
index 1d5072b..a11e53d 100644
--- a/src/rccdb4.h
+++ b/src/rccdb4.h
@@ -3,12 +3,12 @@
#include "../config.h"
+#include "librcc.h"
+
#ifdef HAVE_DB_H
# include <db.h>
#endif /* HAVE_DB_H */
-#include "rccstring.h"
-
struct db4_context_t {
#ifdef HAVE_DB_H
DB_ENV *dbe;
@@ -24,7 +24,7 @@ typedef struct db4_context_t *db4_context;
db4_context rccDb4CreateContext(const char *dbpath, rcc_db4_flags flags);
void rccDb4FreeContext(db4_context ctx);
-int rccDb4SetKey(db4_context ctx, const char *orig, size_t olen, const rcc_string string);
-rcc_string rccDb4GetKey(db4_context ctx, const char *orig, size_t olen);
+int rccDb4SetKey(db4_context ctx, const char *orig, size_t olen, const char *string);
+char *rccDb4GetKey(db4_context ctx, const char *orig, size_t olen);
#endif /* _RCC_DB4_H */
diff --git a/src/rccexternal.c b/src/rccexternal.c
new file mode 100644
index 0000000..16b3667
--- /dev/null
+++ b/src/rccexternal.c
@@ -0,0 +1,210 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+
+#include "../config.h"
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#endif /* HAVE_FCNTL_H */
+#ifdef HAVE_SIGNAL_H
+# include <signal.h>
+#endif /* HAVE_SIGNAL_H */
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif /* HAVE_SYS_TYPES_H */
+#ifdef HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif /* HAVE_SYS_SOCKET_H */
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif /* HAVE_SYS_STAT_H */
+#ifdef HAVE_SYS_UN_H
+# include <sys/un.h>
+#endif /* HAVE_SYS_UN_H */
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif /* HAVE_SYS_TIME_H */
+#ifdef HAVE_SYS_SELECT_H
+# include <sys/select.h>
+#endif /* HAVE_SYS_SELECT_H */
+#ifdef HAVE_SYS_WAIT_H
+# include <sys/wait.h>
+#endif /* HAVE_SYS_WAIT_H */
+
+#include "rccexternal.h"
+#include "internal.h"
+
+#define RCC_EXT_PROG_NAME "rccexternal"
+
+static pid_t pid = (pid_t)-1;
+static char *addr = NULL;
+
+int rccExternalInit() {
+#ifdef HAVE_SIGNAL_H
+ struct sigaction act;
+#endif /* HAVE_SIGNAL_H */
+
+ if (pid != (pid_t)-1) return 0;
+
+ if (!addr) {
+ addr = (char*)malloc(strlen(rcc_home_dir)+32);
+ if (!addr) return -1;
+ }
+
+ pid = fork();
+ if (pid) {
+ if (pid == (pid_t)-1) return -1;
+ sprintf(addr,"%s/.rcc/comm/%lu.sock", rcc_home_dir, (unsigned long)pid);
+
+#ifdef HAVE_SIGNAL_H
+ act.sa_handler = SIG_IGN;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+ sigaction(SIGPIPE,&act,NULL);
+#endif /* HAVE_SIGNAL_H */
+
+ return 0;
+ }
+
+ execl(LIBRCC_DATA_DIR "/" RCC_EXT_PROG_NAME, RCC_EXT_PROG_NAME, NULL);
+ exit(1);
+}
+
+void rccExternalFree() {
+ if (pid == (pid_t)-1) return;
+
+ rccExternalConnect(0);
+ if (addr) free(addr);
+
+ waitpid(pid, NULL, 0);
+ pid = (pid_t)-1;
+}
+
+static int rccExternalSetDeadline(struct timeval *tv, unsigned long timeout) {
+ gettimeofday(tv, NULL);
+ tv->tv_sec += (tv->tv_usec + timeout + RCC_EXTERNAL_TIMEOUT) / 1000000;
+ tv->tv_usec = (tv->tv_usec + timeout + RCC_EXTERNAL_TIMEOUT) % 1000000;
+ return 0;
+}
+
+size_t rccExternalWrite(int s, const char *buffer, ssize_t size, unsigned long timeout) {
+ int err;
+ unsigned char connected = 1;
+ ssize_t writed, res = 0;
+ struct timeval tv;
+ fd_set fdcon;
+
+ if (s == -1) return -1;
+
+ for (writed = 0; (writed < size)&&(connected); writed += connected?res:0) {
+ FD_ZERO(&fdcon);
+ FD_SET(s, &fdcon);
+ rccExternalSetDeadline(&tv, timeout);
+ err = select(s+1,NULL,&fdcon,NULL,&tv);
+ if (err<=0) connected = 0;
+ else {
+ res = write(s, buffer + writed, size - writed);
+ if (res<=0) connected = 0;
+ }
+ }
+
+ return size - writed;
+}
+
+size_t rccExternalRead(int s, char *buffer, ssize_t size, unsigned long timeout) {
+ int err;
+ unsigned char connected = 1;
+ ssize_t readed, res = 0;
+ struct timeval tv;
+ fd_set fdcon;
+
+ if (s == -1) return -1;
+
+ for (readed = 0; (readed < size)&&(connected); readed += connected?res:0) {
+ FD_ZERO(&fdcon);
+ FD_SET(s, &fdcon);
+ rccExternalSetDeadline(&tv, timeout);
+ err = select(s+1,&fdcon,NULL,NULL,&tv);
+ if (err<=0) connected = 0;
+ else {
+ res = read(s, buffer + readed, size - readed);
+ if (res<=0) connected = 0;
+ }
+ }
+
+ return size - readed;
+}
+
+int rccExternalConnect(unsigned char module) {
+ int err;
+ int retries = 10;
+ int sock;
+ int flags;
+ struct sockaddr_un mysock;
+ struct timeval tv;
+ struct timespec ts;
+ fd_set fdcon;
+
+ if (pid == (pid_t)-1) return -1;
+
+ sock = socket(PF_UNIX, SOCK_STREAM, 0);
+ if (sock<=0) return -1;
+
+ flags = fcntl(sock,F_GETFL,0);
+ if (flags<0) flags = 0;
+ if (fcntl(sock,F_SETFL,flags|O_NONBLOCK)<0) {
+ close(sock);
+ return -1;
+ }
+
+ memset(&mysock, 0, sizeof(mysock));
+ mysock.sun_family=AF_UNIX;
+ strncpy(mysock.sun_path,addr,sizeof(mysock.sun_path));
+ mysock.sun_path[sizeof(mysock.sun_path)-1]=0;
+
+again:
+ if (connect(sock,(struct sockaddr*)&mysock,sizeof(mysock))<0) {
+ if (errno == EINPROGRESS) {
+ FD_ZERO(&fdcon);
+ FD_SET(sock, &fdcon);
+
+ rccExternalSetDeadline(&tv, 0);
+ err = select(sock+1,&fdcon,NULL,NULL,&tv);
+ if (err<=0) {
+ close(sock);
+ return -1;
+ }
+ } else if ((errno == ENOENT)&&(retries)) {
+ ts.tv_sec = (RCC_EXTERNAL_TIMEOUT/10) / 1000000;
+ ts.tv_nsec = ((RCC_EXTERNAL_TIMEOUT/10) % 1000000)*1000;
+ nanosleep(&ts, NULL);
+ retries--;
+ goto again;
+ } else {
+ close(sock);
+ return -1;
+ }
+ }
+
+ if (rccExternalWrite(sock, &module, 1, 0)) {
+ close(sock);
+ return -1;
+ }
+
+ return sock;
+}
+
+void rccExternalClose(int s) {
+ unsigned char cmd = 0;
+ if (s != -1) {
+ write(s, &cmd, 1);
+ close(s);
+ }
+}
diff --git a/src/rccexternal.h b/src/rccexternal.h
new file mode 100644
index 0000000..bffd6b3
--- /dev/null
+++ b/src/rccexternal.h
@@ -0,0 +1,35 @@
+#ifndef _RCC_EXTERNAL_H
+#define _RCC_EXTERNAL_H
+
+#define RCC_EXTERNAL_TIMEOUT 1000000
+
+typedef enum rcc_external_module_t {
+ RCC_EXTERNAL_MODULE_CONTROL = 0,
+ RCC_EXTERNAL_MODULE_LIBRTRANSLATE,
+ RCC_EXTERNAL_MODULE_MAX
+} rcc_external_module;
+
+struct rcc_external_info_t {
+ int s;
+};
+typedef struct rcc_external_info_t rcc_external_info_s;
+typedef struct rcc_external_info_t *rcc_external_info;
+
+struct rcc_external_command_t {
+ unsigned long size;
+ unsigned char cmd;
+};
+typedef struct rcc_external_command_t rcc_external_command_s;
+typedef struct rcc_external_command_t *rcc_external_command;
+
+#define RCC_EXTERNAL_COMMAND_CLOSE 0
+
+int rccExternalInit();
+void rccExternalFree();
+
+size_t rccExternalWrite(int s, const char *buffer, ssize_t size, unsigned long timeout);
+size_t rccExternalRead(int s, char *buffer, ssize_t size, unsigned long timeout);
+int rccExternalConnect(unsigned char module);
+void rccExternalClose(int s);
+
+#endif /* _RCC_EXTERNAL_H */
diff --git a/src/rcciconv.c b/src/rcciconv.c
index 65b32b3..d9903de 100644
--- a/src/rcciconv.c
+++ b/src/rcciconv.c
@@ -92,7 +92,28 @@ loop:
return outsize - out_left;
}
-size_t rccIConv(rcc_context ctx, rcc_iconv icnv, const char *buf, size_t len) {
+char *rccIConv(rcc_iconv icnv, const char *buf, size_t len, size_t *rlen) {
+ char *res;
+ size_t size;
+ char tmpbuffer[RCC_MAX_STRING_CHARS+1];
+
+ size = rccIConvRecode(icnv, tmpbuffer, RCC_MAX_STRING_CHARS, buf, len);
+ if (size != (size_t)-1) {
+ res = (char*)malloc((size+1)*sizeof(char));
+ if (!res) return res;
+
+ if (rlen) *rlen = size;
+ memcpy(res, tmpbuffer, size);
+ res[size] = 0;
+
+ return res;
+ }
+
+ return NULL;
+}
+
+size_t rccIConvInternal(rcc_context ctx, rcc_iconv icnv, const char *buf, size_t len) {
if (!ctx) return (size_t)-1;
return rccIConvRecode(icnv, ctx->tmpbuffer, RCC_MAX_STRING_CHARS, buf, len);
}
+
diff --git a/src/rcciconv.h b/src/rcciconv.h
index cc1d1b9..0070696 100644
--- a/src/rcciconv.h
+++ b/src/rcciconv.h
@@ -8,6 +8,18 @@ struct rcc_iconv_t {
};
typedef struct rcc_iconv_t rcc_iconv_s;
-size_t rccIConv(rcc_context ctx, rcc_iconv icnv, const char *buf, size_t len);
+size_t rccIConvInternal(rcc_context ctx, rcc_iconv icnv, const char *buf, size_t len);
+
+/**
+ * Recodes chunk of data.
+ *
+ * @param icnv is recoding context
+ * @param outbuf is preallocated output buffer
+ * @param outsize is size of output buffer (striped string will be returned if buffer to small)
+ * @param buf is data for recoding
+ * @param size is size of the data
+ * @return number of recoded bytes in output buffer or -1 in the case of error
+ */
+size_t rccIConvRecode(rcc_iconv icnv, char *outbuf, size_t outsize, const char *buf, size_t size);
#endif /* _RCC_ICONV_H */
diff --git a/src/rcctranslate.c b/src/rcctranslate.c
new file mode 100644
index 0000000..3bbd916
--- /dev/null
+++ b/src/rcctranslate.c
@@ -0,0 +1,151 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "internal.h"
+#include "rccexternal.h"
+#include "rcctranslate.h"
+
+
+
+int rccTranslateInit() {
+
+ return 0;
+}
+
+void rccTranslateFree() {
+}
+
+
+rcc_translate rccTranslateOpen(const char *from, const char *to) {
+#ifdef HAVE_LIBTRANSLATE
+ rcc_translate translate;
+
+ if ((!from)||(!to)||(!strcasecmp(from,to))) return NULL;
+ if ((strlen(from)!=2)||(strlen(to)!=2)) return NULL;
+
+ translate = (rcc_translate)malloc(sizeof(rcc_translate_s));
+ if (!translate) return NULL;
+
+ translate->sock = rccExternalConnect(RCC_EXTERNAL_MODULE_LIBRTRANSLATE);
+ if (translate->sock == -1) {
+ free(translate);
+ return NULL;
+ }
+
+ translate->remaining = 0;
+ translate->prefix.cmd.cmd = RCC_EXTERNAL_COMMAND_TRANSLATE;
+ translate->prefix.cmd.size = sizeof(rcc_translate_prefix_s);
+ memcpy(translate->prefix.from, from, 3*sizeof(char));
+ memcpy(translate->prefix.to, to, 3*sizeof(char));
+ rccTranslateSetTimeout(translate, RCC_TRANSLATE_DEFAULT_TIMEOUT);
+
+ return translate;
+#else
+ return NULL;
+#endif /* HAVE_LIBTRANSLATE */
+}
+
+void rccTranslateClose(rcc_translate translate) {
+#ifdef HAVE_LIBTRANSLATE
+ if (!translate) return;
+ if (translate->sock != -1) rccExternalClose(translate->sock);
+ free(translate);
+#endif /* HAVE_LIBTRANSLATE */
+}
+
+int rccTranslateSetTimeout(rcc_translate translate, unsigned long us) {
+#ifdef HAVE_LIBTRANSLATE_TIMED_TRANSLATE
+ if (!translate) return -1;
+ translate->prefix.timeout = us;
+ return 0;
+#else
+ return -1;
+#endif /* HAVE_LIBTRANSLATE_TIMED_TRANSLATE */
+}
+
+char *rccTranslate(rcc_translate translate, const char *buf) {
+#ifdef HAVE_LIBTRANSLATE
+ size_t i;
+ rcc_external_command_s resp;
+ size_t err, len;
+ char *buffer;
+
+ if ((!translate)||(!buf)) return NULL;
+
+ if (!strcmp(translate->prefix.to, "en")) {
+ for (i=0;buf[i];i++)
+ if ((unsigned char)buf[i]>0x7F) break;
+ if (!buf[i]) return NULL;
+ }
+
+ if (translate->sock == -1) {
+ translate->sock = rccExternalConnect(RCC_EXTERNAL_MODULE_LIBRTRANSLATE);
+ if (translate->sock == -1) return NULL;
+ } else if (translate->remaining) {
+ if (translate->remaining == (size_t)-1) {
+ err = rccExternalRead(translate->sock, (char*)&resp, sizeof(rcc_external_command_s), 0);
+ if (err) return NULL;
+ translate->remaining = resp.size;
+ }
+
+ buffer = (char*)malloc(translate->remaining*sizeof(char));
+ if (!buffer) {
+ rccExternalClose(translate->sock);
+ translate->sock = -1;
+ return NULL;
+ }
+ err = rccExternalRead(translate->sock, buffer, translate->remaining, 0);
+ free(buffer);
+ if (err) {
+ translate->remaining = err;
+ return NULL;
+ }
+ translate->remaining = 0;
+ }
+
+ len = strlen(buf);
+ translate->prefix.cmd.size = sizeof(rcc_translate_prefix_s) + len - sizeof(rcc_external_command_s);
+ err = rccExternalWrite(translate->sock, (char*)&translate->prefix, sizeof(rcc_translate_prefix_s) - 1, 0);
+ if (err) {
+ rccExternalClose(translate->sock);
+ translate->sock = -1;
+ return NULL;
+ }
+ err = rccExternalWrite(translate->sock, buf, len + 1, 0);
+ if (err) {
+ rccExternalClose(translate->sock);
+ translate->sock = -1;
+ return NULL;
+ }
+
+ err = rccExternalRead(translate->sock, (char*)&resp, sizeof(rcc_external_command_s), translate->prefix.timeout);
+ if (err) {
+ if (err == sizeof(rcc_external_command_s)) {
+ translate->remaining = (size_t)-1;
+ } else {
+ rccExternalClose(translate->sock);
+ translate->sock = -1;
+ }
+ return NULL;
+ }
+ if ((resp.cmd!=RCC_EXTERNAL_COMMAND_TRANSLATE)||(!resp.size)) return NULL;
+
+ buffer = (char*)malloc(resp.size*sizeof(char));
+ if (!buffer) {
+ rccExternalClose(translate->sock);
+ translate->sock = -1;
+ return NULL;
+ }
+ err = rccExternalRead(translate->sock, buffer, resp.size, 0);
+ if (err) {
+ translate->remaining = err;
+ free(buffer);
+ return NULL;
+ }
+
+ return buffer;
+#else
+ return NULL;
+#endif /* HAVE_LIBTRANSLATE */
+}
diff --git a/src/rcctranslate.h b/src/rcctranslate.h
new file mode 100644
index 0000000..961af6f
--- /dev/null
+++ b/src/rcctranslate.h
@@ -0,0 +1,31 @@
+#ifndef _RCC_TRANSLATE_H
+#define _RCC_TRANSLATE_H
+
+#include "rccexternal.h"
+#define RCC_TRANSLATE_DEFAULT_TIMEOUT 5000000 /* 5s */
+#define RCC_EXTERNAL_COMMAND_TRANSLATE 0x80
+
+
+struct rcc_translate_prefix_t {
+ rcc_external_command_s cmd;
+ unsigned long timeout;
+ char from[3];
+ char to[3];
+ char text[1];
+};
+typedef struct rcc_translate_prefix_t rcc_translate_prefix_s;
+typedef struct rcc_translate_prefix_t *rcc_translate_prefix;
+
+
+struct rcc_translate_t {
+ rcc_translate_prefix_s prefix;
+ size_t remaining;
+ int sock;
+};
+typedef struct rcc_translate_t rcc_translate_s;
+
+
+int rccTranslateInit();
+void rccTranslateFree();
+
+#endif /* _RCC_TRANSLATE_H */
diff --git a/src/recode.c b/src/recode.c
index a1b7f31..c44095c 100644
--- a/src/recode.c
+++ b/src/recode.c
@@ -9,6 +9,7 @@
#include "rccstring.h"
#include "rccconfig.h"
#include "rccdb4.h"
+#include "rcctranslate.h"
@@ -37,6 +38,7 @@ rcc_string rccSizedFrom(rcc_context ctx, rcc_class_id class_id, const char *buf,
rcc_iconv icnv = NULL;
rcc_string result;
rcc_option_value usedb4;
+ const char *charset;
if (!ctx) {
if (rcc_default_ctx) ctx = rcc_default_ctx;
@@ -66,11 +68,17 @@ rcc_string rccSizedFrom(rcc_context ctx, rcc_class_id class_id, const char *buf,
if (err) return NULL;
charset_id = rccIConvAuto(ctx, class_id, buf, len);
- if (charset_id != (rcc_autocharset_id)-1) icnv = ctx->iconv_auto[charset_id];
+ if (charset_id != (rcc_autocharset_id)-1) {
+ icnv = ctx->iconv_auto[charset_id];
+ if (rccGetOption(ctx, RCC_OPTION_AUTOENGINE_SET_CURRENT)) {
+ charset = rccGetAutoCharsetName(ctx, charset_id);
+ rccSetCharsetByName(ctx, class_id, charset);
+ }
+ }
else icnv = ctx->iconv_from[class_id];
if (icnv) {
- ret = rccIConv(ctx, icnv, buf, len);
+ ret = rccIConvInternal(ctx, icnv, buf, len);
if (ret == (size_t)-1) return NULL;
result = rccCreateString(language_id, ctx->tmpbuffer, ret);
} else {
@@ -92,8 +100,10 @@ char *rccSizedTo(rcc_context ctx, rcc_class_id class_id, rcc_const_string buf, s
char *result;
char *prefix, *name;
const char *utfstring;
+ char *translated = NULL;
rcc_language_config config;
rcc_language_id language_id;
+ rcc_language_id current_language_id;
rcc_class_type class_type;
rcc_iconv icnv;
@@ -117,6 +127,38 @@ char *rccSizedTo(rcc_context ctx, rcc_class_id class_id, rcc_const_string buf, s
if (err) return NULL;
class_type = rccGetClassType(ctx, class_id);
+ if ((class_type != RCC_CLASS_FS)&&(rccGetOption(ctx, RCC_OPTION_TRANSLATE))) {
+ current_language_id = rccGetCurrentLanguage(ctx);
+ if (current_language_id != language_id) {
+ if ((config->trans)&&(config->translang != current_language_id)) {
+ rccTranslateClose(config->trans);
+ config->trans = NULL;
+ }
+ if (!config->trans) {
+ config->trans = rccTranslateOpen(rccGetLanguageName(ctx, language_id), rccGetLanguageName(ctx, current_language_id));
+ config->translang = current_language_id;
+ }
+ if (config->trans) {
+ translated = rccTranslate(config->trans, utfstring);
+ if (translated) {
+ language_id = current_language_id;
+
+ config = rccGetConfig(ctx, language_id);
+ if (!config) {
+ free(translated);
+ return NULL;
+ }
+
+ err = rccConfigConfigure(config);
+ if (err) {
+ free(translated);
+ return NULL;
+ }
+ }
+ }
+ }
+ }
+
if ((class_type == RCC_CLASS_FS)&&(rccGetOption(ctx, RCC_OPTION_AUTODETECT_FS_NAMES))) {
if (rccIsASCII(utfstring)) {
result = rccStringExtractString(buf);
@@ -141,14 +183,20 @@ char *rccSizedTo(rcc_context ctx, rcc_class_id class_id, rcc_const_string buf, s
icnv = config->iconv_to[class_id];
if (icnv) {
- newlen = rccIConv(ctx, icnv, rccStringGetString((const char*)buf), newlen);
+ newlen = rccIConvInternal(ctx, icnv, translated?translated:utfstring, newlen);
+ if (translated) free(translated);
if (newlen == (size_t)-1) return NULL;
result = rccCreateResult(ctx, newlen);
if (rlen) *rlen = newlen;
} else {
- result = rccStringExtractString(buf);
- if (rlen) *rlen = newlen;
+ if (translated) {
+ result = translated;
+ if (rlen) *rlen = strlen(result);
+ } else {
+ result = rccStringExtractString(buf);
+ if (rlen) *rlen = newlen;
+ }
}
return result;
@@ -274,7 +322,7 @@ rcc_string rccSizedFromCharset(rcc_context ctx, const char *charset, const char
icnv = rccIConvOpen("UTF-8", charset);
if (icnv) {
- res = rccIConv(ctx, icnv, buf, len);
+ res = rccIConvInternal(ctx, icnv, buf, len);
rccIConvClose(icnv);
if (res == (size_t)-1) return NULL;
return rccCreateString(language_id, ctx->tmpbuffer, res);
@@ -293,7 +341,7 @@ char *rccSizedToCharset(rcc_context ctx, const char *charset, rcc_const_string b
icnv = rccIConvOpen(charset, "UTF-8");
if (icnv) {
- res = rccIConv(ctx, icnv, rccStringGetString(buf), res);
+ res = rccIConvInternal(ctx, icnv, rccStringGetString(buf), res);
rccIConvClose(icnv);
if (res == (size_t)-1) return NULL;
@@ -321,7 +369,7 @@ char *rccSizedRecodeToCharset(rcc_context ctx, rcc_class_id class_id, const char
icnv = rccIConvOpen(charset, "UTF-8");
if (icnv) {
- res = rccIConv(ctx, icnv, str, 0);
+ res = rccIConvInternal(ctx, icnv, str, 0);
rccIConvClose(icnv);
free(utf8);
@@ -349,7 +397,7 @@ char *rccSizedRecodeFromCharset(rcc_context ctx, rcc_class_id class_id, const ch
icnv = rccIConvOpen("UTF-8", charset);
if (icnv) {
- res = rccIConv(ctx, icnv, buf, len);
+ res = rccIConvInternal(ctx, icnv, buf, len);
rccIConvClose(icnv);
if (res == (size_t)-1) return NULL;
@@ -373,7 +421,7 @@ char *rccSizedRecodeCharsets(rcc_context ctx, const char *from, const char *to,
icnv = rccIConvOpen(to, from);
if (!icnv) return NULL;
- res = rccIConv(ctx, icnv, buf, len);
+ res = rccIConvInternal(ctx, icnv, buf, len);
rccIConvClose(icnv);
if (res == (size_t)-1) return NULL;