Commit 78d888e3 authored by Almer S. Tigelaar's avatar Almer S. Tigelaar Committed by Almer S. Tigelaar

Give focus to the edit line when an error is encountered. Don't store the

2001-04-23  Almer S. Tigelaar  <almer@gnome.org>

	* src/workbook-edit.c (workbook_finish_editing): Give focus
	to the edit line when an error is encountered.
	* src/workbook-control-gui.c
	(wbcg_close_control) : Don't store the partially entered expression
	when we are going to close.
	(cb_file_quit) : Idem.
	(cb_notebook_switch_page) : Idem, for switching between tabs
	when we are _not_ in a subexpression.

	* src/parser.y : Correct off-by-one glitches and strtod exponent
	out of range error problem.

	* src/expr.[ch] (expr_parse_string): Use a ParseError struct
	instead of an error string.

	* src/commands.c (cmd_area_set_text_redo): Use expr_parse_string
	in the newly corrected fashion.
	* src/expr-name.c (expr_name_create): Idem, require a ParseError
	struct to be passed instead of a char** aswell.
	* src/parse-util.c (parse_text_value_or_expr): Idem.
	* src/sheet-object-widget.c (cb_checkbox_config_clicked): Idem.
	* src/test-parser.c (main): Idem.
	* src/xml-io.c (xml_cell_set_array_expr): Idem.

	* src/sheet.c (sheet_clone_names): Use expr_name_create which now
	uses ParseError instead of char **.
	* src/xml-io.c (xml_read_names): Idem.

2001-04-23  Almer S. Tigelaar  <almer@gnome.org>

	* dialog-define-names.c (cb_name_guru_add):
	Correct use of expr_parse_string.
parent 59400947
2001-04-23 Almer S. Tigelaar <almer@gnome.org>
* src/workbook-edit.c (workbook_finish_editing): Give focus
to the edit line when an error is encountered.
* src/workbook-control-gui.c
(wbcg_close_control) : Don't store the partially entered expression
when we are going to close.
(cb_file_quit) : Idem.
(cb_notebook_switch_page) : Idem, for switching between tabs
when we are _not_ in a subexpression.
* src/parser.y : Correct off-by-one glitches and strtod exponent
out of range error problem.
* src/expr.[ch] (expr_parse_string): Use a ParseError struct
instead of an error string.
* src/commands.c (cmd_area_set_text_redo): Use expr_parse_string
in the newly corrected fashion.
* src/expr-name.c (expr_name_create): Idem, require a ParseError
struct to be passed instead of a char** aswell.
* src/parse-util.c (parse_text_value_or_expr): Idem.
* src/sheet-object-widget.c (cb_checkbox_config_clicked): Idem.
* src/test-parser.c (main): Idem.
* src/xml-io.c (xml_cell_set_array_expr): Idem.
* src/sheet.c (sheet_clone_names): Use expr_name_create which now
uses ParseError instead of char **.
* src/xml-io.c (xml_read_names): Idem.
2001-04-23 Morten Welinder <terra@diku.dk>
* src/GNOME_Gnumeric.xml: Define a few more outline commands, just
......
Gnumeric 0.65
Almer:
* Fix a variety of bugs
* Improve parser error messages
Chema:
* GNUMERIC_ENABLE_XL_OVERWRITE
......
2001-04-23 Almer S. Tigelaar <almer@gnome.org>
* src/workbook-edit.c (workbook_finish_editing): Give focus
to the edit line when an error is encountered.
* src/workbook-control-gui.c
(wbcg_close_control) : Don't store the partially entered expression
when we are going to close.
(cb_file_quit) : Idem.
(cb_notebook_switch_page) : Idem, for switching between tabs
when we are _not_ in a subexpression.
* src/parser.y : Correct off-by-one glitches and strtod exponent
out of range error problem.
* src/expr.[ch] (expr_parse_string): Use a ParseError struct
instead of an error string.
* src/commands.c (cmd_area_set_text_redo): Use expr_parse_string
in the newly corrected fashion.
* src/expr-name.c (expr_name_create): Idem, require a ParseError
struct to be passed instead of a char** aswell.
* src/parse-util.c (parse_text_value_or_expr): Idem.
* src/sheet-object-widget.c (cb_checkbox_config_clicked): Idem.
* src/test-parser.c (main): Idem.
* src/xml-io.c (xml_cell_set_array_expr): Idem.
* src/sheet.c (sheet_clone_names): Use expr_name_create which now
uses ParseError instead of char **.
* src/xml-io.c (xml_read_names): Idem.
2001-04-23 Morten Welinder <terra@diku.dk>
* src/GNOME_Gnumeric.xml: Define a few more outline commands, just
......
2001-04-23 Almer S. Tigelaar <almer@gnome.org>
* src/workbook-edit.c (workbook_finish_editing): Give focus
to the edit line when an error is encountered.
* src/workbook-control-gui.c
(wbcg_close_control) : Don't store the partially entered expression
when we are going to close.
(cb_file_quit) : Idem.
(cb_notebook_switch_page) : Idem, for switching between tabs
when we are _not_ in a subexpression.
* src/parser.y : Correct off-by-one glitches and strtod exponent
out of range error problem.
* src/expr.[ch] (expr_parse_string): Use a ParseError struct
instead of an error string.
* src/commands.c (cmd_area_set_text_redo): Use expr_parse_string
in the newly corrected fashion.
* src/expr-name.c (expr_name_create): Idem, require a ParseError
struct to be passed instead of a char** aswell.
* src/parse-util.c (parse_text_value_or_expr): Idem.
* src/sheet-object-widget.c (cb_checkbox_config_clicked): Idem.
* src/test-parser.c (main): Idem.
* src/xml-io.c (xml_cell_set_array_expr): Idem.
* src/sheet.c (sheet_clone_names): Use expr_name_create which now
uses ParseError instead of char **.
* src/xml-io.c (xml_read_names): Idem.
2001-04-23 Morten Welinder <terra@diku.dk>
* src/GNOME_Gnumeric.xml: Define a few more outline commands, just
......
2001-04-23 Almer S. Tigelaar <almer@gnome.org>
* src/workbook-edit.c (workbook_finish_editing): Give focus
to the edit line when an error is encountered.
* src/workbook-control-gui.c
(wbcg_close_control) : Don't store the partially entered expression
when we are going to close.
(cb_file_quit) : Idem.
(cb_notebook_switch_page) : Idem, for switching between tabs
when we are _not_ in a subexpression.
* src/parser.y : Correct off-by-one glitches and strtod exponent
out of range error problem.
* src/expr.[ch] (expr_parse_string): Use a ParseError struct
instead of an error string.
* src/commands.c (cmd_area_set_text_redo): Use expr_parse_string
in the newly corrected fashion.
* src/expr-name.c (expr_name_create): Idem, require a ParseError
struct to be passed instead of a char** aswell.
* src/parse-util.c (parse_text_value_or_expr): Idem.
* src/sheet-object-widget.c (cb_checkbox_config_clicked): Idem.
* src/test-parser.c (main): Idem.
* src/xml-io.c (xml_cell_set_array_expr): Idem.
* src/sheet.c (sheet_clone_names): Use expr_name_create which now
uses ParseError instead of char **.
* src/xml-io.c (xml_read_names): Idem.
2001-04-23 Morten Welinder <terra@diku.dk>
* src/GNOME_Gnumeric.xml: Define a few more outline commands, just
......
2001-04-23 Almer S. Tigelaar <almer@gnome.org>
* src/workbook-edit.c (workbook_finish_editing): Give focus
to the edit line when an error is encountered.
* src/workbook-control-gui.c
(wbcg_close_control) : Don't store the partially entered expression
when we are going to close.
(cb_file_quit) : Idem.
(cb_notebook_switch_page) : Idem, for switching between tabs
when we are _not_ in a subexpression.
* src/parser.y : Correct off-by-one glitches and strtod exponent
out of range error problem.
* src/expr.[ch] (expr_parse_string): Use a ParseError struct
instead of an error string.
* src/commands.c (cmd_area_set_text_redo): Use expr_parse_string
in the newly corrected fashion.
* src/expr-name.c (expr_name_create): Idem, require a ParseError
struct to be passed instead of a char** aswell.
* src/parse-util.c (parse_text_value_or_expr): Idem.
* src/sheet-object-widget.c (cb_checkbox_config_clicked): Idem.
* src/test-parser.c (main): Idem.
* src/xml-io.c (xml_cell_set_array_expr): Idem.
* src/sheet.c (sheet_clone_names): Use expr_name_create which now
uses ParseError instead of char **.
* src/xml-io.c (xml_read_names): Idem.
2001-04-23 Morten Welinder <terra@diku.dk>
* src/GNOME_Gnumeric.xml: Define a few more outline commands, just
......
2001-04-20 Almer S. Tigelaar <almer@gnome.org>
* xml-sax-read.c (xml_cell_set_array_expr): Correct
for newly updated expr_parse_string function.
2001-04-18 Jody Goldberg <jgoldberg@home.com>
* xml-sax-read.c : s/xml2/xmlSax/ to correspond with naming
......
......@@ -921,13 +921,12 @@ static void
xml_cell_set_array_expr (Cell *cell, char const *text,
int const cols, int const rows)
{
char *error_string = NULL;
ParsePos pp;
ExprTree * expr;
expr = expr_parse_string (text,
parse_pos_init_cell (&pp, cell),
NULL, &error_string);
NULL, NULL);
g_return_if_fail (expr != NULL);
cell_set_array_formula (cell->base.sheet,
......
......@@ -696,11 +696,10 @@ cmd_area_set_text_redo (GnumericCommand *cmd, WorkbookControl *wbc)
l = me->selection;
start = gnumeric_char_start_expr_p (me->text);
if (start != NULL && me->as_array && l != NULL && l->next == NULL) {
char *error_string = NULL;
ParsePos pp;
expr = expr_parse_string (start,
parse_pos_init_evalpos (&pp, &me->pos),
NULL, &error_string);
NULL, NULL);
if (expr == NULL)
return TRUE;
......
2001-04-23 Almer S. Tigelaar <almer@gnome.org>
* dialog-define-names.c (cb_name_guru_add):
Correct use of expr_parse_string.
2001-04-19 Jody Goldberg <jgoldberg@home.com>
* dialog-stf-export-sheet-page.c (stf_export_dialog_sheet_page_init) :
......
......@@ -433,6 +433,7 @@ cb_name_guru_add (NameGuruState *state)
{
NamedExpression *expr_name;
ParsePos pos, *pp;
ParseError perr;
ExprTree *expr;
char const *name, *expr_text, *tmp;
gchar *error;
......@@ -457,11 +458,11 @@ cb_name_guru_add (NameGuruState *state)
if (NULL != (tmp = gnumeric_char_start_expr_p (expr_text)))
expr_text = tmp;
expr = expr_parse_string (expr_text, pp, NULL, &error);
expr = expr_parse_string (expr_text, pp, NULL, &perr);
/* If the expression is invalid */
if (expr == NULL) {
gnumeric_notice (state->wbcg, GNOME_MESSAGE_BOX_ERROR, error);
gnumeric_notice (state->wbcg, GNOME_MESSAGE_BOX_ERROR, perr.message);
gtk_widget_grab_focus (GTK_WIDGET (state->expr_text));
return FALSE;
} else if (expr_name) {
......
......@@ -200,17 +200,22 @@ expr_name_add (Workbook *wb, Sheet *sheet, const char *name,
**/
NamedExpression *
expr_name_create (Workbook *wb, Sheet *sheet, const char *name,
const char *value, char **error_msg)
const char *value, ParseError *error)
{
ExprTree *tree;
ParsePos pos, *pp;
pp = parse_pos_init (&pos, wb, sheet, 0, 0);
tree = expr_parse_string (value, pp, NULL, error_msg);
tree = expr_parse_string (value, pp, NULL, error);
if (!tree)
return NULL;
return expr_name_add (wb, sheet, name, tree, error_msg);
/*
* We know there has been no parse error, but set the
* use the message part of the struct to pass a name
* creation error back to the calling routine
*/
return expr_name_add (wb, sheet, name, tree, &error->message);
}
static void
......
......@@ -3,6 +3,7 @@
#include "gnumeric.h"
#include "expr.h"
#include "parse-util.h"
/* Initialise builtins */
void expr_name_init (void);
......@@ -13,7 +14,7 @@ NamedExpression *expr_name_add (Workbook *wb, Sheet *sheet, const char *n
/* Convenience function to parse the name */
NamedExpression *expr_name_create (Workbook *wb, Sheet *sheet, const char *name,
const char *value, char **error_msg);
const char *value, ParseError *error);
/* Lookup - use sparingly */
NamedExpression *expr_name_lookup (const ParsePos *pos, const char *name);
......
......@@ -183,24 +183,32 @@ expr_tree_get_const_str (ExprTree const *expr)
return expr->constant.value->v_str.val->str;
}
/**
* expr_parse_string:
*
* Parse a string. if @error is non-null it will be assumed that the
* caller has passed a pointer to a ParseError struct AND that it will
* take responsibility for freeing that struct and it's contents.
* with parse_error_free.
**/
ExprTree *
expr_parse_string (char const *expr_text, ParsePos const *pp,
StyleFormat **desired_format, char **error_msg)
StyleFormat **desired_format, ParseError *error)
{
ExprTree *tree;
ParseError perr;
ParseError *perr = error;
g_return_val_if_fail (expr_text != NULL, NULL);
if (error == NULL)
perr = g_new0 (ParseError, 1);
tree = gnumeric_expr_parser (expr_text, pp, TRUE, FALSE, desired_format,
parse_error_init (&perr));
parse_error_init (perr));
if (error == NULL)
parse_error_free (perr);
/* TODO : use perr when we populate it */
if (tree == NULL)
*error_msg = perr.message;
else
*error_msg = NULL;
parse_error_free (&perr);
return tree;
}
......
......@@ -3,6 +3,7 @@
#include "gnumeric.h"
#include "numbers.h"
#include "parse-util.h"
#include "position.h"
/* Warning: if you add something here, see do_expr_decode_tree ! */
......@@ -141,7 +142,7 @@ struct _NamedExpression {
};
ExprTree *expr_parse_string (char const *expr, ParsePos const *pp,
StyleFormat **desired_format, char **error_msg);
StyleFormat **desired_format, ParseError *error);
ExprTree *expr_tree_duplicate (ExprTree *expr);
char *expr_tree_as_string (ExprTree const *tree, ParsePos const *fp);
......
......@@ -517,14 +517,12 @@ parse_text_value_or_expr (EvalPos const *pos, char const *text,
if (NULL != expr_start) {
if (*expr_start) {
char *error_msg = _("ERROR");
ParsePos pp;
/* Parse in the supplied eval context */
*expr = expr_parse_string (expr_start,
parse_pos_init_evalpos (&pp, pos),
&desired_format,
&error_msg);
&desired_format, NULL);
/* If the parse fails set the value to be the syntax error */
if (*expr == NULL)
......
......@@ -333,7 +333,7 @@ gnumeric_parse_error (ParserState *state, char *message, int end, int relative_b
g_return_val_if_fail (state->error != NULL, ERROR);
state->error->message = message;
state->error->begin_char = end - relative_begin;
state->error->begin_char = (end - relative_begin);
state->error->end_char = end;
return ERROR;
......@@ -437,7 +437,7 @@ exp: CONSTANT { $$ = $1; }
if (expr_name == NULL) {
int retval = gnumeric_parse_error (
state, g_strdup_printf (_("Expression '%s' does not exist on sheet '%s'"), name, $1->name_quoted),
(state->expr_text - state->expr_backup), strlen (name) - 1);
state->expr_text - state->expr_backup + 1, strlen (name));
unregister_allocation ($2); expr_tree_unref ($2);
return retval;
......@@ -457,7 +457,7 @@ sheetref: string_opt_quote SHEET_SEP {
if (sheet == NULL) {
int retval = gnumeric_parse_error (
state, g_strdup_printf (_("Unknown sheet '%s'"), name),
(state->expr_text - state->expr_backup) - 1, strlen (name) - 1);
state->expr_text - state->expr_backup, strlen (name));
unregister_allocation ($1); expr_tree_unref ($1);
return retval;
......@@ -487,7 +487,7 @@ sheetref: string_opt_quote SHEET_SEP {
if (sheet == NULL) {
int retval = gnumeric_parse_error (
state, g_strdup_printf (_("Unknown sheet '%s'"), sheetname),
(state->expr_text - state->expr_backup) - 1, strlen (sheetname) - 1);
state->expr_text - state->expr_backup, strlen (sheetname));
unregister_allocation ($4); expr_tree_unref ($4);
return retval;
......@@ -579,7 +579,7 @@ array_row: array_exp {
} else {
return gnumeric_parse_error (
state, g_strdup_printf (_("The character %c can not be used to separate array elements"),
state->array_col_separator), (state->expr_text - state->expr_backup), 1);
state->array_col_separator), state->expr_text - state->expr_backup + 1, 1);
}
}
| array_exp '\\' array_row {
......@@ -592,7 +592,7 @@ array_row: array_exp {
/* FIXME: Is this the right error to display? */
return gnumeric_parse_error (
state, g_strdup_printf (_("The character %c can not be used to separate array elements"),
state->array_col_separator), (state->expr_text - state->expr_backup), 1);
state->array_col_separator), state->expr_text - state->expr_backup + 1, 1);
}
}
| { $$ = NULL; }
......@@ -699,9 +699,21 @@ yylex (void)
v = value_new_float ((gnum_float)d);
state->expr_text = end;
} else {
return gnumeric_parse_error (
state, g_strdup (_("The number is out of range")),
state->expr_text - state->expr_backup - 1, end - start);
if (tolower (c) != 'e') {
return gnumeric_parse_error (
state, g_strdup (_("The number is out of range")),
state->expr_text - state->expr_backup, end - start);
} else {
/*
* For an exponent it's hard to highlight
* the right region w/o it turning into an
* ugly hack, for now the cursor is put
* at the end.
*/
return gnumeric_parse_error (
state, g_strdup (_("The number is out of range")),
0, 0);
}
}
} else
g_warning ("%s is not a double, but was expected to be one", start);
......@@ -726,7 +738,7 @@ yylex (void)
if (l == LONG_MIN || l == LONG_MAX) {
return gnumeric_parse_error (
state, g_strdup (_("The number is out of range")),
state->expr_text - state->expr_backup - 1, end - start);
state->expr_text - state->expr_backup, end - start);
}
}
} else
......@@ -758,7 +770,7 @@ yylex (void)
if (!*state->expr_text) {
return gnumeric_parse_error (
state, g_strdup (_("Could not find matching closing quote")),
(p - state->expr_backup), 1);
(p - state->expr_backup) + 1, 1);
}
s = string = (char *) alloca (1 + state->expr_text - p);
......@@ -901,6 +913,18 @@ gnumeric_expr_parser (char const *expr_text, ParsePos const *pos,
#ifndef KEEP_DEALLOCATION_STACK_BETWEEN_CALLS
deallocate_uninit ();
#endif
/*
* If an error has occured we ALWAYS return NULL.
* In some cases the expression tree may have been partially
* built-up before an error occurs. Therefore the pstate.result
* (which is resulting ExprTree) must be freed in case it's non-null
* and an error has occured.
*/
if (pstate.error->message != NULL) {
if (pstate.result)
expr_tree_unref (pstate.result);
return pstate.result;
return NULL;
} else
return pstate.result;
}
......@@ -467,10 +467,9 @@ cb_checkbox_config_clicked (GnomeDialog *dialog, gint button_number,
if (text != NULL && *text) {
ParsePos pp;
char *error_string = NULL;
ExprTree *expr = expr_parse_string (text,
parse_pos_init (&pp, NULL, so->sheet, 0, 0),
NULL, &error_string);
NULL, NULL);
/* FIXME : Should we be more verbose about errors */
if (expr != NULL && expr->any.oper == OPER_VAR)
......
......@@ -3906,13 +3906,14 @@ sheet_clone_names (Sheet const *src, Sheet *dst)
#if 0 /* Feature not implemented, not cloning it yet. */
for (; names; names = names->next) {
NamedExpression *expresion = names->data;
ParseError perr;
gchar *text;
gchar *error;
g_return_if_fail (expresion != NULL);
text = expr_name_value (expresion);
if (!expr_name_create (dst->workbook, dst, expresion->name->str, text, &error))
if (!expr_name_create (dst->workbook, dst, expresion->name->str, text, &perr))
g_warning ("Could not create expression. Sheet.c :%i, Error %s",
__LINE__, error);
__LINE__, perr.message);
parse_error_free (&perr);
}
#endif
g_list_free (names);
......
......@@ -25,14 +25,15 @@ main ()
{
Value *v;
EvalTree *node;
ParseError perr;
int i;
char *error;
for (i = 0; exp [i]; i++){
printf ("Expression: %s; ", exp [i]);
node = expr_parse_string (exp [i], 0, 0, 0, NULL, &error);
node = expr_parse_string (exp [i], 0, 0, 0, NULL, &perr);
if (node == NULL){
printf ("parse error: %s\n", error);
printf ("parse error: %s\n", perr.message);
continue;
}
v = eval_expr (NULL, node, 0, 0, &error);
......
......@@ -1080,8 +1080,8 @@ wbcg_close_control (WorkbookControlGUI *wbcg)
g_return_val_if_fail (IS_WORKBOOK_VIEW (wb_view), TRUE);
g_return_val_if_fail (wb_view->wb_controls != NULL, TRUE);
/* If we were editing when the quit request came in save the edit. */
workbook_finish_editing (wbcg, TRUE);
/* If we were editing when the quit request came in abort the edit. */
workbook_finish_editing (wbcg, FALSE);
/* This is the last control */
if (wb_view->wb_controls->len <= 1) {
......@@ -1196,8 +1196,8 @@ cb_file_quit (GtkWidget *widget, WorkbookControlGUI *wbcg)
return;
}
/* If we were editing when the quit request came in save the edit. */
workbook_finish_editing (wbcg, TRUE);
/* If we were editing when the quit request came in abort the edit. */
workbook_finish_editing (wbcg, FALSE);
/* list is modified during workbook destruction */
workbooks = g_list_copy (application_workbook_list ());
......@@ -3049,7 +3049,7 @@ cb_notebook_switch_page (GtkNotebook *notebook, GtkNotebookPage *page,
/* If we are not at a subexpression boundary then finish editing */
accept = !workbook_editing_expr (wbcg);
if (accept)
workbook_finish_editing (wbcg, TRUE);
workbook_finish_editing (wbcg, FALSE);
}
/* if we are not selecting a range for an expression update */
......
......@@ -106,28 +106,39 @@ workbook_finish_editing (WorkbookControlGUI *wbcg, gboolean accept)
if (expr_txt != NULL) {
ParsePos pp;
ParseError perr;
ExprTree *tree;
parse_pos_init (&pp, wb_control_workbook (wbc), sheet,
sheet->edit_pos.col, sheet->edit_pos.row);
parse_error_init (&perr);
gnumeric_expr_parser (expr_txt, &pp, TRUE, FALSE, NULL, &perr);
/*
* We check to see if any error has occured by querying
* if an error message is set. The return value of
* gnumeric_expr_parser is no good for this purpose
*/
if (perr.message != NULL) {
gtk_entry_select_region (
GTK_ENTRY (workbook_get_entry (wbcg)),
perr.begin_char, perr.end_char);
tree = gnumeric_expr_parser (expr_txt, &pp, TRUE, FALSE, NULL, &perr);
if (!tree) {
/*
*If begin and end char are zero we'll simply
* put the cursor at the end, otherwise we
* select the region indicated.
*/
if (perr.begin_char == 0 && perr.end_char == 0)
gtk_editable_set_position (
GTK_EDITABLE (workbook_get_entry (wbcg)), -1);
else
gtk_entry_select_region (
GTK_ENTRY (workbook_get_entry (wbcg)),
perr.begin_char, perr.end_char);
gnome_error_dialog_parented (perr.message, wbcg->toplevel);
parse_error_free (&perr);
gtk_window_set_focus (GTK_WINDOW (wbcg->toplevel),
GTK_WIDGET (workbook_get_entry (wbcg)));
return FALSE;
} else
} else {
cmd_set_text (wbc, sheet, &sheet->edit_pos, txt);
expr_tree_unref (tree);
}
parse_error_free (&perr);
} else
......
......@@ -865,17 +865,18 @@ xml_read_names (XmlParseContext *ctxt, xmlNodePtr tree, Workbook *wb,
if (!strcmp (bits->name, "name")) {
name = xmlNodeGetContent (bits);
} else {
char *txt;
char *error;
char *txt;
ParseError perr;
g_return_if_fail (name != NULL);
txt = xmlNodeGetContent (bits);