210 lines
4.9 KiB
C
210 lines
4.9 KiB
C
/* Notes */ /*{{{C}}}*//*{{{*/
|
|
/*
|
|
|
|
xdr_enum() is unusable, because enum_t may have a different size than
|
|
an enum. The construction
|
|
|
|
int_value=*enum_value;
|
|
result=xdr_int(xdrs,&int_value);
|
|
*enum_value=int_value;
|
|
return result;
|
|
|
|
solves the problem and works for both encoding and decoding.
|
|
Unfortunately, I could not yet find such a solution for a variable sized
|
|
array terminated by a special element.
|
|
|
|
*/
|
|
/*}}}*/
|
|
/* #includes */ /*{{{*/
|
|
#ifdef DMALLOC
|
|
#include "dmalloc.h"
|
|
#endif
|
|
|
|
#include <assert.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "sheet.h"
|
|
#include "xdr.h"
|
|
/*}}}*/
|
|
|
|
/* xdr_token */ /*{{{*/
|
|
static bool_t xdr_token(XDR *xdrs, Token *t)
|
|
{
|
|
int x,result;
|
|
|
|
if (xdrs->x_op==XDR_DECODE) (void)memset(t,0,sizeof(Token));
|
|
x=t->type;
|
|
if (t->type==OPERATOR) x|=t->u.op<<8;
|
|
result=xdr_int(xdrs,&x);
|
|
if ((x&0xff)==OPERATOR) t->u.op=(x>>8)&0xff;
|
|
t->type=x&0xff;
|
|
if (result==0) return result;
|
|
switch (t->type)
|
|
{
|
|
/* EMPTY */ /*{{{*/
|
|
case EMPTY:
|
|
{
|
|
return 1;
|
|
}
|
|
/*}}}*/
|
|
/* STRING */ /*{{{*/
|
|
case STRING:
|
|
{
|
|
return xdr_wrapstring(xdrs,&(t->u.string));
|
|
}
|
|
/*}}}*/
|
|
/* FLOAT */ /*{{{*/
|
|
case FLOAT:
|
|
{
|
|
return xdr_double(xdrs,&(t->u.flt));
|
|
}
|
|
/*}}}*/
|
|
/* INT */ /*{{{*/
|
|
case INT:
|
|
{
|
|
return xdr_long(xdrs,&(t->u.integer));
|
|
}
|
|
/*}}}*/
|
|
/* OPERATOR */ /*{{{*/
|
|
case OPERATOR:
|
|
{
|
|
return 1; /* since op is encoded in type */
|
|
}
|
|
/*}}}*/
|
|
/* LIDENT */ /*{{{*/
|
|
case LIDENT:
|
|
{
|
|
return xdr_wrapstring(xdrs,&(t->u.lident));
|
|
}
|
|
/*}}}*/
|
|
/* FIDENT */ /*{{{*/
|
|
case FIDENT:
|
|
{
|
|
return xdr_int(xdrs,&(t->u.fident));
|
|
}
|
|
/*}}}*/
|
|
/* LOCATION */ /*{{{*/
|
|
case LOCATION:
|
|
{
|
|
return (xdr_int(xdrs,&(t->u.location[0])) && xdr_int(xdrs,&(t->u.location[1])) && xdr_int(xdrs,&(t->u.location[2])));
|
|
}
|
|
/*}}}*/
|
|
/* EEK */ /*{{{*/
|
|
case EEK:
|
|
{
|
|
return xdr_wrapstring(xdrs,&(t->u.err));
|
|
}
|
|
/*}}}*/
|
|
/* default -- should not happen */ /*{{{*/
|
|
default: assert(0);
|
|
/*}}}*/
|
|
}
|
|
return 0;
|
|
}
|
|
/*}}}*/
|
|
/* xdr_tokenptr */ /*{{{*/
|
|
static bool_t xdr_tokenptr(XDR *xdrs, Token **t)
|
|
{
|
|
return xdr_pointer(xdrs,(char**)t,sizeof(Token),(xdrproc_t)xdr_token);
|
|
}
|
|
/*}}}*/
|
|
/* xdr_tokenptrvec */ /*{{{*/
|
|
static bool_t xdr_tokenptrvec(XDR *xdrs, Token ***t)
|
|
{
|
|
unsigned int len;
|
|
int result;
|
|
|
|
assert(t!=(Token***)0);
|
|
if (xdrs->x_op!=XDR_DECODE)
|
|
{
|
|
Token **run;
|
|
|
|
if (*t==(Token**)0) len=0;
|
|
else for (len=1,run=*t; *run!=(Token*)0; ++len,++run);
|
|
}
|
|
result=xdr_array(xdrs,(char**)t,&len,65536,sizeof(Token*),(xdrproc_t)xdr_tokenptr);
|
|
if (len==0) *t=(Token**)0;
|
|
return result;
|
|
}
|
|
/*}}}*/
|
|
/* xdr_mystring */ /*{{{*/
|
|
static bool_t xdr_mystring(XDR *xdrs, char **str)
|
|
{
|
|
static struct xdr_discrim arms[3]=
|
|
{
|
|
{ 0, (xdrproc_t)xdr_void },
|
|
{ 1, (xdrproc_t)xdr_wrapstring },
|
|
{ -1, (xdrproc_t)0 }
|
|
};
|
|
enum_t x;
|
|
int res;
|
|
|
|
x=(*str!=(char*)0);
|
|
res=xdr_union(xdrs, &x, (char*)str, arms, (xdrproc_t)0);
|
|
if (!x) *str=(char*)0;
|
|
return res;
|
|
}
|
|
/*}}}*/
|
|
|
|
/* Notes */ /*{{{*/
|
|
/*
|
|
|
|
The saved sheet consists of three xdr_int()s which specify x, y and z
|
|
position of the cell saved with xdr_cell(). Perhaps xdr_cell could be
|
|
given those as parameters, which would be more correct concerning the
|
|
purpose of the xdr_functions. Then again, reading the position may
|
|
fail (eof), whereas after the position has been read, xdr_cell() must
|
|
not fail when loading a sheet.
|
|
|
|
*/
|
|
/*}}}*/
|
|
/* xdr_cell */ /*{{{*/
|
|
bool_t xdr_cell(XDR *xdrs, Cell *cell)
|
|
{
|
|
int result,x;
|
|
|
|
assert(cell!=(Cell*)0);
|
|
if (!(xdr_tokenptrvec(xdrs, &(cell->contents)) && xdr_tokenptrvec(xdrs, &(cell->ccontents)) /* && xdr_token(xdrs, &(cell->value)) */ )) return 0;
|
|
if (xdr_mystring(xdrs, &(cell->label))==0) return 0;
|
|
x=cell->adjust;
|
|
result=xdr_int(xdrs, &x);
|
|
cell->adjust=x;
|
|
if (result==0) return 0;
|
|
if (xdr_int(xdrs, &(cell->precision))==0) return 0;
|
|
x=(cell->updated&1)|((cell->shadowed&1)<<1)|((cell->scientific&1)<<2)|((cell->locked&1)<<3)|((cell->transparent&1)<<4)|((cell->ignored&1)<<5)|((cell->bold&1)<<6)|((cell->underline&1)<<7);
|
|
result=xdr_int(xdrs, &x);
|
|
cell->updated=((x&(1))!=0);
|
|
cell->shadowed=((x&(1<<1))!=0);
|
|
cell->scientific=((x&(1<<2))!=0);
|
|
cell->locked=((x&(1<<3))!=0);
|
|
cell->transparent=((x&(1<<4))!=0);
|
|
cell->ignored=((x&(1<<5))!=0);
|
|
cell->bold=((x&(1<<6))!=0);
|
|
cell->underline=((x&(1<<7))!=0);
|
|
return result;
|
|
}
|
|
/*}}}*/
|
|
/* xdr_column */ /*{{{*/
|
|
bool_t xdr_column(XDR *xdrs, int *x, int *z, int *width)
|
|
{
|
|
return (xdr_int(xdrs, x) && xdr_int(xdrs, z) && xdr_int(xdrs, width));
|
|
}
|
|
/*}}}*/
|
|
/* xdr_magic */ /*{{{*/
|
|
#define MAGIC0 (('#'<<24)|('!'<<16)|('t'<<8)|'e')
|
|
#define MAGIC1 (('a'<<24)|('p'<<16)|('o'<<8)|'t')
|
|
#define MAGIC2 (('\n'<<24)|('x'<<16)|('d'<<8)|'r')
|
|
|
|
bool_t xdr_magic(XDR *xdrs)
|
|
{
|
|
long m0,m1,m2;
|
|
|
|
m0=MAGIC0;
|
|
m1=MAGIC1;
|
|
m2=MAGIC2;
|
|
return (xdr_long(xdrs,&m0) && m0==MAGIC0 && xdr_long(xdrs,&m1) && m1==MAGIC1 && xdr_long(xdrs,&m2) && m2==MAGIC2);
|
|
}
|
|
/*}}}*/
|