Commit 0ff37596 authored by Jody Goldberg's avatar Jody Goldberg

- Fix typo in recent unlogged commit.

- Drawing fixes to avoid infinite loops.
- Parsing fixes for numbers (more work needed)
- More functions.
parent 10adef43
1999-07-20 Jody Goldberg <jgoldberg@home.com>
* src/fn-math.c : Moved gpow10 from here.
* src/utils.[ch] : to here.
* src/expr.c (value_area_get_x_y) : return NULL in all cases of
invalid refernces dont fake a 0.
Rename TYPE_ERROR -> TYPE_MISMATCH.
(is_null_string) : New function.
(compare) : Allow equality tests between empty/error things too.
(eval_expr) : Allow comparisons of empty/error values. It can handle
it now.
(OPER_ARRAY) : Use value_area_get_x_y not fetch_x_y, handle empty/error.
(value_get_as_string) : Fix typo in recent unlogged change. The change
might break importing files from a different locale.
* src/fn-string.c : Add TEXT, improve VALUE, REPLACE so that they
passes more tests.
* src/number-match.c (compute_value) : Partial support for thousands
separator. Why doesn't this code use locale ?
* src/format.c (format_value) : better support for ranges, attempt to
work around problem of a thousands seperator in a date format.
* src/cell-draw.c (cell_draw) : Fix potential for infinite loop
with HALIGN_FILL.
* src/print-cell.c (print_cell_text) : Ditto.
* src/parser.y (make_string_return) : A string of the form "..." is
a string, don't try to parse it as a number.
* src/pattern-selector.[ch] : pattern_selector_select made static. In
preparation for different approach.
1999-07-19 Andreas Voegele <andreas.voegele@gmx.de>
* src/parser.y (gnumeric_unsafe_expr_parser): Use the locale to
......@@ -63,6 +98,9 @@
* src/expr-name.[ch] (expr_name_add, expr_name_lookup) : Const.
* src/parser.y (make_string_return) : Handle special case of "" avoid
turning it into a number.
1999-07-13 Michael Meeks <michael@edenproject.org>
* src/Makefile.am (GNUMERIC_BASE_SOURCES): add summary.[ch]
......
......@@ -17,7 +17,9 @@ Jukka:
analysis tool
Jody:
* Added HYPERLINK stub, fixed OFFSET.
* Added TEXT, HYPERLINK stub, fixed OFFSET, VALUE.
* Improve handling of empty cells, and null strings. Still incomplete.
* Partial fix formating/parsing.
* Bug fixes for Excel import.
Michael:
......
1999-07-20 Jody Goldberg <jgoldberg@home.com>
* src/fn-math.c : Moved gpow10 from here.
* src/utils.[ch] : to here.
* src/expr.c (value_area_get_x_y) : return NULL in all cases of
invalid refernces dont fake a 0.
Rename TYPE_ERROR -> TYPE_MISMATCH.
(is_null_string) : New function.
(compare) : Allow equality tests between empty/error things too.
(eval_expr) : Allow comparisons of empty/error values. It can handle
it now.
(OPER_ARRAY) : Use value_area_get_x_y not fetch_x_y, handle empty/error.
(value_get_as_string) : Fix typo in recent unlogged change. The change
might break importing files from a different locale.
* src/fn-string.c : Add TEXT, improve VALUE, REPLACE so that they
passes more tests.
* src/number-match.c (compute_value) : Partial support for thousands
separator. Why doesn't this code use locale ?
* src/format.c (format_value) : better support for ranges, attempt to
work around problem of a thousands seperator in a date format.
* src/cell-draw.c (cell_draw) : Fix potential for infinite loop
with HALIGN_FILL.
* src/print-cell.c (print_cell_text) : Ditto.
* src/parser.y (make_string_return) : A string of the form "..." is
a string, don't try to parse it as a number.
* src/pattern-selector.[ch] : pattern_selector_select made static. In
preparation for different approach.
1999-07-19 Andreas Voegele <andreas.voegele@gmx.de>
* src/parser.y (gnumeric_unsafe_expr_parser): Use the locale to
......@@ -63,6 +98,9 @@
* src/expr-name.[ch] (expr_name_add, expr_name_lookup) : Const.
* src/parser.y (make_string_return) : Handle special case of "" avoid
turning it into a number.
1999-07-13 Michael Meeks <michael@edenproject.org>
* src/Makefile.am (GNUMERIC_BASE_SOURCES): add summary.[ch]
......
......@@ -52,29 +52,6 @@ gcd (int a, int b)
return a;
}
static float_t
gpow10 (int n)
{
float_t res = 1.0;
float_t p;
const int maxn = 300;
if (n >= 0) {
p = 10.0;
n = (n > maxn) ? maxn : n;
} else {
p = 0.1;
/* Note carefully that we avoid overflow. */
n = (n < -maxn) ? maxn : -n;
}
while (n > 0) {
if (n & 1) res *= p;
p *= p;
n >>= 1;
}
return res;
}
typedef struct {
GSList *list;
......@@ -2654,6 +2631,14 @@ void math_functions_init()
function_add_args (cat, "tanh", "f", "number", &help_tanh, gnumeric_tanh);
function_add_args (cat, "trunc", "f|f", "number,digits", &help_trunc, gnumeric_trunc);
function_add_args (cat, "pi", "", "", &help_pi, gnumeric_pi);
function_add_args (cat, "mmult", "AA", "array1,array2", &help_mmult, gnumeric_mmult);
function_add_args (cat, "transpose","A", "array1", &help_transpose, gnumeric_transpose);
function_add_args (cat, "mmult", "AA", "array1,array2",
&help_mmult, gnumeric_mmult);
function_add_args (cat, "transpose","A", "array",
&help_transpose, gnumeric_transpose);
#if 0
function_add_args (cat, "mdeterm","A", "array",
&help_mdeterm, gnumeric_mdeterm);
function_add_args (cat, "minverse","A", "array",
&help_minverse, gnumeric_minverse);
#endif
}
......@@ -12,6 +12,7 @@
#include "gnumeric.h"
#include "utils.h"
#include "func.h"
#include "format.h"
#include "number-match.h"
static char *help_char = {
......@@ -582,6 +583,7 @@ gnumeric_replace (FunctionEvalInfo *ei, Value **argv)
gchar *s;
gint start, num, oldlen, newlen;
/* Why do we need this ? */
if (argv[0]->type != VALUE_STRING ||
argv[1]->type != VALUE_INTEGER ||
argv[2]->type != VALUE_INTEGER ||
......@@ -592,9 +594,11 @@ gnumeric_replace (FunctionEvalInfo *ei, Value **argv)
num = value_get_as_int (argv[2]);
oldlen = strlen(argv[0]->v.str->str);
if (start <= 0 || num <= 0 || --start + num > oldlen )
if (start <= 0 || num <= 0)
return function_error (ei, _("Invalid arguments"));
if (--start + num > oldlen)
num = oldlen - start;
newlen = strlen (argv [3]->v.str->str);
s = g_new (gchar, 1 + newlen + oldlen - num);
......@@ -612,6 +616,8 @@ gnumeric_replace (FunctionEvalInfo *ei, Value **argv)
return v;
}
/*****************************************************************/
static char *help_t = {
N_("@FUNCTION=T\n"
"@SYNTAX=T(value)\n"
......@@ -630,6 +636,60 @@ gnumeric_t (FunctionEvalInfo *ei, Value **argv)
return value_new_string ("");
}
/*****************************************************************/
static char *help_text = {
N_("@FUNCTION=TEXT\n"
"@SYNTAX=TEXT(value,format_text)\n"
"@DESCRIPTION="
"Returns @value as a string with the specified format."
"\n"
"@SEEALSO=DOLLAR")
};
static Value *
gnumeric_text (FunctionEvalInfo *ei, Value **args)
{
StyleFormat *format = style_format_new (args[1]->v.str->str);
Value *res, *tmp = NULL;
Value const *arg = args[0];
gboolean ok = FALSE;
/* FIXME FIXME FIXME : All this should really be moved
* into value_get_as_float
*/
if (arg->type == VALUE_CELLRANGE || arg->type == VALUE_ARRAY) {
if (value_area_get_height (&ei->pos, arg) == 1 &&
value_area_get_width (&ei->pos, arg) == 1)
arg = value_area_fetch_x_y (&ei->pos, arg, 0, 0);
}
if (arg->type == VALUE_STRING) {
char *format = NULL;
float_t num = 0.;
if ((ok = format_match (arg->v.str->str, &num, &format)))
tmp = value_new_float (num);
} else
ok = VALUE_IS_NUMBER(arg);
if (ok)
{
char const *str = format_value (format,
(tmp != NULL) ? tmp : arg,
NULL);
res = value_new_string (str);
} else
res = function_error (ei, _("Type mismatch"));
if (tmp != NULL)
value_release (tmp);
style_format_unref (format);
return res;
}
/*****************************************************************/
static char *help_trim = {
N_("@FUNCTION=TRIM\n"
"@SYNTAX=TRIM(text)\n"
......@@ -1142,15 +1202,12 @@ string_functions_init ()
&help_substitute, gnumeric_substitute);
function_add_args (cat, "t", "?", "value",
&help_t, gnumeric_t);
function_add_args (cat, "text", "?s", "value,format_text",
&help_text, gnumeric_text);
function_add_args (cat, "trim", "s", "text",
&help_trim, gnumeric_trim);
function_add_args (cat, "upper", "s", "text",
&help_upper, gnumeric_upper);
function_add_args (cat, "value", "?", "text",
&help_value, gnumeric_value);
/* Missing:
* TEXT(number,format) formats number
*/
}
......@@ -316,7 +316,7 @@ cell_draw (Cell *cell, SheetView *sheet_view, GdkGC *gc, GdkDrawable *drawable,
gdk_draw_text (drawable, font, gc, 1 + x1 + x, text_base, text, strlen (text));
x1 += len;
total += len;
} while (halign == HALIGN_FILL && total < rect.width);
} while (halign == HALIGN_FILL && total < rect.width && len >0);
}
return end_col - start_col + 1;
......
......@@ -8,6 +8,7 @@
#include <gnome.h>
#include <math.h>
#include <string.h>
#include <locale.h>
#include "gnumeric.h"
#include "expr.h"
#include "eval.h"
......@@ -502,7 +503,7 @@ value_get_as_string (const Value *value)
{
struct lconv *locinfo;
separator = ",";
char const * separator = ",";
locinfo = localeconv ();
if (locinfo->decimal_point &&
locinfo->decimal_point [0] == ',' &&
......@@ -955,7 +956,7 @@ value_area_get_x_y (EvalPosition const *ep, Value const *v, guint x, guint y)
if (v->type == VALUE_ARRAY){
g_return_val_if_fail (x < v->v.array.x &&
y < v->v.array.y,
value_zero);
NULL);
return v->v.array.vals [x][y];
} else {
CellRef const * const a = &v->v.cell_range.cell_a;
......@@ -997,8 +998,8 @@ value_area_get_x_y (EvalPosition const *ep, Value const *v, guint x, guint y)
* This should return NA but some of the math functions may
* rely on this for now.
*/
g_return_val_if_fail (a_row<=b_row, value_zero);
g_return_val_if_fail (a_col<=b_col, value_zero);
g_return_val_if_fail (a_row<=b_row, NULL);
g_return_val_if_fail (a_col<=b_col, NULL);
sheet = a->sheet?a->sheet:ep->sheet;
g_return_val_if_fail (sheet != NULL, NULL);
......@@ -1282,7 +1283,7 @@ typedef enum {
IS_EQUAL,
IS_LESS,
IS_GREATER,
TYPE_ERROR
TYPE_MISMATCH
} compare_t;
static compare_t
......@@ -1307,12 +1308,27 @@ compare_float_float (float_t a, float_t b)
return IS_GREATER;
}
static gboolean
is_null_string (Value const *v)
{
return v != NULL && v->type == VALUE_STRING && v->v.str->str[0] == '\0';
}
/*
* Compares two (Value *) and returns one of compare_t
*/
static compare_t
compare (const Value *a, const Value *b)
{
/* Handle trivial and double NULL case */
if (a == b)
return IS_EQUAL;
if (a == NULL)
return is_null_string (b) ? IS_EQUAL : TYPE_MISMATCH;
if (b == NULL)
return is_null_string (a) ? IS_EQUAL : TYPE_MISMATCH;
if (a->type == VALUE_INTEGER){
int f;
......@@ -1328,7 +1344,7 @@ compare (const Value *a, const Value *b)
return compare_float_float (a->v.v_int, f);
default:
return TYPE_ERROR;
return TYPE_MISMATCH;
}
}
......@@ -1347,7 +1363,7 @@ compare (const Value *a, const Value *b)
return compare_float_float (a->v.v_float, f);
default:
return TYPE_ERROR;
return TYPE_MISMATCH;
}
}
......@@ -1363,7 +1379,7 @@ compare (const Value *a, const Value *b)
return IS_LESS;
}
return TYPE_ERROR;
return TYPE_MISMATCH;
}
/*
......@@ -1426,21 +1442,26 @@ eval_expr (FunctionEvalInfo *s, ExprTree *tree)
int comp;
a = eval_expr (s, tree->u.binary.value_a);
if (!a)
return NULL;
b = eval_expr (s, tree->u.binary.value_b);
if (!b) {
value_release (a);
return NULL;
}
comp = compare (a, b);
value_release (a);
value_release (b);
if (comp == TYPE_ERROR){
error_message_set (s->error, _("Type error"));
if (a != NULL)
value_release (a);
if (b != NULL)
value_release (b);
if (comp == TYPE_MISMATCH){
/* TODO TODO TODO : Make error more informative
* regarding what is comparing to what
*/
/* For equality comparisons even errors are ok */
if (tree->oper == OPER_EQUAL)
return value_new_bool (FALSE);
if (tree->oper == OPER_NOT_EQUAL)
return value_new_bool (TRUE);
error_message_set (s->error, _("Type Mismatch"));
return NULL;
}
......@@ -1457,16 +1478,16 @@ eval_expr (FunctionEvalInfo *s, ExprTree *tree)
res = value_new_bool (comp == IS_LESS);
break;
case OPER_LTE:
res = value_new_bool (comp == IS_EQUAL || comp == IS_LESS);
case OPER_NOT_EQUAL:
res = value_new_bool (comp != IS_EQUAL);
break;
case OPER_GTE:
res = value_new_bool (comp == IS_EQUAL || comp == IS_GREATER);
case OPER_LTE:
res = value_new_bool (comp != IS_GREATER);
break;
case OPER_NOT_EQUAL:
res = value_new_bool (comp != IS_EQUAL);
case OPER_GTE:
res = value_new_bool (comp != IS_LESS);
break;
default:
......@@ -1726,13 +1747,15 @@ eval_expr (FunctionEvalInfo *s, ExprTree *tree)
EvalPosition tmp_ep = s->pos;
tmp_ep.eval_col -= x;
tmp_ep.eval_row -= y;
a = (Value *)value_area_fetch_x_y (
&tmp_ep,
a, x, y);
a = (Value *)value_area_get_x_y (
&tmp_ep, a, x, y);
} else
return function_error (s, gnumeric_err_NA);
} else if (x >= 1 || y >= 1)
return function_error (s, gnumeric_err_NA);
if (a == NULL)
return NULL;
return value_duplicate (a);
}
}
......
......@@ -52,29 +52,6 @@ gcd (int a, int b)
return a;
}
static float_t
gpow10 (int n)
{
float_t res = 1.0;
float_t p;
const int maxn = 300;
if (n >= 0) {
p = 10.0;
n = (n > maxn) ? maxn : n;
} else {
p = 0.1;
/* Note carefully that we avoid overflow. */
n = (n < -maxn) ? maxn : -n;
}
while (n > 0) {
if (n & 1) res *= p;
p *= p;
n >>= 1;
}
return res;
}
typedef struct {
GSList *list;
......@@ -2654,6 +2631,14 @@ void math_functions_init()
function_add_args (cat, "tanh", "f", "number", &help_tanh, gnumeric_tanh);
function_add_args (cat, "trunc", "f|f", "number,digits", &help_trunc, gnumeric_trunc);
function_add_args (cat, "pi", "", "", &help_pi, gnumeric_pi);
function_add_args (cat, "mmult", "AA", "array1,array2", &help_mmult, gnumeric_mmult);
function_add_args (cat, "transpose","A", "array1", &help_transpose, gnumeric_transpose);
function_add_args (cat, "mmult", "AA", "array1,array2",
&help_mmult, gnumeric_mmult);
function_add_args (cat, "transpose","A", "array",
&help_transpose, gnumeric_transpose);
#if 0
function_add_args (cat, "mdeterm","A", "array",
&help_mdeterm, gnumeric_mdeterm);
function_add_args (cat, "minverse","A", "array",
&help_minverse, gnumeric_minverse);
#endif
}
......@@ -12,6 +12,7 @@
#include "gnumeric.h"
#include "utils.h"
#include "func.h"
#include "format.h"
#include "number-match.h"
static char *help_char = {
......@@ -582,6 +583,7 @@ gnumeric_replace (FunctionEvalInfo *ei, Value **argv)
gchar *s;
gint start, num, oldlen, newlen;
/* Why do we need this ? */
if (argv[0]->type != VALUE_STRING ||
argv[1]->type != VALUE_INTEGER ||
argv[2]->type != VALUE_INTEGER ||
......@@ -592,9 +594,11 @@ gnumeric_replace (FunctionEvalInfo *ei, Value **argv)
num = value_get_as_int (argv[2]);
oldlen = strlen(argv[0]->v.str->str);
if (start <= 0 || num <= 0 || --start + num > oldlen )
if (start <= 0 || num <= 0)
return function_error (ei, _("Invalid arguments"));
if (--start + num > oldlen)
num = oldlen - start;
newlen = strlen (argv [3]->v.str->str);
s = g_new (gchar, 1 + newlen + oldlen - num);
......@@ -612,6 +616,8 @@ gnumeric_replace (FunctionEvalInfo *ei, Value **argv)
return v;
}
/*****************************************************************/
static char *help_t = {
N_("@FUNCTION=T\n"
"@SYNTAX=T(value)\n"
......@@ -630,6 +636,60 @@ gnumeric_t (FunctionEvalInfo *ei, Value **argv)
return value_new_string ("");
}
/*****************************************************************/
static char *help_text = {
N_("@FUNCTION=TEXT\n"
"@SYNTAX=TEXT(value,format_text)\n"
"@DESCRIPTION="
"Returns @value as a string with the specified format."
"\n"
"@SEEALSO=DOLLAR")
};
static Value *
gnumeric_text (FunctionEvalInfo *ei, Value **args)
{
StyleFormat *format = style_format_new (args[1]->v.str->str);
Value *res, *tmp = NULL;
Value const *arg = args[0];
gboolean ok = FALSE;
/* FIXME FIXME FIXME : All this should really be moved
* into value_get_as_float
*/
if (arg->type == VALUE_CELLRANGE || arg->type == VALUE_ARRAY) {
if (value_area_get_height (&ei->pos, arg) == 1 &&
value_area_get_width (&ei->pos, arg) == 1)
arg = value_area_fetch_x_y (&ei->pos, arg, 0, 0);
}
if (arg->type == VALUE_STRING) {
char *format = NULL;
float_t num = 0.;
if ((ok = format_match (arg->v.str->str, &num, &format)))
tmp = value_new_float (num);
} else
ok = VALUE_IS_NUMBER(arg);
if (ok)
{
char const *str = format_value (format,
(tmp != NULL) ? tmp : arg,
NULL);
res = value_new_string (str);
} else
res = function_error (ei, _("Type mismatch"));
if (tmp != NULL)
value_release (tmp);
style_format_unref (format);
return res;
}
/*****************************************************************/
static char *help_trim = {
N_("@FUNCTION=TRIM\n"
"@SYNTAX=TRIM(text)\n"
......@@ -1142,15 +1202,12 @@ string_functions_init ()
&help_substitute, gnumeric_substitute);
function_add_args (cat, "t", "?", "value",
&help_t, gnumeric_t);
function_add_args (cat, "text", "?s", "value,format_text",
&help_text, gnumeric_text);
function_add_args (cat, "trim", "s", "text",
&help_trim, gnumeric_trim);
function_add_args (cat, "upper", "s", "text",
&help_upper, gnumeric_upper);
function_add_args (cat, "value", "?", "text",
&help_value, gnumeric_value);
/* Missing:
* TEXT(number,format) formats number
*/
}
......@@ -740,7 +740,13 @@ format_number (gdouble number, const StyleFormatEntry *style_format_entry)
}
case CHAR_THOUSAND: {
info.comma_separator_seen = TRUE;
if (!can_render_number) {
char c = lc->thousands_sep [0];
if (c == 0)
c = ',';
g_string_append_c (result, c);
} else
info.comma_separator_seen = TRUE;
break;
}
......@@ -1026,7 +1032,10 @@ format_value (StyleFormat *format, const Value *value, StyleColor **color)
}
/* FIXME: what about translated "General"? */
/* Use top left corner of an array result */
/*
* Use top left corner of an array result.
* This wont work for ranges because we dont't have a location
*/
if (value->type == VALUE_ARRAY)
value = value_area_fetch_x_y (NULL, value, 0, 0);
......
......@@ -52,29 +52,6 @@ gcd (int a, int b)
return a;
}
static float_t
gpow10 (int n)
{
float_t res = 1.0;
float_t p;
const int maxn = 300;
if (n >= 0) {
p = 10.0;
n = (n > maxn) ? maxn : n;
} else {
p = 0.1;
/* Note carefully that we avoid overflow. */
n = (n < -maxn) ? maxn : -n;
}
while (n > 0) {
if (n & 1) res *= p;
p *= p;
n >>= 1;
}
return res;
}
typedef struct {
GSList *list;
......@@ -2654,6 +2631,14 @@ void math_functions_init()
function_add_args (cat, "tanh", "f", "number", &help_tanh, gnumeric_tanh);
function_add_args (cat, "trunc", "f|f", "number,digits", &help_trunc, gnumeric_trunc);
function_add_args (cat, "pi", "", "", &help_pi, gnumeric_pi);
function_add_args (cat, "mmult", "AA", "array1,array2", &help_mmult, gnumeric_mmult);
function_add_args (cat, "transpose","A", "array1", &help_transpose, gnumeric_transpose);
function_add_args (cat, "mmult", "AA", "array1,array2",
&help_mmult, gnumeric_mmult);
function_add_args (cat, "transpose","A", "array",
&help_transpose, gnumeric_transpose);
#if 0
function_add_args (cat, "mdeterm","A", "array",
&help_mdeterm, gnumeric_mdeterm);
function_add_args (cat, "minverse","A", "array",
&help_minverse, gnumeric_minverse);
#endif
}
......@@ -12,6 +12,7 @@
#include "gnumeric.h"
#include "utils.h"
#include "func.h"
#include "format.h"
#include "number-match.h"
static char *help_char = {
......@@ -582,6 +583,7 @@ gnumeric_replace (FunctionEvalInfo *ei, Value **argv)
gchar *s;
gint start, num, oldlen, newlen;
/* Why do we need this ? */
if (argv[0]->type != VALUE_STRING ||
argv[1]->type != VALUE_INTEGER ||
argv[2]->type != VALUE_INTEGER ||
......@@ -592,9 +594,11 @@ gnumeric_replace (FunctionEvalInfo *ei, Value **argv)
num = value_get_as_int (argv[2]);
oldlen = strlen(argv[0]->v.str->str);
if (start <= 0 || num <= 0 || --start + num > oldlen )
if (start <= 0 || num <= 0)
return function_error (ei, _("Invalid arguments"));
if (--start + num > oldlen)
num = oldlen - start;
newlen = strlen (argv [3]->v.str->str);
s = g_new (gchar, 1 + newlen + oldlen - num);
......@@ -612,6 +616,8 @@ gnumeric_replace (FunctionEvalInfo *ei, Value **argv)
return v;
}
/*****************************************************************/
static char *help_t = {
N_("@FUNCTION=T\n"
"@SYNTAX=T(value)\n"
......@@ -630,6 +636,60 @@ gnumeric_t (FunctionEvalInfo *ei, Value **argv)
return value_new_string ("");
}
/*****************************************************************/
static char *help_text = {
N_("@FUNCTION=TEXT\n"
"@SYNTAX=TEXT(value,format_text)\n"
"@DESCRIPTION="
"Returns @value as a string with the specified format."
"\n"
"@SEEALSO=DOLLAR")
};
static Value *
gnumeric_text (FunctionEvalInfo *ei, Value **args)
{