diff options
-rw-r--r-- | examples/rcc.xml | 32 | ||||
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/librcc.h | 62 | ||||
-rw-r--r-- | src/lngconfig.c | 5 | ||||
-rw-r--r-- | src/opt.c | 102 | ||||
-rw-r--r-- | src/opt.h | 27 | ||||
-rw-r--r-- | src/rccconfig.c | 103 | ||||
-rw-r--r-- | src/rccconfig.h | 7 | ||||
-rw-r--r-- | src/rcciconv.c | 66 | ||||
-rw-r--r-- | src/rcciconv.h | 5 | ||||
-rw-r--r-- | src/rcclocale.c | 8 | ||||
-rw-r--r-- | src/rccxml.c | 58 | ||||
-rw-r--r-- | src/recode.c | 8 | ||||
-rw-r--r-- | ui/Makefile.am | 5 | ||||
-rw-r--r-- | ui/gtk.c | 64 | ||||
-rw-r--r-- | ui/internal.h | 29 | ||||
-rw-r--r-- | ui/librccui.c | 301 | ||||
-rw-r--r-- | ui/librccui.h | 28 | ||||
-rw-r--r-- | ui/rccmenu.c | 89 | ||||
-rw-r--r-- | ui/rccmenu.h | 55 | ||||
-rw-r--r-- | ui/rccnames.c | 107 | ||||
-rw-r--r-- | ui/rccnames.h | 6 |
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; @@ -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); +} @@ -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 @@ -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 */ |