Allow elements out of context in GOM.
[gedcom-parse.git] / gom / event.c
1 /* Event sub-structure in the gedcom object model.
2    Copyright (C) 2002 The Genes Development Team
3    This file is part of the Gedcom parser library.
4    Contributed by Peter Verthez <Peter.Verthez@advalvas.be>, 2002.
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 <stdlib.h>
25 #include <string.h>
26 #include "family.h"
27 #include "individual.h"
28 #include "event.h"
29 #include "place.h"
30 #include "address.h"
31 #include "source_citation.h"
32 #include "multimedia_link.h"
33 #include "note_sub.h"
34 #include "user_rec.h"
35 #include "gom.h"
36 #include "gedcom.h"
37 #include "gom_internal.h"
38
39 Gedcom_ctxt sub_evt_start(_ELT_PARAMS_)
40 {
41   Gom_ctxt ctxt = (Gom_ctxt)parent;
42   Gom_ctxt result = NULL;
43
44   if (! ctxt)
45     NO_CONTEXT;
46   else {
47     struct event *evt = SUB_MAKEFUNC(event)();
48     if (evt) {
49       evt->event = parsed_tag;
50       evt->event_name = strdup(tag);
51       if (! evt->event_name) {
52         MEMORY_ERROR;
53         free(evt);
54       }
55       else {
56         int err = 0;
57         if (GEDCOM_IS_STRING(parsed_value)) {
58           evt->val = strdup(GEDCOM_STRING(parsed_value));
59           if (! evt->val) {
60             MEMORY_ERROR;
61             free(evt->event_name);
62             free(evt);
63             err = 1;
64           }
65         }
66
67         if (! err) {
68           int type = ctxt_type(ctxt);
69           switch (type) {
70             case REC_FAM:
71               ADDFUNC2(family,event)(ctxt, evt); break;
72             case REC_INDI:
73               ADDFUNC2(individual,event)(ctxt, evt); break;
74             default:
75               UNEXPECTED_CONTEXT(type);
76           }
77           result = MAKE_GOM_CTXT(elt, event, evt);
78         }
79       }
80     }
81   }
82
83   return (Gedcom_ctxt)result;
84 }
85
86 Gedcom_ctxt sub_attr_start(_ELT_PARAMS_)
87 {
88   Gom_ctxt ctxt = (Gom_ctxt)parent;
89   Gom_ctxt result = NULL;
90
91   if (! ctxt)
92     NO_CONTEXT;
93   else {
94     struct event *evt = SUB_MAKEFUNC(event)();
95     if (evt) {
96       evt->event = parsed_tag;
97       evt->event_name = strdup(tag);
98       if (! evt->event_name) {
99         MEMORY_ERROR;
100         free(evt);
101       }
102       else {
103         int err = 0;
104         if (GEDCOM_IS_STRING(parsed_value)) {
105           evt->val = strdup(GEDCOM_STRING(parsed_value));
106           if (! evt->val) {
107             MEMORY_ERROR;
108             free(evt->event_name);
109             free(evt);
110             err = 1;
111           }
112         }
113
114         if (! err) {
115           int type = ctxt_type(ctxt);
116           switch (type) {
117             case REC_INDI:
118               ADDFUNC2_TOVAR(individual,event,attribute)(ctxt, evt); break;
119             default:
120               UNEXPECTED_CONTEXT(type);
121           }
122           result = MAKE_GOM_CTXT(elt, event, evt);
123         }
124       }
125     }
126   }
127   return (Gedcom_ctxt)result;
128 }
129
130 DEFINE_SUB_MAKEFUNC(event)
131 DEFINE_SUB_ADDFUNC(event)
132 DEFINE_SUB_FINDFUNC(event)
133 DEFINE_SUB_REMOVEFUNC(event)
134 DEFINE_SUB_MOVEFUNC(event)
135      
136 DEFINE_STRING_CB(event, sub_evt_type_start, type)
137 DEFINE_DATE_CB(event, sub_evt_date_start, date)
138 DEFINE_AGE_CB(event, sub_evt_age_start, age)
139 DEFINE_STRING_CB(event, sub_evt_agnc_start, agency)
140 DEFINE_STRING_CB(event, sub_evt_caus_start, cause)
141 DEFINE_NULL_CB(event, sub_fam_evt_husb_wife_start)
142 DEFINE_XREF_CB(event, sub_evt_famc_start, family, family)
143 DEFINE_STRING_CB(event, sub_evt_famc_adop_start, adoption_parent)
144      
145 DEFINE_ADDFUNC2(event, source_citation, citation)
146 DEFINE_ADDFUNC2(event, multimedia_link, mm_link)
147 DEFINE_ADDFUNC2(event, note_sub, note)
148 DEFINE_ADDFUNC2(event, user_data, extra)
149 DEFINE_ADDFUNC2_NOLIST(event, place, place)
150 DEFINE_ADDFUNC2_NOLIST(event, address, address)
151 DEFINE_ADDFUNC2_STRN(event, phone, 3)
152
153 Gedcom_ctxt sub_fam_evt_age_start(_ELT_PARAMS_)
154 {
155   Gom_ctxt ctxt = (Gom_ctxt)parent;
156   Gom_ctxt result = NULL;
157   
158   if (! ctxt)
159     NO_CONTEXT;
160   else {
161     struct event *evt = SAFE_CTXT_CAST(event, ctxt);
162     if (evt) {
163       int err = 0;
164       struct age_value age = GEDCOM_AGE(parsed_value);
165       int type = ctxt_type(ctxt);
166       switch (type) {
167         case ELT_SUB_FAM_EVT_HUSB:
168           evt->husband_age = gedcom_new_age_value(&age);
169           if (! evt->husband_age) {
170             MEMORY_ERROR;
171             err = 1;
172           }
173           break;
174         case ELT_SUB_FAM_EVT_WIFE:
175           evt->wife_age = gedcom_new_age_value(&age);
176           if (! evt->wife_age) {
177             MEMORY_ERROR;
178             err = 1;
179           }
180           break;
181         default:
182           UNEXPECTED_CONTEXT(type);
183       }
184       if (! err)
185         result = MAKE_GOM_CTXT(elt, event, evt);
186     }
187   }
188   return (Gedcom_ctxt)result;
189 }
190
191 void event_subscribe()
192 {
193   gedcom_subscribe_to_element(ELT_SUB_FAM_EVT, sub_evt_start, def_elt_end);
194   gedcom_subscribe_to_element(ELT_SUB_FAM_EVT_EVEN,
195                               sub_evt_start, def_elt_end);
196   gedcom_subscribe_to_element(ELT_SUB_INDIV_ATTR,
197                               sub_attr_start, def_elt_end);  
198   gedcom_subscribe_to_element(ELT_SUB_INDIV_RESI,
199                               sub_attr_start, def_elt_end);
200   gedcom_subscribe_to_element(ELT_SUB_INDIV_BIRT,
201                               sub_evt_start, def_elt_end);
202   gedcom_subscribe_to_element(ELT_SUB_INDIV_BIRT_FAMC,
203                               sub_evt_famc_start, def_elt_end);
204   gedcom_subscribe_to_element(ELT_SUB_INDIV_GEN,
205                               sub_evt_start, def_elt_end);
206   gedcom_subscribe_to_element(ELT_SUB_INDIV_ADOP,
207                               sub_evt_start, def_elt_end);
208   gedcom_subscribe_to_element(ELT_SUB_INDIV_ADOP_FAMC,
209                               sub_evt_famc_start, def_elt_end);
210   gedcom_subscribe_to_element(ELT_SUB_INDIV_ADOP_FAMC_ADOP,
211                               sub_evt_famc_adop_start, def_elt_end);
212   gedcom_subscribe_to_element(ELT_SUB_INDIV_EVEN,
213                               sub_evt_start, def_elt_end);
214   gedcom_subscribe_to_element(ELT_SUB_FAM_EVT_HUSB,
215                               sub_fam_evt_husb_wife_start, def_elt_end);
216   gedcom_subscribe_to_element(ELT_SUB_FAM_EVT_WIFE,
217                               sub_fam_evt_husb_wife_start, def_elt_end);
218   gedcom_subscribe_to_element(ELT_SUB_FAM_EVT_AGE,
219                               sub_fam_evt_age_start, def_elt_end);
220   gedcom_subscribe_to_element(ELT_SUB_EVT_TYPE,
221                               sub_evt_type_start, def_elt_end);
222   gedcom_subscribe_to_element(ELT_SUB_EVT_DATE,
223                               sub_evt_date_start, def_elt_end);
224   gedcom_subscribe_to_element(ELT_SUB_EVT_AGE,
225                               sub_evt_age_start, def_elt_end);
226   gedcom_subscribe_to_element(ELT_SUB_EVT_AGNC,
227                               sub_evt_agnc_start, def_elt_end);
228   gedcom_subscribe_to_element(ELT_SUB_EVT_CAUS,
229                               sub_evt_caus_start, def_elt_end);
230 }
231
232 void UNREFALLFUNC(event)(struct event* obj)
233 {
234   if (obj) {
235     struct event* runner;
236     for (runner = obj; runner; runner = runner->next) {
237       UNREFALLFUNC(place)(runner->place);
238       UNREFALLFUNC(address)(runner->address);
239       UNREFALLFUNC(source_citation)(runner->citation);
240       UNREFALLFUNC(multimedia_link)(runner->mm_link);
241       UNREFALLFUNC(note_sub)(runner->note);
242       unref_xref_value(runner->family);
243       UNREFALLFUNC(user_data)(runner->extra);
244     }
245   }
246 }
247
248 void CLEANFUNC(event)(struct event* evt)
249 {
250   if (evt) {
251     SAFE_FREE(evt->event_name);
252     SAFE_FREE(evt->val);
253     SAFE_FREE(evt->type);
254     SAFE_FREE(evt->date);
255     CLEANFUNC(place)(evt->place);
256     CLEANFUNC(address)(evt->address);
257     SAFE_FREE(evt->phone[0]);
258     SAFE_FREE(evt->phone[1]);
259     SAFE_FREE(evt->phone[2]);
260     SAFE_FREE(evt->age);
261     SAFE_FREE(evt->agency);
262     SAFE_FREE(evt->cause);
263     DESTROY_CHAIN_ELTS(source_citation, evt->citation);
264     DESTROY_CHAIN_ELTS(multimedia_link, evt->mm_link);
265     DESTROY_CHAIN_ELTS(note_sub, evt->note);
266     SAFE_FREE(evt->husband_age);
267     SAFE_FREE(evt->wife_age);
268     SAFE_FREE(evt->adoption_parent);
269     DESTROY_CHAIN_ELTS(user_data, evt->extra);
270   }
271 }
272
273 static int get_gedcom_elt(EventType evt_type, int parsed_tag)
274 {
275   int obj_elt = 0;
276   switch (evt_type) {
277     case EVT_TYPE_FAMILY:
278       obj_elt = (parsed_tag == TAG_EVEN ? ELT_SUB_FAM_EVT_EVEN :
279                  ELT_SUB_FAM_EVT);
280       break;
281     case EVT_TYPE_INDIV_ATTR:
282       obj_elt = (parsed_tag == TAG_RESI ? ELT_SUB_INDIV_RESI :
283                  ELT_SUB_INDIV_ATTR);
284       break;
285     case EVT_TYPE_INDIV_EVT:
286       switch (parsed_tag) {
287         case TAG_BIRT: case TAG_CHR:
288           obj_elt = ELT_SUB_INDIV_BIRT; break;
289         case TAG_DEAT: case TAG_BURI: case TAG_CREM: case TAG_BAPM:
290         case TAG_BARM: case TAG_BASM: case TAG_BLES: case TAG_CHRA:
291         case TAG_CONF: case TAG_FCOM: case TAG_ORDN: case TAG_NATU:
292         case TAG_EMIG: case TAG_IMMI: case TAG_CENS: case TAG_PROB:
293         case TAG_WILL: case TAG_GRAD: case TAG_RETI:
294           obj_elt = ELT_SUB_INDIV_GEN; break;
295         case TAG_ADOP:
296           obj_elt = ELT_SUB_INDIV_ADOP; break;
297         case TAG_EVEN:
298           obj_elt = ELT_SUB_INDIV_EVEN; break;
299         default:
300           gedcom_warning(_("Internal error: unknown evt tag %d"), parsed_tag);
301       }
302       break;
303     default:
304       gedcom_warning(_("Internal error: unknown evt type %d"), evt_type);
305   }
306   return obj_elt;
307 }
308
309 int get_gedcom_fam_elt(int elt)
310 {
311   int fam_obj_elt = 0;
312   switch (elt) {
313     case ELT_SUB_INDIV_BIRT:
314       fam_obj_elt = ELT_SUB_INDIV_BIRT_FAMC;
315       break;
316     case ELT_SUB_INDIV_ADOP:
317       fam_obj_elt = ELT_SUB_INDIV_ADOP_FAMC;
318       break;
319     default:
320       gedcom_warning(_("Internal error: wrong parent for evt->family"));
321   }
322   return fam_obj_elt;
323 }
324
325 int write_events(Gedcom_write_hndl hndl, int parent, EventType evt_type,
326                  struct event* evt)
327 {
328   int result = 0;
329   int i;
330   struct event* obj;
331
332   if (!evt) return 1;
333
334   for (obj = evt; obj; obj = obj->next) {
335     int obj_elt = get_gedcom_elt(evt_type, obj->event);
336     result |= gedcom_write_element_str(hndl, obj_elt, obj->event,
337                                        parent, obj->val);
338     if (obj->type)
339       result |= gedcom_write_element_str(hndl, ELT_SUB_EVT_TYPE, 0,
340                                          obj_elt, obj->type);
341     if (obj->date)
342       result |= gedcom_write_element_date(hndl, ELT_SUB_EVT_DATE, 0,
343                                           obj_elt, obj->date);
344     if (obj->place)
345       result |= write_place(hndl, obj_elt, obj->place);
346     if (obj->address)
347       result |= write_address(hndl, obj_elt, obj->address);
348     for (i = 0; i < 3 && obj->phone[i]; i++)
349       result |= gedcom_write_element_str(hndl, ELT_SUB_PHON, 0, obj_elt,
350                                          obj->phone[i]);
351     if (obj->age)
352       result |= gedcom_write_element_age(hndl, ELT_SUB_EVT_AGE, 0,
353                                          obj_elt, obj->age);
354     if (obj->agency)
355       result |= gedcom_write_element_str(hndl, ELT_SUB_EVT_AGNC, 0,
356                                          obj_elt, obj->agency);
357     if (obj->cause)
358       result |= gedcom_write_element_str(hndl, ELT_SUB_EVT_CAUS, 0,
359                                          obj_elt, obj->cause);
360     if (obj->citation)
361       result |= write_citations(hndl, obj_elt, obj->citation);
362     if (obj->mm_link)
363       result |= write_multimedia_links(hndl, obj_elt, obj->mm_link);
364     if (obj->note)
365       result |= write_note_subs(hndl, obj_elt, obj->note);
366     if (obj->husband_age) {
367       result |= gedcom_write_element_str(hndl, ELT_SUB_FAM_EVT_HUSB, 0,
368                                          obj_elt, NULL);
369       result |= gedcom_write_element_age(hndl, ELT_SUB_FAM_EVT_AGE, 0,
370                                          ELT_SUB_FAM_EVT_HUSB,
371                                          obj->husband_age);
372     }
373     if (obj->wife_age) {
374       result |= gedcom_write_element_str(hndl, ELT_SUB_FAM_EVT_WIFE, 0,
375                                          obj_elt, NULL);
376       result |= gedcom_write_element_age(hndl, ELT_SUB_FAM_EVT_AGE, 0,
377                                          ELT_SUB_FAM_EVT_WIFE,
378                                          obj->wife_age);
379     }
380     if (obj->family) {
381       int fam_obj_elt = get_gedcom_fam_elt(obj_elt);
382       result |= gedcom_write_element_xref(hndl, fam_obj_elt, 0,
383                                           obj_elt, obj->family);
384       if (obj->adoption_parent) {
385         result |= gedcom_write_element_str(hndl, ELT_SUB_INDIV_ADOP_FAMC_ADOP,
386                                            0, fam_obj_elt,
387                                            obj->adoption_parent);
388       }
389     }
390     if (obj->extra)
391       result |= write_user_data(hndl, obj->extra);
392   }
393   
394   return result;
395 }
396