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