Commit f9c9e6c0 authored by Morten Welinder's avatar Morten Welinder Committed by Morten Welinder

New file. New file.

2000-01-16  Morten Welinder  <terra@diku.dk>

	* src/auto-format.c: New file.
	* src/auto-format.h: New file.

	* src/formats.c (cell_format_general, cell_format_numbers,
 	cell_format_currency, cell_format_account, cell_format_date,
 	cell_format_time, cell_format_percent, cell_format_fraction,
 	cell_format_science, cell_format_text): Make static.

	* src/cell.c (cell_set_formula): Free the format.  Only set format
 	if the cell was previously blank.
	(cell_has_assigned_format, cell_get_format): New functions.

	* src/parser.y (gnumeric_expr_parser): Drop const for
 	desired_format.  On error, free the format.
	(make_string_return): g_strdup the format.

	* src/expr.c (expr_parse_string): Drop const for desired_format.

	* src/functions/fn-financial.c (finance_functions_init): Add
 	result types for auto-format.

	* src/functions/fn-date.c (date_functions_init): Add result types
 	for auto-format.

	* src/functions/fn-math.c (math_functions_init): Add result types
 	for auto-format.

	* src/Makefile.am (GNUMERIC_BASE_SOURCES): Add auto-format.c and
 	auto-format.h.

	* src/main.c (gnumeric_main): Init and shutdown for auto_format.
parent 98320654
2000-01-16 Morten Welinder <terra@diku.dk>
* src/auto-format.c: New file.
* src/auto-format.h: New file.
* src/formats.c (cell_format_general, cell_format_numbers,
cell_format_currency, cell_format_account, cell_format_date,
cell_format_time, cell_format_percent, cell_format_fraction,
cell_format_science, cell_format_text): Make static.
* src/cell.c (cell_set_formula): Free the format. Only set format
if the cell was previously blank.
(cell_has_assigned_format, cell_get_format): New functions.
* src/parser.y (gnumeric_expr_parser): Drop const for
desired_format. On error, free the format.
(make_string_return): g_strdup the format.
* src/expr.c (expr_parse_string): Drop const for desired_format.
* src/functions/fn-financial.c (finance_functions_init): Add
result types for auto-format.
* src/functions/fn-date.c (date_functions_init): Add result types
for auto-format.
* src/functions/fn-math.c (math_functions_init): Add result types
for auto-format.
* src/Makefile.am (GNUMERIC_BASE_SOURCES): Add auto-format.c and
auto-format.h.
* src/main.c (gnumeric_main): Init and shutdown for auto_format.
2000-01-16 Morten Welinder <terra@diku.dk>
* gnumeric.spec.in (gnome-print): require 0.10.
* configure.in (gnome-print): require 0.10.
2000-01-16 Miguel de Icaza <miguel@gnu.org>
* src/sheet.c (sheet_redraw_range): New function.
......
2000-01-16 Morten Welinder <terra@diku.dk>
* src/auto-format.c: New file.
* src/auto-format.h: New file.
* src/formats.c (cell_format_general, cell_format_numbers,
cell_format_currency, cell_format_account, cell_format_date,
cell_format_time, cell_format_percent, cell_format_fraction,
cell_format_science, cell_format_text): Make static.
* src/cell.c (cell_set_formula): Free the format. Only set format
if the cell was previously blank.
(cell_has_assigned_format, cell_get_format): New functions.
* src/parser.y (gnumeric_expr_parser): Drop const for
desired_format. On error, free the format.
(make_string_return): g_strdup the format.
* src/expr.c (expr_parse_string): Drop const for desired_format.
* src/functions/fn-financial.c (finance_functions_init): Add
result types for auto-format.
* src/functions/fn-date.c (date_functions_init): Add result types
for auto-format.
* src/functions/fn-math.c (math_functions_init): Add result types
for auto-format.
* src/Makefile.am (GNUMERIC_BASE_SOURCES): Add auto-format.c and
auto-format.h.
* src/main.c (gnumeric_main): Init and shutdown for auto_format.
2000-01-16 Morten Welinder <terra@diku.dk>
* gnumeric.spec.in (gnome-print): require 0.10.
* configure.in (gnome-print): require 0.10.
2000-01-16 Miguel de Icaza <miguel@gnu.org>
* src/sheet.c (sheet_redraw_range): New function.
......
......@@ -11,6 +11,7 @@
#include "utils.h"
#include "func.h"
#include "number-match.h"
#include "auto-format.h"
#define DAY_SECONDS (3600*24)
......@@ -836,60 +837,83 @@ gnumeric_networkdays (FunctionEvalInfo *ei, Value **argv)
void
date_functions_init(void)
{
FunctionDefinition *def;
FunctionCategory *cat = function_get_category (_("Date / Time"));
function_add_args (cat, "date", "fff",
"year,month,day",
&help_date, gnumeric_date);
function_add_args (cat, "datevalue", "?",
"date_str",
&help_datevalue, gnumeric_datevalue);
function_add_args (cat, "day", "?",
"date",
&help_day, gnumeric_day);
function_add_args (cat, "days360", "??|f",
"date1,date2,method",
&help_days360, gnumeric_days360);
function_add_args (cat, "edate", "ff",
"serial_number,months",
&help_edate, gnumeric_edate);
function_add_args (cat, "eomonth", "?|f",
"start_date,months",
&help_eomonth, gnumeric_eomonth);
function_add_args (cat, "hour", "?",
"time",
&help_hour, gnumeric_hour );
function_add_args (cat, "minute", "?",
"time",
&help_minute, gnumeric_minute );
function_add_args (cat, "month", "?",
"date",
&help_month, gnumeric_month);
function_add_args (cat, "networkdays", "??|?",
"start_date,end_date,holidays",
&help_networkdays, gnumeric_networkdays );
function_add_args (cat, "now", "",
"",
&help_now, gnumeric_now );
function_add_args (cat, "second", "?",
"time",
&help_second, gnumeric_second );
function_add_args (cat, "time", "fff",
"hours,minutes,seconds",
&help_time, gnumeric_time );
function_add_args (cat, "timevalue", "?",
"",
&help_timevalue, gnumeric_timevalue );
function_add_args (cat, "today", "",
"",
&help_today, gnumeric_today );
function_add_args (cat, "weekday", "?",
"date",
&help_weekday, gnumeric_weekday);
function_add_args (cat, "workday", "?f|?",
"date,days,holidays",
&help_workday, gnumeric_workday);
function_add_args (cat, "year", "?",
"date",
&help_year, gnumeric_year);
def = function_add_args (cat, "date", "fff",
"year,month,day",
&help_date, gnumeric_date);
auto_format_function_result (def, AF_DATE);
def = function_add_args (cat, "datevalue", "?",
"date_str",
&help_datevalue, gnumeric_datevalue);
def = function_add_args (cat, "day", "?",
"date",
&help_day, gnumeric_day);
def = function_add_args (cat, "days360", "??|f",
"date1,date2,method",
&help_days360, gnumeric_days360);
def = function_add_args (cat, "edate", "ff",
"serial_number,months",
&help_edate, gnumeric_edate);
auto_format_function_result (def, AF_DATE);
def = function_add_args (cat, "eomonth", "?|f",
"start_date,months",
&help_eomonth, gnumeric_eomonth);
auto_format_function_result (def, AF_DATE);
def = function_add_args (cat, "hour", "?",
"time",
&help_hour, gnumeric_hour );
def = function_add_args (cat, "minute", "?",
"time",
&help_minute, gnumeric_minute );
def = function_add_args (cat, "month", "?",
"date",
&help_month, gnumeric_month);
def = function_add_args (cat, "networkdays", "??|?",
"start_date,end_date,holidays",
&help_networkdays, gnumeric_networkdays );
def = function_add_args (cat, "now", "",
"",
&help_now, gnumeric_now );
def = function_add_args (cat, "second", "?",
"time",
&help_second, gnumeric_second );
def = function_add_args (cat, "time", "fff",
"hours,minutes,seconds",
&help_time, gnumeric_time );
auto_format_function_result (def, AF_TIME);
def = function_add_args (cat, "timevalue", "?",
"",
&help_timevalue, gnumeric_timevalue );
def = function_add_args (cat, "today", "",
"",
&help_today, gnumeric_today );
auto_format_function_result (def, AF_DATE);
def = function_add_args (cat, "weekday", "?",
"date",
&help_weekday, gnumeric_weekday);
def = function_add_args (cat, "workday", "?f|?",
"date,days,holidays",
&help_workday, gnumeric_workday);
def = function_add_args (cat, "year", "?",
"date",
&help_year, gnumeric_year);
}
This diff is collapsed.
......@@ -12,7 +12,7 @@
#include "func.h"
#include "mathfunc.h"
#include "collect.h"
#include "auto-format.h"
static int
gcd (int a, int b)
......@@ -3355,10 +3355,13 @@ gnumeric_sumproduct (FunctionEvalInfo *ei, GList *expr_node_list)
void
math_functions_init (void)
{
FunctionDefinition *def;
FunctionCategory *cat = function_get_category (_("Maths / Trig."));
function_add_args (cat, "abs", "f",
"number", &help_abs, gnumeric_abs);
def = function_add_args (cat, "abs", "f",
"number", &help_abs, gnumeric_abs);
auto_format_function_result (def, AF_FIRST_ARG_FORMAT);
function_add_args (cat, "acos", "f",
"number", &help_acos, gnumeric_acos);
function_add_args (cat, "acosh", "f",
......@@ -3380,11 +3383,16 @@ math_functions_init (void)
function_add_args (cat, "countif", "r?",
"range,criteria",
&help_countif, gnumeric_countif);
function_add_args (cat, "ceil", "f",
"number", &help_ceil, gnumeric_ceil);
function_add_args (cat, "ceiling", "ff",
"number,significance",
&help_ceiling, gnumeric_ceiling);
def = function_add_args (cat, "ceil", "f",
"number", &help_ceil, gnumeric_ceil);
auto_format_function_result (def, AF_FIRST_ARG_FORMAT);
def = function_add_args (cat, "ceiling", "ff",
"number,significance",
&help_ceiling, gnumeric_ceiling);
auto_format_function_result (def, AF_FIRST_ARG_FORMAT);
function_add_args (cat, "degrees", "f",
"number", &help_degrees, gnumeric_degrees);
function_add_args (cat, "even", "f",
......@@ -3398,13 +3406,19 @@ math_functions_init (void)
&help_factdouble, gnumeric_factdouble);
function_add_args (cat, "combin", "ff",
"n,k", &help_combin, gnumeric_combin);
function_add_args (cat, "floor", "f|f",
"number", &help_floor, gnumeric_floor);
def = function_add_args (cat, "floor", "f|f",
"number", &help_floor, gnumeric_floor);
auto_format_function_result (def, AF_FIRST_ARG_FORMAT);
function_add_nodes (cat, "gcd", "ff",
"number1,number2",
&help_gcd, gnumeric_gcd);
function_add_args (cat, "int", "f",
"number", &help_int, gnumeric_int);
def = function_add_args (cat, "int", "f",
"number", &help_int, gnumeric_int);
auto_format_function_result (def, AF_FIRST_ARG_FORMAT);
function_add_nodes (cat, "lcm", 0,
"", &help_lcm, gnumeric_lcm);
function_add_args (cat, "ln", "f",
......@@ -3418,9 +3432,12 @@ math_functions_init (void)
"number", &help_log10, gnumeric_log10);
function_add_args (cat, "mod", "ff",
"num,denom", &help_mod, gnumeric_mod);
function_add_args (cat, "mround", "ff",
"number,multiple",
&help_mround, gnumeric_mround);
def = function_add_args (cat, "mround", "ff",
"number,multiple",
&help_mround, gnumeric_mround);
auto_format_function_result (def, AF_FIRST_ARG_FORMAT);
function_add_nodes (cat, "multinomial", 0,
"",
&help_multinomial, gnumeric_multinomial);
......@@ -3445,15 +3462,22 @@ math_functions_init (void)
function_add_args (cat, "roman", "f|f",
"number[,type]",
&help_roman, gnumeric_roman);
function_add_args (cat, "round", "f|f",
"number[,digits]",
&help_round, gnumeric_round);
function_add_args (cat, "rounddown", "f|f",
"number,digits",
&help_rounddown, gnumeric_rounddown);
function_add_args (cat, "roundup", "f|f",
"number,digits",
&help_roundup, gnumeric_roundup);
def = function_add_args (cat, "round", "f|f",
"number[,digits]",
&help_round, gnumeric_round);
auto_format_function_result (def, AF_FIRST_ARG_FORMAT);
def = function_add_args (cat, "rounddown", "f|f",
"number,digits",
&help_rounddown, gnumeric_rounddown);
auto_format_function_result (def, AF_FIRST_ARG_FORMAT);
def = function_add_args (cat, "roundup", "f|f",
"number,digits",
&help_roundup, gnumeric_roundup);
auto_format_function_result (def, AF_FIRST_ARG_FORMAT);
function_add_nodes (cat, "seriessum", 0,
"x,n,m,coefficients",
&help_seriessum, gnumeric_seriessum);
......@@ -3470,12 +3494,17 @@ math_functions_init (void)
function_add_nodes (cat, "subtotal", 0,
"function_nbr,ref1,ref2,...",
&help_subtotal, gnumeric_subtotal);
function_add_nodes (cat, "sum", 0,
"number1,number2,...",
&help_sum, gnumeric_sum);
function_add_nodes (cat, "suma", 0,
"number1,number2,...",
&help_suma, gnumeric_suma);
def = function_add_nodes (cat, "sum", 0,
"number1,number2,...",
&help_sum, gnumeric_sum);
auto_format_function_result (def, AF_FIRST_ARG_FORMAT);
def = function_add_nodes (cat, "suma", 0,
"number1,number2,...",
&help_suma, gnumeric_suma);
auto_format_function_result (def, AF_FIRST_ARG_FORMAT);
function_add_args (cat, "sumif", "r?|r",
"range,criteria[,actual_range]",
&help_sumif, gnumeric_sumif);
......@@ -3497,9 +3526,12 @@ math_functions_init (void)
"number", &help_tan, gnumeric_tan);
function_add_args (cat, "tanh", "f",
"number", &help_tanh, gnumeric_tanh);
function_add_args (cat, "trunc", "f|f",
"number,digits",
&help_trunc, gnumeric_trunc);
def = function_add_args (cat, "trunc", "f|f",
"number,digits",
&help_trunc, gnumeric_trunc);
auto_format_function_result (def, AF_FIRST_ARG_FORMAT);
function_add_args (cat, "pi", "",
"", &help_pi, gnumeric_pi);
function_add_args (cat, "mmult", "AA",
......
......@@ -52,6 +52,8 @@ GNUMERIC_BASE_SOURCES = \
analysis-tools.c \
application.c \
application.h \
auto-format.c \
auto-format.h \
border.c \
border.h \
cell.h \
......
/*
* auto-format.c: Suggest formats for expressions.
*
* Authors:
* Morten Welinder <terra@diku.dk>
*/
#include <config.h>
#include "auto-format.h"
#include "utils.h"
#include "formats.h"
#include "expr.h"
/* ------------------------------------------------------------------------- */
/*
* An important note about correctness.
*
* For some functions it is easy to tell what correct behaviour is;
* if the evaluation of the percent operator yields anything but x/100
* that is bad.
*
* This function is not that simple.
*
* If we fail to suggest a format when one might have been deduced, that
* is really not a big deal. So the fact that "=date(2000,1,1)^1" is not
* recognised as a date bothers no-one.
*
* If we occasionally suggest a format where none is reasonable, that is
* not a problem either. "=pv(1,2,3,4,5)*today()" has no reasonable
* format, but we assign one. Tough.
*
* On the other hand, if we suggest a bad format for a function that does
* have a good format, this is bad. (Since the user will just select
* another format, it isn't critical, just bad.)
*
* Please resist the temptation of making this ridiculously smart. For
* example, avoid too much algebra here and don't look at actual numbers
* encountered. Let the evaluator do that. One reason for this is that
* if you are entering a range of similar data, you really want the same
* format. You don't want a different number of decimals for "22%" and
* "22.5%".
*/
/* ------------------------------------------------------------------------- */
static GHashTable *auto_format_function_hash;
void
auto_format_init (void)
{
auto_format_function_hash =
g_hash_table_new (gnumeric_strcase_hash, gnumeric_strcase_equal);
}
static void
cb_free_name (gpointer key, gpointer value, gpointer data)
{
g_free (key);
}
void
auto_format_shutdown (void)
{
g_hash_table_foreach (auto_format_function_hash,
cb_free_name,
NULL);
g_hash_table_destroy (auto_format_function_hash);
auto_format_function_hash = NULL;
}
/* ------------------------------------------------------------------------- */
void
auto_format_function_result (FunctionDefinition *fd, AutoFormatTypes res)
{
const char *name;
g_return_if_fail (fd != NULL);
g_return_if_fail (res != AF_UNKNOWN);
g_return_if_fail (res != AF_EXPLICIT);
name = function_def_get_name (fd);
g_hash_table_insert (auto_format_function_hash,
g_strdup (name), GINT_TO_POINTER (res));
}
/* ------------------------------------------------------------------------- */
static AutoFormatTypes do_af_suggest_list (GList *list, EvalPosition *ppos, char **explicit);
struct cb_af_suggest { AutoFormatTypes typ; char **explicit; };
static Value *
cb_af_suggest (Sheet *sheet, int col, int row, Cell *cell, void *_data)
{
struct cb_af_suggest *data = _data;
*(data->explicit) = cell_get_format (cell);
if (*(data->explicit)) {
data->typ = AF_EXPLICIT;
return value_terminate ();
}
return NULL;
}
static AutoFormatTypes
do_af_suggest (const ExprTree *expr, EvalPosition *ppos, char **explicit)
{
switch (expr->oper) {
case OPER_EQUAL:
case OPER_GT:
case OPER_LT:
case OPER_GTE:
case OPER_LTE:
case OPER_NOT_EQUAL:
return AF_UNITLESS; /* Close enough. */
case OPER_MULT:
/* Fall through. This isn't quite right, but good enough. */
case OPER_ADD:
case OPER_SUB: {
/* Return the first interesting type we see. */
AutoFormatTypes typ;
typ = do_af_suggest (expr->u.binary.value_a, ppos, explicit);
if (typ != AF_UNKNOWN && typ != AF_UNITLESS)
return typ;
return do_af_suggest (expr->u.binary.value_b, ppos, explicit);
}
case OPER_DIV:
/* Check the left-hand side only. */
return do_af_suggest (expr->u.binary.value_a, ppos, explicit);
case OPER_FUNCALL: {
AutoFormatTypes typ;
const char *name;
name = expr->u.function.symbol->str;
typ = (AutoFormatTypes)
GPOINTER_TO_INT
(g_hash_table_lookup (auto_format_function_hash, name));
switch (typ) {
case AF_FIRST_ARG_FORMAT:
return do_af_suggest_list (expr->u.function.arg_list,
ppos, explicit);
default:
return typ;
}
}
case OPER_CONSTANT: {
const Value *v = expr->u.constant;
switch (v->type) {
case VALUE_STRING:
case VALUE_ERROR:
case VALUE_ARRAY:
return AF_UNKNOWN;
case VALUE_CELLRANGE: {
Sheet *sheet;
const CellRef *ref_a, *ref_b;
int col_a, col_b, row_a, row_b;
struct cb_af_suggest closure;
ref_a = &v->v.cell_range.cell_a;
ref_b = &v->v.cell_range.cell_b;
sheet = eval_sheet (ref_a->sheet, ppos->sheet);
/* If we don't have a sheet, we cannot look up vars. */
if (sheet == NULL)
return AF_UNKNOWN;
cell_get_abs_col_row (ref_a, &ppos->eval, &col_a, &row_a);
cell_get_abs_col_row (ref_b, &ppos->eval, &col_b, &row_b);
closure.typ = AF_UNKNOWN;
closure.explicit = explicit;
sheet_cell_foreach_range (sheet, TRUE,
col_a, row_a,
col_b, row_b,
&cb_af_suggest,
&closure);
return closure.typ;
}
default:
return AF_UNITLESS;
}
}
case OPER_VAR: {
Sheet *sheet;
const CellRef *ref;
int col, row;
const Cell *cell;
ref = &expr->u.ref;
sheet = eval_sheet (ref->sheet, ppos->sheet);
/* If we don't have a sheet, we cannot look up vars. */
if (sheet == NULL)
return AF_UNKNOWN;
cell_get_abs_col_row (ref, &ppos->eval, &col, &row);
cell = sheet_cell_get (sheet, col, row);
if (cell == NULL)
return AF_UNKNOWN;
*explicit = cell_get_format (cell);
return explicit ? AF_EXPLICIT : AF_UNKNOWN;
}
case OPER_NEG:
return do_af_suggest (expr->u.value, ppos, explicit);
case OPER_PERCENT:
return AF_PERCENT;
case OPER_EXP:
case OPER_CONCAT:
case OPER_NAME:
case OPER_ARRAY:
default:
return AF_UNKNOWN;
}
}
static AutoFormatTypes
do_af_suggest_list (GList *list, EvalPosition *ppos, char **explicit)
{
AutoFormatTypes typ = AF_UNKNOWN;
while (list && (typ == AF_UNKNOWN || typ == AF_UNITLESS)) {
typ = do_af_suggest (list->data, ppos, explicit);
list = list->next;
}
return typ;
}
/* ------------------------------------------------------------------------- */
char *
auto_format_suggest (const ExprTree *expr, EvalPosition *ppos)
{
char *explicit = NULL;