A little simplification in the write interface.
[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               family_add_event(ctxt, evt); break;
74             case REC_INDI:
75               individual_add_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               individual_add_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 STRING_CB(event, sub_evt_type_start, type)
135 DATE_CB(event, sub_evt_date_start, date)
136 AGE_CB(event, sub_evt_age_start, age)
137 STRING_CB(event, sub_evt_agnc_start, agency)
138 STRING_CB(event, sub_evt_caus_start, cause)
139 NULL_CB(event, sub_fam_evt_husb_wife_start)
140 XREF_CB(event, sub_evt_famc_start, family, make_family_record)
141 STRING_CB(event, sub_evt_famc_adop_start, adoption_parent)
142      
143 Gedcom_ctxt sub_fam_evt_age_start(_ELT_PARAMS_)
144 {
145   Gom_ctxt ctxt = (Gom_ctxt)parent;
146   Gom_ctxt result = NULL;
147   
148   if (! ctxt)
149     NO_CONTEXT;
150   else {
151     struct event *evt = SAFE_CTXT_CAST(event, ctxt);
152     if (evt) {
153       int err = 0;
154       struct age_value age = GEDCOM_AGE(parsed_value);
155       switch (ctxt->ctxt_type) {
156         case ELT_SUB_FAM_EVT_HUSB:
157           evt->husband_age = gedcom_new_age_value(&age);
158           if (! evt->husband_age) {
159             MEMORY_ERROR;
160             err = 1;
161           }
162           break;
163         case ELT_SUB_FAM_EVT_WIFE:
164           evt->wife_age = gedcom_new_age_value(&age);
165           if (! evt->wife_age) {
166             MEMORY_ERROR;
167             err = 1;
168           }
169           break;
170         default:
171           UNEXPECTED_CONTEXT(ctxt->ctxt_type);
172       }
173       if (! err)
174         result = MAKE_GOM_CTXT(elt, event, evt);
175     }
176   }
177   return (Gedcom_ctxt)result;
178 }
179
180 void event_add_place(Gom_ctxt ctxt, struct place* place)
181 {
182   struct event *evt = SAFE_CTXT_CAST(event, ctxt);
183   if (evt)
184     evt->place = place;
185 }
186
187 void event_add_address(Gom_ctxt ctxt, struct address* address)
188 {
189   struct event *evt = SAFE_CTXT_CAST(event, ctxt);
190   if (evt)
191     evt->address = address;
192 }
193
194 void event_add_phone(Gom_ctxt ctxt, char *phone)
195 {
196   struct event *evt = SAFE_CTXT_CAST(event, ctxt);
197   if (evt) {
198     int i = 0;
199     while (i<2 && evt->phone[i]) i++;
200     if (! evt->phone[i]) {
201       evt->phone[i] = strdup(phone);
202       if (! evt->phone[i]) MEMORY_ERROR;
203     }
204   }
205 }
206
207 void event_add_citation(Gom_ctxt ctxt, struct source_citation* cit)
208 {
209   struct event *evt = SAFE_CTXT_CAST(event, ctxt);
210   if (evt)
211     LINK_CHAIN_ELT(source_citation, evt->citation, cit);  
212 }
213
214 void event_add_mm_link(Gom_ctxt ctxt, struct multimedia_link* mm)
215 {
216   struct event *evt = SAFE_CTXT_CAST(event, ctxt);
217   if (evt)
218     LINK_CHAIN_ELT(multimedia_link, evt->mm_link, mm);
219 }
220
221 void event_add_note(Gom_ctxt ctxt, struct note_sub* note)
222 {
223   struct event *evt = SAFE_CTXT_CAST(event, ctxt);
224   if (evt)
225     LINK_CHAIN_ELT(note_sub, evt->note, note);
226 }
227
228 void event_add_user_data(Gom_ctxt ctxt, struct user_data* data)
229 {
230   struct event *obj = SAFE_CTXT_CAST(event, ctxt);
231   if (obj)
232     LINK_CHAIN_ELT(user_data, obj->extra, data);
233 }
234
235 void event_subscribe()
236 {
237   gedcom_subscribe_to_element(ELT_SUB_FAM_EVT, sub_evt_start, def_elt_end);
238   gedcom_subscribe_to_element(ELT_SUB_FAM_EVT_EVEN,
239                               sub_evt_start, def_elt_end);
240   gedcom_subscribe_to_element(ELT_SUB_INDIV_ATTR,
241                               sub_attr_start, def_elt_end);  
242   gedcom_subscribe_to_element(ELT_SUB_INDIV_RESI,
243                               sub_attr_start, def_elt_end);
244   gedcom_subscribe_to_element(ELT_SUB_INDIV_BIRT,
245                               sub_evt_start, def_elt_end);
246   gedcom_subscribe_to_element(ELT_SUB_INDIV_BIRT_FAMC,
247                               sub_evt_famc_start, def_elt_end);
248   gedcom_subscribe_to_element(ELT_SUB_INDIV_GEN,
249                               sub_evt_start, def_elt_end);
250   gedcom_subscribe_to_element(ELT_SUB_INDIV_ADOP,
251                               sub_evt_start, def_elt_end);
252   gedcom_subscribe_to_element(ELT_SUB_INDIV_ADOP_FAMC,
253                               sub_evt_famc_start, def_elt_end);
254   gedcom_subscribe_to_element(ELT_SUB_INDIV_ADOP_FAMC_ADOP,
255                               sub_evt_famc_adop_start, def_elt_end);
256   gedcom_subscribe_to_element(ELT_SUB_INDIV_EVEN,
257                               sub_evt_start, def_elt_end);
258   gedcom_subscribe_to_element(ELT_SUB_FAM_EVT_HUSB,
259                               sub_fam_evt_husb_wife_start, def_elt_end);
260   gedcom_subscribe_to_element(ELT_SUB_FAM_EVT_WIFE,
261                               sub_fam_evt_husb_wife_start, def_elt_end);
262   gedcom_subscribe_to_element(ELT_SUB_FAM_EVT_AGE,
263                               sub_fam_evt_age_start, def_elt_end);
264   gedcom_subscribe_to_element(ELT_SUB_EVT_TYPE,
265                               sub_evt_type_start, def_elt_end);
266   gedcom_subscribe_to_element(ELT_SUB_EVT_DATE,
267                               sub_evt_date_start, def_elt_end);
268   gedcom_subscribe_to_element(ELT_SUB_EVT_AGE,
269                               sub_evt_age_start, def_elt_end);
270   gedcom_subscribe_to_element(ELT_SUB_EVT_AGNC,
271                               sub_evt_agnc_start, def_elt_end);
272   gedcom_subscribe_to_element(ELT_SUB_EVT_CAUS,
273                               sub_evt_caus_start, def_elt_end);
274 }
275
276 void event_cleanup(struct event* evt)
277 {
278   if (evt) {
279     SAFE_FREE(evt->event_name);
280     SAFE_FREE(evt->val);
281     SAFE_FREE(evt->type);
282     SAFE_FREE(evt->date);
283     place_cleanup(evt->place);
284     address_cleanup(evt->address);
285     SAFE_FREE(evt->phone[0]);
286     SAFE_FREE(evt->phone[1]);
287     SAFE_FREE(evt->phone[2]);
288     SAFE_FREE(evt->age);
289     SAFE_FREE(evt->agency);
290     SAFE_FREE(evt->cause);
291     DESTROY_CHAIN_ELTS(source_citation, evt->citation, citation_cleanup);
292     DESTROY_CHAIN_ELTS(multimedia_link, evt->mm_link, multimedia_link_cleanup);
293     DESTROY_CHAIN_ELTS(note_sub, evt->note, note_sub_cleanup);
294     SAFE_FREE(evt->husband_age);
295     SAFE_FREE(evt->wife_age);
296     SAFE_FREE(evt->adoption_parent);
297     DESTROY_CHAIN_ELTS(user_data, evt->extra, user_data_cleanup);
298   }
299 }
300
301 static int get_gedcom_elt(EventType evt_type, int parsed_tag)
302 {
303   int obj_elt = 0;
304   switch (evt_type) {
305     case EVT_TYPE_FAMILY:
306       obj_elt = (parsed_tag == TAG_EVEN ? ELT_SUB_FAM_EVT_EVEN :
307                  ELT_SUB_FAM_EVT);
308       break;
309     case EVT_TYPE_INDIV_ATTR:
310       obj_elt = (parsed_tag == TAG_RESI ? ELT_SUB_INDIV_RESI :
311                  ELT_SUB_INDIV_ATTR);
312       break;
313     case EVT_TYPE_INDIV_EVT:
314       switch (parsed_tag) {
315         case TAG_BIRT: case TAG_CHR:
316           obj_elt = ELT_SUB_INDIV_BIRT; break;
317         case TAG_DEAT: case TAG_BURI: case TAG_CREM: case TAG_BAPM:
318         case TAG_BARM: case TAG_BASM: case TAG_BLES: case TAG_CHRA:
319         case TAG_CONF: case TAG_FCOM: case TAG_ORDN: case TAG_NATU:
320         case TAG_EMIG: case TAG_IMMI: case TAG_CENS: case TAG_PROB:
321         case TAG_WILL: case TAG_GRAD: case TAG_RETI:
322           obj_elt = ELT_SUB_INDIV_GEN; break;
323         case TAG_ADOP:
324           obj_elt = ELT_SUB_INDIV_ADOP; break;
325         case TAG_EVEN:
326           obj_elt = ELT_SUB_INDIV_EVEN; break;
327         default:
328           gedcom_warning(_("Internal error: unknown evt tag %d"), parsed_tag);
329       }
330       break;
331     default:
332       gedcom_warning(_("Internal error: unknown evt type %d"), evt_type);
333   }
334   return obj_elt;
335 }
336
337 int get_gedcom_fam_elt(int elt)
338 {
339   int fam_obj_elt = 0;
340   switch (elt) {
341     case ELT_SUB_INDIV_BIRT:
342       fam_obj_elt = ELT_SUB_INDIV_BIRT_FAMC;
343       break;
344     case ELT_SUB_INDIV_ADOP:
345       fam_obj_elt = ELT_SUB_INDIV_ADOP_FAMC;
346       break;
347     default:
348       gedcom_warning(_("Internal error: wrong parent for evt->family"));
349   }
350   return fam_obj_elt;
351 }
352
353 int write_events(Gedcom_write_hndl hndl, int parent, EventType evt_type,
354                  struct event* evt)
355 {
356   int result = 0;
357   int i;
358   struct event* obj;
359
360   if (!evt) return 1;
361
362   for (obj = evt; obj; obj = obj->next) {
363     int obj_elt = get_gedcom_elt(evt_type, obj->event);
364     result |= gedcom_write_element_str(hndl, obj_elt, obj->event,
365                                        parent, obj->val);
366     if (obj->type)
367       result |= gedcom_write_element_str(hndl, ELT_SUB_EVT_TYPE, 0,
368                                          obj_elt, obj->type);
369     if (obj->date)
370       result |= gedcom_write_element_date(hndl, ELT_SUB_EVT_DATE, 0,
371                                           obj_elt, obj->date);
372     if (obj->place)
373       result |= write_place(hndl, obj_elt, obj->place);
374     if (obj->address)
375       result |= write_address(hndl, obj_elt, obj->address);
376     for (i = 0; i < 3 && obj->phone[i]; i++)
377       result |= gedcom_write_element_str(hndl, ELT_SUB_PHON, 0, obj_elt,
378                                          obj->phone[i]);
379     if (obj->age)
380       result |= gedcom_write_element_age(hndl, ELT_SUB_EVT_AGE, 0,
381                                          obj_elt, obj->age);
382     if (obj->agency)
383       result |= gedcom_write_element_str(hndl, ELT_SUB_EVT_AGNC, 0,
384                                          obj_elt, obj->agency);
385     if (obj->cause)
386       result |= gedcom_write_element_str(hndl, ELT_SUB_EVT_CAUS, 0,
387                                          obj_elt, obj->cause);
388     if (obj->citation)
389       result |= write_citations(hndl, obj_elt, obj->citation);
390     if (obj->mm_link)
391       result |= write_multimedia_links(hndl, obj_elt, obj->mm_link);
392     if (obj->note)
393       result |= write_note_subs(hndl, obj_elt, obj->note);
394     if (obj->husband_age) {
395       result |= gedcom_write_element_str(hndl, ELT_SUB_FAM_EVT_HUSB, 0,
396                                          obj_elt, NULL);
397       result |= gedcom_write_element_age(hndl, ELT_SUB_FAM_EVT_AGE, 0,
398                                          ELT_SUB_FAM_EVT_HUSB,
399                                          obj->husband_age);
400     }
401     if (obj->wife_age) {
402       result |= gedcom_write_element_str(hndl, ELT_SUB_FAM_EVT_WIFE, 0,
403                                          obj_elt, NULL);
404       result |= gedcom_write_element_age(hndl, ELT_SUB_FAM_EVT_AGE, 0,
405                                          ELT_SUB_FAM_EVT_WIFE,
406                                          obj->wife_age);
407     }
408     if (obj->family) {
409       int fam_obj_elt = get_gedcom_fam_elt(obj_elt);
410       result |= gedcom_write_element_xref(hndl, fam_obj_elt, 0,
411                                           obj_elt, obj->family);
412       if (obj->adoption_parent) {
413         result |= gedcom_write_element_str(hndl, ELT_SUB_INDIV_ADOP_FAMC_ADOP,
414                                            0, fam_obj_elt,
415                                            obj->adoption_parent);
416       }
417     }
418     if (obj->extra)
419       result |= write_user_data(hndl, obj->extra);
420   }
421   
422   return result;
423 }
424