1 /* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
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 */
25 /**
26 *@file
27 *The definition
28 *of the #CRNum class.
29 */
31 #include "cr-num.h"
32 #include "string.h"
34 /**
35 *The default constructor of
36 *#CRNum.
37 *@return the newly built instance of
38 *#CRNum.
39 */
40 CRNum *
41 cr_num_new (void)
42 {
43 CRNum *result = NULL;
45 result = g_try_malloc (sizeof (CRNum));
47 if (result == NULL) {
48 cr_utils_trace_info ("Out of memory");
49 return NULL;
50 }
52 memset (result, 0, sizeof (CRNum));
54 return result;
55 }
57 /**
58 *A constructor of #CRNum.
59 *@param a_is_natural indicates whether the intance of #CRNum is
60 *a natural number or not.
61 *@param a_integer_part the integer part of the instance
62 *of #CRNum
63 *@param a_decimal_part in case the instance of #CRNum
64 *natural number (but a decimal one) this parameter
65 *is the decimal part of the instance of #CRNum.
66 *@return the newly built instance of #CRNum or
67 *NULL if an error arises.
68 */
69 CRNum *
70 cr_num_new_with_val (gdouble a_val, enum CRNumType a_type)
71 {
72 CRNum *result = NULL;
74 result = cr_num_new ();
76 g_return_val_if_fail (result, NULL);
78 result->val = a_val;
79 result->type = a_type;
81 return result;
82 }
84 /**
85 *Returns the string representation of the
86 *current instance of #CRNum.
87 *@param a_this the current instance of #CRNum.
88 *@return the newly built string representation
89 *of the current instance of #CRNum. The returned
90 *string is NULL terminated. The caller *must*
91 *free the returned string.
92 */
93 guchar *
94 cr_num_to_string (CRNum * a_this)
95 {
96 gdouble test_val = 0.0;
98 guchar *tmp_char1 = NULL,
99 *tmp_char2 = NULL,
100 *result = NULL;
102 g_return_val_if_fail (a_this, NULL);
104 test_val = a_this->val - (glong) a_this->val;
106 if (!test_val) {
107 tmp_char1 = g_strdup_printf ("%ld", (glong) a_this->val);
108 } else {
109 /* We can't use g_ascii_dtostr, because that sometimes uses
110 e notation (which wouldn't be a valid number in CSS). */
111 size_t const buflen = 35; /* fairly arbitrary. */
112 tmp_char1 = g_malloc (buflen);
113 g_ascii_formatd (tmp_char1, buflen, "%.17f", a_this->val);
114 }
116 g_return_val_if_fail (tmp_char1, NULL);
118 switch (a_this->type) {
119 case NUM_LENGTH_EM:
120 tmp_char2 = (guchar *) "em";
121 break;
123 case NUM_LENGTH_EX:
124 tmp_char2 = (guchar *) "ex";
125 break;
127 case NUM_LENGTH_PX:
128 tmp_char2 = (guchar *) "px";
129 break;
131 case NUM_LENGTH_IN:
132 tmp_char2 = (guchar *) "in";
133 break;
135 case NUM_LENGTH_CM:
136 tmp_char2 = (guchar *) "cm";
137 break;
139 case NUM_LENGTH_MM:
140 tmp_char2 = (guchar *) "mm";
141 break;
143 case NUM_LENGTH_PT:
144 tmp_char2 = (guchar *) "pt";
145 break;
147 case NUM_LENGTH_PC:
148 tmp_char2 = (guchar *) "pc";
149 break;
151 case NUM_ANGLE_DEG:
152 tmp_char2 = (guchar *) "deg";
153 break;
155 case NUM_ANGLE_RAD:
156 tmp_char2 = (guchar *) "rad";
157 break;
159 case NUM_ANGLE_GRAD:
160 tmp_char2 = (guchar *) "grad";
161 break;
163 case NUM_TIME_MS:
164 tmp_char2 = (guchar *) "ms";
165 break;
167 case NUM_TIME_S:
168 tmp_char2 = (guchar *) "s";
169 break;
171 case NUM_FREQ_HZ:
172 tmp_char2 = (guchar *) "Hz";
173 break;
175 case NUM_FREQ_KHZ:
176 tmp_char2 = (guchar *) "KHz";
177 break;
179 case NUM_PERCENTAGE:
180 tmp_char2 = (guchar *) "%";
181 break;
182 case NUM_INHERIT:
183 tmp_char2 = (guchar *) "inherit";
184 break ;
185 case NUM_AUTO:
186 tmp_char2 = (guchar *) "auto";
187 break ;
188 case NUM_GENERIC:
189 tmp_char2 = NULL ;
190 break ;
191 default:
192 tmp_char2 = (guchar *) "unknown";
193 break;
194 }
196 if (tmp_char2) {
197 result = g_strconcat (tmp_char1, tmp_char2, NULL);
198 g_free (tmp_char1);
199 } else {
200 result = tmp_char1;
201 }
203 return result;
204 }
206 /**
207 *Copies an instance of #CRNum.
208 *@param a_src the instance of #CRNum to copy.
209 *Must be non NULL.
210 *@param a_dst the destination of the copy.
211 *Must be non NULL
212 *@return CR_OK upon successful completion, an
213 *error code otherwise.
214 */
215 enum CRStatus
216 cr_num_copy (CRNum * a_dest, CRNum * a_src)
217 {
218 g_return_val_if_fail (a_dest && a_src, CR_BAD_PARAM_ERROR);
220 memcpy (a_dest, a_src, sizeof (CRNum));
222 return CR_OK;
223 }
225 /**
226 *Duplicates an instance of #CRNum
227 *@param a_this the instance of #CRNum to duplicate.
228 *@return the newly created (duplicated) instance of #CRNum.
229 *Must be freed by cr_num_destroy().
230 */
231 CRNum *
232 cr_num_dup (CRNum * a_this)
233 {
234 CRNum *result = NULL;
235 enum CRStatus status = CR_OK;
237 g_return_val_if_fail (a_this, NULL);
239 result = cr_num_new ();
240 g_return_val_if_fail (result, NULL);
242 status = cr_num_copy (result, a_this);
243 g_return_val_if_fail (status == CR_OK, NULL);
245 return result;
246 }
248 /**
249 *Sets an instance of #CRNum.
250 *@param a_this the current instance of #CRNum to be set.
251 *@param a_val the new numerical value to be hold by the current
252 *instance of #CRNum
253 *@param a_type the new type of #CRNum.
254 */
255 enum CRStatus
256 cr_num_set (CRNum * a_this, gdouble a_val, enum CRNumType a_type)
257 {
258 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
260 a_this->val = a_val;
261 a_this->type = a_type;
263 return CR_OK;
264 }
266 /**
267 *Tests if the current instance of #CRNum is a fixed
268 *length value or not. Typically a fixed length value
269 *is anything from NUM_LENGTH_EM to NUM_LENGTH_PC.
270 *See the definition of #CRNumType to see what we mean.
271 *@return TRUE if the instance of #CRNum is a fixed length number,
272 *FALSE otherwise.
273 */
274 gboolean
275 cr_num_is_fixed_length (CRNum * a_this)
276 {
277 gboolean result = FALSE;
279 g_return_val_if_fail (a_this, FALSE);
281 if (a_this->type >= NUM_LENGTH_EM
282 && a_this->type <= NUM_LENGTH_PC) {
283 result = TRUE ;
284 }
285 return result ;
286 }
288 /**
289 *The destructor of #CRNum.
290 *@param a_this the this pointer of
291 *the current instance of #CRNum.
292 */
293 void
294 cr_num_destroy (CRNum * a_this)
295 {
296 g_return_if_fail (a_this);
298 g_free (a_this);
299 }