1 /* Compatibility handling for the GEDCOM parser.
2 Copyright (C) 2001, 2002 The Genes Development Team
3 This file is part of the Gedcom parser library.
4 Contributed by Peter Verthez <Peter.Verthez@advalvas.be>, 2001.
6 The Gedcom parser library is free software; you can redistribute it
7 and/or modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 The Gedcom parser library is distributed in the hope that it will be
12 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the Gedcom parser library; if not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
25 #include "interface.h"
29 #include "gedcom_internal.h"
32 int compat_enabled = 1;
33 int compatibility = 0;
34 const char* default_charset = "";
36 #define SUBMITTER_LINK "@__COMPAT__SUBM__@"
37 #define SLGC_FAMC_LINK "@__COMPAT__FAM_SLGC__@"
38 #define DEFAULT_SUBMITTER_NAME "Submitter"
39 #define DEFAULT_GEDCOM_VERS "5.5"
40 #define DEFAULT_GEDCOM_FORM "LINEAGE-LINKED"
48 /* Incompatibility list (with GEDCOM 5.5):
51 - no submitter record, no submitter link in the header
52 - INDI.ADDR instead of INDI.RESI.ADDR
53 - NOTE doesn't have a value
56 - no submitter record, no submitter link in the header
57 - no GEDC field in the header
58 - no CHAR field in the header
59 - HEAD.TIME instead of HEAD.DATE.TIME (will be ignored here)
60 - '@' not written as '@@' in values
61 - lots of missing required values
63 - Personal Ancestral File:
64 - '@' not written as '@@' in values
65 - some 5.5.1 (draft) tags are used: EMAIL, FONE, ROMN
66 - no FAMC field in SLGC
71 /* C_NO_SUBMITTER */ C_FTREE | C_LIFELINES,
72 /* C_INDI_ADDR */ C_FTREE,
73 /* C_NOTE_NO_VALUE */ C_FTREE,
74 /* C_NO_GEDC */ C_LIFELINES,
75 /* C_NO_CHAR */ C_LIFELINES,
76 /* C_HEAD_TIME */ C_LIFELINES,
77 /* C_NO_DOUBLE_AT */ C_LIFELINES | C_PAF,
78 /* C_NO_REQUIRED_VALUES */ C_LIFELINES,
79 /* C_551_TAGS */ C_PAF,
80 /* C_NO_SLGC_FAMC */ C_PAF,
86 /* C_NO_SUBMITTER */ 0,
88 /* C_NOTE_NO_VALUE */ 0,
92 /* C_NO_DOUBLE_AT */ 0,
93 /* C_NO_REQUIRED_VALUES */ 0,
95 /* C_NO_SLGC_FAMC */ 0,
99 /* Compatibility handling */
101 void gedcom_set_compat_handling(int enable_compat)
103 compat_enabled = enable_compat;
106 void enable_compat_msg(const char* program_name)
108 gedcom_warning(_("Enabling compatibility with '%s'"), program_name);
111 void set_compatibility(const char* program)
113 /* Reinitialize compatibility */
115 default_charset = "";
117 for (i = 0; i < C_NR_OF_RULES; i++)
120 if (compat_enabled) {
121 if (! strncmp(program, "ftree", 6)) {
122 enable_compat_msg("ftree");
123 compatibility = C_FTREE;
125 else if (! strncmp(program, "LIFELINES", 9)) {
126 /* Matches "LIFELINES 3.0.2" */
127 enable_compat_msg("Lifelines");
128 compatibility = C_LIFELINES;
129 default_charset = "ANSI";
131 else if (! strncmp(program, "PAF", 4)) {
132 enable_compat_msg("Personal Ancestral File");
133 compatibility = C_PAF;
138 int compat_mode(Compat_rule rule)
140 return (compat_matrix[rule] & compatibility);
143 void compat_generate_submitter_link(Gedcom_ctxt parent)
145 struct xref_value *xr = gedcom_parse_xref(SUBMITTER_LINK, XREF_USED,
147 struct tag_struct ts;
152 gedcom_warning(_("Adding link to submitter record with xref '%s'"),
154 self = start_element(ELT_HEAD_SUBM,
155 parent, 1, ts, SUBMITTER_LINK,
156 GEDCOM_MAKE_XREF_PTR(val1, xr));
157 end_element(ELT_HEAD_SUBM, parent, self, NULL);
158 compat_state[C_NO_SUBMITTER] = 1;
161 void compat_generate_submitter()
163 if (compat_state[C_NO_SUBMITTER]) {
164 struct xref_value *xr = gedcom_parse_xref(SUBMITTER_LINK, XREF_DEFINED,
166 struct tag_struct ts;
167 Gedcom_ctxt self1, self2;
169 /* first generate "0 SUBM" */
172 self1 = start_record(REC_SUBM, 0, GEDCOM_MAKE_XREF_PTR(val1, xr), ts,
173 NULL, GEDCOM_MAKE_NULL(val2));
175 /* then generate "1 NAME ..." */
178 self2 = start_element(ELT_SUBM_NAME, self1, 1, ts, DEFAULT_SUBMITTER_NAME,
179 GEDCOM_MAKE_STRING(val1, DEFAULT_SUBMITTER_NAME));
181 /* close "1 NAME ..." */
182 end_element(ELT_SUBM_NAME, self1, self2, NULL);
185 end_record(REC_SUBM, self1, NULL);
186 compat_state[C_NO_SUBMITTER] = 0;
190 void compat_generate_gedcom(Gedcom_ctxt parent)
192 struct tag_struct ts;
193 Gedcom_ctxt self1, self2;
195 /* first generate "1 GEDC" */
198 self1 = start_element(ELT_HEAD_GEDC, parent, 1, ts, NULL,
199 GEDCOM_MAKE_NULL(val1));
201 /* then generate "2 VERS <DEFAULT_GEDC_VERS>" */
204 self2 = start_element(ELT_HEAD_GEDC_VERS, self1, 2, ts,
206 GEDCOM_MAKE_STRING(val1, DEFAULT_GEDCOM_VERS));
209 end_element(ELT_HEAD_GEDC_VERS, self1, self2, NULL);
211 /* then generate "2 FORM <DEFAULT_GEDCOM_FORM> */
214 self2 = start_element(ELT_HEAD_GEDC_FORM, self1, 2, ts,
216 GEDCOM_MAKE_STRING(val1, DEFAULT_GEDCOM_FORM));
219 end_element(ELT_HEAD_GEDC_FORM, self1, self2, NULL);
222 end_element(ELT_HEAD_GEDC, parent, self1, NULL);
225 int compat_generate_char(Gedcom_ctxt parent)
227 struct tag_struct ts;
231 /* first generate "1 CHAR <DEFAULT_CHAR>" */
235 /* Must strdup, because default_charset is const char */
236 charset = strdup(default_charset);
240 self1 = start_element(ELT_HEAD_CHAR, parent, 1, ts, charset,
241 GEDCOM_MAKE_STRING(val1, charset));
245 end_element(ELT_HEAD_CHAR, parent, self1, NULL);
247 if (open_conv_to_internal(default_charset) == 0)
253 Gedcom_ctxt compat_generate_resi_start(Gedcom_ctxt parent)
256 struct tag_struct ts;
260 self = start_element(ELT_SUB_INDIV_RESI, parent, 1, ts, NULL,
261 GEDCOM_MAKE_NULL(val1));
265 void compat_generate_resi_end(Gedcom_ctxt parent, Gedcom_ctxt self)
267 end_element(ELT_SUB_INDIV_RESI, parent, self, NULL);
270 int is_551_tag(const char* tag)
272 if (strncmp(tag, "EMAIL", 6))
274 else if (strncmp(tag, "FONE", 5))
276 else if (strncmp(tag, "ROMN", 5))
282 int compat_check_551_tag(const char* tag, struct safe_buffer* b)
284 if (is_551_tag(tag)) {
286 SAFE_BUF_ADDCHAR(b, '_');
287 safe_buf_append(b, tag);
288 gedcom_warning(_("Converting 5.5.1 tag '%s' to standard 5.5 user tag '%s'"),
289 tag, get_buf_string(b));
296 void compat_generate_slgc_famc_link(Gedcom_ctxt parent)
298 struct xref_value *xr = gedcom_parse_xref(SLGC_FAMC_LINK, XREF_USED,
300 struct tag_struct ts;
305 gedcom_warning(_("Adding link to family record with xref '%s'"),
307 self = start_element(ELT_SUB_LIO_SLGC_FAMC,
308 parent, 2, ts, SLGC_FAMC_LINK,
309 GEDCOM_MAKE_XREF_PTR(val1, xr));
310 end_element(ELT_SUB_LIO_SLGC_FAMC, parent, self, NULL);
311 compat_state[C_NO_SLGC_FAMC]++;
314 void compat_generate_slgc_famc_fam()
316 /* If bigger than 1, then the FAM record has already been generated */
317 if (compat_state[C_NO_SLGC_FAMC] == 1) {
318 struct xref_value *xr = gedcom_parse_xref(SLGC_FAMC_LINK, XREF_DEFINED,
320 struct tag_struct ts;
323 /* generate "0 FAM" */
326 self = start_record(REC_FAM, 0, GEDCOM_MAKE_XREF_PTR(val1, xr), ts,
327 NULL, GEDCOM_MAKE_NULL(val2));
330 end_record(REC_FAM, self, NULL);