Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was short-cutting in getvalue() when the contents of a cell were empty, preventing the update of the internal cache of the value of the cell. However, tracking this down (and getting the associated memory management correct) necessitated implementing a debugging mode in which I could dump the internal states of cells and print various other stuff to standard output. It also involved understanding the meaning of various pointers in the code, in the process of which I renamed some commonly used macros, particularly the former SHEET(s,x,y,z) which was not returning a Sheet at all but rather a pointer to a Cell. So this macro is now called CELL_AT. I also replaced several very repeatedly used patterns of checking the validity of locations and pointers with macros, now defined in sheet.h. Therefore, unfortunately the (relatively small in the end) bugfix for this major issue is entangled with numerous textual changes to the code made in tracking it down. Fixes #18. Closes #19.
This commit is contained in:
parent
c072cb9af4
commit
08b42bf424
37
eval.c
37
eval.c
@ -63,25 +63,36 @@ void tfree(Token *n)
|
||||
n->u.lident=(char*)0;
|
||||
}
|
||||
}
|
||||
/*}}}*/
|
||||
/* tvecfreetoks -- free the tokens in vector of pointer to tokens */ /*{{{*/
|
||||
void tvecfreetoks(Token **tvec)
|
||||
{
|
||||
if (tvec!=EMPTY_TVEC)
|
||||
while (*tvec != NULLTOKEN)
|
||||
{
|
||||
tfree(*tvec);
|
||||
free(*tvec);
|
||||
*(tvec++) = NULLTOKEN;
|
||||
}
|
||||
}
|
||||
|
||||
/*}}}*/
|
||||
/* tvecfree -- free a vector of pointer to tokens entirely */ /*{{{*/
|
||||
void tvecfree(Token **tvec)
|
||||
{
|
||||
if (tvec!=(Token**)0)
|
||||
{
|
||||
/* variables */ /*{{{*/
|
||||
Token **t;
|
||||
/*}}}*/
|
||||
|
||||
for (t=tvec; *t!=(Token*)0; ++t)
|
||||
{
|
||||
tfree(*t);
|
||||
free(*t);
|
||||
}
|
||||
free(tvec);
|
||||
}
|
||||
tvecfreetoks(tvec);
|
||||
free(tvec);
|
||||
}
|
||||
/*}}}*/
|
||||
/* tveclen -- return length of a vector of pointer to tokens */ /*{{{*/
|
||||
size_t tveclen(Token **tvec)
|
||||
{
|
||||
size_t len;
|
||||
if (tvec == EMPTY_TVEC) return 0;
|
||||
for (len=1; *tvec != NULLTOKEN; ++len,++tvec);
|
||||
return len;
|
||||
}
|
||||
/*}}}*/
|
||||
/* tadd -- + operator */ /*{{{*/
|
||||
Token tadd(Token l, Token r)
|
||||
{
|
||||
|
2
eval.h
2
eval.h
@ -5,7 +5,9 @@
|
||||
|
||||
Token tcopy(Token n);
|
||||
void tfree(Token *n);
|
||||
void tvecfreetoks(Token **tvec);
|
||||
void tvecfree(Token **tvec);
|
||||
size_t tveclen(Token **tvec);
|
||||
Token tpow(Token l, Token r);
|
||||
Token tdiv(Token l, Token r);
|
||||
Token tmod(Token l, Token r);
|
||||
|
@ -68,12 +68,6 @@ decl {\#include "misc.h"} {private global
|
||||
decl {\#include "display.h"} {public global
|
||||
}
|
||||
|
||||
decl {\#define SHEET(s,x,y,z) (*(s->sheet+(x)*s->dimz*s->dimy+(y)*s->dimz+(z)))} {private global
|
||||
}
|
||||
|
||||
decl {\#define SHADOWED(sheet,x,y,z) (x<sheet->dimx && y<sheet->dimy && z<sheet->dimz && SHEET(sheet,x,y,z)!=(Cell*)0 && SHEET(sheet,x,y,z)->shadowed)} {private global
|
||||
}
|
||||
|
||||
class TeapotTable {open : {public Fl_Table}
|
||||
} {
|
||||
decl {Sheet *cursheet;} {protected local
|
||||
@ -269,6 +263,7 @@ updating = false;
|
||||
case 'v': k = ctrl?(cut?BLOCK_MOVE:BLOCK_COPY):(Key)'v'; break;
|
||||
case 'x': if (ctrl) { do_mark(cursheet, 2); cut = true, k = K_NONE; } break;
|
||||
case 'r': if (ctrl) k = K_RECALC; break;
|
||||
case 'd': if (ctrl && shift && debug_level > 0) k = K_DUMPCELL; break;
|
||||
case FL_Insert: if (ctrl) { do_mark(cursheet, 2); cut = false; } k = !shift?K_NONE:cut?BLOCK_MOVE:BLOCK_COPY; break;
|
||||
case FL_Delete: if (shift) { do_mark(cursheet, 2); cut = true; } k = shift?K_NONE:BLOCK_CLEAR; break;
|
||||
case FL_Home: k = ctrl?K_FIRSTL:shift?K_FSHEET:K_HOME; break;
|
||||
|
18
main.c
18
main.c
@ -50,6 +50,7 @@ unsigned int batchln=0;
|
||||
int def_precision=DEF_PRECISION;
|
||||
int quote=0;
|
||||
int header=1;
|
||||
int debug_level=0;
|
||||
static int usexdr=1;
|
||||
/*}}}*/
|
||||
|
||||
@ -1632,6 +1633,7 @@ int do_sheetcmd(Sheet *cursheet, Key c, int moveonly)
|
||||
#else
|
||||
case K_HELP: show_text(_("Sorry, manual is not installed.")); break;
|
||||
#endif
|
||||
case K_DUMPCELL: dump_current_cell(cursheet); break;
|
||||
case K_ABOUT: show_text(_("<html><head><title>About teapot</title></head><body><center><pre>\n\n"
|
||||
" ` ',` ' ' \n"
|
||||
" ` ' ` ' ' \n"
|
||||
@ -1655,10 +1657,13 @@ int do_sheetcmd(Sheet *cursheet, Key c, int moveonly)
|
||||
"\n"
|
||||
"<p>Original Version: Michael Haardt<br>\n"
|
||||
"Current Maintainer: Joerg Walter<br>\n"
|
||||
"Contibutions by: Glen Whitney<br>\b"
|
||||
"Home Page: <a href='http://www.syntax-k.de/projekte/teapot/'>http://www.syntax-k.de/projekte/teapot/</a></p>\n"
|
||||
"This distribution: <a href='https://code.studioinfinity.org/glen/teapot-spreadsheet/'>https://code.studioinfinity.org/glen/teapot-spreadsheet/</a></p>\n"
|
||||
"\n"
|
||||
"<p>Copyright 1995-2006 Michael Haardt,<br>\n"
|
||||
"Copyright 2009-2010 Joerg Walter (<a href='mailto:info@syntax-k.de'>info@syntax-k.de</a>)</p></center>\n"
|
||||
"Copyright 2009-2010 Joerg Walter (<a href='mailto:info@syntax-k.de'>info@syntax-k.de</a>)<br>"
|
||||
"Copyright 2019 Glen Whitney</p></center>\n"
|
||||
"\f"
|
||||
"<p>This program is free software: you can redistribute it and/or modify\n"
|
||||
"it under the terms of the GNU General Public License as published by\n"
|
||||
@ -1765,7 +1770,7 @@ int main(int argc, char *argv[])
|
||||
find_helpfile(helpfile, sizeof(helpfile), argv[0]);
|
||||
|
||||
/* parse options */ /*{{{*/
|
||||
while ((o=getopt(argc,argv,"abhnrqHp:?"))!=EOF) switch (o)
|
||||
while ((o=getopt(argc,argv,"abdhnrqHp:?"))!=EOF) switch (o)
|
||||
{
|
||||
/* a -- use ascii as default */ /*{{{*/
|
||||
case 'a':
|
||||
@ -1777,6 +1782,9 @@ int main(int argc, char *argv[])
|
||||
/* b -- run batch */ /*{{{*/
|
||||
case 'b': batch=1; break;
|
||||
/*}}}*/
|
||||
/* d -- increase debug level */ /*{{{*/
|
||||
case 'd': ++debug_level; break;
|
||||
/*}}}*/
|
||||
/* n -- no quoted strings */ /*{{{*/
|
||||
case 'n': quote=0; break;
|
||||
/*}}}*/
|
||||
@ -1813,10 +1821,12 @@ int main(int argc, char *argv[])
|
||||
default:
|
||||
{
|
||||
fprintf(stderr,_(
|
||||
"Usage: %s [-a] [-b] [-n] [-H] [-r] [-p digits] [file]\n"
|
||||
"Usage: %s [-a] [-b] [-d]* [-h] [-n|-q] [-H] [-r] [-p digits] [file]\n"
|
||||
" -a: use ASCII file format as default\n"
|
||||
" -b: batch mode\n"
|
||||
" -q: display strings in quotes\n"
|
||||
" -d: increase debug level, once for each occurrence\n"
|
||||
" -h: print this message and exit\n"
|
||||
" -n|-q: DO NOT or DO display strings in quotes, respectively\n"
|
||||
" -H: hide row/column headers\n"
|
||||
" -r: redraw more often\n"
|
||||
" -p: set decimal precision\n"
|
||||
|
4
main.h
4
main.h
@ -15,6 +15,7 @@ extern int batch;
|
||||
extern int def_precision;
|
||||
extern int quote;
|
||||
extern int header;
|
||||
extern int debug_level;
|
||||
extern unsigned int batchln;
|
||||
|
||||
/* A variable of type Key is either a special symbol from this enum, representing
|
||||
@ -78,7 +79,8 @@ typedef enum {
|
||||
BLOCK_MIRROR = -53,
|
||||
K_ABOUT = -54,
|
||||
K_HELP = -55,
|
||||
ADJUST_UNDERLINE = -56
|
||||
K_DUMPCELL = -56,
|
||||
ADJUST_UNDERLINE = -57
|
||||
} Key;
|
||||
|
||||
extern int do_sheetcmd(Sheet *cursheet, Key c, int moveonly);
|
||||
|
12
parser.c
12
parser.c
@ -314,3 +314,15 @@ Token eval(Token **n)
|
||||
return result;
|
||||
}
|
||||
/*}}}*/
|
||||
|
||||
/* eval_safe -- like eval, but handles null pointer to token sequence */ /*{{{*/
|
||||
Token eval_safe(Token **n)
|
||||
{
|
||||
Token result;
|
||||
if (n == EMPTY_TVEC)
|
||||
{
|
||||
result.type = EMPTY;
|
||||
return result;
|
||||
}
|
||||
return eval(n);
|
||||
}
|
||||
|
3
parser.h
3
parser.h
@ -3,6 +3,7 @@
|
||||
|
||||
#include "scanner.h"
|
||||
|
||||
Token eval(Token *n[]);
|
||||
Token eval_safe(Token **n); /* OK to call on null ptr */
|
||||
Token eval(Token *n[]); /* Don't call with null ptr */
|
||||
|
||||
#endif
|
||||
|
14
sc.c
14
sc.c
@ -230,8 +230,8 @@ const char *loadsc(Sheet *sheet, const char *name)
|
||||
sscanf(buf+7,"%s %d %d %d",colstr,&colwidth,&precision,&whoknows);
|
||||
col=(colstr[0]-'A'); if (colstr[1]) col=col*26+(colstr[1]-'A');
|
||||
initcell(sheet,col,0,0);
|
||||
SHEET(sheet,col,0,0)->adjust=RIGHT;
|
||||
SHEET(sheet,col,0,0)->precision=precision;
|
||||
CELL_AT(sheet,col,0,0)->adjust=RIGHT;
|
||||
CELL_AT(sheet,col,0,0)->precision=precision;
|
||||
setwidth(sheet,col,0,colwidth);
|
||||
}
|
||||
/*}}}*/
|
||||
@ -254,8 +254,8 @@ const char *loadsc(Sheet *sheet, const char *name)
|
||||
goto eek;
|
||||
}
|
||||
initcell(sheet,x,y,0);
|
||||
SHEET(sheet,x,y,0)->adjust=strncmp(buf,"leftstring ",11) ? RIGHT : LEFT;
|
||||
SHEET(sheet,x,y,0)->contents=contents;
|
||||
CELL_AT(sheet,x,y,0)->adjust=strncmp(buf,"leftstring ",11) ? RIGHT : LEFT;
|
||||
CELL_AT(sheet,x,y,0)->contents=contents;
|
||||
}
|
||||
/*}}}*/
|
||||
else if (strncmp(buf,"let ",4)==0) /* let cell = expression */ /*{{{*/
|
||||
@ -293,8 +293,8 @@ const char *loadsc(Sheet *sheet, const char *name)
|
||||
goto eek;
|
||||
}
|
||||
initcell(sheet,x,y,0);
|
||||
SHEET(sheet,x,y,0)->adjust=RIGHT;
|
||||
SHEET(sheet,x,y,0)->contents=contents;
|
||||
CELL_AT(sheet,x,y,0)->adjust=RIGHT;
|
||||
CELL_AT(sheet,x,y,0)->contents=contents;
|
||||
}
|
||||
}
|
||||
/*}}}*/
|
||||
@ -307,7 +307,7 @@ const char *loadsc(Sheet *sheet, const char *name)
|
||||
int prec;
|
||||
|
||||
prec=getprecision(sheet,x,0,0)==def_precision ? 2 : getprecision(sheet,x,0,0);
|
||||
for (y=1; y<sheet->dimy; ++y) if (SHEET(sheet,x,y,0)) SHEET(sheet,x,y,0)->precision=prec;
|
||||
for (y=1; y<sheet->dimy; ++y) if (CELL_AT(sheet,x,y,0)) CELL_AT(sheet,x,y,0)->precision=prec;
|
||||
}
|
||||
/*}}}*/
|
||||
eek:
|
||||
|
114
scanner.c
114
scanner.c
@ -24,6 +24,7 @@ extern double strtod(const char *nptr, char **endptr); /* SunOS 4 hack */
|
||||
#include "func.h"
|
||||
#include "main.h"
|
||||
#include "misc.h"
|
||||
#include "utf8.h"
|
||||
#include "scanner.h"
|
||||
/*}}}*/
|
||||
|
||||
@ -225,38 +226,34 @@ Token **scan(const char **s)
|
||||
return na;
|
||||
}
|
||||
/*}}}*/
|
||||
/* print -- print token sequence */ /*{{{*/
|
||||
void print(char *s, size_t size, size_t chars, int quote, int scientific, int precision, Token **n)
|
||||
/* printtok -- print a single token, passed by address, although not changed */ /*{{{*/
|
||||
size_t printtok(char* dest, size_t size, size_t field_width,
|
||||
int quote_strings, int use_scientific,
|
||||
int precision, int verbose_error, Token *tok)
|
||||
{
|
||||
size_t cur;
|
||||
|
||||
cur=0;
|
||||
if (n!=(Token**)0) for (; cur<size-1 && (*n)!=(Token*)0; ++n) switch ((*n)->type)
|
||||
|
||||
if (debug_level > 2) {
|
||||
printf("..Entering printtok; bufsize %d, field_width %d, qs %d, us %d, prec %d, verr %d\n", size, field_width, quote_strings, use_scientific, precision, verbose_error);
|
||||
}
|
||||
cur = 0;
|
||||
if (tok != NULLTOKEN) switch (tok->type)
|
||||
{
|
||||
/* EMPTY */ /*{{{*/
|
||||
case EMPTY: assert(cur==0); *(s+cur)='\0'; ++cur; break;
|
||||
case EMPTY: if (size > 0) dest[cur++] = '\0'; break;
|
||||
/*}}}*/
|
||||
/* STRING */ /*{{{*/
|
||||
case STRING:
|
||||
{
|
||||
char *str=(*n)->u.string;
|
||||
char *str = tok->u.string;
|
||||
|
||||
if (quote)
|
||||
if (quote_strings && cur<size) dest[cur++] = '"';
|
||||
for (;cur<size && *str != '\0'; ++str)
|
||||
{
|
||||
*(s+cur)='"';
|
||||
++cur;
|
||||
}
|
||||
while (cur<size && *str!='\0')
|
||||
{
|
||||
if (quote) if (*str=='"' || *str=='\\') *(s+cur++)='\\';
|
||||
if (cur<size) *(s+cur++)=*str;
|
||||
++str;
|
||||
}
|
||||
if (quote)
|
||||
{
|
||||
if (cur<size) *(s+cur)='"';
|
||||
++cur;
|
||||
if (quote_strings && (*str == '"' || *str=='\\')) dest[cur++] = '\\';
|
||||
if (cur<size) dest[cur++]=*str;
|
||||
}
|
||||
if (quote_strings && cur<size) dest[cur++] = '"';
|
||||
break;
|
||||
}
|
||||
/*}}}*/
|
||||
@ -266,9 +263,9 @@ void print(char *s, size_t size, size_t chars, int quote, int scientific, int pr
|
||||
char buf[20];
|
||||
size_t buflen;
|
||||
|
||||
buflen=sprintf(buf,"%ld",(*n)->u.integer);
|
||||
buflen=sprintf(buf,"%ld",tok->u.integer);
|
||||
assert(buflen<sizeof(buf));
|
||||
(void)strncpy(s+cur,buf,size-cur-1);
|
||||
(void)strncpy(dest+cur,buf,size-cur-1);
|
||||
cur+=buflen;
|
||||
break;
|
||||
}
|
||||
@ -281,16 +278,18 @@ void print(char *s, size_t size, size_t chars, int quote, int scientific, int pr
|
||||
size_t len;
|
||||
/*}}}*/
|
||||
|
||||
len=sprintf(buf,scientific ? "%.*e" : "%.*f",precision==-1 ? DBL_DIG-2 : precision, (*n)->u.flt);
|
||||
len=sprintf(buf, use_scientific ? "%.*e" : "%.*f",
|
||||
precision == -1 ? DBL_DIG-2 : precision,
|
||||
tok->u.flt);
|
||||
assert(len<sizeof(buf));
|
||||
if (!scientific && precision==-1)
|
||||
if (!use_scientific && precision==-1)
|
||||
{
|
||||
p=&buf[len-1];
|
||||
while (p>buf && *p=='0' && *(p-1)!='.') { *p='\0'; --p; --len; }
|
||||
}
|
||||
p=buf+len;
|
||||
while (*--p==' ') { *p='\0'; --len; }
|
||||
(void)strncpy(s+cur,buf,size-cur-1);
|
||||
(void)strncpy(dest+cur,buf,size-cur-1);
|
||||
cur+=len;
|
||||
break;
|
||||
}
|
||||
@ -300,8 +299,11 @@ void print(char *s, size_t size, size_t chars, int quote, int scientific, int pr
|
||||
{
|
||||
static const char *ops[]={ "+", "-", "*", "/", "(", ")", ",", "<", "<=", ">=", ">", "==", "~=", "!=", "^", "%" };
|
||||
|
||||
if ((size-cur)>1) *(s+cur++)=*ops[(*n)->u.op];
|
||||
if (*(ops[(*n)->u.op]+1) && (size-cur)>1) *(s+cur++)=*(ops[(*n)->u.op]+1);
|
||||
if ((size-cur)>1)
|
||||
{
|
||||
dest[cur++]=*ops[tok->u.op];
|
||||
if (*(ops[tok->u.op]+1) && size>cur) dest[cur++]=*(ops[tok->u.op]+1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
/*}}}*/
|
||||
@ -310,9 +312,9 @@ void print(char *s, size_t size, size_t chars, int quote, int scientific, int pr
|
||||
{
|
||||
size_t identlen;
|
||||
|
||||
identlen=strlen((*n)->u.lident);
|
||||
if ((cur+identlen+1)<=size) strcpy(s+cur,(*n)->u.lident);
|
||||
else (void)strncpy(s+cur,(*n)->u.lident,size-cur-1);
|
||||
identlen=strlen(tok->u.lident);
|
||||
if ((cur+identlen+1)<=size) strcpy(dest+cur,tok->u.lident);
|
||||
else (void)strncpy(dest+cur,tok->u.lident,size-cur-1);
|
||||
cur+=identlen;
|
||||
break;
|
||||
}
|
||||
@ -321,10 +323,12 @@ void print(char *s, size_t size, size_t chars, int quote, int scientific, int pr
|
||||
case FIDENT:
|
||||
{
|
||||
size_t identlen;
|
||||
|
||||
identlen=strlen(tfunc[(*n)->u.fident].name);
|
||||
if ((cur+identlen+1)<=size) strcpy(s+cur,tfunc[(*n)->u.fident].name);
|
||||
else (void)strncpy(s+cur,tfunc[(*n)->u.fident].name,size-cur-1);
|
||||
if (debug_level > 2) {
|
||||
printf("...Found function [%s].\n", tfunc[tok->u.fident].name);
|
||||
}
|
||||
identlen=strlen(tfunc[tok->u.fident].name);
|
||||
if ((cur+identlen+1)<=size) strcpy(dest+cur,tfunc[tok->u.fident].name);
|
||||
else (void)strncpy(dest+cur,tfunc[tok->u.fident].name,size-cur-1);
|
||||
cur+=identlen;
|
||||
break;
|
||||
}
|
||||
@ -334,8 +338,8 @@ void print(char *s, size_t size, size_t chars, int quote, int scientific, int pr
|
||||
{
|
||||
char buf[60];
|
||||
|
||||
sprintf(buf,"&(%d,%d,%d)",(*n)->u.location[0],(*n)->u.location[1],(*n)->u.location[2]);
|
||||
(void)strncpy(s+cur,buf,size-cur-1);
|
||||
sprintf(buf,"&(%d,%d,%d)",tok->u.location[0],tok->u.location[1],tok->u.location[2]);
|
||||
(void)strncpy(dest+cur,buf,size-cur-1);
|
||||
cur+=strlen(buf);
|
||||
break;
|
||||
}
|
||||
@ -343,8 +347,19 @@ void print(char *s, size_t size, size_t chars, int quote, int scientific, int pr
|
||||
/* EEK */ /*{{{*/
|
||||
case EEK:
|
||||
{
|
||||
(void)strncpy(s+cur,_("ERROR"),size-cur-1);
|
||||
cur+=5;
|
||||
size_t errlen;
|
||||
|
||||
(void)strncpy(dest+cur,_("ERROR"),size-cur-1);
|
||||
cur += strlen(_("ERROR"));
|
||||
if (verbose_error)
|
||||
{
|
||||
(void)strncpy(dest+cur, ": ", size-cur-1);
|
||||
cur += 2;
|
||||
errlen = strlen(tok->u.err);
|
||||
if ((cur+errlen+1) <= size) strcpy(dest+cur, tok->u.err);
|
||||
else (void)strncpy(dest+cur, tok->u.err, size-cur-1);
|
||||
cur += errlen;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/*}}}*/
|
||||
@ -352,6 +367,27 @@ void print(char *s, size_t size, size_t chars, int quote, int scientific, int pr
|
||||
default: assert(0);
|
||||
/*}}}*/
|
||||
}
|
||||
if (cur<size) dest[cur] = 0;
|
||||
else
|
||||
{
|
||||
dest[size-1] = 0;
|
||||
cur = size;
|
||||
}
|
||||
if (field_width && mbslen(dest) > field_width) {
|
||||
for (cur = 0; cur < field_width; ++cur) dest[cur] = '#';
|
||||
dest[cur] = 0;
|
||||
}
|
||||
return cur;
|
||||
}
|
||||
/*}}}*/
|
||||
/* print -- print token sequence */ /*{{{*/
|
||||
void print(char *s, size_t size, size_t chars, int quote, int scientific, int precision, Token **n)
|
||||
{
|
||||
size_t cur;
|
||||
|
||||
cur=0;
|
||||
if (n != EMPTY_TVEC) for (; cur<size-1 && (*n) != NULLTOKEN; ++n)
|
||||
cur += printtok(s+cur, size-cur, 0, quote, scientific, precision, 0, *n);
|
||||
if (cur<size) s[cur] = 0;
|
||||
else s[size-1] = 0;
|
||||
if (chars && mbslen(s) > chars) {
|
||||
|
@ -32,8 +32,14 @@ typedef struct
|
||||
} u;
|
||||
} Token;
|
||||
|
||||
#define NULLTOKEN ((Token*)0)
|
||||
#define EMPTY_TVEC ((Token**)0)
|
||||
|
||||
int identcode(const char *s, size_t len);
|
||||
Token **scan(const char **s);
|
||||
size_t printtok(char* dest, size_t size, size_t field_width,
|
||||
int quote_strings, int use_scientific,
|
||||
int precision, int verbose_error, Token *tok);
|
||||
void print(char *s, size_t size, size_t chars, int quote, int scientific, int precision, Token **n);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
9
sheet.h
9
sheet.h
@ -7,7 +7,13 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define SHEET(s,x,y,z) (*(s->sheet+(x)*s->dimz*s->dimy+(y)*s->dimz+(z)))
|
||||
#define LOC_WITHIN(s,x,y,z) (x<s->dimx && y<s->dimy && z<s->dimz)
|
||||
#define CELL_AT(s,x,y,z) (*(s->sheet+(x)*s->dimz*s->dimy+(y)*s->dimz+(z)))
|
||||
#define NULLCELL ((Cell*)0)
|
||||
#define CELL_IS_NULL(s,x,y,z) (CELL_AT(s,x,y,z) == NULLCELL)
|
||||
#define CELL_IS_GOOD(s,x,y,z) (LOC_WITHIN(s,x,y,z) && !CELL_IS_NULL(s,x,y,z))
|
||||
#define SHADOWED(s,x,y,z) (CELL_IS_GOOD(s,x,y,z) && CELL_AT(s,x,y,z)->shadowed)
|
||||
#define ALL_CELLS_IN_SHEET(s,x,y,z) x=0; x<s->dimx; ++x) for (y=0; y<s->dimy; ++y) for (z=0; z<s->dimz; ++z
|
||||
|
||||
typedef enum { LEFT=0, RIGHT=1, CENTER=2, AUTOADJUST=3 } Adjust;
|
||||
|
||||
@ -86,6 +92,7 @@ void initcell(Sheet *sheet, int x, int y, int z);
|
||||
void cachelabels(Sheet *sheet);
|
||||
void freesheet(Sheet *sheet, int all);
|
||||
void forceupdate(Sheet *sheet);
|
||||
void dump_current_cell(Sheet *sheet);
|
||||
void freecell(Sheet *sheet, int x, int y, int z);
|
||||
int columnwidth(Sheet *sheet, int x, int z);
|
||||
void setwidth(Sheet *sheet, int x, int z, int width);
|
||||
|
36
teapot.1
36
teapot.1
@ -2,7 +2,7 @@
|
||||
.\" Copyright(c) 2010 by wave++ "Yuri D'Elia" <wavexx@users.sf.net>
|
||||
.\" Distributed under GNU GPL WITHOUT ANY WARRANTY.
|
||||
.\"
|
||||
.Dd Dicember 8, 2010
|
||||
.Dd December 8, 2010
|
||||
.Dt TEAPOT 1
|
||||
.\"
|
||||
.\"
|
||||
@ -12,10 +12,12 @@
|
||||
.\"
|
||||
.\"
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl abHqr
|
||||
\fBfteapot|teapot\fP
|
||||
.Op Fl abdhHr
|
||||
.Op Fl n|q
|
||||
.Op Fl p Ar digits
|
||||
.Op Ar file
|
||||
.YS
|
||||
.\"
|
||||
.\"
|
||||
.Sh DESCRIPTION
|
||||
@ -25,12 +27,19 @@ dimensions with linear addressing, relative references, formula references,
|
||||
type safety of computations, iterative expressions and platform independent
|
||||
file format.
|
||||
.Pp
|
||||
.Pp
|
||||
When invoked as 'teapot' the program uses a console-based text interface; when
|
||||
invoked as 'fteapot' it uses a windowed graphical interface. The
|
||||
.Pa file
|
||||
argument, if given, specifies an initial file to load upon startup.
|
||||
.Pp
|
||||
This document only describes command-line arguments. Please refer to the
|
||||
complete manual that can be found under
|
||||
.Pa /usr/share/doc/teapot
|
||||
in both html and pdf format.
|
||||
The manual can also be viewed from within the graphical version, fteapot,
|
||||
using the Help menu.
|
||||
(or other standard documentation location on your system) in both html
|
||||
and pdf format, teapot.pdf.
|
||||
The manual can also be viewed from within the graphical version using
|
||||
the Help menu.
|
||||
.\"
|
||||
.\"
|
||||
.Sh OPTIONS
|
||||
@ -39,10 +48,16 @@ using the Help menu.
|
||||
Use ASCII instead of XDR as default file format when loading or saving.
|
||||
.It Fl b
|
||||
Read batch commands from standard input.
|
||||
.It Fl d
|
||||
Increment the debug level, once per occurrence; teapot may produce various
|
||||
output on standard out when this is specified, and additional key bindings
|
||||
may be in effect.
|
||||
.It Fl h
|
||||
Print a brief usage message.
|
||||
.It Fl H
|
||||
Hide row and column headers.
|
||||
.It Fl q
|
||||
Display strings quoted.
|
||||
.It Fl n|q
|
||||
Display strings definitely NOT quoted or definitely quoted, respectively.
|
||||
.It Fl r
|
||||
Redraw the terminal window more often.
|
||||
.It Fl p Ar digits
|
||||
@ -67,6 +82,11 @@ Copyright (C) 2009-2012
|
||||
J\(:org Walter
|
||||
.Me
|
||||
.Pp
|
||||
Copyright (C) 2019
|
||||
.Mt glen@studioinfinity.org
|
||||
Glen Whitney
|
||||
.Me
|
||||
.Pp
|
||||
Manual page written by
|
||||
.Mt wavexx@users.sf.net
|
||||
Yuri D'Elia
|
||||
|
16
wk1.c
16
wk1.c
@ -836,7 +836,7 @@ const char *loadwk1(Sheet *sheet, const char *name)
|
||||
{
|
||||
if (bodylen!=5) { err=_("Invalid record body length"); goto ouch; }
|
||||
initcell(sheet,it(body+1),it(body+3),0);
|
||||
format((unsigned char)body[0],SHEET(sheet,it(body+1),it(body+3),0));
|
||||
format((unsigned char)body[0],CELL_AT(sheet,it(body+1),it(body+3),0));
|
||||
break;
|
||||
}
|
||||
/*}}}*/
|
||||
@ -853,7 +853,7 @@ const char *loadwk1(Sheet *sheet, const char *name)
|
||||
t[0]->type=INT;
|
||||
t[0]->u.integer=it(body+5);
|
||||
putcont(sheet,it(body+1),it(body+3),0,t,0);
|
||||
format((unsigned char)body[0],SHEET(sheet,it(body+1),it(body+3),0));
|
||||
format((unsigned char)body[0],CELL_AT(sheet,it(body+1),it(body+3),0));
|
||||
break;
|
||||
}
|
||||
/*}}}*/
|
||||
@ -870,7 +870,7 @@ const char *loadwk1(Sheet *sheet, const char *name)
|
||||
t[0]->type=FLOAT;
|
||||
t[0]->u.flt=dbl((unsigned char*)body+5);
|
||||
putcont(sheet,it(body+1),it(body+3),0,t,0);
|
||||
format((unsigned char)body[0],SHEET(sheet,it(body+1),it(body+3),0));
|
||||
format((unsigned char)body[0],CELL_AT(sheet,it(body+1),it(body+3),0));
|
||||
break;
|
||||
}
|
||||
/*}}}*/
|
||||
@ -887,7 +887,7 @@ const char *loadwk1(Sheet *sheet, const char *name)
|
||||
t[0]->type=STRING;
|
||||
t[0]->u.string=mystrmalloc(body+6);
|
||||
putcont(sheet,it(body+1),it(body+3),0,t,0);
|
||||
format((unsigned char)body[0],SHEET(sheet,it(body+1),it(body+3),0));
|
||||
format((unsigned char)body[0],CELL_AT(sheet,it(body+1),it(body+3),0));
|
||||
break;
|
||||
}
|
||||
/*}}}*/
|
||||
@ -944,7 +944,7 @@ const char *loadwk1(Sheet *sheet, const char *name)
|
||||
#if WK1DEBUG
|
||||
fprintf(se,", value %f",dbl((unsigned char*)body+5));
|
||||
#endif
|
||||
format((unsigned char)body[0],SHEET(sheet,it(body+1),it(body+3),0));
|
||||
format((unsigned char)body[0],CELL_AT(sheet,it(body+1),it(body+3),0));
|
||||
#if WK1DEBUG
|
||||
fprintf(se,"\r\n");
|
||||
#endif
|
||||
@ -969,8 +969,8 @@ const char *loadwk1(Sheet *sheet, const char *name)
|
||||
#endif
|
||||
free(offset);
|
||||
initcell(sheet,it(body+1),it(body+3),0);
|
||||
SHEET(sheet,it(body+1),it(body+3),0)->value.type=FLOAT;
|
||||
SHEET(sheet,it(body+1),it(body+3),0)->value.u.flt=dbl((unsigned char*)body+5);
|
||||
CELL_AT(sheet,it(body+1),it(body+3),0)->value.type=FLOAT;
|
||||
CELL_AT(sheet,it(body+1),it(body+3),0)->value.u.flt=dbl((unsigned char*)body+5);
|
||||
putcont(sheet,it(body+1),it(body+3),0,t,0);
|
||||
}
|
||||
break;
|
||||
@ -1092,7 +1092,7 @@ const char *loadwk1(Sheet *sheet, const char *name)
|
||||
t[0]->type=STRING;
|
||||
t[0]->u.string=mystrmalloc(body+5);
|
||||
putcont(sheet,it(body+1),it(body+3),0,t,0);
|
||||
format((unsigned char)body[0],SHEET(sheet,it(body+1),it(body+3),0));
|
||||
format((unsigned char)body[0],CELL_AT(sheet,it(body+1),it(body+3),0));
|
||||
break;
|
||||
}
|
||||
/*}}}*/
|
||||
|
Loading…
Reference in New Issue
Block a user