Files
gnucash/src/register/pricecell.c
Dave Peticolas b12e1d6675 Convert parser to use gnc_numerics.
Fix bug in gnc_numeric_reduce.


git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@3093 57a11ea4-9604-0410-9ed3-97b8803252fd
2000-10-30 10:46:46 +00:00

390 lines
8.7 KiB
C

/********************************************************************\
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License*
* along with this program; if not, contact: *
* *
* Free Software Foundation Voice: +1-617-542-5942 *
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
* Boston, MA 02111-1307, USA gnu@gnu.org *
* *
\********************************************************************/
/*
* FILE:
* pricecell.c
*
* FUNCTION:
* Implements the price cell
*
* HISTORY:
* Copyright (c) 1998, 1999, 2000 Linas Vepstas
* Copyright (c) 2000 Dave Peticolas
*/
#include <ctype.h>
#include <string.h>
#include <locale.h>
#include <string.h>
#include "gnc-common.h"
#include "gnc-exp-parser.h"
#include "util.h"
#include "basiccell.h"
#include "pricecell.h"
/* GUI-dependent */
extern void xaccPriceGUIInit (PriceCell *);
static void PriceSetValue (BasicCell *, const char *);
static const char * xaccPriceCellPrintValue (PriceCell *cell);
/* ================================================ */
/* set the color of the text to red, if the value is negative */
/* hack alert -- the actual color should probably be configurable */
#define COLORIZE(cell,amount) { \
if ((0.0 > amount) && !DEQ(amount, 0.0)) { \
/* red */ \
cell->cell.fg_color = 0xff0000; \
} else { \
/* black */ \
cell->cell.fg_color = 0x0; \
} \
}
#define SET(cell,str) { \
g_free ((cell)->value); \
(cell)->value = g_strdup (str); \
}
/* ================================================ */
static gboolean
PriceEnter (BasicCell *_cell,
int *cursor_position,
int *start_selection,
int *end_selection)
{
*cursor_position = -1;
*start_selection = 0;
*end_selection = -1;
return TRUE;
}
/* ================================================ */
/* This callback only allows numbers with a single
* decimal point in them */
static void
PriceMV (BasicCell *_cell,
const char *change,
const char *newval,
int *cursor_position,
int *start_selection,
int *end_selection)
{
PriceCell *cell = (PriceCell *) _cell;
struct lconv *lc = gnc_localeconv();
const char *toks = "+-*/=()";
char decimal_point;
char thousands_sep;
int i;
/* accept the newval string if user action was delete */
if (change == NULL)
{
SET ((&(cell->cell)), newval);
cell->need_to_parse = TRUE;
return;
}
if (cell->monetary)
decimal_point = lc->mon_decimal_point[0];
else
decimal_point = lc->decimal_point[0];
if (cell->monetary)
thousands_sep = lc->mon_thousands_sep[0];
else
thousands_sep = lc->thousands_sep[0];
for (i = 0; change[i] != '\0'; i++)
if (!isdigit(change[i]) &&
!isspace(change[i]) &&
(decimal_point != change[i]) &&
(thousands_sep != change[i]) &&
(strchr (toks, change[i]) == NULL))
return;
SET ((&(cell->cell)), newval);
cell->need_to_parse = TRUE;
}
/* ================================================ */
static void
PriceParse (PriceCell *cell)
{
const char *newval;
char *oldval;
gnc_numeric amount;
if (!cell->need_to_parse)
return;
oldval = cell->cell.value;
if (oldval == NULL)
oldval = "";
if (gnc_exp_parser_parse (cell->cell.value, &amount, NULL))
cell->amount = gnc_numeric_to_double (amount);
else
cell->amount = 0.0;
COLORIZE (cell, cell->amount);
newval = xaccPriceCellPrintValue(cell);
/* If they are identical do nothing */
if (strcmp(newval, oldval) == 0)
return;
/* Otherwise, change it */
SET ((&(cell->cell)), newval);
}
/* ================================================ */
static void
PriceLeave (BasicCell *_cell)
{
PriceCell *cell = (PriceCell *) _cell;
PriceParse (cell);
}
/* ================================================ */
static char *
PriceHelp (BasicCell *bcell)
{
if ((bcell->value != NULL) && (bcell->value[0] != 0))
{
const char *help_str;
help_str = bcell->value;
return g_strdup(help_str);
}
if (bcell->blank_help != NULL)
return g_strdup(bcell->blank_help);
return NULL;
}
/* ================================================ */
PriceCell *
xaccMallocPriceCell (void)
{
PriceCell *cell;
cell = g_new(PriceCell, 1);
xaccInitPriceCell (cell);
return cell;
}
/* ================================================ */
void
xaccInitPriceCell (PriceCell *cell)
{
xaccInitBasicCell (&(cell->cell));
cell->amount = 0.0;
cell->blank_zero = TRUE;
cell->monetary = TRUE;
cell->is_currency = FALSE;
cell->shares_value = FALSE;
cell->need_to_parse = FALSE;
SET (&(cell->cell), "");
COLORIZE (cell, 0.0);
cell->cell.use_fg_color = TRUE;
cell->cell.enter_cell = PriceEnter;
cell->cell.modify_verify = PriceMV;
cell->cell.leave_cell = PriceLeave;
cell->cell.set_value = PriceSetValue;
cell->cell.get_help_value = PriceHelp;
xaccPriceGUIInit (cell);
}
/* ================================================ */
void
xaccDestroyPriceCell (PriceCell *cell)
{
cell->amount = 0.0;
xaccDestroyBasicCell (&(cell->cell));
}
/* ================================================ */
static const char *
xaccPriceCellPrintValue (PriceCell *cell)
{
GNCPrintAmountFlags flags = PRTSEP;
if (cell->blank_zero && DEQ(cell->amount, 0.0))
return "";
if (cell->shares_value)
flags |= PRTSHR;
if (cell->is_currency)
flags |= PRTCUR;
return DxaccPrintAmount(cell->amount, flags, NULL);
}
/* ================================================ */
double
xaccGetPriceCellValue (PriceCell *cell)
{
if (cell == NULL)
return 0.0;
PriceParse (cell);
return cell->amount;
}
void
xaccSetPriceCellValue (PriceCell * cell, double amount)
{
const char *buff;
if (cell == NULL)
return;
cell->amount = amount;
buff = xaccPriceCellPrintValue (cell);
cell->need_to_parse = FALSE;
SET (&(cell->cell), buff);
/* set the cell color to red if the value is negative */
COLORIZE (cell, amount);
}
void
xaccSetPriceCellBlank (PriceCell *cell)
{
if (cell == NULL)
return;
cell->amount = 0.0;
cell->need_to_parse = FALSE;
SET (&(cell->cell), "");
COLORIZE (cell, 0.0);
}
/* ================================================ */
void
xaccSetPriceCellSharesValue (PriceCell * cell, gboolean shares_value)
{
if (cell == NULL)
return;
cell->shares_value = shares_value;
}
/* ================================================ */
void
xaccSetPriceCellMonetary (PriceCell * cell, gboolean monetary)
{
if (cell == NULL)
return;
cell->monetary = monetary;
}
/* ================================================ */
void
xaccSetPriceCellIsCurrency (PriceCell *cell, gboolean is_currency)
{
if (cell == NULL)
return;
cell->is_currency = is_currency;
}
/* ================================================ */
void
xaccSetPriceCellBlankZero (PriceCell *cell, gboolean blank_zero)
{
if (cell == NULL)
return;
cell->blank_zero = blank_zero;
}
/* ================================================ */
void xaccSetDebCredCellValue (PriceCell * debit,
PriceCell * credit,
double amount)
{
/* debits are positive, credits are negative */
if (amount > 0.0) {
xaccSetPriceCellValue (debit, amount);
xaccSetPriceCellValue (credit, 0.0);
} else {
xaccSetPriceCellValue (debit, 0.0);
xaccSetPriceCellValue (credit, -amount);
}
}
/* ================================================ */
static void
PriceSetValue (BasicCell *_cell, const char *str)
{
PriceCell *cell = (PriceCell *) _cell;
gnc_numeric amount;
if (str == NULL)
str = "";
if (*str == '\0')
xaccSetPriceCellValue (cell, 0.0);
else if (gnc_exp_parser_parse (str, &amount, NULL))
xaccSetPriceCellValue (cell, gnc_numeric_to_double (amount));
}
/* --------------- end of file ---------------------- */