GnuCash  5.6-150-g038405b370+
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 */
48 static QofLogModule log_module = GNC_MOD_REGISTER;
49 
50 gboolean
51 gnc_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 
57 BasicCell *
58 gnc_basic_cell_new (void)
59 {
60  BasicCell * cell;
61 
62  cell = g_new0 (BasicCell, 1);
63 
64  gnc_basic_cell_init (cell);
65 
66  return cell;
67 }
68 
69 static void
70 gnc_basic_cell_clear (BasicCell *cell)
71 {
72  g_free (cell->cell_name);
73  cell->cell_name = NULL;
74  g_free (cell->cell_type_name);
75  cell->cell_type_name = NULL;
76  cell->changed = FALSE;
77  cell->conditionally_changed = FALSE;
78 
79  cell->value = NULL;
80  cell->value_chars = 0;
81 
82  cell->set_value = NULL;
83  cell->enter_cell = NULL;
84  cell->modify_verify = NULL;
85  cell->direct_update = NULL;
86  cell->leave_cell = NULL;
87  cell->gui_realize = NULL;
88  cell->gui_move = NULL;
89  cell->gui_destroy = NULL;
90 
91  cell->is_popup = FALSE;
92 
93  cell->gui_private = NULL;
94 
95  g_free (cell->sample_text);
96  cell->sample_text = NULL;
97 }
98 
99 void
100 gnc_basic_cell_init (BasicCell *cell)
101 {
102  gnc_basic_cell_clear (cell);
103 
104  cell->value = g_strdup ("");
105 }
106 
107 void
108 gnc_basic_cell_destroy (BasicCell *cell)
109 {
110  ENTER(" ");
111  if (cell->destroy)
112  cell->destroy (cell);
113 
114  /* give any gui elements a chance to clean up */
115  if (cell->gui_destroy)
116  (*(cell->gui_destroy)) (cell);
117 
118  /* free up data strings */
119  g_free (cell->value);
120  cell->value = NULL;
121 
122  /* help prevent access to freed memory */
123  gnc_basic_cell_clear (cell);
124 
125  /* free the object itself */
126  g_free (cell);
127  LEAVE(" ");
128 }
129 
130 void
131 gnc_basic_cell_set_name (BasicCell *cell, const char *name)
132 {
133  if (!cell) return;
134  if (cell->cell_name == name) return;
135 
136  g_free (cell->cell_name);
137  cell->cell_name = g_strdup (name);
138 }
139 
140 gboolean
141 gnc_basic_cell_has_name (BasicCell *cell, const char *name)
142 {
143  if (!cell) return FALSE;
144  if (!name) return FALSE;
145  if (!cell->cell_name) return FALSE;
146 
147  return (strcmp (name, cell->cell_name) == 0);
148 }
149 
150 
151 void
152 gnc_basic_cell_set_type_name (BasicCell *cell, const gchar *type_name)
153 {
154  if (!cell) return;
155  if (cell->cell_type_name == type_name) return;
156 
157  g_free (cell->cell_type_name);
158  cell->cell_type_name = g_strdup(type_name);
159 }
160 
161 gboolean
162 gnc_basic_cell_has_type_name (BasicCell *cell, const gchar *type_name)
163 {
164  if (!cell) return FALSE;
165  if (!type_name) return FALSE;
166  if (!cell->cell_type_name) return FALSE;
167 
168  return (g_strcmp0 (type_name, cell->cell_type_name));
169 }
170 
171 void
172 gnc_basic_cell_set_sample_text (BasicCell *cell,
173  const char *sample_text)
174 {
175  if (!cell) return;
176  if (cell->sample_text == sample_text) return;
177 
178  g_free (cell->sample_text);
179  cell->sample_text = g_strdup (sample_text);
180 }
181 
182 void
183 gnc_basic_cell_set_alignment (BasicCell *cell,
184  CellAlignment alignment)
185 {
186  if (!cell) return;
187  cell->alignment = alignment;
188 }
189 
190 void
191 gnc_basic_cell_set_expandable (BasicCell *cell, gboolean expandable)
192 {
193  if (!cell) return;
194  cell->expandable = expandable;
195 }
196 
197 void
198 gnc_basic_cell_set_span (BasicCell *cell, gboolean span)
199 {
200  if (!cell) return;
201  cell->span = span;
202 }
203 
204 const char *
205 gnc_basic_cell_get_value (BasicCell *cell)
206 {
207  g_return_val_if_fail (cell != NULL, NULL);
208 
209  return cell->value;
210 }
211 
212 void
213 gnc_basic_cell_set_value (BasicCell *cell, const char *val)
214 {
215  CellSetValueFunc cb;
216 
217  cb = cell->set_value;
218  if (cb)
219  {
220  /* avoid recursion by disabling the
221  * callback while it's being called. */
222  cell->set_value = NULL;
223  cb (cell, val);
224  cell->set_value = cb;
225  }
226  else
227  gnc_basic_cell_set_value_internal (cell, val);
228 }
229 
230 gboolean
231 gnc_basic_cell_get_changed (BasicCell *cell)
232 {
233  if (!cell) return FALSE;
234 
235  return cell->changed;
236 }
237 
238 gboolean
239 gnc_basic_cell_get_conditionally_changed (BasicCell *cell)
240 {
241  if (!cell) return FALSE;
242 
243  return cell->conditionally_changed;
244 }
245 
246 void
247 gnc_basic_cell_set_changed (BasicCell *cell, gboolean changed)
248 {
249  if (!cell) return;
250 
251  cell->changed = changed;
252 }
253 
254 void
255 gnc_basic_cell_set_conditionally_changed (BasicCell *cell, gboolean changed)
256 {
257  if (!cell) return;
258 
259  cell->conditionally_changed = changed;
260 }
261 
262 void
263 gnc_basic_cell_set_value_internal (BasicCell *cell, const char *value)
264 {
265  if (value == NULL)
266  value = "";
267 
268  /* If the caller tries to set the value with our own value then do
269  * nothing because we have no work to do (or, at least, all the work
270  * will result in the status-quo, so why do anything?) See bug
271  * #103174 and the description in the changelog on 2003-09-04.
272  */
273  if (cell->value == value)
274  return;
275 
276  g_free (cell->value);
277  cell->value = g_strdup (value);
278  cell->value_chars = g_utf8_strlen(value, -1);
279 }
280 
281 char *
282 gnc_basic_cell_validate (BasicCell *cell, GNCPrintAmountInfo print_info,
283  const char *change, const char *newval,
284  const char *toks, gint *cursor_position)
285 {
286  struct lconv *lc = gnc_localeconv ();
287  gunichar decimal_point;
288  gunichar thousands_sep;
289  const char *symbol = NULL;
290  char *tokens;
291 
292  if (print_info.monetary)
293  {
294  const gnc_commodity *comm = print_info.commodity;
295 
296  decimal_point = g_utf8_get_char (lc->mon_decimal_point);
297  thousands_sep = g_utf8_get_char (lc->mon_thousands_sep);
298 
299  if (comm)
300  symbol = gnc_commodity_get_nice_symbol (comm);
301  else
303 
304  tokens = g_strconcat (toks, symbol, NULL);
305  }
306  else
307  {
308  decimal_point = g_utf8_get_char (lc->decimal_point);
309  thousands_sep = g_utf8_get_char (lc->thousands_sep);
310 
311  tokens = g_strdup (toks);
312  }
313 
314  for (const char *c = change; c && *c; c = g_utf8_next_char (c))
315  {
316  gunichar uc = g_utf8_get_char (c);
317  if (!g_unichar_isdigit (uc) &&
318  !g_unichar_isspace (uc) &&
319  !g_unichar_isalpha (uc) &&
320  (decimal_point != uc) &&
321  (thousands_sep != uc) &&
322  (g_utf8_strchr (tokens, -1, uc) == NULL))
323  {
324  g_free (tokens);
325  return NULL;
326  }
327  }
328  g_free (tokens);
329 
330  gnc_filter_text_set_cursor_position (newval, symbol, cursor_position);
331 
332  return gnc_filter_text_for_currency_symbol (newval, symbol);
333 }
#define ENTER(format, args...)
Print a function entry debugging message.
Definition: qoflog.h:272
gnc_commodity * gnc_default_currency(void)
Return the default currency set by the user.
void gnc_filter_text_set_cursor_position(const char *incoming_text, const char *symbol, int *zcursor_position)
Updates cursor_position after removal of currency symbols.
const char * gnc_commodity_get_nice_symbol(const gnc_commodity *cm)
Retrieve a symbol for the specified commodity, suitable for display to the user.
All type declarations for the whole Gnucash engine.
char * gnc_filter_text_for_currency_symbol(const char *incoming_text, const char *symbol)
Returns the incoming text removed of a currency symbol.
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition: qoflog.h:282