Definition of SUB_MAKEFUNC.
[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      
130 DEFINE_STRING_CB(event, sub_evt_type_start, type)
131 DEFINE_DATE_CB(event, sub_evt_date_start, date)
132 DEFINE_AGE_CB(event, sub_evt_age_start, age)
133 DEFINE_STRING_CB(event, sub_evt_agnc_start, agency)
134 DEFINE_STRING_CB(event, sub_evt_caus_start, cause)
135 DEFINE_NULL_CB(event, sub_fam_evt_husb_wife_start)
136 DEFINE_XREF_CB(event, sub_evt_famc_start, family, family)
137 DEFINE_STRING_CB(event, sub_evt_famc_adop_start, adoption_parent)
138      
139 DEFINE_ADDFUNC2(event, source_citation, citation)
140 DEFINE_ADDFUNC2(event, multimedia_link, mm_link)
141 DEFINE_ADDFUNC2(event, note_sub, note)
142 DEFINE_ADDFUNC2(event, user_data, extra)
143 DEFINE_ADDFUNC2_NOLIST(event, place, place)
144 DEFINE_ADDFUNC2_NOLIST(event, address, address)
145 DEFINE_ADDFUNC2_STRN(event, phone, 3)
146
147 Gedcom_ctxt sub_fam_evt_age_start(_ELT_PARAMS_)
148 {
149   Gom_ctxt ctxt = (Gom_ctxt)parent;
150   Gom_ctxt result = NULL;
151   
152   if (! ctxt)
153     NO_CONTEXT;
154   else {
155     struct event *evt = SAFE_CTXT_CAST(event, ctxt);
156     if (evt) {
157       int err = 0;
158       struct age_value age = GEDCOM_AGE(parsed_value);
159       switch (ctxt->ctxt_type) {
160         case ELT_SUB_FAM_EVT_HUSB:
161           evt->husband_age = gedcom_new_age_value(&age);
162           if (! evt->husband_age) {
163             MEMORY_ERROR;
164             err = 1;
165           }
166           break;
167         case ELT_SUB_FAM_EVT_WIFE:
168           evt->wife_age = gedcom_new_age_value(&age);
169           if (! evt->wife_age) {
170             MEMORY_ERROR;
171             err = 1;
172           }
173           break;
174         default:
175           UNEXPECTED_CONTEXT(ctxt->ctxt_type);
176       }
177       if (! err)
178         result = MAKE_GOM_CTXT(elt, event, evt);
179     }
180   }
181   return (Gedcom_ctxt)result;
182 }
183
184 void event_subscribe()
185 {
186   gedcom_subscribe_to_element(ELT_SUB_FAM_EVT, sub_evt_start, def_elt_end);
187   gedcom_subscribe_to_element(ELT_SUB_FAM_EVT_EVEN,
188                               sub_evt_start, def_elt_end);
189   gedcom_subscribe_to_element(ELT_SUB_INDIV_ATTR,
190                               sub_attr_start, def_elt_end);  
191   gedcom_subscribe_to_element(ELT_SUB_INDIV_RESI,
192                               sub_attr_start, def_elt_end);
193   gedcom_subscribe_to_element(ELT_SUB_INDIV_BIRT,
194                               sub_evt_start, def_elt_end);
195   gedcom_subscribe_to_element(ELT_SUB_INDIV_BIRT_FAMC,
196                               sub_evt_famc_start, def_elt_end);
197   gedcom_subscribe_to_element(ELT_SUB_INDIV_GEN,
198                               sub_evt_start, def_elt_end);
199   gedcom_subscribe_to_element(ELT_SUB_INDIV_ADOP,
200                               sub_evt_start, def_elt_end);
201   gedcom_subscribe_to_element(ELT_SUB_INDIV_ADOP_FAMC,
202                               sub_evt_famc_start, def_elt_end);
203   gedcom_subscribe_to_element(ELT_SUB_INDIV_ADOP_FAMC_ADOP,
204                               sub_evt_famc_adop_start, def_elt_end);
205   gedcom_subscribe_to_element(ELT_SUB_INDIV_EVEN,
206                               sub_evt_start, def_elt_end);
207   gedcom_subscribe_to_element(ELT_SUB_FAM_EVT_HUSB,
208                               sub_fam_evt_husb_wife_start, def_elt_end);
209   gedcom_subscribe_to_element(ELT_SUB_FAM_EVT_WIFE,
210                               sub_fam_evt_husb_wife_start, def_elt_end);
211   gedcom_subscribe_to_element(ELT_SUB_FAM_EVT_AGE,
212                               sub_fam_evt_age_start, def_elt_end);
213   gedcom_subscribe_to_element(ELT_SUB_EVT_TYPE,
214                               sub_evt_type_start, def_elt_end);
215   gedcom_subscribe_to_element(ELT_SUB_EVT_DATE,
216                               sub_evt_date_start, def_elt_end);
217   gedcom_subscribe_to_element(ELT_SUB_EVT_AGE,
218                               sub_evt_age_start, def_elt_end);
219   gedcom_subscribe_to_element(ELT_SUB_EVT_AGNC,
220                               sub_evt_agnc_start, def_elt_end);
221   gedcom_subscribe_to_element(ELT_SUB_EVT_CAUS,
222                               sub_evt_caus_start, def_elt_end);
223 }
224
225 void CLEANFUNC(event)(struct event* evt)
226 {
227   if (evt) {
228     SAFE_FREE(evt->event_name);
229     SAFE_FREE(evt->val);
230     SAFE_FREE(evt->type);
231     SAFE_FREE(evt->date);
232     CLEANFUNC(place)(evt->place);
233     CLEANFUNC(address)(evt->address);
234     SAFE_FREE(evt->phone[0]);
235     SAFE_FREE(evt->phone[1]);
236     SAFE_FREE(evt->phone[2]);
237     SAFE_FREE(evt->age);
238     SAFE_FREE(evt->agency);
239     SAFE_FREE(evt->cause);
240     DESTROY_CHAIN_ELTS(source_citation, evt->citation);
241     DESTROY_CHAIN_ELTS(multimedia_link, evt->mm_link);
242     DESTROY_CHAIN_ELTS(note_sub, evt->note);
243     SAFE_FREE(evt->husband_age);
244     SAFE_FREE(evt->wife_age);
245     SAFE_FREE(evt->adoption_parent);
246     DESTROY_CHAIN_ELTS(user_data, evt->extra);
247   }
248 }
249
250 static int get_gedcom_elt(EventType evt_type, int parsed_tag)
251 {
252   int obj_elt = 0;
253   switch (evt_type) {
254     case EVT_TYPE_FAMILY:
255       obj_elt = (parsed_tag == TAG_EVEN ? ELT_SUB_FAM_EVT_EVEN :
256                  ELT_SUB_FAM_EVT);
257       break;
258     case EVT_TYPE_INDIV_ATTR:
259       obj_elt = (parsed_tag == TAG_RESI ? ELT_SUB_INDIV_RESI :
260                  ELT_SUB_INDIV_ATTR);
261       break;
262     case EVT_TYPE_INDIV_EVT:
263       switch (parsed_tag) {
264         case TAG_BIRT: case TAG_CHR:
265           obj_elt = ELT_SUB_INDIV_BIRT; break;
266         case TAG_DEAT: case TAG_BURI: case TAG_CREM: case TAG_BAPM:
267         case TAG_BARM: case TAG_BASM: case TAG_BLES: case TAG_CHRA:
268         case TAG_CONF: case TAG_FCOM: case TAG_ORDN: case TAG_NATU:
269         case TAG_EMIG: case TAG_IMMI: case TAG_CENS: case TAG_PROB:
270         case TAG_WILL: case TAG_GRAD: case TAG_RETI:
271           obj_elt = ELT_SUB_INDIV_GEN; break;
272         case TAG_ADOP:
273           obj_elt = ELT_SUB_INDIV_ADOP; break;
274         case TAG_EVEN:
275           obj_elt = ELT_SUB_INDIV_EVEN; break;
276         default:
277           gedcom_warning(_("Internal error: unknown evt tag %d"), parsed_tag);
278       }
279       break;
280     default:
281       gedcom_warning(_("Internal error: unknown evt type %d"), evt_type);
282   }
283   return obj_elt;
284 }
285
286 int get_gedcom_fam_elt(int elt)
287 {
288   int fam_obj_elt = 0;
289   switch (elt) {
290     case ELT_SUB_INDIV_BIRT:
291       fam_obj_elt = ELT_SUB_INDIV_BIRT_FAMC;
292       break;
293     case ELT_SUB_INDIV_ADOP:
294       fam_obj_elt = ELT_SUB_INDIV_ADOP_FAMC;
295       break;
296     default:
297       gedcom_warning(_("Internal error: wrong parent for evt->family"));
298   }
299   return fam_obj_elt;
300 }
301
302 int write_events(Gedcom_write_hndl hndl, int parent, EventType evt_type,
303                  struct event* evt)
304 {
305   int result = 0;
306   int i;
307   struct event* obj;
308
309   if (!evt) return 1;
310
311   for (obj = evt; obj; obj = obj->next) {
312     int obj_elt = get_gedcom_elt(evt_type, obj->event);
313     result |= gedcom_write_element_str(hndl, obj_elt, obj->event,
314                                        parent, obj->val);
315     if (obj->type)
316       result |= gedcom_write_element_str(hndl, ELT_SUB_EVT_TYPE, 0,
317                                          obj_elt, obj->type);
318     if (obj->date)
319       result |= gedcom_write_element_date(hndl, ELT_SUB_EVT_DATE, 0,
320                                           obj_elt, obj->date);
321     if (obj->place)
322       result |= write_place(hndl, obj_elt, obj->place);
323     if (obj->address)
324       result |= write_address(hndl, obj_elt, obj->address);
325     for (i = 0; i < 3 && obj->phone[i]; i++)
326       result |= gedcom_write_element_str(hndl, ELT_SUB_PHON, 0, obj_elt,
327                                          obj->phone[i]);
328     if (obj->age)
329       result |= gedcom_write_element_age(hndl, ELT_SUB_EVT_AGE, 0,
330                                          obj_elt, obj->age);
331     if (obj->agency)
332       result |= gedcom_write_element_str(hndl, ELT_SUB_EVT_AGNC, 0,
333                                          obj_elt, obj->agency);
334     if (obj->cause)
335       result |= gedcom_write_element_str(hndl, ELT_SUB_EVT_CAUS, 0,
336                                          obj_elt, obj->cause);
337     if (obj->citation)
338       result |= write_citations(hndl, obj_elt, obj->citation);
339     if (obj->mm_link)
340       result |= write_multimedia_links(hndl, obj_elt, obj->mm_link);
341     if (obj->note)
342       result |= write_note_subs(hndl, obj_elt, obj->note);
343     if (obj->husband_age) {
344       result |= gedcom_write_element_str(hndl, ELT_SUB_FAM_EVT_HUSB, 0,
345                                          obj_elt, NULL);
346       result |= gedcom_write_element_age(hndl, ELT_SUB_FAM_EVT_AGE, 0,
347                                          ELT_SUB_FAM_EVT_HUSB,
348                                          obj->husband_age);
349     }
350     if (obj->wife_age) {
351       result |= gedcom_write_element_str(hndl, ELT_SUB_FAM_EVT_WIFE, 0,
352                                          obj_elt, NULL);
353       result |= gedcom_write_element_age(hndl, ELT_SUB_FAM_EVT_AGE, 0,
354                                          ELT_SUB_FAM_EVT_WIFE,
355                                          obj->wife_age);
356     }
357     if (obj->family) {
358       int fam_obj_elt = get_gedcom_fam_elt(obj_elt);
359       result |= gedcom_write_element_xref(hndl, fam_obj_elt, 0,
360                                           obj_elt, obj->family);
361       if (obj->adoption_parent) {
362         result |= gedcom_write_element_str(hndl, ELT_SUB_INDIV_ADOP_FAMC_ADOP,
363                                            0, fam_obj_elt,
364                                            obj->adoption_parent);
365       }
366     }
367     if (obj->extra)
368       result |= write_user_data(hndl, obj->extra);
369   }
370   
371   return result;
372 }
373