X-Git-Url: https://git.dlugolecki.net.pl/?a=blobdiff_plain;f=gedcom%2Fcompat.c;h=833bac1dede62236970cf8dcd20d0cc311177101;hb=a549f1db4f3cd24e46cacf05cb4bec6eecce6570;hp=be9b3a1ae4210546740cde88295f83435b9b3a76;hpb=98a5cf857ba2bc9f574b924bc7e96d5e50c0a4db;p=gedcom-parse.git diff --git a/gedcom/compat.c b/gedcom/compat.c index be9b3a1..833bac1 100644 --- a/gedcom/compat.c +++ b/gedcom/compat.c @@ -30,7 +30,9 @@ #include "gedcom.h" int compat_enabled = 1; -int compatibility = 0; +int compatibility = 0; +int compatibility_program = 0; +int compatibility_version = 0; const char* default_charset = ""; #define SUBMITTER_LINK "@__COMPAT__SUBM__@" @@ -39,10 +41,27 @@ const char* default_charset = ""; #define DEFAULT_GEDCOM_VERS "5.5" #define DEFAULT_GEDCOM_FORM "LINEAGE-LINKED" +enum _COMPAT_PROGRAM { + CP_FTREE = 1, + CP_LIFELINES, + CP_PAF, + CP_FAMORIG +}; + +const char* program_name[] = { + /* NULL */ "", + /* CP_FTREE */ "ftree", + /* CP_LIFELINES */ "Lifelines", + /* CP_PAF */ "Personal Ancestral File", + /* CP_FAMORIG */ "Family Origins" +}; + enum _COMPAT { C_FTREE = 0x01, C_LIFELINES = 0x02, - C_PAF = 0x04 + C_PAF5 = 0x04, + C_PAF2 = 0x08, + C_FAMORIG = 0x10 }; /* Incompatibility list (with GEDCOM 5.5): @@ -60,24 +79,34 @@ enum _COMPAT { - '@' not written as '@@' in values - lots of missing required values - - Personal Ancestral File: + - Personal Ancestral File 5: - '@' not written as '@@' in values - some 5.5.1 (draft) tags are used: EMAIL, FONE, ROMN - no FAMC field in SLGC + + - Personal Ancestral File 2: + - '@' not written as '@@' in values + - COMM tag in submitter record + - double dates written as e.g. '1815/1816' instead of '1815/16' + + - Family Origins: + - '@' not written as '@@' in values */ int compat_matrix[] = { - /* C_NO_SUBMITTER */ C_FTREE | C_LIFELINES, + /* C_NO_SUBMITTER */ C_FTREE | C_LIFELINES | C_PAF2, /* C_INDI_ADDR */ C_FTREE, /* C_NOTE_NO_VALUE */ C_FTREE, - /* C_NO_GEDC */ C_LIFELINES, + /* C_NO_GEDC */ C_LIFELINES | C_PAF2, /* C_NO_CHAR */ C_LIFELINES, /* C_HEAD_TIME */ C_LIFELINES, - /* C_NO_DOUBLE_AT */ C_LIFELINES | C_PAF, + /* C_NO_DOUBLE_AT */ C_LIFELINES | C_PAF5 | C_PAF2 | C_FAMORIG, /* C_NO_REQUIRED_VALUES */ C_LIFELINES, - /* C_551_TAGS */ C_PAF, - /* C_NO_SLGC_FAMC */ C_PAF + /* C_551_TAGS */ C_PAF5, + /* C_NO_SLGC_FAMC */ C_PAF5, + /* C_SUBM_COMM */ C_PAF2, + /* C_DOUBLE_DATES_4 */ C_PAF2 }; int compat_state[C_NR_OF_RULES]; @@ -89,34 +118,100 @@ void gedcom_set_compat_handling(int enable_compat) compat_enabled = enable_compat; } -void enable_compat_msg(const char* program_name) +void enable_compat_msg(const char* program_name, int version) +{ + if (version > 0) + gedcom_warning(_("Enabling compatibility with '%s', version %d"), + program_name, version); + else + gedcom_warning(_("Enabling compatibility with '%s'"), + program_name); +} + +int program_equal(const char* program, const char* compare) +{ + return !strncmp(program, compare, strlen(compare)+1); +} + +int program_equal_continued(const char* program, const char* compare) +{ + size_t len = strlen(compare); + int result = strncmp(program, compare, len); + if (result == 0) { + if (strlen(program) > len) + set_compatibility_version(program + len); + } + return !result; +} + +void set_compatibility_program(const char* program) { - gedcom_warning(_("Enabling compatibility with '%s'"), program_name); + compatibility_program = 0; + if (compat_enabled) { + if (program_equal(program, "ftree")) { + compatibility_program = CP_FTREE; + } + else if (program_equal_continued(program, "LIFELINES")) { + compatibility_program = CP_LIFELINES; + } + else if (program_equal_continued(program, "PAF")) { + compatibility_program = CP_PAF; + } + else if (program_equal(program, "FamilyOrigins")) { + compatibility_program = CP_FAMORIG; + } + } } -void set_compatibility(const char* program) +void compute_compatibility() { /* Reinitialize compatibility */ int i; + int version = 0; default_charset = ""; compatibility = 0; for (i = 0; i < C_NR_OF_RULES; i++) compat_state[i] = 0; - - if (compat_enabled) { - if (! strncmp(program, "ftree", 6)) { - enable_compat_msg("ftree"); + + switch (compatibility_program) { + case CP_FTREE: compatibility = C_FTREE; - } - else if (! strncmp(program, "LIFELINES", 9)) { - /* Matches "LIFELINES 3.0.2" */ - enable_compat_msg("Lifelines"); + break; + case CP_LIFELINES: compatibility = C_LIFELINES; default_charset = "ANSI"; - } - else if (! strncmp(program, "PAF", 4)) { - enable_compat_msg("Personal Ancestral File"); - compatibility = C_PAF; + break; + case CP_PAF: + if (compatibility_version >= 20000 && compatibility_version < 30000) { + compatibility = C_PAF2; + version = 2; + } + else if (compatibility_version >= 50000) { + compatibility = C_PAF5; + version = 5; + } + break; + case CP_FAMORIG: + compatibility = C_FAMORIG; + break; + default: + break; + } + if (compatibility) + enable_compat_msg(program_name[compatibility_program], version); +} + +void set_compatibility_version(const char* version) +{ + if (compat_enabled) { + unsigned int major=0, minor=0, patch=0; + int result; + + result = sscanf(version, " %u.%u.%u", &major, &minor, &patch); + if (result > 0) { + gedcom_debug_print("Setting compat version to %u.%u.%u", + major, minor, patch); + compatibility_version = major * 10000 + minor * 100 + patch; } } } @@ -126,6 +221,10 @@ int compat_mode(Compat_rule rule) return (compat_matrix[rule] & compatibility); } +/********************************************************************/ +/* C_NO_SUBMITTER */ +/********************************************************************/ + void compat_generate_submitter_link(Gedcom_ctxt parent) { struct xref_value *xr = gedcom_parse_xref(SUBMITTER_LINK, XREF_USED, @@ -173,6 +272,10 @@ void compat_generate_submitter() } } +/********************************************************************/ +/* C_NO_GEDC */ +/********************************************************************/ + void compat_generate_gedcom(Gedcom_ctxt parent) { struct tag_struct ts; @@ -208,6 +311,10 @@ void compat_generate_gedcom(Gedcom_ctxt parent) end_element(ELT_HEAD_GEDC, parent, self1, NULL); } +/********************************************************************/ +/* C_NO_CHAR */ +/********************************************************************/ + int compat_generate_char(Gedcom_ctxt parent) { struct tag_struct ts; @@ -236,6 +343,10 @@ int compat_generate_char(Gedcom_ctxt parent) return 0; } +/********************************************************************/ +/* C_INDI_ADDR */ +/********************************************************************/ + Gedcom_ctxt compat_generate_resi_start(Gedcom_ctxt parent) { Gedcom_ctxt self; @@ -253,6 +364,10 @@ void compat_generate_resi_end(Gedcom_ctxt parent, Gedcom_ctxt self) end_element(ELT_SUB_INDIV_RESI, parent, self, NULL); } +/********************************************************************/ +/* C_551_TAGS */ +/********************************************************************/ + int is_551_tag(const char* tag) { if (strncmp(tag, "EMAIL", 6)) @@ -279,6 +394,10 @@ int compat_check_551_tag(const char* tag, struct safe_buffer* b) return 0; } +/********************************************************************/ +/* C_NO_SLGC_FAMC */ +/********************************************************************/ + void compat_generate_slgc_famc_link(Gedcom_ctxt parent) { struct xref_value *xr = gedcom_parse_xref(SLGC_FAMC_LINK, XREF_USED, @@ -316,3 +435,60 @@ void compat_generate_slgc_famc_fam() end_record(REC_FAM, self, NULL); } } + +/********************************************************************/ +/* C_SUBM_COMM */ +/********************************************************************/ + +int compat_check_subm_comm(const char* tag, const char* parent_tag, + struct safe_buffer* b) +{ + if (!strcmp(tag, "COMM") && !strcmp(parent_tag, "SUBM")) { + reset_buffer(b); + SAFE_BUF_ADDCHAR(b, '_'); + safe_buf_append(b, tag); + gedcom_warning(_("Converting non-standard tag '%s' to user tag '%s'"), + tag, get_buf_string(b)); + compat_state[C_SUBM_COMM] = 1; + return 1; + } + else + return 0; +} + +void compat_close_subm_comm() +{ + compat_state[C_SUBM_COMM] = 0; +} + +int compat_check_subm_comm_cont(const char* tag) +{ + if (compat_state[C_SUBM_COMM] && !strcmp(tag, "CONT")) { + compat_state[C_SUBM_COMM] = 2; + return 1; + } + else + return 0; +} + +Gedcom_ctxt compat_subm_comm_cont_start(Gedcom_ctxt parent, char* str) +{ + Gedcom_ctxt self = NULL; + struct tag_struct ts; + + if (compat_state[C_SUBM_COMM] == 2) { + ts.string = "_CONT"; + ts.value = USERTAG; + self = start_element(ELT_USER, parent, 2, ts, str, &val2); + } + + return self; +} + +void compat_subm_comm_cont_end(Gedcom_ctxt parent, Gedcom_ctxt self) +{ + if (compat_state[C_SUBM_COMM] == 2) { + end_element(ELT_USER, parent, self, NULL); + compat_state[C_SUBM_COMM] = 1; + } +}