More generic use of event.
[familia.git] / src / storage / positions.c
1 /****************************************************************************
2  *  Familia Lignum - Genealogical program                                   *
3  *  Copyright (C) 2011-2012 Rafał Długołęcki <rafal@dlugolecki.net.pl>      *
4  *                                                                          *
5  *  This program is free software; you can redistribute it and/or modify    *
6  *  it under the terms of the GNU General Public License as published by    *
7  *  the Free Software Foundation; version 2 of the License.                 *
8  *                                                                          *
9  *  This program is distributed in the hope that it will be useful,         *
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of          *
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
12  *  GNU General Public License for more details.                            *
13  *                                                                          *
14  *  You should have received a copy of the GNU General Public License along *
15  *  with this program; if not, write to the Free Software Foundation, Inc., *
16  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.             *
17  *                                                                          *
18  ****************************************************************************/
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <assert.h>
23
24 #include "../debug.h"
25
26 #include "positions.h"
27
28 /**
29  * Structure holding individual and position pair
30  */
31 struct familia_storage_individual_position {
32         struct familia_individual *ind;
33         struct position *pos;
34 };
35
36 /**
37  * Structure holding family and position pair
38  */
39 struct familia_storage_family_position {
40         struct familia_family *fam;
41         struct position *pos;
42 };
43
44 /**
45  * Structure holding individual and family positions
46  */
47 struct familia_storage_positions {
48         struct familia_storage_individual_position **individuals;
49
50         unsigned int individuals_no;
51
52         struct familia_storage_family_position **families;
53
54         unsigned int families_no;
55 };
56
57 /**
58  * Global variable for storing positions of graphic objects.
59  *
60  * Example graphic object is an individual or family...
61  */
62 struct familia_storage_positions * storage_positions;
63
64 /**
65  * Initializes storage for individual and family positions.
66  */
67 void _familia_storage_positions_init()
68 {
69         if (!storage_positions) {
70                 storage_positions = malloc(sizeof(struct familia_storage_positions));
71                 
72                 if (!storage_positions) {
73                         debug("["__FILE__ "] There was a problem with allocating memory for storage of positions.\n");
74                 }
75                 else {
76                         storage_positions->individuals_no = 0;
77                         storage_positions->families_no = 0;
78                 }
79         }
80 }
81
82 /**
83  * Frees storage for the positions
84  */
85 void _familia_storage_positions_free()
86 {
87         if (storage_positions) {
88                 if (storage_positions->individuals) {
89                         free(storage_positions->individuals);
90                 }
91
92                 if (storage_positions->families) {
93                         free(storage_positions->families);
94                 }
95
96                 free(storage_positions);
97                 storage_positions = NULL;
98         }
99 }
100
101 /**
102  * Adds new position for the given individual.
103  *
104  * This function should be invoked only internaly and thus is not declared in
105  * header. Usage without caution can create duplicates in global variable
106  * storage_positions. Variable storage_positions is not prepared for such duplicates
107  * and this can provide to errors.
108  */
109 void _familia_positions_add_individual_position(struct familia_individual *individual, struct position *pos)
110 {
111         struct familia_storage_individual_position ** tmp = NULL;
112         unsigned int alloc_size = sizeof(struct familia_storage_individual_position *);
113
114         int size = (storage_positions->individuals_no + 1);
115
116         tmp = realloc(storage_positions->individuals, size * alloc_size);
117
118         if (tmp) {
119                 storage_positions->individuals = tmp;
120                 storage_positions->individuals[storage_positions->individuals_no]->ind = individual;
121                 storage_positions->individuals[storage_positions->individuals_no]->pos = pos;
122                 storage_positions->individuals_no++;
123         }
124         else {
125                 debug("There were problems with allocating memory for storage of individual positions->\n");
126         }
127 }
128
129 /**
130  * Adds new position for the given family.
131  *
132  * This function should be invoked only internaly and thus is not declared in
133  * header. Usage without caution can create duplicates in global variable
134  * storage_positions. Variable storage_positions is not prepared for such duplicates
135  * and this can provide to errors.
136  */
137 void _familia_positions_add_family_position(struct familia_family *family, struct position *pos)
138 {
139         struct familia_storage_family_position ** tmp = NULL;
140         unsigned int alloc_size = sizeof(struct familia_storage_family_position *);
141
142         int size = (storage_positions->families_no + 1);
143
144         tmp = realloc(storage_positions->families, size * alloc_size);
145
146         if (tmp) {
147                 storage_positions->families = tmp;
148                 storage_positions->families[storage_positions->families_no]->fam = family;
149                 storage_positions->families[storage_positions->families_no]->pos = pos;
150                 storage_positions->families_no++;
151         }
152         else {
153                 debug("There were problems with allocating memory for storage of family positions.\n");
154         }
155 }
156
157 void familia_positions_set_individual_position(struct familia_individual *individual, struct position *pos)
158 {
159         struct position * p = NULL;
160
161         p = familia_position_get_individual_position(individual);
162
163         /* If not found create a new one */
164         if (p == NULL) {
165                 _familia_positions_add_individual_position(individual, pos);
166         }
167 }
168
169 void familia_positions_set_family_position(struct familia_family *family, struct position *pos)
170 {
171         struct position * p = NULL;
172
173         p = familia_position_get_family_position(family);
174
175         /* If not found create a new one */
176         if (p == NULL) {
177                 _familia_positions_add_family_position(family, pos);
178         }
179 }
180
181 struct position * familia_position_get_individual_position(struct familia_individual *individual)
182 {
183         unsigned int i;
184         unsigned int id;
185
186         /*
187          * Uninitialized global. Return error.
188          */
189         if (!storage_positions || !storage_positions->individuals) {
190                 debug("Trying to request individual position, but positions storage is not initialized.\n");
191                 return NULL;
192         }
193
194         id = individual->id;
195
196         for (i = 0; i < storage_positions->individuals_no; i++) {
197                 if (storage_positions->individuals[i]->ind->id == id) {
198                         return storage_positions->individuals[i]->pos;
199                 }
200         }
201
202         /*
203          * Entry not found for a given individual. Return NULL.
204          */
205         return NULL;
206 }
207
208 struct position * familia_position_get_family_position(struct familia_family *family)
209 {
210         unsigned int i;
211         unsigned int id;
212
213         /*
214          * Uninitialized global. Return error.
215          */
216         if (!storage_positions || !storage_positions->families) {
217                 debug("Trying to request family position, but positions storage is not initialized.\n");
218                 return NULL;
219         }
220
221         id = family->id;
222
223         for (i = 0; i < storage_positions->families_no; i++) {
224                 if (storage_positions->families[i]->fam->id == id) {
225                         return storage_positions->families[i]->pos;
226                 }
227         }
228
229         /*
230          * Entry not found for a given individual. Return error.
231          */
232         return NULL;
233 }