Add mouse vertical scrolling.
[familia.git] / src / storage / individual.c
1 #include <stdlib.h>
2 #include <string.h>
3
4 #include "individual.h"
5
6 #include "../debug.h"
7
8 struct familia_individual * familia_individual_new()
9 {
10         struct familia_individual * individual = NULL;
11         individual = malloc(sizeof(struct familia_individual));
12
13         if (!individual) {
14                 debug("["__FILE__ "] There was a problem with allocating memory for individual.\n");
15                 return NULL;
16         }
17
18         individual->id = 0;
19         individual->first_name = NULL;
20         individual->last_name = NULL;
21         individual->families = NULL;
22         individual->families_no = 0;
23         individual->parents = NULL;
24         individual->birth = NULL;
25
26         return individual;
27 }
28
29 void familia_individual_free(struct familia_individual * individual)
30 {
31         unsigned int i = 0;
32
33         if (individual->first_name) {
34                 free(individual->first_name);
35                 individual->first_name = NULL;
36         }
37
38         if (individual->last_name) {
39                 free(individual->last_name);
40                 individual->last_name = NULL;
41         }
42
43         if (individual->families) {
44                 /* Remove all family links. */
45                 for (i = 0; i < individual->families_no; i++) {
46                         individual->families[i] = NULL;
47                 }
48                 free(individual->families);
49                 individual->families = NULL;
50                 individual->families_no = 0;
51         }
52
53         if (individual->parents) {
54                 individual->parents = NULL;
55         }
56
57         if (individual->birth) {
58                 free(individual->birth);
59                 individual->birth = NULL;
60         }
61
62         free(individual);
63 }
64
65 void familia_individual_set_first_name(struct familia_individual * individual, char * first_name)
66 {
67         /* Remove old data if it exists */
68         if (individual->first_name) {
69                 free(individual->first_name);
70         }
71
72         individual->first_name = malloc(strlen(first_name) + 1);
73
74         /*
75          * Malloc could return null on allocation failure.
76          * Check if memory is allocated correctly and copy string.
77          */
78         if (individual->first_name) {
79                 strcpy(individual->first_name, first_name);
80         }
81         else {
82                 debug("There were problems with allocating memory for individual first name.\n");
83         }
84 }
85
86 char * familia_individual_get_first_name(struct familia_individual * individual)
87 {
88         return individual->first_name;
89 }
90
91 void familia_individual_set_last_name(struct familia_individual * individual, char * last_name)
92 {
93         /* Remove old data if it exists */
94         if (individual->last_name) {
95                 free(individual->last_name);
96         }
97         
98         if (last_name == NULL) {
99                 debug ("IS NULL");
100         }
101
102         individual->last_name = malloc(strlen(last_name) + 1);
103
104         /*
105          * Malloc returns NULL on allocation failure.
106          * Check if memory is allocated correctly and copy string.
107          */
108         if (individual->last_name) {
109                 strncpy(individual->last_name, last_name, strlen(last_name));
110         }
111         else {
112                 debug("There were problems with allocating memory for individual last name.\n");
113         }
114 }
115
116 char * familia_individual_get_last_name(struct familia_individual * individual)
117 {
118         return individual->last_name;
119 }
120
121 void familia_individual_add_family(struct familia_individual * individual, struct familia_family * family)
122 {
123         struct familia_family ** tmp = NULL;
124         int size = (individual->families_no + 1);
125
126         tmp = realloc(individual->families, size * sizeof(struct familia_family *));
127
128         if (tmp) {
129                 individual->families = tmp;
130                 individual->families[individual->families_no] = family;
131                 individual->families_no++;
132         }
133         else {
134                 debug("There were problems with allocating memory for family.\n");
135         }
136
137 }
138
139 struct familia_family * familia_individual_get_family_by_id(struct familia_individual * individual, unsigned int id)
140 {
141         if (individual->families_no < id) {
142                 debug("Trying to get not existing family!\n");
143                 return NULL;
144         }
145         return individual->families[id];
146 }
147
148 void familia_individual_remove_family_by_id(struct familia_individual * individual, unsigned int id)
149 {
150         unsigned int i = 0;
151         int found = 0;
152         struct familia_family ** tmp = NULL;
153         
154         if (individual->families_no < id) {
155                 debug("Trying to remove not existing family!\n");
156                 return;
157         }
158
159         for (i = 0; i < individual->families_no; i++) {
160                 if (individual->families[i]->id == id) {
161                         found = 1;
162                         individual->families[i] = NULL;
163                 }
164
165                 /*
166                  * If family has been found, reorder rest of files to avoid
167                  * NULL pointers inside array.
168                  */
169                 if (found && (i < individual->families_no - 1)) {
170                         individual->families[i] = individual->families[i + 1];
171                 }
172         }
173         
174         if (found) {
175                 tmp = realloc(individual->families,
176                         (individual->families_no) * sizeof(struct familia_family *));
177
178                 if (tmp) {
179                         individual->families = tmp;
180                 }
181                 individual->families_no--;
182         }
183 }
184
185 void familia_individual_set_parents(struct familia_individual * individual, struct familia_family * family)
186 {
187         individual->parents = family;
188 }
189
190 struct familia_family * familia_individual_get_parents(struct familia_individual * individual)
191 {
192         return individual->parents;
193 }
194
195 void familia_individual_remove_parents(struct familia_individual * individual)
196 {
197         individual->parents = NULL;
198 }
199
200 int familia_individual_nth_child_of_family(struct familia_individual * individual, struct familia_family * family)
201 {
202         unsigned int i;
203         unsigned int children_no = family->children_no;
204
205         for (i = 0; i < children_no; i++) {
206                 if (family->children[i]->id == individual->id) {
207                         return i;
208                 }
209         }
210
211         return -1;
212 }
213
214 void familia_individual_set_birth_date(struct familia_individual * individual, struct date_value dv)
215 {
216         /* TODO: Add multiple birth dates (in case there are many different sources) */
217         if (!individual->birth) {
218                 struct date_value * date = NULL;
219                 date = gedcom_new_date_value(NULL);
220
221                 /* Just copy parsed date_value to newly allocated variable... */
222                 memcpy(date, &dv, sizeof(struct date_value));
223                 individual->birth = date;
224         }
225         else {
226                 fprintf(stderr, "> Date has been already set, ignoring new one: %s\n", gedcom_date_to_string(&dv));
227         }
228 }