Only try to delete address if present.
[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           switch (ctxt->ctxt_type) {
69             case REC_FAM:
70               ADDFUNC2(family,event)(ctxt, evt); break;
71             case REC_INDI:
72               ADDFUNC2(individual,event)(ctxt, evt); break;
73             default:
74               UNEXPECTED_CONTEXT(ctxt->ctxt_type);
75           }
76           result = MAKE_GOM_CTXT(elt, event, evt);
77         }
78       }
79     }
80   }
81
82   return (Gedcom_ctxt)result;
83 }
84
85 Gedcom_ctxt sub_attr_start(_ELT_PARAMS_)
86 {
87   Gom_ctxt ctxt = (Gom_ctxt)parent;
88   Gom_ctxt result = NULL;
89
90   if (! ctxt)
91     NO_CONTEXT;
92   else {
93     struct event *evt = SUB_MAKEFUNC(event)();
94     if (evt) {
95       evt->event = parsed_tag;
96       evt->event_name = strdup(tag);
97       if (! evt->event_name) {
98         MEMORY_ERROR;
99         free(evt);
100       }
101       else {
102         int err = 0;
103         if (GEDCOM_IS_STRING(parsed_value)) {
104           evt->val = strdup(GEDCOM_STRING(parsed_value));
105           if (! evt->val) {
106             MEMORY_ERROR;
107             free(evt->event_name);
108             free(evt);
109             err = 1;
110           }
111         }
112
113         if (! err) {
114           switch (ctxt->ctxt_type) {
115             case REC_INDI:
116               ADDFUNC2_TOVAR(individual,event,attribute)(ctxt, evt); break;
117             default:
118               UNEXPECTED_CONTEXT(ctxt->ctxt_type);
119           }
120           result = MAKE_GOM_CTXT(elt, event, evt);
121         }
122       }
123     }
124   }
125   return (Gedcom_ctxt)result;
126 }
127
128 DEFINE_SUB_MAKEFUNC(event)
129 DEFINE_SUB_ADDFUNC(event)
130 DEFINE_SUB_FINDFUNC(event)
131 DEFINE_SUB_REMOVEFUNC(event)
132 DEFINE_SUB_MOVEFUNC(event)
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 UNREFALLFUNC(event)(struct event* obj)
230 {
231   if (obj) {
232     struct event* runner;
233     for (runner = obj; runner; runner = runner->next) {
234       UNREFALLFUNC(place)(runner->place);
235       UNREFALLFUNC(address)(runner->address);
236       UNREFALLFUNC(source_citation)(runner->citation);
237       UNREFALLFUNC(multimedia_link)(runner->mm_link);
238       UNREFALLFUNC(note_sub)(runner->note);
239       unref_xref_value(runner->family);
240       UNREFALLFUNC(user_data)(runner->extra);
241     }
242   }
243 }
244
245 void CLEANFUNC(event)(struct event* evt)
246 {
247   if (evt) {
248     SAFE_FREE(evt->event_name);
249     SAFE_FREE(evt->val);
250     SAFE_FREE(evt->type);
251     SAFE_FREE(evt->date);
252     CLEANFUNC(place)(evt->place);
253     CLEANFUNC(address)(evt->address);
254     SAFE_FREE(evt->phone[0]);
255     SAFE_FREE(evt->phone[1]);
256     SAFE_FREE(evt->phone[2]);
257     SAFE_FREE(evt->age);
258     SAFE_FREE(evt->agency);
259     SAFE_FREE(evt->cause);
260     DESTROY_CHAIN_ELTS(source_citation, evt->citation);
261     DESTROY_CHAIN_ELTS(multimedia_link, evt->mm_link);
262     DESTROY_CHAIN_ELTS(note_sub, evt->note);
263     SAFE_FREE(evt->husband_age);
264     SAFE_FREE(evt->wife_age);
265     SAFE_FREE(evt->adoption_parent);
266     DESTROY_CHAIN_ELTS(user_data, evt->extra);
267   }
268 }
269
270 static int get_gedcom_elt(EventType evt_type, int parsed_tag)
271 {
272   int obj_elt = 0;
273   switch (evt_type) {
274     case EVT_TYPE_FAMILY:
275       obj_elt = (parsed_tag == TAG_EVEN ? ELT_SUB_FAM_EVT_EVEN :
276                  ELT_SUB_FAM_EVT);
277       break;
278     case EVT_TYPE_INDIV_ATTR:
279       obj_elt = (parsed_tag == TAG_RESI ? ELT_SUB_INDIV_RESI :
280                  ELT_SUB_INDIV_ATTR);
281       break;
282     case EVT_TYPE_INDIV_EVT:
283       switch (parsed_tag) {
284         case TAG_BIRT: case TAG_CHR:
285           obj_elt = ELT_SUB_INDIV_BIRT; break;
286         case TAG_DEAT: case TAG_BURI: case TAG_CREM: case TAG_BAPM:
287         case TAG_BARM: case TAG_BASM: case TAG_BLES: case TAG_CHRA:
288         case TAG_CONF: case TAG_FCOM: case TAG_ORDN: case TAG_NATU:
289         case TAG_EMIG: case TAG_IMMI: case TAG_CENS: case TAG_PROB:
290         case TAG_WILL: case TAG_GRAD: case TAG_RETI:
291           obj_elt = ELT_SUB_INDIV_GEN; break;
292         case TAG_ADOP:
293           obj_elt = ELT_SUB_INDIV_ADOP; break;
294         case TAG_EVEN:
295           obj_elt = ELT_SUB_INDIV_EVEN; break;
296         default:
297           gedcom_warning(_("Internal error: unknown evt tag %d"), parsed_tag);
298       }
299       break;
300     default:
301       gedcom_warning(_("Internal error: unknown evt type %d"), evt_type);
302   }
303   return obj_elt;
304 }
305
306 int get_gedcom_fam_elt(int elt)
307 {
308   int fam_obj_elt = 0;
309   switch (elt) {
310     case ELT_SUB_INDIV_BIRT:
311       fam_obj_elt = ELT_SUB_INDIV_BIRT_FAMC;
312       break;
313     case ELT_SUB_INDIV_ADOP:
314       fam_obj_elt = ELT_SUB_INDIV_ADOP_FAMC;
315       break;
316     default:
317       gedcom_warning(_("Internal error: wrong parent for evt->family"));
318   }
319   return fam_obj_elt;
320 }
321
322 int write_events(Gedcom_write_hndl hndl, int parent, EventType evt_type,
323                  struct event* evt)
324 {
325   int result = 0;
326   int i;
327   struct event* obj;
328
329   if (!evt) return 1;
330
331   for (obj = evt; obj; obj = obj->next) {
332     int obj_elt = get_gedcom_elt(evt_type, obj->event);
333     result |= gedcom_write_element_str(hndl, obj_elt, obj->event,
334                                        parent, obj->val);
335     if (obj->type)
336       result |= gedcom_write_element_str(hndl, ELT_SUB_EVT_TYPE, 0,
337                                          obj_elt, obj->type);
338     if (obj->date)
339       result |= gedcom_write_element_date(hndl, ELT_SUB_EVT_DATE, 0,
340                                           obj_elt, obj->date);
341     if (obj->place)
342       result |= write_place(hndl, obj_elt, obj->place);
343     if (obj->address)
344       result |= write_address(hndl, obj_elt, obj->address);
345     for (i = 0; i < 3 && obj->phone[i]; i++)
346       result |= gedcom_write_element_str(hndl, ELT_SUB_PHON, 0, obj_elt,
347                                          obj->phone[i]);
348     if (obj->age)
349       result |= gedcom_write_element_age(hndl, ELT_SUB_EVT_AGE, 0,
350                                          obj_elt, obj->age);
351     if (obj->agency)
352       result |= gedcom_write_element_str(hndl, ELT_SUB_EVT_AGNC, 0,
353                                          obj_elt, obj->agency);
354     if (obj->cause)
355       result |= gedcom_write_element_str(hndl, ELT_SUB_EVT_CAUS, 0,
356                                          obj_elt, obj->cause);
357     if (obj->citation)
358       result |= write_citations(hndl, obj_elt, obj->citation);
359     if (obj->mm_link)
360       result |= write_multimedia_links(hndl, obj_elt, obj->mm_link);
361     if (obj->note)
362       result |= write_note_subs(hndl, obj_elt, obj->note);
363     if (obj->husband_age) {
364       result |= gedcom_write_element_str(hndl, ELT_SUB_FAM_EVT_HUSB, 0,
365                                          obj_elt, NULL);
366       result |= gedcom_write_element_age(hndl, ELT_SUB_FAM_EVT_AGE, 0,
367                                          ELT_SUB_FAM_EVT_HUSB,
368                                          obj->husband_age);
369     }
370     if (obj->wife_age) {
371       result |= gedcom_write_element_str(hndl, ELT_SUB_FAM_EVT_WIFE, 0,
372                                          obj_elt, NULL);
373       result |= gedcom_write_element_age(hndl, ELT_SUB_FAM_EVT_AGE, 0,
374                                          ELT_SUB_FAM_EVT_WIFE,
375                                          obj->wife_age);
376     }
377     if (obj->family) {
378       int fam_obj_elt = get_gedcom_fam_elt(obj_elt);
379       result |= gedcom_write_element_xref(hndl, fam_obj_elt, 0,
380                                           obj_elt, obj->family);
381       if (obj->adoption_parent) {
382         result |= gedcom_write_element_str(hndl, ELT_SUB_INDIV_ADOP_FAMC_ADOP,
383                                            0, fam_obj_elt,
384                                            obj->adoption_parent);
385       }
386     }
387     if (obj->extra)
388       result |= write_user_data(hndl, obj->extra);
389   }
390   
391   return result;
392 }
393