A first stab at refactoring

In general, the goal of these changes is to be more type-specific wherever
  possible, reduce duplicated code, and avoid magic numbers. The biggest
  individual change is to use Location triples of integers wherever possible
  rather than three separate int variables. Another very helpful change for
  understanding what is going on in the code is introducing the MarkState enum
  for tracking the process of marking and unmarking blocks of cell.

  The MarkState change was motivated by the issues with Ctrl-C,
  and this commit, in fact,
  resolves #28.

  Because of the lack of a test harness, it is possible that a change of
  this scope has created some bugs as well, but teapot was running OK for
  me at the time of the commit. However, I don't know how good my coverage of
  the changed code was -- I certainly did not save or load a Lotus 1-2-3 file!
This commit is contained in:
Glen Whitney 2019-07-27 00:14:26 -04:00
parent 2837cc2253
commit 255bd86bf5
20 changed files with 1521 additions and 1269 deletions

View File

@ -24,29 +24,35 @@
/*}}}*/
/* savecontext -- save as ConTeXt table */ /*{{{*/
const char *savecontext(Sheet *sheet, const char *name, int body, int x1, int y1, int z1, int x2, int y2, int z2, unsigned int *count)
const char *savecontext(Sheet *sheet, const char *name, int body,
const Location beg, const Location end,
unsigned int *count)
{
/* variables */ /*{{{*/
FILE *fp=(FILE*)0; /* cause runtime error */
int x,y,z;
Location w;
char buf[1024];
char num[20];
char fullname[PATH_MAX];
Cell *cell;
/*}}}*/
/* asserts */ /*{{{*/
assert(sheet!=(Sheet*)0);
assert(name!=(const char*)0);
assert(sheet != (Sheet*)0);
assert(name != (const char*)0);
/*}}}*/
*count=0;
for (z=z1; z<=z2; ++z) for (y=y1; y<=y2; ++y) if (shadowed(sheet,x1,y,z)) return _("Shadowed cells in first column");
w[X] = beg[X];
for (w[Z]=beg[Z]; w[Z]<=end[Z]; ++(w[Z]))
for (w[Y]=beg[Y]; w[Y]<=end[Y]; ++(w[Y]))
if (shadowed(CELL_AT(sheet,w))) return _("Shadowed cells in first column");
if (!body && (fp=fopen(name,"w"))==(FILE*)0) return strerror(errno);
for (z=z1; z<=z2; ++z)
for (w[Z]=beg[Z]; w[Z]<=end[Z]; ++(w[Z]))
{
if (body)
/* open new file */ /*{{{*/
{
sprintf(num,".%d",z);
sprintf(num, ".%d", w[Z]);
fullname[sizeof(fullname)-strlen(num)-1]='\0';
(void)strncpy(fullname,name,sizeof(fullname)-strlen(num)-1);
@ -58,7 +64,7 @@ const char *savecontext(Sheet *sheet, const char *name, int body, int x1, int y1
/*}}}*/
else
/* print header */ /*{{{*/
if (z==z1)
if (w[Z] == beg[Z])
{
if (fputs_close("\\starttext\n",fp)==EOF) return strerror(errno);
}
@ -70,31 +76,34 @@ const char *savecontext(Sheet *sheet, const char *name, int body, int x1, int y1
/* print bogus format */ /*{{{*/
fprintf(fp,"\\starttable[");
for (x=x1; x<=x2; ++x) if (fputs_close("|l",fp)==EOF) return strerror(errno);
for (w[X]=beg[X]; w[X]<=end[X]; ++(w[X]))
if (fputs_close("|l",fp)==EOF) return strerror(errno);
fprintf(fp,"|]\n");
/*}}}*/
for (y=y1; y<=y2; ++y)
for (w[Y]=beg[Y]; w[Y]<=end[Y]; ++(w[Y]))
/* print contents */ /*{{{*/
{
for (x=x1; x<=x2; )
for (w[X]=beg[X]; w[X]<=end[X]; )
{
int multicols;
char *bufp;
if (x>x1 && fputs_close("\\NC",fp)==EOF) return strerror(errno);
for (multicols=x+1; multicols<sheet->dimx && shadowed(sheet,multicols,y,z); ++multicols);
multicols=multicols-x;
if (w[X] > beg[X] && fputs_close("\\NC",fp)==EOF) return strerror(errno);
for (multicols=w[X]+1; multicols<sheet->dimx && SHADOWEDC(sheet,multicols,w[Y],w[Z]); ++multicols);
multicols=multicols-w[X];
if (multicols>1) fprintf(fp,"\\use{%d}",multicols);
switch (getadjust(sheet,x,y,z))
cell = CELL_AT(sheet, w);
switch (getadjust(cell))
{
case LEFT: if (fputs_close("\\JustLeft ",fp)==EOF) return strerror(errno); break;
case RIGHT: if (fputs_close("\\JustRight ",fp)==EOF) return strerror(errno); break;
case CENTER: if (fputs_close("\\JustCenter ",fp)==EOF) return strerror(errno); break;
default: assert(0);
}
printvalue(buf,sizeof(buf),0,0,getscientific(sheet,x,y,z),getprecision(sheet,x,y,z),sheet,x,y,z);
printvalue(buf, sizeof(buf), 0, 0, getscientific(cell),
getprecision(cell), sheet, w);
/* if (fputs_close("}{",fp)==EOF) return strerror(errno);*/
if (transparent(sheet,x,y,z))
if (transparent(cell))
{
if (fputs_close(buf,fp)==EOF) return strerror(errno);
}
@ -113,10 +122,10 @@ const char *savecontext(Sheet *sheet, const char *name, int body, int x1, int y1
default: if (fputc_close(*bufp,fp)==EOF) return strerror(errno);
}
/* if (fputc_close('}',fp)==EOF) return strerror(errno);*/
x+=multicols;
w[X] += multicols;
++*count;
}
if (fputs_close(y<y2 ? "\\MR\n" : "\n\\stoptable\n",fp)==EOF) return strerror(errno);
if (fputs_close(w[Y]<end[Y] ? "\\MR\n" : "\n\\stoptable\n",fp)==EOF) return strerror(errno);
}
/*}}}*/
if (body)

View File

@ -3,6 +3,8 @@
#include "sheet.h"
const char *savecontext(Sheet *sheet, const char *name, int body, int x1, int y1, int z1, int x2, int y2, int z2, unsigned int *count);
const char *savecontext(Sheet *sheet, const char *name, int body,
const Location beg, const Location end,
unsigned int *count);
#endif

153
display.c
View File

@ -19,6 +19,7 @@
#include <pwd.h>
#include <termios.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -60,6 +61,8 @@ static int do_attribute(Sheet *cursheet)
MenuChoice mainmenu[5];
MenuChoice adjmenu[11];
MarkState ms;
const char *prompt;
int c;
/* create menus */
@ -82,8 +85,16 @@ static int do_attribute(Sheet *cursheet)
do
{
c = line_menu(cursheet->mark1x==-1 ? _("Cell attribute:") : _("Block attribute:"),mainmenu,0);
if (cursheet->mark1x==-1 && c!=2 && locked(cursheet,cursheet->curx,cursheet->cury,cursheet->curz)) line_msg(_("Cell attribute:"),_("Cell is locked"));
ms = getmarkstate(cursheet);
if (ms == UNMARKED) prompt = _("Cell attribute");
else prompt = _("Block attribute");
c = line_menu(prompt, mainmenu, 0);
/* There is a magic number "2" in the next line, presumably it represents
the selection of the lock attribute in the list of items above, in which
lock does indeed appear at index 2
*/
if (ms == UNMARKED && c != 2 && locked(curcell(cursheet)))
line_msg(_("Cell attribute:"),_("Cell is locked"));
else
{
switch (c)
@ -92,7 +103,7 @@ static int do_attribute(Sheet *cursheet)
case -1: c = KEY_CANCEL; break;
case 0:
{
switch (c=line_menu(cursheet->mark1x==-1 ? _("Cell attribute:") : _("Block attribute:"),adjmenu,0))
switch (c = line_menu(prompt, adjmenu,0))
{
case -2:
case -1: c = K_INVALID; break;
@ -135,6 +146,7 @@ static int do_attribute(Sheet *cursheet)
return c;
}
/* do_file -- file menu */
static int do_file(Sheet *cursheet)
{
@ -406,7 +418,7 @@ void display_end(void)
endwin();
}
void redraw_cell(Sheet *sheet, int x, int y, int z)
void redraw_cell(Sheet *sheet, const Location at )
{
redraw_sheet(sheet);
}
@ -420,35 +432,41 @@ void redraw_sheet(Sheet *sheet)
char *buf=malloc(128);
size_t bufsz=128;
const char *label;
Location tmp;
Cell *cell;
MarkState ms;
char *err;
char moveonly;
assert(sheet!=(Sheet*)0);
assert(sheet->curx>=0);
assert(sheet->cury>=0);
assert(sheet->curz>=0);
assert(IN_OCTANT(sheet->cur));
assert(sheet->offx>=0);
assert(sheet->offy>=0);
/* correct offsets to keep cursor visible */
while (shadowed(sheet,sheet->curx,sheet->cury,sheet->curz))
while (shadowed(curcell(sheet)))
{
--(sheet->curx);
assert(sheet->curx>=0);
--(sheet->cur[X]);
assert(sheet->cur[X] >= 0);
}
if (sheet->cury-sheet->offy>(sheet->maxy-2-header)) sheet->offy=sheet->cury-sheet->maxy+2+header;
if (sheet->cury<sheet->offy) sheet->offy=sheet->cury;
if (sheet->curx<sheet->offx) sheet->offx=sheet->curx;
if (sheet->cur[Y] - sheet->offy > (sheet->maxy - 2 - header))
sheet->offy = sheet->cur[Y] - sheet->maxy + 2 + header;
if (sheet->cur[Y] < sheet->offy) sheet->offy = sheet->cur[Y];
if (sheet->cur[X] < sheet->offx) sheet->offx = sheet->cur[X];
do
{
again=0;
for (width=4*header,x=sheet->offx,col=0; width<=sheet->maxx; width+=columnwidth(sheet,x,sheet->curz),++x,++col);
for (width = 4*header, x = sheet->offx, col=0;
width <= sheet->maxx;
width += columnwidth(sheet, x, sheet->cur[Z]), ++x, ++col);
--col;
sheet->width=col;
if (sheet->curx!=sheet->offx)
sheet->width = col;
if (sheet->cur[X] != sheet->offx)
{
if (col==0) { ++sheet->offx; again=1; }
else if (sheet->curx-sheet->offx>=col) { ++sheet->offx; again=1; }
else if (sheet->cur[X] - sheet->offx >= col) {
++sheet->offx; again=1;
}
}
} while (again);
@ -456,10 +474,12 @@ void redraw_sheet(Sheet *sheet)
(void)wattron(stdscr,DEF_NUMBER);
/* draw x numbers */
for (width=4; width<sheet->maxx; ++width) mvwaddch(stdscr,0+sheet->oriy,sheet->orix+width,(chtype)(unsigned char)' ');
for (width=4,x=sheet->offx; width<sheet->maxx; width+=col,++x)
for (width=4; width < sheet->maxx; ++width)
mvwaddch(stdscr, 0+sheet->oriy, sheet->orix+width,
(chtype)(unsigned char)' ');
for (width=4, x=sheet->offx; width<sheet->maxx; width+=col,++x)
{
col=columnwidth(sheet,x,sheet->curz);
col = columnwidth(sheet, x, sheet->cur[Z]);
if (bufsz<(size_t)(col*UTF8SZ+1)) buf=realloc(buf,bufsz=(size_t)(col*UTF8SZ+1));
snprintf(buf,bufsz,"%d",x);
if (mbslen(buf)>col) {
@ -478,74 +498,86 @@ void redraw_sheet(Sheet *sheet)
(void)wattroff(stdscr,DEF_NUMBER);
/* draw z number */
(void)mvwprintw(stdscr,sheet->oriy,sheet->orix,"%3d",sheet->curz);
(void)mvwprintw(stdscr, sheet->oriy, sheet->orix, "%3d", sheet->cur[Z]);
}
/* draw elements */
for (y=header; y<sheet->maxy-1; ++y) for (width=4*header,x=sheet->offx; width<sheet->maxx; width+=columnwidth(sheet,x,sheet->curz),++x)
for (y=header; y<sheet->maxy-1; ++y)
for (width = 4*header, x = sheet->offx;
width < sheet->maxx;
width += columnwidth(sheet, x, sheet->cur[Z]),++x)
{
size_t size,realsize,fill,cutoff;
int realx;
realx=x;
cutoff=0;
if (x==sheet->offx) while (shadowed(sheet,realx,y-header+sheet->offy,sheet->curz))
realx = x;
cutoff = 0;
if (x == sheet->offx)
while (SHADOWEDC(sheet,realx,y-header+sheet->offy,sheet->cur[Z]))
{
--realx;
cutoff+=columnwidth(sheet,realx,sheet->curz);
cutoff+=columnwidth(sheet, realx, sheet->cur[Z]);
}
if ((size=cellwidth(sheet,realx,y-header+sheet->offy,sheet->curz)))
tmp[X] = realx; tmp[Y] = y - header + sheet->offy;
tmp[Z] = sheet->cur[Z]; cell = safe_cell_at(sheet, tmp);
if ((size = cellwidth(sheet, tmp)))
{
int invert;
bool invert;
if (bufsz<(size*UTF8SZ+1)) buf=realloc(buf,bufsz=(size*UTF8SZ+1));
printvalue(buf,(size*UTF8SZ+1),size,quote,getscientific(sheet,realx,y-header+sheet->offy,sheet->curz),getprecision(sheet,realx,y-header+sheet->offy,sheet->curz),sheet,realx,y-header+sheet->offy,sheet->curz);
adjust(getadjust(sheet,realx,y-header+sheet->offy,sheet->curz),buf,size);
if (bufsz < (size*UTF8SZ+1))
buf = realloc(buf, bufsz=(size*UTF8SZ+1));
printvalue(buf, (size*UTF8SZ+1), size, quote, getscientific(cell),
getprecision(cell), sheet, tmp);
adjust(getadjust(cell), buf, size);
assert(size>=cutoff);
if (width+((int)(size-cutoff))>=sheet->maxx)
if (width+((int)(size-cutoff)) >= sheet->maxx)
{
*(buf+cutoff+sheet->maxx-width)='\0';
realsize=sheet->maxx-width+cutoff;
}
else realsize=size;
invert=
(
(sheet->mark1x!=-1) &&
((x>=sheet->mark1x && x<=sheet->mark2x) || (x>=sheet->mark2x && x<=sheet->mark1x)) &&
((y-header+sheet->offy>=sheet->mark1y && y-header+sheet->offy<=sheet->mark2y) || (y-header+sheet->offy>=sheet->mark2y && y-header+sheet->offy<=sheet->mark1y)) &&
((sheet->curz>=sheet->mark1z && sheet->curz<=sheet->mark2z) || (sheet->curz>=sheet->mark2z && sheet->curz<=sheet->mark1z))
);
if (x==sheet->curx && (y-header+sheet->offy)==sheet->cury) invert=(sheet->marking ? 1 : 1-invert);
ms = getmarkstate(sheet);
invert =
(ms != UNMARKED) && loc_in_box(tmp, sheet->mark1, sheet->mark2);
if (x == sheet->cur[X] && (y-header+sheet->offy) == sheet->cur[Y])
invert = (ms == MARKING) ? true : !invert;
if (invert) (void)wattron(stdscr,DEF_CELLCURSOR);
if (isbold(sheet,realx,y-header+sheet->offy,sheet->curz)) wattron(stdscr,A_BOLD);
if (underlined(sheet,realx,y-header+sheet->offy,sheet->curz)) wattron(stdscr,A_UNDERLINE);
if (isbold(cell)) wattron(stdscr,A_BOLD);
if (underlined(cell)) wattron(stdscr,A_UNDERLINE);
(void)mvwaddstr(stdscr,sheet->oriy+y,sheet->orix+width,buf+cutoff);
for (fill=mbslen(buf+cutoff); fill<realsize; ++fill) (void)waddch(stdscr,(chtype)(unsigned char)' ');
for (fill=mbslen(buf+cutoff); fill<realsize; ++fill)
(void)waddch(stdscr,(chtype)(unsigned char)' ');
wstandend(stdscr);
}
}
/* draw contents of current element */
if (bufsz<(unsigned int)(sheet->maxx*UTF8SZ+1)) buf=realloc(buf,bufsz=(sheet->maxx*UTF8SZ+1));
label=getlabel(sheet,sheet->curx,sheet->cury,sheet->curz);
assert(label!=(const char*)0);
moveonly=sheet->moveonly ? *_("V") : *_("E");
if (*label=='\0') sprintf(pbuf,"%c @(%d,%d,%d)=",moveonly,sheet->curx,sheet->cury,sheet->curz);
else sprintf(pbuf,"%c @(%s)=",moveonly,label);
if (bufsz < (unsigned int)(sheet->maxx*UTF8SZ+1))
buf = realloc(buf,bufsz=(sheet->maxx*UTF8SZ+1));
label = getlabel(curcell(sheet));
assert(label != (const char*)0);
moveonly = sheet->moveonly ? *_("V") : *_("E");
if (*label=='\0')
sprintf(pbuf, "%c @(%d,%d,%d)=", moveonly,
sheet->cur[X], sheet->cur[Y], sheet->cur[Z]);
else sprintf(pbuf, "%c @(%s)=", moveonly, label);
(void)strncpy(buf,pbuf,bufsz);
buf[bufsz-1] = 0;
if ((err=geterror(sheet,sheet->curx,sheet->cury,sheet->curz))!=(const char*)0)
if ((err=geterror(sheet,sheet->cur)) != (const char*)0)
{
(void)strncpy(buf, err, bufsz);
free(err);
(void)strncpy(buf, err, bufsz);
free(err);
}
else
{
print(buf+strlen(buf),bufsz-strlen(buf),0,1,getscientific(sheet,sheet->curx,sheet->cury,sheet->curz),-1,getcont(sheet,sheet->curx,sheet->cury,sheet->curz,0));
if (getcont(sheet,sheet->curx,sheet->cury,sheet->curz,1) && mbslen(buf) < (size_t)(sheet->maxx+1-4))
{
strcat(buf," -> ");
print(buf+strlen(buf),bufsz-strlen(buf),0,1,getscientific(sheet,sheet->curx,sheet->cury,sheet->curz),-1,getcont(sheet,sheet->curx,sheet->cury,sheet->curz,1));
cell = curcell(sheet);
print(buf+strlen(buf), bufsz-strlen(buf), 0, 1, getscientific(cell),
-1, getcont(cell, BASE));
if (getcont(cell, ITERATIVE) && mbslen(buf) < (size_t)(sheet->maxx+1-4))
{
strcat(buf," -> ");
print(buf+strlen(buf), bufsz-strlen(buf), 0, 1,
getscientific(cell), -1, getcont(cell, ITERATIVE));
}
}
*mbspos(buf, sheet->maxx) = 0;
@ -615,7 +647,9 @@ int line_edit(Sheet *sheet, char *buf, size_t size, const char *prompt, size_t *
case 'v': {
char valbuf[1024];
printvalue(valbuf,sizeof(valbuf),0,1,getscientific(sheet,sheet->curx,sheet->cury,sheet->curz),-1,sheet,sheet->curx,sheet->cury,sheet->curz);
printvalue(valbuf, sizeof(valbuf), 0, 1,
getscientific(curcell(sheet)), -1,
sheet, sheet->cur);
if (strlen(buf)+strlen(valbuf) >= (size-1)) break;
(void)memmove(src+strlen(valbuf), src, strlen(src));
(void)memcpy(src, valbuf, strlen(valbuf));
@ -627,7 +661,8 @@ int line_edit(Sheet *sheet, char *buf, size_t size, const char *prompt, size_t *
case 'p': {
char valbuf[1024];
sprintf(valbuf,"(%d,%d,%d)",sheet->curx,sheet->cury,sheet->curz);
sprintf(valbuf, "(%d,%d,%d)",
sheet->cur[X], sheet->cur[Y], sheet->cur[Z]);
if (strlen(buf)+strlen(valbuf) >= (size-1)) break;
(void)memmove(src+strlen(valbuf), src, strlen(src));
(void)memcpy(src, valbuf, strlen(valbuf));

View File

@ -17,7 +17,7 @@ typedef struct
void display_main(Sheet *cursheet);
void display_init(Sheet *cursheet, int always_redraw);
void display_end(void);
void redraw_cell(Sheet *sheet, int x, int y, int z);
void redraw_cell(Sheet *sheet, const Location at);
void redraw_sheet(Sheet *sheet);
const char *line_file(const char *file, const char *pattern, const char *title, int create);
int line_edit(Sheet *sheet, char *buf, size_t size, const char *prompt, size_t *x, size_t *offx);

4
eval.c
View File

@ -84,15 +84,17 @@ void tvecfree(Token **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);
for (len = 0; *tvec != NULLTOKEN; ++len,++tvec);
return len;
}
/*}}}*/
/* tadd -- + operator */ /*{{{*/
Token tadd(Token l, Token r)
{

View File

@ -104,22 +104,22 @@ do_callback(CONTEXT_NONE, 0, 0);} {}
} {
code {return cursheet;} {}
}
Function {draw_cell(TableContext context, int R, int C, int X, int Y, int W, int H)} {open return_type void
Function {draw_cell(TableContext context, int R, int C, int xx, int yy, int W, int H)} {open return_type void
} {
code {char s[1024];
//printf("DRAW: %i @%i,%i - (%i,%i) %ix%i\\n", context, C,R, X,Y, W,H);
//printf("DRAW: %i @%i,%i - (%i,%i) %ix%i\\n", context, C,R, xx,yy, W,H);
switch (context) {
case CONTEXT_ENDPAGE:
W = X-x()-2;
H = Y-y()-2;
X = x()+2;
Y = y()+2;
W = xx-x()-2;
H = yy-y()-2;
xx = x()+2;
yy = y()+2;
fl_font(FL_HELVETICA | FL_BOLD, 14);
fl_push_clip(X, Y, W, H);
fl_draw_box(FL_DIAMOND_UP_BOX, X, Y, W, H, col_header_color());
fl_push_clip(xx, yy, W, H);
fl_draw_box(FL_DIAMOND_UP_BOX, xx, yy, W, H, col_header_color());
fl_color(FL_INACTIVE_COLOR);
sprintf(s, "%d", cursheet->curz);
fl_draw(s, X, Y, W, H, FL_ALIGN_CENTER);
sprintf(s, "%d", cursheet->cur[Z]);
fl_draw(s, xx, yy, W, H, FL_ALIGN_CENTER);
fl_pop_clip();
break;
@ -130,54 +130,59 @@ case CONTEXT_STARTPAGE:
case CONTEXT_COL_HEADER:
fl_font(FL_HELVETICA | FL_BOLD, 14);
fl_push_clip(X, Y, W, H);
fl_draw_box(FL_THIN_UP_BOX, X, Y, W, H, col_header_color());
fl_push_clip(xx, yy, W, H);
fl_draw_box(FL_THIN_UP_BOX, xx, yy, W, H, col_header_color());
fl_color(FL_FOREGROUND_COLOR);
sprintf(s, "%d", C);
fl_draw(s, X, Y, W, H, FL_ALIGN_CENTER);
fl_draw(s, xx, yy, W, H, FL_ALIGN_CENTER);
fl_pop_clip();
return;
case CONTEXT_ROW_HEADER:
fl_font(FL_HELVETICA | FL_BOLD, 14);
fl_push_clip(X, Y, W, H);
fl_draw_box(FL_THIN_UP_BOX, X, Y, W, H, row_header_color());
fl_push_clip(xx, yy, W, H);
fl_draw_box(FL_THIN_UP_BOX, xx, yy, W, H, row_header_color());
fl_color(FL_FOREGROUND_COLOR);
sprintf(s, "%d", R);
fl_draw(s, X, Y, W, H, FL_ALIGN_CENTER);
fl_draw(s, xx, yy, W, H, FL_ALIGN_CENTER);
fl_pop_clip();
return;
case CONTEXT_CELL: {
while (SHADOWED(cursheet, C, R, cursheet->curz)) X -= W = col_width(--C);
while (SHADOWEDC(cursheet, C, R, cursheet->cur[Z])) xx -= W = col_width(--C);
int x = C+1;
while (SHADOWED(cursheet,x,R,cursheet->curz)) W += col_width(x), x++;
while (SHADOWEDC(cursheet,x,R,cursheet->cur[Z])) W += col_width(x), x++;
fl_push_clip(X, Y, W, H);
fl_push_clip(xx, yy, W, H);
bool selected = false;
if (cursheet->mark1x >= 0) {
int x1 = cursheet->mark1x, x2 = cursheet->mark2x, y1 = cursheet->mark1y, y2 = cursheet->mark2y, z1 = cursheet->mark1z, z2 = cursheet->mark2z;
posorder(&x1, &x2);
posorder(&y1, &y2);
posorder(&z1, &z2);
selected = cursheet->mark1x >= 0 && C >= x1 && C <= x2 && R >= y1 && R <= y2 && cursheet->curz >= z1 && cursheet->curz <= z2;
}
fl_draw_box(C == cursheet->curx && R == cursheet->cury?FL_BORDER_BOX:FL_THIN_DOWN_BOX, X, Y, W, H, selected?FL_SELECTION_COLOR:FL_BACKGROUND2_COLOR);
if (Fl::focus() == this && C == cursheet->curx && R == cursheet->cury) draw_focus(FL_BORDER_BOX, X, Y, W, H);
MarkState ms = getmarkstate(cursheet);
Location test;
test[X] = C; test[Y] = R; test[Z] = cursheet->cur[Z];
if (ms != UNMARKED)
selected = loc_in_box(test, cursheet->mark1, cursheet->mark2);
bool iscurrent = C == cursheet->cur[X] && R == cursheet->cur[Y];
fl_draw_box(iscurrent ? FL_BORDER_BOX : FL_THIN_DOWN_BOX, xx, yy, W, H,
selected ? FL_SELECTION_COLOR : FL_BACKGROUND2_COLOR);
if (Fl::focus() == this && iscurrent)
draw_focus(FL_BORDER_BOX, xx, yy, W, H);
fl_pop_clip();
fl_push_clip(X+3, Y+3, W-6, H-6);
fl_color(FL_FOREGROUND_COLOR);
fl_font(FL_HELVETICA | (isbold(cursheet, C, R, cursheet->curz)? FL_BOLD:0), 14);
Cell *cell = safe_cell_at(cursheet, test);
fl_push_clip(xx+3, yy+3, W-6, H-6);
fl_color(FL_FOREGROUND_COLOR);
fl_font(FL_HELVETICA | (isbold(cell) ? FL_BOLD : 0), 14);
printvalue(s, sizeof(s), 0, 0, getscientific(cell),
getprecision(cell), cursheet, test);
printvalue(s, sizeof(s), 0, 0, getscientific(cursheet, C, R, cursheet->curz), getprecision(cursheet, C, R, cursheet->curz), cursheet, C, R, cursheet->curz);
int ww = 0, hh = 0;
fl_measure(s, ww, hh, 0);
if (ww > W-6) for (int i = 0; s[i]; i++) s[i] = '\#';
int adj = getadjust(cursheet, C, R, cursheet->curz);
fl_draw(s, X+3, Y+3, W-6, H-6, adj == RIGHT?FL_ALIGN_RIGHT:adj == LEFT?FL_ALIGN_LEFT:FL_ALIGN_CENTER);
if (underlined(cursheet, C, R, cursheet->curz)) fl_xyline(X, Y+H-7, X+W);
int adj = getadjust(cell);
fl_draw(s, xx+3, yy+3, W-6, H-6, adj == RIGHT?FL_ALIGN_RIGHT:adj == LEFT?FL_ALIGN_LEFT:FL_ALIGN_CENTER);
if (underlined(cell)) fl_xyline(xx, yy+H-7, xx+W);
fl_pop_clip();
return;
@ -200,12 +205,13 @@ if (cursheet->dimy > rows()) rows(cursheet->dimy);
adjust_outside();
for (int x = 0; x < cursheet->dimx; x++) {
int w = columnwidth(cursheet, x, cursheet->curz)*10;
int w = columnwidth(cursheet, x, cursheet->cur[Z])*10;
if (col_width(x) != w) col_width(x, w);
}
col_position(cursheet->offx);
row_position(cursheet->offy);
set_selection(cursheet->cury, cursheet->curx, cursheet->cury, cursheet->curx);
set_selection(cursheet->cur[Y], cursheet->cur[X],
cursheet->cur[Y], cursheet->cur[X]);
move_cursor(0,0);
updating = false;} {}
}
@ -218,12 +224,12 @@ updating = true;
get_selection(y1, x1, y2, x2);
if (x1 != x2 || y1 != y2) {
cursheet->mark1x = x1;
cursheet->mark1y = y1;
cursheet->mark2x = x2;
cursheet->mark2y = y2;
cursheet->mark1z = cursheet->mark2z = cursheet->curz;
cursheet->marking = 0;
cursheet->mark1[X] = x1;
cursheet->mark1[Y] = y1;
cursheet->mark2[X] = x2;
cursheet->mark2[Y] = y2;
cursheet->mark1[Z] = cursheet->mark2[Z] = cursheet->cur[Z];
cursheet->marking = MARKED;
}
moveto(cursheet, current_col, current_row, -1);
visible_cells(cursheet->offy, cursheet->maxy, cursheet->offx, cursheet->maxx);
@ -231,10 +237,11 @@ cursheet->maxx -= cursheet->offx;
cursheet->maxy -= cursheet->offy;
if (is_interactive_resize()) {
for (int C = 0; C < cursheet->dimx; C++) {
int w = (col_width(C) + 5)/10;
if (w != columnwidth(cursheet, C, cursheet->curz)) setwidth(cursheet, C, cursheet->curz, w);
}
for (int C = 0; C < cursheet->dimx; C++) {
int w = (col_width(C) + 5)/10;
if (w != columnwidth(cursheet, C, cursheet->cur[Z]))
setwidth(cursheet, C, cursheet->cur[Z], w);
}
}
@ -259,19 +266,22 @@ updating = false;
case FL_Tab: if (shift) { k = K_CLOCK; break; }
case FL_Enter:
case FL_KP_Enter: k = alt?K_MENTER:K_ENTER; break;
case 'c': if (ctrl) { do_mark(cursheet, 2); cut = false; k = K_NONE; } break;
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 'c': if (ctrl) { do_mark(cursheet, GET_MARK_CUR); cut = false; k = K_NONE; } break;
case 'v': if (ctrl) { do_mark(cursheet, MARKED);
k = cut ? BLOCK_MOVE : BLOCK_COPY;
}
break;
case 'x': if (ctrl) { do_mark(cursheet, GET_MARK_CUR); 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_Insert: if (ctrl) { do_mark(cursheet, GET_MARK_CUR); cut = false; } k = !shift?K_NONE:cut?BLOCK_MOVE:BLOCK_COPY; break;
case FL_Delete: if (shift) { do_mark(cursheet, GET_MARK_CUR); cut = true; } k = shift?K_NONE:BLOCK_CLEAR; break;
case FL_Home: k = ctrl?K_FIRSTL:shift?K_FSHEET:K_HOME; break;
case FL_End: k = ctrl?K_LASTL:shift?K_LSHEET:K_END; break;
case FL_Up: if (shift && !cursheet->marking) do_mark(cursheet, 1); k = ctrl?K_PPAGE:K_UP; break;
case FL_Down: if (shift && !cursheet->marking) do_mark(cursheet, 1); k = ctrl?K_NPAGE:K_DOWN; break;
case FL_Right: if (shift && !cursheet->marking) do_mark(cursheet, 1); k = ctrl?K_FPAGE:K_RIGHT; break;
case FL_Left: if (shift && !cursheet->marking) do_mark(cursheet, 1); k = ctrl?K_BPAGE:K_LEFT; break;
case FL_Up: if (shift) do_mark(cursheet, MARKING); k = ctrl?K_PPAGE:K_UP; break;
case FL_Down: if (shift) do_mark(cursheet, MARKING); k = ctrl?K_NPAGE:K_DOWN; break;
case FL_Right: if (shift) do_mark(cursheet, MARKING); k = ctrl?K_FPAGE:K_RIGHT; break;
case FL_Left: if (shift) do_mark(cursheet, MARKING); k = ctrl?K_BPAGE:K_LEFT; break;
case FL_Page_Down: k = shift?K_NSHEET:ctrl?K_LASTL :K_NPAGE; break;
case FL_Page_Up: k = shift?K_PSHEET:ctrl?K_FIRSTL:K_PPAGE; break;
}
@ -557,17 +567,23 @@ if (Fl::focus() && (Fl::focus() != table || enterkey || Fl::event_key(FL_Escape)
callback {Sheet *sheet = table->sheet();
table->update_sheet();
const char *label = getlabel(sheet,sheet->curx,sheet->cury,sheet->curz);
const char *label = getlabel(curcell(sheet));
char moveonly=sheet->moveonly ? *_("V") : *_("E");
char buf[1024];
if (*label == 0) snprintf(buf, sizeof(buf), "%c @@(%d,%d,%d)=", moveonly, sheet->curx, sheet->cury, sheet->curz);
if (*label == 0)
snprintf(buf, sizeof(buf), "%c @@(%d,%d,%d)=", moveonly,
sheet->cur[X], sheet->cur[Y], sheet->cur[Z]);
else snprintf(buf, sizeof(buf), "%c @@(%s)=", moveonly, label);
if (moveonly && table->callback_context() == TeapotTable::ACTION) {
char valbuf[1024] = "";
if (Fl::event_key() == 'p' || Fl::event_button1()) sprintf(valbuf, "(%i,%i,%i)", sheet->curx, sheet->cury, sheet->curz);
else if (Fl::event_key() == 'v') printvalue(valbuf,sizeof(valbuf),0,1,getscientific(sheet,sheet->curx,sheet->cury,sheet->curz),-1,sheet,sheet->curx,sheet->cury,sheet->curz);
if (Fl::event_key() == 'p' || Fl::event_button1())
sprintf(valbuf, "(%i,%i,%i)",
sheet->cur[X], sheet->cur[Y], sheet->cur[Z]);
else if (Fl::event_key() == 'v')
printvalue(valbuf, sizeof(valbuf), 0, 1,
getscientific(curcell(sheet)), -1, sheet, sheet->cur);
else if (Fl::event_key(FL_Tab)) line_input->take_focus();
if (valbuf[0]) {
line_input->insert(valbuf);
@ -578,37 +594,41 @@ if (moveonly && table->callback_context() == TeapotTable::ACTION) {
char *err;
char val[1024];
if ((err = geterror(sheet, sheet->curx, sheet->cury, sheet->curz))) {
strncpy(val,err,sizeof(val));
free(err);
val[sizeof(val)-1] = 0;
if ((err = geterror(sheet, sheet->cur))) {
strncpy(val,err,sizeof(val));
free(err);
val[sizeof(val)-1] = 0;
} else {
print(val,sizeof(val),0,1,getscientific(sheet,sheet->curx,sheet->cury,sheet->curz),-1,getcont(sheet,sheet->curx,sheet->cury,sheet->curz,0));
if (getcont(sheet,sheet->curx,sheet->cury,sheet->curz,1)) {
snprintf(val+strlen(val),sizeof(val)-strlen(val)," -> ");
print(val+strlen(val),sizeof(val)-strlen(val),0,1,getscientific(sheet,sheet->curx,sheet->cury,sheet->curz),-1,getcont(sheet,sheet->curx,sheet->cury,sheet->curz,1));
print(val, sizeof(val), 0, 1, getscientific(curcell(sheet)), -1,
getcont(curcell(sheet), BASE));
Token **iter = getcont(curcell(sheet), ITERATIVE);
if (iter != EMPTY_TVEC) {
snprintf(val+strlen(val),sizeof(val)-strlen(val)," -> ");
print(val+strlen(val), sizeof(val)-strlen(val), 0, 1,
getscientific(curcell(sheet)), -1, iter);
}
}
line_edit(sheet, val, 0, buf, 0, 0);
int x = sheet->curx, y = sheet->cury, z = sheet->curz;
int adj = getadjust(sheet, x, y, z);
Cell *cell = curcell(sheet);
int adj = getadjust(cell);
if (adj == LEFT) left->setonly();
else if (adj == RIGHT) right->setonly();
else if (adj == CENTER) center->setonly();
if (shadowed(sheet, x+1, y, z)) shadow->set();
if (SHADOWEDC(sheet, sheet->cur[X]+1, sheet->cur[Y], sheet->cur[Z]))
shadow->set();
else shadow->clear();
if (::transparent(sheet, x, y, z)) transparent->set();
if (::transparent(cell)) transparent->set();
else transparent->clear();
if (locked(sheet, x, y, z)) lock->set();
if (locked(cell)) lock->set();
else lock->clear();
if (ignored(sheet, x, y, z)) ignore->set();
if (ignored(cell)) ignore->set();
else ignore->clear();
if (isbold(sheet, x, y, z)) bold->set();
if (isbold(cell)) bold->set();
else bold->clear();
if (underlined(sheet, x, y, z)) underline->set();
if (underlined(cell)) underline->set();
else underline->clear();
if (getscientific(sheet, x, y, z)) sci->set();
if (getscientific(cell)) sci->set();
else sci->clear();}
protected xywh {0 50 800 525} box DOWN_FRAME labeltype NO_LABEL resizable
code0 {table->sheet(sheet);}
@ -758,7 +778,7 @@ t->update_table();
t->redraw();} {}
}
Function {redraw_cell(Sheet *sheet, int x, int y, int z)} {C return_type void
Function {redraw_cell(Sheet *sheet, const Location /* at */)} {C return_type void
} {
code {redraw_sheet(sheet);} {}
}

195
func.c
View File

@ -303,11 +303,15 @@ static double deg2rad(double x)
}
/*}}}*/
#define INTPATIBLE(t) (t.type == INT || t.type == EMPTY)
/* @ */ /*{{{*/
static Token at_func(int argc, const Token argv[])
{
/* variables */ /*{{{*/
Token result;
Location tmp;
Dimensions dim;
/*}}}*/
/* asserts */ /*{{{*/
@ -315,23 +319,36 @@ static Token at_func(int argc, const Token argv[])
/*}}}*/
if (argc==0)
/* return value at current location */ /*{{{*/
return (getvalue(upd_sheet,upd_x,upd_y,upd_z));
return (getvalue(upd_sheet, upd_l));
/*}}}*/
if (argc==1 && argv[0].type==LOCATION)
/* return value at location pointed to by argument */ /*{{{*/
return (getvalue(upd_sheet,argv[0].u.location[0],argv[0].u.location[1],argv[0].u.location[2]));
return (getvalue(upd_sheet, argv[0].u.location));
/*}}}*/
else if (argc==1 && (argv[0].type==INT || argv[0].type==EMPTY))
LOCATION_GETS(tmp, upd_l);
if (argc==1 && (argv[0].type==INT || argv[0].type==EMPTY))
/* return value at x on current y,z */ /*{{{*/
return (getvalue(upd_sheet,argv[0].type==INT ? argv[0].u.integer : upd_x,upd_y,upd_z));
{
if (argv[0].type == INT) tmp[X] = argv[0].u.integer;
return getvalue(upd_sheet, tmp);
}
/*}}}*/
else if (argc==2 && (argv[0].type==INT || argv[0].type==EMPTY) && (argv[1].type==INT || argv[1].type==EMPTY))
if (argc==2 && INTPATIBLE(argv[0]) && INTPATIBLE(argv[1]))
/* return value at x,y on current z */ /*{{{*/
return (getvalue(upd_sheet,argv[0].type==INT ? argv[0].u.integer : upd_x,argv[1].type==INT ? argv[1].u.integer : upd_y,upd_z));
{
if (argv[0].type == INT) tmp[X] = argv[0].u.integer;
if (argv[1].type == INT) tmp[Y] = argv[1].u.integer;
return getvalue(upd_sheet, tmp);
}
/*}}}*/
else if (argc==3 && (argv[0].type==INT || argv[0].type==EMPTY) && (argv[1].type==INT || argv[1].type==EMPTY) && (argv[2].type==INT || argv[2].type==EMPTY))
if (argc==3 && INTPATIBLE(argv[0]) && INTPATIBLE(argv[1]) &&
INTPATIBLE(argv[2]))
/* return value at x,y,z */ /*{{{*/
return (getvalue(upd_sheet,argv[0].type==INT ? argv[0].u.integer : upd_x,argv[1].type==INT ? argv[1].u.integer : upd_y,argv[2].type==INT ? argv[2].u.integer : upd_z));
{
for (dim = X; dim < HYPER; ++dim)
if (argv[dim].type == INT) tmp[dim] = argv[dim].u.integer;
return getvalue(upd_sheet, tmp);
}
/*}}}*/
else
/* return error */ /*{{{*/
@ -343,50 +360,48 @@ static Token at_func(int argc, const Token argv[])
/*}}}*/
}
/*}}}*/
/* & */ /*{{{*/
static Token adr_func(int argc, const Token argv[])
{
/* variables */ /*{{{*/
Token result;
Dimensions dim;
/*}}}*/
/* asserts */ /*{{{*/
assert(argv!=(Token*)0);
assert(argv != (Token*)0);
/*}}}*/
if (argc==3 && (argv[0].type==INT || argv[0].type==EMPTY) && (argv[1].type==INT || argv[1].type==EMPTY) && (argv[2].type==INT || argv[2].type==EMPTY))
LOCATION_GETS(result.u.location, upd_l);
if (argc==3 && INTPATIBLE(argv[0]) && INTPATIBLE(argv[1]) &&
INTPATIBLE(argv[2]))
/* result is location of the given position */ /*{{{*/
{
result.type=LOCATION;
result.u.location[0]=(argv[0].type==INT ? argv[0].u.integer : upd_x);
result.u.location[1]=(argv[1].type==INT ? argv[1].u.integer : upd_y);
result.u.location[2]=(argv[2].type==INT ? argv[2].u.integer : upd_z);
for (dim = X; dim < HYPER; ++dim)
if (argv[dim].type == INT) result.u.location[dim] = argv[dim].u.integer;
}
/*}}}*/
else if (argc==2 && (argv[0].type==INT || argv[0].type==EMPTY) && (argv[1].type==INT || argv[1].type==EMPTY))
else if (argc==2 && INTPATIBLE(argv[0]) && INTPATIBLE(argv[1]))
/* result is location of the given position in the current z layer */ /*{{{*/
{
result.type=LOCATION;
result.u.location[0]=(argv[0].type==INT ? argv[0].u.integer : upd_x);
result.u.location[1]=(argv[1].type==INT ? argv[1].u.integer : upd_y);
result.u.location[2]=upd_z;
for (dim = X; dim <= Y; ++dim)
if (argv[dim].type == INT) result.u.location[dim] = argv[dim].u.integer;
}
/*}}}*/
else if (argc==1 && (argv[0].type==INT || argv[0].type==EMPTY))
else if (argc==1 && INTPATIBLE(argv[0]))
/* result is location of the given position in the current y,z layer */ /*{{{*/
{
result.type=LOCATION;
result.u.location[0]=(argv[0].type==INT ? argv[0].u.integer : upd_x);
result.u.location[1]=upd_y;
result.u.location[2]=upd_z;
if (argv[0].type == INT) result.u.location[X] = argv[0].u.integer;
}
/*}}}*/
else if (argc==0)
/* result is location of the current position */ /*{{{*/
{
result.type=LOCATION;
result.u.location[0]=upd_x;
result.u.location[1]=upd_y;
result.u.location[2]=upd_z;
}
/*}}}*/
else
@ -399,6 +414,7 @@ static Token adr_func(int argc, const Token argv[])
return result;
}
/*}}}*/
/* x */ /*{{{*/
static Token x_func(int argc, const Token argv[])
{
@ -409,15 +425,15 @@ static Token x_func(int argc, const Token argv[])
if (argc==0)
/* result is currently updated x position */ /*{{{*/
{
result.type=INT;
result.u.integer=upd_x;
result.type = INT;
result.u.integer = upd_l[X];
}
/*}}}*/
else if (argc==1 && argv[0].type==LOCATION)
/* return x component of location */ /*{{{*/
{
result.type=INT;
result.u.integer=argv[0].u.location[0];
result.type = INT;
result.u.integer = argv[0].u.location[X];
}
/*}}}*/
else
@ -430,6 +446,7 @@ static Token x_func(int argc, const Token argv[])
return result;
}
/*}}}*/
/* y */ /*{{{*/
static Token y_func(int argc, const Token argv[])
{
@ -440,15 +457,15 @@ static Token y_func(int argc, const Token argv[])
if (argc==0)
/* result is currently updated y position */ /*{{{*/
{
result.type=INT;
result.u.integer=upd_y;
result.type = INT;
result.u.integer = upd_l[Y];
}
/*}}}*/
else if (argc==1 && argv[0].type==LOCATION)
/* return y component of location */ /*{{{*/
{
result.type=INT;
result.u.integer=argv[0].u.location[1];
result.type = INT;
result.u.integer = argv[0].u.location[Y];
}
/*}}}*/
else
@ -461,6 +478,7 @@ static Token y_func(int argc, const Token argv[])
return result;
}
/*}}}*/
/* z */ /*{{{*/
static Token z_func(int argc, const Token argv[])
{
@ -471,15 +489,15 @@ static Token z_func(int argc, const Token argv[])
if (argc==0)
/* result is currently updated z position */ /*{{{*/
{
result.type=INT;
result.u.integer=upd_z;
result.type = INT;
result.u.integer = upd_l[Z];
}
/*}}}*/
else if (argc==1 && argv[0].type==LOCATION)
else if (argc == 1 && argv[0].type == LOCATION)
/* return z component of location */ /*{{{*/
{
result.type=INT;
result.u.integer=argv[0].u.location[2];
result.type = INT;
result.u.integer = argv[0].u.location[Z];
}
/*}}}*/
else
@ -492,6 +510,7 @@ static Token z_func(int argc, const Token argv[])
return result;
}
/*}}}*/
/* e */ /*{{{*/
static Token e_func(int argc, const Token argv[])
{
@ -534,8 +553,10 @@ static Token eval_func(int argc, const Token argv[])
{
Token **contents;
contents=getcont(upd_sheet,argv[0].u.location[0],argv[0].u.location[1],argv[0].u.location[2],2);
if (contents==(Token**)0) result.type=EMPTY;
contents = EMPTY_TVEC;
if (LOC_WITHIN(upd_sheet, argv[0].u.location))
contents = getcont(CELL_AT(upd_sheet,argv[0].u.location), CONTINGENT);
if (contents == EMPTY_TVEC) result.type = EMPTY;
else result=eval(contents);
}
/*}}}*/
@ -550,6 +571,7 @@ static Token eval_func(int argc, const Token argv[])
return result;
}
/*}}}*/
/* error */ /*{{{*/
static Token error_func(int argc, const Token argv[])
{
@ -577,23 +599,28 @@ static Token string_func(int argc, const Token argv[])
{
/* variables */ /*{{{*/
Token result;
Cell *cell;
char *buf;
char staticbuf[4096];
size_t size;
/*}}}*/
if (argc==1 && argv[0].type==LOCATION) /* cell to string */ /*{{{*/
{
buf=(char*)0;
size=0;
do
{
if (buf!=(char*)0) free(buf);
size+=16;
buf=malloc(size);
printvalue(buf,size,0,0,getscientific(upd_sheet,argv[0].u.location[0],argv[0].u.location[1],argv[0].u.location[2]),getprecision(upd_sheet,argv[0].u.location[0],argv[0].u.location[1],argv[0].u.location[2]),upd_sheet,argv[0].u.location[0],argv[0].u.location[1],argv[0].u.location[2]);
} while (strlen(buf)==size-1);
result.type=STRING;
result.u.string=buf;
if (LOC_WITHIN(upd_sheet, argv[0].u.location))
{
cell = CELL_AT(upd_sheet, argv[0].u.location);
printvalue(staticbuf, sizeof(staticbuf), 0, 0, getscientific(cell),
getprecision(cell), upd_sheet, argv[0].u.location);
result.u.string = malloc(strlen(staticbuf) + 1);
strcpy(result.u.string, staticbuf);
}
else
{
result.u.string = malloc(1);
result.u.string[0] = '\0';
}
}
/*}}}*/
else if (argc==1 && argv[0].type==FLOAT) /* float to string */ /*{{{*/
@ -648,7 +675,7 @@ static Token sum_func(int argc, const Token argv[])
if (argc==2 && argv[0].type==LOCATION && argv[1].type==LOCATION) /* result is sum */ /*{{{*/
{
/* variables */ /*{{{*/
int x,y,z;
Location w;
int x1,y1,z1;
int x2,y2,z2;
Token tmp;
@ -658,13 +685,13 @@ static Token sum_func(int argc, const Token argv[])
y1=argv[0].u.location[1]; y2=argv[1].u.location[1]; posorder(&y1,&y2);
z1=argv[0].u.location[2]; z2=argv[1].u.location[2]; posorder(&z1,&z2);
result.type=EMPTY;
for (x=x1; x<=x2; ++x)
for (y=y1; y<=y2; ++y)
for (z=z1; z<=z2; ++z)
for (w[X]=x1; w[X]<=x2; ++(w[X]))
for (w[Y]=y1; w[Y]<=y2; ++(w[Y]))
for (w[Z]=z1; w[Z]<=z2; ++(w[Z]))
{
Token t;
tmp=tadd(result,t=getvalue(upd_sheet,x,y,z));
tmp = tadd(result, t=getvalue(upd_sheet,w));
tfree(&t);
tfree(&result);
result=tmp;
@ -692,7 +719,7 @@ static Token n_func(int argc, const Token argv[])
/* result is number of elements */ /*{{{*/
{
/* variables */ /*{{{*/
int x,y,z;
Location w;
int x1,y1,z1;
int x2,y2,z2;
Token tmp;
@ -703,16 +730,16 @@ static Token n_func(int argc, const Token argv[])
y1=argv[0].u.location[1]; y2=argv[1].u.location[1]; posorder(&y1,&y2);
z1=argv[0].u.location[2]; z2=argv[1].u.location[2]; posorder(&z1,&z2);
n=0;
for (x=x1; x<=x2; ++x)
for (y=y1; y<=y2; ++y)
for (z=z1; z<=z2; ++z)
for (w[X]=x1; w[X]<=x2; ++(w[X]))
for (w[Y]=y1; w[Y]<=y2; ++(w[Y]))
for (w[Z]=z1; w[Z]<=z2; ++(w[Z]))
{
tmp=getvalue(upd_sheet,x,y,z);
if (tmp.type!=EMPTY) ++n;
tmp = getvalue(upd_sheet, w);
if (tmp.type != EMPTY) ++n;
tfree(&tmp);
}
result.type=INT;
result.u.integer=n;
result.type = INT;
result.u.integer = n;
}
/*}}}*/
else
@ -725,6 +752,7 @@ static Token n_func(int argc, const Token argv[])
return result;
}
/*}}}*/
/* int */ /*{{{*/
static Token int_func(int argc, const Token argv[])
{
@ -888,14 +916,14 @@ static Token minmax_func(int argc, const Token argv[], int min)
{
/* variables */ /*{{{*/
Token result;
int resultx,resulty,resultz;
Location minloc;
/*}}}*/
if (argc==2 && argv[0].type==LOCATION && argv[1].type==LOCATION)
/* result is min/max */ /*{{{*/
{
/* variables */ /*{{{*/
int x,y,z;
Location w;
int x1,y1,z1;
int x2,y2,z2;
Token tmp;
@ -904,28 +932,27 @@ static Token minmax_func(int argc, const Token argv[], int min)
x1=argv[0].u.location[0]; x2=argv[1].u.location[0]; posorder(&x1,&x2);
y1=argv[0].u.location[1]; y2=argv[1].u.location[1]; posorder(&y1,&y2);
z1=argv[0].u.location[2]; z2=argv[1].u.location[2]; posorder(&z1,&z2);
result=getvalue(upd_sheet,x1,y1,z1);
resultx=x1;
resulty=y1;
resultz=z1;
for (x=x1; x<=x2; ++x)
for (y=y1; y<=y2; ++y)
for (z=z1; z<=z2; ++z)
minloc[X] = x1; minloc[Y] = y1; minloc[Z] = z1;
result = getvalue(upd_sheet, minloc);
for (w[X]=x1; w[X]<=x2; ++(w[X]))
for (w[Y]=y1; w[Y]<=y2; ++(w[Y]))
for (w[Z]=z1; w[Z]<=z2; ++(w[Z]))
{
Token t;
tmp=(min ? tle(result,t=getvalue(upd_sheet,x,y,z)) : tge(result,t=getvalue(upd_sheet,x,y,z)));
t = getvalue(upd_sheet, w);
tmp = (min ? tle(result,t) : tge(result, t));
if (tmp.type==INT)
/* successful comparison */ /*{{{*/
{
tfree(&tmp);
if (tmp.u.integer==0)
if (tmp.u.integer == 0)
{
tfree(&result);
result=t;
resultx=x;
resulty=y;
resultz=z;
LOCATION_GETS(minloc, w);
}
else tfree(&t);
}
@ -941,9 +968,7 @@ static Token minmax_func(int argc, const Token argv[], int min)
}
tfree(&result);
result.type=LOCATION;
result.u.location[0]=resultx;
result.u.location[1]=resulty;
result.u.location[2]=resultz;
LOCATION_GETS(result.u.location, minloc);
return result;
}
/*}}}*/
@ -1108,7 +1133,7 @@ static Token clock_func(int argc, const Token argv[])
if (argc==2 && argv[0].type==INT && argv[1].type==LOCATION) /* clock(condition,location) */ /*{{{*/
{
if (argv[0].u.integer) clk(upd_sheet,argv[1].u.location[0],argv[1].u.location[1],argv[1].u.location[2]);
if (argv[0].u.integer) clk(upd_sheet, argv[1].u.location);
result.type=EMPTY;
}
/*}}}*/
@ -1117,7 +1142,7 @@ static Token clock_func(int argc, const Token argv[])
if (argv[0].u.integer)
{
/* variables */ /*{{{*/
int x,y,z;
Location w;
int x1,y1,z1;
int x2,y2,z2;
/*}}}*/
@ -1125,9 +1150,11 @@ static Token clock_func(int argc, const Token argv[])
x1=argv[1].u.location[0]; x2=argv[2].u.location[0]; posorder(&x1,&x2);
y1=argv[1].u.location[1]; y2=argv[2].u.location[1]; posorder(&y1,&y2);
z1=argv[1].u.location[2]; z2=argv[2].u.location[2]; posorder(&z1,&z2);
for (x=x1; x<=x2; ++x)
for (y=y1; y<=y2; ++y)
for (z=z1; z<=z2; ++z) clk(upd_sheet,x,y,z);
for (w[X]=x1; w[X]<=x2; ++(w[X]))
for (w[Y]=y1; w[Y]<=y2; ++(w[Y]))
for (w[Z]=z1; w[Z]<=z2; ++(w[Z]))
clk(upd_sheet, w);
}
result.type=EMPTY;
}

View File

@ -24,28 +24,34 @@
/*}}}*/
/* savehtml -- save as HTML table */ /*{{{*/
const char *savehtml(Sheet *sheet, const char *name, int body, int x1, int y1, int z1, int x2, int y2, int z2, unsigned int *count)
const char *savehtml(Sheet *sheet, const char *name, int body,
const Location beg, const Location end,
unsigned int *count)
{
/* variables */ /*{{{*/
FILE *fp=(FILE*)0; /* cause runtime error */
int x,y,z;
Location w;
char buf[1024];
char num[20];
char fullname[PATH_MAX];
Cell *cell;
/*}}}*/
/* asserts */ /*{{{*/
assert(sheet!=(Sheet*)0);
assert(name!=(const char*)0);
assert(sheet != (Sheet*)0);
assert(name != (const char*)0);
/*}}}*/
*count=0;
for (z=z1; z<=z2; ++z) for (y=y1; y<=y2; ++y) if (shadowed(sheet,x1,y,z)) return _("Shadowed cells in first column");
w[X] = beg[X];
for (w[Z]=beg[Z]; w[Z]<=end[Z]; ++(w[Z]))
for (w[Y]=beg[Y]; w[Y]<=end[Y]; ++(w[Y]))
if (shadowed(CELL_AT(sheet,w))) return _("Shadowed cells in first column");
if (!body && (fp=fopen(name,"w"))==(FILE*)0) return strerror(errno);
for (z=z1; z<=z2; ++z)
for (w[Z]=beg[Z]; w[Z]<=end[Z]; ++(w[Z]))
{
if (body) /* open new file */ /*{{{*/
{
sprintf(num,".%d",z);
sprintf(num, ".%d", w[Z]);
fullname[sizeof(fullname)-strlen(num)-1]='\0';
(void)strncpy(fullname,name,sizeof(fullname)-strlen(num)-1);
@ -60,27 +66,29 @@ const char *savehtml(Sheet *sheet, const char *name, int body, int x1, int y1, i
/*}}}*/
if (fputs_close("<table>\n",fp)==EOF) return strerror(errno);
for (y=y1; y<=y2; ++y) /* print contents */ /*{{{*/
for (w[Y]=beg[Y]; w[Y]<=end[Y]; ++(w[Y])) /* print contents */ /*{{{*/
{
if (fputs_close("<tr>",fp)==EOF) return strerror(errno);
for (x=x1; x<=x2; )
for (w[X]=beg[X]; w[X]<=end[X]; )
{
int multicols;
char *bufp;
for (multicols=x+1; multicols<sheet->dimx && shadowed(sheet,multicols,y,z); ++multicols);
multicols=multicols-x;
for (multicols=w[X]+1; multicols<sheet->dimx && SHADOWEDC(sheet,multicols,w[Y],w[Z]); ++multicols);
multicols = multicols - w[X];
if (multicols>1) fprintf(fp,"<td colspan=%d",multicols);
else fprintf(fp,"<td");
switch (getadjust(sheet,x,y,z))
cell = CELL_AT(sheet, w);
switch (getadjust(cell))
{
case LEFT: if (fputs_close(" align=left>",fp)==EOF) return strerror(errno); break;
case RIGHT: if (fputs_close(" align=right>",fp)==EOF) return strerror(errno); break;
case CENTER: if (fputs_close(" align=center>",fp)==EOF) return strerror(errno); break;
default: assert(0);
}
printvalue(buf,sizeof(buf),0,0,getscientific(sheet,x,y,z),getprecision(sheet,x,y,z),sheet,x,y,z);
if (transparent(sheet,x,y,z))
printvalue(buf, sizeof(buf), 0, 0, getscientific(cell),
getprecision(cell), sheet, w);
if (transparent(cell))
{
if (fputs_close(buf,fp)==EOF) return strerror(errno);
}
@ -93,7 +101,7 @@ const char *savehtml(Sheet *sheet, const char *name, int body, int x1, int y1, i
default: if (fputc_close(*bufp,fp)==EOF) return strerror(errno);
}
if (fputs_close("</td>",fp)==EOF) return strerror(errno);
x+=multicols;
w[X] += multicols;
++*count;
}
if (fputs_close("</tr>\n",fp)==EOF) return strerror(errno);

View File

@ -3,6 +3,8 @@
#include "sheet.h"
const char *savehtml(Sheet *sheet, const char *name, int body, int x1, int y1, int z1, int x2, int y2, int z2, unsigned int *count);
const char *savehtml(Sheet *sheet, const char *name, int body,
const Location beg, const Location end,
unsigned int *count);
#endif

51
latex.c
View File

@ -24,29 +24,36 @@
/*}}}*/
/* savelatex -- save as LaTeX table */ /*{{{*/
const char *savelatex(Sheet *sheet, const char *name, int body, int x1, int y1, int z1, int x2, int y2, int z2, unsigned int *count)
const char *savelatex(Sheet *sheet, const char *name, int body,
const Location beg, const Location end,
unsigned int *count)
{
/* variables */ /*{{{*/
FILE *fp=(FILE*)0; /* cause runtime error */
int x,y,z;
Location w;
char buf[1024];
char num[20];
char fullname[PATH_MAX];
Cell *cell;
/*}}}*/
/* asserts */ /*{{{*/
assert(sheet != (Sheet*)0);
assert(name != (const char*)0);
/*}}}*/
/* asserts */ /*{{{*/
assert(sheet!=(Sheet*)0);
assert(name!=(const char*)0);
/*}}}*/
*count=0;
for (z=z1; z<=z2; ++z) for (y=y1; y<=y2; ++y) if (shadowed(sheet,x1,y,z)) return _("Shadowed cells in first column");
w[X] = beg[X];
for (w[Z]=beg[Z]; w[Z]<=end[Z]; ++(w[Z]))
for (w[Y]=beg[Y]; w[Y]<=end[Y]; ++(w[Y]))
if (shadowed(CELL_AT(sheet,w))) return _("Shadowed cells in first column");
if (!body && (fp=fopen(name,"w"))==(FILE*)0) return strerror(errno);
for (z=z1; z<=z2; ++z)
for (w[Z]=beg[Z]; w[Z]<=end[Z]; ++(w[Z]))
{
if (body)
/* open new file */ /*{{{*/
{
sprintf(num,".%d",z);
sprintf(num, ".%d", w[Z]);
fullname[sizeof(fullname)-strlen(num)-1]='\0';
(void)strncpy(fullname,name,sizeof(fullname)-strlen(num)-1);
@ -58,7 +65,7 @@ const char *savelatex(Sheet *sheet, const char *name, int body, int x1, int y1,
/*}}}*/
else
/* print header */ /*{{{*/
if (z==z1)
if (w[Z] == beg[Z])
{
if (fputs_close("\\documentclass{article}\n\\usepackage{longtable}\n\\begin{document}\n\\setlongtables\n\\vfill\n",fp)==EOF) return strerror(errno);
}
@ -70,31 +77,33 @@ const char *savelatex(Sheet *sheet, const char *name, int body, int x1, int y1,
/* print bogus format */ /*{{{*/
fprintf(fp,"\\begin{longtable}{");
for (x=x1; x<=x2; ++x) if (fputc_close('l',fp)==EOF) return strerror(errno);
for (w[X]=beg[X]; w[X]<=end[X]; ++(w[X])) if (fputc_close('l',fp)==EOF) return strerror(errno);
fprintf(fp,"}\n");
/*}}}*/
for (y=y1; y<=y2; ++y)
for (w[Y]=beg[Y]; w[Y]<=end[Y]; ++(w[Y]))
/* print contents */ /*{{{*/
{
for (x=x1; x<=x2; )
for (w[X]=beg[X]; w[X]<=end[X]; )
{
int multicols;
char *bufp;
if (x>x1 && fputc_close('&',fp)==EOF) return strerror(errno);
for (multicols=x+1; multicols<sheet->dimx && shadowed(sheet,multicols,y,z); ++multicols);
multicols=multicols-x;
if (w[X]>beg[X] && fputc_close('&',fp)==EOF) return strerror(errno);
for (multicols = w[X]+1; multicols<sheet->dimx && SHADOWEDC(sheet,multicols,w[Y],w[Z]); ++multicols);
multicols = multicols - w[X];
fprintf(fp,"\\multicolumn{%d}{",multicols);
switch (getadjust(sheet,x,y,z))
cell = CELL_AT(sheet, w);
switch (getadjust(cell))
{
case LEFT: if (fputc_close('l',fp)==EOF) return strerror(errno); break;
case RIGHT: if (fputc_close('r',fp)==EOF) return strerror(errno); break;
case CENTER: if (fputc_close('c',fp)==EOF) return strerror(errno); break;
default: assert(0);
}
printvalue(buf,sizeof(buf),0,0,getscientific(sheet,x,y,z),getprecision(sheet,x,y,z),sheet,x,y,z);
printvalue(buf, sizeof(buf), 0, 0, getscientific(cell),
getprecision(cell), sheet, w);
if (fputs_close("}{",fp)==EOF) return strerror(errno);
if (transparent(sheet,x,y,z))
if (transparent(cell))
{
if (fputs_close(buf,fp)==EOF) return strerror(errno);
}
@ -113,10 +122,10 @@ const char *savelatex(Sheet *sheet, const char *name, int body, int x1, int y1,
default: if (fputc_close(*bufp,fp)==EOF) return strerror(errno);
}
if (fputc_close('}',fp)==EOF) return strerror(errno);
x+=multicols;
w[X] += multicols;
++*count;
}
if (fputs_close(y<y2 ? "\\\\\n" : "\n\\end{longtable}\n",fp)==EOF) return strerror(errno);
if (fputs_close(w[Y]<end[Y] ? "\\\\\n" : "\n\\end{longtable}\n",fp)==EOF) return strerror(errno);
}
/*}}}*/
if (body)

View File

@ -3,6 +3,8 @@
#include "sheet.h"
const char *savelatex(Sheet *sheet, const char *name, int body, int x1, int y1, int z1, int x2, int y2, int z2, unsigned int *count);
const char *savelatex(Sheet *sheet, const char *name, int body,
const Location beg, const Location end,
unsigned int *count);
#endif

594
main.c

File diff suppressed because it is too large Load Diff

5
main.h
View File

@ -86,9 +86,10 @@ typedef enum {
extern int do_sheetcmd(Sheet *cursheet, Key c, int moveonly);
extern int doanyway(Sheet *sheet, const char *msg);
extern void moveto(Sheet *sheet, int x, int y, int z);
extern void movetoloc(Sheet *sheet, const Location dest);
extern void relmoveto(Sheet *sheet, int x, int y, int z);
extern void do_mark(Sheet *cursheet, int force);
extern void do_mark(Sheet *cursheet, MarkState ms);
#ifdef __cplusplus
}
#endif

37
sc.c
View File

@ -33,6 +33,7 @@ static int s2t_term(Sheet *sheet);
static int s2t_loc(Sheet *sheet, const char **s, char **t)
{
int x,y;
Location tmp;
char label[10],*l;
l=label;
@ -63,7 +64,8 @@ static int s2t_loc(Sheet *sheet, const char **s, char **t)
*(*t)++=*(*s)++;
}
*l='\0';
if (*getlabel(sheet,x,y,0)=='\0') setlabel(sheet,x,y,0,label,0);
tmp[X] = x; tmp[Y] = y; tmp[Z] = 0;
if (*getlabel(CELL_AT(sheet, tmp))=='\0') setlabel(sheet, tmp, label, 0);
return 1;
}
/*}}}*/
@ -207,6 +209,8 @@ const char *loadsc(Sheet *sheet, const char *name)
int line;
size_t width;
const char *err;
Cell *cell;
Location tmp;
int x,y;
/*}}}*/
@ -229,10 +233,12 @@ 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);
CELL_AT(sheet,col,0,0)->adjust=RIGHT;
CELL_AT(sheet,col,0,0)->precision=precision;
setwidth(sheet,col,0,colwidth);
OLOCATION(tmp);
tmp[X] = col;
cell = initcell(sheet, tmp);
cell->adjust = RIGHT;
cell->precision = precision;
setwidth(sheet, col, 0, colwidth);
}
/*}}}*/
else if (strncmp(buf,"leftstring ",11)==0 || strncmp(buf,"rightstring ",12)==0) /* rightstring/leftstring cell = "string" */ /*{{{*/
@ -253,9 +259,10 @@ const char *loadsc(Sheet *sheet, const char *name)
err=errbuf;
goto eek;
}
initcell(sheet,x,y,0);
CELL_AT(sheet,x,y,0)->adjust=strncmp(buf,"leftstring ",11) ? RIGHT : LEFT;
CELL_AT(sheet,x,y,0)->contents=contents;
tmp[X] = x; tmp[Y] = y; tmp[Z] = 0;
cell = initcell(sheet, tmp);
cell->adjust = strncmp(buf,"leftstring ",11) ? RIGHT : LEFT;
cell->contents[BASE] = contents;
}
/*}}}*/
else if (strncmp(buf,"let ",4)==0) /* let cell = expression */ /*{{{*/
@ -269,7 +276,8 @@ const char *loadsc(Sheet *sheet, const char *name)
s=buf+4;
x=*s++-'A'; if (*s>='A' && *s<='Z') x=x*26+(*s++-'A');
y=*s++-'0'; while (*s>='0' && *s<='9') y=10*y+(*s++-'0');
if (getcont(sheet,x,y,0,0)==(Token**)0)
tmp[X] = x; tmp[Y] = y; tmp[Z] = 0;
if (getcont(CELL_ATC(sheet,x,y,0),BASE)==(Token**)0)
{
s+=3;
s2t_s=s; s2t_t=newbuf;
@ -292,9 +300,10 @@ const char *loadsc(Sheet *sheet, const char *name)
err=errbuf;
goto eek;
}
initcell(sheet,x,y,0);
CELL_AT(sheet,x,y,0)->adjust=RIGHT;
CELL_AT(sheet,x,y,0)->contents=contents;
tmp[X] = x; tmp[Y] = y; tmp[Z] = 0;
cell = initcell(sheet, tmp);
cell->adjust = RIGHT;
cell->contents[BASE] = contents;
}
}
/*}}}*/
@ -306,8 +315,8 @@ 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 (CELL_AT(sheet,x,y,0)) CELL_AT(sheet,x,y,0)->precision=prec;
prec=getprecision(CELL_ATC(sheet,x,0,0))==def_precision ? 2 : getprecision(CELL_ATC(sheet,x,0,0));
for (y=1; y<sheet->dimy; ++y) if (CELL_ATC(sheet,x,y,0)) CELL_ATC(sheet,x,y,0)->precision=prec;
}
/*}}}*/
eek:

View File

@ -46,6 +46,18 @@ int identcode(const char *s, size_t len)
}
/*}}}*/
/* loc_in_box -- returns true if test is in the box determined by b and c */
bool loc_in_box(const Location test,
const Location b, const Location c)
{
for (Dimensions dim = X; dim < HYPER; ++dim)
{
if (test[dim] < b[dim] && test[dim] < c[dim]) return false;
if (test[dim] > b[dim] && test[dim] > c[dim]) return false;
}
return true;
}
/* charstring -- match quoted string and return token */ /*{{{*/
static Token *charstring(const char **s)
{

View File

@ -2,6 +2,7 @@
#define SCANNER_H
#include <sys/types.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
@ -18,6 +19,22 @@ extern const char *Type_Name[];
typedef enum { PLUS, MINUS, MUL, DIV, OP, CP, COMMA, LT, LE, GE, GT, ISEQUAL, ABOUTEQ, NE, POW, MOD } Operator;
typedef int Location[3]; /* NOTE: Locations are passed by REFERENCE not value */
/* I.e., to accapt a Location argument, declare the parameter to be of type
const Location*
*/
typedef enum { X=0, Y=1, Z=2, HYPER} Dimensions;
#define OLOCATION(loc) ((void)memset(loc, 0, sizeof(Location)))
#define IN_OCTANT(loc) (loc[X]>=0 && loc[Y]>=0 && loc[Z]>=0)
#define LOCATION_GETS(la,lb) ((void)memcpy(la, lb, sizeof(Location)))
#define SAME_LOC(la,lb) (memcmp(la,lb,sizeof(Location))==0)
#define LOCATION_SUB(la,lb) (la)[X]-=(lb)[X]; (la)[Y]-=(lb)[Y]; (la)[Z]-=(lb)[Z];
bool loc_in_box(const Location test,
const Location b, const Location c);
typedef struct
{
Type type;
@ -29,7 +46,7 @@ typedef struct
Operator op;
char *lident;
int fident;
int location[3];
Location location;
char *err;
} u;
} Token;

1266
sheet.c

File diff suppressed because it is too large Load Diff

129
sheet.h
View File

@ -7,14 +7,6 @@
extern "C" {
#endif
#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;
typedef enum { IN_X, IN_Y, IN_Z } Direction;
@ -32,10 +24,11 @@ typedef struct
int sortkey; /* OR-ed value of the above constants */
} Sortkey;
typedef enum { BASE=0, ITERATIVE=1, CONTINGENT=2 } ContentVariety;
typedef struct
{
Token **contents;
Token **ccontents;
Token **contents[CONTINGENT];
char *label;
Token value;
Token resvalue;
@ -54,20 +47,24 @@ typedef struct
unsigned int underline:1;
} Cell;
#define NULLCELL ((Cell*)0)
struct Label
{
const char *label;
int x,y,z;
Location location;
struct Label *next;
};
typedef enum { MARK_CYCLE = 0, GET_MARK_CUR = 1, GET_MARK_ALL = 2,
MARKING = 3, MARKED = 4, UNMARKED = 5 } MarkState;
typedef struct
{
struct Label *labelcache[LABEL_CACHE];
int curx, cury, curz;
int mark1x, mark1y, mark1z;
int mark2x, mark2y, mark2z;
int marking;
Location cur;
Location mark1, mark2;
MarkState marking;
int offx, offy;
Cell **sheet;
int *column;
@ -81,64 +78,84 @@ typedef struct
void *display;
} Sheet;
#define LOC_WITHINC(s,x,y,z) (x<s->dimx && y<s->dimy && z<s->dimz)
#define LOC_WITHIN(s,l) (LOC_WITHINC(s,l[X],l[Y],l[Z]))
#define CELL_ATC(s,x,y,z) (*((s)->sheet + (z)*(s)->dimy*(s)->dimx + (y)*(s)->dimx +(x)))
#define CELL_AT(s,l) (CELL_ATC(s,l[X],l[Y],l[Z]))
#define CELL_IS_NULLC(s,x,y,z) (CELL_ATC(s,x,y,z) == NULLCELL)
#define CELL_IS_NULL(s,l) (CELL_AT(s,l) == NULLCELL)
#define CELL_IS_GOODC(s,x,y,z) (LOC_WITHINC(s,x,y,z) && !CELL_IS_NULLC(s,x,y,z))
#define CELL_IS_GOOD(s,l) (LOC_WITHIN(s,l) && !CELL_IS_NULL(s,l))
#define SHADOWEDC(s,x,y,z) (CELL_IS_GOODC(s,x,y,z) && CELL_ATC(s,x,y,z)->shadowed)
#define SHADOWED(s,l) (CELL_IS_GOOD(s,l) && CELL_AT(s,l)->shadowed)
#define ALL_COORDS_IN_SHEETC(s,x,y,z) x=0; x<(s)->dimx; ++x) for (y=0; y<(s)->dimy; ++y) for (z=0; z<(s)->dimz; ++z
#define ALL_LOCS_IN_SHEET(s,l) l[Z]=0; l[Z]<(s)->dimz; ++(l[Z])) for (l[Y]=0; l[Y]<(s)->dimy; ++(l[Y])) for (l[X]=0; l[X]<(s)->dimx; ++(l[X])
#define ALL_LOCS_IN_REGION(s,l) l[Z]=(s)->mark1[Z]; l[Z]<=(s)->mark2[Z]; ++(l[Z])) for (l[Y]=(s)->mark1[Y]; l[Y]<=(s)->mark2[Y]; ++(l[Y])) for (l[X]=(s)->mark1[X]; l[X]<=(s)->mark2[X]; ++(l[X])
#define ALL_CELLS_IN_SHEET(s,i,c) i=0,c=*((s)->sheet); i<(s)->dimx*(s)->dimy*(s)->dimz; ++i, c=*((s)->sheet+i)
extern Sheet *upd_sheet;
extern int upd_x;
extern int upd_y;
extern int upd_z;
extern Location upd_l;
extern int max_eval;
void initialize_sheet(Sheet *sheet);
void resize(Sheet *sheet, int x, int y, int z);
void initcell(Sheet *sheet, int x, int y, int z);
Cell *initcell(Sheet *sheet, const Location at);
Cell *safe_cell_at(Sheet *sheet, const Location at);
Cell *curcell(Sheet *sheet);
void cachelabels(Sheet *sheet);
void freesheet(Sheet *sheet, int all);
void forceupdate(Sheet *sheet);
MarkState getmarkstate(Sheet *sheet);
void dump_current_cell(Sheet *sheet);
void freecell(Sheet *sheet, int x, int y, int z);
void freecell(Sheet *sheet, const Location at);
int columnwidth(Sheet *sheet, int x, int z);
void setwidth(Sheet *sheet, int x, int z, int width);
int cellwidth(Sheet *sheet, int x, int y, int z);
void putcont(Sheet *sheet, int x, int y, int z, Token **t, int c);
Token **getcont(Sheet *sheet, int x, int y, int z, int c);
Token getvalue(Sheet *sheet, int x, int y, int z);
int cellwidth(Sheet *sheet, const Location at);
void putcont(Sheet *sheet, const Location at, Token **t, ContentVariety v);
Token **getcont(const Cell *cell, ContentVariety v);
Token getvalue(Sheet *sheet, const Location at);
void update(Sheet *sheet);
char *geterror(Sheet *sheet, int x, int y, int z);
void printvalue(char *s, size_t size, size_t chars, int quote, int scientific, int precision, Sheet *sheet, int x, int y, int z);
Adjust getadjust(Sheet *sheet, int x, int y, int z);
void setadjust(Sheet *sheet, int x, int y, int z, Adjust adjust);
void shadow(Sheet *sheet, int x, int y, int z, int yep);
int shadowed(Sheet *sheet, int x, int y, int z);
void bold(Sheet *sheet, int x, int y, int z, int yep);
int isbold(Sheet *sheet, int x, int y, int z);
void underline(Sheet *sheet, int x, int y, int z, int yep);
int underlined(Sheet *sheet, int x, int y, int z);
void lockcell(Sheet *sheet, int x, int y, int z, int yep);
int locked(Sheet *sheet, int x, int y, int z);
int transparent(Sheet *sheet, int x, int y, int z);
void maketrans(Sheet *sheet, int x, int y, int z, int yep);
void igncell(Sheet *sheet, int x, int y, int z, int yep);
int ignored(Sheet *sheet, int x, int y, int z);
void clk(Sheet *sheet, int x, int y, int z);
void setscientific(Sheet *sheet, int x, int y, int z, int yep);
int getscientific(Sheet *sheet, int x, int y, int z);
void setprecision(Sheet *sheet, int x, int y, int z, int precision);
int getprecision(Sheet *sheet, int x, int y, int z);
const char *getlabel(Sheet *sheet, int x, int y, int z);
void setlabel(Sheet *sheet, int x, int y, int z, const char *buf, int update);
char *geterror(Sheet *sheet, const Location at);
void printvalue(char *s, size_t size, size_t chars, int quote, int scientific, int precision, Sheet *sheet, const Location at);
Adjust getadjust(const Cell *cell);
void setadjust(Sheet *sheet, const Location at, Adjust adjust);
void shadow(Sheet *sheet, const Location at, int yep);
int shadowed(const Cell *cell);
void bold(Sheet *sheet, const Location at, int yep);
int isbold(const Cell *cell);
void underline(Sheet *sheet, const Location at, int yep);
int underlined(const Cell *cell);
void lockcell(Sheet *sheet, const Location at, int yep);
int locked(const Cell *cell);
int transparent(const Cell *cell);
void maketrans(Sheet *sheet, const Location at, int yep);
void igncell(Sheet *sheet, const Location at, int yep);
int ignored(const Cell *cell);
void clk(Sheet *sheet, const Location at);
void setscientific(Sheet *sheet, const Location at, int yep);
int getscientific(const Cell *cell);
void setprecision(Sheet *sheet, const Location at, int precision);
int getprecision(const Cell* cell);
const char *getlabel(const Cell* cell);
void setlabel(Sheet *sheet, const Location at, const char *buf, int update);
Token findlabel(Sheet *sheet, const char *label);
void relabel(Sheet *sheet, const char *oldlabel, const char *newlabel, int x, int y, int z);
void relabel(Sheet* sheet, const Location at,
const char *oldlabel, const char *newlabel);
const char *savexdr(Sheet *sheet, const char *name, unsigned int *count);
const char *savetbl(Sheet *sheet, const char *name, int body, int x1, int y1, int z1, int x2, int y2, int z2, unsigned int *count);
const char *savetext(Sheet *sheet, const char *name, int x1, int y1, int z1, int x2, int y2, int z2, unsigned int *count);
const char *savecsv(Sheet *sheet, const char *name, char sep, int x1, int y1, int z1, int x2, int y2, int z2, unsigned int *count);
const char *savetbl(Sheet *sheet, const char *name, int body, const Location beg, const Location end, unsigned int *count);
const char *savetext(Sheet *sheet, const char *name, const Location beg, const Location end, unsigned int *count);
const char *savecsv(Sheet *sheet, const char *name, char sep, const Location beg, const Location end, unsigned int *count);
const char *saveport(Sheet *sheet, const char *name, unsigned int *count);
const char *loadxdr(Sheet *sheet, const char *name);
const char *loadport(Sheet *sheet, const char *name);
const char *loadcsv(Sheet *sheet, const char *name);
void insertcube(Sheet *sheet, int x1, int y1, int z1, int x2, int y2, int z2, Direction ins);
void deletecube(Sheet *sheet, int x1, int y1, int z1, int x2, int y2, int z2, Direction ins);
void moveblock(Sheet *sheet, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3, int copy);
const char *sortblock(Sheet *sheet, int x1, int y1, int z1, int x2, int y2, int z2, Direction dir, Sortkey *sk, size_t sklen);
void mirrorblock(Sheet *sheet, int x1, int y1, int z1, int x2, int y2, int z2, Direction dir);
void insertcube(Sheet *sheet, const Location beg, const Location end, Direction ins);
void deletecube(Sheet *sheet, const Location beg, const Location end, Direction ins);
void moveblock(Sheet *sheet, const Location beg, const Location end, const Location dest, int copy);
const char *sortblock(Sheet *sheet, const Location beg, const Location end, Direction dir, Sortkey *sk, size_t sklen);
void mirrorblock(Sheet *sheet, const Location beg, const Location end, Direction dir);
#ifdef __cplusplus
}

46
wk1.c
View File

@ -692,6 +692,8 @@ const char *loadwk1(Sheet *sheet, const char *name)
char *body=(char*)0,*newbody;
size_t bodymaxlen=0;
size_t bodylen;
Location tmp;
Cell *cell;
int found_bof=0,found_eof=0;
/*}}}*/
@ -835,8 +837,9 @@ const char *loadwk1(Sheet *sheet, const char *name)
case 0xC:
{
if (bodylen!=5) { err=_("Invalid record body length"); goto ouch; }
initcell(sheet,it(body+1),it(body+3),0);
format((unsigned char)body[0],CELL_AT(sheet,it(body+1),it(body+3),0));
tmp[X] = it(body+1); tmp[Y] = it(body+3); tmp[Z] = 0;
cell = initcell(sheet, tmp);
format((unsigned char)body[0], cell);
break;
}
/*}}}*/
@ -846,14 +849,15 @@ const char *loadwk1(Sheet *sheet, const char *name)
Token **t;
assert(bodylen==7);
initcell(sheet,it(body+1),it(body+3),0);
tmp[X] = it(body+1); tmp[Y] = it(body+3); tmp[Z] = 0;
cell = initcell(sheet, tmp);
t=malloc(2*sizeof(Token*));
t[0]=malloc(sizeof(Token));
t[1]=(Token*)0;
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],CELL_AT(sheet,it(body+1),it(body+3),0));
putcont(sheet, tmp, t, BASE);
format((unsigned char)body[0], cell);
break;
}
/*}}}*/
@ -863,14 +867,15 @@ const char *loadwk1(Sheet *sheet, const char *name)
Token **t;
assert(bodylen==13);
initcell(sheet,it(body+1),it(body+3),0);
tmp[X] = it(body+1); tmp[Y] = it(body+3); tmp[Z] = 0;
cell = initcell(sheet, tmp);
t=malloc(2*sizeof(Token*));
t[0]=malloc(sizeof(Token));
t[1]=(Token*)0;
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],CELL_AT(sheet,it(body+1),it(body+3),0));
putcont(sheet, tmp, t, BASE);
format((unsigned char)body[0], cell);
break;
}
/*}}}*/
@ -880,14 +885,15 @@ const char *loadwk1(Sheet *sheet, const char *name)
Token **t;
assert(bodylen>=6 && bodylen<=245);
initcell(sheet,it(body+1),it(body+3),0);
tmp[X] = it(body+1); tmp[Y] = it(body+3); tmp[Z] = 0;
cell = initcell(sheet, tmp);
t=malloc(2*sizeof(Token*));
t[0]=malloc(sizeof(Token));
t[1]=(Token*)0;
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],CELL_AT(sheet,it(body+1),it(body+3),0));
putcont(sheet, tmp, t, BASE);
format((unsigned char)body[0], cell);
break;
}
/*}}}*/
@ -944,7 +950,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],CELL_AT(sheet,it(body+1),it(body+3),0));
format((unsigned char)body[0],CELL_ATC(sheet,it(body+1),it(body+3),0));
#if WK1DEBUG
fprintf(se,"\r\n");
#endif
@ -968,10 +974,11 @@ const char *loadwk1(Sheet *sheet, const char *name)
fprintf(se,"[<-- %d tokens]\r\n",tokens);
#endif
free(offset);
initcell(sheet,it(body+1),it(body+3),0);
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);
tmp[X] = it(body+1); tmp[Y] = it(body+3); tmp[Z] = 0;
cell = initcell(sheet, tmp);
cell->value.type=FLOAT;
cell->value.u.flt=dbl((unsigned char*)body+5);
putcont(sheet, tmp, t, BASE);
}
break;
}
@ -1085,14 +1092,15 @@ const char *loadwk1(Sheet *sheet, const char *name)
Token **t;
assert(bodylen>=6 && bodylen<=245);
initcell(sheet,it(body+1),it(body+3),0);
tmp[X] = it(body+1); tmp[Y] = it(body+3); tmp[Z] = 0;
cell = initcell(sheet, tmp);
t=malloc(2*sizeof(Token*));
t[0]=malloc(sizeof(Token));
t[1]=(Token*)0;
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],CELL_AT(sheet,it(body+1),it(body+3),0));
putcont(sheet, tmp, t, BASE);
format((unsigned char)body[0], cell);
break;
}
/*}}}*/

4
xdr.c
View File

@ -166,7 +166,9 @@ 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_tokenptrvec(xdrs, &(cell->contents[BASE]))
&& xdr_tokenptrvec(xdrs, &(cell->contents[ITERATIVE])) /* && xdr_token(xdrs, &(cell->value)) */ ))
return 0;
if (xdr_mystring(xdrs, &(cell->label))==0) return 0;
x=cell->adjust;
result=xdr_int(xdrs, &x);