diff options
-rw-r--r-- | configure.in | 4 | ||||
-rw-r--r-- | examples/rcc.xml | 12 | ||||
-rw-r--r-- | librcc.spec.in | 3 | ||||
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/internal.h | 1 | ||||
-rw-r--r-- | src/librcc.c | 71 | ||||
-rw-r--r-- | src/librcc.h | 15 | ||||
-rw-r--r-- | src/lngconfig.c | 26 | ||||
-rw-r--r-- | src/opt.c | 23 | ||||
-rw-r--r-- | src/opt.h | 5 | ||||
-rw-r--r-- | src/rccconfig.c | 77 | ||||
-rw-r--r-- | src/rccconfig.h | 1 | ||||
-rw-r--r-- | src/rccxml.c | 464 | ||||
-rw-r--r-- | src/rccxml.h (renamed from src/xml.h) | 3 | ||||
-rw-r--r-- | src/xml.c | 14 | ||||
-rw-r--r-- | ui/gtk.c | 16 | ||||
-rw-r--r-- | ui/internal.h | 39 | ||||
-rw-r--r-- | ui/librccui.c | 102 | ||||
-rw-r--r-- | ui/rccnames.c | 27 |
19 files changed, 810 insertions, 95 deletions
diff --git a/configure.in b/configure.in index ae98654..e2fe1c4 100644 --- a/configure.in +++ b/configure.in @@ -41,7 +41,7 @@ dnl Checks for programs. dnl Checks for header files. AC_CHECK_HEADERS(iconv.h,, [AC_MSG_ERROR(Missing iconv header)]) -AC_CHECK_HEADERS(mntent.h) +AC_CHECK_HEADERS(mntent.h pwd.h sys/types.h unistd.h) AC_TRY_COMPILE([#include <langinfo.h>], [char *codeset = nl_langinfo (CODESET);], @@ -55,7 +55,7 @@ if test $XML2_CONFIG = no; then AC_MSG_ERROR(LibXML2 is required) fi XML_LIBS="\`xml2-config --libs\`" -XML_INCLUDES="\`xml-config --cflags\`" +XML_INCLUDES="\`xml2-config --cflags\`" AC_SUBST(XML_LIBS) AC_SUBST(XML_INCLUDES) diff --git a/examples/rcc.xml b/examples/rcc.xml new file mode 100644 index 0000000..b991a5c --- /dev/null +++ b/examples/rcc.xml @@ -0,0 +1,12 @@ +<?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> diff --git a/librcc.spec.in b/librcc.spec.in index 998b8ca..f89af8b 100644 --- a/librcc.spec.in +++ b/librcc.spec.in @@ -52,6 +52,8 @@ is part of rusxmms patch. %install %makeinstall prefix=$RPM_BUILD_ROOT%{prefix} rm -f $RPM_BUILD_ROOT%{prefix}/lib/*.la +mkdir -p $RPM_BUILD_ROOT/etc +install -m 644 example/rcc.xml $RPM_BUILD_ROOT/etc %clean rm -rf $RPM_BUILD_ROOT @@ -63,6 +65,7 @@ rm -rf $RPM_BUILD_ROOT %files %defattr(-, root, root) %doc AUTHORS ChangeLog NEWS README COPYING +/etc/rcc.xml %{prefix}/lib/lib*.so.* %files devel diff --git a/src/Makefile.am b/src/Makefile.am index b45d4b1..bef8240 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -11,7 +11,7 @@ librcc_la_SOURCES = librcc.c \ rccenca.c rccenca.h \ engine.c engine.h \ rccstring.c rccstring.h \ - xml.c xml.h \ + rccxml.c rccxml.h \ rcciconv.c rcciconv.h \ fs.c fs.h \ recode.c recode.h \ diff --git a/src/internal.h b/src/internal.h index 24e9cc8..1706ff5 100644 --- a/src/internal.h +++ b/src/internal.h @@ -15,6 +15,7 @@ struct rcc_context_t { rcc_language_alias_list aliases; rcc_option_value options[RCC_MAX_OPTIONS]; + unsigned char default_options[RCC_MAX_OPTIONS]; unsigned int max_languages; unsigned int n_languages; diff --git a/src/librcc.c b/src/librcc.c index d6acc72..5b6a66f 100644 --- a/src/librcc.c +++ b/src/librcc.c @@ -1,22 +1,79 @@ #include <stdio.h> +#include <stdlib.h> #include <string.h> +#include "../config.h" + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif /* HAVE_UNISTD_H */ + +#ifdef HAVE_SYS_TYPES_H +# include <sys/types.h> +#endif /* HAVE_SYS_TYPES_H */ + +#ifdef HAVE_PWD_H +# include <pwd.h> +#endif /* HAVE_PWD_H */ + #include <librcd.h> #include "internal.h" #include "rccconfig.h" #include "rccenca.h" #include "rcclist.h" +#include "rccenca.h" +#include "rccxml.h" - +static int initialized = 0; +char *rcc_home_dir = NULL; int rccInit() { - /*DS: Load addition languages from config! */ - return rccEncaInit(); + int err; + char *tmp; + +#ifdef HAVE_PWD_H + struct passwd *pw; +#endif /* HAVE_PWD_H */ + + if (initialized) return 0; + + tmp = getenv ("HOME"); + if (tmp) rcc_home_dir = strdup (tmp); +#ifdef HAVE_PWD_H + else { + setpwent (); + pw = getpwuid(getuid ()); + endpwent (); + if ((pw)&&(pw->pw_dir)) rcc_home_dir = strdup (pw->pw_dir); + } +#endif /* HAVE_PWD_H */ + if (!rcc_home_dir) rcc_home_dir = strdup("/"); + + + err = rccEncaInit(); + if (!err) err = rccXmlInit(); + + if (err) { + rccFree(); + return err; + } + + initialized = 1; + + return 0; } void rccFree() { + rccXmlFree(); rccEncaFree(); + + if (rcc_home_dir) { + free(rcc_home_dir); + rcc_home_dir = NULL; + } + + initialized = 0; } rcc_context rccCreateContext(const char *locale_variable, unsigned int max_languages, unsigned int max_classes, rcc_class_ptr defclasses, rcc_init_flags flags) { @@ -137,8 +194,10 @@ rcc_context rccCreateContext(const char *locale_variable, unsigned int max_langu } } - for (i=0;i<RCC_MAX_OPTIONS;i++) - ctx->options[i] = 0; + for (i=0;i<RCC_MAX_OPTIONS;i++) { + ctx->options[i] = rccGetOptionDefaultValue((rcc_option)i); + ctx->default_options[i] = 1; + } ctx->configure = 1; @@ -258,12 +317,10 @@ rcc_alias_id rccRegisterLanguageAlias(rcc_context ctx, rcc_language_alias *alias } rcc_class_id rccRegisterClass(rcc_context ctx, rcc_class *cl) { - puts("yes"); if ((!ctx)||(!cl)) return -1; if (ctx->configuration_lock) return -3; if (ctx->n_classes == ctx->max_classes) return -2; - puts(" -----> New class"); ctx->configure = 1; ctx->classes[ctx->n_classes++] = cl; ctx->classes[ctx->n_classes] = NULL; diff --git a/src/librcc.h b/src/librcc.h index 6e40130..1f5ee72 100644 --- a/src/librcc.h +++ b/src/librcc.h @@ -140,6 +140,8 @@ typedef enum rcc_option_t { struct rcc_option_name_t { rcc_option option; const char *name; + + const char *sn; }; typedef struct rcc_option_name_t rcc_option_name; @@ -158,6 +160,8 @@ int rccSetLanguageByName(rcc_context ctx, const char *name); /* opt.c */ 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); /* lngconfig.c */ @@ -169,6 +173,7 @@ rcc_engine_id rccConfigGetEngineByName(rcc_language_config config, const char *n rcc_charset_id rccConfigGetCharsetByName(rcc_language_config config, const char *name); rcc_charset_id rccConfigGetAutoCharsetByName(rcc_language_config config, const char *name); +rcc_language_config rccCheckConfig(rcc_context ctx, rcc_language_id language_id); rcc_language_config rccGetConfig(rcc_context ctx, rcc_language_id language_id); rcc_language_config rccGetConfigByName(rcc_context ctx, const char *name); rcc_language_config rccGetCurrentConfig(rcc_context ctx); @@ -226,6 +231,16 @@ rcc_engine_ptr *rccGetCurrentEngineList(rcc_context ctx); 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 ****************************** diff --git a/src/lngconfig.c b/src/lngconfig.c index ad87189..67b7e0b 100644 --- a/src/lngconfig.c +++ b/src/lngconfig.c @@ -127,6 +127,17 @@ int rccConfigFree(rcc_language_config config) { } } +rcc_language_config rccCheckConfig(rcc_context ctx, rcc_language_id language_id) { + rcc_language_id new_language_id; + int err; + + new_language_id = rccGetRealLanguage(ctx, language_id); + if ((language_id<=0)||(new_language_id != language_id)) return NULL; + if (!ctx->configs[language_id].charset) return NULL; + if (!strcasecmp(ctx->languages[language_id]->sn, "off")) return NULL; + + return ctx->configs + language_id; +} rcc_language_config rccGetConfig(rcc_context ctx, rcc_language_id language_id) { int err; @@ -271,10 +282,12 @@ const char *rccConfigGetCurrentCharsetName(rcc_language_config config, rcc_class int rccConfigSetEngine(rcc_language_config config, rcc_engine_id engine_id) { unsigned int i; - if ((!config)||(!config->language)||(engine_id < 0)) return -1; + if ((!config)||(!config->language)||(engine_id < -1)) return -1; - for (i=0;config->language->engines[i];i++); - if (engine_id >= i) return -1; + if (engine_id != (rcc_engine_id)-1) { + for (i=0;config->language->engines[i];i++); + if (engine_id >= i) return -1; + } if (config->engine != engine_id) { if (config->ctx->current_config == config) config->ctx->configure = 1; @@ -285,7 +298,12 @@ int rccConfigSetEngine(rcc_language_config config, rcc_engine_id engine_id) { int rccConfigSetEngineByName(rcc_language_config config, const char *name) { rcc_engine_id engine_id; - + + if (!config) return -1; + + if ((!name)||(!strcasecmp(name,rcc_engine_nonconfigured))) + return rccConfigSetEngine(config, (rcc_engine_id)-1); + engine_id = rccConfigGetEngineByName(config, name); if (engine_id < 0) return -1; @@ -9,9 +9,32 @@ rcc_option_value rccGetOption(rcc_context ctx, rcc_option option) { return ctx->options[option]; } +int rccOptionIsDefault(rcc_context ctx, rcc_option option) { + if ((!ctx)||(option<0)||(option>=RCC_MAX_OPTIONS)) return -1; + + return ctx->default_options[option]; +} + int rccSetOption(rcc_context ctx, rcc_option option, rcc_option_value value) { if ((!ctx)||(option>=RCC_MAX_OPTIONS)) return -1; + ctx->default_options[option] = 0; + + if (ctx->options[option] != value) { + ctx->configure = 1; + ctx->options[option]=value; + } + + return 0; +} + +int rccOptionSetDefault(rcc_context ctx, rcc_option option) { + rcc_option_value value; + if ((!ctx)||(option>=RCC_MAX_OPTIONS)) return -1; + + ctx->default_options[option] = 1; + value = rccGetOptionDefaultValue(option); + if (ctx->options[option] != value) { ctx->configure = 1; ctx->options[option]=value; @@ -1,5 +1,10 @@ #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; #endif /* _RCC_OPT_H */ diff --git a/src/rccconfig.c b/src/rccconfig.c index 6d0a372..e1ac34a 100644 --- a/src/rccconfig.c +++ b/src/rccconfig.c @@ -3,6 +3,7 @@ #include "internal.h" #include "rccconfig.h" +#include "opt.h" static rcc_charset_id rcc_autoengine_russian(rcc_engine_context ctx, const char *buf, int len) { return (rcc_charset_id)rcdGetRussianCharset(buf,len); @@ -14,7 +15,8 @@ rcc_language_alias rcc_default_aliases[] = { { NULL, NULL} }; -const char rcc_engine_nonconfigured[] = "NonConfigured"; +const char rcc_engine_nonconfigured[] = "default"; +const char rcc_option_nonconfigured[] = "default"; rcc_engine rcc_default_engine = { "Off", NULL, NULL, NULL, {NULL} @@ -24,7 +26,7 @@ rcc_engine rcc_russian_engine = { "Russian", NULL, NULL, &rcc_autoengine_russian, {"CP1251","KOI8-R","UTF-8","IBM866", NULL} }; -rcc_language rcc_default_languages[] = { +rcc_language rcc_default_languages[RCC_MAX_LANGUAGES + 1] = { {"default", {"Default", NULL}, { &rcc_default_engine, NULL @@ -115,8 +117,71 @@ rcc_language_name rcc_default_language_names[RCC_MAX_LANGUAGES+1] = { }; rcc_option_name rcc_default_option_names[] = { - { RCC_LEARNING_MODE, "Learning Mode" }, - { RCC_AUTODETECT_FS_TITLES, "Autodetect FS Encoding" }, - { RCC_AUTODETECT_FS_NAMES, "Autodetect File Names" }, - { RCC_MAX_OPTIONS, NULL} + { RCC_LEARNING_MODE, "Learning Mode", "LEARNING_MODE" }, + { RCC_AUTODETECT_FS_TITLES, "Autodetect FS Encoding", "AUTODETECT_FS_TITLES" }, + { RCC_AUTODETECT_FS_NAMES, "Autodetect File Names", "AUTODETECT_FS_NAMES" }, + { RCC_MAX_OPTIONS, NULL, NULL} }; + +rcc_option_defval rcc_default_option_values[] = { + { RCC_LEARNING_MODE, 0 }, + { RCC_AUTODETECT_FS_TITLES, 1}, + { RCC_AUTODETECT_FS_NAMES, 1}, + { RCC_MAX_OPTIONS, 0} +}; + +const char *rccGetLanguageFullName(const char *lang) { + 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; + + return NULL; +} + +const char *rccGetOptionFullName(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].name; + + 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 8ca4810..89bbac8 100644 --- a/src/rccconfig.h +++ b/src/rccconfig.h @@ -8,6 +8,7 @@ extern rcc_language_alias rcc_default_aliases[]; extern const char rcc_engine_nonconfigured[]; +extern const char rcc_option_nonconfigured[]; extern rcc_engine rcc_default_engine; extern rcc_engine rcc_russian_engine; diff --git a/src/rccxml.c b/src/rccxml.c new file mode 100644 index 0000000..8283a39 --- /dev/null +++ b/src/rccxml.c @@ -0,0 +1,464 @@ +#include <stdio.h> +#include <stdarg.h> + +#include <unistd.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/file.h> + +#include <libxml/parser.h> +#include <libxml/tree.h> +#include <libxml/xpath.h> + +#include "internal.h" +#include "rccconfig.h" + +extern char *rcc_home_dir; + +#define MAX_HOME_CHARS 96 +#define XPATH_LANGUAGE "//Language[@name]" + +static xmlDocPtr xmlctx = NULL; + +static const char *rccXmlGetText(xmlNodePtr node) { + if ((node)&&(node->children)&&(node->children->type == XML_TEXT_NODE)&&(node->children->content)) return node->children->content; +} + +int rccXmlInit() { + FILE *f; + char config[MAX_HOME_CHARS + 32]; + + xmlXPathContextPtr xpathctx; + xmlXPathObjectPtr obj; + xmlNodeSetPtr node_set; + unsigned long i, nnodes; + xmlNodePtr cnode, pnode, node; + xmlAttrPtr attr; + const char *lang, *fullname; + unsigned int pos, cpos, npos; + + xmlInitParser(); + xmlInitCharEncodingHandlers(); + xmlKeepBlanksDefault(0); + + if (strlen(rcc_home_dir)>MAX_HOME_CHARS) config[0] = 0; + else { + sprintf(config, "%s/.rcc/rcc.xml", rcc_home_dir); + f = fopen(config, "r"); + if (f) fclose(f); + else config[0] = 0; + } + if (!config[0]) { + strcpy(config, "/etc/rcc.xml"); + f = fopen(config, "r"); + if (f) fclose(f); + else config[0] = 0; + } + + + // Load Extra Languages + if (config[0]) { + xmlctx = xmlReadFile(config, NULL, 0); + if (!xmlctx) goto clear; + + xpathctx = xmlXPathNewContext(xmlctx); + if (!xpathctx) goto clear; + + obj = xmlXPathEvalExpression(XPATH_LANGUAGE, xpathctx); + if (!obj) goto clear; + + node_set = obj->nodesetval; + if (!node_set) return 0; + + 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++); + puts("+++"); + + + nnodes = node_set->nodeNr; + for (i=0;i<nnodes;i++) { + pnode = node_set->nodeTab[i]; + attr = xmlHasProp(pnode, "name"); + lang = attr->children->content; + + if ((!lang)||(!lang[0])) continue; + puts(lang); + + for (cpos=1,fullname=NULL,node=pnode->children;node;node=node->next) { + if (node->type != XML_ELEMENT_NODE) continue; + puts(node->name); + if (!xmlStrcmp(node->name, "Charsets")) { + for (cpos = 0, cnode=node->children;cnode;cnode=cnode->next) { + if (cnode->type != XML_ELEMENT_NODE) continue; + if ((!xmlStrcmp(cnode->name, "Charset"))&&(rccXmlGetText(cnode))&&(cpos<RCC_MAX_CHARSETS)) { + rcc_default_languages[pos].charsets[cpos++] = rccXmlGetText(cnode); + } + } + } else if (!xmlStrcmp(node->name, "FullName")) { + if (rccXmlGetText(node)) fullname = rccXmlGetText(node); + } + } + + if (cpos > 1) { + rcc_default_languages[pos].sn = lang; + rcc_default_languages[pos].charsets[0] = "Default"; + 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; + } + } + +clear: + if (xmlctx) { + if (xpathctx) { + xmlXPathFreeContext(xpathctx); + if (obj) { + xmlXPathFreeObject(obj); + } + } + } + } +} + +void rccXmlFree() { + if (xmlctx) { + xmlFreeDoc(xmlctx); + xmlctx = NULL; + } + + xmlCleanupCharEncodingHandlers(); + xmlCleanupParser(); +} + + +static xmlNodePtr rccNodeFind(xmlXPathContextPtr xpathctx, const char *request, ...) { + xmlXPathObjectPtr obj; + xmlNodeSetPtr node_set; + xmlNodePtr res = NULL; + + unsigned int i, args = 0; + unsigned int size = 64; + va_list ap; + char *req; + + for (req = strstr(request, "%s"); req; req = strstr(req + 1, "%s")) args++; + + 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->nodeNr > 0) { + res = node_set->nodeTab[0]; + } + xmlXPathFreeObject(obj); + } + + if (args) free(req); + + return res; +} + +#define XPATH_SELECTED "/Config" +#define XPATH_SELECTED_LANGUAGE "/Config/Language" +#define XPATH_SELECTED_OPTIONS "/Config/Options" +#define XPATH_SELECTED_OPTION "/Config/Options/Option[@name=\"%s\"]" + +#define XPATH_SELECTED_LANGS "/Config/Languages" +#define XPATH_SELECTED_LANG "/Config/Languages/Language[@name=\"%s\"]" +#define XPATH_SELECTED_ENGINE "/Config/Languages/Language[@name=\"%s\"]/Engine" +#define XPATH_SELECTED_CLASSES "/Config/Languages/Language[@name=\"%s\"]/Classes" +#define XPATH_SELECTED_CLASS "/Config/Languages/Language[@name=\"%s\"]/Classes/Class[@name=\"%s\"]" + +int rccSave(rcc_context ctx, const char *name) { + int fd; + char *config; + struct stat st; + + unsigned int i, j, size; + + rcc_language_ptr *languages; + rcc_language_ptr language; + rcc_language_config cfg; + rcc_class_ptr *classes; + rcc_class_ptr cl; + + xmlXPathContextPtr xpathctx; + xmlDocPtr doc = NULL; + xmlNodePtr pnode, lnode, onode, llnode, cnode, enode, node; + unsigned char oflag = 0, llflag = 0, cflag; + const char *oname; + char value[16]; + + int memsize; + xmlChar *mem; + + if ((!name)||(!strcmp(name, "rcc"))||(strlen(rcc_home_dir)<3)) name = "default"; + + size = strlen(rcc_home_dir) + strlen(name) + 32; + config = (char*)malloc(size*sizeof(char)); + if (!config) return -1; + + sprintf(config,"%s/.rcc/",rcc_home_dir); + mkdir(config, 00644); + + sprintf(config,"%s/.rcc/%s.xml",rcc_home_dir,name); + fd = open(config, O_CREAT|O_RDWR,00644); + if (fd == -1) goto clear; + flock(fd, LOCK_EX); + + if ((!fstat(fd, &st))&&(st.st_size)) { + doc = xmlReadFd(fd, config, NULL, 0); + } + + if (!doc) { + doc = xmlNewDoc("1.0"); + if (!doc) goto clear; + } + + xpathctx = xmlXPathNewContext(doc); + if (!xpathctx) goto clear; + + pnode = rccNodeFind(xpathctx, XPATH_SELECTED); + if (pnode) { + lnode = rccNodeFind(xpathctx, XPATH_SELECTED_LANGUAGE); + onode = rccNodeFind(xpathctx, XPATH_SELECTED_OPTIONS); + llnode = rccNodeFind(xpathctx, XPATH_SELECTED_LANGS); + } else { + pnode = xmlNewChild((xmlNodePtr)doc, NULL, "Config", NULL); + lnode = NULL; + onode = NULL; + llnode = NULL; + } + + if (lnode) xmlNodeSetContent(lnode, rccGetSelectedLanguageName(ctx)); + else lnode = xmlNewChild(pnode,NULL, "Language", rccGetSelectedLanguageName(ctx)); + + if (onode) oflag = 1; + else onode = xmlNewChild(pnode, NULL, "Options", NULL); + + for (i=0;i<RCC_MAX_OPTIONS;i++) { + oname = rccGetOptionName(i); + 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)); + + if (node) xmlNodeSetContent(node, value); + else { + node = xmlNewChild(onode, NULL, "Option", value); + xmlSetProp(node, "name", oname); + } + } + + if (llnode) llflag = 1; + else llnode = xmlNewChild(pnode, NULL, "Languages", NULL); + + languages = ctx->languages; + classes = ctx->classes; + for (i=1;languages[i];i++) { + language = languages[i]; + cfg = rccCheckConfig(ctx, (rcc_language_id)i); + if (!cfg) continue; + + if (llflag) lnode = rccNodeFind(xpathctx, XPATH_SELECTED_LANG, language->sn); + else lnode = NULL; + + if (lnode) { + enode = rccNodeFind(xpathctx, XPATH_SELECTED_ENGINE, language->sn); + cnode = rccNodeFind(xpathctx, XPATH_SELECTED_CLASSES, language->sn); + } else { + lnode = xmlNewChild(llnode, NULL, "Language", NULL); + xmlSetProp(lnode, "name", language->sn); + enode = NULL; + cnode = NULL; + } + + if (enode) xmlNodeSetContent(enode, rccConfigGetSelectedEngineName(cfg)); + else xmlNewChild(lnode, NULL, "Engine", rccConfigGetSelectedEngineName(cfg)); + + if (cnode) cflag = 1; + else { + cnode = xmlNewChild(lnode, NULL, "Classes", NULL); + cflag = 0; + } + + for (j=0;classes[j];j++) { + cl = classes[j]; + + if (cflag) node = rccNodeFind(xpathctx, XPATH_SELECTED_CLASS, language->sn, cl->name); + else node = NULL; + + if (node) xmlNodeSetContent(node, rccConfigGetSelectedCharsetName(cfg, (rcc_class_id)j)); + else { + node = xmlNewChild(cnode, NULL, "Class", rccConfigGetSelectedCharsetName(cfg, (rcc_class_id)j)); + xmlSetProp(node, "name", cl->name); + } + } + } + + xmlDocDumpFormatMemory(doc,&mem,&memsize,1); + ftruncate(fd, 0); + lseek(fd, SEEK_SET, 0); + if (mem) { + write(fd, mem, memsize); + free(mem); + } + +clear: + if (config) { + if (fd != -1) { + if (doc) { + if (xpathctx) { + xmlXPathFreeContext(xpathctx); + } + xmlFreeDoc(doc); + } + fsync(fd); + flock(fd, LOCK_UN); + close(fd); + } + free(config); + } + + return 0; +} + +int rccLoad(rcc_context ctx, const char *name) { + int err; + + int fd; + char *config; + struct stat st; + + unsigned int i, j, size; + const char *tmp; + const char *oname; + + rcc_language_config cfg; + rcc_language_ptr *languages; + rcc_language_ptr language; + rcc_class_ptr *classes; + rcc_class_ptr cl; + + xmlXPathContextPtr xpathctx; + xmlDocPtr doc = NULL; + xmlNodePtr node, lnode; + + if ((!name)||(!strcmp(name, "rcc"))||(strlen(rcc_home_dir)<3)) name = "default"; + + size = strlen(rcc_home_dir) + strlen(name) + 32; + config = (char*)malloc(size*sizeof(char)); + if (!config) return -1; + + sprintf(config,"%s/.rcc/%s.xml",rcc_home_dir,name); + fd = open(config, O_RDONLY); + if (fd == -1) goto clear; + flock(fd, LOCK_EX); + + if ((!fstat(fd, &st))&&(st.st_size)) { + doc = xmlReadFd(fd, config, NULL, 0); + } else goto clear; + + xpathctx = xmlXPathNewContext(doc); + if (!xpathctx) goto clear; + + node = rccNodeFind(xpathctx, XPATH_SELECTED_LANGUAGE); + if (node) { + tmp = rccXmlGetText(node); + if (tmp) err = rccSetLanguageByName(ctx, tmp); + else err = -1; + } else err = -1; + if (err) rccSetLanguage(ctx, 0); + + for (i=0;i<RCC_MAX_OPTIONS;i++) { + oname = rccGetOptionName((rcc_option)i); + if (!oname) continue; + + node = rccNodeFind(xpathctx, 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)); + else err = -1; + } else err = -1; + if (err) rccOptionSetDefault(ctx, (rcc_option)i); + } + + + languages = ctx->languages; + classes = ctx->classes; + for (i=1;languages[i];i++) { + language = languages[i]; + + lnode = rccNodeFind(xpathctx, XPATH_SELECTED_LANG, language->sn); + if (!lnode) continue; + + cfg = rccGetConfig(ctx, (rcc_language_id)i); + if (!cfg) continue; + + node = rccNodeFind(xpathctx, XPATH_SELECTED_ENGINE, language->sn); + if (node) { + tmp = rccXmlGetText(node); + if (tmp) err = rccConfigSetEngineByName(cfg, tmp); + else err = -1; + } else err = -1; + if (err) rccConfigSetEngineByName(cfg, NULL); + + for (j=0;classes[j];j++) { + cl = classes[j]; + + node = rccNodeFind(xpathctx, XPATH_SELECTED_CLASS, language->sn, cl->name); + if (node) { + tmp = rccXmlGetText(node); + if (tmp) err = rccConfigSetCharsetByName(cfg, (rcc_class_id)j, tmp); + else err = -1; + } else err = -1; + if (err) rccConfigSetCharset(cfg, (rcc_class_id)j, 0); + } + } + +clear: + if (config) { + if (fd != -1) { + if (doc) { + if (xpathctx) { + xmlXPathFreeContext(xpathctx); + } + xmlFreeDoc(doc); + } + close(fd); + } + free(config); + } + + return 0; +} @@ -1,4 +1,7 @@ #ifndef _RCC_XML_H #define _RCC_XML_H +int rccXmlInit(); +void rccXmlFree(); + #endif /* _RCC_XML_H */ diff --git a/src/xml.c b/src/xml.c deleted file mode 100644 index 459bccf..0000000 --- a/src/xml.c +++ /dev/null @@ -1,14 +0,0 @@ -#include <stdio.h> -#include "internal.h" - -/* pass programm name */ - -/* Load and Then Save */ -/* flock */ -int rccSave(rcc_context ctx, const char *name) { - return 0; -} - -int rccLoad(rcc_context ctx, const char *name) { - return 0; -} @@ -53,7 +53,6 @@ int rccUiMenuSet(rcc_ui_menu_context ctx, rcc_ui_id id) { static int rccGtkMenuLanguageCB(GtkWidget * w, gpointer item) { - puts("LanguageCB!!!!!!!!!!!!!!!!!!!!!!"); rccUiRestoreLanguage(((rcc_ui_menu_context)item)->uictx); } @@ -184,8 +183,11 @@ rcc_ui_box rccUiBoxCreate(rcc_ui_menu_context ctx, const char *title) { return (rcc_ui_box)hbox; } -rcc_ui_frame rccUiFrameCreate(rcc_ui_context ctx, const char *title) { +rcc_ui_frame rccUiFrameCreate(rcc_ui_frame_context ctx, const char *title) { GtkWidget *frame, *box; + + if (!ctx) return NULL; + frame = gtk_frame_new(title?title:""); gtk_container_border_width(GTK_CONTAINER(frame), FRAME_BORDER); @@ -195,10 +197,16 @@ rcc_ui_frame rccUiFrameCreate(rcc_ui_context ctx, const char *title) { return (rcc_ui_frame)frame; } -int rccUiFrameAdd(rcc_ui_frame frame, rcc_ui_box box) { +void rccUiFrameFree(rcc_ui_frame_context ctx) { +} + + +int rccUiFrameAdd(rcc_ui_frame_context ctx, rcc_ui_box box) { GtkWidget *vbox; - vbox = gtk_container_children(GTK_CONTAINER(frame))->data; + if ((!ctx)||(!box)) return -1; + + vbox = gtk_container_children(GTK_CONTAINER(ctx->frame))->data; gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(box), FALSE, FALSE, 0); return 0; } diff --git a/ui/internal.h b/ui/internal.h index a16c506..8448fb5 100644 --- a/ui/internal.h +++ b/ui/internal.h @@ -5,7 +5,7 @@ #include "librccui.h" typedef unsigned int rcc_ui_id; -typedef void *rcc_ui_internal; + typedef void *rcc_ui_menu_internal; enum rcc_ui_menu_type_t { @@ -30,6 +30,30 @@ struct rcc_ui_menu_context_t { typedef struct rcc_ui_menu_context_t rcc_ui_menu_context_s; typedef struct rcc_ui_menu_context_t *rcc_ui_menu_context; +typedef void *rcc_ui_frame_internal; + +enum rcc_ui_frame_type_t { + RCC_UI_FRAME_LANGUAGE = 0, + RCC_UI_FRAME_CHARSETS, + RCC_UI_FRAME_ENGINE, + RCC_UI_FRAME_MAX +}; +typedef enum rcc_ui_frame_type_t rcc_ui_frame_type; + +struct rcc_ui_frame_context_t { + rcc_ui_frame frame; + + rcc_ui_context uictx; + rcc_ui_frame_type type; + + rcc_ui_frame_internal internal; +}; +typedef struct rcc_ui_frame_context_t rcc_ui_frame_context_s; +typedef struct rcc_ui_frame_context_t *rcc_ui_frame_context; + + +typedef void *rcc_ui_internal; + struct rcc_ui_context_t { rcc_context rccctx; @@ -43,9 +67,9 @@ struct rcc_ui_context_t { rcc_language_name *language_names; rcc_option_name *option_names; - rcc_ui_frame language_frame; - rcc_ui_frame charset_frame; - rcc_ui_frame engine_frame; + rcc_ui_frame_context language_frame; + rcc_ui_frame_context charset_frame; + rcc_ui_frame_context engine_frame; rcc_ui_page page; }; @@ -63,8 +87,11 @@ rcc_ui_id rccUiMenuGet(rcc_ui_menu_context ctx); int rccUiMenuSet(rcc_ui_menu_context ctx, rcc_ui_id id); rcc_ui_box rccUiBoxCreate(rcc_ui_menu_context ctx, const char *title); -rcc_ui_frame rccUiFrameCreate(rcc_ui_context ctx, const char *title); -int rccUiFrameAdd(rcc_ui_frame frame, rcc_ui_box box); + +rcc_ui_frame rccUiFrameCreate(rcc_ui_frame_context ctx, const char *title); +void rccUiFrameFree(rcc_ui_frame_context ctx); +int rccUiFrameAdd(rcc_ui_frame_context ctx, rcc_ui_box box); + rcc_ui_page rccUiPageCreate(rcc_ui_context ctx, const char *title); int rccUiPageAdd(rcc_ui_page page, rcc_ui_frame frame); diff --git a/ui/librccui.c b/ui/librccui.c index 060ada3..c868708 100644 --- a/ui/librccui.c +++ b/ui/librccui.c @@ -28,6 +28,27 @@ static void rccUiMenuFreeContext(rcc_ui_menu_context ctx) { free(ctx); } +static rcc_ui_frame_context rccUiFrameCreateContext(rcc_ui_frame_type type, rcc_ui_context uictx) { + rcc_ui_frame_context ctx; + if ((!uictx)||(type>RCC_UI_FRAME_MAX)) return NULL; + + ctx = (rcc_ui_frame_context)malloc(sizeof(rcc_ui_frame_context_s)); + if (!ctx) return ctx; + + ctx->uictx = uictx; + ctx->type = type; + + ctx->frame = NULL; + + return ctx; +} + +static void rccUiFrameFreeContext(rcc_ui_frame_context ctx) { + if (!ctx) return; + rccUiFrameFree(ctx); + free(ctx); +} + rcc_ui_context rccUiCreateContext(rcc_context rccctx) { int err = 0; unsigned int i; @@ -55,17 +76,12 @@ rcc_ui_context rccUiCreateContext(rcc_context rccctx) { return NULL; } - ctx->language_frame = NULL; - ctx->charset_frame = NULL; - ctx->engine_frame = NULL; - ctx->page = NULL; - ctx->options = options; ctx->charsets = charsets; ctx->rccctx = rccctx; - ctx->language_names = rcc_default_language_names; - ctx->option_names = rcc_default_option_names; + ctx->language_names = NULL; + ctx->option_names = NULL; ctx->internal = rccUiCreateInternal(ctx); @@ -81,7 +97,13 @@ rcc_ui_context rccUiCreateContext(rcc_context rccctx) { if (!options[i]) err = 1; } - if ((err)||(!ctx->language)||(!ctx->engine)) { + ctx->language_frame = rccUiFrameCreateContext(RCC_UI_FRAME_LANGUAGE, ctx); + ctx->charset_frame = rccUiFrameCreateContext(RCC_UI_FRAME_CHARSETS, ctx); + ctx->engine_frame = rccUiFrameCreateContext(RCC_UI_FRAME_ENGINE, ctx); + ctx->page = NULL; + + + if ((err)||(!ctx->language)||(!ctx->engine)||(!ctx->language_frame)||(!ctx->charset_frame)||(!ctx->engine_frame)) { rccUiFreeContext(ctx); return NULL; } @@ -96,7 +118,11 @@ void rccUiFreeContext(rcc_ui_context ctx) { if (!ctx) return; rccUiFreeInternal(ctx); - + + if (ctx->engine_frame) rccUiFrameFreeContext(ctx->engine_frame); + if (ctx->charset_frame) rccUiFrameFreeContext(ctx->charset_frame); + if (ctx->language_frame) rccUiFrameFreeContext(ctx->language_frame); + if (ctx->charsets) { classes = rccGetClassList(ctx->rccctx); for (i=0; classes[i]; i++) @@ -219,7 +245,6 @@ rcc_ui_widget rccUiGetCharsetMenu(rcc_ui_context ctx, rcc_class_id id) { classes = rccGetClassList(ctx->rccctx); for (i=0;classes[i];i++); - printf("Recalc: %i %i\n", id, i); if (id>=i) return NULL; if (rccUiMenuConfigureWidget(ctx->charsets[id])) return NULL; @@ -265,7 +290,6 @@ rcc_ui_box rccUiGetCharsetBox(rcc_ui_context ctx, rcc_class_id id, const char *t classes = rccGetClassList(ctx->rccctx); for (i=0; classes[i]; i++); - printf("Charset Box: %i %i\n", id, i); if (id>=i) return NULL; if (ctx->charsets[id]->box) return ctx->charsets[id]->box; @@ -274,10 +298,7 @@ rcc_ui_box rccUiGetCharsetBox(rcc_ui_context ctx, rcc_class_id id, const char *t charset = rccUiGetCharsetMenu(ctx, id); if (!charset) return NULL; - puts("Charset Box Pre"); - printf("%p %p\n", ctx->charsets[id], ctx->charsets[id]->widget); ctx->charsets[id]->box = rccUiBoxCreate(ctx->charsets[id], title); - puts("Charset Box Post"); return ctx->charsets[id]->box; } @@ -297,38 +318,35 @@ rcc_ui_box rccUiGetEngineBox(rcc_ui_context ctx, const char *title) { rcc_ui_box rccUiGetOptionBox(rcc_ui_context ctx, rcc_option option, const char *title) { rcc_ui_widget opt; - printf("Option Strt: %i %p\n", option, title); if ((!ctx)||(option<0)||(option>=RCC_MAX_OPTIONS)) return NULL; if (ctx->options[option]->box) return ctx->options[option]->box; - puts("=== Option Box ==="); opt = rccUiGetOptionMenu(ctx, option); if (!opt) return NULL; - puts("Option Menu"); ctx->options[option]->box = rccUiBoxCreate(ctx->options[option], title); - puts("Option Finish"); return ctx->options[option]->box; } rcc_ui_frame rccUiGetLanguageFrame(rcc_ui_context ctx, const char *title) { + rcc_ui_frame_context framectx; rcc_ui_frame frame; rcc_ui_box language; if (!ctx) return NULL; - - if (ctx->language_frame) return ctx->language_frame; - frame = rccUiFrameCreate(ctx, title); - if (!frame) return NULL; + framectx = ctx->language_frame; + if (framectx->frame) return framectx->frame; + + frame = rccUiFrameCreate(ctx->language_frame, title); + if (frame) framectx->frame = frame; + else return NULL; language = rccUiGetLanguageBox(ctx, title); if (!language) return NULL; - rccUiFrameAdd(frame, language); - - ctx->language_frame = frame; + rccUiFrameAdd(framectx, language); return frame; } @@ -336,25 +354,27 @@ rcc_ui_frame rccUiGetLanguageFrame(rcc_ui_context ctx, const char *title) { rcc_ui_frame rccUiGetCharsetsFrame(rcc_ui_context ctx, const char *title) { unsigned int i; rcc_class_ptr *classes; + rcc_ui_frame_context framectx; rcc_ui_frame frame; rcc_ui_box charset; if (!ctx) return NULL; - if (ctx->charset_frame) return ctx->charset_frame; + framectx = ctx->charset_frame; + if (framectx->frame) return framectx->frame; - frame = rccUiFrameCreate(ctx, title); - if (!frame) return NULL; + frame = rccUiFrameCreate(framectx, title); + if (frame) framectx->frame = frame; + else return NULL; classes = rccGetClassList(ctx->rccctx); for (i=0; classes[i]; i++) { if (classes[i]->fullname) { charset = rccUiGetCharsetBox(ctx, (rcc_class_id)i, classes[i]->fullname); - rccUiFrameAdd(frame, charset); + rccUiFrameAdd(framectx, charset); } } - ctx->charset_frame = frame; return frame; } @@ -362,30 +382,28 @@ rcc_ui_frame rccUiGetCharsetsFrame(rcc_ui_context ctx, const char *title) { rcc_ui_frame rccUiGetEngineFrame(rcc_ui_context ctx, const char *title) { unsigned int i; + rcc_ui_frame_context framectx; rcc_ui_frame frame; rcc_ui_box engine; rcc_ui_box opt; if (!ctx) return NULL; - if (ctx->engine_frame) return ctx->engine_frame; + framectx = ctx->engine_frame; + if (framectx->frame) return framectx->frame; - frame = rccUiFrameCreate(ctx, title); - if (!frame) return NULL; + frame = rccUiFrameCreate(framectx, title); + if (frame) framectx->frame = frame; + else return NULL; engine = rccUiGetEngineBox(ctx, title); - puts("Engine"); - rccUiFrameAdd(frame, engine); - puts("Added"); + rccUiFrameAdd(framectx, engine); for (i=0; i<RCC_MAX_OPTIONS; i++) { - printf("OptionBox: %u\n", i); opt = rccUiGetOptionBox(ctx, (rcc_option)i, rccUiGetOptionName(ctx, i)); - rccUiFrameAdd(frame, opt); + rccUiFrameAdd(framectx, opt); } - ctx->engine_frame = frame; - return frame; } @@ -401,18 +419,14 @@ rcc_ui_page rccUiGetPage(rcc_ui_context ctx, const char *title, const char *lang page = rccUiPageCreate(ctx, title); if (!page) return NULL; - puts("P C"); frame = rccUiGetLanguageFrame(ctx, language_title); rccUiPageAdd(page, frame); - puts("L C"); frame = rccUiGetCharsetsFrame(ctx, charset_title); rccUiPageAdd(page, frame); - puts("C C"); frame = rccUiGetEngineFrame(ctx, engine_title); rccUiPageAdd(page, frame); - puts("E C"); ctx->page = page; diff --git a/ui/rccnames.c b/ui/rccnames.c index 961dbbc..2e11165 100644 --- a/ui/rccnames.c +++ b/ui/rccnames.c @@ -3,29 +3,42 @@ #include "internal.h" const char *rccUiGetLanguageName(rcc_ui_context ctx, const char *lang) { + const char *res; unsigned int i; rcc_language_name *names; if ((!ctx)||(!lang)) return NULL; - + names = ctx->language_names; + + if (names) { + for (i=0;names[i].sn;i++) + if (!strcmp(lang, names[i].sn)) return names[i].name; + } - for (i=0;names[i].sn;i++) - if (!strcmp(lang, names[i].sn)) return names[i].name; + + res = rccGetLanguageFullName(lang); + if (res) return res; return lang; } const char *rccUiGetOptionName(rcc_ui_context ctx, rcc_option option) { + const char *res; unsigned int i; rcc_option_name *names; - if (!ctx) return NULL; + if ((!ctx)||(option<0)||(option>RCC_MAX_OPTIONS)) return NULL; names = ctx->option_names; - for (i=0;((i<RCC_MAX_OPTIONS)&&(names[i].option!=RCC_MAX_OPTIONS));i++) - if (names[i].option == option) return names[i].name; + 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; + } + + res = rccGetOptionFullName(option); + if (res) return res; - return NULL; + return ""; } |