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