Added extra argument to callback functions: the record/element identifier.
[gedcom-parse.git] / gedcom / compat.c
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.
5
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.
10
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.
15
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
19    02111-1307 USA.  */
20
21 /* $Id$ */
22 /* $Name$ */
23
24 #include "compat.h"
25 #include "interface.h"
26 #include "encoding.h"
27 #include "xref.h"
28 #include "gedcom_internal.h"
29 #include "gedcom.h"
30
31 int compat_enabled = 1;
32 int compatibility  = 0; 
33 int compat_at = 0;
34 char* default_charset = "";
35
36 #define SUBMITTER_LINK         "@__COMPAT__SUBM__@"
37 #define DEFAULT_SUBMITTER_NAME "Submitter"
38 #define DEFAULT_GEDCOM_VERS    "5.5"
39 #define DEFAULT_GEDCOM_FORM    "LINEAGE-LINKED"
40
41 /* Incompatibility list (with GEDCOM 5.5):
42
43     - ftree:
44         - no submitter record, no submitter link in the header
45         - INDI.ADDR instead of INDI.RESI.ADDR
46         - NOTE doesn't have a value
47
48     - Lifelines (3.0.2):
49         - no submitter record, no submitter link in the header
50         - no GEDC field in the header
51         - no CHAR field in the header
52         - HEAD.TIME instead of HEAD.DATE.TIME (will be ignored here)
53         - '@' not written as '@@' in values
54         - lots of missing required values
55  */
56
57 /* Compatibility handling */
58
59 void gedcom_set_compat_handling(int enable_compat)
60 {
61   compat_enabled = enable_compat;
62 }
63
64 void set_compatibility(char* program)
65 {
66   if (compat_enabled) {
67     if (! strncmp(program, "ftree", 6)) {
68       gedcom_warning(_("Enabling compatibility with 'ftree'"));
69       compatibility = C_FTREE;
70     }
71     else if (! strncmp(program, "LIFELINES", 9)) {
72       /* Matches "LIFELINES 3.0.2" */
73       gedcom_warning(_("Enabling compatibility with 'Lifelines'"));
74       compatibility = C_LIFELINES;
75       default_charset = "ANSI";
76       compat_at = 1;
77     }
78     else {
79       compatibility = 0;
80     }
81   }
82 }
83
84 int compat_mode(int compat_flags)
85 {
86   return (compat_flags & compatibility);
87 }
88
89 void compat_generate_submitter_link(Gedcom_ctxt parent)
90 {
91   struct xref_value *xr = gedcom_parse_xref(SUBMITTER_LINK, XREF_USED,
92                                             XREF_SUBM);
93   struct tag_struct ts;
94   Gedcom_ctxt self;
95   
96   ts.string = "SUBM";
97   ts.value  = TAG_SUBM;
98   self = start_element(ELT_HEAD_SUBM,
99                        parent, 1, ts, SUBMITTER_LINK,
100                        GEDCOM_MAKE_XREF_PTR(val1, xr));
101   end_element(ELT_HEAD_SUBM, parent, self, NULL);
102 }
103
104 void compat_generate_submitter()
105 {
106   struct xref_value *xr = gedcom_parse_xref(SUBMITTER_LINK, XREF_DEFINED,
107                                             XREF_SUBM);
108   struct tag_struct ts;
109   Gedcom_ctxt self1, self2;
110
111   /* first generate "0 SUBM" */
112   ts.string = "SUBM";
113   ts.value  = TAG_SUBM;
114   self1 = start_record(REC_SUBM, 0, GEDCOM_MAKE_XREF_PTR(val1, xr), ts,
115                        NULL, GEDCOM_MAKE_NULL(val2));
116
117   /* then generate "1 NAME ..." */
118   ts.string = "NAME";
119   ts.value  = TAG_NAME;
120   self2 = start_element(ELT_SUBM_NAME, self1, 1, ts, DEFAULT_SUBMITTER_NAME,
121                         GEDCOM_MAKE_STRING(val1, DEFAULT_SUBMITTER_NAME));
122
123   /* close "1 NAME ..." */
124   end_element(ELT_SUBM_NAME, self1, self2, NULL);
125
126   /* close "0 SUBM" */
127   end_record(REC_SUBM, self1);
128 }
129
130 void compat_generate_gedcom(Gedcom_ctxt parent)
131 {
132   struct tag_struct ts;
133   Gedcom_ctxt self1, self2;
134   
135   /* first generate "1 GEDC" */
136   ts.string = "GEDC";
137   ts.value  = TAG_GEDC;
138   self1 = start_element(ELT_HEAD_GEDC, parent, 1, ts, NULL,
139                         GEDCOM_MAKE_NULL(val1));
140   
141   /* then generate "2 VERS <DEFAULT_GEDC_VERS>" */
142   ts.string = "VERS";
143   ts.value  = TAG_VERS;
144   self2 = start_element(ELT_HEAD_GEDC_VERS, self1, 2, ts,
145                         DEFAULT_GEDCOM_VERS,
146                         GEDCOM_MAKE_STRING(val1, DEFAULT_GEDCOM_VERS));
147   
148   /* close "2 VERS" */
149   end_element(ELT_HEAD_GEDC_VERS, self1, self2, NULL);
150   
151   /* then generate "2 FORM <DEFAULT_GEDCOM_FORM> */
152   ts.string = "FORM";
153   ts.value  = TAG_FORM;
154   self2 = start_element(ELT_HEAD_GEDC_FORM, self1, 2, ts,
155                         DEFAULT_GEDCOM_FORM,
156                         GEDCOM_MAKE_STRING(val1, DEFAULT_GEDCOM_FORM));
157   
158   /* close "2 FORM" */
159   end_element(ELT_HEAD_GEDC_FORM, self1, self2, NULL);
160   
161   /* close "1 GEDC" */
162   end_element(ELT_HEAD_GEDC, parent, self1, NULL);
163 }
164
165 int compat_generate_char(Gedcom_ctxt parent)
166 {
167   struct tag_struct ts;
168   Gedcom_ctxt self1;
169   
170   /* first generate "1 CHAR <DEFAULT_CHAR>" */
171   ts.string = "CHAR";
172   ts.value  = TAG_CHAR;
173   self1 = start_element(ELT_HEAD_CHAR, parent, 1, ts, default_charset,
174                         GEDCOM_MAKE_STRING(val1, default_charset));
175   
176   /* close "1 CHAR" */
177   end_element(ELT_HEAD_CHAR, parent, self1, NULL);
178   if (open_conv_to_internal(default_charset) == 0)
179     return 1;
180   else
181     return 0;
182 }
183
184 Gedcom_ctxt compat_generate_resi_start(Gedcom_ctxt parent)
185 {
186   Gedcom_ctxt self;
187   struct tag_struct ts;
188
189   ts.string = "RESI";
190   ts.value  = TAG_RESI;
191   self = start_element(ELT_SUB_INDIV_RESI, parent, 1, ts, NULL,
192                        GEDCOM_MAKE_NULL(val1));
193   return self;
194 }
195
196 void compat_generate_resi_end(Gedcom_ctxt parent, Gedcom_ctxt self)
197 {
198   end_element(ELT_SUB_INDIV_RESI, parent, self, NULL);
199 }