+
+/********************************************************************/
+/* C_551_TAGS */
+/********************************************************************/
+
+int is_551_tag(const char* tag)
+{
+ if (strncmp(tag, "EMAIL", 6))
+ return 1;
+ else if (strncmp(tag, "FONE", 5))
+ return 1;
+ else if (strncmp(tag, "ROMN", 5))
+ return 1;
+ else
+ return 0;
+}
+
+int compat_check_551_tag(const char* tag, struct safe_buffer* b)
+{
+ if (is_551_tag(tag)) {
+ reset_buffer(b);
+ SAFE_BUF_ADDCHAR(b, '_');
+ safe_buf_append(b, tag);
+ gedcom_warning(_("Converting 5.5.1 tag '%s' to standard 5.5 user tag '%s'"),
+ tag, get_buf_string(b));
+ return 1;
+ }
+ else
+ 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,
+ XREF_FAM);
+ struct tag_struct ts;
+ Gedcom_ctxt self;
+
+ ts.string = "FAMC";
+ ts.value = TAG_FAMC;
+ gedcom_warning(_("Adding link to family record with xref '%s'"),
+ SLGC_FAMC_LINK);
+ self = start_element(ELT_SUB_LIO_SLGC_FAMC,
+ parent, 2, ts, SLGC_FAMC_LINK,
+ GEDCOM_MAKE_XREF_PTR(val1, xr));
+ end_element(ELT_SUB_LIO_SLGC_FAMC, parent, self, NULL);
+ compat_state[C_NO_SLGC_FAMC].i++;
+}
+
+void compat_generate_slgc_famc_fam()
+{
+ /* If bigger than 1, then the FAM record has already been generated */
+ if (compat_state[C_NO_SLGC_FAMC].i == 1) {
+ struct xref_value *xr = gedcom_parse_xref(SLGC_FAMC_LINK, XREF_DEFINED,
+ XREF_FAM);
+ struct tag_struct ts;
+ Gedcom_ctxt self;
+
+ /* generate "0 FAM" */
+ ts.string = "FAM";
+ ts.value = TAG_FAM;
+ self = start_record(REC_FAM, 0, GEDCOM_MAKE_XREF_PTR(val1, xr), ts,
+ NULL, GEDCOM_MAKE_NULL(val2));
+
+ /* close "0 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].i = 1;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+void compat_close_subm_comm()
+{
+ compat_state[C_SUBM_COMM].i = 0;
+}
+
+int compat_check_subm_comm_cont(const char* tag)
+{
+ if (compat_state[C_SUBM_COMM].i && !strcmp(tag, "CONT")) {
+ compat_state[C_SUBM_COMM].i = 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].i == 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].i == 2) {
+ end_element(ELT_USER, parent, self, NULL);
+ compat_state[C_SUBM_COMM].i = 1;
+ }
+}
+
+/********************************************************************/
+/* C_DOUBLE_DATES_4 */
+/********************************************************************/
+
+void compat_date_start()
+{
+ if (compat_mode(C_DOUBLE_DATES_4)) {
+ reset_buffer(&compat_buffer);
+ compat_state[C_DOUBLE_DATES_4].i = 0;
+ }
+}
+
+int compat_double_date_check(char* year2)
+{
+ return (compat_mode(C_DOUBLE_DATES_4)
+ && !compat_state[C_DOUBLE_DATES_4].i
+ && strlen(year2) == 4);
+}
+
+int compat_double_date_final(struct date_value* dv, const char** curr_line)
+{
+ char* compat_line_value = get_buf_string(&compat_buffer);
+ compat_state[C_DOUBLE_DATES_4].i = 1;
+ if (compat_line_value && compat_line_value[0]
+ && (dv->type == DV_NO_MODIFIER || dv->type == DV_ABOUT)
+ && dv->date1.day == -1
+ && dv->date1.month == -1) {
+ gedcom_warning(_("Converting '%s' to standard '%s'"),
+ *curr_line, compat_line_value);
+ *curr_line = compat_line_value;
+ }
+ return 1;
+}
+
+int compat_date_check(struct date_value* dv, const char** curr_line)
+{
+ if (compat_mode(C_DOUBLE_DATES_4)
+ && compat_double_date_final(dv, curr_line)) {
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+
+/********************************************************************/
+/* C_NOTE_TOO_LONG */
+/********************************************************************/
+
+char compat_prefix[MAXGEDCLINELEN];
+
+int compat_long_line(int level, int tag)
+{
+ return compat_mode(C_NOTE_TOO_LONG) && (level > 0) && (tag == TAG_NOTE);
+}
+
+char* compat_long_line_get_prefix(char* str)
+{
+ if (str && utf8_strlen(str) > MAXGEDCLINELEN - 7) {
+ int len = MAXGEDCLINELEN - 7;
+ char* ch = nth_utf8_char(str, len - 1);
+ char* nextch = next_utf8_char(ch);
+ memset(compat_prefix, 0, MAXGEDCLINELEN);
+ while (len > 1 && (*ch == ' ' || *nextch == ' ')) {
+ len--;
+ nextch = ch;
+ ch = nth_utf8_char(str, len - 1);
+ }
+ len = nextch - str;
+ strncpy(compat_prefix, str, len);
+ compat_state[C_NOTE_TOO_LONG].vp = (void*)nextch;
+ return compat_prefix;
+ }
+ else {
+ compat_state[C_NOTE_TOO_LONG].vp = NULL;
+ return str;
+ }
+}
+
+void compat_long_line_finish(Gedcom_ctxt parent, int level)
+{
+ struct tag_struct ts;
+ ts.string = "CONC";
+ ts.value = TAG_CONC;
+
+ while (compat_state[C_NOTE_TOO_LONG].vp) {
+ Gedcom_ctxt ctxt;
+ char* input = (char*)compat_state[C_NOTE_TOO_LONG].vp;
+ char* output = compat_long_line_get_prefix(input);
+
+ ctxt = start_element(ELT_SUB_CONC, parent, level + 1, ts, output,
+ GEDCOM_MAKE_STRING(val1, output));
+ end_element(ELT_SUB_CONC, parent, ctxt, GEDCOM_MAKE_NULL(val1));
+ }
+}
+
+/********************************************************************/
+/* C_NOTE_CONC_SOUR */
+/********************************************************************/
+
+Gedcom_ctxt compat_generate_note_sour_start(Gedcom_ctxt parent,
+ int level, struct tag_struct ts,
+ char* pointer)
+{
+ Gedcom_ctxt self;
+ struct xref_value *xr = gedcom_parse_xref(pointer, XREF_USED, XREF_SOUR);
+ if (xr == NULL) {
+ self = (void*)-1;
+ }
+ else {
+ self = start_element(ELT_SUB_SOUR, parent, level-1, ts, pointer,
+ GEDCOM_MAKE_XREF_PTR(val1, xr));
+ }
+ compat_state[C_NOTE_CONC_SOUR].vp = parent;
+ return self;
+}
+
+void compat_generate_note_sour_end(Gedcom_ctxt self)
+{
+ if (self != (void*) -1) {
+ end_element(ELT_SUB_SOUR, compat_state[C_NOTE_CONC_SOUR].vp,
+ self, GEDCOM_MAKE_NULL(val1));
+ }
+}
+
+/********************************************************************/
+/* C_NONSTD_SOUR_TAGS */
+/********************************************************************/
+
+int is_nonstd_sour_tag(const char* tag)
+{
+ if (strncmp(tag, "FILN", 5))
+ return 1;
+ else if (strncmp(tag, "URL", 4))
+ return 1;
+ else if (strncmp(tag, "LOCA", 5))
+ return 1;
+ else if (strncmp(tag, "REGI", 5))
+ return 1;
+ else if (strncmp(tag, "VOL", 4))
+ return 1;
+ else
+ return 0;
+}
+
+int compat_check_sour_tag(const char* tag, struct safe_buffer* b)
+{
+ if (is_nonstd_sour_tag(tag)) {
+ reset_buffer(b);
+ SAFE_BUF_ADDCHAR(b, '_');
+ safe_buf_append(b, tag);
+ gedcom_warning(_("Converting undefined tag '%s' to user tag '%s'"),
+ tag, get_buf_string(b));
+ return 1;
+ }
+ else
+ return 0;
+}
+
+Gedcom_ctxt compat_generate_nonstd_sour_start(Gedcom_ctxt parent, int level,
+ struct tag_struct ts,
+ char* value,
+ struct safe_buffer* b)
+{
+ Gedcom_ctxt self = NULL;
+ reset_buffer(b);
+ SAFE_BUF_ADDCHAR(b, '_');
+ safe_buf_append(b, ts.string);
+ gedcom_warning(_("Converting invalidly used tag '%s' to user tag '%s'"),
+ ts.string, get_buf_string(b));
+ ts.string = get_buf_string(b);
+
+ self = start_element(ELT_USER, parent, level, ts, value,
+ GEDCOM_MAKE_NULL_OR_STRING(val1, value));
+ compat_state[C_NONSTD_SOUR_TAGS].i = 1;
+ return self;
+}
+
+void compat_generate_nonstd_sour_end(Gedcom_ctxt parent, Gedcom_ctxt self)
+{
+ end_element(ELT_USER, parent, self, NULL);
+ compat_state[C_NONSTD_SOUR_TAGS].i = 0;
+}
+
+int compat_generate_nonstd_sour_state()
+{
+ return compat_state[C_NONSTD_SOUR_TAGS].i;
+}