Also write empty CONT lines.
[gedcom-parse.git] / gom / change_date.c
1 /* Change date 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 <time.h>
27 #include "change_date.h"
28 #include "family.h"
29 #include "individual.h"
30 #include "note_sub.h"
31 #include "multimedia.h"
32 #include "note.h"
33 #include "repository.h"
34 #include "source.h"
35 #include "submitter.h"
36 #include "user_rec.h"
37 #include "gom_internal.h"
38 #include "gom.h"
39 #include "gedcom.h"
40
41 Gedcom_ctxt sub_chan_start(_ELT_PARAMS_)
42 {
43   Gom_ctxt ctxt = (Gom_ctxt)parent;
44   Gom_ctxt result = NULL;
45
46   if (! ctxt)
47     NO_CONTEXT;
48   else {
49     struct change_date *chan = SUB_MAKEFUNC(change_date)();
50     if (chan) {
51       switch (ctxt->ctxt_type) {
52         case REC_FAM:
53           ADDFUNC2_NOLIST(family,change_date)(ctxt, chan); break;
54         case REC_INDI:
55           ADDFUNC2_NOLIST(individual,change_date)(ctxt, chan); break;
56         case REC_OBJE:
57           ADDFUNC2_NOLIST(multimedia,change_date)(ctxt, chan); break;
58         case REC_NOTE:
59           ADDFUNC2_NOLIST(note,change_date)(ctxt, chan); break;
60         case REC_REPO:
61           ADDFUNC2_NOLIST(repository,change_date)(ctxt, chan); break;
62         case REC_SOUR:
63           ADDFUNC2_NOLIST(source,change_date)(ctxt, chan); break;
64         case REC_SUBM:
65           ADDFUNC2_NOLIST(submitter,change_date)(ctxt, chan); break;
66         default:
67           UNEXPECTED_CONTEXT(ctxt->ctxt_type);
68       }
69       result = MAKE_GOM_CTXT(elt, change_date, chan);
70     }
71   }
72   
73   return (Gedcom_ctxt)result;
74 }
75
76 DEFINE_SUB_MAKEFUNC(change_date)
77 DEFINE_SUB_SETFUNC(change_date)
78 DEFINE_SUB_DELETEFUNC(change_date)
79
80 DEFINE_DATE_CB(change_date, sub_chan_date_start, date)
81 DEFINE_STRING_CB(change_date, sub_chan_time_start, time)
82
83 DEFINE_ADDFUNC2(change_date, note_sub, note)
84 DEFINE_ADDFUNC2(change_date, user_data, extra)
85
86 void change_date_subscribe()
87 {
88   gedcom_subscribe_to_element(ELT_SUB_CHAN, sub_chan_start, def_elt_end);
89   gedcom_subscribe_to_element(ELT_SUB_CHAN_DATE, sub_chan_date_start,
90                               def_elt_end);
91   gedcom_subscribe_to_element(ELT_SUB_CHAN_TIME, sub_chan_time_start,
92                               def_elt_end);
93 }
94
95 void UNREFALLFUNC(change_date)(struct change_date* obj)
96 {
97   if (obj) {
98     UNREFALLFUNC(note_sub)(obj->note);
99     UNREFALLFUNC(user_data)(obj->extra);
100   }
101 }
102
103 void CLEANFUNC(change_date)(struct change_date *chan)
104 {
105   if (chan) {
106     SAFE_FREE(chan->date);
107     SAFE_FREE(chan->time);
108     DESTROY_CHAIN_ELTS(note_sub, chan->note);
109     DESTROY_CHAIN_ELTS(user_data, chan->extra);
110   }
111   SAFE_FREE(chan);
112 }
113
114 int update_date(struct date_value** dv, struct tm* tm_ptr)
115 {
116   int result;
117   struct date_value* dval = gedcom_new_date_value(NULL);
118   dval->type        = DV_NO_MODIFIER;
119   dval->date1.cal   = CAL_GREGORIAN;
120   dval->date1.day   = tm_ptr->tm_mday;
121   dval->date1.month = tm_ptr->tm_mon + 1;
122   dval->date1.year  = tm_ptr->tm_year + 1900;
123   result = gedcom_normalize_date(DI_FROM_NUMBERS, dval);
124
125   if (result == 0) {
126     if (*dv) free(*dv);
127     *dv = dval;
128   }
129   return result;
130 }
131
132 int update_time(char** tv, struct tm* tm_ptr)
133 {
134   char tval[16];
135   sprintf(tval, "%02d:%02d:%02d",
136           tm_ptr->tm_hour, tm_ptr->tm_min, tm_ptr->tm_sec);
137
138   if (gom_set_string(tv, tval))
139     return 0;
140   else
141     return 1;
142 }
143
144 int gom_update_timestamp(struct change_date** chan, time_t t)
145 {
146   int result = 1;
147   if (chan) {
148     if (! *chan) gom_set_new_change_date(chan);
149     if (*chan) {
150       struct tm *tm_ptr = localtime(&t);
151       result = 0;
152       result |= update_date(&((*chan)->date), tm_ptr);
153       result |= update_time(&((*chan)->time), tm_ptr);
154     }
155   }
156   return result;
157 }
158
159 int write_change_date(Gedcom_write_hndl hndl, int parent,
160                       struct change_date *chan)
161 {
162   int result = 0;
163
164   if (!chan) return 1;
165
166   result |= gedcom_write_element_str(hndl, ELT_SUB_CHAN, 0, parent, NULL);
167   if (chan->date)
168     result |= gedcom_write_element_date(hndl, ELT_SUB_CHAN_DATE, 0,
169                                         ELT_SUB_CHAN, chan->date);
170   if (chan->time)
171     result |= gedcom_write_element_str(hndl, ELT_SUB_CHAN_TIME, 0,
172                                        ELT_SUB_CHAN_DATE, chan->time);
173   if (chan->note)
174     result |= write_note_subs(hndl, ELT_SUB_CHAN, chan->note);
175   if (chan->extra)
176     result |= write_user_data(hndl, chan->extra);
177   
178   return result;
179 }