From 08b42bf4246573a3206b6f403e342abe114ead83 Mon Sep 17 00:00:00 2001 From: Glen Whitney Date: Wed, 24 Jul 2019 10:47:39 -0700 Subject: [PATCH] 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. --- eval.c | 37 ++-- eval.h | 2 + fteapot.fl | 7 +- main.c | 18 +- main.h | 4 +- parser.c | 12 ++ parser.h | 3 +- sc.c | 14 +- scanner.c | 114 +++++++---- scanner.h | 6 + sheet.c | 586 ++++++++++++++++++++++++++++++----------------------- sheet.h | 9 +- teapot.1 | 36 +++- wk1.c | 16 +- 14 files changed, 527 insertions(+), 337 deletions(-) diff --git a/eval.c b/eval.c index 6783a40..554ac5f 100644 --- a/eval.c +++ b/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) { diff --git a/eval.h b/eval.h index 9f3cc87..868602f 100644 --- a/eval.h +++ b/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); diff --git a/fteapot.fl b/fteapot.fl index cb73a78..a5867f9 100644 --- a/fteapot.fl +++ b/fteapot.fl @@ -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) (xdimx && ydimy && zdimz && 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; diff --git a/main.c b/main.c index 4041655..cd50488 100644 --- a/main.c +++ b/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(_("About teapot
\n\n"
         "               ` ',`    '  '                   \n"
         "                `   '  ` ' '                   \n"
@@ -1655,10 +1657,13 @@ int do_sheetcmd(Sheet *cursheet, Key c, int moveonly)
         "\n"
         "

Original Version: Michael Haardt
\n" "Current Maintainer: Joerg Walter
\n" + "Contibutions by: Glen Whitney
\b" "Home Page: http://www.syntax-k.de/projekte/teapot/

\n" + "This distribution: https://code.studioinfinity.org/glen/teapot-spreadsheet/

\n" "\n" "

Copyright 1995-2006 Michael Haardt,
\n" - "Copyright 2009-2010 Joerg Walter (info@syntax-k.de)

\n" + "Copyright 2009-2010 Joerg Walter (info@syntax-k.de)
" + "Copyright 2019 Glen Whitney

\n" "\f" "

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" diff --git a/main.h b/main.h index 0f38923..626c115 100644 --- a/main.h +++ b/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); diff --git a/parser.c b/parser.c index 58095c3..9338bf2 100644 --- a/parser.c +++ b/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); +} diff --git a/parser.h b/parser.h index 89653f2..5e25f31 100644 --- a/parser.h +++ b/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 diff --git a/sc.c b/sc.c index 179fb59..37a6639 100644 --- a/sc.c +++ b/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; ydimy; ++y) if (SHEET(sheet,x,y,0)) SHEET(sheet,x,y,0)->precision=prec; + for (y=1; ydimy; ++y) if (CELL_AT(sheet,x,y,0)) CELL_AT(sheet,x,y,0)->precision=prec; } /*}}}*/ eek: diff --git a/scanner.c b/scanner.c index aec7bae..115c764 100644 --- a/scanner.c +++ b/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 (; curtype) + + 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 && curu.integer); + buflen=sprintf(buf,"%ld",tok->u.integer); assert(buflenu.flt); + len=sprintf(buf, use_scientific ? "%.*e" : "%.*f", + precision == -1 ? DBL_DIG-2 : precision, + tok->u.flt); assert(lenbuf && *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 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 chars) { diff --git a/scanner.h b/scanner.h index f7cb0e8..501ebdc 100644 --- a/scanner.h +++ b/scanner.h @@ -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 diff --git a/sheet.c b/sheet.c index 6cd7625..052ada8 100644 --- a/sheet.c +++ b/sheet.c @@ -25,8 +25,6 @@ /*}}}*/ /* #defines */ /*{{{*/ -#define SHEET(s,x,y,z) (*(s->sheet+(x)*s->dimz*s->dimy+(y)*s->dimz+(z))) - #define HASH(x,s) \ { \ const unsigned char *S=(const unsigned char*)s; \ @@ -36,7 +34,6 @@ x%=LABEL_CACHE; \ } -#define SHADOWED(sheet,x,y,z) (xdimx && ydimy && zdimz && SHEET(sheet,x,y,z)!=(Cell*)0 && SHEET(sheet,x,y,z)->shadowed) /*}}}*/ /* variables */ /*{{{*/ @@ -49,62 +46,139 @@ int upd_z; int max_eval; /*}}}*/ +/* copytokens -- copy a sequence of tokens, possibly reallocating dest */ /*{{{*/ +static void copytokens(Token*** totoks, Token** fromtoks) +{ + /* variables */ /*{{{*/ + size_t from_len, i; + /*}}}*/ + + from_len = tveclen(fromtoks); + if (from_len == 0) + { + tvecfree(*totoks); + *totoks = EMPTY_TVEC; + return; + } + from_len; + if (from_len > tveclen(*totoks)) + { + tvecfree(*totoks); + *totoks = malloc((from_len+1)*sizeof(Token*)); + (*totoks)[from_len] = NULLTOKEN; + } else { + tvecfreetoks(*totoks); + } + for (i=0; idimx && y1dimy && z1dimz) + if (LOC_WITHIN(sheet1,x1,y1,z1)) { sheet2->changed=1; - if (SHEET(sheet1,x1,y1,z1)==(Cell*)0) freecell(sheet2,x2,y2,z2); + fromcell = CELL_AT(sheet1,x1,y1,z1); + if (fromcell == NULLCELL) freecell(sheet2,x2,y2,z2); else /* copy first cell to second */ /*{{{*/ { freecell(sheet2,x2,y2,z2); initcell(sheet2,x2,y2,z2); - memcpy(SHEET(sheet2,x2,y2,z2),SHEET(sheet1,x1,y1,z1),sizeof(Cell)); - if (SHEET(sheet1,x1,y1,z1)->contents!=(Token**)0) - { - for (len=1,run=SHEET(sheet1,x1,y1,z1)->contents; *run!=(Token*)0; ++len,++run); - SHEET(sheet2,x2,y2,z2)->contents=malloc(len*sizeof(Token*)); - for (i=0; icontents+i)==(Token*)0) *(SHEET(sheet2,x2,y2,z2)->contents+i)=(Token*)0; - else - { - *(SHEET(sheet2,x2,y2,z2)->contents+i)=malloc(sizeof(Token)); - **(SHEET(sheet2,x2,y2,z2)->contents+i)=tcopy(**(SHEET(sheet1,x1,y1,z1)->contents+i)); - } - } - } - if (SHEET(sheet1,x1,y1,z1)->ccontents!=(Token**)0) - { - for (len=1,run=SHEET(sheet1,x1,y1,z1)->ccontents; *run!=(Token*)0; ++len,++run); - SHEET(sheet2,x2,y2,z2)->ccontents=malloc(len*sizeof(Token*)); - for (i=0; iccontents+i)==(Token*)0) *(SHEET(sheet2,x2,y2,z2)->ccontents+i)=(Token*)0; - else - { - *(SHEET(sheet2,x2,y2,z2)->ccontents+i)=malloc(sizeof(Token)); - **(SHEET(sheet2,x2,y2,z2)->ccontents+i)=tcopy(**(SHEET(sheet1,x1,y1,z1)->ccontents+i)); - } - } - } - if (SHEET(sheet1,x1,y1,z1)->label!=(char*)0) SHEET(sheet2,x2,y2,z2)->label=strcpy(malloc(strlen(SHEET(sheet1,x1,y1,z1)->label)+1),SHEET(sheet1,x1,y1,z1)->label); - SHEET(sheet2,x2,y2,z2)->value.type=EMPTY; + tocell = CELL_AT(sheet2,x2,y2,z2); + memcpy(tocell, fromcell, sizeof(Cell)); + copytokens(&(tocell->contents), fromcell->contents); + copytokens(&(tocell->ccontents), fromcell->ccontents); + if (fromcell->label != (char*)0) + tocell->label = strcpy(malloc(strlen(fromcell->label)+1), + fromcell->label); + tocell->value.type=EMPTY; } /*}}}*/ } else freecell(sheet2,x2,y2,z2); } /*}}}*/ +/* dump_cell -- write internal contents of cell to standard out */ /*{{{*/ +static void dump_cell(Sheet *sheet, int x, int y, int z) +{ + Cell* c; + char buf[2048]; + + assert(sheet != (Sheet*)0); + if (x < 0 || y < 0 || z < 0) + { + printf("TEADUMP: Requested cell &(%d,%d,%d) has negative coordinates.\n", + x, y, z); + return; + } + if (!LOC_WITHIN(sheet, x, y, z)) + { + printf("TEADUMP: Requested cell &(%d,%d,%d) outside sheet dims %d,%d,%d.\n", + x, y, z, sheet->dimx, sheet->dimy, sheet->dimz); + return; + } + c = CELL_AT(sheet, x, y, z); + if (c == NULLCELL) + { + printf("TEADUMP: Cell at &(%d,%d,%d) is empty.\n", x, y, z); + return; + } + printf("TEADUMP of &(%d,%d,%d):\n", x, y, z); + print(buf, sizeof(buf), 0, 1, 0, -1, c->contents); + printf(" Base expr: %s.\n", buf); + print(buf, sizeof(buf), 0, 1, 0, -1, c->ccontents); + printf(" Update expr: %s.\n", buf); + if (c->label == (char *)0) printf("\n No label.\n"); + else printf("\n Label: %s.\n", c->label); + printtok(buf, sizeof(buf), 0, 1, 0, -1, 1, &(c->value)); + printf(" Current value: %s.\n", buf); + printtok(buf, sizeof(buf), 0, 1, 0, -1, 1, &(c->resvalue)); + printf(" Stored result value: %s.\n Adjustment: ", buf); + switch (c->adjust) { + case LEFT: printf("LEFT\n"); break; + case RIGHT: printf("RIGHT\n"); break; + case CENTER: printf("CENTER\n"); break; + case AUTOADJUST: printf("AUTO\n"); break; + } + printf(" Precision: %d\n Attributes: ", c->precision); + if (c->updated) printf("updated "); + if (c->shadowed) printf("shadowed "); + if (c->scientific) printf("scientific "); + if (c->locked) printf("locked "); + if (c->transparent) printf("transparent "); + if (c->ignored) printf("ignored "); + if (c->clock_t0) printf("clock_t0 "); + if (c->clock_t1) printf("clock_t1 "); + if (c->clock_t2) printf("clock_t2 "); + if (c->bold) printf("bold "); + if (c->underline) printf("underline "); + printf("\n\n"); +} +/*}}}*/ +/* dump_current_cell -- dump_cell of the current_cell */ /*{{{*/ +void dump_current_cell(Sheet *sheet) +{ + assert(sheet != (Sheet *)0); + dump_cell(sheet, sheet->curx, sheet->cury, sheet->curz); +} +/*}}}*/ /* swapblock -- swap two non-overlapping blocks of cells */ /*{{{*/ static void swapblock(Sheet *sheet1, int x1, int y1, int z1, Sheet *sheet2, int x2, int y2, int z2, int xdist, int ydist, int zdist) { @@ -120,9 +194,9 @@ static void swapblock(Sheet *sheet1, int x1, int y1, int z1, Sheet *sheet2, int { Cell *t; - t=SHEET(sheet1,x1+xoff,y1+yoff,z1+zoff); - SHEET(sheet1,x1+xoff,y1+yoff,z1+zoff)=SHEET(sheet2,x2+xoff,y2+yoff,z2+zoff); - SHEET(sheet2,x2+xoff,y2+yoff,z2+zoff)=t; + t = CELL_AT(sheet1,x1+xoff,y1+yoff,z1+zoff); + CELL_AT(sheet1,x1+xoff,y1+yoff,z1+zoff) = CELL_AT(sheet2,x2+xoff,y2+yoff,z2+zoff); + CELL_AT(sheet2,x2+xoff,y2+yoff,z2+zoff) = t; } sheet1->changed=1; sheet2->changed=1; @@ -138,26 +212,29 @@ second. A result of 2 means they are not comparable. /*}}}*/ static int cmpcell(Sheet *sheet1, int x1, int y1, int z1, Sheet *sheet2, int x2, int y2, int z2, int sortkey) { + Cell *leftcell, *rightcell; assert(sheet1!=(Sheet*)0); assert(sheet2!=(Sheet*)0); /* empty cells are smaller than any non-empty cell */ /*{{{*/ - if (x1>=sheet1->dimx || y1>=sheet1->dimy || z1>=sheet1->dimz || SHEET(sheet1,x1,y1,z1)==(Cell*)0 || SHEET(sheet1,x1,y1,z1)->value.type==EMPTY) + if (!CELL_IS_GOOD(sheet1,x1,y1,z1) || CELL_AT(sheet1,x1,y1,z1)->value.type==EMPTY) { - if (x2>=sheet2->dimx || y2>=sheet2->dimy || z2>=sheet2->dimz || SHEET(sheet2,x2,y2,z2)==(Cell*)0 || SHEET(sheet2,x2,y2,z2)->value.type==EMPTY) return 0; + if (!CELL_IS_GOOD(sheet2,x2,y2,z2) || CELL_AT(sheet2,x2,y2,z2)->value.type==EMPTY) return 0; else return (sortkey&ASCENDING ? -1 : 1); } - if (x2>=sheet2->dimx || y2>=sheet2->dimy || z2>=sheet2->dimz || SHEET(sheet2,x2,y2,z2)==(Cell*)0 || SHEET(sheet2,x2,y2,z2)->value.type==EMPTY) return (sortkey&ASCENDING ? 1 : -1); + if (!CELL_IS_GOOD(sheet2,x2,y2,z2) || CELL_AT(sheet2,x2,y2,z2)->value.type==EMPTY) return (sortkey&ASCENDING ? 1 : -1); /*}}}*/ - switch (SHEET(sheet1,x1,y1,z1)->value.type) + leftcell = CELL_AT(sheet1,x1,y1,z1); + rightcell = CELL_AT(sheet2,x2,y2,z2); + switch (leftcell->value.type) { /* STRING */ /*{{{*/ case STRING: { - if (SHEET(sheet2,x2,y2,z2)->value.type==STRING) + if (rightcell->value.type==STRING) { int r; - r=strcmp(SHEET(sheet1,x1,y1,z1)->value.u.string,SHEET(sheet2,x2,y2,z2)->value.u.string); + r=strcmp(leftcell->value.u.string, rightcell->value.u.string); if (r<0) return (sortkey&ASCENDING ? -1 : 1); else if (r==0) return 0; else return (sortkey&ASCENDING ? 1 : -1); @@ -168,16 +245,16 @@ static int cmpcell(Sheet *sheet1, int x1, int y1, int z1, Sheet *sheet2, int x2, /* FLOAT */ /*{{{*/ case FLOAT: { - if (SHEET(sheet2,x2,y2,z2)->value.type==FLOAT) + if (rightcell->value.type==FLOAT) { - if (SHEET(sheet1,x1,y1,z1)->value.u.fltvalue.u.flt) return (sortkey&ASCENDING ? -1 : 1); - else if (SHEET(sheet1,x1,y1,z1)->value.u.flt==SHEET(sheet2,x2,y2,z2)->value.u.flt) return 0; + if (leftcell->value.u.fltvalue.u.flt) return (sortkey&ASCENDING ? -1 : 1); + else if (leftcell->value.u.flt==rightcell->value.u.flt) return 0; else return (sortkey&ASCENDING ? 1 : -1); } - if (SHEET(sheet2,x2,y2,z2)->value.type==INT) + if (rightcell->value.type==INT) { - if (SHEET(sheet1,x1,y1,z1)->value.u.fltvalue.u.integer) return (sortkey&ASCENDING ? -1 : 1); - else if (SHEET(sheet1,x1,y1,z1)->value.u.flt==SHEET(sheet2,x2,y2,z2)->value.u.integer) return 0; + if (leftcell->value.u.fltvalue.u.integer) return (sortkey&ASCENDING ? -1 : 1); + else if (leftcell->value.u.flt==rightcell->value.u.integer) return 0; else return (sortkey&ASCENDING ? 1 : -1); } return 2; @@ -186,16 +263,16 @@ static int cmpcell(Sheet *sheet1, int x1, int y1, int z1, Sheet *sheet2, int x2, /* INT */ /*{{{*/ case INT: { - if (SHEET(sheet2,x2,y2,z2)->value.type==INT) + if (rightcell->value.type==INT) { - if (SHEET(sheet1,x1,y1,z1)->value.u.integervalue.u.integer) return (sortkey&ASCENDING ? -1 : 1); - else if (SHEET(sheet1,x1,y1,z1)->value.u.integer==SHEET(sheet2,x2,y2,z2)->value.u.integer) return 0; + if (leftcell->value.u.integervalue.u.integer) return (sortkey&ASCENDING ? -1 : 1); + else if (leftcell->value.u.integer==rightcell->value.u.integer) return 0; else return (sortkey&ASCENDING ? 1 : -1); } - if (SHEET(sheet2,x2,y2,z2)->value.type==FLOAT) + if (rightcell->value.type==FLOAT) { - if (SHEET(sheet1,x1,y1,z1)->value.u.integervalue.u.flt) return (sortkey&ASCENDING ? -1 : 1); - else if (SHEET(sheet1,x1,y1,z1)->value.u.integer==SHEET(sheet2,x2,y2,z2)->value.u.flt) return 0; + if (leftcell->value.u.integervalue.u.flt) return (sortkey&ASCENDING ? -1 : 1); + else if (leftcell->value.u.integer==rightcell->value.u.flt) return 0; else return (sortkey&ASCENDING ? 1 : -1); } return 2; @@ -213,7 +290,7 @@ void resize(Sheet *sheet, int x, int y, int z) assert(y>=0); assert(z>=0); assert(sheet!=(Sheet*)0); - if (x>=sheet->dimx || y>=sheet->dimy || z>=sheet->dimz) + if (!LOC_WITHIN(sheet,x,y,z)) { /* variables */ /*{{{*/ Cell **newsheet; @@ -229,8 +306,8 @@ void resize(Sheet *sheet, int x, int y, int z) newsheet=malloc(ndimx*ndimy*ndimz*sizeof(Cell*)); for (x=0; xdimx && ydimy && zdimz) *(newsheet+x*ndimz*ndimy+y*ndimz+z)=SHEET(sheet,x,y,z); - else *(newsheet+x*ndimz*ndimy+y*ndimz+z)=(Cell*)0; + if (LOC_WITHIN(sheet,x,y,z)) *(newsheet+x*ndimz*ndimy+y*ndimz+z)=CELL_AT(sheet,x,y,z); + else *(newsheet+x*ndimz*ndimy+y*ndimz+z)= NULLCELL; } if (sheet->sheet!=(Cell**)0) free(sheet->sheet); sheet->sheet=newsheet; @@ -257,30 +334,33 @@ void resize(Sheet *sheet, int x, int y, int z) /* initcell -- initialise new cell, if it does not exist yet */ /*{{{*/ void initcell(Sheet *sheet, int x, int y, int z) { + Cell *nc; + assert(x>=0); assert(y>=0); assert(z>=0); resize(sheet,x,y,z); - if (SHEET(sheet,x,y,z)==(Cell*)0) + if (CELL_AT(sheet,x,y,z) == NULLCELL) { sheet->changed=1; - SHEET(sheet,x,y,z)=malloc(sizeof(Cell)); - SHEET(sheet,x,y,z)->contents=(Token**)0; - SHEET(sheet,x,y,z)->ccontents=(Token**)0; - SHEET(sheet,x,y,z)->label=(char*)0; - SHEET(sheet,x,y,z)->adjust=AUTOADJUST; - SHEET(sheet,x,y,z)->precision=-1; - SHEET(sheet,x,y,z)->shadowed=0; - SHEET(sheet,x,y,z)->bold=0; - SHEET(sheet,x,y,z)->underline=0; - SHEET(sheet,x,y,z)->scientific=DEF_SCIENTIFIC; - SHEET(sheet,x,y,z)->value.type=EMPTY; - SHEET(sheet,x,y,z)->resvalue.type=EMPTY; - SHEET(sheet,x,y,z)->locked=0; - SHEET(sheet,x,y,z)->ignored=0; - SHEET(sheet,x,y,z)->clock_t0=0; - SHEET(sheet,x,y,z)->clock_t1=0; - SHEET(sheet,x,y,z)->clock_t2=0; + nc = malloc(sizeof(Cell)); + CELL_AT(sheet,x,y,z) = nc; + nc->contents = EMPTY_TVEC; + nc->ccontents = EMPTY_TVEC; + nc->label=(char*)0; + nc->adjust=AUTOADJUST; + nc->precision=-1; + nc->shadowed=0; + nc->bold=0; + nc->underline=0; + nc->scientific=DEF_SCIENTIFIC; + nc->value.type=EMPTY; + nc->resvalue.type=EMPTY; + nc->locked=0; + nc->ignored=0; + nc->clock_t0=0; + nc->clock_t1=0; + nc->clock_t2=0; } } /*}}}*/ @@ -305,7 +385,7 @@ void cachelabels(Sheet *sheet) sheet->labelcache[i]=(struct Label*)0; } /*}}}*/ - for (x=0; xdimx; ++x) for (y=0; ydimy; ++y) for (z=0; zdimz; ++z) + for (ALL_CELLS_IN_SHEET(sheet,x,y,z)) /* cache all labels */ /*{{{*/ { const char *l; @@ -343,7 +423,7 @@ void freesheet(Sheet *sheet, int all) assert(sheet!=(Sheet*)0); sheet->changed=0; - for (x=0; xdimx; ++x) for (y=0; ydimy; ++y) for (z=0; zdimz; ++z) + for (ALL_CELLS_IN_SHEET(sheet,x,y,z)) { freecell(sheet,x,y,z); } @@ -386,7 +466,7 @@ void forceupdate(Sheet *sheet) int i; assert(sheet!=(Sheet*)0); - for (i=0; idimx*sheet->dimy*sheet->dimz; ++i) if (*(sheet->sheet+i)!=(Cell*)0) + for (i=0; idimx*sheet->dimy*sheet->dimz; ++i) if (*(sheet->sheet+i) != NULLCELL) { (*(sheet->sheet+i))->updated=0; (*(sheet->sheet+i))->clock_t0=0; @@ -399,14 +479,17 @@ void forceupdate(Sheet *sheet) /* freecell -- free one cell */ /*{{{*/ void freecell(Sheet *sheet, int x, int y, int z) { + Cell *c; assert(sheet!=(Sheet*)0); - if (sheet->sheet!=(Cell**)0 && xdimx && ydimy && zdimz && SHEET(sheet,x,y,z)!=(Cell*)0) + if (sheet->sheet!=(Cell**)0 && CELL_IS_GOOD(sheet,x,y,z)) { - tvecfree(SHEET(sheet,x,y,z)->contents); - tvecfree(SHEET(sheet,x,y,z)->ccontents); - tfree(&(SHEET(sheet,x,y,z)->value)); - free(SHEET(sheet,x,y,z)); - SHEET(sheet,x,y,z)=(Cell*)0; + c = CELL_AT(sheet,x,y,z); + tvecfree(c->contents); + tvecfree(c->ccontents); + tfree(&(c->value)); + tfree(&(c->resvalue)); + free(c); + CELL_AT(sheet,x,y,z) = NULLCELL; sheet->changed=1; } } @@ -448,13 +531,13 @@ void putcont(Sheet *sheet, int x, int y, int z, Token **t, int c) initcell(sheet,x,y,z); if (c) { - tvecfree(SHEET(sheet,x,y,z)->ccontents); - SHEET(sheet,x,y,z)->ccontents=t; + tvecfree(CELL_AT(sheet,x,y,z)->ccontents); + CELL_AT(sheet,x,y,z)->ccontents=t; } else { - tvecfree(SHEET(sheet,x,y,z)->contents); - SHEET(sheet,x,y,z)->contents=t; + tvecfree(CELL_AT(sheet,x,y,z)->contents); + CELL_AT(sheet,x,y,z)->contents=t; } redraw_cell(sheet, x, y, z); } @@ -462,10 +545,9 @@ void putcont(Sheet *sheet, int x, int y, int z, Token **t, int c) /* getcont -- get contents */ /*{{{*/ Token **getcont(Sheet *sheet, int x, int y, int z, int c) { - if (x>=sheet->dimx || y>=sheet->dimy || z>=sheet->dimz) return (Token**)0; - else if (SHEET(sheet,x,y,z)==(Cell*)0) return (Token**)0; - else if (c==2) return (SHEET(sheet,x,y,z)->clock_t0 && SHEET(sheet,x,y,z)->ccontents ? SHEET(sheet,x,y,z)->ccontents : SHEET(sheet,x,y,z)->contents); - else return (c ? SHEET(sheet,x,y,z)->ccontents : SHEET(sheet,x,y,z)->contents); + if (!CELL_IS_GOOD(sheet,x,y,z)) return EMPTY_TVEC; + else if (c==2) return (CELL_AT(sheet,x,y,z)->clock_t0 && CELL_AT(sheet,x,y,z)->ccontents ? CELL_AT(sheet,x,y,z)->ccontents : CELL_AT(sheet,x,y,z)->contents); + else return (c ? CELL_AT(sheet,x,y,z)->ccontents : CELL_AT(sheet,x,y,z)->contents); } /*}}}*/ /* getvalue -- get tcopy()ed value */ /*{{{*/ @@ -482,67 +564,70 @@ Token getvalue(Sheet *sheet, int x, int y, int z) { result.type=EEK; result.u.err=mystrmalloc(_("Negative index")); + return result; } /*}}}*/ - else if (getcont(sheet,x,y,z,2)==(Token**)0) - /* return empty value */ /*{{{*/ - result.type=EMPTY; - /*}}}*/ - else + result.type = EMPTY; + /* Can always short-circuit an out-of-bounds or empty cell */ + if (!CELL_IS_GOOD(sheet,x,y,z)) return result; + /* only short-circuit on empty contents of a good cell if we are NOT + depending on this call to update the current value + */ + if (!upd_clock && getcont(sheet,x,y,z,2) == EMPTY_TVEC) return result; /* update value of this cell if needed and return it */ /*{{{*/ + orig_upd_clock = upd_clock; + if (CELL_AT(sheet,x,y,z)->ignored) { - orig_upd_clock=upd_clock; - if (SHEET(sheet,x,y,z)->ignored) - { - /* variables */ /*{{{*/ - Token oldvalue; - /*}}}*/ + /* variables */ /*{{{*/ + Token oldvalue; + /*}}}*/ - oldvalue=SHEET(sheet,x,y,z)->value; - SHEET(sheet,x,y,z)->updated=1; - SHEET(sheet,x,y,z)->value.type=EMPTY; + oldvalue=CELL_AT(sheet,x,y,z)->value; + CELL_AT(sheet,x,y,z)->updated=1; + CELL_AT(sheet,x,y,z)->value.type=EMPTY; + tfree(&oldvalue); + } + else if (CELL_AT(sheet,x,y,z)->updated==0) + { + /* variables */ /*{{{*/ + Sheet *old_sheet; + int old_x,old_y,old_z,old_max_eval; + Token oldvalue; + /*}}}*/ + + old_sheet=upd_sheet; + old_x=upd_x; + old_y=upd_y; + old_z=upd_z; + old_max_eval=max_eval; + upd_sheet=sheet; + upd_x=x; + upd_y=y; + upd_z=z; + max_eval=MAX_EVALNEST; + if (CELL_AT(sheet,x,y,z)->clock_t1==0) + { + CELL_AT(sheet,x,y,z)->updated = 1; + oldvalue = CELL_AT(sheet,x,y,z)->value; + upd_clock = 0; + CELL_AT(sheet,x,y,z)->value = eval_safe(getcont(sheet, x, y, z, 2)); tfree(&oldvalue); } - else if (SHEET(sheet,x,y,z)->updated==0) + else if (upd_clock) { - /* variables */ /*{{{*/ - Sheet *old_sheet; - int old_x,old_y,old_z,old_max_eval; - Token oldvalue; - /*}}}*/ - - old_sheet=upd_sheet; - old_x=upd_x; - old_y=upd_y; - old_z=upd_z; - old_max_eval=max_eval; - upd_sheet=sheet; - upd_x=x; - upd_y=y; - upd_z=z; - max_eval=MAX_EVALNEST; - if (SHEET(sheet,x,y,z)->clock_t1==0) - { - SHEET(sheet,x,y,z)->updated=1; - oldvalue=SHEET(sheet,x,y,z)->value; - upd_clock=0; - SHEET(sheet,x,y,z)->value=eval(getcont(sheet,x,y,z,2)); - tfree(&oldvalue); - } - else if (upd_clock) - { - SHEET(sheet,x,y,z)->updated=1; - upd_clock=0; - SHEET(sheet,x,y,z)->resvalue=eval(getcont(sheet,x,y,z,2)); - } - upd_sheet=old_sheet; - upd_x=old_x; - upd_y=old_y; - upd_z=old_z; - max_eval=old_max_eval; + CELL_AT(sheet,x,y,z)->updated=1; + upd_clock=0; + oldvalue=CELL_AT(sheet,x,y,z)->resvalue; + CELL_AT(sheet,x,y,z)->resvalue = eval_safe(getcont(sheet,x,y,z,2)); + tfree(&oldvalue); } - if (!orig_upd_clock) result=tcopy(SHEET(sheet,x,y,z)->value); + upd_sheet=old_sheet; + upd_x=old_x; + upd_y=old_y; + upd_z=old_z; + max_eval=old_max_eval; } + if (!orig_upd_clock) result=tcopy(CELL_AT(sheet,x,y,z)->value); /*}}}*/ return result; } @@ -564,28 +649,29 @@ void update(Sheet *sheet) ++iterating; } else if (iterating==0) ++iterating; - for (x=0; xdimx; ++x) for (y=0; ydimy; ++y) for (z=0; zdimz; ++z) + for (ALL_CELLS_IN_SHEET(sheet,x,y,z)) { - if (SHEET(sheet,x,y,z) && SHEET(sheet,x,y,z)->clock_t2) + if (CELL_AT(sheet,x,y,z) && CELL_AT(sheet,x,y,z)->clock_t2) { - SHEET(sheet,x,y,z)->updated=0; - SHEET(sheet,x,y,z)->clock_t0=1; - SHEET(sheet,x,y,z)->clock_t1=1; - SHEET(sheet,x,y,z)->clock_t2=0; + CELL_AT(sheet,x,y,z)->updated=0; + CELL_AT(sheet,x,y,z)->clock_t0=1; + CELL_AT(sheet,x,y,z)->clock_t1=1; + CELL_AT(sheet,x,y,z)->clock_t2=0; } } - for (x=0; xdimx; ++x) for (y=0; ydimy; ++y) for (z=0; zdimz; ++z) + for (ALL_CELLS_IN_SHEET(sheet,x,y,z)) { upd_clock=1; getvalue(sheet,x,y,z); } - for (x=0; xdimx; ++x) for (y=0; ydimy; ++y) for (z=0; zdimz; ++z) + for (ALL_CELLS_IN_SHEET(sheet,x,y,z)) { - if (SHEET(sheet,x,y,z) && SHEET(sheet,x,y,z)->clock_t1) + if (CELL_AT(sheet,x,y,z) && CELL_AT(sheet,x,y,z)->clock_t1) { - tfree(&(SHEET(sheet,x,y,z)->value)); - SHEET(sheet,x,y,z)->value=SHEET(sheet,x,y,z)->resvalue; - SHEET(sheet,x,y,z)->clock_t1=0; + tfree(&(CELL_AT(sheet,x,y,z)->value)); + CELL_AT(sheet,x,y,z)->value = CELL_AT(sheet,x,y,z)->resvalue; + CELL_AT(sheet,x,y,z)->resvalue.type = EMPTY; + CELL_AT(sheet,x,y,z)->clock_t1 = 0; } } upd_clock=0; @@ -615,12 +701,11 @@ char *geterror(Sheet *sheet, int x, int y, int z) /* printvalue -- get ASCII representation of value */ /*{{{*/ void printvalue(char *s, size_t size, size_t chars, int quote, int scientific, int precision, Sheet *sheet, int x, int y, int z) { - Token *tv[2],t; + Token t; assert(sheet!=(Sheet*)0); - t=getvalue(sheet,x,y,z); tv[0]=&t; - tv[1]=(Token*)0; - print(s,size,chars,quote,scientific,precision,tv); + t=getvalue(sheet,x,y,z); + printtok(s,size,chars,quote,scientific,precision,0,&t); tfree(&t); } /*}}}*/ @@ -628,12 +713,12 @@ void printvalue(char *s, size_t size, size_t chars, int quote, int scientific, i Adjust getadjust(Sheet *sheet, int x, int y, int z) { assert(sheet!=(Sheet*)0); - if (x>=sheet->dimx || y>=sheet->dimy || z>=sheet->dimz || SHEET(sheet,x,y,z)==(Cell*)0) + if (!CELL_IS_GOOD(sheet,x,y,z)) { return LEFT; } - else if (SHEET(sheet,x,y,z)->adjust==AUTOADJUST) return (SHEET(sheet,x,y,z)->value.type==INT || SHEET(sheet,x,y,z)->value.type==FLOAT ? RIGHT : LEFT); - else return (SHEET(sheet,x,y,z)->adjust); + else if (CELL_AT(sheet,x,y,z)->adjust==AUTOADJUST) return (CELL_AT(sheet,x,y,z)->value.type==INT || CELL_AT(sheet,x,y,z)->value.type==FLOAT ? RIGHT : LEFT); + else return (CELL_AT(sheet,x,y,z)->adjust); } /*}}}*/ /* setadjust -- set cell adjustment */ /*{{{*/ @@ -643,7 +728,7 @@ void setadjust(Sheet *sheet, int x, int y, int z, Adjust adjust) sheet->changed=1; resize(sheet,x,y,z); initcell(sheet,x,y,z); - SHEET(sheet,x,y,z)->adjust=adjust; + CELL_AT(sheet,x,y,z)->adjust=adjust; } /*}}}*/ @@ -652,7 +737,7 @@ void shadow(Sheet *sheet, int x, int y, int z, int yep) { sheet->changed=1; initcell(sheet,x,y,z); - SHEET(sheet,x,y,z)->shadowed=yep; + CELL_AT(sheet,x,y,z)->shadowed=yep; } /*}}}*/ /* shadowed -- is cell shadowed? */ /*{{{*/ @@ -666,13 +751,13 @@ void bold(Sheet *sheet, int x, int y, int z, int yep) { sheet->changed=1; initcell(sheet,x,y,z); - SHEET(sheet,x,y,z)->bold=yep; + CELL_AT(sheet,x,y,z)->bold=yep; } /*}}}*/ /* isbold -- is cell bold? */ /*{{{*/ int isbold(Sheet *sheet, int x, int y, int z) { - return (xdimx && ydimy && zdimz && SHEET(sheet,x,y,z)!=(Cell*)0 && SHEET(sheet,x,y,z)->bold); + return (CELL_IS_GOOD(sheet,x,y,z) && CELL_AT(sheet,x,y,z)->bold); } /*}}}*/ /* underline -- underline */ /*{{{*/ @@ -680,13 +765,13 @@ void underline(Sheet *sheet, int x, int y, int z, int yep) { sheet->changed=1; initcell(sheet,x,y,z); - SHEET(sheet,x,y,z)->underline=yep; + CELL_AT(sheet,x,y,z)->underline=yep; } /*}}}*/ /* isunderline -- is cell underlined? */ /*{{{*/ int underlined(Sheet *sheet, int x, int y, int z) { - return (xdimx && ydimy && zdimz && SHEET(sheet,x,y,z)!=(Cell*)0 && SHEET(sheet,x,y,z)->underline); + return (CELL_IS_GOOD(sheet,x,y,z) && CELL_AT(sheet,x,y,z)->underline); } /*}}}*/ /* lockcell -- lock cell */ /*{{{*/ @@ -694,19 +779,19 @@ void lockcell(Sheet *sheet, int x, int y, int z, int yep) { sheet->changed=1; initcell(sheet,x,y,z); - SHEET(sheet,x,y,z)->locked=yep; + CELL_AT(sheet,x,y,z)->locked=yep; } /*}}}*/ /* locked -- is cell locked? */ /*{{{*/ int locked(Sheet *sheet, int x, int y, int z) { - return (xdimx && ydimy && zdimz && SHEET(sheet,x,y,z)!=(Cell*)0 && SHEET(sheet,x,y,z)->locked); + return (CELL_IS_GOOD(sheet,x,y,z) && CELL_AT(sheet,x,y,z)->locked); } /*}}}*/ /* transparent -- is cell transparent? */ /*{{{*/ int transparent(Sheet *sheet, int x, int y, int z) { - return (xdimx && ydimy && zdimz && SHEET(sheet,x,y,z)!=(Cell*)0 && SHEET(sheet,x,y,z)->transparent); + return (CELL_IS_GOOD(sheet,x,y,z) && CELL_AT(sheet,x,y,z)->transparent); } /*}}}*/ /* maketrans -- make cell transparent */ /*{{{*/ @@ -714,7 +799,7 @@ void maketrans(Sheet *sheet, int x, int y, int z, int yep) { sheet->changed=1; initcell(sheet,x,y,z); - SHEET(sheet,x,y,z)->transparent=yep; + CELL_AT(sheet,x,y,z)->transparent=yep; } /*}}}*/ /* igncell -- ignore cell */ /*{{{*/ @@ -722,13 +807,13 @@ void igncell(Sheet *sheet, int x, int y, int z, int yep) { sheet->changed=1; initcell(sheet,x,y,z); - SHEET(sheet,x,y,z)->ignored=yep; + CELL_AT(sheet,x,y,z)->ignored=yep; } /*}}}*/ /* ignored -- is cell ignored? */ /*{{{*/ int ignored(Sheet *sheet, int x, int y, int z) { - return (xdimx && ydimy && zdimz && SHEET(sheet,x,y,z)!=(Cell*)0 && SHEET(sheet,x,y,z)->ignored); + return (CELL_IS_GOOD(sheet,x,y,z) && CELL_AT(sheet,x,y,z)->ignored); } /*}}}*/ /* clk -- clock cell */ /*{{{*/ @@ -738,9 +823,9 @@ void clk(Sheet *sheet, int x, int y, int z) assert(x>=0 && xdimx); assert(y>=0 && ydimy); assert(z>=0 && zdimz); - if (SHEET(sheet,x,y,z)) + if (CELL_AT(sheet,x,y,z)) { - SHEET(sheet,x,y,z)->clock_t2=1; + CELL_AT(sheet,x,y,z)->clock_t2=1; sheet->clk=1; } } @@ -751,13 +836,13 @@ void setscientific(Sheet *sheet, int x, int y, int z, int yep) sheet->changed=1; resize(sheet,x,y,z); initcell(sheet,x,y,z); - SHEET(sheet,x,y,z)->scientific=yep; + CELL_AT(sheet,x,y,z)->scientific=yep; } /*}}}*/ /* getscientific -- should value be displayed in scientific notation? */ /*{{{*/ int getscientific(Sheet *sheet, int x, int y, int z) { - if (xdimx && ydimy && zdimz && SHEET(sheet,x,y,z)!=(Cell*)0) return SHEET(sheet,x,y,z)->scientific; + if (CELL_IS_GOOD(sheet,x,y,z)) return CELL_AT(sheet,x,y,z)->scientific; else return DEF_SCIENTIFIC; } /*}}}*/ @@ -767,21 +852,21 @@ void setprecision(Sheet *sheet, int x, int y, int z, int precision) sheet->changed=1; resize(sheet,x,y,z); initcell(sheet,x,y,z); - SHEET(sheet,x,y,z)->precision=precision; + CELL_AT(sheet,x,y,z)->precision=precision; } /*}}}*/ /* getprecision -- get cell precision */ /*{{{*/ int getprecision(Sheet *sheet, int x, int y, int z) { - if (xdimx && ydimy && zdimz && SHEET(sheet,x,y,z)!=(Cell*)0) return (SHEET(sheet,x,y,z)->precision==-1 ? def_precision : SHEET(sheet,x,y,z)->precision); + if (CELL_IS_GOOD(sheet,x,y,z)) return (CELL_AT(sheet,x,y,z)->precision==-1 ? def_precision : CELL_AT(sheet,x,y,z)->precision); else return def_precision; } /*}}}*/ /* getlabel -- get cell label */ /*{{{*/ const char *getlabel(Sheet *sheet, int x, int y, int z) { - if (x>=sheet->dimx || y>=sheet->dimy || z>=sheet->dimz || SHEET(sheet,x,y,z)==(Cell*)0 || SHEET(sheet,x,y,z)->label==(char*)0) return ""; - else return (SHEET(sheet,x,y,z)->label); + if (!CELL_IS_GOOD(sheet,x,y,z) || CELL_AT(sheet,x,y,z)->label==(char*)0) return ""; + else return (CELL_AT(sheet,x,y,z)->label); } /*}}}*/ /* setlabel -- set cell label */ /*{{{*/ @@ -790,9 +875,9 @@ void setlabel(Sheet *sheet, int x, int y, int z, const char *buf, int update) sheet->changed=1; resize(sheet,x,y,z); initcell(sheet,x,y,z); - if (SHEET(sheet,x,y,z)->label!=(char*)0) free(SHEET(sheet,x,y,z)->label); - if (*buf!='\0') SHEET(sheet,x,y,z)->label=strcpy(malloc(strlen(buf)+1),buf); - else SHEET(sheet,x,y,z)->label=(char*)0; + if (CELL_AT(sheet,x,y,z)->label!=(char*)0) free(CELL_AT(sheet,x,y,z)->label); + if (*buf!='\0') CELL_AT(sheet,x,y,z)->label=strcpy(malloc(strlen(buf)+1),buf); + else CELL_AT(sheet,x,y,z)->label=(char*)0; if (update) { cachelabels(sheet); @@ -848,25 +933,28 @@ void relabel(Sheet *sheet, const char *oldlabel, const char *newlabel, int x, in assert(y>=0); assert(z>=0); /*}}}*/ - if (!(x>=sheet->dimx || y>=sheet->dimy || z>=sheet->dimz || SHEET(sheet,x,y,z)==(Cell*)0 || SHEET(sheet,x,y,z)->contents==(Token**)0)) + if (CELL_IS_GOOD(sheet,x,y,z)) { - for (run=SHEET(sheet,x,y,z)->contents; *run!=(Token*)0; ++run) + if (CELL_AT(sheet,x,y,z)->contents != EMPTY_TVEC) { - if ((*run)->type==LIDENT && strcmp((*run)->u.lident,oldlabel)==0) + for (run=CELL_AT(sheet,x,y,z)->contents; *run!=NULLTOKEN; ++run) { - free((*run)->u.lident); - (*run)->u.lident=mystrmalloc(newlabel); + if ((*run)->type==LIDENT && strcmp((*run)->u.lident,oldlabel)==0) + { + free((*run)->u.lident); + (*run)->u.lident=mystrmalloc(newlabel); + } } } - } - if (!(x>=sheet->dimx || y>=sheet->dimy || z>=sheet->dimz || SHEET(sheet,x,y,z)==(Cell*)0 || SHEET(sheet,x,y,z)->ccontents==(Token**)0)) - { - for (run=SHEET(sheet,x,y,z)->ccontents; *run!=(Token*)0; ++run) + if (CELL_AT(sheet,x,y,z)->ccontents != EMPTY_TVEC) { - if ((*run)->type==LIDENT && strcmp((*run)->u.lident,oldlabel)==0) + for (run=CELL_AT(sheet,x,y,z)->ccontents; *run!=NULLTOKEN; ++run) { - free((*run)->u.lident); - (*run)->u.lident=mystrmalloc(newlabel); + if ((*run)->type==LIDENT && strcmp((*run)->u.lident,oldlabel)==0) + { + free((*run)->u.lident); + (*run)->u.lident=mystrmalloc(newlabel); + } } } } @@ -910,10 +998,10 @@ const char *savexdr(Sheet *sheet, const char *name, unsigned int *count) } for (y=sheet->dimy-1; y>=0; --y) { - if (SHEET(sheet,x,y,z)!=(Cell*)0) + if (CELL_AT(sheet,x,y,z)!=NULLCELL) { u=1; - if (xdr_int(&xdrs,&u)==0 || xdr_int(&xdrs,&x)==0 || xdr_int(&xdrs,&y)==0 || xdr_int(&xdrs,&z)==0 || xdr_cell(&xdrs,SHEET(sheet,x,y,z))==0) + if (xdr_int(&xdrs,&u)==0 || xdr_int(&xdrs,&x)==0 || xdr_int(&xdrs,&y)==0 || xdr_int(&xdrs,&z)==0 || xdr_cell(&xdrs,CELL_AT(sheet,x,y,z))==0) { xdr_destroy(&xdrs); (void)fclose(fp); @@ -997,7 +1085,7 @@ const char *savetbl(Sheet *sheet, const char *name, int body, int x1, int y1, in if (!shadowed(sheet,x,y,z)) { if (x>x1 && fputc_close('\t',fp)==EOF) return strerror(errno); - if (SHEET(sheet,x,y,z)!=(Cell*)0) + if (CELL_AT(sheet,x,y,z)!=NULLCELL) { char *bufp; @@ -1084,7 +1172,7 @@ const char *savetext(Sheet *sheet, const char *name, int x1, int y1, int z1, int for (x=x1; x<=x2; ++x) { size=cellwidth(sheet,x,y,z); - if (SHEET(sheet,x,y,z)!=(Cell*)0) + if (CELL_AT(sheet,x,y,z)!=NULLCELL) { char *buf; @@ -1139,13 +1227,13 @@ const char *savecsv(Sheet *sheet, const char *name, char sep, int x1, int y1, in for (x=x1; x<=x2; ++x) { if (x>x1) if (fputc_close(sep,fp)==EOF) return strerror(errno); - if (SHEET(sheet,x,y,z)!=(Cell*)0) + if (CELL_AT(sheet,x,y,z)!=NULLCELL) { char *buf,*s; buf=malloc(255*UTF8SZ+1); printvalue(buf,255*UTF8SZ+1,255,0,getscientific(sheet,x,y,z),getprecision(sheet,x,y,z),sheet,x,y,z); - if (SHEET(sheet,x,y,z)->value.type==STRING && fputc_close('"',fp)==EOF) + if (CELL_AT(sheet,x,y,z)->value.type==STRING && fputc_close('"',fp)==EOF) { free(buf); return strerror(errno); @@ -1159,7 +1247,7 @@ const char *savecsv(Sheet *sheet, const char *name, char sep, int x1, int y1, in } } free(buf); - if (SHEET(sheet,x,y,z)->value.type==STRING && fputc_close('"',fp)==EOF) return strerror(errno); + if (CELL_AT(sheet,x,y,z)->value.type==STRING && fputc_close('"',fp)==EOF) return strerror(errno); } ++*count; } @@ -1193,32 +1281,32 @@ const char *saveport(Sheet *sheet, const char *name, unsigned int *count) for (x=sheet->dimx-1; x>=0; --x) { if (y==0) if (columnwidth(sheet,x,z)!=DEF_COLUMNWIDTH) fprintf(fp,"W%d %d %d\n",x,z,columnwidth(sheet,x,z)); - if (SHEET(sheet,x,y,z)!=(Cell*)0) + if (CELL_AT(sheet,x,y,z)!=NULLCELL) { fprintf(fp,"C%d %d %d ",x,y,z); - if (SHEET(sheet,x,y,z)->adjust!=AUTOADJUST) fprintf(fp,"A%c ","lrc"[SHEET(sheet,x,y,z)->adjust]); - if (SHEET(sheet,x,y,z)->label) fprintf(fp,"L%s ",SHEET(sheet,x,y,z)->label); - if (SHEET(sheet,x,y,z)->precision!=-1) fprintf(fp,"P%d ",SHEET(sheet,x,y,z)->precision); - if (SHEET(sheet,x,y,z)->shadowed) fprintf(fp,"S "); - if (SHEET(sheet,x,y,z)->bold) fprintf(fp,"B "); - if (SHEET(sheet,x,y,z)->underline) fprintf(fp,"U "); - if (SHEET(sheet,x,y,z)->scientific!=DEF_SCIENTIFIC) fprintf(fp,"E "); - if (SHEET(sheet,x,y,z)->locked) fprintf(fp,"C "); - if (SHEET(sheet,x,y,z)->transparent) fprintf(fp,"T "); - if (SHEET(sheet,x,y,z)->contents) + if (CELL_AT(sheet,x,y,z)->adjust!=AUTOADJUST) fprintf(fp,"A%c ","lrc"[CELL_AT(sheet,x,y,z)->adjust]); + if (CELL_AT(sheet,x,y,z)->label) fprintf(fp,"L%s ",CELL_AT(sheet,x,y,z)->label); + if (CELL_AT(sheet,x,y,z)->precision!=-1) fprintf(fp,"P%d ",CELL_AT(sheet,x,y,z)->precision); + if (CELL_AT(sheet,x,y,z)->shadowed) fprintf(fp,"S "); + if (CELL_AT(sheet,x,y,z)->bold) fprintf(fp,"B "); + if (CELL_AT(sheet,x,y,z)->underline) fprintf(fp,"U "); + if (CELL_AT(sheet,x,y,z)->scientific!=DEF_SCIENTIFIC) fprintf(fp,"E "); + if (CELL_AT(sheet,x,y,z)->locked) fprintf(fp,"C "); + if (CELL_AT(sheet,x,y,z)->transparent) fprintf(fp,"T "); + if (CELL_AT(sheet,x,y,z)->contents) { char buf[4096]; if (fputc_close(':',fp)==EOF) return strerror(errno); - print(buf,sizeof(buf),0,1,SHEET(sheet,x,y,z)->scientific,SHEET(sheet,x,y,z)->precision,SHEET(sheet,x,y,z)->contents); + print(buf,sizeof(buf),0,1,CELL_AT(sheet,x,y,z)->scientific,CELL_AT(sheet,x,y,z)->precision,CELL_AT(sheet,x,y,z)->contents); if (fputs_close(buf,fp)==EOF) return strerror(errno); } - if (SHEET(sheet,x,y,z)->ccontents) + if (CELL_AT(sheet,x,y,z)->ccontents) { char buf[4096]; if (fputs_close("\\\n",fp)==EOF) return strerror(errno); - print(buf,sizeof(buf),0,1,SHEET(sheet,x,y,z)->scientific,SHEET(sheet,x,y,z)->precision,SHEET(sheet,x,y,z)->ccontents); + print(buf,sizeof(buf),0,1,CELL_AT(sheet,x,y,z)->scientific,CELL_AT(sheet,x,y,z)->precision,CELL_AT(sheet,x,y,z)->ccontents); if (fputs_close(buf,fp)==EOF) return strerror(errno); } if (fputc_close('\n',fp)==EOF) return strerror(errno); @@ -1479,18 +1567,18 @@ const char *loadport(Sheet *sheet, const char *name) } /*}}}*/ initcell(sheet,x,y,z); - SHEET(sheet,x,y,z)->adjust=adjust; - SHEET(sheet,x,y,z)->label=label; - SHEET(sheet,x,y,z)->precision=precision; - SHEET(sheet,x,y,z)->shadowed=shadowed; - SHEET(sheet,x,y,z)->bold=bold; - SHEET(sheet,x,y,z)->underline=underline; - SHEET(sheet,x,y,z)->scientific=scientific; - SHEET(sheet,x,y,z)->locked=locked; - SHEET(sheet,x,y,z)->transparent=transparent; - SHEET(sheet,x,y,z)->ignored=ignored; - SHEET(sheet,x,y,z)->contents=contents; - SHEET(sheet,x,y,z)->ccontents=ccontents; + CELL_AT(sheet,x,y,z)->adjust=adjust; + CELL_AT(sheet,x,y,z)->label=label; + CELL_AT(sheet,x,y,z)->precision=precision; + CELL_AT(sheet,x,y,z)->shadowed=shadowed; + CELL_AT(sheet,x,y,z)->bold=bold; + CELL_AT(sheet,x,y,z)->underline=underline; + CELL_AT(sheet,x,y,z)->scientific=scientific; + CELL_AT(sheet,x,y,z)->locked=locked; + CELL_AT(sheet,x,y,z)->transparent=transparent; + CELL_AT(sheet,x,y,z)->ignored=ignored; + CELL_AT(sheet,x,y,z)->contents=contents; + CELL_AT(sheet,x,y,z)->ccontents=ccontents; break; } /*}}}*/ @@ -1607,7 +1695,7 @@ const char *loadxdr(Sheet *sheet, const char *name) return strerror(olderror); } initcell(sheet,x,y,z); - if (xdr_cell(&xdrs,SHEET(sheet,x,y,z))==0) + if (xdr_cell(&xdrs,CELL_AT(sheet,x,y,z))==0) { freecell(sheet,x,y,z); olderror=errno; @@ -1743,8 +1831,8 @@ void insertcube(Sheet *sheet, int x1, int y1, int z1, int x2, int y2, int z2, Di for (z=z1; z<=z2; ++z) for (y=y1; y<=y2; ++y) for (x=right; x>x2; --x) { resize(sheet,x,y,z); - SHEET(sheet,x,y,z)=SHEET(sheet,x-(x2-x1+1),y,z); - SHEET(sheet,x-(x2-x1+1),y,z)=(Cell*)0; + CELL_AT(sheet,x,y,z)=CELL_AT(sheet,x-(x2-x1+1),y,z); + CELL_AT(sheet,x-(x2-x1+1),y,z)=NULLCELL; } break; } @@ -1758,8 +1846,8 @@ void insertcube(Sheet *sheet, int x1, int y1, int z1, int x2, int y2, int z2, Di for (z=z1; z<=z2; ++z) for (x=x1; x<=x2; ++x) for (y=down; y>y2; --y) { resize(sheet,x,y,z); - SHEET(sheet,x,y,z)=SHEET(sheet,x,y-(y2-y1+1),z); - SHEET(sheet,x,y-(y2-y1+1),z)=(Cell*)0; + CELL_AT(sheet,x,y,z)=CELL_AT(sheet,x,y-(y2-y1+1),z); + CELL_AT(sheet,x,y-(y2-y1+1),z)=NULLCELL; } break; } @@ -1773,8 +1861,8 @@ void insertcube(Sheet *sheet, int x1, int y1, int z1, int x2, int y2, int z2, Di for (y=y1; y<=y2; ++y) for (x=x1; x<=x2; ++x) for (z=bottom; z>z2; --z) { resize(sheet,x,y,z); - SHEET(sheet,x,y,z)=SHEET(sheet,x,y,z-(z2-z1+1)); - SHEET(sheet,x,y,z-(z2-z1+1))=(Cell*)0; + CELL_AT(sheet,x,y,z)=CELL_AT(sheet,x,y,z-(z2-z1+1)); + CELL_AT(sheet,x,y,z-(z2-z1+1))=NULLCELL; } break; } @@ -1810,8 +1898,8 @@ void deletecube(Sheet *sheet, int x1, int y1, int z1, int x2, int y2, int z2, Di { if (x+(x2-x1+1)dimx && ydimy && zdimz) { - SHEET(sheet,x,y,z)=SHEET(sheet,x+(x2-x1+1),y,z); - SHEET(sheet,x+(x2-x1+1),y,z)=(Cell*)0; + CELL_AT(sheet,x,y,z)=CELL_AT(sheet,x+(x2-x1+1),y,z); + CELL_AT(sheet,x+(x2-x1+1),y,z)=NULLCELL; } } break; @@ -1824,8 +1912,8 @@ void deletecube(Sheet *sheet, int x1, int y1, int z1, int x2, int y2, int z2, Di { if (xdimx && y+(y2-y1+1)dimy && zdimz) { - SHEET(sheet,x,y,z)=SHEET(sheet,x,y+(y2-y1+1),z); - SHEET(sheet,x,y+(y2-y1+1),z)=(Cell*)0; + CELL_AT(sheet,x,y,z)=CELL_AT(sheet,x,y+(y2-y1+1),z); + CELL_AT(sheet,x,y+(y2-y1+1),z)=NULLCELL; } } break; @@ -1838,8 +1926,8 @@ void deletecube(Sheet *sheet, int x1, int y1, int z1, int x2, int y2, int z2, Di { if (xdimx && ydimy && z+(z2-z1+1)dimz) { - SHEET(sheet,x,y,z)=SHEET(sheet,x,y,z+(z2-z1+1)); - SHEET(sheet,x,y,z+(z2-z1+1))=(Cell*)0; + CELL_AT(sheet,x,y,z)=CELL_AT(sheet,x,y,z+(z2-z1+1)); + CELL_AT(sheet,x,y,z+(z2-z1+1))=NULLCELL; } } break; @@ -1884,8 +1972,8 @@ void moveblock(Sheet *sheet, int x1, int y1, int z1, int x2, int y2, int z2, int if (x1+xdimx && y1+ydimy && z1+zdimz) { resize(sheet,x3+x,y3+y,z3+z); - SHEET(sheet,x3+x,y3+y,z3+z)=SHEET(sheet,x1+x,y1+y,z1+z); - SHEET(sheet,x1+x,y1+y,z1+z)=(Cell*)0; + CELL_AT(sheet,x3+x,y3+y,z3+z)=CELL_AT(sheet,x1+x,y1+y,z1+z); + CELL_AT(sheet,x1+x,y1+y,z1+z)=NULLCELL; } else { diff --git a/sheet.h b/sheet.h index 1ee5898..94e27eb 100644 --- a/sheet.h +++ b/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) (xdimx && ydimy && zdimz) +#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; xdimx; ++x) for (y=0; ydimy; ++y) for (z=0; zdimz; ++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); diff --git a/teapot.1 b/teapot.1 index 3a0dbc7..70ad9b5 100644 --- a/teapot.1 +++ b/teapot.1 @@ -2,7 +2,7 @@ .\" Copyright(c) 2010 by wave++ "Yuri D'Elia" .\" 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 diff --git a/wk1.c b/wk1.c index 72574cf..d51c28f 100644 --- a/wk1.c +++ b/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; } /*}}}*/