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