Commit edef82e5 authored by Arturo Espinosa's avatar Arturo Espinosa

Lots of work: parser, symbol management, cell storage, finally some cell



Lots of work: parser, symbol management, cell storage, finally some
cell content rendering, currently it is in debug mode, so you wont see
much.

Miguel
parent 3cdb09ee
......@@ -12,8 +12,10 @@ INCLUDES = \
gnumeric_SOURCES = \
cell.h \
gnumeric-sheet.h \
expr.c \
expr.h \
gnumeric-sheet.c \
gnumeric-sheet.h \
gnumeric.h \
item-bar.c \
item-bar.h \
......@@ -26,10 +28,13 @@ gnumeric_SOURCES = \
item-grid.c \
item-grid.h \
main.c \
parser.y \
sheet.c \
sheet.h \
style.c \
style.h \
symbol.h \
symbol.c \
workbook.c
gnumeric_LDADD = \
......
......@@ -4,23 +4,6 @@
typedef unsigned char ColType;
typedef unsigned short RowType;
typedef enum {
VALUE_STRING,
VALUE_NUMBER
} ValueType;
/*
* We use the GNU Multi-precission library for storing our
* numbers
*/
typedef struct {
ValueType type;
union {
char *string; /* string */
mpf_t number; /* floating point */
} v;
} Value;
typedef struct {
int ref_count;
GdkColor color;
......@@ -41,15 +24,19 @@ typedef struct {
void *data;
} ColRowInfo;
typedef enum {
CELL_COLOR_IS_SET
} CellFlags;
typedef struct {
ColRowInfo *col;
ColRowInfo *row;
/* Text as entered by the user */
char *entered_text;
/* Type of the content and the actual parsed content */
Value *value;
EvalNode *parsed_node;
Style *style;
/* computed versions of the cell contents */
......@@ -57,6 +44,8 @@ typedef struct {
GdkColor color; /* color for the displayed text */
int width; /* Width of text */
int height; /* Height of text */
int flags;
} Cell;
#define CELL_IS_FORMULA(cell) (cell->entered_text [0] == '=')
......
#include <glib.h>
#include <gmp.h>
#include "symbol.h"
#include "expr.h"
char *parser_expr;
char **parser_error_message;
EvalNode *parser_result;
EvalNode *
eval_parse_string (char *expr, int col, int row, char **error_msg)
{
parser_expr = expr;
parser_error_message = error_msg;
yyparse ();
return NULL;
}
void
eval_release_node (EvalNode *node)
{
switch (node->oper){
case OP_CONSTANT:
default:
}
}
#ifndef EXPR_H
#define EXPR_H
typedef enum {
OP_ADD,
OP_SUB,
OP_MULT,
OP_DIV,
OP_EXP,
OP_CONCAT,
OP_FUNCALL,
OP_CONSTANT,
OP_CAST_TO_STRING,
OP_NEG
} Operation;
typedef enum {
VALUE_STRING,
VALUE_NUMBER,
VALUE_CELLRANGE
} ValueType;
/*
* We use the GNU Multi-precission library for storing our
* numbers
*/
typedef struct {
int col;
int row;
} CellRef;
typedef struct {
ValueType type;
union {
struct {
CellRef a;
CellRef b;
} cell;
Symbol *str;
mpf_t number; /* floating point */
} v;
} Value;
struct EvalNode {
Operation oper;
union {
Value *constant;
struct {
Symbol *symbol;
GList *arg_list;
} function;
struct {
struct EvalNode *value_a;
struct EvalNode *value_b;
} binary;
struct EvalNode *value;
} u;
};
typedef struct EvalNode EvalNode;
/* For talking to yyparse */
extern char *parser_expr;
extern char **parser_error_message;
extern EvalNode *parser_result;
EvalNode *eval_parse_string (char *expr, int col, int row, char **error_msg);
void eval_release_node (EvalNode *node);
int yyparse (void);
#endif
......@@ -65,18 +65,18 @@ gnumeric_sheet_accept_pending_output (GnumericSheet *sheet)
g_return_if_fail (sheet != NULL);
g_return_if_fail (GNUMERIC_IS_SHEET (sheet));
cell = sheet_cell_new_with_text (
sheet->sheet, sheet->cursor_col, sheet->cursor_row,
gtk_entry_get_text (GTK_ENTRY (sheet->entry)));
sheet_cell_add (sheet, cell);
if (!sheet->item_editor)
return;
/* Destroy the object */
if (sheet->item_editor){
gtk_object_destroy (GTK_OBJECT (sheet->item_editor));
sheet->item_editor = NULL;
}
cell = sheet_cell_get (sheet->sheet, sheet->cursor_col, sheet->cursor_row);
if (!cell)
cell = sheet_cell_new (sheet->sheet, sheet->cursor_col, sheet->cursor_row);
cell_set_text (cell, gtk_entry_get_text (GTK_ENTRY (sheet->entry)));
gtk_object_destroy (GTK_OBJECT (sheet->item_editor));
sheet->item_editor = NULL;
}
void
......@@ -153,11 +153,9 @@ gnumeric_sheet_move_cursor (GnumericSheet *sheet, int col, int row)
{
ItemCursor *item_cursor = sheet->item_cursor;
gnumeric_sheet_cursor_set (sheet, col, row);
gnumeric_sheet_accept_pending_output (sheet);
sheet_selection_clear (sheet->sheet);
gnumeric_sheet_cursor_set (sheet, col, row);
sheet_selection_clear (sheet->sheet);
item_cursor_set_bounds (item_cursor, col, row, col, row);
gnumeric_sheet_load_cell_val (sheet);
}
......@@ -261,10 +259,14 @@ gnumeric_sheet_key (GtkWidget *widget, GdkEventKey *event)
(*movefn_vertical)(sheet, 1);
break;
case GDK_Return:
gnumeric_sheet_move_cursor (sheet, sheet->cursor_col, sheet->cursor_row);
break;
case GDK_F2:
gtk_window_set_focus (GTK_WINDOW (wb->toplevel), wb->ea_input);
/* fallback */
default:
if (!sheet->item_editor){
if (event->keyval >= 0x20 && event->keyval <= 0xff)
......
......@@ -65,18 +65,18 @@ gnumeric_sheet_accept_pending_output (GnumericSheet *sheet)
g_return_if_fail (sheet != NULL);
g_return_if_fail (GNUMERIC_IS_SHEET (sheet));
cell = sheet_cell_new_with_text (
sheet->sheet, sheet->cursor_col, sheet->cursor_row,
gtk_entry_get_text (GTK_ENTRY (sheet->entry)));
sheet_cell_add (sheet, cell);
if (!sheet->item_editor)
return;
/* Destroy the object */
if (sheet->item_editor){
gtk_object_destroy (GTK_OBJECT (sheet->item_editor));
sheet->item_editor = NULL;
}
cell = sheet_cell_get (sheet->sheet, sheet->cursor_col, sheet->cursor_row);
if (!cell)
cell = sheet_cell_new (sheet->sheet, sheet->cursor_col, sheet->cursor_row);
cell_set_text (cell, gtk_entry_get_text (GTK_ENTRY (sheet->entry)));
gtk_object_destroy (GTK_OBJECT (sheet->item_editor));
sheet->item_editor = NULL;
}
void
......@@ -153,11 +153,9 @@ gnumeric_sheet_move_cursor (GnumericSheet *sheet, int col, int row)
{
ItemCursor *item_cursor = sheet->item_cursor;
gnumeric_sheet_cursor_set (sheet, col, row);
gnumeric_sheet_accept_pending_output (sheet);
sheet_selection_clear (sheet->sheet);
gnumeric_sheet_cursor_set (sheet, col, row);
sheet_selection_clear (sheet->sheet);
item_cursor_set_bounds (item_cursor, col, row, col, row);
gnumeric_sheet_load_cell_val (sheet);
}
......@@ -261,10 +259,14 @@ gnumeric_sheet_key (GtkWidget *widget, GdkEventKey *event)
(*movefn_vertical)(sheet, 1);
break;
case GDK_Return:
gnumeric_sheet_move_cursor (sheet, sheet->cursor_col, sheet->cursor_row);
break;
case GDK_F2:
gtk_window_set_focus (GTK_WINDOW (wb->toplevel), wb->ea_input);
/* fallback */
default:
if (!sheet->item_editor){
if (event->keyval >= 0x20 && event->keyval <= 0xff)
......
#include <gmp.h>
#include "style.h"
#include "symbol.h"
#include "expr.h"
#include "cell.h"
#include "sheet.h"
......@@ -210,7 +210,6 @@ item_cursor_translate (GnomeCanvasItem *item, double dx, double dy)
static gint
item_cursor_event (GnomeCanvasItem *item, GdkEvent *event)
{
printf ("Cursor event\n");
return 0;
}
......@@ -273,6 +272,7 @@ item_cursor_class_init (ItemCursorClass *item_cursor_class)
GTK_ARG_WRITABLE, ARG_ITEM_GRID);
object_class->set_arg = item_cursor_set_arg;
object_class->destroy = item_cursor_destroy;
/* GnomeCanvasItem method overrides */
item_class->realize = item_cursor_realize;
......
......@@ -14,12 +14,6 @@
#include "gnumeric-sheet.h"
#include "item-debug.h"
/* The signals we emit */
enum {
LAST_SIGNAL
};
static guint item_grid_signals [LAST_SIGNAL] = { 0 };
static GnomeCanvasItem *item_grid_parent_class;
/* The arguments we take */
......@@ -63,6 +57,7 @@ item_grid_realize (GnomeCanvasItem *item)
/* Configure the default grid gc */
item_grid->grid_gc = gc = gdk_gc_new (window);
item_grid->fill_gc = gdk_gc_new (window);
item_grid->gc = gdk_gc_new (window);
gdk_gc_set_line_attributes (gc, 1, GDK_LINE_SOLID,
GDK_CAP_PROJECTING, GDK_JOIN_MITER);
......@@ -70,7 +65,8 @@ item_grid_realize (GnomeCanvasItem *item)
/* Allocate the default colors */
item_grid->background = color_alloc (item->canvas, "white");
item_grid->grid_color = color_alloc (item->canvas, "gray60");
item_grid->default_color = color_alloc (item->canvas, "black");
gdk_gc_set_foreground (gc, &item_grid->grid_color);
gdk_gc_set_background (gc, &item_grid->background);
......@@ -159,19 +155,91 @@ item_grid_draw_cell (GdkDrawable *drawable, ItemGrid *item_grid,
{
GnumericSheet *gsheet = GNUMERIC_SHEET (item_grid->sheet->sheet_view);
GnomeCanvas *canvas = GNOME_CANVAS_ITEM (item_grid)->canvas;
GdkGC *black_gc = GTK_WIDGET (canvas)->style->black_gc;
GdkGC *grid_gc = item_grid->grid_gc;
Sheet *sheet = item_grid->sheet;
GdkGC *gc = item_grid->gc;
GdkFont *font;
Cell *cell;
Style *style;
int x_offset, y_offset;
Cell *clip_left, *clip_right;
item_debug_cross (drawable, gc, x1, y1, x1+width, y1+height);
if (sheet_selection_is_cell_selected (item_grid->sheet, col, row)){
/* If cell is selected, draw selection */
if (sheet_selection_is_cell_selected (sheet, col, row)){
GdkGC *black_gc = GTK_WIDGET (canvas)->style->black_gc;
if (!(gsheet->cursor_col == col && gsheet->cursor_row == row))
gdk_draw_rectangle (drawable, black_gc,
TRUE,
gdk_draw_rectangle (drawable, black_gc, TRUE,
x1+1, y1+1, width - 2, height - 2);
}
cell = sheet_cell_get (item_grid->sheet, col, row);
printf ("%s\n", cell);
cell = sheet_cell_get (sheet, col, row);
if (!cell)
return;
/* The offsets where we start drawing the text */
x_offset = y_offset = 0;
/* True if we have a sibling cell in the direction where we paint */
clip_left = NULL;
clip_right = NULL;
style = cell->style;
font = style->font->font;
switch (style->halign){
case HALIGN_GENERAL:
if (col < SHEET_MAX_COLS-1)
clip_right = sheet_cell_get (sheet, col+1, row);
x_offset = 0;
break;
case HALIGN_LEFT:
if (col < SHEET_MAX_COLS-1)
clip_right = sheet_cell_get (sheet, col+1, row);
x_offset = 0;
break;
case HALIGN_RIGHT:
if (col > 0)
clip_left = sheet_cell_get (sheet, col-1, row);
x_offset = cell->col->pixels - cell->width;
break;
case HALIGN_CENTER:
if (col > 0)
clip_left = sheet_cell_get (sheet, col-1, row);
if (col < SHEET_MAX_COLS-1)
clip_right = sheet_cell_get (sheet, col-1, row);
x_offset = (cell->width - cell->col->pixels)/2;
break;
case HALIGN_FILL:
if (col < SHEET_MAX_COLS-1)
clip_right = sheet_cell_get (sheet, col-1, row);
x_offset = 0;
break;
case HALIGN_JUSTIFY:
g_warning ("No horizontal justification supported yet\n");
break;
}
if (cell->flags & CELL_COLOR_IS_SET){
gdk_gc_set_foreground (gc, &cell->color);
} else
gdk_gc_set_foreground (gc, &item_grid->default_color);
gdk_gc_set_foreground (gc, &item_grid->default_color);
printf ("(%d,%d), text: %s\n", col, row, cell->text);
gdk_draw_text (drawable, font, gc, x1, y1, "TEXTO", 5);
/*
x1 + x_offset,
y1 + y_offset,
cell->text, strlen (cell->text));
*/
}
static void
......@@ -179,7 +247,6 @@ item_grid_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int
{
ItemGrid *item_grid = ITEM_GRID (item);
Sheet *sheet = item_grid->sheet;
GnumericSheet *gsheet = GNUMERIC_SHEET (sheet->sheet_view);
GdkGC *grid_gc = item_grid->grid_gc;
int end_x, end_y;
int paint_col, paint_row, max_paint_col, max_paint_row;
......@@ -198,6 +265,7 @@ item_grid_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int
return;
}
max_paint_col = max_paint_row = 0;
paint_col = find_col (item_grid, x, &x_paint);
paint_row = find_row (item_grid, y, &y_paint);
......@@ -242,8 +310,10 @@ item_grid_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int
pd.item_grid = item_grid;
pd.gsheet = GNUMERIC_SHEET (item_grid->sheet->sheet_view);
#if 0
printf ("Painting the (%d,%d)-(%d,%d) region\n",
paint_col, paint_row, max_paint_col, max_paint_row);
#endif
col = paint_col;
for (x_paint = -diff_x; x_paint < end_x; col++){
......@@ -403,6 +473,7 @@ item_grid_class_init (ItemGridClass *item_grid_class)
GTK_ARG_WRITABLE, ARG_SHEET);
object_class->set_arg = item_grid_set_arg;
object_class->destroy = item_grid_destroy;
/* GnomeCanvasItem method overrides */
item_class->realize = item_grid_realize;
......
......@@ -22,9 +22,11 @@ typedef struct {
GdkGC *grid_gc; /* Draw grid gc */
GdkGC *fill_gc; /* Default background fill gc */
GdkGC *gc; /* Color used for the cell */
GdkColor background;
GdkColor grid_color;
GdkColor default_color;
} ItemGrid;
GtkType item_grid_get_type (void);
......
%{
#include <glib.h>
#include <gmp.h>
#include "symbol.h"
#include "expr.h"
#include <ctype.h>
static GList *alloc_list;
static void *alloc_buffer (int size);
static void dump_node (EvalNode *node);
static void register_symbol (Symbol *sym);
static void alloc_clean (void);
static void dump_constant (EvalNode *node);
static int yylex (void);
static int yyerror (char *s);
#define p_new(type) \
((type *) alloc_buffer ((unsigned) sizeof (type)))
%}
%union {
EvalNode *node;
CellRef *cell;
GList *list;
}
%type <node> exp
%type <list> arg_list
%token <node> NUMBER STRING FUNCALL
%left '-' '+' '&'
%left '*' '/'
%left '!'
%right '^'
%%
line: exp { parser_result = $1; dump_node (parser_result); }
| error { alloc_clean (); }
;
exp: NUMBER { $$ = $1 }
| exp '+' exp {
$$ = p_new (EvalNode);
$$->oper = OP_ADD;
$$->u.binary.value_a = $1;
$$->u.binary.value_b = $3;
}
| exp '-' exp {
$$ = p_new (EvalNode);
$$->oper = OP_SUB;
$$->u.binary.value_a = $1;
$$->u.binary.value_b = $3;
}
| exp '*' exp {
$$ = p_new (EvalNode);
$$->oper = OP_MULT;
$$->u.binary.value_a = $1;
$$->u.binary.value_b = $3;
}
| exp '/' exp {
$$ = p_new (EvalNode);
$$->oper = OP_DIV;
$$->u.binary.value_a = $1;
$$->u.binary.value_b = $3;
}
| '(' exp ')' {
$$ = p_new (EvalNode);
$$ = $2;
}
| exp '&' exp {
$$ = p_new (EvalNode);
$$->oper = OP_CONCAT;
$$->u.binary.value_a = $1;
$$->u.binary.value_b = $3;
}
;
| FUNCALL '(' arg_list ')' {
$$ = p_new (EvalNode);
$$->oper = OP_FUNCALL;
$$->u.function.symbol = $1->u.function.symbol;
$$->u.function.arg_list = $3;
}
;
arg_list: {}
| exp ',' arg_list { }
;
%%
int yylex (void)
{
int c;
c = getchar ();
if (isdigit (c)){
EvalNode *e = p_new (EvalNode);
Value *v = p_new (Value);
v->type = VALUE_NUMBER;
e->oper = OP_CONSTANT;
e->u.constant = v;
yylval.node = e;
return NUMBER;
}
if (isalpha (c)){
EvalNode *e = p_new (EvalNode);
Value *v = p_new (Value);
char buf [2] = { 0 , 0 };
buf [0] = c;
v->v.str = symbol_install (buf, SYMBOL_STRING, NULL);
register_symbol (v->v.str);
v->type = VALUE_STRING;
e->oper = OP_CONSTANT;
e->u.constant = v;
yylval.node = e;
return STRING;
}
if (c == '$'){
EvalNode *e = p_new (EvalNode);
e->oper = OP_FUNCALL;
e->u.function.symbol = symbol_install
("STRFUNC", SYMBOL_FUNCTION, 0);
register_symbol (e->u.function.symbol);
e->u.function.arg_list = NULL;
yylval.node = e;
return FUNCALL;
}
if (c == '\n')
return 0;
if (c == EOF)
return 0;
return c;
}
int
yyerror (char *s)
{
printf ("Error: %s\n", s);
return 0;
}
typedef enum {
ALLOC_SYMBOL,
ALLOC_BUFFER,
} AllocType;
typedef struct {
AllocType type;
void *data;
} AllocRec;
static void
register_symbol (Symbol *sym)
{
AllocRec *a_info = g_new (AllocRec, 1);
a_info->type = ALLOC_SYMBOL;
a_info->data = sym;
alloc_list = g_list_prepend (alloc_list, a_info);
}
void *
alloc_buffer (int size)
{
AllocRec *a_info = g_new (AllocRec, 1);
char *res = g_malloc (size);
a_info->type = ALLOC_BUFFER;
a_info->data = res;
alloc_list = g_list_prepend (alloc_list, a_info);
return res;
}
static void
alloc_clean (void)
{
GList *l = alloc_list;
for (; l; l = l->next){
AllocRec *rec = l->data;
switch (rec->type){
case ALLOC_BUFFER:
g_free (rec->data);
break;
case ALLOC_SYMBOL:
symbol_unref ((Symbol *)rec->data);
break;
}
}
g_list_free (l);
alloc_list = NULL;
}
static void
dump_constant (EvalNode *node)
{
Value *value = node->u.constant;
switch (value->type){
case VALUE_STRING:
printf ("STRING: %s\n", value->v.str->str);
break;
case VALUE_NUMBER:
printf ("NUM: %d\n", 0);
break;
default:
printf ("Unhandled item type\n");
}
}
void
dump_node (EvalNode *node)
{
Symbol *s;
switch (node->oper){
case OP_CONSTANT:
dump_constant (node);
return;
case OP_FUNCALL:
s = symbol_lookup (node->u.function.symbol->str);
printf ("Function call: %s\n", s->str);
break;
case OP_ADD:
case OP_SUB:
case OP_MULT:
case OP_DIV:
case OP_EXP:
case OP_CONCAT:
dump_node (node->u.binary.value_a);
dump_node (node->u.binary.value_b);
switch (node->oper){
case OP_ADD: printf ("ADD\n"); break;
case OP_SUB: printf ("SUB\n"); break;
case OP_MULT: printf ("MULT\n"); break;
case OP_DIV: printf ("DIV\n"); break;
case OP_CONCAT: printf ("CONCAT\n"); break;
case OP_EXP: printf ("EXP\n"); break;
default:
printf ("Error\n");
}
break;
case OP_NEG:
dump_node (node->u.value);
printf ("NEGATIVE\n");
break;
case OP_CAST_TO_STRING:
dump_node (node->u.value);
printf ("CAST TO STRING\n");
break;
}
}