#include <fcntl.h>
#define MAXWRITELEN MAXGEDCLINELEN
-#define MAXCHARSETLEN 32
-char charset[MAXCHARSETLEN+1] = "ASCII";
-const char* encoding = "ASCII";
-int write_encoding_details = ONE_BYTE;
/* SYS_NEWLINE is defined in config.h */
-const char* write_terminator = SYS_NEWLINE;
+struct encoding_state write_encoding =
+{ "ASCII", "ASCII", ONE_BYTE, WITHOUT_BOM, SYS_NEWLINE };
+Enc_from write_encoding_from = ENC_FROM_FILE;
+Enc_from write_terminator_from = ENC_FROM_SYS;
struct Gedcom_write_struct {
int filedesc;
return 0;
}
-int write_encoding(Gedcom_write_hndl hndl,
- int level, char* xref, char* tag, char* value)
+int write_encoding_value(Gedcom_write_hndl hndl,
+ int level, char* xref, char* tag, char* value)
{
- if (strcmp(value, charset))
- gedcom_warning(_("Forcing HEAD.CHAR value to '%s'"), charset);
- return write_simple(hndl, level, xref, tag, charset);
+ if (strcmp(value, write_encoding.charset))
+ gedcom_warning(_("Forcing HEAD.CHAR value to '%s'"),
+ write_encoding.charset);
+ return write_simple(hndl, level, xref, tag, write_encoding.charset);
}
int supports_continuation(int elt_or_rec, int which_continuation)
int cont_supported = supports_continuation(elt_or_rec, OPT_CONT);
int cont_as_conc = supports_continuation(elt_or_rec, OPT_CONT_AS_CONC);
if (nl_pos && !cont_supported) {
- gedcom_error (_("The tag %s doesn't support newlines\n"), tag);
+ gedcom_error (_("The tag %s doesn't support newlines"), tag);
return 1;
}
else {
return 0;
}
-int gedcom_write_set_encoding(const char* new_charset,
+int gedcom_write_set_encoding(Enc_from from, const char* new_charset,
Encoding width, Enc_bom bom)
{
char* new_encoding = NULL;
- if (!strcmp(new_charset, "UNICODE")) {
- if (width == ONE_BYTE) {
- gedcom_error(_("Unicode cannot be encoded into one byte"));
- return 1;
+ if (from == ENC_FROM_SYS) {
+ return 1;
+ }
+ write_encoding_from = from;
+ if (from == ENC_MANUAL) {
+ if (!strcmp(new_charset, "UNICODE")) {
+ if (width == ONE_BYTE) {
+ gedcom_error(_("Unicode cannot be encoded into one byte"));
+ return 1;
+ }
+ else {
+ new_encoding = get_encoding(new_charset, width);
+ if (new_encoding) {
+ write_encoding.encoding = new_encoding;
+ write_encoding.width = width;
+ write_encoding.bom = bom;
+ strncpy(write_encoding.charset, new_charset, MAX_CHARSET_LEN);
+ }
+ else
+ return 1;
+ }
}
else {
- new_encoding = get_encoding(new_charset, width);
+ new_encoding = get_encoding(new_charset, ONE_BYTE);
if (new_encoding) {
- encoding = new_encoding;
- write_encoding_details = width | bom;
- strncpy(charset, new_charset, MAXCHARSETLEN);
+ write_encoding.encoding = new_encoding;
+ write_encoding.width = ONE_BYTE;
+ write_encoding.bom = bom;
+ strncpy(write_encoding.charset, new_charset, MAX_CHARSET_LEN);
}
else
return 1;
}
}
- else {
- new_encoding = get_encoding(new_charset, ONE_BYTE);
- if (new_encoding) {
- encoding = new_encoding;
- write_encoding_details = ONE_BYTE;
- strncpy(charset, new_charset, MAXCHARSETLEN);
- }
- else
- return 1;
- }
return 0;
}
-int gedcom_write_set_line_terminator(Enc_line_end end)
+void copy_write_encoding_from_file()
+{
+ if (read_encoding.charset[0] != '\0') {
+ strncpy(write_encoding.charset, read_encoding.charset, MAX_CHARSET_LEN);
+ write_encoding.encoding = read_encoding.encoding;
+ write_encoding.width = read_encoding.width;
+ write_encoding.bom = read_encoding.bom;
+ }
+}
+
+int gedcom_write_set_line_terminator(Enc_from from, Enc_line_end end)
{
- write_terminator = terminator[end];
+ const char* new_term = NULL;
+ write_terminator_from = from;
+ if (from == ENC_FROM_SYS) {
+ new_term = SYS_NEWLINE;
+ }
+ else if (from == ENC_MANUAL) {
+ new_term = terminator[end];
+ }
+ if (new_term)
+ strncpy(write_encoding.terminator, new_term, MAX_TERMINATOR_LEN);
return 0;
}
+void copy_write_terminator_from_file()
+{
+ if (read_encoding.terminator[0] != '\0') {
+ strncpy(write_encoding.terminator, read_encoding.terminator,
+ MAX_TERMINATOR_LEN);
+ }
+}
+
Gedcom_write_hndl gedcom_write_open(const char *filename)
{
Gedcom_write_hndl hndl;
if (!hndl)
MEMORY_ERROR;
else {
+ if (write_encoding_from == ENC_FROM_FILE)
+ copy_write_encoding_from_file();
+ if (write_terminator_from == ENC_FROM_FILE)
+ copy_write_terminator_from_file();
hndl->total_conv_fails = 0;
- hndl->conv = initialize_utf8_conversion(encoding, 0);
+ hndl->conv = initialize_utf8_conversion(write_encoding.encoding, 0);
if (!hndl->conv) {
gedcom_error(_("Could not open encoding '%s' for writing: %s"),
- encoding, strerror(errno));
+ write_encoding.encoding, strerror(errno));
free(hndl);
hndl = NULL;
}
hndl = NULL;
}
else {
- hndl->term = write_terminator;
+ hndl->term = write_encoding.terminator;
hndl->ctxt_level = -1;
- if (write_encoding_details & WITH_BOM) {
- if (write_encoding_details & TWO_BYTE_HILO)
+ if (write_encoding.bom == WITH_BOM) {
+ if (write_encoding.width == TWO_BYTE_HILO)
write(hndl->filedesc, "\xFE\xFF", 2);
- else if (write_encoding_details & TWO_BYTE_LOHI)
+ else if (write_encoding.width == TWO_BYTE_LOHI)
write(hndl->filedesc, "\xFF\xFE", 2);
+ else if (!strcmp(write_encoding.encoding, "UTF-8"))
+ write(hndl->filedesc, "\xEF\xBB\xBF", 3);
else
- gedcom_warning(_("Byte order mark configured, but no Unicode"));
+ gedcom_warning(_("Byte order mark configured, but not relevant"));
}
}
}
}
}
else {
- gedcom_error(_("The element or record type '%s' requires a specific tag"
+ gedcom_error(_("The element or record type '%s' requires a specific tag "
"for writing"),
tag_data[elt_or_rec].elt_name);
return NULL;
level = get_level(hndl, rec_or_elt, parent_rec_or_elt);
if (tag_str && (level != -1)) {
if (rec_or_elt == ELT_HEAD_CHAR)
- result = write_encoding(hndl, level, xrefstr, tag_str, val);
+ result = write_encoding_value(hndl, level, xrefstr, tag_str, val);
else if (supports_continuation(rec_or_elt, OPT_CONT|OPT_CONC))
result = write_long(hndl, rec_or_elt, level, xrefstr, tag_str, val);
else