Improved context handling, to allow elements out of context.
[gedcom-parse.git] / gom / address.c
1 /* Address 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 "gom_internal.h"
27 #include "header.h"
28 #include "event.h"
29 #include "address.h"
30 #include "repository.h"
31 #include "submitter.h"
32 #include "user_rec.h"
33 #include "gom.h"
34 #include "gedcom.h"
35
36 Gedcom_ctxt sub_addr_start(_ELT_PARAMS_)
37 {
38   Gom_ctxt ctxt = (Gom_ctxt)parent;
39   Gom_ctxt result = NULL;
40
41   if (!ctxt)
42     NO_CONTEXT;
43   else {
44     struct address *addr = SUB_MAKEFUNC(address)();
45     if (addr) {
46       int type = ctxt_type(ctxt);
47       switch (type) {
48         case ELT_HEAD_SOUR_CORP:
49           ADDFUNC2_NOLIST(header,address)(ctxt, addr); break;
50         case ELT_SUB_FAM_EVT:
51         case ELT_SUB_FAM_EVT_EVEN:
52         case ELT_SUB_INDIV_ATTR:
53         case ELT_SUB_INDIV_RESI:
54         case ELT_SUB_INDIV_BIRT:
55         case ELT_SUB_INDIV_GEN:
56         case ELT_SUB_INDIV_ADOP:
57         case ELT_SUB_INDIV_EVEN:
58           ADDFUNC2_NOLIST(event,address)(ctxt, addr); break;
59         case REC_REPO:
60           ADDFUNC2_NOLIST(repository,address)(ctxt, addr); break;
61         case REC_SUBM:
62           ADDFUNC2_NOLIST(submitter,address)(ctxt, addr); break;
63         default:
64           UNEXPECTED_CONTEXT(type);
65       }
66       result = MAKE_GOM_CTXT(elt, address, addr);
67     }
68   }
69   
70   return (Gedcom_ctxt)result;
71 }
72
73 Gedcom_ctxt sub_addr_cont_start(_ELT_PARAMS_)
74 {
75   Gom_ctxt ctxt = (Gom_ctxt)parent;
76   Gom_ctxt result = NULL;
77   if (! ctxt)
78     NO_CONTEXT;
79   else {
80     result = dup_gom_ctxt(ctxt, elt);
81   }
82   return (Gedcom_ctxt)result;
83 }
84
85 DEFINE_SUB_MAKEFUNC(address)
86 DEFINE_SUB_SETFUNC(address)
87 DEFINE_SUB_DELETEFUNC(address)
88
89 DEFINE_STRING_END_CB(address, sub_addr_end, full_label)
90 DEFINE_STRING_CB(address, sub_addr_adr1_start, line1)
91 DEFINE_STRING_CB(address, sub_addr_adr2_start, line2)
92 DEFINE_STRING_CB(address, sub_addr_city_start, city)
93 DEFINE_STRING_CB(address, sub_addr_stae_start, state)
94 DEFINE_STRING_CB(address, sub_addr_post_start, postal)
95 DEFINE_STRING_CB(address, sub_addr_ctry_start, country)
96
97 DEFINE_ADDFUNC2(address, user_data, extra)
98
99 Gedcom_ctxt sub_phon_start(_ELT_PARAMS_)
100 {
101   Gom_ctxt ctxt = (Gom_ctxt)parent;
102   Gom_ctxt result = NULL;
103
104   if (! ctxt)
105     NO_CONTEXT;
106   else {
107     char *str = GEDCOM_STRING(parsed_value);
108     int type = ctxt_type(ctxt);
109     switch (type) {
110       case ELT_HEAD_SOUR_CORP:
111         header_add_phone(ctxt, str); break;
112       case ELT_SUB_FAM_EVT:
113       case ELT_SUB_INDIV_ATTR:
114       case ELT_SUB_INDIV_RESI:
115       case ELT_SUB_INDIV_BIRT:
116       case ELT_SUB_INDIV_GEN:
117       case ELT_SUB_INDIV_ADOP:
118       case ELT_SUB_INDIV_EVEN:
119         event_add_phone(ctxt, str); break;
120       case REC_REPO:
121         repository_add_phone(ctxt, str); break;
122       case REC_SUBM:
123         submitter_add_phone(ctxt, str); break;
124       default:
125         UNEXPECTED_CONTEXT(type);
126     }
127     result = dup_gom_ctxt(ctxt, elt);
128   }
129   return (Gedcom_ctxt)result;
130 }
131
132 void address_subscribe()
133 {
134   gedcom_subscribe_to_element(ELT_SUB_ADDR, sub_addr_start, sub_addr_end);
135   gedcom_subscribe_to_element(ELT_SUB_ADDR_CONT,
136                               sub_addr_cont_start, def_elt_end);
137   gedcom_subscribe_to_element(ELT_SUB_ADDR_ADR1,
138                               sub_addr_adr1_start, def_elt_end);
139   gedcom_subscribe_to_element(ELT_SUB_ADDR_ADR2,
140                               sub_addr_adr2_start, def_elt_end);
141   gedcom_subscribe_to_element(ELT_SUB_ADDR_CITY,
142                               sub_addr_city_start, def_elt_end);
143   gedcom_subscribe_to_element(ELT_SUB_ADDR_STAE,
144                               sub_addr_stae_start, def_elt_end);
145   gedcom_subscribe_to_element(ELT_SUB_ADDR_POST,
146                               sub_addr_post_start, def_elt_end);
147   gedcom_subscribe_to_element(ELT_SUB_ADDR_CTRY,
148                               sub_addr_ctry_start, def_elt_end);
149   gedcom_subscribe_to_element(ELT_SUB_PHON, sub_phon_start, def_elt_end);
150 }
151
152 void UNREFALLFUNC(address)(struct address *address)
153 {
154   if (address) {
155     UNREFALLFUNC(user_data)(address->extra);
156   }
157 }
158
159 void CLEANFUNC(address)(struct address *address)
160 {
161   if (address) {
162     SAFE_FREE(address->full_label);
163     SAFE_FREE(address->line1);
164     SAFE_FREE(address->line2);
165     SAFE_FREE(address->city);
166     SAFE_FREE(address->state);
167     SAFE_FREE(address->postal);
168     SAFE_FREE(address->country);
169     DESTROY_CHAIN_ELTS(user_data, address->extra);
170   }
171   SAFE_FREE(address);
172 }
173
174 int write_address(Gedcom_write_hndl hndl, int parent, struct address *address)
175 {
176   int result = 0;
177
178   if (!address) return 1;
179   
180   if (address->full_label)
181     result |= gedcom_write_element_str(hndl, ELT_SUB_ADDR, 0, parent,
182                                        address->full_label);
183   if (address->line1)
184     result |= gedcom_write_element_str(hndl, ELT_SUB_ADDR_ADR1, 0,
185                                        ELT_SUB_ADDR, address->line1);
186   if (address->line2)
187     result |= gedcom_write_element_str(hndl, ELT_SUB_ADDR_ADR2, 0,
188                                        ELT_SUB_ADDR, address->line2);
189   if (address->city)
190     result |= gedcom_write_element_str(hndl, ELT_SUB_ADDR_CITY, 0,
191                                        ELT_SUB_ADDR, address->city);
192   if (address->state)
193     result |= gedcom_write_element_str(hndl, ELT_SUB_ADDR_STAE, 0,
194                                        ELT_SUB_ADDR, address->state);
195   if (address->postal)
196     result |= gedcom_write_element_str(hndl, ELT_SUB_ADDR_POST, 0,
197                                        ELT_SUB_ADDR, address->postal);
198   if (address->country)
199     result |= gedcom_write_element_str(hndl, ELT_SUB_ADDR_CTRY, 0,
200                                        ELT_SUB_ADDR, address->country);
201   if (address->extra)
202     result |= write_user_data(hndl, address->extra);
203
204   return result;
205 }