/*
 * XCC - XML Compiler-Compiler
 * 
 * Copyright (c) 2000-2004 Evgeny Stambulchik
 * 
 * 
 *                           All Rights Reserved
 * 
 *    This program is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; either version 2 of the License, or
 *    (at your option) any later version.
 * 
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 * 
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

/* Public stuff */

#ifndef __XCC_H_
#define __XCC_H_

#include <stdio.h>
#include <string.h>
#include <expat.h>

#define XCC_VERSION_MAJOR   0
#define XCC_VERSION_MINOR   3
#define XCC_VERSION_NANO    1
#define XCC_VERSION_STRING  "xcc-0.3.1"

#define XCC_RETURN_SUCCESS   0
#define XCC_RETURN_FAILURE   1

#define XCC_NS_SEPARATOR    '|'

#define XCC_STACK_CHUNK_SIZE  16

#define XCC_BUFFSIZE	    8192

/* ------------------- */

#define xcc_realloc realloc

typedef void (*XCC_stack_data_free)(void *data); 

typedef struct _XCCStack {
    unsigned int size;
    unsigned int depth;
    void **entries;
    XCC_stack_data_free data_free;
} XCCStack;

typedef struct _XCCString {
    unsigned int length;
    char *s;
} XCCString;

typedef struct _XCCElementEntry {
    int key;
    char *name;
} XCCElementEntry;

typedef struct _XCCParserData {
    int error;
    
    char *cbuffer;
    int cbufsize;
    int cbuflen;
    
    XCCStack *nodes;
    void *root;
    
    void *udata;
} XCCParserData;

typedef struct _XCCNode {
    char *name;
    int  id;
    void *data;
} XCCNode;

void xcc_get_version_numbers(int *major, int *minor, int *nano);
char *xcc_get_version_string(void);

void xcc_free(void *p);

void xcc_error(const char *fmt, ...);

int xcc_stack_increment(XCCStack *xs, const void *data);
int xcc_stack_decrement(XCCStack *xs);
int xcc_stack_get_last(const XCCStack *xs, void **data);
int xcc_stack_depth(const XCCStack *xs);

XCCString *xcc_string_new(void);
void xcc_string_free(XCCString *xstr);
int xcc_string_set(XCCString *xstr, const char *s);

XCCNode *xcc_node_new(void);

char *xcc_get_local(const char *name, const char *ns_uri, int *skip);

void *xcc_get_root(XCCParserData *pdata);

int xcc_parse(FILE *fp, void *udata, void **root,
              XML_StartElementHandler start_element_handler,
              XML_EndElementHandler end_element_handler);

#endif /* __XCC_H_ */
/*
 * XCC - XML Compiler-Compiler
 * 
 * Copyright (c) 2000-2004 Evgeny Stambulchik
 * 
 * 
 *                           All Rights Reserved
 * 
 *    This program is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; either version 2 of the License, or
 *    (at your option) any later version.
 * 
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 * 
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <string.h>
#include <stdarg.h>


void xcc_get_version_numbers(int *major, int *minor, int *nano)
{
    *major = XCC_VERSION_MAJOR;
    *minor = XCC_VERSION_MINOR;
    *nano  = XCC_VERSION_NANO;
}

char *xcc_get_version_string(void)
{
    return XCC_VERSION_STRING;
}

void xcc_error(const char *fmt, ...)
{
    va_list ap;
    char new_fmt[128];
    sprintf(new_fmt, "xcc: %s\n", fmt);

    va_start(ap, fmt);
    
    vfprintf(stderr, new_fmt, ap);
    va_end(ap);
}

void xcc_free(void *p)
{
    if (p) {
        free(p);
    }
}

void *xcc_malloc(size_t size)
{
    if (size == 0) {
        return NULL;
    } else {
        void *p = malloc(size);
        if (p) {
            return p;
        } else {
            fprintf(stderr, "Memory exhausted\n");
            abort();
        }
    }
}

char *xcc_strdup(const char *s)
{
    char *ret;
    if (s) {
        ret = xcc_malloc(strlen(s) + 1);
        if (ret) {
            strcpy(ret, s);
        }
    } else {
        ret = NULL;
    }
    return ret;
}

static unsigned int xcc_strlen(const char *s)
{
    if (s) {
        return strlen(s);
    } else {
        return 0;
    }
}

XCCStack *xcc_stack_new(XCC_stack_data_free data_free)
{
    XCCStack *xs = xcc_malloc(sizeof(XCCStack));
    
    if (xs) {
        xs->size      = 0;
        xs->depth     = 0;
        xs->entries   = NULL;
        xs->data_free = data_free;
    }
    
    return xs;
}

void xcc_stack_free(XCCStack *xs)
{
    if (xs) {
        while (xs->depth) {
            void *e;
            xs->depth--;
            e = xs->entries[xs->depth];
            if (e && xs->data_free) {
                xs->data_free(e);
            }
        }
        xcc_free(xs->entries);
        
        xcc_free(xs);
    }
}

int xcc_stack_increment(XCCStack *xs, const void *data)
{
    if (xs->size <= xs->depth) {
        unsigned int new_size = xs->size + XCC_STACK_CHUNK_SIZE;
        void **p = xcc_realloc(xs->entries, new_size*sizeof(void *));
        if (!p) {
            return XCC_RETURN_FAILURE;
        } else {
            xs->entries = p;
            xs->size = new_size;
        }
    }
    xs->entries[xs->depth] = (void *) data;
    xs->depth++;
    
    return XCC_RETURN_SUCCESS;
}

int xcc_stack_decrement(XCCStack *xs)
{
    if (xs->depth < 1) {
        return XCC_RETURN_FAILURE;
    } else {
        void *e;
        xs->depth--;
        e = xs->entries[xs->depth];
        if (e && xs->data_free) {
            xs->data_free(e);
        }
        
        return XCC_RETURN_SUCCESS;
    }
}

int xcc_stack_get_first(const XCCStack *xs, void **data)
{
    if (xs && xs->depth > 0) {
        *data = xs->entries[0];
        return XCC_RETURN_SUCCESS;
    } else {
        return XCC_RETURN_FAILURE;
    }
}

int xcc_stack_get_last(const XCCStack *xs, void **data)
{
    if (xs && xs->depth > 0) {
        *data = xs->entries[xs->depth - 1];
        return XCC_RETURN_SUCCESS;
    } else {
        return XCC_RETURN_FAILURE;
    }
}

int xcc_stack_get_data(const XCCStack *xs, unsigned int ind, void **data)
{
    if (xs && xs->depth > ind) {
        *data = xs->entries[ind];
        return XCC_RETURN_SUCCESS;
    } else {
        return XCC_RETURN_FAILURE;
    }
}

int xcc_stack_depth(const XCCStack *xs)
{
    return xs->depth;
}


XCCString *xcc_string_new(void)
{
    XCCString *xstr;
    
    xstr = xcc_malloc(sizeof(XCCString));
    if (xstr) {
        xstr->s = NULL;
        xstr->length = 0;
    }
    
    return xstr;
}

void xcc_string_free(XCCString *xstr)
{
    if (xstr) {
        xcc_free(xstr->s);
        xcc_free(xstr);
    }
}

int xcc_string_set(XCCString *xstr, const char *s)
{
    if (xstr) {
        xcc_free(xstr->s);
        xstr->s = xcc_strdup(s);
        xstr->length = xcc_strlen(xstr->s);
    }
    
    return XCC_RETURN_SUCCESS;
}

XCCNode *xcc_node_new(void)
{
    XCCNode *n;
    n = xcc_malloc(sizeof(XCCNode));
    if (n) {
        memset(n, 0, sizeof(XCCNode));
    }
    return n;
}

void xcc_node_free(XCCNode *n)
{
    if (n) {
        xcc_free(n->name);
        xcc_free(n);
    }
}

char *xcc_get_local(const char *name, const char *ns_uri, int *skip)
{
    char *sep, *local_name;
    if (ns_uri && (sep = strchr(name, XCC_NS_SEPARATOR))) {
        char *buf = strstr(name, ns_uri);
        if (buf != name) {
            *skip = 1;
        }
        local_name = xcc_strdup(sep + 1);
    } else {
        local_name = xcc_strdup(name);
    }
    
    return local_name;
}

void *xcc_get_root(XCCParserData *pdata)
{
    void *p;
    if (xcc_stack_get_data(pdata->nodes, 0, &p) != XCC_RETURN_SUCCESS) {
        return NULL;
    } else {
        XCCNode *node = p;
        return node->data;
    }
}

static void xcc_char_data_handler(void *data, const char *s, int len)
{
    XCCParserData *pdata = (XCCParserData *) data;
    int new_len;

    if (pdata->error) {
        return;
    }
    
    new_len = pdata->cbuflen + len;
    
    if (new_len >= pdata->cbufsize) {
        pdata->cbuffer = xcc_realloc(pdata->cbuffer, (new_len + 1));
        pdata->cbufsize = new_len + 1;
    }
    
    memcpy(pdata->cbuffer + pdata->cbuflen, s, len);
    pdata->cbuffer[new_len] = '\0';
    pdata->cbuflen = new_len;
}

int xcc_parse(FILE *fp, void *udata, void **root,
              XML_StartElementHandler start_element_handler,
              XML_EndElementHandler end_element_handler)
{
    XML_Parser xp;
    XCCParserData pdata;
    char Buff[XCC_BUFFSIZE];
    
    xp = XML_ParserCreateNS(NULL, XCC_NS_SEPARATOR);
    if (!xp) {
        *root = NULL;
        xcc_error("Couldn't allocate memory for parser");
        return XCC_RETURN_FAILURE;
    }

    /* Set XML_Parser's user data */
    pdata.error    = 0;
    
    pdata.cbuffer  = NULL;
    pdata.cbufsize = 0;
    pdata.cbuflen  = 0;
 
    pdata.nodes    = xcc_stack_new((XCC_stack_data_free) xcc_node_free);
    pdata.root     = NULL;
    
    pdata.udata    = udata;
    
    XML_SetUserData(xp, (void *) &pdata);

    XML_SetElementHandler(xp, start_element_handler, end_element_handler);

    /* Set the char data handler */
    XML_SetCharacterDataHandler(xp, xcc_char_data_handler);

    while (!pdata.error) {
        int done;
        int len;

        len = fread(Buff, 1, XCC_BUFFSIZE, fp);
        if (ferror(fp)) {
            xcc_error("Read error");
            pdata.error = 1;
            break;
        }
        done = feof(fp);

        if (!XML_Parse(xp, Buff, len, done)) {
            fprintf(stderr, "Parse error at line %d:\n%s\n",
	            XML_GetCurrentLineNumber(xp),
	            XML_ErrorString(XML_GetErrorCode(xp)));
            pdata.error = 1;
            break;
        }

        if (done) {
            break;
        }
    }
    
    /* Free allocated storage */
    XML_ParserFree(xp);
    xcc_stack_free(pdata.nodes);
    xcc_free(pdata.cbuffer);
    
    *root = pdata.root;
    if (!pdata.error) {
        return XCC_RETURN_SUCCESS;
    } else {
        return XCC_RETURN_FAILURE;
    }
}

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "defines.h"
#include "files.h"
#include "utils.h"
#include "dicts.h"
#include "core_utils.h"
#include "protos.h"

#include "xstrings.h"

typedef struct {
    RunTime *rt;
    int nrow;
} ParserData;

typedef struct _Page {
    int width;
    int height;
    int bgfill;
    int bgcolor;
} Page;

Page *page_new(void)
{
    Page *retval;
    
    retval = xmalloc(sizeof(Page));
    if (retval) {
        memset(retval, 0, sizeof(Page));
        retval->bgfill = TRUE;
    }
    
    return retval;
}

Colordef *colordef_new(void)
{
    Colordef *retval;
    retval = xmalloc(sizeof(Colordef));
    retval->id = -1;
    retval->cname = NULL;
    return retval;
}

void colordef_free(Colordef *cd)
{
    if (cd) {
        xfree(cd->cname);
        xfree(cd);
    }
}

Fontdef *fontdef_new()
{
    Fontdef *retval;
    retval = xmalloc(sizeof(Fontdef));
    retval->id = -1;
    retval->fontname = NULL;
    retval->fallback = NULL;
    return retval;
}

void fontdef_free(Fontdef *fd)
{
    if (fd) {
        xfree(fd->fontname);
        xfree(fd->fallback);
        xfree(fd);
    }
}

typedef struct {
    int font;
    int color;
    double size;
} FaceSpec;

FaceSpec *facespec_new()
{
    FaceSpec *fs;
    fs = xmalloc(sizeof(FaceSpec));
    if (fs) {
        memset(fs, 0, sizeof(FaceSpec));
    }
    return fs;
}

void facespec_free(FaceSpec *fs)
{
    if (fs) {
        xfree(fs);
    }
}

typedef struct {
    GraphType type;
    int stacked;
    double bargap;
} PresentationSpec;


PresentationSpec *presentationspec_new()
{
    PresentationSpec *ps;
    ps = xmalloc(sizeof(PresentationSpec));
    if (ps) {
        memset(ps, 0, sizeof(PresentationSpec));
    }
    return ps;
}

void presentationspec_free(PresentationSpec *ps)
{
    if (ps) {
        xfree(ps);
    }
}

view *view_new()
{
    view *v;
    v = xmalloc(sizeof(view));
    if (v) {
        memset(v, 0, sizeof(view));
    }
    return v;
}

typedef struct {
    int type;
    double min;
    double max;
    int invert;
} Scale;

Scale *scale_new()
{
    Scale *s;
    s = xmalloc(sizeof(Scale));
    if (s) {
        memset(s, 0, sizeof(Scale));
    }
    return s;
}

typedef struct {
    int type;
    APoint ap;
} Location;

Location *location_new()
{
    Location *retval;
    retval = xmalloc(sizeof(Location));
    if (retval) {
        memset(retval, 0, sizeof(Location));
    }
    return retval;
}

typedef struct {
    FPoint anchor;
    int just;
    VPoint offset;
    Line line;
    Pen fillpen;
} Legframe;

legend *legend_new()
{
    legend *l;
    l = xmalloc(sizeof(legend));
    if (l) {
        memset(l, 0, sizeof(legend));
    }
    return l;
}

Legframe *legframe_new()
{
    Legframe *lf;
    lf = xmalloc(sizeof(Legframe));
    if (lf) {
        memset(lf, 0, sizeof(Legframe));
    }
    return lf;
}

typedef struct {
    int active;
    double x;
    double y;
} Fixedpoint;

Fixedpoint *fixedpoint_new()
{
    Fixedpoint *fp;
    fp = xmalloc(sizeof(Fixedpoint));
    if (fp) {
        memset(fp, 0, sizeof(Fixedpoint));
    }
    return fp;
}

GLocator *glocator_new()
{
    GLocator *retval;
    retval = xmalloc(sizeof(GLocator));
    if (retval) {
        memset(retval, 0, sizeof(GLocator));
    }
    return retval;
}

typedef struct {
    int type;
    int prec;
} Format;

Format *format_new()
{
    Format *retval;
    retval = xmalloc(sizeof(Format));
    if (retval) {
        memset(retval, 0, sizeof(Format));
    }
    return retval;
}

typedef struct {
    int zero;
    VPoint offset;
} APlacement;

APlacement *axisplacement_new()
{
    APlacement *retval;
    retval = xmalloc(sizeof(APlacement));
    if (retval) {
        memset(retval, 0, sizeof(APlacement));
    }
    return retval;
}

typedef struct {
    int active;
    Line line;
} ABar;

ABar *axisbar_new()
{
    ABar *retval;
    retval = xmalloc(sizeof(ABar));
    if (retval) {
        memset(retval, 0, sizeof(ABar));
    }
    return retval;
}

typedef struct {
    char *s;
    
    TextProps tprops;
    
    int layout;
    int sideplacement;
    int autoplace;
    VPoint offset;
} ALabel;

ALabel *axislabel_new()
{
    ALabel *retval;
    retval = xmalloc(sizeof(ALabel));
    if (retval) {
        memset(retval, 0, sizeof(ALabel));
    }
    return retval;
}

typedef struct {
    int active;
    int sideplacement;
    tickprops props;
    tickprops mprops;
} TMarks;

TMarks *tmarks_new()
{
    TMarks *retval;
    retval = xmalloc(sizeof(TMarks));
    if (retval) {
        memset(retval, 0, sizeof(TMarks));
    }
    return retval;
}

typedef struct {
    int active;
    int sideplacement;
    char *transform;
    char *prepend;
    char *append;
    int autoplace;
    VPoint offset;
    
    TextProps tprops;
    
    int skip;
    int stagger;
    int autostart;
    double start;
    int autostop;
    double stop;
    Format format;
} TLabels;

TLabels *tlabels_new()
{
    TLabels *retval;
    retval = xmalloc(sizeof(TLabels));
    if (retval) {
        memset(retval, 0, sizeof(TLabels));
    }
    return retval;
}

typedef struct {
    int type;                   /* type of user ticks */
    int nticks;                 /* total number of ticks */
    tickloc tloc[MAX_TICKS];    /* locations of ticks */
} UTicks;

UTicks *uticks_new()
{
    UTicks *retval;
    retval = xmalloc(sizeof(UTicks));
    if (retval) {
        memset(retval, 0, sizeof(UTicks));
    }
    return retval;
}

tickloc *tick_new()
{
    tickloc *retval;
    retval = xmalloc(sizeof(tickloc));
    if (retval) {
        memset(retval, 0, sizeof(tickloc));
    }
    return retval;
}

int utick_add(UTicks *uticks, tickloc *tick)
{
    if (uticks && uticks->nticks < MAX_TICKS) {
        uticks->tloc[uticks->nticks++] = *tick;
        return RETURN_SUCCESS;
    } else {
        return RETURN_FAILURE;
    }
}


typedef struct {
    double major;
    int nminor;
    int autonum;
    int round;
    UTicks uticks;
    TMarks tmarks;
    TLabels tlabels;
} Ticks;

Ticks *ticks_new()
{
    Ticks *retval;
    retval = xmalloc(sizeof(Ticks));
    if (retval) {
        memset(retval, 0, sizeof(Ticks));
    }
    return retval;
}

tickprops *tickprops_new()
{
    tickprops *retval;
    retval = xmalloc(sizeof(tickprops));
    if (retval) {
        memset(retval, 0, sizeof(tickprops));
    }
    return retval;
}

typedef struct {
    int autov;
    double value;
} Autoval;

Arrow *arrow_new(void)
{
    Arrow *retval;
    retval = xmalloc(sizeof(Arrow));
    if (retval) {
        memset(retval, 0, sizeof(Arrow));
    }
    return retval;
}

typedef struct {
    int decor;
    double offset;
    Line line;
    Pen fillpen;
} TextFrame;

TextFrame *textframe_new(void)
{
    TextFrame *retval;
    retval = xmalloc(sizeof(TextFrame));
    if (retval) {
        memset(retval, 0, sizeof(TextFrame));
    }
    return retval;
}

typedef struct {
    int active;
    Arrow arrow;
} TextPointer;

TextPointer *textpointer_new(void)
{
    TextPointer *retval;
    retval = xmalloc(sizeof(TextPointer));
    if (retval) {
        memset(retval, 0, sizeof(TextPointer));
    }
    return retval;
}

AValue *avalue_new(void)
{
    AValue *retval;
    retval = xmalloc(sizeof(AValue));
    if (retval) {
        memset(retval, 0, sizeof(AValue));
    }
    return retval;
}

void avalue_free(AValue *av)
{
    if (av) {
        xfree(av->prestr);
        xfree(av->appstr);
        xfree(av);
    }
}

char *utf2iso(const char *s)
{
    char *retval;
    char *p1, *p2;
    
    if (!s) {
        return NULL;
    }
    
    retval = xmalloc(strlen(s) + 1);
    if (!retval) {
        return NULL;
    }
    
    p1 = (char *) s;
    p2 = retval;
    
    while (*p1) {
        if (*p1 & 0x80) {
            /* last 2 bits */
            *p2 = (*p1 & 0x03) << 6; p1++;
            /* last 6 bits of the next byte */
            *p2 += *p1 & 0x3F;
        } else {
            *p2 = *p1;
        }
        p1++; p2++;
    }
    
    *(p2) = '\0';
    
    return retval;
}

    
typedef union {
    int ival;
    double dval;
    char * sval;
    int bval;
    RGB * rgb;
    int ftype;
    int fontid;
    VPoint * offset;
    FPoint * fpoint;
    int axislayout;
    int sideplacement;
    int inoutplacement;
    int uticktype;
    int ticktype;
    Autoval * autoval;
    int loctype;
    SetType settype;
    int fillrule;
    int regiontype;
    double dateordval;
    Autoval * autodateordval;
} XCCAType;

typedef union {
    Quark * project;
    Page * page;
    XCCString * string;
    Pen * pen;
    Line * line;
    void * dummy;
    Colordef * colordef;
    Fontdef * fontdef;
    FaceSpec * facespec;
    Quark * graph;
    PresentationSpec * presentationspec;
    view * view;
    Scale * scale;
    double * dptr;
    legend * legend;
    Legframe * legframe;
    GLocator * glocator;
    Fixedpoint * fixedpoint;
    Format * format;
    Quark * frame;
    TextProps * textprops;
    Quark * axis;
    APlacement * axisplacement;
    ABar * axisbar;
    ALabel * axislabel;
    Ticks * ticks;
    TMarks * tmarks;
    tickprops * tickprops;
    TLabels * tlabels;
    UTicks * uticks;
    tickloc * tick;
    Quark * object;
    Quark * atext;
    Location * location;
    DOLineData * do_line_data;
    DOBoxData * do_box_data;
    DOArcData * do_arc_data;
    TextFrame * textframe;
    TextPointer * textpointer;
    Arrow * arrow;
    Quark * set;
    Symbol * symbol;
    SetLine * setline;
    AValue * annotation;
    Errbar * errorbar;
    BarLine * barline;
    RiserLine * riserline;
    Dataset * dataset;
    Datapoint * datapoint;
    Quark * region;
    void * unicast;
} XCCEType;

static XCCElementEntry XCCElementTab[] = {
    {1, EStrGrace},
    {2, EStrDefinitions},
    {3, EStrColormap},
    {4, EStrFontmap},
    {5, EStrScales},
    {6, EStrColorDef},
    {7, EStrFontDef},
    {8, EStrPage},
    {9, EStrDescription},
    {10, EStrDataFormats},
    {11, EStrFaceSpec},
    {12, EStrDates},
    {13, EStrWorld},
    {14, EStrText},
    {15, EStrFillSpec},
    {16, EStrFrame},
    {17, EStrGraph},
    {18, EStrPresentationSpec},
    {19, EStrViewport},
    {20, EStrXscale},
    {21, EStrYscale},
    {22, EStrZscale},
    {23, EStrLegend},
    {24, EStrLegframe},
    {25, EStrLineSpec},
    {26, EStrLocator},
    {27, EStrFixedpoint},
    {28, EStrXformat},
    {29, EStrYformat},
    {30, EStrAxis},
    {31, EStrPlacement},
    {32, EStrAxisbar},
    {33, EStrAxislabel},
    {34, EStrTicks},
    {35, EStrUserticks},
    {36, EStrTickmarks},
    {37, EStrMajor},
    {38, EStrMinor},
    {39, EStrTicklabels},
    {40, EStrTick},
    {41, EStrFormat},
    {42, EStrObject},
    {43, EStrLocation},
    {44, EStrBoxData},
    {45, EStrArcData},
    {46, EStrLineData},
    {47, EStrAText},
    {48, EStrTextFrame},
    {49, EStrPointer},
    {50, EStrArrow},
    {51, EStrSet},
    {52, EStrSymbol},
    {53, EStrLine},
    {54, EStrAnnotation},
    {55, EStrTextProperties},
    {56, EStrErrorbar},
    {57, EStrBarline},
    {58, EStrRiserline},
    {59, EStrLegendEntry},
    {60, EStrDataset},
    {61, EStrRow},
    {62, EStrRegion}
};

static int get_element_id_by_name(const char *name)
{
    int i;
    for (i = 0; i < 62; i++) {
        if (!strcmp(XCCElementTab[i].name, name)) {
            return XCCElementTab[i].key;
        }
    }
    return -1;
}

void xcc_start_handler(void *data, const char *el, const char **attr)
{
    XCCParserData *pdata = (XCCParserData *) data;
    XCCNode *pnode = NULL, *node;
    XCCEType element;
    XCCAType attribute;
    int i, element_id, parent_id, parent_child, skip = 0;
    const char *avalue;
    char *aname, *el_local;

    if (pdata->error) {
        return;
    }

    pdata->cbuflen = 0;
    if (pdata->cbufsize) {
        pdata->cbuffer[0] = '\0';
    }
    el_local  = xcc_get_local(el, GRACE_NS_URI, &skip);
    if (xcc_stack_depth(pdata->nodes) == 0) {
        parent_id = 0;
    } else {
        void *p;
        xcc_stack_get_last(pdata->nodes, &p);
        pnode = p;
        parent_id = pnode->id;
    }
    if (parent_id < 0) {
        skip = 1;
    }
    if (skip) {
        element_id = -1;
    } else {
        element_id = get_element_id_by_name(el_local);
    }
    if (parent_id >= 0 && element_id >= 0) {
        parent_child = 62*parent_id + element_id;
    } else {
        parent_child = -1;
    }

    switch (parent_child) {
    case 1:
    case 71:
    case 64:
    case 70:
    case 72:
    case 78:
    case 104:
    case 109:
    case 127:
    case 128:
    case 129:
    case 192:
    case 255:
    case 572:
    case 632:
    case 633:
    case 1011:
    case 1015:
    case 1017:
    case 1007:
    case 1009:
    case 1034:
    case 1039:
    case 1072:
    case 1074:
    case 1075:
    case 1076:
    case 1080:
    case 1084:
    case 1105:
    case 1096:
    case 1101:
    case 1116:
    case 1437:
    case 1450:
    case 1513:
    case 1503:
    case 1639:
    case 1640:
    case 1641:
    case 1891:
    case 1892:
    case 1893:
    case 1894:
    case 2009:
    case 2101:
    case 2060:
    case 2143:
    case 2144:
    case 2147:
    case 2210:
    case 2269:
    case 2270:
    case 2319:
    case 2381:
    case 2473:
    case 2459:
    case 2629:
    case 2647:
    case 2619:
    case 2650:
    case 2648:
    case 2649:
    case 2902:
    case 2957:
    case 2928:
    case 2969:
    case 2962:
    case 2963:
    case 3001:
    case 2991:
    case 3088:
    case 3214:
    case 3215:
    case 3216:
    case 3218:
    case 3221:
    case 3222:
    case 3249:
    case 3239:
    case 3311:
    case 3301:
    case 3403:
    case 3389:
    case 3421:
    case 3529:
    case 3530:
    case 3559:
    case 3621:
    case 3672:
    case 3781:
    case 3905:
        break;
    default:
        if (!skip) {
            xcc_error("unexpected \"%s\"->\"%s\" combination", pnode ? pnode->name:"xml", el_local);
            pdata->error = 1;
        }
        break;
    }

    switch (element_id) {
    case 1: /* #EStrGrace */
            
        element.project = project_new(((ParserData *) pdata->udata)->rt->qfactory);
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrVersion)) {
                    
        attribute.ival = atoi(avalue);
    
                {
                        
            project_set_version_id(element.project, attribute.ival);
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 2: /* #EStrDefinitions */
            
        element.dummy = NULL;
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 3: /* #EStrColormap */
            
        element.dummy = NULL;
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 4: /* #EStrFontmap */
            
        element.dummy = NULL;
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 5: /* #EStrScales */
            
        element.dummy = NULL;
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrFontSize)) {
                    
        attribute.dval = atof(avalue);
    
                {
                        
	    project_set_fontsize_scale(xcc_get_root(pdata), attribute.dval);
        
                }
                } else
                if (!strcmp(aname, AStrLineWidth)) {
                    
        attribute.dval = atof(avalue);
    
                {
                        
	    project_set_linewidth_scale(xcc_get_root(pdata), attribute.dval);
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 6: /* #EStrColorDef */
            
        element.colordef = colordef_new();
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrId)) {
                    
        attribute.ival = atoi(avalue);
    
                {
                        
            element.colordef->id = attribute.ival;
        
                }
                } else
                if (!strcmp(aname, AStrRgb)) {
                    
        unsigned int r, g, b;
        attribute.rgb = xmalloc(sizeof(RGB));
        sscanf(avalue, "#%02x%02x%02x", &r, &g, &b);
        attribute.rgb->red = r; attribute.rgb->green = g; attribute.rgb->blue = b;
    
                {
                        
            element.colordef->rgb = *(attribute.rgb);
            xfree(attribute.rgb);
        
                }
                } else
                if (!strcmp(aname, AStrName)) {
                    
        attribute.sval = utf2iso(avalue);
    
                {
                        
            element.colordef->cname = attribute.sval;
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 7: /* #EStrFontDef */
            
        element.fontdef = fontdef_new();
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrId)) {
                    
        attribute.ival = atoi(avalue);
    
                {
                        
            element.fontdef->id = attribute.ival;
        
                }
                } else
                if (!strcmp(aname, AStrName)) {
                    
        attribute.sval = utf2iso(avalue);
    
                {
                        
            element.fontdef->fontname = attribute.sval;
        
                }
                } else
                if (!strcmp(aname, AStrFallback)) {
                    
        attribute.sval = utf2iso(avalue);
    
                {
                        
            element.fontdef->fallback = attribute.sval;
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 8: /* #EStrPage */
            
        element.page = page_new();
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrWidth)) {
                    
        attribute.ival = atoi(avalue);
    
                {
                        
            element.page->width = attribute.ival;
        
                }
                } else
                if (!strcmp(aname, AStrHeight)) {
                    
        attribute.ival = atoi(avalue);
    
                {
                        
            element.page->height = attribute.ival;
        
                }
                } else
                if (!strcmp(aname, AStrColorId)) {
                    
        attribute.ival = atoi(avalue);
    
                {
                        
            element.page->bgcolor = attribute.ival;
        
                }
                } else
                if (!strcmp(aname, AStrFill)) {
                    
        attribute.bval = compare_strings(avalue, "yes");
    
                {
                        
            element.page->bgfill = attribute.bval;
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 9: /* #EStrDescription */
            
        element.string = xcc_string_new();
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 10: /* #EStrDataFormats */
            
        element.dummy = NULL;
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 11: /* #EStrFaceSpec */
            
        element.facespec = facespec_new();
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrFontId)) {
                    
        attribute.fontid = atoi(avalue);
    
                {
                        
            element.facespec->font = attribute.fontid;
        
                }
                } else
                if (!strcmp(aname, AStrColorId)) {
                    
        attribute.ival = atoi(avalue);
    
                {
                        
            element.facespec->color = attribute.ival;
        
                }
                } else
                if (!strcmp(aname, AStrCharSize)) {
                    
        attribute.dval = atof(avalue);
    
                {
                        
            element.facespec->size = attribute.dval;
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 12: /* #EStrDates */
            
        element.dummy = NULL;
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrReference)) {
                    
        attribute.ival = atoi(avalue);
    
                {
                        
            project_set_ref_date(xcc_get_root(pdata), attribute.ival);
        
                }
                } else
                if (!strcmp(aname, AStrWrap)) {
                    
        attribute.bval = compare_strings(avalue, "yes");
    
                {
                        
            project_allow_two_digits_years(xcc_get_root(pdata), attribute.bval);
        
                }
                } else
                if (!strcmp(aname, AStrWrapYear)) {
                    
        attribute.ival = atoi(avalue);
    
                {
                        
            project_set_wrap_year(xcc_get_root(pdata), attribute.ival);
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 13: /* #EStrWorld */
            
        element.dummy = NULL;
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrFormat)) {
                    
        attribute.sval = utf2iso(avalue);
    
                {
                        
            project_set_sformat(xcc_get_root(pdata), attribute.sval);
            xfree(attribute.sval);
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 14: /* #EStrText */
            
        element.string = xcc_string_new();
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 15: /* #EStrFillSpec */
            
        element.pen = xmalloc(sizeof(Pen));
        element.pen->color = element.pen->pattern = 1;
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrColorId)) {
                    
        attribute.ival = atoi(avalue);
    
                {
                        
            element.pen->color = attribute.ival;
        
                }
                } else
                if (!strcmp(aname, AStrPatternId)) {
                    
        attribute.ival = atoi(avalue);
    
                {
                        
            element.pen->pattern = attribute.ival;
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 16: /* #EStrFrame */
            
        element.frame = frame_new((Quark *)pnode->data);
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrId)) {
                    
        attribute.sval = utf2iso(avalue);
    
                {
                        
            quark_idstr_set(element.frame, attribute.sval);
            xfree(attribute.sval);
        
                }
                } else
                if (!strcmp(aname, AStrActive)) {
                    
        attribute.bval = compare_strings(avalue, "yes");
    
                {
                        
            quark_set_active(element.frame, attribute.bval);
        
                }
                } else
                if (!strcmp(aname, AStrType)) {
                    
        attribute.ival = atoi(avalue);
    
                {
                        
            frame_set_type(element.frame, attribute.ival);
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 17: /* #EStrGraph */
            
        element.graph = graph_new((Quark *)pnode->data);
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrId)) {
                    
        attribute.sval = utf2iso(avalue);
    
                {
                        
            quark_idstr_set(element.graph, attribute.sval);
            xfree(attribute.sval);
        
                }
                } else
                if (!strcmp(aname, AStrActive)) {
                    
        attribute.bval = compare_strings(avalue, "yes");
    
                {
                        
            quark_set_active(element.graph, attribute.bval);
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 18: /* #EStrPresentationSpec */
            
        element.presentationspec = presentationspec_new();
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrType)) {
                    
        attribute.sval = utf2iso(avalue);
    
                {
                        
            RunTime *rt = ((ParserData *)pdata->udata)->rt;
            element.presentationspec->type = graph_get_type_by_name(rt, attribute.sval);
            xfree(attribute.sval);
        
                }
                } else
                if (!strcmp(aname, AStrStacked)) {
                    
        attribute.bval = compare_strings(avalue, "yes");
    
                {
                        
            element.presentationspec->stacked = attribute.bval;
        
                }
                } else
                if (!strcmp(aname, AStrBargap)) {
                    
        attribute.dval = atof(avalue);
    
                {
                        
            element.presentationspec->bargap = attribute.dval;
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 19: /* #EStrViewport */
            
        element.view = view_new();
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrXmin)) {
                    
        attribute.dval = atof(avalue);
    
                {
                        
            element.view->xv1 = attribute.dval;
        
                }
                } else
                if (!strcmp(aname, AStrYmin)) {
                    
        attribute.dval = atof(avalue);
    
                {
                        
            element.view->yv1 = attribute.dval;
        
                }
                } else
                if (!strcmp(aname, AStrXmax)) {
                    
        attribute.dval = atof(avalue);
    
                {
                        
            element.view->xv2 = attribute.dval;
        
                }
                } else
                if (!strcmp(aname, AStrYmax)) {
                    
        attribute.dval = atof(avalue);
    
                {
                        
            element.view->yv2 = attribute.dval;
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 20: /* #EStrXscale */
            
        element.scale = scale_new();
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrMin)) {
                    
        if (parse_date_or_number(xcc_get_root(pdata), avalue, FALSE, &attribute.dateordval) != RETURN_SUCCESS) {
                attribute.dateordval = 0.0;
        }
    
                {
                        
            element.scale->min = attribute.dateordval;
        
                }
                } else
                if (!strcmp(aname, AStrMax)) {
                    
        if (parse_date_or_number(xcc_get_root(pdata), avalue, FALSE, &attribute.dateordval) != RETURN_SUCCESS) {
                attribute.dateordval = 0.0;
        }
    
                {
                        
            element.scale->max = attribute.dateordval;
        
                }
                } else
                if (!strcmp(aname, AStrType)) {
                    
        attribute.sval = utf2iso(avalue);
    
                {
                        
            element.scale->type = get_scale_type_by_name(attribute.sval);
            xfree(attribute.sval);
        
                }
                } else
                if (!strcmp(aname, AStrInvert)) {
                    
        attribute.bval = compare_strings(avalue, "yes");
    
                {
                        
            element.scale->invert = attribute.bval;
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 21: /* #EStrYscale */
            
        element.scale = scale_new();
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrMin)) {
                    
        if (parse_date_or_number(xcc_get_root(pdata), avalue, FALSE, &attribute.dateordval) != RETURN_SUCCESS) {
                attribute.dateordval = 0.0;
        }
    
                {
                        
            element.scale->min = attribute.dateordval;
        
                }
                } else
                if (!strcmp(aname, AStrMax)) {
                    
        if (parse_date_or_number(xcc_get_root(pdata), avalue, FALSE, &attribute.dateordval) != RETURN_SUCCESS) {
                attribute.dateordval = 0.0;
        }
    
                {
                        
            element.scale->max = attribute.dateordval;
        
                }
                } else
                if (!strcmp(aname, AStrType)) {
                    
        attribute.sval = utf2iso(avalue);
    
                {
                        
            element.scale->type = get_scale_type_by_name(attribute.sval);
            xfree(attribute.sval);
        
                }
                } else
                if (!strcmp(aname, AStrInvert)) {
                    
        attribute.bval = compare_strings(avalue, "yes");
    
                {
                        
            element.scale->invert = attribute.bval;
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 22: /* #EStrZscale */
            
        element.dptr = xcalloc(1, SIZEOF_DOUBLE);
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrNorm)) {
                    
        attribute.dval = atof(avalue);
    
                {
                        
            *(element.dptr) = attribute.dval;
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 23: /* #EStrLegend */
            
        element.legend = legend_new();
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrActive)) {
                    
        attribute.bval = compare_strings(avalue, "yes");
    
                {
                        
            element.legend->active = attribute.bval;
        
                }
                } else
                if (!strcmp(aname, AStrLength)) {
                    
        attribute.dval = atof(avalue);
    
                {
                        
            element.legend->len = attribute.dval;
        
                }
                } else
                if (!strcmp(aname, AStrVgap)) {
                    
        attribute.dval = atof(avalue);
    
                {
                        
            element.legend->vgap = attribute.dval;
        
                }
                } else
                if (!strcmp(aname, AStrHgap)) {
                    
        attribute.dval = atof(avalue);
    
                {
                        
            element.legend->hgap = attribute.dval;
        
                }
                } else
                if (!strcmp(aname, AStrInvert)) {
                    
        attribute.bval = compare_strings(avalue, "yes");
    
                {
                        
            element.legend->invert = attribute.bval;
        
                }
                } else
                if (!strcmp(aname, AStrSingleSymbol)) {
                    
        attribute.bval = compare_strings(avalue, "yes");
    
                {
                        
            element.legend->singlesym = attribute.bval;
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 24: /* #EStrLegframe */
            
        element.legframe = legframe_new();
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrAnchor)) {
                    
        attribute.fpoint = xmalloc(sizeof(FPoint));
        sscanf(avalue, "(%lg, %lg)", &(attribute.fpoint->x), &(attribute.fpoint->y));
    
                {
                        
            element.legframe->anchor = *(attribute.fpoint);
            xfree(attribute.fpoint);
        
                }
                } else
                if (!strcmp(aname, AStrJustification)) {
                    
        attribute.ival = atoi(avalue);
    
                {
                        
            element.legframe->just = attribute.ival;
        
                }
                } else
                if (!strcmp(aname, AStrOffset)) {
                    
        if (!strcmp(avalue, VStrAuto)) {
            attribute.offset = NULL;
        } else {
            attribute.offset = xmalloc(sizeof(VPoint));
            sscanf(avalue, "(%lg, %lg)", &(attribute.offset->x), &(attribute.offset->y));
        }
    
                {
                        
            element.legframe->offset = *(attribute.offset);
            xfree(attribute.offset);
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 25: /* #EStrLineSpec */
            
        element.line = xmalloc(sizeof(Line));
        element.line->pen.color = element.line->pen.pattern = 1;
        element.line->width = 1.0;
        element.line->style = 1;
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrColorId)) {
                    
        attribute.ival = atoi(avalue);
    
                {
                        
            element.line->pen.color = attribute.ival;
        
                }
                } else
                if (!strcmp(aname, AStrPatternId)) {
                    
        attribute.ival = atoi(avalue);
    
                {
                        
            element.line->pen.pattern = attribute.ival;
        
                }
                } else
                if (!strcmp(aname, AStrStyleId)) {
                    
        attribute.ival = atoi(avalue);
    
                {
                        
            element.line->style = attribute.ival;
        
                }
                } else
                if (!strcmp(aname, AStrWidth)) {
                    
        attribute.dval = atof(avalue);
    
                {
                        
            element.line->width = attribute.dval;
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 26: /* #EStrLocator */
            
        element.glocator = glocator_new();
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrType)) {
                    
        attribute.ival = atoi(avalue);
    
                {
                        
            element.glocator->type = attribute.ival;
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 27: /* #EStrFixedpoint */
            
        element.fixedpoint = fixedpoint_new();
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrActive)) {
                    
        attribute.bval = compare_strings(avalue, "yes");
    
                {
                        
            element.fixedpoint->active = attribute.bval;
        
                }
                } else
                if (!strcmp(aname, AStrX)) {
                    
        attribute.dval = atof(avalue);
    
                {
                        
            element.fixedpoint->x = attribute.dval;
        
                }
                } else
                if (!strcmp(aname, AStrY)) {
                    
        attribute.dval = atof(avalue);
    
                {
                        
            element.fixedpoint->y = attribute.dval;
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 28: /* #EStrXformat */
            
        element.format = format_new();
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrFormat)) {
                    
        attribute.ftype = get_format_type_by_name(avalue);
    
                {
                        
            element.format->type = attribute.ftype;
        
                }
                } else
                if (!strcmp(aname, AStrPrec)) {
                    
        attribute.ival = atoi(avalue);
    
                {
                        
            element.format->prec = attribute.ival;
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 29: /* #EStrYformat */
            
        element.format = format_new();
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrFormat)) {
                    
        attribute.ftype = get_format_type_by_name(avalue);
    
                {
                        
            element.format->type = attribute.ftype;
        
                }
                } else
                if (!strcmp(aname, AStrPrec)) {
                    
        attribute.ival = atoi(avalue);
    
                {
                        
            element.format->prec = attribute.ival;
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 30: /* #EStrAxis */
            
        element.axis = axis_new((Quark *)pnode->data);
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrId)) {
                    
        attribute.sval = utf2iso(avalue);
    
                {
                        
            quark_idstr_set(element.axis, attribute.sval);
            xfree(attribute.sval);
        
                }
                } else
                if (!strcmp(aname, AStrType)) {
                    
        attribute.sval = utf2iso(avalue);
    
                {
                        
            int axis_type;
            if (!strcmp(attribute.sval, "x")) {
                axis_type = AXIS_TYPE_X;
            } else {
                axis_type = AXIS_TYPE_Y;
            }
            axis_set_type(element.axis, axis_type);
            xfree(attribute.sval);
        
                }
                } else
                if (!strcmp(aname, AStrActive)) {
                    
        attribute.bval = compare_strings(avalue, "yes");
    
                {
                        
            quark_set_active(element.axis, attribute.bval);
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 31: /* #EStrPlacement */
            
        element.axisplacement = axisplacement_new();
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrZero)) {
                    
        attribute.bval = compare_strings(avalue, "yes");
    
                {
                        
            element.axisplacement->zero = attribute.bval;
        
                }
                } else
                if (!strcmp(aname, AStrOffset)) {
                    
        if (!strcmp(avalue, VStrAuto)) {
            attribute.offset = NULL;
        } else {
            attribute.offset = xmalloc(sizeof(VPoint));
            sscanf(avalue, "(%lg, %lg)", &(attribute.offset->x), &(attribute.offset->y));
        }
    
                {
                        
            if (attribute.offset) {
                element.axisplacement->offset.x = attribute.offset->x;
                element.axisplacement->offset.y = attribute.offset->y;
                xfree(attribute.offset);
            }
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 32: /* #EStrAxisbar */
            
        element.axisbar = axisbar_new();
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrActive)) {
                    
        attribute.bval = compare_strings(avalue, "yes");
    
                {
                        
            element.axisbar->active = attribute.bval;
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 33: /* #EStrAxislabel */
            
        element.axislabel = axislabel_new();
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrLayout)) {
                    
        if (!strcmp(avalue, VStrParallel)) {
            attribute.axislayout = LAYOUT_PARALLEL;
        } else {
            attribute.axislayout = LAYOUT_PERPENDICULAR;
        }
    
                {
                        
            element.axislabel->layout = attribute.axislayout;
        
                }
                } else
                if (!strcmp(aname, AStrOffset)) {
                    
        if (!strcmp(avalue, VStrAuto)) {
            attribute.offset = NULL;
        } else {
            attribute.offset = xmalloc(sizeof(VPoint));
            sscanf(avalue, "(%lg, %lg)", &(attribute.offset->x), &(attribute.offset->y));
        }
    
                {
                        
            if (attribute.offset) {
                element.axislabel->autoplace = FALSE;
                element.axislabel->offset.x  = attribute.offset->x;
                element.axislabel->offset.y  = attribute.offset->y;
                xfree(attribute.offset);
            } else {
                element.axislabel->autoplace = TRUE;
            }
        
                }
                } else
                if (!strcmp(aname, AStrSidePlacement)) {
                    
        if (!strcmp(avalue, VStrNormal)) {
            attribute.sideplacement = PLACEMENT_NORMAL;
        } else
        if (!strcmp(avalue, VStrOpposite)) {
            attribute.sideplacement = PLACEMENT_OPPOSITE;
        } else
        if (!strcmp(avalue, VStrBoth)) {
            attribute.sideplacement = PLACEMENT_BOTH;
        } else {
            attribute.sideplacement = PLACEMENT_NORMAL;
            errmsg("Wrong sideplacement");
        }
    
                {
                        
            element.axislabel->sideplacement = attribute.sideplacement;
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 34: /* #EStrTicks */
            
        element.ticks = ticks_new();
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrMajorStep)) {
                    
        attribute.dval = atof(avalue);
    
                {
                        
            element.ticks->major = attribute.dval;
        
                }
                } else
                if (!strcmp(aname, AStrMinorDivisions)) {
                    
        attribute.ival = atoi(avalue);
    
                {
                        
            element.ticks->nminor = attribute.ival;
        
                }
                } else
                if (!strcmp(aname, AStrAutoTicking)) {
                    
        attribute.ival = atoi(avalue);
    
                {
                        
            element.ticks->autonum = attribute.ival;
        
                }
                } else
                if (!strcmp(aname, AStrRoundedPosition)) {
                    
        attribute.bval = compare_strings(avalue, "yes");
    
                {
                        
            element.ticks->round = attribute.bval;
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 35: /* #EStrUserticks */
            
        element.uticks = uticks_new();
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrType)) {
                    
        if (!strcmp(avalue, VStrNone)) {
            attribute.uticktype = TICKS_SPEC_NONE;
        } else
        if (!strcmp(avalue, VStrTicks)) {
            attribute.uticktype = TICKS_SPEC_MARKS;
        } else
        if (!strcmp(avalue, VStrBoth)) {
            attribute.uticktype = TICKS_SPEC_BOTH;
        } else {
            attribute.uticktype = TICKS_SPEC_BOTH;
            errmsg("Wrong uticktype");
        }
    
                {
                        
            element.uticks->type = attribute.uticktype;
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 36: /* #EStrTickmarks */
            
        element.tmarks = tmarks_new();
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrActive)) {
                    
        attribute.bval = compare_strings(avalue, "yes");
    
                {
                        
            element.tmarks->active = attribute.bval;
        
                }
                } else
                if (!strcmp(aname, AStrSidePlacement)) {
                    
        if (!strcmp(avalue, VStrNormal)) {
            attribute.sideplacement = PLACEMENT_NORMAL;
        } else
        if (!strcmp(avalue, VStrOpposite)) {
            attribute.sideplacement = PLACEMENT_OPPOSITE;
        } else
        if (!strcmp(avalue, VStrBoth)) {
            attribute.sideplacement = PLACEMENT_BOTH;
        } else {
            attribute.sideplacement = PLACEMENT_NORMAL;
            errmsg("Wrong sideplacement");
        }
    
                {
                        
            element.tmarks->sideplacement = attribute.sideplacement;
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 37: /* #EStrMajor */
            
        element.tickprops = tickprops_new();
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrInoutPlacement)) {
                    
        if (!strcmp(avalue, VStrIn)) {
            attribute.inoutplacement = TICKS_IN;
        } else
        if (!strcmp(avalue, VStrOut)) {
            attribute.inoutplacement = TICKS_OUT;
        } else
        if (!strcmp(avalue, VStrBoth)) {
            attribute.inoutplacement = TICKS_BOTH;
        } else {
            attribute.inoutplacement = TICKS_IN;
            errmsg("Wrong inoutplacement");
        }
    
                {
                        
            element.tickprops->inout = attribute.inoutplacement;
        
                }
                } else
                if (!strcmp(aname, AStrSize)) {
                    
        attribute.dval = atof(avalue);
    
                {
                        
            element.tickprops->size = attribute.dval;
        
                }
                } else
                if (!strcmp(aname, AStrGridLines)) {
                    
        attribute.bval = compare_strings(avalue, "yes");
    
                {
                        
            element.tickprops->gridflag = attribute.bval;
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 38: /* #EStrMinor */
            
        element.tickprops = tickprops_new();
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrInoutPlacement)) {
                    
        if (!strcmp(avalue, VStrIn)) {
            attribute.inoutplacement = TICKS_IN;
        } else
        if (!strcmp(avalue, VStrOut)) {
            attribute.inoutplacement = TICKS_OUT;
        } else
        if (!strcmp(avalue, VStrBoth)) {
            attribute.inoutplacement = TICKS_BOTH;
        } else {
            attribute.inoutplacement = TICKS_IN;
            errmsg("Wrong inoutplacement");
        }
    
                {
                        
            element.tickprops->inout = attribute.inoutplacement;
        
                }
                } else
                if (!strcmp(aname, AStrSize)) {
                    
        attribute.dval = atof(avalue);
    
                {
                        
            element.tickprops->size = attribute.dval;
        
                }
                } else
                if (!strcmp(aname, AStrGridLines)) {
                    
        attribute.bval = compare_strings(avalue, "yes");
    
                {
                        
            element.tickprops->gridflag = attribute.bval;
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 39: /* #EStrTicklabels */
            
        element.tlabels = tlabels_new();
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrActive)) {
                    
        attribute.bval = compare_strings(avalue, "yes");
    
                {
                        
            element.tlabels->active = attribute.bval;
        
                }
                } else
                if (!strcmp(aname, AStrSidePlacement)) {
                    
        if (!strcmp(avalue, VStrNormal)) {
            attribute.sideplacement = PLACEMENT_NORMAL;
        } else
        if (!strcmp(avalue, VStrOpposite)) {
            attribute.sideplacement = PLACEMENT_OPPOSITE;
        } else
        if (!strcmp(avalue, VStrBoth)) {
            attribute.sideplacement = PLACEMENT_BOTH;
        } else {
            attribute.sideplacement = PLACEMENT_NORMAL;
            errmsg("Wrong sideplacement");
        }
    
                {
                        
            element.tlabels->sideplacement = attribute.sideplacement;
        
                }
                } else
                if (!strcmp(aname, AStrTransform)) {
                    
        attribute.sval = utf2iso(avalue);
    
                {
                        
            element.tlabels->transform = attribute.sval;
        
                }
                } else
                if (!strcmp(aname, AStrPrepend)) {
                    
        attribute.sval = utf2iso(avalue);
    
                {
                        
            element.tlabels->prepend = attribute.sval;
        
                }
                } else
                if (!strcmp(aname, AStrAppend)) {
                    
        attribute.sval = utf2iso(avalue);
    
                {
                        
            element.tlabels->append = attribute.sval;
        
                }
                } else
                if (!strcmp(aname, AStrOffset)) {
                    
        if (!strcmp(avalue, VStrAuto)) {
            attribute.offset = NULL;
        } else {
            attribute.offset = xmalloc(sizeof(VPoint));
            sscanf(avalue, "(%lg, %lg)", &(attribute.offset->x), &(attribute.offset->y));
        }
    
                {
                        
            if (attribute.offset) {
                element.tlabels->autoplace = FALSE;
                element.tlabels->offset.x  = attribute.offset->x;
                element.tlabels->offset.y  = attribute.offset->y;
                xfree(attribute.offset);
            } else {
                element.tlabels->autoplace = TRUE;
            }
        
                }
                } else
                if (!strcmp(aname, AStrSkip)) {
                    
        attribute.ival = atoi(avalue);
    
                {
                        
            element.tlabels->skip = attribute.ival;
        
                }
                } else
                if (!strcmp(aname, AStrStagger)) {
                    
        attribute.ival = atoi(avalue);
    
                {
                        
            element.tlabels->stagger = attribute.ival;
        
                }
                } else
                if (!strcmp(aname, AStrStart)) {
                    
        attribute.autodateordval = xmalloc(sizeof(Autoval));
        if (!strcmp(avalue, VStrAuto)) {
            attribute.autodateordval->autov = TRUE;
            attribute.autodateordval->value = 0.0;
        } else {
            attribute.autodateordval->autov = FALSE;
            if (parse_date_or_number(xcc_get_root(pdata), avalue, FALSE, &attribute.autodateordval->value) != RETURN_SUCCESS) {
                    attribute.autodateordval->value = 0.0;
            }
        }
    
                {
                        
            element.tlabels->autostart = attribute.autodateordval->autov;
            element.tlabels->start     = attribute.autodateordval->value;
            xfree(attribute.autodateordval);
        
                }
                } else
                if (!strcmp(aname, AStrStop)) {
                    
        attribute.autodateordval = xmalloc(sizeof(Autoval));
        if (!strcmp(avalue, VStrAuto)) {
            attribute.autodateordval->autov = TRUE;
            attribute.autodateordval->value = 0.0;
        } else {
            attribute.autodateordval->autov = FALSE;
            if (parse_date_or_number(xcc_get_root(pdata), avalue, FALSE, &attribute.autodateordval->value) != RETURN_SUCCESS) {
                    attribute.autodateordval->value = 0.0;
            }
        }
    
                {
                        
            element.tlabels->autostop = attribute.autodateordval->autov;
            element.tlabels->stop     = attribute.autodateordval->value;
            xfree(attribute.autodateordval);
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 40: /* #EStrTick */
            
        element.tick = tick_new();
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrType)) {
                    
        if (!strcmp(avalue, VStrMajor)) {
            attribute.ticktype = TICK_TYPE_MAJOR;
        } else
        if (!strcmp(avalue, VStrMinor)) {
            attribute.ticktype = TICK_TYPE_MINOR;
        } else {
            attribute.ticktype = TICK_TYPE_MINOR;
            errmsg("Wrong ticktype");
        }
    
                {
                        
            element.tick->type = attribute.ticktype;
        
                }
                } else
                if (!strcmp(aname, AStrPosition)) {
                    
        if (parse_date_or_number(xcc_get_root(pdata), avalue, FALSE, &attribute.dateordval) != RETURN_SUCCESS) {
                attribute.dateordval = 0.0;
        }
    
                {
                        
            element.tick->wtpos = attribute.dateordval;
        
                }
                } else
                if (!strcmp(aname, AStrLabel)) {
                    
        attribute.sval = utf2iso(avalue);
    
                {
                        
            element.tick->label = attribute.sval;
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 41: /* #EStrFormat */
            
        element.format = format_new();
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrFormat)) {
                    
        attribute.ftype = get_format_type_by_name(avalue);
    
                {
                        
            element.format->type = attribute.ftype;
        
                }
                } else
                if (!strcmp(aname, AStrPrec)) {
                    
        attribute.ival = atoi(avalue);
    
                {
                        
            element.format->prec = attribute.ival;
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 42: /* #EStrObject */
            
        element.object = object_new((Quark *)pnode->data);
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrId)) {
                    
        attribute.sval = utf2iso(avalue);
    
                {
                        
            quark_idstr_set(element.object, attribute.sval);
            xfree(attribute.sval);
        
                }
                } else
                if (!strcmp(aname, AStrActive)) {
                    
        attribute.bval = compare_strings(avalue, "yes");
    
                {
                        
            quark_set_active(element.object, attribute.bval);
        
                }
                } else
                if (!strcmp(aname, AStrAngle)) {
                    
        attribute.dval = atof(avalue);
    
                {
                        
            object_set_angle(element.object, attribute.dval);
        
                }
                } else
                if (!strcmp(aname, AStrOffset)) {
                    
        if (!strcmp(avalue, VStrAuto)) {
            attribute.offset = NULL;
        } else {
            attribute.offset = xmalloc(sizeof(VPoint));
            sscanf(avalue, "(%lg, %lg)", &(attribute.offset->x), &(attribute.offset->y));
        }
    
                {
                        
            object_set_offset(element.object, attribute.offset);
            xfree(attribute.offset);
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 43: /* #EStrLocation */
            
        element.location = location_new();
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrX)) {
                    
        if (parse_date_or_number(xcc_get_root(pdata), avalue, FALSE, &attribute.dateordval) != RETURN_SUCCESS) {
                attribute.dateordval = 0.0;
        }
    
                {
                        
            element.location->ap.x = attribute.dateordval;
        
                }
                } else
                if (!strcmp(aname, AStrY)) {
                    
        if (parse_date_or_number(xcc_get_root(pdata), avalue, FALSE, &attribute.dateordval) != RETURN_SUCCESS) {
                attribute.dateordval = 0.0;
        }
    
                {
                        
            element.location->ap.y = attribute.dateordval;
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 44: /* #EStrBoxData */
            
        element.do_box_data = object_odata_new(DO_BOX);
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrWidth)) {
                    
        attribute.dval = atof(avalue);
    
                {
                        
            element.do_box_data->width = attribute.dval;
        
                }
                } else
                if (!strcmp(aname, AStrHeight)) {
                    
        attribute.dval = atof(avalue);
    
                {
                        
            element.do_box_data->height = attribute.dval;
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 45: /* #EStrArcData */
            
        element.do_arc_data = object_odata_new(DO_ARC);
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrWidth)) {
                    
        attribute.dval = atof(avalue);
    
                {
                        
            element.do_arc_data->width = attribute.dval;
        
                }
                } else
                if (!strcmp(aname, AStrHeight)) {
                    
        attribute.dval = atof(avalue);
    
                {
                        
            element.do_arc_data->height = attribute.dval;
        
                }
                } else
                if (!strcmp(aname, AStrStartAngle)) {
                    
        attribute.dval = atof(avalue);
    
                {
                        
            element.do_arc_data->angle1 = attribute.dval;
        
                }
                } else
                if (!strcmp(aname, AStrExtentAngle)) {
                    
        attribute.dval = atof(avalue);
    
                {
                        
            element.do_arc_data->angle2 = attribute.dval;
        
                }
                } else
                if (!strcmp(aname, AStrFillMode)) {
                    
        attribute.ival = atoi(avalue);
    
                {
                        
            element.do_arc_data->fillmode = attribute.ival;
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 46: /* #EStrLineData */
            
        element.do_line_data = object_odata_new(DO_LINE);
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrX)) {
                    
        attribute.dval = atof(avalue);
    
                {
                        
            element.do_line_data->vector.x = attribute.dval;
        
                }
                } else
                if (!strcmp(aname, AStrY)) {
                    
        attribute.dval = atof(avalue);
    
                {
                        
            element.do_line_data->vector.y = attribute.dval;
        
                }
                } else
                if (!strcmp(aname, AStrArrowsAt)) {
                    
        attribute.ival = atoi(avalue);
    
                {
                        
            element.do_line_data->arrow_end = attribute.ival;
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 47: /* #EStrAText */
            
        element.atext = atext_new((Quark *)pnode->data);
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrId)) {
                    
        attribute.sval = utf2iso(avalue);
    
                {
                        
            quark_idstr_set(element.atext, attribute.sval);
            xfree(attribute.sval);
        
                }
                } else
                if (!strcmp(aname, AStrActive)) {
                    
        attribute.bval = compare_strings(avalue, "yes");
    
                {
                        
            quark_set_active(element.atext, attribute.bval);
        
                }
                } else
                if (!strcmp(aname, AStrOffset)) {
                    
        if (!strcmp(avalue, VStrAuto)) {
            attribute.offset = NULL;
        } else {
            attribute.offset = xmalloc(sizeof(VPoint));
            sscanf(avalue, "(%lg, %lg)", &(attribute.offset->x), &(attribute.offset->y));
        }
    
                {
                        
            atext_set_offset(element.atext, attribute.offset);
            xfree(attribute.offset);
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 48: /* #EStrTextFrame */
            
        element.textframe = textframe_new();
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrType)) {
                    
        attribute.ival = atoi(avalue);
    
                {
                        
            element.textframe->decor = attribute.ival;
        
                }
                } else
                if (!strcmp(aname, AStrOffset)) {
                    
        attribute.dval = atof(avalue);
    
                {
                        
            element.textframe->offset = attribute.dval;
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 49: /* #EStrPointer */
            
        element.textpointer = textpointer_new();
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrActive)) {
                    
        attribute.bval = compare_strings(avalue, "yes");
    
                {
                        
            element.textpointer->active = attribute.bval;
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 50: /* #EStrArrow */
            
        element.arrow = arrow_new();
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrType)) {
                    
        attribute.ival = atoi(avalue);
    
                {
                        
            element.arrow->type = attribute.ival;
        
                }
                } else
                if (!strcmp(aname, AStrLength)) {
                    
        attribute.dval = atof(avalue);
    
                {
                        
            element.arrow->length = attribute.dval;
        
                }
                } else
                if (!strcmp(aname, AStrDlFf)) {
                    
        attribute.dval = atof(avalue);
    
                {
                        
            element.arrow->dL_ff = attribute.dval;
        
                }
                } else
                if (!strcmp(aname, AStrLlFf)) {
                    
        attribute.dval = atof(avalue);
    
                {
                        
            element.arrow->lL_ff = attribute.dval;
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 51: /* #EStrSet */
            
        element.set = grace_set_new((Quark *)pnode->data);
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrId)) {
                    
        attribute.sval = utf2iso(avalue);
    
                {
                        
            quark_idstr_set(element.set, attribute.sval);
            xfree(attribute.sval);
        
                }
                } else
                if (!strcmp(aname, AStrActive)) {
                    
        attribute.bval = compare_strings(avalue, "yes");
    
                {
                        
            quark_set_active(element.set, attribute.bval);
        
                }
                } else
                if (!strcmp(aname, AStrType)) {
                    
        RunTime *rt = ((ParserData *)pdata->udata)->rt;
        attribute.settype = get_settype_by_name(rt, avalue);
    
                {
                        
            set_set_type(element.set, attribute.settype);
        
                }
                } else
                if (!strcmp(aname, AStrSkip)) {
                    
        attribute.ival = atoi(avalue);
    
                {
                        
            set_set_symskip(element.set, attribute.ival);
        
                }
                } else
                if (!strcmp(aname, AStrSkipMinDist)) {
                    
        attribute.dval = atof(avalue);
    
                {
                        
            set_set_symskipmindist(element.set, attribute.dval);
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 52: /* #EStrSymbol */
            
        element.symbol = symbol_new();
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrType)) {
                    
        attribute.ival = atoi(avalue);
    
                {
                        
            element.symbol->type = attribute.ival;
        
                }
                } else
                if (!strcmp(aname, AStrSize)) {
                    
        attribute.dval = atof(avalue);
    
                {
                        
            element.symbol->size = attribute.dval;
        
                }
                } else
                if (!strcmp(aname, AStrChar)) {
                    
        attribute.ival = atoi(avalue);
    
                {
                        
            element.symbol->symchar = attribute.ival;
        
                }
                } else
                if (!strcmp(aname, AStrFontId)) {
                    
        attribute.fontid = atoi(avalue);
    
                {
                        
            element.symbol->charfont = attribute.fontid;
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 53: /* #EStrLine */
            
        element.setline = setline_new();
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrType)) {
                    
        attribute.ival = atoi(avalue);
    
                {
                        
            element.setline->type = attribute.ival;
        
                }
                } else
                if (!strcmp(aname, AStrFillType)) {
                    
        attribute.ival = atoi(avalue);
    
                {
                        
            element.setline->filltype = attribute.ival;
        
                }
                } else
                if (!strcmp(aname, AStrFillRule)) {
                    
        if (!strcmp(avalue, VStrWinding)) {
            attribute.fillrule = FILLRULE_WINDING;
        } else {
            attribute.fillrule = FILLRULE_EVENODD;
        }
    
                {
                        
            element.setline->fillrule = attribute.fillrule;
        
                }
                } else
                if (!strcmp(aname, AStrBaselineType)) {
                    
        attribute.ival = atoi(avalue);
    
                {
                        
            element.setline->baseline_type = attribute.ival;
        
                }
                } else
                if (!strcmp(aname, AStrDrawBaseline)) {
                    
        attribute.bval = compare_strings(avalue, "yes");
    
                {
                        
            element.setline->baseline = attribute.bval;
        
                }
                } else
                if (!strcmp(aname, AStrDrawDroplines)) {
                    
        attribute.bval = compare_strings(avalue, "yes");
    
                {
                        
            element.setline->droplines = attribute.bval;
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 54: /* #EStrAnnotation */
            
        element.annotation = avalue_new();
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrActive)) {
                    
        attribute.bval = compare_strings(avalue, "yes");
    
                {
                        
            element.annotation->active = attribute.bval;
        
                }
                } else
                if (!strcmp(aname, AStrType)) {
                    
        attribute.ival = atoi(avalue);
    
                {
                        
            element.annotation->type = attribute.ival;
        
                }
                } else
                if (!strcmp(aname, AStrOffset)) {
                    
        if (!strcmp(avalue, VStrAuto)) {
            attribute.offset = NULL;
        } else {
            attribute.offset = xmalloc(sizeof(VPoint));
            sscanf(avalue, "(%lg, %lg)", &(attribute.offset->x), &(attribute.offset->y));
        }
    
                {
                        
            if (attribute.offset) {
                element.annotation->offset = *(attribute.offset);
                xfree(attribute.offset);
            }
        
                }
                } else
                if (!strcmp(aname, AStrPrepend)) {
                    
        attribute.sval = utf2iso(avalue);
    
                {
                        
            element.annotation->prestr = attribute.sval;
        
                }
                } else
                if (!strcmp(aname, AStrAppend)) {
                    
        attribute.sval = utf2iso(avalue);
    
                {
                        
            element.annotation->appstr = attribute.sval;
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 55: /* #EStrTextProperties */
            
        element.textprops = textprops_new();
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrAngle)) {
                    
        attribute.dval = atof(avalue);
    
                {
                        
            element.textprops->angle = attribute.dval;
        
                }
                } else
                if (!strcmp(aname, AStrJustification)) {
                    
        attribute.ival = atoi(avalue);
    
                {
                        
            element.textprops->just = attribute.ival;
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 56: /* #EStrErrorbar */
            
        element.errorbar = xmalloc(sizeof(Errbar));
        memset(element.errorbar, 0, sizeof(Errbar));
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrActive)) {
                    
        attribute.bval = compare_strings(avalue, "yes");
    
                {
                        
            element.errorbar->active = attribute.bval;
        
                }
                } else
                if (!strcmp(aname, AStrSidePlacement)) {
                    
        if (!strcmp(avalue, VStrNormal)) {
            attribute.sideplacement = PLACEMENT_NORMAL;
        } else
        if (!strcmp(avalue, VStrOpposite)) {
            attribute.sideplacement = PLACEMENT_OPPOSITE;
        } else
        if (!strcmp(avalue, VStrBoth)) {
            attribute.sideplacement = PLACEMENT_BOTH;
        } else {
            attribute.sideplacement = PLACEMENT_NORMAL;
            errmsg("Wrong sideplacement");
        }
    
                {
                        
            element.errorbar->ptype = attribute.sideplacement;
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 57: /* #EStrBarline */
            
        element.barline = barline_new();
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrSize)) {
                    
        attribute.dval = atof(avalue);
    
                {
                        
            element.barline->size = attribute.dval;
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 58: /* #EStrRiserline */
            
        element.riserline = riserline_new();
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrArrowClip)) {
                    
        attribute.bval = compare_strings(avalue, "yes");
    
                {
                        
            element.riserline->arrow_clip = attribute.bval;
        
                }
                } else
                if (!strcmp(aname, AStrClipLength)) {
                    
        attribute.dval = atof(avalue);
    
                {
                        
            element.riserline->clip_length = attribute.dval;
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 59: /* #EStrLegendEntry */
            
        element.string = xcc_string_new();
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 60: /* #EStrDataset */
            
        element.dataset = dataset_new();
        ((ParserData *) pdata->udata)->nrow = 0;
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrCols)) {
                    
        attribute.ival = atoi(avalue);
    
                {
                        
            dataset_set_ncols(element.dataset, attribute.ival);
        
                }
                } else
                if (!strcmp(aname, AStrRows)) {
                    
        attribute.ival = atoi(avalue);
    
                {
                        
            dataset_set_nrows(element.dataset, attribute.ival);
        
                }
                } else
                if (!strcmp(aname, AStrComment)) {
                    
        attribute.sval = utf2iso(avalue);
    
                {
                        
            element.dataset->comment = attribute.sval;
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 61: /* #EStrRow */
            
        element.datapoint = datapoint_new();
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, "X")) {
                    
        if (parse_date_or_number(xcc_get_root(pdata), avalue, FALSE, &attribute.dateordval) != RETURN_SUCCESS) {
                attribute.dateordval = 0.0;
        }
    
                {
                        
            element.datapoint->ex[DATA_X] = attribute.dateordval;
        
                }
                } else
                if (!strcmp(aname, "Y")) {
                    
        if (parse_date_or_number(xcc_get_root(pdata), avalue, FALSE, &attribute.dateordval) != RETURN_SUCCESS) {
                attribute.dateordval = 0.0;
        }
    
                {
                        
            element.datapoint->ex[DATA_Y] = attribute.dateordval;
        
                }
                } else
                if (!strcmp(aname, "Y1")) {
                    
        if (parse_date_or_number(xcc_get_root(pdata), avalue, FALSE, &attribute.dateordval) != RETURN_SUCCESS) {
                attribute.dateordval = 0.0;
        }
    
                {
                        
            element.datapoint->ex[DATA_Y1] = attribute.dateordval;
        
                }
                } else
                if (!strcmp(aname, "Y2")) {
                    
        if (parse_date_or_number(xcc_get_root(pdata), avalue, FALSE, &attribute.dateordval) != RETURN_SUCCESS) {
                attribute.dateordval = 0.0;
        }
    
                {
                        
            element.datapoint->ex[DATA_Y2] = attribute.dateordval;
        
                }
                } else
                if (!strcmp(aname, "Y3")) {
                    
        if (parse_date_or_number(xcc_get_root(pdata), avalue, FALSE, &attribute.dateordval) != RETURN_SUCCESS) {
                attribute.dateordval = 0.0;
        }
    
                {
                        
            element.datapoint->ex[DATA_Y3] = attribute.dateordval;
        
                }
                } else
                if (!strcmp(aname, "Y4")) {
                    
        if (parse_date_or_number(xcc_get_root(pdata), avalue, FALSE, &attribute.dateordval) != RETURN_SUCCESS) {
                attribute.dateordval = 0.0;
        }
    
                {
                        
            element.datapoint->ex[DATA_Y4] = attribute.dateordval;
        
                }
                } else
                if (!strcmp(aname, "s")) {
                    
        attribute.sval = utf2iso(avalue);
    
                {
                        
            element.datapoint->s = attribute.sval;
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    case 62: /* #EStrRegion */
            
        element.region = region_new((Quark *)pnode->data);
    
            for (i = 0; attr[i]; i += 2) {
                int askip = 0;
                aname  = xcc_get_local(attr[i], GRACE_NS_URI, &askip);
                avalue = attr[i + 1];
                if (!strcmp(aname, AStrId)) {
                    
        attribute.sval = utf2iso(avalue);
    
                {
                        
            quark_idstr_set(element.region, attribute.sval);
            xfree(attribute.sval);
        
                }
                } else
                if (!strcmp(aname, AStrActive)) {
                    
        attribute.bval = compare_strings(avalue, "yes");
    
                {
                        
            quark_set_active(element.region, attribute.bval);
        
                }
                } else
                if (!strcmp(aname, AStrType)) {
                    
        RunTime *rt = ((ParserData *)pdata->udata)->rt;
        attribute.regiontype = get_regiontype_by_name(rt, avalue);
    
                {
                        
            region_set_type(element.region, attribute.regiontype);
        
                }
                } else
                if (!strcmp(aname, AStrColorId)) {
                    
        attribute.ival = atoi(avalue);
    
                {
                        
            region_set_color(element.region, attribute.ival);
        
                }
                } else
                if (!askip) {
                    xcc_error("unknown attribute \"%s\" of element \"%s\"", aname, el_local);
                }
                xcc_free(aname);
            }
        break;
    default:
        element.unicast = NULL;
        if (!skip) {
            xcc_error("unknown element \"%s\"", el_local);
            pdata->error = 1;
        }
        break;
    }

    node = xcc_node_new();
    node->name = el_local;
    node->id = element_id;
    node->data = element.unicast;
    xcc_stack_increment(pdata->nodes, node);
}

void xcc_end_handler(void *data, const char *el)
{
    XCCParserData *pdata = (XCCParserData *) data;
    XCCNode *node, *pnode;
    void *p;
    int element_id, parent_id, parent_child, skip = 0;
    XCCEType element, pelement;
    char *cdata = pdata->cbuffer;

    if (pdata->error) {
        return;
    }

    xcc_stack_get_last(pdata->nodes, &p);
    node = p;
    element_id = node->id;
    element.unicast = node->data;
    switch (element_id) {
    case 14:
        {
            
            char *s;
            s = utf2iso(cdata);
            xcc_string_set(element.string, s);
            xfree(s);
        
        }
        break;
    }

    xcc_stack_decrement(pdata->nodes);
    if (xcc_stack_depth(pdata->nodes) == 0) {
        pdata->root = element.unicast;
        parent_id  = 0;
        pelement.unicast = NULL;
    } else {
        xcc_stack_get_last(pdata->nodes, &p);
        pnode = p;
        parent_id  = pnode->id;
        pelement.unicast = pnode->data;
    }
    if (parent_id >= 0 && element_id >= 0) {
        parent_child = 62*parent_id + element_id;
    } else {
        parent_child = -1;
        skip = 1;
    }

    switch (parent_child) {
    case 1:
        break;
    case 71:
        {
        
            project_set_description(pelement.project, element.string->s);
            xcc_string_free(element.string);
        
        }
        break;
    case 64:
        {
        
        
        }
        break;
    case 70:
        {
        
            Project *pr  = project_get_data(pelement.project);
            pr->page_wpp = element.page->width;
            pr->page_hpp = element.page->height,
            pr->bgfill   = element.page->bgfill;
            pr->bgcolor  = element.page->bgcolor;
            xfree(element.page);
        
        }
        break;
    case 72:
        {
        
        
        }
        break;
    case 78:
        {
        
        
        }
        break;
    case 104:
        {
        
        
        }
        break;
    case 109:
        {
        
        
        }
        break;
    case 127:
        {
        
        
        }
        break;
    case 128:
        {
        
        
        }
        break;
    case 129:
        {
        
        
        }
        break;
    case 192:
        {
        
            project_add_color(xcc_get_root(pdata), element.colordef);
            colordef_free(element.colordef);
        
        }
        break;
    case 255:
        {
        
	    project_add_font(xcc_get_root(pdata), element.fontdef);
            fontdef_free(element.fontdef);
        
        }
        break;
    case 572:
        {
        
            xcc_string_set(pelement.string, element.string->s);
            xcc_string_free(element.string);
        
        }
        break;
    case 632:
        {
        
        
        }
        break;
    case 633:
        {
        
        
        }
        break;
    case 1011:
        {
        
            frame_set_view(pelement.frame, element.view);
            xfree(element.view);
        
        }
        break;
    case 1015:
        {
        
            frame_set_legend(pelement.frame, element.legend);
            xfree(element.legend);
        
        }
        break;
    case 1017:
        {
        
            frame_set_outline(pelement.frame, element.line);
            xfree(element.line);
        
        }
        break;
    case 1007:
        {
        
            frame_set_fillpen(pelement.frame, element.pen);
            xfree(element.pen);
        
        }
        break;
    case 1009:
        {
        
        
        }
        break;
    case 1034:
        {
        
        
        }
        break;
    case 1039:
        {
        
        
        }
        break;
    case 1072:
        {
        
            graph_set_type(pelement.graph, element.presentationspec->type);
            graph_set_bargap(pelement.graph, element.presentationspec->bargap);
            graph_set_stacked(pelement.graph, element.presentationspec->stacked);
            presentationspec_free(element.presentationspec);
        
        }
        break;
    case 1074:
        {
        
            world w;
            graph_get_world(pelement.graph, &w);
            w.xg1 = element.scale->min;
            w.xg2 = element.scale->max;
            graph_set_world(pelement.graph, &w);
            graph_set_xscale(pelement.graph, element.scale->type);
            graph_set_xinvert(pelement.graph, element.scale->invert);
            xfree(element.scale);
        
        }
        break;
    case 1075:
        {
        
            world w;
            graph_get_world(pelement.graph, &w);
            w.yg1 = element.scale->min;
            w.yg2 = element.scale->max;
            graph_set_world(pelement.graph, &w);
            graph_set_yscale(pelement.graph, element.scale->type);
            graph_set_yinvert(pelement.graph, element.scale->invert);
            xfree(element.scale);
        
        }
        break;
    case 1076:
        {
        
            graph_set_znorm(pelement.graph, *(element.dptr));
            xfree(element.dptr);
        
        }
        break;
    case 1080:
        {
        
            graph_set_locator(pelement.graph, element.glocator);
            xfree(element.glocator);
        
        }
        break;
    case 1084:
        {
        
        
        }
        break;
    case 1105:
        {
        
        
        }
        break;
    case 1096:
        {
        
        
        }
        break;
    case 1101:
        {
        
        
        }
        break;
    case 1116:
        {
        
        
        }
        break;
    case 1437:
        {
        
            pelement.legend->font     = element.facespec->font;
            pelement.legend->color    = element.facespec->color;
            pelement.legend->charsize = element.facespec->size;
            facespec_free(element.facespec);
        
        }
        break;
    case 1450:
        {
        
            pelement.legend->boxfillpen = element.legframe->fillpen;
            pelement.legend->boxline    = element.legframe->line;
            pelement.legend->anchor     = element.legframe->anchor;
            pelement.legend->just       = element.legframe->just;
            pelement.legend->offset     = element.legframe->offset;
            xfree(element.legframe);
        
        }
        break;
    case 1513:
        {
        
            pelement.legframe->line = *(element.line);
            xfree(element.line);
        
        }
        break;
    case 1503:
        {
        
            pelement.legframe->fillpen = *(element.pen);
            xfree(element.pen);
        
        }
        break;
    case 1639:
        {
        
            pelement.glocator->pointset = element.fixedpoint->active;
            pelement.glocator->origin.x = element.fixedpoint->x;
            pelement.glocator->origin.y = element.fixedpoint->y;
            xfree(element.fixedpoint);
        
        }
        break;
    case 1640:
        {
        
            pelement.glocator->fx = element.format->type;
            pelement.glocator->px = element.format->prec;
            xfree(element.format);
        
        }
        break;
    case 1641:
        {
        
            pelement.glocator->fy = element.format->type;
            pelement.glocator->py = element.format->prec;
            xfree(element.format);
        
        }
        break;
    case 1891:
        {
        
            tickmarks *t = axis_get_data(pelement.axis);
            if (t) {
                t->zero   = element.axisplacement->zero;
                t->offsx  = element.axisplacement->offset.x;
                t->offsy  = element.axisplacement->offset.y;
            }
            xfree(element.axisplacement);
        
        }
        break;
    case 1892:
        {
        
            tickmarks *t = axis_get_data(pelement.axis);
            if (t) {
                t->t_drawbar      = element.axisbar->active;
                t->t_drawbarcolor = element.axisbar->line.pen.color;
                t->t_drawbarlines = element.axisbar->line.style;
                t->t_drawbarlinew = element.axisbar->line.width;
            }
            xfree(element.axisbar);
        
        }
        break;
    case 1893:
        {
        
            tickmarks *t = axis_get_data(pelement.axis);
            if (t) {
                t->label        = element.axislabel->s;
                t->label_tprops = element.axislabel->tprops;
            
                t->label_layout = element.axislabel->layout;
                t->label_place  = element.axislabel->autoplace ? TYPE_AUTO:TYPE_SPEC;
                t->label_offset = element.axislabel->offset;
                t->label_op     = element.axislabel->sideplacement;
            }
            xfree(element.axislabel);
        
        }
        break;
    case 1894:
        {
        
            tickmarks *t = axis_get_data(pelement.axis);
            if (t) {
                t->tmajor    = element.ticks->major;
                t->nminor    = element.ticks->nminor;
                t->t_autonum = element.ticks->autonum;
                t->t_round   = element.ticks->round;

                t->t_flag    = element.ticks->tmarks.active;
                t->t_op      = element.ticks->tmarks.sideplacement;
                t->props     = element.ticks->tmarks.props;
                t->mprops    = element.ticks->tmarks.mprops;

                t->t_spec    = element.ticks->uticks.type;
                if (t->t_spec != TICKS_SPEC_NONE) {
                    int i;
                    t->nticks = element.ticks->uticks.nticks;
                    for (i = 0; i < t->nticks; i++) {
                        t->tloc[i] = element.ticks->uticks.tloc[i];
                    }
                }

                t->tl_flag      = element.ticks->tlabels.active;

                t->tl_op        = element.ticks->tlabels.sideplacement;
                t->tl_formula   = element.ticks->tlabels.transform;
                t->tl_tprops    = element.ticks->tlabels.tprops;
                t->tl_skip      = element.ticks->tlabels.skip;
                t->tl_staggered = element.ticks->tlabels.stagger;
                t->tl_format    = element.ticks->tlabels.format.type;
                t->tl_prec      = element.ticks->tlabels.format.prec;
                t->tl_gaptype   = element.ticks->tlabels.autoplace ? TYPE_AUTO:TYPE_SPEC;
                t->tl_gap.x     = element.ticks->tlabels.offset.x;
                t->tl_gap.y     = element.ticks->tlabels.offset.y;
                t->tl_starttype = element.ticks->tlabels.autostart ? TYPE_AUTO:TYPE_SPEC;
                t->tl_start     = element.ticks->tlabels.start;
                t->tl_stoptype  = element.ticks->tlabels.autostop ? TYPE_AUTO:TYPE_SPEC;
                t->tl_stop      = element.ticks->tlabels.stop;
                t->tl_prestr    = copy_string(NULL, element.ticks->tlabels.prepend);
                t->tl_appstr    = copy_string(NULL, element.ticks->tlabels.append);
            }
            xfree(element.ticks->tlabels.prepend);
            xfree(element.ticks->tlabels.append);
            xfree(element.ticks);
        
        }
        break;
    case 2009:
        {
        
            pelement.axisbar->line = *(element.line);
            xfree(element.line);
        
        }
        break;
    case 2101:
        {
        
            pelement.axislabel->tprops = *element.textprops;
            xfree(element.textprops);
        
        }
        break;
    case 2060:
        {
        
            pelement.axislabel->s = copy_string(NULL, element.string->s);
            xcc_string_free(element.string);
        
        }
        break;
    case 2143:
        {
        
            pelement.ticks->uticks = *(element.uticks);
            xfree(element.uticks);
        
        }
        break;
    case 2144:
        {
        
            pelement.ticks->tmarks = *(element.tmarks);
            xfree(element.tmarks);
        
        }
        break;
    case 2147:
        {
        
            pelement.ticks->tlabels = *(element.tlabels);
            xfree(element.tlabels);
        
        }
        break;
    case 2210:
        {
        
            utick_add(pelement.uticks, element.tick);
            xfree(element.tick);
        
        }
        break;
    case 2269:
        {
        
            pelement.tmarks->props = *(element.tickprops);
            xfree(element.tickprops);
        
        }
        break;
    case 2270:
        {
        
            pelement.tmarks->mprops = *(element.tickprops);
            xfree(element.tickprops);
        
        }
        break;
    case 2319:
        {
        
            pelement.tickprops->color = element.line->pen.color;
            pelement.tickprops->linew = element.line->width;
            pelement.tickprops->lines = element.line->style;
            xfree(element.line);
        
        }
        break;
    case 2381:
        {
        
            pelement.tickprops->color = element.line->pen.color;
            pelement.tickprops->linew = element.line->width;
            pelement.tickprops->lines = element.line->style;
            xfree(element.line);
        
        }
        break;
    case 2473:
        {
        
            pelement.tlabels->tprops = *(element.textprops);
            xfree(element.textprops);
        
        }
        break;
    case 2459:
        {
        
            pelement.tlabels->format = *(element.format);
            xfree(element.format);
        
        }
        break;
    case 2629:
        {
        
            object_set_line(pelement.object, element.line);
            xfree(element.line);
        
        }
        break;
    case 2647:
        {
        
            object_set_location(pelement.object, &(element.location->ap));
            xfree(element.location);
        
        }
        break;
    case 2619:
        {
        
            object_set_fillpen(pelement.object, element.pen);
            xfree(element.pen);
        
        }
        break;
    case 2650:
        {
        
            DObject *o = object_get_data(pelement.object);
            if (o) {
                o->odata = element.do_line_data;
                o->type  = DO_LINE;
            }
        
        }
        break;
    case 2648:
        {
        
            DObject *o = object_get_data(pelement.object);
            if (o) {
                o->odata = element.do_box_data;
                o->type  = DO_BOX;
            }
        
        }
        break;
    case 2649:
        {
        
            DObject *o = object_get_data(pelement.object);
            if (o) {
                o->odata = element.do_arc_data;
                o->type  = DO_ARC;
            }
        
        }
        break;
    case 2902:
        {
        
            pelement.do_line_data->arrow = *(element.arrow);
            xfree(element.arrow);
        
        }
        break;
    case 2957:
        {
        
            atext_set_ap(pelement.atext, &(element.location->ap));
            xfree(element.location);
        
        }
        break;
    case 2928:
        {
        
            atext_set_string(pelement.atext, element.string->s);
            xcc_string_free(element.string);
        
        }
        break;
    case 2969:
        {
        
            atext_set_tprops(pelement.atext, element.textprops);
            xfree(element.textprops);
        
        }
        break;
    case 2962:
        {
        
            AText *at = atext_get_data(pelement.atext);
            if (at) {
                at->frame_decor  = element.textframe->decor;
                at->frame_offset = element.textframe->offset;
                at->line         = element.textframe->line;
                at->fillpen      = element.textframe->fillpen;
            }
            xfree(element.textframe);
        
        }
        break;
    case 2963:
        {
        
            AText *at = atext_get_data(pelement.atext);
            if (at) {
                at->arrow_flag = element.textpointer->active;
                at->arrow      = element.textpointer->arrow;
            }
            xfree(element.textpointer);
        
        }
        break;
    case 3001:
        {
        
            pelement.textframe->line = *(element.line);
            xfree(element.line);
        
        }
        break;
    case 2991:
        {
        
            pelement.textframe->fillpen = *(element.pen);
            xfree(element.pen);
        
        }
        break;
    case 3088:
        {
        
            pelement.textpointer->arrow = *(element.arrow);
            xfree(element.arrow);
        
        }
        break;
    case 3214:
        {
        
            set_set_symbol(pelement.set, element.symbol);
            xfree(element.symbol);
        
        }
        break;
    case 3215:
        {
        
            set_set_line(pelement.set, element.setline);
            xfree(element.setline);
        
        }
        break;
    case 3216:
        {
        
            set_set_avalue(pelement.set, element.annotation);
            avalue_free(element.annotation);
        
        }
        break;
    case 3218:
        {
        
            set_set_errbar(pelement.set, element.errorbar);
            xfree(element.errorbar);
        
        }
        break;
    case 3221:
        {
        
            set_set_legstr(pelement.set, element.string->s);
            xcc_string_free(element.string);
        
        }
        break;
    case 3222:
        {
        
            set_set_dataset(pelement.set, element.dataset);
        
        }
        break;
    case 3249:
        {
        
            pelement.symbol->line = *(element.line);
            xfree(element.line);
        
        }
        break;
    case 3239:
        {
        
            pelement.symbol->fillpen = *(element.pen);
            xfree(element.pen);
        
        }
        break;
    case 3311:
        {
        
            pelement.setline->line = *(element.line);
            xfree(element.line);
        
        }
        break;
    case 3301:
        {
        
            pelement.setline->fillpen = *(element.pen);
            xfree(element.pen);
        
        }
        break;
    case 3403:
        {
        
            pelement.annotation->tprops = *element.textprops;
            xfree(element.textprops);
        
        }
        break;
    case 3389:
        {
        
            pelement.annotation->format = element.format->type;
            pelement.annotation->prec   = element.format->prec;
            xfree(element.format);
        
        }
        break;
    case 3421:
        {
        
            pelement.textprops->charsize  = element.facespec->size;
            pelement.textprops->font      = element.facespec->font;
            pelement.textprops->color     = element.facespec->color;
            xfree(element.facespec);
        
        }
        break;
    case 3529:
        {
        
            pelement.errorbar->barsize = element.barline->size;
            pelement.errorbar->pen     = element.barline->line.pen;
            pelement.errorbar->linew   = element.barline->line.width;
            pelement.errorbar->lines   = element.barline->line.style;
            xfree(element.barline);
        
        }
        break;
    case 3530:
        {
        
            pelement.errorbar->arrow_clip  = element.riserline->arrow_clip;
            pelement.errorbar->cliplen     = element.riserline->clip_length;
            pelement.errorbar->riser_linew = element.riserline->line.width;
            pelement.errorbar->riser_lines = element.riserline->line.style;
            xfree(element.riserline);
        
        }
        break;
    case 3559:
        {
        
            pelement.barline->line = *(element.line);
            xfree(element.line);
        
        }
        break;
    case 3621:
        {
        
            pelement.riserline->line = *(element.line);
            xfree(element.line);
        
        }
        break;
    case 3672:
        {
        
            xcc_string_set(pelement.string, element.string->s);
            xcc_string_free(element.string);
        
        }
        break;
    case 3781:
        {
        
            dataset_set_datapoint(pelement.dataset, element.datapoint, ((ParserData *) pdata->udata)->nrow);
            datapoint_free(element.datapoint);
            ((ParserData *) pdata->udata)->nrow++;
        
        }
        break;
    case 3905:
        {
        
            WPoint wp;
            wp.x = element.datapoint->ex[DATA_X];
            wp.y = element.datapoint->ex[DATA_Y];
            region_add_point(pelement.region, &wp);
            datapoint_free(element.datapoint);
        
        }
        break;
    default:
        if (!skip) {
            xcc_error("internal error");
            pdata->error = 1;
        }
        break;
    }

    pdata->cbuflen = 0;
    if (pdata->cbufsize) {
        pdata->cbuffer[0] = '\0';
    }
}

int load_xgr_project(Grace *grace, char *fn)
{
    ParserData udata;
    void *p;
    Quark *project;
    FILE *fp;
    int ret;

    fp = grace_openr(grace, fn, SOURCE_DISK);
    if (fp == NULL) {
	return RETURN_FAILURE;
    }

    udata.rt = grace->rt;
    udata.nrow = -1;
    
    ret = xcc_parse(fp, &udata, &p, xcc_start_handler, xcc_end_handler);
    project = p;

    grace_close(fp);
    
    if (ret == XCC_RETURN_SUCCESS) {
        return grace_set_project(grace, project);
    } else {
        quark_free(project);
        
        return RETURN_FAILURE;
    }
}
    
