1 /* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
2 
3 /*
4  * This file is part of The Croco Library
5  *
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of version 2.1 of the GNU Lesser General Public
9  * License as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19  * USA
20  *
21  * Author: Dodji Seketeli
22  * See COPYRIGHTS file for copyrights information.
23  */
24 
25 /**
26  *@CRNum:
27  *
28  *The definition
29  *of the #CRNum class.
30  */
31 
32 #include "cr-num.h"
33 #include "string.h"
34 
35 /**
36  * cr_num_new:
37  *
38  *#CRNum.
39  *
40  *Returns the newly built instance of
41  *#CRNum.
42  */
43 CRNum *
cr_num_new(void)44 cr_num_new (void)
45 {
46         CRNum *result = NULL;
47 
48         result = g_try_malloc (sizeof (CRNum));
49 
50         if (result == NULL) {
51                 cr_utils_trace_info ("Out of memory");
52                 return NULL;
53         }
54 
55         memset (result, 0, sizeof (CRNum));
56 
57         return result;
58 }
59 
60 /**
61  * cr_num_new_with_val:
62  * @a_val: the numerical value of the number.
63  * @a_type: the type of number.
64  *
65  * A constructor of #CRNum.
66  *
67  * Returns the newly built instance of #CRNum or
68  * NULL if an error arises.
69  */
70 CRNum *
cr_num_new_with_val(gdouble a_val,enum CRNumType a_type)71 cr_num_new_with_val (gdouble a_val, enum CRNumType a_type)
72 {
73         CRNum *result = NULL;
74 
75         result = cr_num_new ();
76 
77         g_return_val_if_fail (result, NULL);
78 
79         result->val = a_val;
80         result->type = a_type;
81 
82         return result;
83 }
84 
85 /**
86  * cr_num_to_string:
87  *@a_this: the current instance of #CRNum.
88  *
89  *Returns the newly built string representation
90  *of the current instance of #CRNum. The returned
91  *string is NULL terminated. The caller *must*
92  *free the returned string.
93  */
94 guchar *
cr_num_to_string(CRNum const * a_this)95 cr_num_to_string (CRNum const * a_this)
96 {
97         gdouble test_val = 0.0;
98 
99         guchar *tmp_char1 = NULL,
100                 *tmp_char2 = NULL,
101                 *result = NULL;
102 
103         g_return_val_if_fail (a_this, NULL);
104 
105         test_val = a_this->val - (glong) a_this->val;
106 
107         if (!test_val) {
108                 tmp_char1 = (guchar *) g_strdup_printf ("%ld", (glong) a_this->val);
109         } else {
110                 tmp_char1 = (guchar *) g_new0 (char, G_ASCII_DTOSTR_BUF_SIZE + 1);
111                 if (tmp_char1 != NULL)
112                         g_ascii_dtostr ((gchar *) tmp_char1, G_ASCII_DTOSTR_BUF_SIZE, a_this->val);
113         }
114 
115         g_return_val_if_fail (tmp_char1, NULL);
116 
117         switch (a_this->type) {
118         case NUM_LENGTH_EM:
119                 tmp_char2 = (guchar *) "em";
120                 break;
121 
122         case NUM_LENGTH_EX:
123                 tmp_char2 = (guchar *) "ex";
124                 break;
125 
126         case NUM_LENGTH_PX:
127                 tmp_char2 = (guchar *) "px";
128                 break;
129 
130         case NUM_LENGTH_IN:
131                 tmp_char2 = (guchar *) "in";
132                 break;
133 
134         case NUM_LENGTH_CM:
135                 tmp_char2 = (guchar *) "cm";
136                 break;
137 
138         case NUM_LENGTH_MM:
139                 tmp_char2 = (guchar *) "mm";
140                 break;
141 
142         case NUM_LENGTH_PT:
143                 tmp_char2 = (guchar *) "pt";
144                 break;
145 
146         case NUM_LENGTH_PC:
147                 tmp_char2 = (guchar *) "pc";
148                 break;
149 
150         case NUM_ANGLE_DEG:
151                 tmp_char2 = (guchar *) "deg";
152                 break;
153 
154         case NUM_ANGLE_RAD:
155                 tmp_char2 = (guchar *) "rad";
156                 break;
157 
158         case NUM_ANGLE_GRAD:
159                 tmp_char2 = (guchar *) "grad";
160                 break;
161 
162         case NUM_TIME_MS:
163                 tmp_char2 = (guchar *) "ms";
164                 break;
165 
166         case NUM_TIME_S:
167                 tmp_char2 = (guchar *) "s";
168                 break;
169 
170         case NUM_FREQ_HZ:
171                 tmp_char2 = (guchar *) "Hz";
172                 break;
173 
174         case NUM_FREQ_KHZ:
175                 tmp_char2 = (guchar *) "KHz";
176                 break;
177 
178         case NUM_PERCENTAGE:
179                 tmp_char2 = (guchar *) "%";
180                 break;
181         case NUM_INHERIT:
182                 tmp_char2 = (guchar *) "inherit";
183                 break ;
184         case NUM_AUTO:
185                 tmp_char2 = (guchar *) "auto";
186                 break ;
187         case NUM_GENERIC:
188                 tmp_char2 = NULL ;
189                 break ;
190         default:
191                 tmp_char2 = (guchar *) "unknown";
192                 break;
193         }
194 
195         if (tmp_char2) {
196                 result = (guchar *)  g_strconcat ((gchar *) tmp_char1, tmp_char2, NULL);
197                 g_free (tmp_char1);
198         } else {
199                 result = tmp_char1;
200         }
201 
202         return result;
203 }
204 
205 /**
206  * cr_num_copy:
207  *@a_src: the instance of #CRNum to copy.
208  *Must be non NULL.
209  *@a_dest: the destination of the copy.
210  *Must be non NULL
211  *
212  *Copies an instance of #CRNum.
213  *
214  *Returns CR_OK upon successful completion, an
215  *error code otherwise.
216  */
217 enum CRStatus
cr_num_copy(CRNum * a_dest,CRNum const * a_src)218 cr_num_copy (CRNum * a_dest, CRNum const * a_src)
219 {
220         g_return_val_if_fail (a_dest && a_src, CR_BAD_PARAM_ERROR);
221 
222         memcpy (a_dest, a_src, sizeof (CRNum));
223 
224         return CR_OK;
225 }
226 
227 /**
228  * cr_num_dup:
229  *@a_this: the instance of #CRNum to duplicate.
230  *
231  *Duplicates an instance of #CRNum
232  *
233  *Returns the newly created (duplicated) instance of #CRNum.
234  *Must be freed by cr_num_destroy().
235  */
236 CRNum *
cr_num_dup(CRNum const * a_this)237 cr_num_dup (CRNum const * a_this)
238 {
239         CRNum *result = NULL;
240         enum CRStatus status = CR_OK;
241 
242         g_return_val_if_fail (a_this, NULL);
243 
244         result = cr_num_new ();
245         g_return_val_if_fail (result, NULL);
246 
247         status = cr_num_copy (result, a_this);
248         g_return_val_if_fail (status == CR_OK, NULL);
249 
250         return result;
251 }
252 
253 /**
254  * cr_num_set:
255  *Sets an instance of #CRNum.
256  *@a_this: the current instance of #CRNum to be set.
257  *@a_val: the new numerical value to be hold by the current
258  *instance of #CRNum
259  *@a_type: the new type of #CRNum.
260  *
261  * Returns CR_OK upon succesful completion, an error code otherwise.
262  */
263 enum CRStatus
cr_num_set(CRNum * a_this,gdouble a_val,enum CRNumType a_type)264 cr_num_set (CRNum * a_this, gdouble a_val, enum CRNumType a_type)
265 {
266         g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
267 
268         a_this->val = a_val;
269         a_this->type = a_type;
270 
271         return CR_OK;
272 }
273 
274 /**
275  * cr_num_is_fixed_length:
276  * @a_this: the current instance of #CRNum .
277  *
278  *Tests if the current instance of #CRNum is a fixed
279  *length value or not. Typically a fixed length value
280  *is anything from NUM_LENGTH_EM to NUM_LENGTH_PC.
281  *See the definition of #CRNumType to see what we mean.
282  *
283  *Returns TRUE if the instance of #CRNum is a fixed length number,
284  *FALSE otherwise.
285  */
286 gboolean
cr_num_is_fixed_length(CRNum const * a_this)287 cr_num_is_fixed_length (CRNum const * a_this)
288 {
289         gboolean result = FALSE;
290 
291         g_return_val_if_fail (a_this, FALSE);
292 
293         if (a_this->type >= NUM_LENGTH_EM
294             && a_this->type <= NUM_LENGTH_PC) {
295                 result = TRUE ;
296         }
297         return result ;
298 }
299 
300 /**
301  * cr_num_destroy:
302  *@a_this: the this pointer of
303  *the current instance of #CRNum.
304  *
305  *The destructor of #CRNum.
306  */
307 void
cr_num_destroy(CRNum * a_this)308 cr_num_destroy (CRNum * a_this)
309 {
310         g_return_if_fail (a_this);
311 
312         g_free (a_this);
313 }
314