GnuCash c935c2f+
Loading...
Searching...
No Matches
pricecell.c
1/********************************************************************\
2 * pricecell.c -- price input/display cell *
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 * pricecell.c
26 *
27 * FUNCTION:
28 * Implements the price cell
29 *
30 * HISTORY:
31 * Copyright (c) 1998, 1999, 2000 Linas Vepstas
32 * Copyright (c) 2000 Dave Peticolas
33 */
34
35#include <config.h>
36
37#include <glib.h>
38#include <glib/gi18n.h>
39#include <string.h>
40
41#include "gnc-exp-parser.h"
42#include "gnc-engine.h"
43#include "gnc-ui-util.h"
44#include "gnc-ui.h"
45
46#include "basiccell.h"
47#include "pricecell.h"
48#include <qoflog.h>
49
50static const QofLogModule log_module = G_LOG_DOMAIN;
51
52static void gnc_price_cell_init (PriceCell *cell);
53static void gnc_price_cell_set_value_internal (BasicCell *bcell,
54 const char *value);
55static const char * gnc_price_cell_print_value (PriceCell *cell);
56
57
58static gboolean
59gnc_price_cell_enter (BasicCell *_cell,
60 int *cursor_position,
61 int *start_selection,
62 int *end_selection)
63{
64 *cursor_position = -1;
65 *start_selection = 0;
66 *end_selection = -1;
67
68 return TRUE;
69}
70
71static void
72gnc_price_cell_modify_verify (BasicCell *_cell,
73 const char *change,
74 int change_len,
75 const char *newval,
76 int newval_len,
77 int *cursor_position,
78 int *start_selection,
79 int *end_selection)
80{
81 PriceCell *cell = (PriceCell *) _cell;
82 const char *toks = "+-*/=()_";
83 char *validated_newval = NULL;
84
85 DEBUG("%s, %d, %s, %d, %d, %d, %d",
86 change ? (gchar *)change : "(null)", change_len,
87 newval ? (gchar *)newval : "(null)", newval_len,
88 *cursor_position, *start_selection, *end_selection);
89
90 validated_newval = gnc_basic_cell_validate (_cell, cell->print_info,
91 change, newval, toks,
92 cursor_position);
93
94 if (!validated_newval)
95 return;
96
97 gnc_basic_cell_set_value_internal (_cell, validated_newval);
98 g_free (validated_newval);
99
100 *end_selection = *start_selection = *cursor_position;
101 cell->need_to_parse = TRUE;
102}
103
104static gint
105gnc_price_cell_parse (PriceCell *cell, gboolean update_value)
106{
107 const char *newval;
108 char *oldval;
109 gnc_numeric amount;
110
111 if (!cell->need_to_parse)
112 return -1;
113
114 oldval = cell->cell.value;
115 if (oldval == NULL)
116 oldval = "";
117
118 {
119 char *err_location = NULL;
120 if (strlen(g_strstrip(cell->cell.value)) == 0)
121 {
122 cell->amount = gnc_numeric_zero ();
123 }
124 else if (gnc_exp_parser_parse (cell->cell.value, &amount, &err_location))
125 {
126 if (cell->fraction > 0)
127 amount = gnc_numeric_convert (amount, cell->fraction, GNC_HOW_RND_ROUND_HALF_UP);
128
129 cell->amount = amount;
130 }
131 else
132 {
133 return (err_location - cell->cell.value);
134 }
135 }
136
137 if (!update_value)
138 return -1;
139
140 newval = gnc_price_cell_print_value (cell);
141
142 /* If they are identical do nothing */
143 if (strcmp(newval, oldval) == 0)
144 return -1;
145
146 /* Otherwise, change it */
147 gnc_basic_cell_set_value_internal (&cell->cell, newval);
148 return -1;
149}
150
151static void
152gnc_price_cell_leave (BasicCell *_cell)
153{
154 gint error_position = -1;
155 PriceCell *cell = (PriceCell *) _cell;
156
157 error_position = gnc_price_cell_parse (cell, TRUE);
158 if (error_position != -1)
159 {
160 gnc_warning_dialog (gnc_ui_get_main_window (NULL),
161 _("An error occurred while processing '%s' at position %d"),
162 cell->cell.value, error_position);
163 }
164
165}
166
167BasicCell *
169{
170 PriceCell *cell;
171
172 cell = g_new0 (PriceCell, 1);
173
174 gnc_price_cell_init (cell);
175
176 return &cell->cell;
177}
178
179void
180gnc_price_cell_init (PriceCell *cell)
181{
182 gnc_basic_cell_init (&(cell->cell));
183
184 cell->amount = gnc_numeric_zero ();
185 cell->fraction = 0;
186 cell->blank_zero = TRUE;
187
188 cell->print_info = gnc_default_print_info (FALSE);
189
190 cell->need_to_parse = FALSE;
191
192 cell->cell.enter_cell = gnc_price_cell_enter;
193 cell->cell.modify_verify = gnc_price_cell_modify_verify;
194 cell->cell.leave_cell = gnc_price_cell_leave;
195 cell->cell.set_value = gnc_price_cell_set_value_internal;
196}
197
198static const char *
199gnc_price_cell_print_value (PriceCell *cell)
200{
201 if (cell->blank_zero && gnc_numeric_zero_p (cell->amount))
202 return "";
203
204 return xaccPrintAmount (cell->amount, cell->print_info);
205}
206
207gnc_numeric
209{
210 if (cell == NULL)
211 return gnc_numeric_zero ();
212
213 gnc_price_cell_parse (cell, FALSE);
214
215 return cell->amount;
216}
217
218gboolean
219gnc_price_cell_set_value (PriceCell * cell, gnc_numeric amount)
220{
221 const char *buff;
222
223 if (cell == NULL)
224 return FALSE;
225
226 if (cell->fraction > 0)
227 amount = gnc_numeric_convert (amount, cell->fraction, GNC_HOW_RND_ROUND_HALF_UP);
228
229 cell->amount = amount;
230 buff = gnc_price_cell_print_value (cell);
231 cell->need_to_parse = FALSE;
232
233 if (g_strcmp0 (buff, cell->cell.value) == 0)
234 return FALSE;
235
236 gnc_basic_cell_set_value_internal (&cell->cell, buff);
237
238 return TRUE;
239}
240
241void
243{
244 if (cell == NULL)
245 return;
246
247 cell->fraction = ABS (fraction);
248}
249
250void
252{
253 if (cell == NULL)
254 return;
255
256 cell->amount = gnc_numeric_zero ();
257 cell->need_to_parse = FALSE;
258
259 gnc_basic_cell_set_value_internal (&cell->cell, "");
260}
261
262void
263gnc_price_cell_set_blank_zero (PriceCell *cell, gboolean blank_zero)
264{
265 if (cell == NULL)
266 return;
267
268 cell->blank_zero = blank_zero;
269}
270
271void
273{
274 if (cell == NULL)
275 return;
276
277 cell->print_info = print_info;
278}
279
280void
282 PriceCell * credit,
283 gnc_numeric amount)
284{
285 /* debits are positive, credits are negative */
286 if (gnc_numeric_positive_p (amount))
287 {
288 gnc_price_cell_set_value (debit, amount);
289 gnc_price_cell_set_value (credit, gnc_numeric_zero ());
290 }
291 else
292 {
293 gnc_price_cell_set_value (debit, gnc_numeric_zero ());
294 gnc_price_cell_set_value (credit, gnc_numeric_neg (amount));
295 }
296}
297
298static void
299gnc_price_cell_set_value_internal (BasicCell *_cell, const char *str)
300{
301 PriceCell *cell = (PriceCell *) _cell;
302 gnc_numeric amount;
303
304 if (str == NULL)
305 str = "";
306
307 if (*str == '\0')
308 gnc_price_cell_set_value (cell, gnc_numeric_zero ());
309 else if (gnc_exp_parser_parse (str, &amount, NULL))
310 gnc_price_cell_set_value (cell, amount);
311}
All type declarations for the whole Gnucash engine.
utility functions for the GnuCash UI
void gnc_price_cell_set_blank_zero(PriceCell *cell, gboolean blank_zero)
determines whether 0 values are left blank or printed.
Definition pricecell.c:263
gnc_numeric gnc_price_cell_get_value(PriceCell *cell)
return the value of a price cell
Definition pricecell.c:208
void gnc_price_cell_set_debt_credit_value(PriceCell *debit, PriceCell *credit, gnc_numeric amount)
updates two cells; the deb cell if amt is negative, the credit cell if amount is positive,...
Definition pricecell.c:281
gboolean gnc_price_cell_set_value(PriceCell *cell, gnc_numeric amount)
updates amount, returns TRUE if string representation actually changed
Definition pricecell.c:219
void gnc_price_cell_set_fraction(PriceCell *cell, int fraction)
Sets the fraction used for rounding.
Definition pricecell.c:242
void gnc_price_cell_set_print_info(PriceCell *cell, GNCPrintAmountInfo print_info)
set the printing context of the price cell
Definition pricecell.c:272
BasicCell * gnc_price_cell_new(void)
installs a callback to handle price recording
Definition pricecell.c:168
void gnc_price_cell_blank(PriceCell *cell)
Sets the cell as blank, regardless of the blank_zero value.
Definition pricecell.c:251
GtkWindow * gnc_ui_get_main_window(GtkWidget *widget)
Get a pointer to the final GncMainWindow widget is rooted in.
const char * xaccPrintAmount(gnc_numeric val, GNCPrintAmountInfo info)
Make a string representation of a gnc_numeric.
#define DEBUG(format, args...)
Print a debugging message.
Definition qoflog.h:264
gboolean gnc_numeric_zero_p(gnc_numeric a)
Returns 1 if the given gnc_numeric is 0 (zero), else returns 0.
gnc_numeric gnc_numeric_neg(gnc_numeric a)
Returns a newly created gnc_numeric that is the negative of the given gnc_numeric value.
gboolean gnc_numeric_positive_p(gnc_numeric a)
Returns 1 if a > 0, otherwise returns 0.
@ GNC_HOW_RND_ROUND_HALF_UP
Round to the nearest integer, rounding away from zero when there are two equidistant nearest integers...
The PriceCell object implements a cell handler that stores a single double-precision value,...
Definition pricecell.h:55
int fraction
the amount associated with this cell
Definition pricecell.h:58
gboolean need_to_parse
amount printing context
Definition pricecell.h:61
gboolean blank_zero
fraction used for rounding, if 0 no rounding
Definition pricecell.h:59
GNCPrintAmountInfo print_info
controls printing of zero values
Definition pricecell.h:60