GnuCash c935c2f+
Loading...
Searching...
No Matches
basiccell.c
1/********************************************************************\
2 * basiccell.c -- base class for editable cell in a table *
3 * *
4 * This program is free software; you can redistribute it and/or *
5 * modify it under the terms of the GNU General Public License as *
6 * published by the Free Software Foundation; either version 2 of *
7 * the License, or (at your option) any later version. *
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*
15 * along with this program; if not, contact: *
16 * *
17 * Free Software Foundation Voice: +1-617-542-5942 *
18 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
19 * Boston, MA 02110-1301, USA gnu@gnu.org *
20 * *
21\********************************************************************/
22
23/*
24 * FILE:
25 * basiccell.c
26 *
27 * FUNCTION:
28 * Implements the base class for the cell handler object.
29 * See the header file for additional documentation.
30 *
31 * HISTORY:
32 * Copyright (c) 1998 Linas Vepstas
33 * Copyright (c) 2000 Dave Peticolas <dave@krondo.com>
34 */
35
36#include <config.h>
37
38#include <stdlib.h>
39#include <locale.h>
40#include <string.h>
41
42#include "gnc-locale-utils.h"
43
44#include "basiccell.h"
45#include "gnc-engine.h"
46
47/* Debugging module */
48static QofLogModule log_module = GNC_MOD_REGISTER;
49
50gboolean
51gnc_cell_name_equal (const char * cell_name_1,
52 const char * cell_name_2)
53{
54 return (g_strcmp0 (cell_name_1, cell_name_2) == 0);
55}
56
57static void
58gnc_basic_cell_gui_realize (BasicCell* bcell, gpointer data)
59{
60 bcell->gui_private = data;
61 bcell->gui_realize = NULL;
62}
63
64static void
65gnc_basic_cell_gui_destroy (BasicCell* bcell)
66{
67 if (bcell->gui_realize == NULL)
68 {
69 bcell->gui_realize = gnc_basic_cell_gui_realize;
70 }
71}
72
73BasicCell *
74gnc_basic_cell_new (void)
75{
76 BasicCell * cell;
77
78 cell = g_new0 (BasicCell, 1);
79
80 gnc_basic_cell_init (cell);
81
82 return cell;
83}
84
85static void
86gnc_basic_cell_clear (BasicCell *cell)
87{
88 g_free (cell->cell_name);
89 cell->cell_name = NULL;
90 g_free (cell->cell_type_name);
91 cell->cell_type_name = NULL;
92 cell->changed = FALSE;
93 cell->conditionally_changed = FALSE;
94
95 cell->value = NULL;
96 cell->value_chars = 0;
97
98 cell->set_value = NULL;
99 cell->enter_cell = NULL;
100 cell->modify_verify = NULL;
101 cell->direct_update = NULL;
102 cell->leave_cell = NULL;
103 cell->gui_realize = NULL;
104 cell->gui_move = NULL;
105 cell->gui_destroy = NULL;
106
107 cell->is_popup = FALSE;
108
109 cell->gui_private = NULL;
110
111 g_free (cell->sample_text);
112 cell->sample_text = NULL;
113}
114
115void
116gnc_basic_cell_init (BasicCell *cell)
117{
118 gnc_basic_cell_clear (cell);
119
120 cell->gui_realize = gnc_basic_cell_gui_realize;
121 cell->gui_destroy = gnc_basic_cell_gui_destroy;
122
123 cell->value = g_strdup ("");
124}
125
126void
127gnc_basic_cell_destroy (BasicCell *cell)
128{
129 ENTER(" ");
130 if (cell->destroy)
131 cell->destroy (cell);
132
133 /* give any gui elements a chance to clean up */
134 if (cell->gui_destroy)
135 (*(cell->gui_destroy)) (cell);
136
137 /* free up data strings */
138 g_free (cell->value);
139 cell->value = NULL;
140
141 /* help prevent access to freed memory */
142 gnc_basic_cell_clear (cell);
143
144 /* free the object itself */
145 g_free (cell);
146 LEAVE(" ");
147}
148
149void
150gnc_basic_cell_set_name (BasicCell *cell, const char *name)
151{
152 if (!cell) return;
153 if (cell->cell_name == name) return;
154
155 g_free (cell->cell_name);
156 cell->cell_name = g_strdup (name);
157}
158
159gboolean
160gnc_basic_cell_has_name (BasicCell *cell, const char *name)
161{
162 if (!cell) return FALSE;
163 if (!name) return FALSE;
164 if (!cell->cell_name) return FALSE;
165
166 return (strcmp (name, cell->cell_name) == 0);
167}
168
169
170void
171gnc_basic_cell_set_type_name (BasicCell *cell, const gchar *type_name)
172{
173 if (!cell) return;
174 if (cell->cell_type_name == type_name) return;
175
176 g_free (cell->cell_type_name);
177 cell->cell_type_name = g_strdup(type_name);
178}
179
180gboolean
181gnc_basic_cell_has_type_name (BasicCell *cell, const gchar *type_name)
182{
183 if (!cell) return FALSE;
184 if (!type_name) return FALSE;
185 if (!cell->cell_type_name) return FALSE;
186
187 return (g_strcmp0 (type_name, cell->cell_type_name));
188}
189
190void
191gnc_basic_cell_set_sample_text (BasicCell *cell,
192 const char *sample_text)
193{
194 if (!cell) return;
195 if (cell->sample_text == sample_text) return;
196
197 g_free (cell->sample_text);
198 cell->sample_text = g_strdup (sample_text);
199}
200
201void
202gnc_basic_cell_set_alignment (BasicCell *cell,
203 CellAlignment alignment)
204{
205 if (!cell) return;
206 cell->alignment = alignment;
207}
208
209void
210gnc_basic_cell_set_expandable (BasicCell *cell, gboolean expandable)
211{
212 if (!cell) return;
213 cell->expandable = expandable;
214}
215
216void
217gnc_basic_cell_set_span (BasicCell *cell, gboolean span)
218{
219 if (!cell) return;
220 cell->span = span;
221}
222
223const char *
224gnc_basic_cell_get_value (BasicCell *cell)
225{
226 g_return_val_if_fail (cell != NULL, NULL);
227
228 return cell->value;
229}
230
231void
232gnc_basic_cell_set_value (BasicCell *cell, const char *val)
233{
234 CellSetValueFunc cb;
235
236 cb = cell->set_value;
237 if (cb)
238 {
239 /* avoid recursion by disabling the
240 * callback while it's being called. */
241 cell->set_value = NULL;
242 cb (cell, val);
243 cell->set_value = cb;
244 }
245 else
246 gnc_basic_cell_set_value_internal (cell, val);
247}
248
249gboolean
250gnc_basic_cell_get_changed (BasicCell *cell)
251{
252 if (!cell) return FALSE;
253
254 return cell->changed;
255}
256
257gboolean
258gnc_basic_cell_get_conditionally_changed (BasicCell *cell)
259{
260 if (!cell) return FALSE;
261
262 return cell->conditionally_changed;
263}
264
265void
266gnc_basic_cell_set_changed (BasicCell *cell, gboolean changed)
267{
268 if (!cell) return;
269
270 cell->changed = changed;
271}
272
273void
274gnc_basic_cell_set_conditionally_changed (BasicCell *cell, gboolean changed)
275{
276 if (!cell) return;
277
278 cell->conditionally_changed = changed;
279}
280
281void
282gnc_basic_cell_set_value_internal (BasicCell *cell, const char *value)
283{
284 if (value == NULL)
285 value = "";
286
287 /* If the caller tries to set the value with our own value then do
288 * nothing because we have no work to do (or, at least, all the work
289 * will result in the status-quo, so why do anything?) See bug
290 * #103174 and the description in the changelog on 2003-09-04.
291 */
292 if (cell->value == value)
293 return;
294
295 g_free (cell->value);
296 cell->value = g_strdup (value);
297 cell->value_chars = g_utf8_strlen(value, -1);
298}
299
300char *
301gnc_basic_cell_validate (BasicCell *cell, GNCPrintAmountInfo print_info,
302 const char *change, const char *newval,
303 const char *toks, gint *cursor_position)
304{
305 struct lconv *lc = gnc_localeconv ();
306 gunichar decimal_point;
307 gunichar thousands_sep;
308 const char *symbol = NULL;
309 char *tokens;
310
311 if (print_info.monetary)
312 {
313 const gnc_commodity *comm = print_info.commodity;
314
315 decimal_point = g_utf8_get_char (lc->mon_decimal_point);
316 thousands_sep = g_utf8_get_char (lc->mon_thousands_sep);
317
318 if (comm)
319 symbol = gnc_commodity_get_nice_symbol (comm);
320 else
322
323 tokens = g_strconcat (toks, symbol, NULL);
324 }
325 else
326 {
327 decimal_point = g_utf8_get_char (lc->decimal_point);
328 thousands_sep = g_utf8_get_char (lc->thousands_sep);
329
330 tokens = g_strdup (toks);
331 }
332
333 for (const char *c = change; c && *c; c = g_utf8_next_char (c))
334 {
335 gunichar uc = g_utf8_get_char (c);
336 if (!g_unichar_isdigit (uc) &&
337 !g_unichar_isspace (uc) &&
338 !g_unichar_isalpha (uc) &&
339 (decimal_point != uc) &&
340 (thousands_sep != uc) &&
341 (g_utf8_strchr (tokens, -1, uc) == NULL))
342 {
343 g_free (tokens);
344 return NULL;
345 }
346 }
347 g_free (tokens);
348
349 gnc_filter_text_set_cursor_position (newval, symbol, cursor_position);
350
351 return gnc_filter_text_for_currency_symbol (newval, symbol);
352}
All type declarations for the whole Gnucash engine.
const char * gnc_commodity_get_nice_symbol(const gnc_commodity *cm)
Retrieve a symbol for the specified commodity, suitable for display to the user.
char * gnc_filter_text_for_currency_symbol(const char *incoming_text, const char *symbol)
Returns the incoming text removed of a currency symbol.
gnc_commodity * gnc_default_currency(void)
Return the default currency set by the user.
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition qoflog.h:282
#define ENTER(format, args...)
Print a function entry debugging message.
Definition qoflog.h:272