Code

Fix bug #552289 - Ungrouping objects changes position of arrow lines. This was due...
[inkscape.git] / src / libcroco / cr-prop-list.c
1 /*
2  * This file is part of The Croco Library
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of version 2.1 of the GNU Lesser General Public
6  * License as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
16  * USA
17  *
18  * Author: Dodji Seketeli
19  * See COPYRIGHTS file for copyrights information.
20  */
22 #include <string.h>
23 #include "cr-prop-list.h"
25 #define PRIVATE(a_obj) (a_obj)->priv
27 struct _CRPropListPriv {
28         CRString *prop;
29         CRDeclaration *decl;
30         CRPropList *next;
31         CRPropList *prev;
32 };
34 static CRPropList *cr_prop_list_allocate (void);
36 /**
37  *Default allocator of CRPropList
38  *@return the newly allocated CRPropList or NULL
39  *if an error arises.
40  */
41 static CRPropList *
42 cr_prop_list_allocate (void)
43 {
44         CRPropList *result = (CRPropList *)g_try_malloc (sizeof (CRPropList));
45         if (!result) {
46                 cr_utils_trace_info ("could not allocate CRPropList");
47                 return NULL;
48         }
49         memset (result, 0, sizeof (CRPropList));
50         PRIVATE (result) = (CRPropListPriv *)g_try_malloc (sizeof (CRPropListPriv));
51         if (!result) {
52                 cr_utils_trace_info ("could not allocate CRPropListPriv");
53                 g_free (result);
54                 return NULL;
55         }
56         memset (PRIVATE (result), 0, sizeof (CRPropListPriv));
57         return result;
58 }
60 /****************
61  *public methods
62  ***************/
64 /**
65  *Appends a property list to the current one.
66  *@param a_this the current instance of #CRPropList
67  *@param a_to_append the property list to append
68  *@return the resulting prop list, or NULL if an error
69  *occured
70  */
71 CRPropList *
72 cr_prop_list_append (CRPropList * a_this, CRPropList * a_to_append)
73 {
74         CRPropList *cur = NULL;
76         g_return_val_if_fail (a_to_append, NULL);
78         if (!a_this)
79                 return a_to_append;
81         /*go fetch the last element of the list */
82         for (cur = a_this;
83              cur && PRIVATE (cur) && PRIVATE (cur)->next;
84              cur = PRIVATE (cur)->next) ;
85         g_return_val_if_fail (cur, NULL);
86         PRIVATE (cur)->next = a_to_append;
87         PRIVATE (a_to_append)->prev = cur;
88         return a_this;
89 }
91 /**
92  *Appends a pair of prop/declaration to
93  *the current prop list.
94  *@param a_this the current instance of #CRPropList
95  *@param a_prop the property to consider
96  *@param a_decl the declaration to consider
97  *@return the resulting property list, or NULL in case
98  *of an error.
99  */
100 CRPropList *
101 cr_prop_list_append2 (CRPropList * a_this,
102                       CRString * a_prop, 
103                       CRDeclaration * a_decl)
105         CRPropList *list = NULL,
106                 *result = NULL;
108         g_return_val_if_fail (a_prop && a_decl, NULL);
110         list = cr_prop_list_allocate ();
111         g_return_val_if_fail (list && PRIVATE (list), NULL);
113         PRIVATE (list)->prop = a_prop;
114         PRIVATE (list)->decl = a_decl;
116         result = cr_prop_list_append (a_this, list);
117         return result;
120 /**
121  *Prepends a list to the current list
122  *@param a_this the current instance of #CRPropList
123  *@param the new list to prepend.
124  */
125 CRPropList *
126 cr_prop_list_prepend (CRPropList * a_this, CRPropList * a_to_prepend)
128         CRPropList *cur = NULL;
130         g_return_val_if_fail (a_to_prepend, NULL);
132         if (!a_this)
133                 return a_to_prepend;
135         for (cur = a_to_prepend; cur && PRIVATE (cur)->next;
136              cur = PRIVATE (cur)->next) ;
137         g_return_val_if_fail (cur, NULL);
138         PRIVATE (cur)->next = a_this;
139         PRIVATE (a_this)->prev = cur;
140         return a_to_prepend;
143 /**
144  *Prepends a list to the current list
145  *@param a_this the current instance of #CRPropList
146  *@param the new list to prepend.
147  */
148 CRPropList *
149 cr_prop_list_prepend2 (CRPropList * a_this,
150                        CRString * a_prop, CRDeclaration * a_decl)
152         CRPropList *list = NULL,
153                 *result = NULL;
155         g_return_val_if_fail (a_this && PRIVATE (a_this)
156                               && a_prop && a_decl, NULL);
158         list = cr_prop_list_allocate ();
159         g_return_val_if_fail (list, NULL);
160         PRIVATE (list)->prop = a_prop;
161         PRIVATE (list)->decl = a_decl;
162         result = cr_prop_list_prepend (a_this, list);
163         return result;
166 /**
167  *Sets the property of a CRPropList
168  *@param a_this the current instance of #CRPropList
169  *@param a_prop the property to set
170  */
171 enum CRStatus
172 cr_prop_list_set_prop (CRPropList * a_this, CRString * a_prop)
174         g_return_val_if_fail (a_this && PRIVATE (a_this)
175                               && a_prop, CR_BAD_PARAM_ERROR);
177         PRIVATE (a_this)->prop = a_prop;
178         return CR_OK;
181 /**
182  *Getter of the property associated to the current instance
183  *of #CRPropList
184  *@param a_this the current instance of #CRPropList
185  *@param a_prop out parameter. The returned property
186  *@return CR_OK upon successful completion, an error code
187  *otherwise.
188  */
189 enum CRStatus
190 cr_prop_list_get_prop (CRPropList * a_this, CRString ** a_prop)
192         g_return_val_if_fail (a_this && PRIVATE (a_this)
193                               && a_prop, CR_BAD_PARAM_ERROR);
195         *a_prop = PRIVATE (a_this)->prop;
196         return CR_OK;
199 enum CRStatus
200 cr_prop_list_set_decl (CRPropList * a_this, CRDeclaration * a_decl)
202         g_return_val_if_fail (a_this && PRIVATE (a_this)
203                               && a_decl, CR_BAD_PARAM_ERROR);
205         PRIVATE (a_this)->decl = a_decl;
206         return CR_OK;
209 enum CRStatus
210 cr_prop_list_get_decl (CRPropList * a_this, CRDeclaration ** a_decl)
212         g_return_val_if_fail (a_this && PRIVATE (a_this)
213                               && a_decl, CR_BAD_PARAM_ERROR);
215         *a_decl = PRIVATE (a_this)->decl;
216         return CR_OK;
219 /**
220  *Lookup a given property/declaration pair
221  *@param a_this the current instance of #CRPropList
222  *@param a_prop the property to lookup
223  *@param a_prop_list out parameter. The property/declaration
224  *pair found (if and only if the function returned code if CR_OK)
225  *@return CR_OK if a prop/decl pair has been found,
226  *CR_VALUE_NOT_FOUND_ERROR if not, or an error code if something
227  *bad happens.
228  */
229 enum CRStatus
230 cr_prop_list_lookup_prop (CRPropList * a_this,
231                           CRString * a_prop, CRPropList ** a_pair)
233         CRPropList *cur = NULL;
235         g_return_val_if_fail (a_prop && a_pair, CR_BAD_PARAM_ERROR);
237         if (!a_this)
238                 return CR_VALUE_NOT_FOUND_ERROR;
240         g_return_val_if_fail (PRIVATE (a_this), CR_BAD_PARAM_ERROR);
242         for (cur = a_this; cur; cur = PRIVATE (cur)->next) {
243                 if (PRIVATE (cur)->prop
244                     && PRIVATE (cur)->prop->stryng
245                     && PRIVATE (cur)->prop->stryng->str
246                     && a_prop->stryng
247                     && a_prop->stryng->str
248                     && !strcmp (PRIVATE (cur)->prop->stryng->str, 
249                                 a_prop->stryng->str))
250                         break;
251         }
253         if (cur) {
254                 *a_pair = cur;
255                 return CR_OK;
256         }
258         return CR_VALUE_NOT_FOUND_ERROR;
261 /**
262  *Gets the next prop/decl pair in the list
263  *@param a_this the current instance of CRPropList
264  *@param the next prop/decl pair, or NULL if we
265  *reached the end of the list.
266  *@return the next prop/declaration pair of the list, 
267  *or NULL if we reached end of list (or if an error occurs)
268  */
269 CRPropList *
270 cr_prop_list_get_next (CRPropList * a_this)
272         g_return_val_if_fail (a_this && PRIVATE (a_this), NULL);
274         return PRIVATE (a_this)->next;
277 /**
278  *Gets the previous prop/decl pair in the list
279  *@param a_this the current instance of CRPropList
280  *@param the previous prop/decl pair, or NULL if we
281  *reached the end of the list.
282  *@return the previous prop/declaration pair of the list, 
283  *or NULL if we reached end of list (or if an error occurs)
284  */
285 CRPropList *
286 cr_prop_list_get_prev (CRPropList * a_this)
288         g_return_val_if_fail (a_this && PRIVATE (a_this), NULL);
290         return PRIVATE (a_this)->prev;
293 /**
294  *Unlinks a prop/decl pair from the list
295  *@param a_this the current list of prop/decl pairs
296  *@param a_pair the prop/decl pair to unlink.
297  *@return the new list or NULL in case of an error.
298  */
299 CRPropList *
300 cr_prop_list_unlink (CRPropList * a_this, CRPropList * a_pair)
302         CRPropList *prev = NULL,
303                 *next = NULL;
305         g_return_val_if_fail (a_this && PRIVATE (a_this) && a_pair, NULL);
307         /*some sanity checks */
308         if (PRIVATE (a_pair)->next) {
309                 next = PRIVATE (a_pair)->next;
310                 g_return_val_if_fail (PRIVATE (next), NULL);
311                 g_return_val_if_fail (PRIVATE (next)->prev == a_pair, NULL);
312         }
313         if (PRIVATE (a_pair)->prev) {
314                 prev = PRIVATE (a_pair)->prev;
315                 g_return_val_if_fail (PRIVATE (prev), NULL);
316                 g_return_val_if_fail (PRIVATE (prev)->next == a_pair, NULL);
317         }
318         if (prev) {
319                 PRIVATE (prev)->next = next;
320         }
321         if (next) {
322                 PRIVATE (next)->prev = prev;
323         }
324         PRIVATE (a_pair)->prev = PRIVATE (a_pair)->next = NULL;
325         if (a_this == a_pair) {
326                 if (next)
327                         return next;
328                 return NULL;
329         }
330         return a_this;
333 void
334 cr_prop_list_destroy (CRPropList * a_this)
336         CRPropList *tail = NULL,
337                 *cur = NULL;
339         g_return_if_fail (a_this && PRIVATE (a_this));
341         for (tail = a_this;
342              tail && PRIVATE (tail) && PRIVATE (tail)->next;
343              tail = cr_prop_list_get_next (tail)) ;
344         g_return_if_fail (tail);
346         cur = tail;
348         while (cur) {
349                 tail = PRIVATE (cur)->prev;
350                 if (tail && PRIVATE (tail))
351                         PRIVATE (tail)->next = NULL;
352                 PRIVATE (cur)->prev = NULL;
353                 g_free (PRIVATE (cur));
354                 PRIVATE (cur) = NULL;
355                 g_free (cur);
356                 cur = tail;
357         }