/* Copyright (C) 2002 Bjoern Beutel. */
/* Description. =============================================================*/
/* Read in and display Malaga debugger expressions. */
/* Includes. ================================================================*/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <setjmp.h>
#include <string.h>
#include <gtk/gtk.h>
#include "basic.h"
#include "scanner.h"
#include "input.h"
#include "canvas.h"
#include "expressions.h"
/* Types. ===================================================================*/
typedef struct
{
list_node_t *next;
pos_string_t *name;
pos_value_t *value;
bool_t is_shown;
} expression_t;
/* Global variables. ========================================================*/
rectangle_t expressions_geometry;
string_t expressions_font_family;
int_t expressions_font_size;
/* Variables. ===============================================================*/
static list_t expressions;
static canvas_t *expressions_canvas;
static pos_string_t *equal, *dots;
/* Functions. ===============================================================*/
static void
configure_expressions( canvas_t *canvas, int_t *width_p, int_t *height_p )
{
int_t width, height;
expression_t *expression;
int_t font_height = get_font_height( canvas );
int_t space_width = get_space_width( canvas );
int_t border_width = get_border_width( canvas );
config_pos_string( equal, canvas );
config_pos_string( dots, canvas );
width = height = border_width;
FOREACH( expression, expressions )
{
if (expression != (expression_t *) expressions.first)
height += font_height;
config_pos_string( expression->name, canvas );
expression->name->x = border_width;
expression->name->y = height;
equal->x = expression->name->x + expression->name->width + space_width;
if (expression->is_shown)
{
config_pos_value( expression->value, canvas );
expression->value->x = equal->x + equal->width + space_width;
expression->value->y = height;
expression->name->y += (expression->value->height - font_height) / 2;
width = MAX( width, expression->value->x + expression->value->width );
height += expression->value->height;
}
else
{
dots->x = equal->x + equal->width + space_width;
width = MAX( width, dots->x + dots->width );
height += font_height;
}
}
*width_p = width + border_width;
*height_p = height + border_width;
}
/*---------------------------------------------------------------------------*/
static void
expose_expressions( canvas_t *canvas, rectangle_t *area )
{
int_t space_width = get_space_width( canvas );
expression_t *expression;
set_color( BLACK );
FOREACH( expression, expressions )
{
draw_pos_string( expression->name, canvas );
equal->x = expression->name->x + expression->name->width + space_width;
equal->y = expression->name->y;
draw_pos_string( equal, canvas );
if (expression->is_shown)
draw_pos_value( expression->value, canvas );
else
{
dots->x = equal->x + equal->width + space_width;
dots->y = equal->y;
draw_pos_string( dots, canvas );
}
}
}
/*---------------------------------------------------------------------------*/
static bool_t
mouse_event( canvas_t *canvas, int_t x, int_t y, int_t button )
/* Called if mouse has moved in CANVAS at position X/Y. */
{
expression_t *expression;
int_t font_height = get_font_height( canvas );
FOREACH( expression, expressions )
{
if (x >= expression->name->x
&& x < expression->name->x + expression->name->width
&& y >= expression->name->y
&& y < expression->name->y + font_height)
{
if (button == 0)
set_cursor( canvas, TRUE );
else if (button == 1)
{
expression->is_shown = ! expression->is_shown;
configure_canvas( canvas );
}
else if (button == 3)
{
free_pos_string( &expression->name );
free_pos_value( &expression->value );
free_node( (list_t *) &expressions, (list_node_t *) expression );
configure_canvas( canvas );
}
return TRUE;
}
}
set_cursor( canvas, FALSE );
return FALSE;
}
/*---------------------------------------------------------------------------*/
static void
show_all_expressions( canvas_t *canvas, guint do_show )
{
expression_t *expression;
FOREACH( expression, expressions )
expression->is_shown = do_show;
configure_canvas( canvas );
}
/*---------------------------------------------------------------------------*/
static void clear_expressions( canvas_t *canvas )
{
expression_t *expression;
FOREACH_FREE( expression, expressions )
{
free_pos_string( &expression->name );
free_pos_value( &expression->value );
}
configure_canvas( canvas );
}
/*---------------------------------------------------------------------------*/
static GtkItemFactoryEntry menu_items[] =
{
{ "/Expressions", NULL, NULL, 0, "<Branch>" },
{ "/Expressions/Clear All", NULL, clear_expressions, NULL, NULL },
{ "/Expressions/Show All", NULL, show_all_expressions, TRUE, NULL },
{ "/Expressions/Hide All", NULL, show_all_expressions, FALSE, NULL },
};
/*---------------------------------------------------------------------------*/
void
read_expressions( void )
/* Read new expressions from STDIN. */
{
string_t line;
expression_t *expression;
while (TRUE)
{
line = read_line( stdin );
if (line == NULL)
complain( "Premature EOF." );
if (strcmp_no_case( line, "end" ) == 0)
break;
/* Read a new expression. */
expression = new_node( &expressions, sizeof( expression_t ), LIST_END );
set_scanner_input( line );
/* Read expression name. */
test_token( TOK_STRING );
expression->name = new_pos_string( token_string );
read_next_token();
/* Read expression value. */
parse_token( '{' );
expression->value = parse_pos_value();
parse_token( '}' );
parse_token( EOF );
set_scanner_input( NULL );
free_mem( &line );
expression->is_shown = TRUE;
}
free_mem( &line );
if (equal == NULL)
equal = new_pos_string( "=" );
if (dots == NULL)
dots = new_pos_string( "..." );
if (expressions_canvas == NULL)
{
expressions_canvas = create_canvas(
"Malaga Expressions", "expressions.eps", &expressions_geometry,
configure_expressions, expose_expressions, NULL, mouse_event,
TRUE, menu_items, ARRAY_LENGTH( menu_items ) );
}
else
{
configure_canvas( expressions_canvas );
go_canvas_bottom( expressions_canvas );
show_canvas( expressions_canvas );
}
}
/* End of file. =============================================================*/