summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am2
-rw-r--r--src/internal.h1
-rw-r--r--src/librcc.c71
-rw-r--r--src/librcc.h15
-rw-r--r--src/lngconfig.c26
-rw-r--r--src/opt.c23
-rw-r--r--src/opt.h5
-rw-r--r--src/rccconfig.c77
-rw-r--r--src/rccconfig.h1
-rw-r--r--src/rccxml.c464
-rw-r--r--src/rccxml.h (renamed from src/xml.h)3
-rw-r--r--src/xml.c14
12 files changed, 670 insertions, 32 deletions
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;
diff --git a/src/opt.c b/src/opt.c
index 85960df..82e1be1 100644
--- a/src/opt.c
+++ b/src/opt.c
@@ -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;
diff --git a/src/opt.h b/src/opt.h
index 566cf1e..c10a53d 100644
--- a/src/opt.h
+++ b/src/opt.h
@@ -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;
+}
diff --git a/src/xml.h b/src/rccxml.h
index 3286a8e..3f0382e 100644
--- a/src/xml.h
+++ b/src/rccxml.h
@@ -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;
-}