summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/rcc.xml32
-rw-r--r--src/Makefile.am2
-rw-r--r--src/librcc.h62
-rw-r--r--src/lngconfig.c5
-rw-r--r--src/opt.c102
-rw-r--r--src/opt.h27
-rw-r--r--src/rccconfig.c103
-rw-r--r--src/rccconfig.h7
-rw-r--r--src/rcciconv.c66
-rw-r--r--src/rcciconv.h5
-rw-r--r--src/rcclocale.c8
-rw-r--r--src/rccxml.c58
-rw-r--r--src/recode.c8
-rw-r--r--ui/Makefile.am5
-rw-r--r--ui/gtk.c64
-rw-r--r--ui/internal.h29
-rw-r--r--ui/librccui.c301
-rw-r--r--ui/librccui.h28
-rw-r--r--ui/rccmenu.c89
-rw-r--r--ui/rccmenu.h55
-rw-r--r--ui/rccnames.c107
-rw-r--r--ui/rccnames.h6
22 files changed, 912 insertions, 257 deletions
diff --git a/examples/rcc.xml b/examples/rcc.xml
index b991a5c..60f363c 100644
--- a/examples/rcc.xml
+++ b/examples/rcc.xml
@@ -1,12 +1,22 @@
<?xml version='1.0' encoding='UTF-8' ?>
-<Languages>
- <Language name="ja">
- <FullName>Japanese</FullName>
- <Charsets>
- <Charset>UTF-8</Charset>
- <Charset>ISO-2022-JP</Charset>
- <Charset>EUC-JP</Charset>
- <Charset>SHIFT-JIS</Charset>
- </Charsets>
- </Language>
-</Languages>
+<LibRCC>
+ <Languages>
+ <Language name="ja">
+ <FullName>Japanese</FullName>
+ <Charsets>
+ <Charset>UTF-8</Charset>
+ <Charset>ISO-2022-JP</Charset>
+ <Charset>EUC-JP</Charset>
+ <Charset>SHIFT-JIS</Charset>
+ </Charsets>
+ </Language>
+ </Languages>
+ <Options>
+ <Option name="LEARNING_MODE">
+ <FullName>L. M.</FullName>
+ <Value name="OFF">
+ <FullName>Dissable</FullName>
+ </Value>
+ </Option>
+ </Options>
+</LibRCC> \ No newline at end of file
diff --git a/src/Makefile.am b/src/Makefile.am
index 022ef1b..1565f1a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -20,7 +20,7 @@ librcc_la_SOURCES = librcc.c \
internal.h
include_HEADERS = librcc.h
-INCLUDES = @XML_INCLUDES@ @DLOPEN_INCLUDES@ @RCD_INCLUDES@ @ENCA_INCLUDES@ @BDB_INCLUDES@
+INCLUDES = -I../src @XML_INCLUDES@ @DLOPEN_INCLUDES@ @RCD_INCLUDES@ @ENCA_INCLUDES@ @BDB_INCLUDES@
librcc_la_LIBADD = @XML_LIBS@ @DLOPEN_LIBS@ @RCD_LIBS@ @ENCA_LIBS@ @BDB_LIBS@
librcc_la_LDFLAGS = -version-info @LIBRCC_VERSION_INFO@
diff --git a/src/librcc.h b/src/librcc.h
index e6fe7bc..87f09ec 100644
--- a/src/librcc.h
+++ b/src/librcc.h
@@ -96,12 +96,6 @@ typedef struct rcc_language_alias_t rcc_language_alias;
typedef rcc_language_alias *rcc_language_alias_ptr;
typedef rcc_language_alias_ptr rcc_language_alias_list[RCC_MAX_ALIASES+1];
-struct rcc_language_name_t {
- const char *sn;
- const char *name;
-};
-typedef struct rcc_language_name_t rcc_language_name;
-
rcc_language_id rccRegisterLanguage(rcc_context ctx, rcc_language *language);
rcc_charset_id rccLanguageRegisterCharset(rcc_language *language, rcc_charset charset);
rcc_engine_id rccLanguageRegisterEngine(rcc_language *language, rcc_engine *engine);
@@ -126,7 +120,7 @@ typedef const struct rcc_class_default_charset_t rcc_class_default_charset;
struct rcc_class_t {
const char *name;
const rcc_class_type class_type;
- const char *defvalue; /* locale variable name or parrent name */
+ const char *defvalue; /* locale variable name or parrent name or multibyte charset */
rcc_class_default_charset *defcharset;
const char *fullname;
};
@@ -140,6 +134,7 @@ rcc_class_type rccGetClassType(rcc_context ctx, rcc_class_id class_id);
************************ Altering Configuaration *******************************
*******************************************************************************/
typedef int rcc_option_value;
+
typedef enum rcc_option_t {
RCC_LEARNING_MODE = 0,
RCC_AUTODETECT_FS_TITLES,
@@ -148,13 +143,27 @@ typedef enum rcc_option_t {
RCC_MAX_OPTIONS
} rcc_option;
-struct rcc_option_name_t {
- rcc_option option;
- const char *name;
-
- const char **subnames;
+typedef enum rcc_option_type_t {
+ RCC_OPTION_TYPE_INVISIBLE = 0,
+ RCC_OPTION_TYPE_STANDARD,
+ RCC_OPTION_TYPE_MAX
+} rcc_option_type;
+
+typedef enum rcc_option_range_type_t {
+ RCC_OPTION_RANGE_TYPE_BOOLEAN = 0,
+ RCC_OPTION_RANGE_TYPE_RANGE,
+ RCC_OPTION_RANGE_TYPE_FLAGS,
+ RCC_OPTION_RANGE_TYPE_MENU,
+ RCC_OPTION_RANGE_TYPE_MAX
+} rcc_option_range_type;
+
+struct rcc_option_range_t {
+ rcc_option_range_type type;
+ rcc_option_value min;
+ rcc_option_value max;
+ rcc_option_value step;
};
-typedef struct rcc_option_name_t rcc_option_name;
+typedef struct rcc_option_range_t rcc_option_range;
/* lng.c */
const char *rccGetLanguageName(rcc_context ctx, rcc_language_id language_id);
@@ -174,6 +183,13 @@ rcc_option_value rccGetOption(rcc_context ctx, rcc_option option);
int rccOptionIsDefault(rcc_context ctx, rcc_option option);
int rccOptionSetDefault(rcc_context ctx, rcc_option option);
int rccSetOption(rcc_context ctx, rcc_option option, rcc_option_value value);
+rcc_option_type rccOptionGetType(rcc_context ctx, rcc_option option);
+rcc_option_range *rccOptionGetRange(rcc_context ctx, rcc_option option);
+
+const char *rccGetOptionName(rcc_option option);
+const char *rccGetOptionValueName(rcc_option option, rcc_option_value value);
+rcc_option rccGetOptionByName(const char *name);
+rcc_option_value rccGetOptionValueByName(rcc_option option, const char *name);
/* lngconfig.c */
@@ -243,17 +259,6 @@ rcc_charset *rccGetCurrentAutoCharsetList(rcc_context ctx);
rcc_class_ptr *rccGetClassList(rcc_context ctx);
/*******************************************************************************
-************************ Default Configuaration ********************************
-*******************************************************************************/
-
-/* rccconfig.c */
-const char *rccGetOptionName(rcc_option option);
-const char *rccGetOptionFullName(rcc_option option);
-rcc_option_value rccGetOptionDefaultValue(rcc_option option);
-const char *rccGetLanguageFullName(const char *lang);
-
-
-/*******************************************************************************
************************ RCC_STRING Manipulations ******************************
*******************************************************************************/
/* string.c */
@@ -277,6 +282,12 @@ int rccStringNCaseCmp(const char *str1, const char *str2, size_t n);
/*******************************************************************************
******************************** Recoding **************************************
*******************************************************************************/
+typedef struct rcc_iconv_t *rcc_iconv;
+
+/* rcciconv.c */
+rcc_iconv rccIConvOpen(const char *from, const char *to);
+void rccIConvClose(rcc_iconv icnv);
+size_t rccIConvRecode(rcc_iconv icnv, char *outbuf, size_t outsize, const char *buf, size_t size);
/* recode.c */
rcc_string rccFrom(rcc_context ctx, rcc_class_id class_id, const char *buf, size_t len, size_t *rlen);
@@ -289,6 +300,9 @@ char *rccFS(rcc_context ctx, rcc_class_id from, rcc_class_id to, const char *fsp
*******************************************************************************/
/* xml.c */
+typedef void *rcc_config;
+
+rcc_config rccGetConfiguration();
int rccSave(rcc_context ctx, const char *name);
int rccLoad(rcc_context ctx, const char *name);
diff --git a/src/lngconfig.c b/src/lngconfig.c
index 39fca76..4ac16c1 100644
--- a/src/lngconfig.c
+++ b/src/lngconfig.c
@@ -311,6 +311,11 @@ rcc_charset_id rccConfigGetCurrentCharset(rcc_language_config config, rcc_class_
charset_id = rccConfigGetLocaleCharset(config, defvalue);
if ((charset_id != 0)&&(charset_id != (rcc_charset_id)-1)) return charset_id;
+ if (cl->defvalue) {
+ charset_id = rccConfigGetCharsetByName(config, defvalue);
+ if ((charset_id != 0)&&(charset_id != (rcc_charset_id)-1)) return charset_id;
+ }
+
defcharset = cl->defcharset;
if (defcharset) {
lang = config->language->sn;
diff --git a/src/opt.c b/src/opt.c
index 040bea4..c14240c 100644
--- a/src/opt.c
+++ b/src/opt.c
@@ -1,5 +1,6 @@
#include <stdio.h>
+#include "rccconfig.h"
#include "internal.h"
#include "opt.h"
@@ -24,12 +25,27 @@ int rccOptionIsDefault(rcc_context ctx, rcc_option option) {
}
int rccSetOption(rcc_context ctx, rcc_option option, rcc_option_value value) {
+ rcc_option_description *desc;
+ rcc_option_value min, max;
+
+
if (!ctx) {
if (rcc_default_ctx) ctx = rcc_default_ctx;
else return -1;
}
if ((option<0)||(option>=RCC_MAX_OPTIONS)) return -1;
-
+
+
+ desc = rccGetOptionDescription(option);
+ if (desc) {
+ // DS: More checks for different range types
+ min = desc->range.min;
+ max = desc->range.max;
+ if ((min)&&(min!=max)) {
+ if ((option<min)||(option>max)) return -1;
+ }
+ }
+
ctx->default_options[option] = 0;
if (ctx->options[option] != value) {
@@ -41,6 +57,7 @@ int rccSetOption(rcc_context ctx, rcc_option option, rcc_option_value value) {
}
int rccOptionSetDefault(rcc_context ctx, rcc_option option) {
+ rcc_option_description *desc;
rcc_option_value value;
if (!ctx) {
@@ -50,7 +67,10 @@ int rccOptionSetDefault(rcc_context ctx, rcc_option option) {
if ((option<0)||(option>=RCC_MAX_OPTIONS)) return -1;
ctx->default_options[option] = 1;
- value = rccGetOptionDefaultValue(option);
+
+ desc = rccGetOptionDescription(option);
+ if (desc) value = desc->value;
+ else value = 0;
if (ctx->options[option] != value) {
ctx->configure = 1;
@@ -59,3 +79,81 @@ int rccOptionSetDefault(rcc_context ctx, rcc_option option) {
return 0;
}
+
+rcc_option_type rccOptionGetType(rcc_context ctx, rcc_option option) {
+ rcc_option_description *desc;
+
+ desc = rccGetOptionDescription(option);
+ if (desc) return desc->type;
+ return 0;
+}
+
+rcc_option_range *rccOptionGetRange(rcc_context ctx, rcc_option option) {
+ rcc_option_description *desc;
+
+ desc = rccGetOptionDescription(option);
+ if (desc) return &desc->range;
+ return 0;
+}
+
+const char *rccOptionDescriptionGetName(rcc_option_description *desc) {
+ if (desc) return desc->sn;
+ return NULL;
+}
+
+rcc_option rccOptionDescriptionGetOption(rcc_option_description *desc) {
+ if (desc) return desc->option;
+ return (rcc_option)-1;
+}
+
+const char *rccOptionDescriptionGetValueName(rcc_option_description *desc, rcc_option_value value) {
+ unsigned int i;
+
+ if (desc) {
+ for (i=0;desc->vsn[i];i++) {
+ if (i == value) return desc->vsn[i];
+ }
+ }
+ return NULL;
+}
+
+rcc_option_value rccOptionDescriptionGetValueByName(rcc_option_description *desc, const char *name) {
+ unsigned int i;
+
+ if ((desc)&&(name)) {
+ for (i=0;desc->vsn[i];i++) {
+ if (!strcasecmp(desc->vsn[i], name)) return (rcc_option_value)i;
+ }
+ }
+
+ return (rcc_option_value)-1;
+}
+
+
+const char *rccGetOptionName(rcc_option option) {
+ rcc_option_description *desc;
+
+ desc = rccGetOptionDescription(option);
+ return rccOptionDescriptionGetName(desc);
+}
+
+const char *rccGetOptionValueName(rcc_option option, rcc_option_value value) {
+ rcc_option_description *desc;
+
+ desc = rccGetOptionDescription(option);
+ return rccOptionDescriptionGetValueName(desc, value);
+}
+
+rcc_option rccGetOptionByName(const char *name) {
+ rcc_option_description *desc;
+
+ desc = rccGetOptionDescriptionByName(name);
+ return rccOptionDescriptionGetOption(desc);
+}
+
+rcc_option_value rccGetOptionValueByName(rcc_option option, const char *name) {
+ rcc_option_description *desc;
+
+ desc = rccGetOptionDescription(option);
+ return rccOptionDescriptionGetValueByName(desc, name);
+}
diff --git a/src/opt.h b/src/opt.h
index 297c679..322c25c 100644
--- a/src/opt.h
+++ b/src/opt.h
@@ -1,30 +1,25 @@
#ifndef _RCC_OPT_H
#define _RCC_OPT_H
-struct rcc_option_defval_t {
- rcc_option option;
- rcc_option_value value;
-};
-typedef struct rcc_option_defval_t rcc_option_defval;
+#include "internal.h"
-enum rcc_option_type_t {
- RCC_OPTION_TYPE_BOOLEAN = 0,
- RCC_OPTION_TYPE_RANGE,
- RCC_OPTION_TYPE_FLAGS,
- RCC_OPTION_TYPE_MENU,
- RCC_OPTION_TYPE_MAX
-};
-typedef enum rcc_option_type_t rcc_option_type;
+typedef const char *rcc_option_value_name;
+typedef const rcc_option_value_name *rcc_option_value_names;
struct rcc_option_description_t {
rcc_option option;
+ rcc_option_value value;
+ rcc_option_range range;
+ rcc_option_type type;
const char *sn;
- rcc_option_type;
- rcc_option_value min;
- rcc_option_value max;
+ rcc_option_value_names vsn;
};
typedef struct rcc_option_description_t rcc_option_description;
+const char *rccOptionDescriptionGetName(rcc_option_description *desc);
+rcc_option rccOptionDescriptionGetOption(rcc_option_description *desc);
+const char *rccOptionDescriptionGetValueName(rcc_option_description *desc, rcc_option_value value);
+rcc_option_value rccOptionDescriptionGetValueByName(rcc_option_description *desc, const char *name);
#endif /* _RCC_OPT_H */
diff --git a/src/rccconfig.c b/src/rccconfig.c
index 10ddf3f..100a7fc 100644
--- a/src/rccconfig.c
+++ b/src/rccconfig.c
@@ -11,8 +11,8 @@ rcc_language_alias rcc_default_aliases[] = {
{ NULL, NULL}
};
-const char rcc_engine_nonconfigured[] = "default";
-const char rcc_option_nonconfigured[] = "default";
+const char rcc_engine_nonconfigured[] = "Default";
+const char rcc_option_nonconfigured[] = "DEFAULT";
rcc_engine rcc_default_engine = {
"Off", NULL, NULL, NULL, {NULL}
@@ -96,103 +96,36 @@ rcc_language rcc_default_languages[RCC_MAX_LANGUAGES + 1] = {
{NULL}
};
-rcc_language_name rcc_default_language_names[RCC_MAX_LANGUAGES+1] = {
-{"default", "Autodetect"},
-{"off", "Dissable"},
-{"ru","Russian"},
-{"uk","Ukrainian"},
-{"be","Belarussian"},
-{"bg","Bulgarian"},
-{"cz","Czech"},
-{"es","Estonian"},
-{"hr","Croatian"},
-{"hu","Hungarian"},
-{"lt","Lithuanian"},
-{"lv","Latvian"},
-{"pl","Polish"},
-{"sk","Slovak"},
-{"sl","Slovenian"},
-{"zh","Chinese"},
-{NULL, NULL}
-};
-
-rcc_option_description rcc_default_option_descriptions[] = {
- {RCC_LEARNING_MODE, "LEARNING_MODE", RCC_OPTION_TYPE_MENU, 0, 3},
- {RCC_AUTODETECT_FS_NAMES, "AUTODETECT_FS_NAMES", RCC_OPTION_TYPE_BOOLEAN, 0, 0},
- {RCC_AUTODETECT_FS_TITLES, "AUTODETECT_FS_TITLES", RCC_OPTION_TYPE_BOOLEAN, 0, 0},
- {RCC_CONFIGURED_LANGUAGES_ONLY, "CONFIGURED_LANGUAGES_ONLY", RCC_OPTION_MENU, 0, 2},
- {RCC_MAX_OPTIONS, NULL}
-};
-
-
-rcc_option_name rcc_default_option_names[] = {
- { RCC_LEARNING_MODE, "Learning Mode", },
- { RCC_AUTODETECT_FS_NAMES, "Autodetect File Names", NULL},
- { RCC_AUTODETECT_FS_TITLES, NULL, NULL},
- { RCC_CONFIGURED_LANGUAGES_ONLY, NULL, NULL},
- { RCC_MAX_OPTIONS, NULL, NULL}
-};
+rcc_option_value_name rcc_sn_boolean[] = { "OFF", "ON", NULL };
+rcc_option_value_name rcc_sn_learning[] = { "OFF", "ON", "RELEARN", "LEARN", NULL };
+rcc_option_value_name rcc_sn_clo[] = { "ALL", "CONFIGURED_AND_AUTO", "CONFIGURED_ONLY", NULL };
-rcc_option_defval rcc_default_option_values[] = {
- { RCC_LEARNING_MODE, 0 },
- { RCC_AUTODETECT_FS_TITLES, 1},
- { RCC_AUTODETECT_FS_NAMES, 1},
- { RCC_CONFIGURED_LANGUAGES_ONLY, 1},
- { RCC_MAX_OPTIONS, 0}
+rcc_option_description rcc_option_descriptions[] = {
+ {RCC_LEARNING_MODE, 0, { RCC_OPTION_RANGE_TYPE_MENU, 0, 3, 1 }, RCC_OPTION_TYPE_STANDARD, "LEARNING_MODE", rcc_sn_learning },
+ {RCC_AUTODETECT_FS_NAMES, 1, { RCC_OPTION_RANGE_TYPE_BOOLEAN, 0, 0, 0}, RCC_OPTION_TYPE_STANDARD, "AUTODETECT_FS_NAMES", rcc_sn_boolean},
+ {RCC_AUTODETECT_FS_TITLES, 1, { RCC_OPTION_RANGE_TYPE_BOOLEAN, 0, 0, 0}, RCC_OPTION_TYPE_INVISIBLE, "AUTODETECT_FS_TITLES", rcc_sn_boolean},
+ {RCC_CONFIGURED_LANGUAGES_ONLY, 0, { RCC_OPTION_RANGE_TYPE_MENU, 0, 2, 1}, RCC_OPTION_TYPE_INVISIBLE, "CONFIGURED_LANGUAGES_ONLY", rcc_sn_clo},
+ {RCC_MAX_OPTIONS}
};
-const char *rccGetLanguageFullName(const char *lang) {
+rcc_option_description *rccGetOptionDescription(rcc_option option) {
unsigned int i;
- rcc_language_name *names;
-
- if (!lang) return NULL;
-
- names = rcc_default_language_names;
-
- for (i=0;names[i].sn;i++)
- if (!strcmp(lang, names[i].sn)) return names[i].name;
-
- return NULL;
-}
-const char *rccGetOptionName(rcc_option option) {
- unsigned int i;
- rcc_option_name *names;
-
if ((option<0)||(option>=RCC_MAX_OPTIONS)) return NULL;
- names = rcc_default_option_names;
-
- for (i=0;names[i].option!=RCC_MAX_OPTIONS;i++)
- if (names[i].option == option) return names[i].sn;
+ for (i=0;rcc_option_descriptions[i].option!=RCC_MAX_OPTIONS;i++)
+ if (rcc_option_descriptions[i].option == option) return rcc_option_descriptions+i;
return NULL;
}
-const char *rccGetOptionFullName(rcc_option option) {
+rcc_option_description *rccGetOptionDescriptionByName(const char *name) {
unsigned int i;
- rcc_option_name *names;
-
- if ((option<0)||(option>=RCC_MAX_OPTIONS)) return NULL;
- names = rcc_default_option_names;
+ if (!name) return NULL;
- for (i=0;names[i].option!=RCC_MAX_OPTIONS;i++)
- if (names[i].option == option) return names[i].name;
+ for (i=0;rcc_option_descriptions[i].option!=RCC_MAX_OPTIONS;i++)
+ if (!strcasecmp(rcc_option_descriptions[i].sn,name)) return rcc_option_descriptions+i;
return NULL;
}
-
-rcc_option_value rccGetOptionDefaultValue(rcc_option option) {
- unsigned int i;
- rcc_option_defval *values;
-
- if ((option<0)||(option>=RCC_MAX_OPTIONS)) return 0;
-
- values = rcc_default_option_values;
-
- for (i=0;values[i].option!=RCC_MAX_OPTIONS;i++)
- if (values[i].option == option) return values[i].value;
-
- return 0;
-}
diff --git a/src/rccconfig.h b/src/rccconfig.h
index 89bbac8..fa644cc 100644
--- a/src/rccconfig.h
+++ b/src/rccconfig.h
@@ -1,6 +1,7 @@
#ifndef _RCC_CONFIG_H
#define _RCC_CONFIG_H
#include "librcc.h"
+#include "opt.h"
#undef RCC_DEBUG
#define RCC_LOCALE_VARIABLE "LC_CTYPE"
@@ -15,7 +16,9 @@ extern rcc_engine rcc_russian_engine;
extern rcc_language rcc_default_languages[];
-extern rcc_language_name rcc_default_language_names[];
-extern rcc_option_name rcc_default_option_names[];
+extern rcc_option_description rcc_option_descriptions[];
+
+rcc_option_description *rccGetOptionDescription(rcc_option option);
+rcc_option_description *rccGetOptionDescriptionByName(const char *name);
#endif /* _RCC_CONFIG_H */
diff --git a/src/rcciconv.c b/src/rcciconv.c
index aaf655f..0fb440f 100644
--- a/src/rcciconv.c
+++ b/src/rcciconv.c
@@ -28,6 +28,72 @@ static int rccIConvUTFBytes(unsigned char c) {
return 6-j;
}
+
+rcc_iconv rccIConvOpen(const char *to, const char *from) {
+ rcc_iconv icnv;
+
+ if ((!from)||(!to)||(!strcasecmp(from,to))) return NULL;
+
+ icnv = (rcc_iconv)malloc(sizeof(rcc_iconv_s));
+ if (!icnv) return icnv;
+
+ icnv->icnv = iconv_open(to, from);
+ return icnv;
+}
+
+void rccIConvClose(rcc_iconv icnv) {
+ if (icnv) {
+ if (icnv->icnv != (iconv_t)-1) iconv_close(icnv->icnv);
+ free(icnv);
+ }
+}
+
+size_t rccIConvRecode(rcc_iconv icnv, char *outbuf, size_t outsize, const char *buf, size_t size) {
+ char *in_buf, *out_buf, *res, err;
+ int in_left, out_left, olen;
+ int ub, utf_mode=0;
+ int errors=0;
+
+ if ((!buf)||(!outbuf)||(!outsize)||(!icnv)||(icnv->icnv == (iconv_t)-1)) return (size_t)-1;
+ if (iconv(icnv->icnv, NULL, NULL, NULL, NULL) == -1) return (size_t)-1;
+
+ size = STRNLEN(buf,size);
+
+loop_restart:
+ errors = 0;
+ in_buf = (char*)buf; /*DS*/
+ in_left = size;
+ out_buf = outbuf;
+ out_left = outsize;
+
+loop:
+ err=iconv(icnv->icnv, &in_buf, &in_left, &out_buf, &out_left);
+ if (err<0) {
+ if (errno==E2BIG) {
+ *(int*)(outbuf+(RCC_MAX_STRING_CHARS-sizeof(int)))=0;
+ } else if (errno==EILSEQ) {
+ if (errors++<RCC_MAX_ERRORS) {
+ for (ub=utf_mode?rccIConvUTFBytes(*in_buf):1;ub>0;ub--)
+ rccIConvCopySymbol(&in_buf, &in_left, &out_buf, &out_left);
+ if (in_left>0) goto loop;
+ } else if (!utf_mode) {
+ utf_mode = 1;
+ goto loop_restart;
+ } else {
+ return (size_t)-1;
+ }
+ } else {
+ return (size_t)-1;
+ }
+ }
+
+ outbuf[outsize - out_left] = 0;
+
+ return outsize - out_left;
+}
+
+
+
size_t rccIConv(rcc_context ctx, iconv_t icnv, const char *buf, size_t len) {
char *in_buf, *out_buf, *res, err;
int in_left, out_left, olen;
diff --git a/src/rcciconv.h b/src/rcciconv.h
index fd72486..4a8fc78 100644
--- a/src/rcciconv.h
+++ b/src/rcciconv.h
@@ -1,6 +1,11 @@
#ifndef _RCC_ICONV_H
#define _RCC_ICONV_H
+struct rcc_iconv_t {
+ iconv_t icnv;
+};
+typedef struct rcc_iconv_t rcc_iconv_s;
+
size_t rccIConv(rcc_context ctx, iconv_t icnv, const char *buf, size_t len);
#endif /* _RCC_ICONV_H */
diff --git a/src/rcclocale.c b/src/rcclocale.c
index 084efa2..3e5b56e 100644
--- a/src/rcclocale.c
+++ b/src/rcclocale.c
@@ -3,6 +3,8 @@
#include <string.h>
#include <locale.h>
+#include "../config.h"
+
#ifdef HAVE_CODESET
# include <langinfo.h>
#endif
@@ -10,6 +12,8 @@
#include "rccconfig.h"
static int rccLocaleGetClassByName(const char *locale) {
+ if (!locale) return LC_CTYPE;
+
if (!strcmp(locale, "LC_CTYPE")) return LC_CTYPE;
if (!strcmp(locale, "LC_MESSAGES")) return LC_MESSAGES;
if (!strcmp(locale, "LC_COLLATE")) return LC_COLLATE;
@@ -32,7 +36,7 @@ int rccLocaleGetLanguage(char *result, const char *lv, unsigned int n) {
int locale_class;
const char *l;
- if (!lv) return -1;
+ if ((!result)||(!n)) return -1;
locale_class = rccLocaleGetClassByName(lv);
if (locale_class >= 0) {
@@ -63,7 +67,7 @@ int rccLocaleGetCharset(char *result, const char *lv, unsigned int n) {
int locale_class;
char *l;
- if (!lv) return -1;
+ if ((!result)||(!n)) return -1;
locale_class = rccLocaleGetClassByName(lv);
diff --git a/src/rccxml.c b/src/rccxml.c
index 7227dbd..7fc9430 100644
--- a/src/rccxml.c
+++ b/src/rccxml.c
@@ -19,6 +19,10 @@
static xmlDocPtr xmlctx = NULL;
+rcc_config rccGetConfiguration() {
+ return (rcc_config)xmlctx;
+}
+
static const char *rccXmlGetText(xmlNodePtr node) {
if ((node)&&(node->children)&&(node->children->type == XML_TEXT_NODE)&&(node->children->content)) return node->children->content;
}
@@ -34,7 +38,7 @@ int rccXmlInit() {
xmlNodePtr cnode, pnode, node;
xmlAttrPtr attr;
const char *lang, *fullname;
- unsigned int pos, cpos, npos;
+ unsigned int pos, cpos;
xmlInitParser();
xmlInitCharEncodingHandlers();
@@ -67,14 +71,11 @@ int rccXmlInit() {
if (!obj) goto clear;
node_set = obj->nodesetval;
- if (!node_set) return 0;
+ if (!node_set) goto clear;
for (pos = 0; rcc_default_languages[pos].sn; pos++);
if (pos == RCC_MAX_LANGUAGES) goto clear;
- for (npos = 0; rcc_default_language_names[npos].sn; npos++);
-
-
nnodes = node_set->nodeNr;
for (i=0;i<nnodes;i++) {
pnode = node_set->nodeTab[i];
@@ -83,7 +84,7 @@ int rccXmlInit() {
if ((!lang)||(!lang[0])) continue;
- for (cpos=1,fullname=NULL,node=pnode->children;node;node=node->next) {
+ for (cpos=1,node=pnode->children;node;node=node->next) {
if (node->type != XML_ELEMENT_NODE) continue;
if (!xmlStrcmp(node->name, "Charsets")) {
for (cpos = 0, cnode=node->children;cnode;cnode=cnode->next) {
@@ -92,9 +93,7 @@ int rccXmlInit() {
rcc_default_languages[pos].charsets[cpos++] = rccXmlGetText(cnode);
}
}
- } else if (!xmlStrcmp(node->name, "FullName")) {
- if (rccXmlGetText(node)) fullname = rccXmlGetText(node);
- }
+ }
}
if (cpos > 1) {
@@ -103,12 +102,6 @@ int rccXmlInit() {
rcc_default_languages[pos].charsets[cpos] = NULL;
rcc_default_languages[pos].engines[0] = &rcc_default_engine;
rcc_default_languages[pos].engines[1] = NULL;
- if ((fullname)&&(npos<RCC_MAX_LANGUAGES)) {
- rcc_default_language_names[npos].sn = lang;
- rcc_default_language_names[npos].name = fullname;
- rcc_default_language_names[++npos].sn = NULL;
- rcc_default_language_names[npos].name = NULL;
- }
rcc_default_languages[++pos].sn = NULL;
if (pos == RCC_MAX_LANGUAGES) break;
@@ -171,7 +164,7 @@ static xmlNodePtr rccNodeFind(xmlXPathContextPtr xpathctx, const char *request,
obj = xmlXPathEvalExpression(req, xpathctx);
if (obj) {
node_set = obj->nodesetval;
- if (node_set->nodeNr > 0) {
+ if ((node_set)&&(node_set->nodeNr > 0)) {
res = node_set->nodeTab[0];
}
xmlXPathFreeObject(obj);
@@ -210,7 +203,9 @@ int rccSave(rcc_context ctx, const char *name) {
xmlDocPtr doc = NULL;
xmlNodePtr pnode, lnode, onode, llnode, cnode, enode, node;
unsigned char oflag = 0, llflag = 0, cflag;
- const char *oname;
+ rcc_option_description *odesc;
+ rcc_option_value ovalue;
+ const char *oname, *ovname;
char value[16];
int memsize;
@@ -266,15 +261,24 @@ int rccSave(rcc_context ctx, const char *name) {
else onode = xmlNewChild(pnode, NULL, "Options", NULL);
for (i=0;i<RCC_MAX_OPTIONS;i++) {
- oname = rccGetOptionName(i);
+ odesc = rccGetOptionDescription(i);
+ if (!odesc) continue;
+
+ oname = rccOptionDescriptionGetName(odesc);
if (!oname) continue;
+
if (oflag) node = rccNodeFind(xpathctx, XPATH_SELECTED_OPTION, oname);
else node = NULL;
if (rccOptionIsDefault(ctx, (rcc_option)i)) strcpy(value, rcc_option_nonconfigured);
- else sprintf(value, "%i", rccGetOption(ctx, (rcc_option)i));
-
+ else {
+ ovalue = rccGetOption(ctx, (rcc_option)i);
+ ovname = rccOptionDescriptionGetValueName(odesc, ovalue);
+ if (ovname) strcpy(value, ovname);
+ else sprintf(value, "%i", ovalue);
+ }
+
if (node) xmlNodeSetContent(node, value);
else {
node = xmlNewChild(onode, NULL, "Option", value);
@@ -364,6 +368,9 @@ int rccLoad(rcc_context ctx, const char *name) {
unsigned int i, j, size;
const char *tmp;
+
+ rcc_option_description *odesc;
+ rcc_option_value ovalue;
const char *oname;
rcc_language_config cfg;
@@ -443,14 +450,21 @@ int rccLoad(rcc_context ctx, const char *name) {
if (err) rccSetLanguage(ctx, 0);
for (i=0;i<RCC_MAX_OPTIONS;i++) {
- oname = rccGetOptionName((rcc_option)i);
+ odesc = rccGetOptionDescription(i);
+ if (!odesc) continue;
+
+ oname = rccOptionDescriptionGetName(odesc);
if (!oname) continue;
node = rccNodeFind(xpathctx, XPATH_SELECTED_OPTION, oname);
if (!node) node = rccNodeFind(sysxpathctx, XPATH_SELECTED_OPTION, oname);
if (node) {
tmp = rccXmlGetText(node);
- if ((tmp)&&(strcasecmp(tmp,rcc_option_nonconfigured))) err = rccSetOption(ctx, (rcc_option)i, (rcc_option_value)atoi(tmp));
+ if ((tmp)&&(strcasecmp(tmp,rcc_option_nonconfigured))) {
+ ovalue = rccOptionDescriptionGetValueByName(odesc, tmp);
+ if (ovalue == (rcc_option_value)-1) ovalue = (rcc_option_value)atoi(tmp);
+ err = rccSetOption(ctx, (rcc_option)i, ovalue);
+ }
else err = -1;
} else err = -1;
if (err) rccOptionSetDefault(ctx, (rcc_option)i);
diff --git a/src/recode.c b/src/recode.c
index f071f33..9983992 100644
--- a/src/recode.c
+++ b/src/recode.c
@@ -44,11 +44,13 @@ rcc_string rccFrom(rcc_context ctx, rcc_class_id class_id, const char *buf, size
if ((class_id<0)||(class_id>=ctx->n_classes)||(!buf)) return NULL;
- string = rccDb4GetKey(ctx->db4ctx, buf, len);
- if (string) {
+/*
+ result = rccDb4GetKey(ctx->db4ctx, buf, len);
+ if (result) {
puts("Got a string");
- return string;
+ return result;
}
+*/
err = rccConfigure(ctx);
if (err) return NULL;
diff --git a/ui/Makefile.am b/ui/Makefile.am
index 121d2c4..69395fb 100644
--- a/ui/Makefile.am
+++ b/ui/Makefile.am
@@ -1,12 +1,13 @@
if HAVE_GTK
lib_LTLIBRARIES = librccgtk.la
librccgtk_la_SOURCES = librccui.c \
+ rccmenu.c rccmenu.h \
rccnames.c rccnames.h \
internal.h \
gtk.c
-librccgtk_la_LIBADD = @GTK_LIBS@ ../src/librcc.la
+librccgtk_la_LIBADD = @GTK_LIBS@ @XML_LIBS@ ../src/librcc.la
librccgtk_la_LDFLAGS = -version-info @LIBRCC_VERSION_INFO@
endif
-INCLUDES = -I../src @GTK_INCLUDES@
+INCLUDES = -I../src @GTK_INCLUDES@ @XML_INCLUDES@
include_HEADERS = librccui.h
diff --git a/ui/gtk.c b/ui/gtk.c
index 2fdf2f4..22854ab 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -1,5 +1,8 @@
#include <stdio.h>
#include <gtk/gtk.h>
+
+#include <librcc.h>
+
#include "internal.h"
#include "rccnames.h"
@@ -71,7 +74,10 @@ int rccUiMenuConfigureWidget(rcc_ui_menu_context ctx) {
rcc_charset_id charset_id;
rcc_engine_id engine_id;
-
+
+ rcc_option_name *option_name;
+ rcc_option_value_names optnames;
+
GtkWidget *list, *item, *menu;
if (!ctx) return -1;
@@ -81,9 +87,10 @@ int rccUiMenuConfigureWidget(rcc_ui_menu_context ctx) {
switch (ctx->type) {
case RCC_UI_MENU_LANGUAGE:
- list = gtk_menu_new();
-
languages=rccGetLanguageList(rccctx);
+ if (!languages) return -1;
+
+ list = gtk_menu_new();
for (i=0; languages[i]; i++) {
item = gtk_menu_item_new_with_label(rccUiGetLanguageName(uictx, languages[i]->sn));
gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(rccGtkMenuLanguageCB), ctx);
@@ -104,11 +111,12 @@ int rccUiMenuConfigureWidget(rcc_ui_menu_context ctx) {
gtk_option_menu_set_history(GTK_OPTION_MENU(menu), language_id);
break;
case RCC_UI_MENU_CHARSET:
- list = gtk_menu_new();
language_id = (rcc_language_id)rccUiMenuGet(uictx->language);
charsets = rccGetCharsetList(rccctx, language_id);
+ if (!charsets) return -1;
+ list = gtk_menu_new();
for (i=0;charsets[i];i++) {
item = gtk_menu_item_new_with_label(charsets[i]);
gtk_widget_show(item);
@@ -125,15 +133,17 @@ int rccUiMenuConfigureWidget(rcc_ui_menu_context ctx) {
gtk_option_menu_set_menu(GTK_OPTION_MENU(menu), list);
config = rccGetConfig(rccctx, language_id);
- charset_id = rccConfigGetSelectedCharset(config, (rcc_class_id)ctx->id);
+ charset_id = rccConfigGetSelectedCharset(config, rccUiMenuGetClassId(ctx));
if (charset_id == (rcc_charset_id)-1) charset_id = 0;
gtk_option_menu_set_history(GTK_OPTION_MENU(menu), charset_id);
break;
case RCC_UI_MENU_ENGINE:
- list = gtk_menu_new();
language_id = (rcc_language_id)rccUiMenuGet(uictx->language);
engines = rccGetEngineList(rccctx, language_id);
+ if (!engines) return -1;
+
+ list = gtk_menu_new();
for (i=0;engines[i];i++) {
item = gtk_menu_item_new_with_label(engines[i]->title);
gtk_widget_show(item);
@@ -154,12 +164,44 @@ int rccUiMenuConfigureWidget(rcc_ui_menu_context ctx) {
gtk_option_menu_set_history(GTK_OPTION_MENU(menu), engine_id);
break;
case RCC_UI_MENU_OPTION:
- if (!ctx->widget) {
- item = gtk_check_button_new_with_label(rccUiGetOptionName(uictx, (rcc_option)ctx->id));
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(item), rccGetOption(rccctx, (rcc_option)ctx->id));
- ctx->widget = item;
+ switch (rccUiMenuGetRangeType(ctx)) {
+ case RCC_OPTION_RANGE_TYPE_BOOLEAN:
+ if (!ctx->widget) {
+ item = gtk_check_button_new_with_label(rccUiGetOptionName(uictx, rccUiMenuGetOption(ctx)));
+ ctx->widget = item;
+ }
+
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(item), rccGetOption(rccctx, rccUiMenuGetOption(ctx)));
+ break;
+ case RCC_OPTION_RANGE_TYPE_MENU:
+ if (!ctx->widget) {
+ option_name = rccUiGetOptionRccName(uictx, rccUiMenuGetOption(ctx));
+ if (!option_name) return -1;
+ optnames = option_name->value_names;
+ if (!optnames) return -1;
+
+ list = gtk_menu_new();
+ for (i=0;optnames[i];i++) {
+ item = gtk_menu_item_new_with_label(optnames[i]);
+ gtk_widget_show(item);
+ gtk_menu_append(GTK_MENU(list), item);
+ }
+
+ menu = gtk_option_menu_new();
+ ctx->widget = menu;
+
+ gtk_option_menu_remove_menu(GTK_OPTION_MENU(menu));
+ gtk_option_menu_set_menu(GTK_OPTION_MENU(menu), list);
+ }
+
+ gtk_option_menu_set_history(GTK_OPTION_MENU(menu), rccGetOption(rccctx, rccUiMenuGetOption(ctx)));
+ break;
+ default:
+ return -1;
}
break;
+ default:
+ return -1;
}
return 0;
@@ -170,7 +212,7 @@ rcc_ui_box rccUiBoxCreate(rcc_ui_menu_context ctx, const char *title) {
GtkWidget *hbox, *label;
hbox = gtk_hbox_new(FALSE, BOX_SPACING);
gtk_container_border_width(GTK_CONTAINER(hbox), BOX_BORDER);
- if (ctx->type != RCC_UI_MENU_OPTION) {
+ if ((ctx->type != RCC_UI_MENU_OPTION)||(rccUiMenuGetRangeType(ctx) != RCC_OPTION_RANGE_TYPE_BOOLEAN)) {
label = gtk_label_new(title);
gtk_widget_set_usize(label, TITLE_WIDTH, TITLE_HEIGHT);
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
diff --git a/ui/internal.h b/ui/internal.h
index 8448fb5..64ee978 100644
--- a/ui/internal.h
+++ b/ui/internal.h
@@ -1,34 +1,13 @@
#ifndef _RCC_UI_INTERNAL_H
#define _RCC_UI_INTERNAL_H
-#include "../src/librcc.h"
-#include "librccui.h"
+#define RCC_UI_MAX_STRING_CHARS 1024
-typedef unsigned int rcc_ui_id;
-
-typedef void *rcc_ui_menu_internal;
+#include <librcc.h>
-enum rcc_ui_menu_type_t {
- RCC_UI_MENU_LANGUAGE = 0,
- RCC_UI_MENU_CHARSET,
- RCC_UI_MENU_ENGINE,
- RCC_UI_MENU_OPTION,
- RCC_UI_MENU_MAX
-};
-typedef enum rcc_ui_menu_type_t rcc_ui_menu_type;
+#include "rccmenu.h"
-struct rcc_ui_menu_context_t {
- rcc_ui_widget widget;
- rcc_ui_box box;
-
- rcc_ui_context uictx;
- rcc_ui_menu_type type;
- rcc_ui_id id;
-
- rcc_ui_menu_internal internal;
-};
-typedef struct rcc_ui_menu_context_t rcc_ui_menu_context_s;
-typedef struct rcc_ui_menu_context_t *rcc_ui_menu_context;
+typedef unsigned int rcc_ui_id;
typedef void *rcc_ui_frame_internal;
diff --git a/ui/librccui.c b/ui/librccui.c
index 3b8bcdc..9f4dc49 100644
--- a/ui/librccui.c
+++ b/ui/librccui.c
@@ -1,31 +1,272 @@
#include <stdio.h>
-#include "../src/rccconfig.h"
+#include <string.h>
+#include <stdarg.h>
+#include <locale.h>
+
+#include "../config.h"
+
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+
+#include <librcc.h>
+
#include "internal.h"
#include "rccnames.h"
#define RCC_UI_LOCK_CODE 0x1111
-static rcc_ui_menu_context rccUiMenuCreateContext(rcc_ui_menu_type type, rcc_ui_id id, rcc_ui_context uictx) {
- rcc_ui_menu_context ctx;
- if ((!uictx)||(type>RCC_UI_MENU_MAX)) return NULL;
+#define XPATH_LANGUAGE "//Languages/Language[@name]"
+#define XPATH_OPTION "//Options/Option[@name]"
+#define XPATH_VALUE "//Options/Option[@name=\"%s\"]/Value[@name]"
+#define XPATH_LANGUAGE_REQUEST_LOCALE "//Languages/Language[@name=\"%s\"]/FullName[@locale=\"%s\"]"
+#define XPATH_LANGUAGE_REQUEST "//Languages/Language[@name=\"%s\"]/FullName"
+#define XPATH_OPTION_REQUEST_LOCALE "//Options/Option[@name=\"%s\"]/FullName[@locale=\"%s\"]"
+#define XPATH_OPTION_REQUEST "//Options/Option[@name=\"%s\"]/FullName"
+#define XPATH_VALUE_REQUEST_LOCALE "//Options/Option[@name=\"%s\"]/Value[@name=\"%s\"]/FullName[@locale=\"%s\"]"
+#define XPATH_VALUE_REQUEST "//Options/Option[@name=\"%s\"]/Value[@name=\"%s\"]/FullName"
+
+static const char *rccUiXmlGetText(xmlNodePtr node) {
+ if ((node)&&(node->children)&&(node->children->type == XML_TEXT_NODE)&&(node->children->content)) return node->children->content;
+}
+
+static xmlNodePtr rccUiNodeFind(xmlXPathContextPtr xpathctx, const char *request, ...) {
+ xmlXPathObjectPtr obj;
+ xmlNodeSetPtr node_set;
+ xmlNodePtr res = NULL;
+
+ unsigned int i, args = 0;
+ unsigned int size = 128;
+ va_list ap;
+ char *req;
- ctx = (rcc_ui_menu_context)malloc(sizeof(rcc_ui_menu_context_s));
- if (!ctx) return ctx;
+ if (!xpathctx) return NULL;
+
+ for (req = strstr(request, "%s"); req; req = strstr(req + 1, "%s")) args++;
- ctx->uictx = uictx;
- ctx->type = type;
- ctx->id = id;
+ if (args) {
+ va_start(ap, request);
+ for (i=0;i<args;i++) {
+ req = va_arg(ap, char*);
+ size += strlen(req);
+ }
+ va_end(ap);
+
+ req = (char*)malloc(size*sizeof(char));
+ if (!req) return NULL;
+
+ va_start(ap, request);
+ vsprintf(req,request,ap);
+ va_end(ap);
+ } else req = (char*)request;
+
+ obj = xmlXPathEvalExpression(req, xpathctx);
+ if (obj) {
+ node_set = obj->nodesetval;
+ if ((node_set)&&(node_set->nodeNr > 0)) {
+ res = node_set->nodeTab[0];
+ }
+ xmlXPathFreeObject(obj);
+ }
+
+ if (args) free(req);
+
+ return res;
+}
+
+int rccUiInit() {
+ int err;
+ unsigned long i, j, k, nnodes;
+
+ xmlDocPtr xmlctx;
+ xmlXPathContextPtr xpathctx = NULL;
+ xmlXPathObjectPtr obj;
+ xmlNodeSetPtr node_set;
+
+ xmlNodePtr node, cnode;
+ xmlAttrPtr attr;
+
+ rcc_language_name *lang_name;
+ const char *lang, *fullname;
+ const char *locale;
+ char *lpos;
+ char *search[4];
+
+ rcc_option option;
+ const char *opt, *val;
+ rcc_option_name *option_name;
+ const char *value_name;
+
+ unsigned int npos;
+
+ size_t newsize;
+ char tmpbuf[RCC_UI_MAX_STRING_CHARS+1];
+ char ctype_charset[32];
+ rcc_iconv icnv;
+
+ err = rccInit();
+ if (err) return err;
- ctx->widget = rccUiMenuCreateWidget(ctx);
- ctx->box = NULL;
+ if (rccLocaleGetCharset(ctype_charset, NULL, 32)) icnv = NULL;
+ else {
+ if ((!strcasecmp(ctype_charset, "UTF-8"))||(!strcasecmp(ctype_charset, "UTF8"))) icnv = NULL;
+ else icnv = rccIConvOpen(ctype_charset, "UTF-8");
+ }
- return ctx;
+ locale = setlocale(LC_CTYPE, NULL);
+ if (locale) {
+ search[0] = strdup(locale);
+ if (!search[0]) goto clean;
+ lpos = strrchr(search[0], '@');
+ if (lpos) *lpos = 0;
+
+ lpos = strrchr(search[0], '.');
+ if (lpos) {
+ search[1] = strdup(search[0]);
+ if (!search[1]) goto clean;
+ *strchr(search[1], '.') = 0;
+
+ lpos = strrchr(search[1], '_');
+ if (lpos) {
+ search[2] = strdup(search[1]);
+ if (!search[2]) goto clean;
+ *strchr(search[2],'_') = 0;
+ search[3] = NULL;
+ } else search[2] = NULL;
+ } else search[1] = NULL;
+ } else search[0] = NULL;
+
+ for (npos = 0; rcc_default_language_names[npos].sn; npos++);
+
+ xmlctx = (xmlDocPtr)rccGetConfiguration();
+ if (xmlctx) xpathctx = xmlXPathNewContext(xmlctx);
+ else xpathctx = NULL;
+ if (xpathctx) {
+ obj = xmlXPathEvalExpression(XPATH_LANGUAGE, xpathctx);
+ if (obj) {
+ node_set = obj->nodesetval;
+ if (node_set) nnodes = node_set->nodeNr;
+ else nnodes = 0;
+ } else nnodes = 0;
+
+ for (i=0;i<nnodes;i++) {
+ node = node_set->nodeTab[i];
+ attr = xmlHasProp(node, "name");
+ lang = attr->children->content;
+
+ if ((!lang)||(!lang[0])) continue;
+
+ for (j=0, node = NULL;((search[j])&&(!node));j++)
+ node = rccUiNodeFind(xpathctx, XPATH_LANGUAGE_REQUEST_LOCALE, lang, search[j]);
+ if (!node) {
+ node = rccUiNodeFind(xpathctx, XPATH_LANGUAGE_REQUEST, lang);
+ if (!node) continue;
+ }
+
+ fullname = rccUiXmlGetText(node);
+ if (!fullname) continue;
+
+ if (icnv) {
+ newsize = rccIConvRecode(icnv, tmpbuf, RCC_UI_MAX_STRING_CHARS, fullname, 0);
+ if (newsize != (size_t)-1) {
+ cnode = xmlNewChild(node->parent, NULL, "Recoded", tmpbuf);
+ fullname = rccUiXmlGetText(cnode);
+ if (!fullname) fullname = rccUiXmlGetText(node);
+ }
+ }
+
+ lang_name = rccUiGetLanguageRccName(NULL, lang);
+ if (lang_name) lang_name->name = fullname;
+ else if (npos<RCC_MAX_LANGUAGES) {
+ rcc_default_language_names[npos].sn = lang;
+ rcc_default_language_names[npos].name = fullname;
+ rcc_default_language_names[++npos].sn = NULL;
+ rcc_default_language_names[npos].name = NULL;
+ }
+ }
+
+ if (obj) xmlXPathFreeObject(obj);
+
+ obj = xmlXPathEvalExpression(XPATH_OPTION, xpathctx);
+ if (obj) {
+ node_set = obj->nodesetval;
+ if (node_set) nnodes = node_set->nodeNr;
+ else nnodes = 0;
+ } else nnodes = 0;
+
+ for (i=0;i<nnodes;i++) {
+ node = node_set->nodeTab[i];
+ attr = xmlHasProp(node, "name");
+ opt = attr->children->content;
+
+ if ((!opt)||(!opt[0])) continue;
+ option = rccGetOptionByName(opt);
+ if (option == (rcc_option)-1) continue;
+ option_name = rccUiGetOptionRccName(NULL, option);
+ if (!option_name) continue;
+
+ for (j=0, node = NULL;((search[j])&&(!node));j++)
+ node = rccUiNodeFind(xpathctx, XPATH_OPTION_REQUEST_LOCALE, opt, search[j]);
+ if (!node) {
+ node = rccUiNodeFind(xpathctx, XPATH_OPTION_REQUEST, opt);
+ }
+
+ if (node) {
+ fullname = rccUiXmlGetText(node);
+ if (fullname) {
+ if (icnv) {
+ newsize = rccIConvRecode(icnv, tmpbuf, RCC_UI_MAX_STRING_CHARS, fullname, 0);
+ if (newsize != (size_t)-1) {
+ cnode = xmlNewChild(node->parent, NULL, "Recoded", tmpbuf);
+ fullname = rccUiXmlGetText(cnode);
+ if (!fullname) fullname = rccUiXmlGetText(node);
+ }
+ }
+ option_name->name = fullname;
+ }
+ }
+
+ if (!option_name->value_names) continue;
+
+ for (k=0;option_name->value_names[k];k++) {
+ value_name = rccGetOptionValueName(option, (rcc_option_value)k);
+ if (!value_name) continue;
+
+ for (j=0, node = NULL;((search[j])&&(!node));j++)
+ node = rccUiNodeFind(xpathctx, XPATH_VALUE_REQUEST_LOCALE, opt, value_name, search[j]);
+ if (!node) {
+ node = rccUiNodeFind(xpathctx, XPATH_VALUE_REQUEST, opt, value_name);
+ }
+
+ if (node) {
+ fullname = rccUiXmlGetText(node);
+ if (fullname) {
+ if (icnv) {
+ newsize = rccIConvRecode(icnv, tmpbuf, RCC_UI_MAX_STRING_CHARS, fullname, 0);
+ if (newsize != (size_t)-1) {
+ cnode = xmlNewChild(node->parent, NULL, "Recoded", tmpbuf);
+ fullname = rccUiXmlGetText(cnode);
+ if (!fullname) fullname = rccUiXmlGetText(node);
+ }
+ }
+ option_name->value_names[k] = fullname;
+ }
+ }
+ }
+ }
+ if (obj) xmlXPathFreeObject(obj);
+
+ xmlXPathFreeContext(xpathctx);
+ }
+
+clean:
+ for (j=0;search[j];j++) free(search[j]);
+ if (icnv) rccIConvClose(icnv);
+
+ return 0;
}
-static void rccUiMenuFreeContext(rcc_ui_menu_context ctx) {
- if (!ctx) return;
- rccUiMenuFreeWidget(ctx);
- free(ctx);
+void rccUiFree() {
}
static rcc_ui_frame_context rccUiFrameCreateContext(rcc_ui_frame_type type, rcc_ui_context uictx) {
@@ -57,6 +298,8 @@ rcc_ui_context rccUiCreateContext(rcc_context rccctx) {
rcc_ui_context ctx;
rcc_ui_menu_context *charsets;
rcc_ui_menu_context *options;
+ rcc_option_type otype;
+ rcc_option_range *orange;
if (!rccctx) return NULL;
@@ -85,15 +328,17 @@ rcc_ui_context rccUiCreateContext(rcc_context rccctx) {
ctx->internal = rccUiCreateInternal(ctx);
- ctx->language = rccUiMenuCreateContext(RCC_UI_MENU_LANGUAGE, 0, ctx);
- ctx->engine = rccUiMenuCreateContext(RCC_UI_MENU_ENGINE, 0, ctx);
+ ctx->language = rccUiMenuCreateContext(RCC_UI_MENU_LANGUAGE, ctx);
+ ctx->engine = rccUiMenuCreateContext(RCC_UI_MENU_ENGINE, ctx);
for (i=0; classes[i]; i++) {
- charsets[i] = rccUiMenuCreateContext(RCC_UI_MENU_CHARSET, i, ctx);
+ charsets[i] = rccUiCharsetMenuCreateContext(RCC_UI_MENU_CHARSET, (rcc_charset_id)i, ctx);
if (!charsets[i]) err = 1;
}
charsets[i] = NULL;
for (i=0; i<RCC_MAX_OPTIONS; i++) {
- options[i] = rccUiMenuCreateContext(RCC_UI_MENU_OPTION, i, ctx);
+ otype = rccOptionGetType(rccctx, (rcc_option)i);
+ orange = rccOptionGetRange(rccctx, (rcc_option)i);
+ options[i] = rccUiOptionMenuCreateContext(RCC_UI_MENU_OPTION, (rcc_option)i, otype, orange, ctx);
if (!options[i]) err = 1;
}
@@ -145,17 +390,15 @@ void rccUiFreeContext(rcc_ui_context ctx) {
int rccUiSetLanguageNames(rcc_ui_context ctx, rcc_language_name *names) {
if (!ctx) return -1;
-
- if (names) ctx->language_names = names;
- else ctx->language_names = rcc_default_language_names;
+
+ ctx->language_names = names;
return 0;
}
int rccUiSetOptionNames(rcc_ui_context ctx, rcc_option_name *names) {
if (!ctx) return -1;
- if (names) ctx->option_names = names;
- else ctx->option_names = rcc_default_option_names;
+ ctx->option_names = names;
return 0;
}
@@ -383,7 +626,7 @@ rcc_ui_frame rccUiGetEngineFrame(rcc_ui_context ctx, const char *title) {
rcc_ui_frame frame;
rcc_ui_box engine;
rcc_ui_box opt;
- const char *optname;
+ rcc_option_name *optname;
if (!ctx) return NULL;
@@ -398,10 +641,12 @@ rcc_ui_frame rccUiGetEngineFrame(rcc_ui_context ctx, const char *title) {
rccUiFrameAdd(framectx, engine);
for (i=0; i<RCC_MAX_OPTIONS; i++) {
- optname = rccUiGetOptionName(ctx, i);
+ if (rccUiMenuGetType(ctx->options[i]) == RCC_OPTION_TYPE_INVISIBLE) continue;
+
+ optname = rccUiGetOptionRccName(ctx, i);
if (!optname) continue;
- opt = rccUiGetOptionBox(ctx, (rcc_option)i, optname);
+ opt = rccUiGetOptionBox(ctx, (rcc_option)i, optname->name);
rccUiFrameAdd(framectx, opt);
}
diff --git a/ui/librccui.h b/ui/librccui.h
index 6b114da..5a8d034 100644
--- a/ui/librccui.h
+++ b/ui/librccui.h
@@ -14,10 +14,11 @@ typedef void *rcc_ui_page;
typedef struct rcc_ui_context_t *rcc_ui_context;
+int rccUiInit();
+void rccUiFree();
+
rcc_ui_context rccUiCreateContext(rcc_context rccctx);
void rccUiFreeContext(rcc_ui_context ctx);
-int rccUiSetLanguageNames(rcc_ui_context ctx, rcc_language_name *names);
-int rccUiSetOptionNames(rcc_ui_context ctx, rcc_option_name *names);
int rccUiRestoreLanguage(rcc_ui_context ctx);
int rccUiRestore(rcc_ui_context ctx);
@@ -39,6 +40,29 @@ rcc_ui_frame rccUiGetEngineFrame(rcc_ui_context ctx, const char *title);
rcc_ui_page rccUiGetPage(rcc_ui_context ctx, const char *title, const char *language_title, const char *charset_title, const char *engine_title);
+/*******************************************************************************
+************************************ Names *************************************
+*******************************************************************************/
+
+struct rcc_language_name_t {
+ const char *sn;
+ const char *name;
+};
+typedef struct rcc_language_name_t rcc_language_name;
+
+typedef const char *rcc_option_value_name;
+typedef rcc_option_value_name *rcc_option_value_names;
+
+struct rcc_option_name_t {
+ rcc_option option;
+ const char *name;
+ rcc_option_value_names value_names;
+};
+typedef struct rcc_option_name_t rcc_option_name;
+
+int rccUiSetLanguageNames(rcc_ui_context ctx, rcc_language_name *names);
+int rccUiSetOptionNames(rcc_ui_context ctx, rcc_option_name *names);
+
#ifdef __cplusplus
}
#endif
diff --git a/ui/rccmenu.c b/ui/rccmenu.c
new file mode 100644
index 0000000..da04cbd
--- /dev/null
+++ b/ui/rccmenu.c
@@ -0,0 +1,89 @@
+#include <stdio.h>
+#include <string.h>
+
+#include "internal.h"
+#include "rccmenu.h"
+
+rcc_ui_menu_context rccUiMenuCreateContext(rcc_ui_menu_type type, rcc_ui_context uictx) {
+ rcc_ui_menu_context ctx;
+ if ((!uictx)||(type>=RCC_UI_MENU_MAX)) return NULL;
+
+ ctx = (rcc_ui_menu_context)malloc(sizeof(rcc_ui_menu_context_s));
+ if (!ctx) return ctx;
+
+ ctx->uictx = uictx;
+ ctx->type = type;
+
+ ctx->widget = rccUiMenuCreateWidget(ctx);
+ ctx->box = NULL;
+
+ return ctx;
+}
+
+rcc_ui_menu_context rccUiCharsetMenuCreateContext(rcc_ui_menu_type type, rcc_charset_id id, rcc_ui_context uictx) {
+ rcc_ui_charset_menu_context ctx;
+
+ if ((!uictx)||(type>=RCC_UI_MENU_MAX)) return NULL;
+
+ ctx = (rcc_ui_charset_menu_context)malloc(sizeof(rcc_ui_charset_menu_context_s));
+ if (!ctx) return NULL;
+
+ ctx->ui_menu.uictx = uictx;
+ ctx->ui_menu.type = type;
+ ctx->id = id;
+
+ ctx->ui_menu.widget = rccUiMenuCreateWidget((rcc_ui_menu_context)ctx);
+ ctx->ui_menu.box = NULL;
+
+ return (rcc_ui_menu_context)ctx;
+}
+
+rcc_ui_menu_context rccUiOptionMenuCreateContext(rcc_ui_menu_type type, rcc_option id, rcc_option_type otype, rcc_option_range *range, rcc_ui_context uictx) {
+ rcc_ui_option_menu_context ctx;
+
+ if ((!uictx)||(type>=RCC_UI_MENU_MAX)) return NULL;
+
+ ctx = (rcc_ui_option_menu_context)malloc(sizeof(rcc_ui_option_menu_context_s));
+ if (!ctx) return NULL;
+
+ ctx->ui_menu.uictx = uictx;
+ ctx->ui_menu.type = type;
+ ctx->id = id;
+ ctx->type = otype;
+ ctx->range = range;
+
+ ctx->ui_menu.widget = rccUiMenuCreateWidget((rcc_ui_menu_context)ctx);
+ ctx->ui_menu.box = NULL;
+
+ return (rcc_ui_menu_context)ctx;
+}
+
+
+void rccUiMenuFreeContext(rcc_ui_menu_context ctx) {
+ if (!ctx) return;
+ rccUiMenuFreeWidget(ctx);
+ free(ctx);
+}
+
+
+rcc_class_id rccUiMenuGetClassId(rcc_ui_menu_context ctx) {
+ if (ctx->type != RCC_UI_MENU_CHARSET) return (rcc_class_id)-1;
+ return ((rcc_ui_charset_menu_context)ctx)->id;
+}
+
+rcc_option rccUiMenuGetOption(rcc_ui_menu_context ctx) {
+ if (ctx->type != RCC_UI_MENU_OPTION) return (rcc_option)-1;
+ return ((rcc_ui_option_menu_context)ctx)->id;
+}
+
+
+rcc_option_type rccUiMenuGetType(rcc_ui_menu_context ctx) {
+ if (ctx->type != RCC_UI_MENU_OPTION) return (rcc_option_type)-1;
+ return ((rcc_ui_option_menu_context)ctx)->type;
+}
+
+rcc_option_range_type rccUiMenuGetRangeType(rcc_ui_menu_context ctx) {
+ if (ctx->type != RCC_UI_MENU_OPTION) return (rcc_option_type)-1;
+ return ((rcc_ui_option_menu_context)ctx)->range->type;
+}
+
diff --git a/ui/rccmenu.h b/ui/rccmenu.h
new file mode 100644
index 0000000..5ad14ff
--- /dev/null
+++ b/ui/rccmenu.h
@@ -0,0 +1,55 @@
+#ifndef _RCC_UI_MENU_H
+#define _RCC_UI_MENU_H
+
+#include "librccui.h"
+
+typedef void *rcc_ui_menu_internal;
+
+enum rcc_ui_menu_type_t {
+ RCC_UI_MENU_LANGUAGE = 0,
+ RCC_UI_MENU_CHARSET,
+ RCC_UI_MENU_ENGINE,
+ RCC_UI_MENU_OPTION,
+ RCC_UI_MENU_MAX
+};
+typedef enum rcc_ui_menu_type_t rcc_ui_menu_type;
+
+struct rcc_ui_menu_context_t {
+ rcc_ui_widget widget;
+ rcc_ui_box box;
+
+ rcc_ui_context uictx;
+ rcc_ui_menu_type type;
+
+ rcc_ui_menu_internal internal;
+};
+typedef struct rcc_ui_menu_context_t rcc_ui_menu_context_s;
+typedef struct rcc_ui_menu_context_t *rcc_ui_menu_context;
+
+struct rcc_ui_charset_menu_context_t {
+ rcc_ui_menu_context_s ui_menu;
+ rcc_class_id id;
+};
+typedef struct rcc_ui_charset_menu_context_t rcc_ui_charset_menu_context_s;
+typedef struct rcc_ui_charset_menu_context_t *rcc_ui_charset_menu_context;
+
+struct rcc_ui_option_menu_context_t {
+ rcc_ui_menu_context_s ui_menu;
+ rcc_option id;
+ rcc_option_type type;
+ rcc_option_range *range;
+};
+typedef struct rcc_ui_option_menu_context_t rcc_ui_option_menu_context_s;
+typedef struct rcc_ui_option_menu_context_t *rcc_ui_option_menu_context;
+
+rcc_ui_menu_context rccUiMenuCreateContext(rcc_ui_menu_type type, rcc_ui_context uictx);
+rcc_ui_menu_context rccUiCharsetMenuCreateContext(rcc_ui_menu_type type, rcc_charset_id id, rcc_ui_context uictx);
+rcc_ui_menu_context rccUiOptionMenuCreateContext(rcc_ui_menu_type type, rcc_option id, rcc_option_type otype, rcc_option_range *range, rcc_ui_context uictx);
+void rccUiMenuFreeContext(rcc_ui_menu_context ctx);
+
+rcc_class_id rccUiMenuGetClassId(rcc_ui_menu_context ctx);
+rcc_option rccUiMenuGetOption(rcc_ui_menu_context ctx);
+rcc_option_type rccUiMenuGetType(rcc_ui_menu_context ctx);
+rcc_option_range_type rccUiMenuGetRangeType(rcc_ui_menu_context ctx);
+
+#endif /* _RCC_UI_MENU_H */
diff --git a/ui/rccnames.c b/ui/rccnames.c
index f5bf4d8..9ebaba4 100644
--- a/ui/rccnames.c
+++ b/ui/rccnames.c
@@ -1,44 +1,111 @@
#include <stdio.h>
+#include <librcc.h>
+
#include "internal.h"
-const char *rccUiGetLanguageName(rcc_ui_context ctx, const char *lang) {
+rcc_language_name rcc_default_language_names[RCC_MAX_LANGUAGES+1] = {
+{"default", "Autodetect"},
+{"off", "Dissable"},
+{"ru","Russian"},
+{"uk","Ukrainian"},
+{"be","Belarussian"},
+{"bg","Bulgarian"},
+{"cz","Czech"},
+{"es","Estonian"},
+{"hr","Croatian"},
+{"hu","Hungarian"},
+{"lt","Lithuanian"},
+{"lv","Latvian"},
+{"pl","Polish"},
+{"sk","Slovak"},
+{"sl","Slovenian"},
+{"zh","Chinese"},
+{NULL, NULL}
+};
+
+rcc_option_value_name rcc_default_option_boolean_names[] = { "Off", "On", NULL };
+rcc_option_value_name rcc_default_option_learning_names[] = { "Off", "On", "Relearn", "Learn", NULL };
+rcc_option_value_name rcc_default_option_clo_names[] = { "All Languages", "Configured / AutoEngine", "Configured Only", NULL };
+
+rcc_option_name rcc_default_option_names[RCC_MAX_OPTIONS+1] = {
+ { RCC_LEARNING_MODE, "Recodings Cache", rcc_default_option_learning_names },
+ { RCC_AUTODETECT_FS_NAMES, "Autodetect File Names", rcc_default_option_boolean_names },
+ { RCC_AUTODETECT_FS_TITLES, "Autodetect FS Titles", rcc_default_option_boolean_names },
+ { RCC_CONFIGURED_LANGUAGES_ONLY, "Enabled Languages", rcc_default_option_clo_names },
+ { RCC_MAX_OPTIONS }
+};
+
+
+rcc_language_name *rccUiGetLanguageRccName(rcc_ui_context ctx, const char *lang) {
const char *res;
- unsigned int i;
+ unsigned int i,j;
rcc_language_name *names;
- if ((!ctx)||(!lang)) return NULL;
+ if (!lang) return NULL;
- names = ctx->language_names;
+ for (j=0;j<2;j++) {
+ if (j) names = rcc_default_language_names;
+ else names = ctx?ctx->language_names:NULL;
- if (names) {
- for (i=0;names[i].sn;i++)
- if (!strcmp(lang, names[i].sn)) return names[i].name;
+ if (names) {
+ for (i=0;names[i].sn;i++)
+ if (!strcmp(lang, names[i].sn)) return names+i;
+ }
}
+
+ return NULL;
+}
-
- res = rccGetLanguageFullName(lang);
- if (res) return res;
+const char *rccUiGetLanguageName(rcc_ui_context ctx, const char *lang) {
+ const char *res;
+ unsigned int i,j;
+ rcc_language_name *names;
+
+ names = rccUiGetLanguageRccName(ctx, lang);
+ if ((names)&&(names->name)) return names->name;
return lang;
}
+rcc_option_name *rccUiGetOptionRccName(rcc_ui_context ctx, rcc_option option) {
+ unsigned int i,j;
+ rcc_option_name *names;
+
+ if ((option<0)||(option>=RCC_MAX_OPTIONS)) return NULL;
+
+ for (j=0;j<2;j++) {
+ if (j) names = rcc_default_option_names;
+ else names = ctx?ctx->option_names:NULL;
+
+ if (names) {
+ for (i=0;names[i].option!=RCC_MAX_OPTIONS;i++)
+ if (names[i].option == option) return names+i;
+ }
+ }
+
+ return NULL;
+}
+
const char *rccUiGetOptionName(rcc_ui_context ctx, rcc_option option) {
- const char *res;
unsigned int i;
- rcc_option_name *names;
+ rcc_option_name *name;
- if ((!ctx)||(option<0)||(option>RCC_MAX_OPTIONS)) return NULL;
+ name = rccUiGetOptionRccName(ctx, option);
+ if (name) return name->name;
- names = ctx->option_names;
+ return NULL;
+}
- if (names) {
- for (i=0;((i<RCC_MAX_OPTIONS)&&(names[i].option!=RCC_MAX_OPTIONS));i++)
- if (names[i].option == option) return names[i].name;
+const char *rccUiGetOptionValueName(rcc_ui_context ctx, rcc_option option, rcc_option_value value) {
+ unsigned int i;
+ rcc_option_name *name;
+
+ name = rccUiGetOptionRccName(ctx, option);
+ if (name) {
+ for (i=0;name->value_names[i];i++)
+ if (i == value) return name->value_names[i];
}
-
- res = rccGetOptionFullName(option);
- if (res) return res;
return NULL;
}
diff --git a/ui/rccnames.h b/ui/rccnames.h
index cb23960..f73bd19 100644
--- a/ui/rccnames.h
+++ b/ui/rccnames.h
@@ -1,9 +1,13 @@
#ifndef _RCC_UI_NAMES_C
#define _RCC_UI_NAMES_H
+extern rcc_language_name rcc_default_language_names[];
+extern rcc_option_name rcc_default_option_names[];
+rcc_language_name *rccUiGetLanguageRccName(rcc_ui_context ctx, const char *lang);
const char *rccUiGetLanguageName(rcc_ui_context ctx, const char *lang);
+rcc_option_name *rccUiGetOptionRccName(rcc_ui_context ctx, rcc_option option);
const char *rccUiGetOptionName(rcc_ui_context ctx, rcc_option option);
-
+const char *rccUiGetOptionValueName(rcc_ui_context ctx, rcc_option option, rcc_option_value value);
#endif /* _RCC_UI_NAMES_H */