8 #define INTERNAL_ENCODING "UTF8"
9 #define ENCODING_CONF_FILE "gedcom.enc"
12 static iconv_t cd_to_internal = (iconv_t) -1;
13 static char int_buf[MAXGEDCLINELEN*2];
14 static void *encoding_mapping = NULL;
15 static ENCODING the_enc = ONE_BYTE;
22 char* charwidth_string[] = { "1", "2_HILO", "2_LOHI" };
24 int node_compare(const void *node1, const void *node2)
26 return strcmp(((const struct node *) node1)->gedcom_name,
27 ((const struct node *) node2)->gedcom_name);
30 void add_encoding(char *gedcom_n, char* charwidth, char *iconv_n)
33 struct node *nodeptr = (struct node *) malloc(sizeof *nodeptr);
34 nodeptr->gedcom_name = (char *) malloc(strlen(gedcom_n)
35 + strlen(charwidth) + 3);
36 nodeptr->iconv_name = (char *) malloc(strlen(iconv_n) + 1);
37 sprintf(nodeptr->gedcom_name, "%s(%s)", gedcom_n, charwidth);
38 strcpy(nodeptr->iconv_name, iconv_n);
39 datum = tsearch(nodeptr, &encoding_mapping, node_compare);
40 if ((datum == NULL) || (*datum != nodeptr)) {
41 gedcom_warning("Duplicate entry found for encoding '%s', ignoring",
46 char* get_encoding(char* gedcom_n, ENCODING enc)
49 struct node search_node;
50 char buffer[MAXBUF + 1];
51 sprintf(buffer, "%s(%s)", gedcom_n, charwidth_string[enc]);
52 search_node.gedcom_name = buffer;
53 datum = tfind(&search_node, &encoding_mapping, node_compare);
55 gedcom_error("No encoding found for '%s'", gedcom_n);
59 return ((const struct node *) *datum)->iconv_name;
65 if (encoding_mapping == NULL) {
67 char buffer[MAXBUF + 1];
68 char gedcom_n[MAXBUF + 1];
69 char charwidth[MAXBUF + 1];
70 char iconv_n[MAXBUF + 1];
71 in = fopen(ENCODING_CONF_FILE, "r");
73 while (fgets(buffer, sizeof(buffer), in) != NULL) {
74 if (buffer[strlen(buffer) - 1] != '\n') {
75 gedcom_error("Line too long in encoding configuration file '%s'",
79 else if (buffer[0] != '#') {
80 if (sscanf(buffer, "%s %s %s", gedcom_n, charwidth, iconv_n) == 3) {
81 add_encoding(gedcom_n, charwidth, iconv_n);
84 gedcom_error("Missing data in encoding configuration file '%s'",
93 gedcom_warning("Could not open encoding configuration file '%s'",
99 void set_encoding_width(ENCODING enc)
104 static char conv_buf[MAXGEDCLINELEN * 2];
105 static int conv_buf_size;
107 int open_conv_to_internal(char* fromcode)
109 char *encoding = get_encoding(fromcode, the_enc);
110 if (cd_to_internal != (iconv_t) -1)
111 iconv_close(cd_to_internal);
112 if (encoding == NULL) {
113 cd_to_internal = (iconv_t) -1;
116 memset(conv_buf, 0, sizeof(conv_buf));
118 cd_to_internal = iconv_open(INTERNAL_ENCODING, encoding);
120 return (cd_to_internal != (iconv_t) -1);
123 void close_conv_to_internal()
125 iconv_close(cd_to_internal);
126 cd_to_internal = (iconv_t) -1;
129 char* to_internal(char* str, size_t len)
132 size_t outsize = MAXGEDCLINELEN * 2;
133 char *wrptr = int_buf;
134 char *rdptr = conv_buf;
135 /* set up input buffer (concatenate to what was left previous time) */
136 /* can't use strcpy, because possible null bytes from unicode */
137 memcpy(conv_buf + conv_buf_size, str, len);
138 conv_buf_size += len;
139 insize = conv_buf_size;
140 /* set up output buffer (empty it) */
141 memset(int_buf, 0, sizeof(int_buf));
142 /* do the conversion */
143 iconv(cd_to_internal, &rdptr, &insize, &wrptr, &outsize);
144 /* then shift what is left over to the head of the input buffer */
145 memmove(conv_buf, rdptr, insize);
146 memset(conv_buf + insize, 0, sizeof(conv_buf) - insize);
147 conv_buf_size = insize;