From 255bd86bf54733ed1cdcf3915a95adf51b6cee79 Mon Sep 17 00:00:00 2001 From: Glen Whitney Date: Sat, 27 Jul 2019 00:14:26 -0400 Subject: [PATCH] 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! --- context.c | 47 +- context.h | 4 +- display.c | 153 ++++--- display.h | 2 +- eval.c | 4 +- fteapot.fl | 176 ++++---- func.c | 195 ++++---- htmlio.c | 38 +- htmlio.h | 4 +- latex.c | 51 ++- latex.h | 4 +- main.c | 594 ++++++++++++------------ main.h | 5 +- sc.c | 37 +- scanner.c | 12 + scanner.h | 19 +- sheet.c | 1266 +++++++++++++++++++++++++++------------------------- sheet.h | 129 +++--- wk1.c | 46 +- xdr.c | 4 +- 20 files changed, 1521 insertions(+), 1269 deletions(-) diff --git a/context.c b/context.c index 90f1c23..59561ee 100644 --- a/context.c +++ b/context.c @@ -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; multicolsdimx && 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; multicolsdimx && 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 #include #include +#include #include #include #include @@ -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->curyoffy) sheet->offy=sheet->cury; - if (sheet->curxoffx) 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; widthmaxx; ++width) mvwaddch(stdscr,0+sheet->oriy,sheet->orix+width,(chtype)(unsigned char)' '); - for (width=4,x=sheet->offx; widthmaxx; 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; widthmaxx; 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; ymaxy-1; ++y) for (width=4*header,x=sheet->offx; widthmaxx; width+=columnwidth(sheet,x,sheet->curz),++x) + for (y=header; ymaxy-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); fillmaxx*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)); diff --git a/display.h b/display.h index 96ff19b..e322987 100644 --- a/display.h +++ b/display.h @@ -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); diff --git a/eval.c b/eval.c index 8b89b98..6799330 100644 --- a/eval.c +++ b/eval.c @@ -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) { diff --git a/fteapot.fl b/fteapot.fl index a5867f9..9ac13ef 100644 --- a/fteapot.fl +++ b/fteapot.fl @@ -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);} {} } diff --git a/func.c b/func.c index 62a2b28..db1d801 100644 --- a/func.c +++ b/func.c @@ -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; } diff --git a/htmlio.c b/htmlio.c index 147e5b2..c8bee89 100644 --- a/htmlio.c +++ b/htmlio.c @@ -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("\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("",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; multicolsdimx && shadowed(sheet,multicols,y,z); ++multicols); - multicols=multicols-x; + for (multicols=w[X]+1; multicolsdimx && SHADOWEDC(sheet,multicols,w[Y],w[Z]); ++multicols); + multicols = multicols - w[X]; if (multicols>1) fprintf(fp,"",fp)==EOF) return strerror(errno); - x+=multicols; + w[X] += multicols; ++*count; } if (fputs_close("\n",fp)==EOF) return strerror(errno); diff --git a/htmlio.h b/htmlio.h index 248fd4f..bb64d57 100644 --- a/htmlio.h +++ b/htmlio.h @@ -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 diff --git a/latex.c b/latex.c index 0c2462d..e9ce2ed 100644 --- a/latex.c +++ b/latex.c @@ -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; multicolsdimx && 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; multicolsdimx && 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 #include #include +#include #include #include extern char *optarg; @@ -54,65 +55,34 @@ int debug_level=0; static int usexdr=1; /*}}}*/ -static void get_mark(Sheet *sheet, int *x1, int *x2, int *y1, int *y2, int *z1, int *z2, int everything) -{ - if (sheet->marking) { - posorder(&sheet->mark1x, &sheet->mark2x); - posorder(&sheet->mark1y, &sheet->mark2y); - posorder(&sheet->mark1z, &sheet->mark2z); - sheet->marking = 0; - } - if (x1) { - if (sheet->mark1x >= 0) { - *x1 = sheet->mark1x; - *x2 = sheet->mark2x; - *y1 = sheet->mark1y; - *y2 = sheet->mark2y; - *z1 = sheet->mark1z; - *z2 = sheet->mark2z; - } else if (everything) { - *x1 = 0; - *x2 = sheet->dimx-1; - *y1 = 0; - *y2 = sheet->dimy-1; - *z1 = 0; - *z2 = sheet->dimz-1; - } else { - *x1 = *x2 = sheet->curx; - *y1 = *y2 = sheet->cury; - *z1 = *z2 = sheet->curz; - } - } -} - void moveto(Sheet *sheet, int x, int y, int z) { int need_redraw = 0; - int xdir = x > sheet->curx?1:-1; + int xdir = x > sheet->cur[X]?1:-1; - if (x >= 0) sheet->curx = x; - if (y >= 0) sheet->cury = y; - if (z >= 0) need_redraw++, sheet->curz = z; - while (sheet->curx > 0 && shadowed(sheet, sheet->curx, sheet->cury, sheet->curz)) sheet->curx += xdir; + if (x >= 0) sheet->cur[X] = x; + if (y >= 0) sheet->cur[Y] = y; + if (z >= 0) need_redraw++, sheet->cur[Z] = z; + while (sheet->cur[X] > 0 && SHADOWED(sheet, sheet->cur)) sheet->cur[X] += xdir; - if (sheet->marking) { - sheet->mark2x = sheet->curx; - sheet->mark2y = sheet->cury; - sheet->mark2z = sheet->curz; - } + if (getmarkstate(sheet) == MARKING) LOCATION_GETS(sheet->mark2, sheet->cur); - if (sheet->curx <= sheet->offx && sheet->offx) need_redraw++, sheet->offx = (sheet->curx?sheet->curx-1:0); - if (sheet->cury <= sheet->offy && sheet->offy) need_redraw++, sheet->offy = (sheet->cury?sheet->cury-1:0); - if (sheet->curx >= sheet->offx+sheet->maxx) need_redraw++, sheet->offx = sheet->curx-sheet->maxx+2; - if (sheet->cury >= sheet->offy+sheet->maxy) need_redraw++, sheet->offy = sheet->cury-sheet->maxy+2; + if (sheet->cur[X] <= sheet->offx && sheet->offx) need_redraw++, sheet->offx = (sheet->cur[X]?sheet->cur[X]-1:0); + if (sheet->cur[Y] <= sheet->offy && sheet->offy) need_redraw++, sheet->offy = (sheet->cur[Y]?sheet->cur[Y]-1:0); + if (sheet->cur[X] >= sheet->offx+sheet->maxx) need_redraw++, sheet->offx = sheet->cur[X]-sheet->maxx+2; + if (sheet->cur[Y] >= sheet->offy+sheet->maxy) need_redraw++, sheet->offy = sheet->cur[Y]-sheet->maxy+2; if (need_redraw) redraw_sheet(sheet); - else if (x != sheet->curx || y != sheet->cury || z != sheet->curz) redraw_cell(sheet, sheet->curx, sheet->cury, sheet->curz); + else if (x != sheet->cur[X] || y != sheet->cur[Y] || z != sheet->cur[Z]) redraw_cell(sheet, sheet->cur); +} + +void movetoloc(Sheet *sheet, const Location dest) { + moveto(sheet, dest[X], dest[Y], dest[Z]); } void relmoveto(Sheet *sheet, int x, int y, int z) { - moveto(sheet, sheet->curx+x, sheet->cury+y, (z?sheet->curz+z:-1)); + moveto(sheet, sheet->cur[X]+x, sheet->cur[Y]+y, (z?sheet->cur[Z]+z:-1)); } /* line_numedit -- number line editor function */ /*{{{*/ @@ -185,45 +155,50 @@ int doanyway(Sheet *sheet, const char *msg) /*}}}*/ /* do_edit -- set or modify cell contents */ /*{{{*/ -static int do_edit(Sheet *cursheet, Key c, const char *expr, int clocked) +static int do_edit(Sheet *cursheet, Key c, const char *expr, ContentVariety cv) { /* variables */ /*{{{*/ char buf[1024]; - const char *s; + const char *s, *prompt; size_t x,offx; - int curx,cury,curz; + Location scur; Token **t; + Cell *cell; /*}}}*/ - if (locked(cursheet,cursheet->curx,cursheet->cury,cursheet->curz)) line_msg(_("Edit cell:"),_("Cell is locked")); + cell = curcell(cursheet); + if (locked(cell)) line_msg(_("Edit cell:"),_("Cell is locked")); else { - curx=cursheet->curx; - cury=cursheet->cury; - curz=cursheet->curz; + LOCATION_GETS(scur, cursheet->cur); if (expr) { s=expr; t=scan(&s); - if (*s!='\0' && t==(Token**)0) line_msg(clocked ? _("Clocked cell contents:") : _("Cell contents:"),"XXX invalid expression"); + prompt = _("Cell contents:"); + if (cv == ITERATIVE) prompt = _("Clocked cell contents"); + if (*s!='\0' && t==(Token**)0) line_msg(prompt, "XXX invalid expression"); } else { offx=0; if (c==K_NONE) { - print(buf,sizeof(buf),0,1,getscientific(cursheet,cursheet->curx,cursheet->cury,cursheet->curz),-1,getcont(cursheet,cursheet->curx,cursheet->cury,cursheet->curz,clocked)); + print(buf, sizeof(buf), 0, 1, getscientific(cell), -1, + getcont(cell, cv)); s=buf+strlen(buf); } else if (c==K_BACKSPACE) { - print(buf,sizeof(buf),0,1,getscientific(cursheet,cursheet->curx,cursheet->cury,cursheet->curz),-1,getcont(cursheet,cursheet->curx,cursheet->cury,cursheet->curz,clocked)); + print(buf, sizeof(buf), 0, 1, getscientific(cell), -1, + getcont(cell, cv)); if (strlen(buf)) *mbspos(buf+strlen(buf),-1)='\0'; s=buf+strlen(buf); } else if (c==K_DC) { - print(buf,sizeof(buf),0,1,getscientific(cursheet,cursheet->curx,cursheet->cury,cursheet->curz),-1,getcont(cursheet,cursheet->curx,cursheet->cury,cursheet->curz,clocked)); + print(buf, sizeof(buf), 0, 1, getscientific(cell), -1, + getcont(cell, cv)); memmove(buf,mbspos(buf,1),strlen(mbspos(buf,1))+1); s=buf; } @@ -246,8 +221,11 @@ static int do_edit(Sheet *cursheet, Key c, const char *expr, int clocked) int r; x=mbslen(buf)-mbslen(s); - if ((r=line_edit(cursheet,buf,sizeof(buf),clocked ? _("Clocked cell contents:") : _("Cell contents:"),&x,&offx))<0) return r; - s=buf; + prompt = _("Cell contents:"); + if (cv == ITERATIVE) prompt = _("Clocked cell contents:"); + if ((r = line_edit(cursheet, buf, sizeof(buf), prompt, &x, &offx)) < 0) + return r; + s = buf; if (buf[0] == '"' && buf[strlen(buf)-1] != '"' && strlen(buf)+1 < sizeof(buf)) { buf[strlen(buf)+1] = 0; buf[strlen(buf)] = '"'; @@ -256,13 +234,14 @@ static int do_edit(Sheet *cursheet, Key c, const char *expr, int clocked) } while (*s!='\0' && t==(Token**)0); } if (t!=(Token**)0 && *t==(Token*)0) { free(t); t=(Token**)0; } - moveto(cursheet,curx,cury,curz); - putcont(cursheet,cursheet->curx,cursheet->cury,cursheet->curz,t,clocked); + movetoloc(cursheet, scur); + putcont(cursheet, cursheet->cur, t, cv); forceupdate(cursheet); } return 0; } /*}}}*/ + /* do_label -- modify cell label */ /*{{{*/ static int do_label(Sheet *sheet) { @@ -270,117 +249,115 @@ static int do_label(Sheet *sheet) char buf[1024],oldlabel[1024]; size_t edx,offx,ok; Token t; - int x,y,z,x1,y1,z1,x2,y2,z2; + Location w; + int tried; int c; /*}}}*/ - assert(sheet!=(Sheet*)0); - if (sheet->mark1x==-1 && locked(sheet,sheet->curx,sheet->cury,sheet->curz)) line_msg(_("Cell label:"),_("Cell is locked")); + assert(sheet != (Sheet*)0); + do_mark(sheet, GET_MARK_ALL); + if (SAME_LOC(sheet->mark1,sheet->mark2) && + locked(CELL_AT(sheet, sheet->mark1))) + { + line_msg(_("Cell label:"),_("Cell is locked")); + } else { - get_mark(sheet, &x1, &x2, &y1, &y2, &z1, &z2, 0); ok=edx=offx=0; - (void)strcpy(buf,getlabel(sheet,sheet->curx,sheet->cury,sheet->curz)); - (void)strcpy(oldlabel,buf); + (void)strcpy(buf, getlabel(curcell(sheet))); + (void)strcpy(oldlabel, buf); + tried = 0; do { + if (tried) { + line_msg(_("Cell label:"), _("Label already in use")); + } if ((c=line_idedit(buf,sizeof(buf),_("Cell label:"),&edx,&offx))<0) return c; + tried = 1; if (buf[0]=='\0') ok=1; else { - ok=((t=findlabel(sheet,buf)).type==EEK || (t.type==LOCATION && t.u.location[0]==sheet->curx && t.u.location[1]==sheet->cury && t.u.location[2]==sheet->curz)); + ok=((t=findlabel(sheet,buf)).type==EEK || + (t.type == LOCATION && SAME_LOC(t.u.location, sheet->cur))); tfree(&t); } } while (!ok); - setlabel(sheet,sheet->curx,sheet->cury,sheet->curz,buf,1); - if (buf[0]!='\0') for (x=x1; x<=x2; ++x) for (y=y1; y<=y2; ++y) for (z=z1; z<=z2; ++z) relabel(sheet,oldlabel,buf,x,y,z); + setlabel(sheet, sheet->cur, buf,1); + if (buf[0]!='\0') + for (ALL_LOCS_IN_REGION(sheet,w)) + relabel(sheet, w, oldlabel, buf); } return -1; } /*}}}*/ + /* do_columnwidth -- set the column width */ /*{{{*/ static int do_columnwidth(Sheet *cursheet) { /* variables */ /*{{{*/ size_t edx,offx; int n; - int x,x1,x2,z,z1,z2; + int x, z; int c; /*}}}*/ offx=0; edx=0; - n=columnwidth(cursheet,cursheet->curx,cursheet->curz); - do if ((c=line_numedit(&n,_("Column width:"),&edx,&offx))<0) return c; while (n<=0); - if (cursheet->mark1x==-1) - /* range is the current cell */ /*{{{*/ - { - x1=x2=cursheet->curx; - z1=z2=cursheet->curz; - } + do_mark(cursheet, GET_MARK_CUR); + n = columnwidth(cursheet, cursheet->mark1[X], cursheet->mark1[Z]); + do { + if ((c=line_numedit(&n,_("Column width:"),&edx,&offx))<0) return c; + } while (n<=0); /*}}}*/ - else - /* range is the marked cube */ /*{{{*/ - { - x1=cursheet->mark1x; x2=cursheet->mark2x; - z1=cursheet->mark1z; z2=cursheet->mark2z; - } - /*}}}*/ - for (x=x1; x<=x2; ++x) for (z=z1; z<=z2; ++z) setwidth(cursheet,x,z,n); + for (x = cursheet->mark1[X]; x <= cursheet->mark2[X]; ++x) + for (z = cursheet->mark1[Z]; z <= cursheet->mark2[Z]; ++z) + setwidth(cursheet,x,z,n); return -1; } /*}}}*/ + /* do_attribute -- set cell attributes */ /*{{{*/ static void do_attribute(Sheet *cursheet, Key action) { /* variables */ /*{{{*/ - int x,y,z; - int x1,y1,z1; - int x2,y2,z2; + Location w; + Adjust adj; + bool onecell; + Cell *fcell; int c = 0; /*}}}*/ - get_mark(cursheet, &x1, &x2, &y1, &y2, &z1, &z2, 0); - - if (action != ADJUST_LOCK && cursheet->mark1x==-1 && action != ADJUST_LOCK && locked(cursheet,cursheet->curx,cursheet->cury,cursheet->curz)) + adj = LEFT; + do_mark(cursheet, GET_MARK_CUR); + onecell = SAME_LOC(cursheet->mark1, cursheet->mark2); + fcell = CELL_AT(cursheet, cursheet->mark1); + if (action != ADJUST_LOCK && onecell && locked(fcell)) { line_msg(_("Cell attribute:"),_("Cell is locked")); return; } switch ((int)action) { - /* 0 -- adjust left */ /*{{{*/ + case ADJUST_CENTER: ++adj; /* drop through */ + case ADJUST_RIGHT: ++adj; case ADJUST_LEFT: { - if (cursheet->mark1x != -1 && line_ok(_("Make block left-adjusted:"), 0) <= 0) break; - for (x=x1; x<=x2; ++x) for (y=y1; y<=y2; ++y) for (z=z1; z<=z2; ++z) setadjust(cursheet,x,y,z,LEFT); + if (!onecell && line_ok(_("Change adjustment of block:"), 0) <= 0) break; + for (ALL_LOCS_IN_REGION(cursheet,w)) + setadjust(cursheet, w, adj); break; } - /*}}}*/ - /* 1 -- adjust right */ /*{{{*/ - case ADJUST_RIGHT: - { - if (cursheet->mark1x != -1 && line_ok(_("Make block right-adjusted:"), 0) <= 0) break; - for (x=x1; x<=x2; ++x) for (y=y1; y<=y2; ++y) for (z=z1; z<=z2; ++z) setadjust(cursheet,x,y,z,RIGHT); - break; - } - /*}}}*/ - /* 2 -- adjust centered */ /*{{{*/ - case ADJUST_CENTER: - { - if (cursheet->mark1x != -1 && line_ok(_("Make block centered:"), 0) <= 0) break; - for (x=x1; x<=x2; ++x) for (y=y1; y<=y2; ++y) for (z=z1; z<=z2; ++z) setadjust(cursheet,x,y,z,CENTER); - break; - } - /*}}}*/ /* 3 -- set scientific notation flag */ /*{{{*/ case ADJUST_SCIENTIFIC: { int n; - if (cursheet->mark1x==-1) n = !getscientific(cursheet,x1,y1,z1); - else n = line_ok(_("Make block notation scientific:"), getscientific(cursheet,x1,y1,z1)); - if (n >= 0) for (x=x1; x<=x2; ++x) for (y=y1; y<=y2; ++y) for (z=z1; z<=z2; ++z) setscientific(cursheet,x,y,z,n); + if (onecell) n = !getscientific(fcell); + else n = line_ok(_("Make block notation scientific:"), + getscientific(fcell)); + if (n >= 0) + for (ALL_LOCS_IN_REGION(cursheet,w)) + setscientific(cursheet, w, n); break; } /*}}}*/ @@ -392,9 +369,9 @@ static void do_attribute(Sheet *cursheet, Key action) offx=0; ex=0; - n=getprecision(cursheet,x1,y1,z1); - do if (line_numedit(&n,cursheet->mark1x==-1 ? _("Precision for cell:") : _("Precision for block:"),&ex,&offx)==-1) return; while (n!=-1 && (n==0 || n>20)); - for (x=x1; x<=x2; ++x) for (y=y1; y<=y2; ++y) for (z=z1; z<=z2; ++z) setprecision(cursheet,x,y,z,n); + n = getprecision(fcell); + do if (line_numedit(&n, onecell ? _("Precision for cell:") : _("Precision for block:"),&ex,&offx)==-1) return; while (n!=-1 && (n==0 || n>20)); + for (ALL_LOCS_IN_REGION(cursheet,w)) setprecision(cursheet, w, n); break; } /*}}}*/ @@ -403,20 +380,25 @@ static void do_attribute(Sheet *cursheet, Key action) { int n; - if (cursheet->mark1x==-1) n = !shadowed(cursheet,x1,y1,z1); - else n = line_ok(_("Shadow block:"), shadowed(cursheet,x1,y1,z1)); - if (x1 == 0 && n == 1) { + if (onecell) n = !SHADOWED(cursheet, cursheet->mark1); + else n = line_ok(_("Shadow block:"), SHADOWED(cursheet, cursheet->mark1)); + if (cursheet->mark1[X] == 0 && n == 1) { line_msg(_("Shadow cell:"),_("You can not shadow cells in column 0")); break; } if (n >= 0) { - for (x=x1; x<=x2; ++x) for (y=y1; y<=y2; ++y) for (z=z1; z<=z2; ++z) + for (ALL_LOCS_IN_REGION(cursheet,w)) { - int rx; + Location r; - if (n==0) for (rx=x+1; shadowed(cursheet,rx,y,z); ++rx) shadow(cursheet,rx,y,z,0); - else if (x>0) shadow(cursheet,x,y,z,1); + if (n==0) + { + LOCATION_GETS(r, w); + for (++(r[X]); SHADOWED(cursheet, r); ++(r[X])) + shadow(cursheet, r, 0); + } + else if (w[X]>0) shadow(cursheet, w, 1); } } break; @@ -427,9 +409,11 @@ static void do_attribute(Sheet *cursheet, Key action) { int n; - if (cursheet->mark1x==-1) n = !transparent(cursheet,x1,y1,z1); - else n = line_ok(_("Make block transparent:"), transparent(cursheet,x1,y1,z1)); - if (n >= 0) for (x=x1; x<=x2; ++x) for (y=y1; y<=y2; ++y) for (z=z1; z<=z2; ++z) maketrans(cursheet,x,y,z,n); + if (onecell) n = !transparent(fcell); + else n = line_ok(_("Make block transparent:"), + transparent(fcell)); + if (n >= 0) + for (ALL_LOCS_IN_REGION(cursheet,w)) maketrans(cursheet, w, n); break; } /*}}}*/ @@ -438,9 +422,10 @@ static void do_attribute(Sheet *cursheet, Key action) { int n; - if (cursheet->mark1x==-1) n = !isbold(cursheet,x1,y1,z1); - else n = line_ok(_("Make block bold:"), isbold(cursheet,x1,y1,z1)); - if (n >= 0) for (x=x1; x<=x2; ++x) for (y=y1; y<=y2; ++y) for (z=z1; z<=z2; ++z) bold(cursheet,x,y,z,n); + if (onecell) n = !isbold(fcell); + else n = line_ok(_("Make block bold:"), isbold(fcell)); + if (n >= 0) + for (ALL_LOCS_IN_REGION(cursheet,w)) bold(cursheet, w, n); break; } /*}}}*/ @@ -449,9 +434,10 @@ static void do_attribute(Sheet *cursheet, Key action) { int n; - if (cursheet->mark1x==-1) n = !underlined(cursheet,x1,y1,z1); - else n = line_ok(_("Make block underlined:"), underlined(cursheet,x1,y1,z1)); - if (n >= 0) for (x=x1; x<=x2; ++x) for (y=y1; y<=y2; ++y) for (z=z1; z<=z2; ++z) underline(cursheet,x,y,z,n); + if (onecell) n = !underlined(fcell); + else n = line_ok(_("Underline block:"), underlined(fcell)); + if (n >= 0) + for (ALL_LOCS_IN_REGION(cursheet,w)) underline(cursheet, w, n); break; } /*}}}*/ @@ -467,10 +453,10 @@ static void do_attribute(Sheet *cursheet, Key action) { int n; - if (cursheet->mark1x==-1) n = !locked(cursheet,x1,y1,z1); - else n = line_ok(_("Lock block:"), locked(cursheet,x1,y1,z1)); - if (n >= 0) for (x=x1; x<=x2; ++x) for (y=y1; y<=y2; ++y) for (z=z1; z<=z2; ++z) lockcell(cursheet,x,y,z,n); - + if (onecell) n = !locked(fcell); + else n = line_ok(_("Lock block:"), locked(fcell)); + if (n >= 0) + for (ALL_LOCS_IN_REGION(cursheet,w)) lockcell(cursheet, w, n); break; } /*}}}*/ @@ -479,9 +465,11 @@ static void do_attribute(Sheet *cursheet, Key action) { int n; - if (cursheet->mark1x==-1) n = !ignored(cursheet,x1,y1,z1); - else n = line_ok(_("Ignore values of all cells in this block:"), ignored(cursheet,x1,y1,z1)); - if (n >= 0) for (x=x1; x<=x2; ++x) for (y=y1; y<=y2; ++y) for (z=z1; z<=z2; ++z) igncell(cursheet,x,y,z,n); + if (onecell) n = !ignored(fcell); + else n = line_ok(_("Ignore contents of all cells in this block:"), + ignored(fcell)); + if (n >= 0) + for (ALL_LOCS_IN_REGION(cursheet,w)) igncell(cursheet, w, n); break; } /*}}}*/ @@ -491,13 +479,14 @@ static void do_attribute(Sheet *cursheet, Key action) } if (c>=0) { - if (cursheet->mark1x==-1) redraw_cell(cursheet, cursheet->curx, cursheet->cury, cursheet->curz); + if (onecell) redraw_cell(cursheet, cursheet->mark1); else redraw_sheet(cursheet); } forceupdate(cursheet); return; } /*}}}*/ + /* do_savexdr -- save sheet as XDR file */ /*{{{*/ static int do_savexdr(Sheet *cursheet, const char *name) { @@ -543,22 +532,23 @@ static int do_saveport(Sheet *cursheet, const char *name) return -1; } /*}}}*/ + /* do_savetbl -- save sheet as tbl file */ /*{{{*/ static int do_savetbl(Sheet *cursheet, const char *name) { char buf[PATH_MAX]; const char *msg; int standalone=0; - int x1,y1,z1,x2,y2,z2; unsigned int count; - get_mark(cursheet, &x1, &x2, &y1, &y2, &z1, &z2, 1); + do_mark(cursheet, GET_MARK_ALL); if (!name) { name = cursheet->name; if ((standalone=line_ok(_("Save as stand-alone document:"),1))<0) return standalone; } - if ((msg = savetbl(cursheet, name, !standalone, x1, y1, z1, x2, y2, z2, &count))) { + if ((msg = savetbl(cursheet, name, !standalone, + cursheet->mark1, cursheet->mark2, &count))) { line_msg(_("Save in tbl format to file:"),msg); return -2; } @@ -568,22 +558,23 @@ static int do_savetbl(Sheet *cursheet, const char *name) return -1; } /*}}}*/ + /* do_savelatex -- save sheet as LaTeX file */ /*{{{*/ static int do_savelatex(Sheet *cursheet, const char *name) { char buf[PATH_MAX]; const char *msg; int standalone=0; - int x1,y1,z1,x2,y2,z2; unsigned int count; - get_mark(cursheet, &x1, &x2, &y1, &y2, &z1, &z2, 1); + do_mark(cursheet, GET_MARK_ALL); if (!name) { name = cursheet->name; if ((standalone=line_ok(_("Save as stand-alone document:"),1))<0) return standalone; } - if ((msg = savelatex(cursheet, name, !standalone, x1, y1, z1, x2, y2, z2, &count))) { + if ((msg = savelatex(cursheet, name, !standalone, + cursheet->mark1, cursheet->mark2, &count))) { line_msg(_("Save in LaTeX format to file:"),msg); return -2; } @@ -593,6 +584,7 @@ static int do_savelatex(Sheet *cursheet, const char *name) return -1; } /*}}}*/ + /* do_savecontext -- save sheet as ConTeXt file */ /*{{{*/ static int do_savecontext(Sheet *cursheet, const char *name) { @@ -602,13 +594,16 @@ static int do_savecontext(Sheet *cursheet, const char *name) int x1,y1,z1,x2,y2,z2; unsigned int count; - get_mark(cursheet, &x1, &x2, &y1, &y2, &z1, &z2, 1); - if (!name) { + do_mark(cursheet, GET_MARK_ALL); + if (!name) + { name = cursheet->name; if ((standalone=line_ok(_("Save as stand-alone document:"),1))<0) return standalone; } - if ((msg = savecontext(cursheet, name, !standalone, x1, y1, z1, x2, y2, z2, &count))) { + if ((msg = savecontext(cursheet, name, !standalone, + cursheet->mark1, cursheet->mark2, &count))) + { line_msg(_("Save in ConTeXt format to file:"),msg); return -2; } @@ -618,6 +613,7 @@ static int do_savecontext(Sheet *cursheet, const char *name) return -1; } /*}}}*/ + /* do_savehtml -- save sheet as HTML file */ /*{{{*/ static int do_savehtml(Sheet *cursheet, const char *name) { @@ -627,13 +623,14 @@ static int do_savehtml(Sheet *cursheet, const char *name) int x1,y1,z1,x2,y2,z2; unsigned int count; - get_mark(cursheet, &x1, &x2, &y1, &y2, &z1, &z2, 1); + do_mark(cursheet, GET_MARK_ALL); if (!name) { name = cursheet->name; if ((standalone=line_ok(_("Save as stand-alone document:"),1))<0) return standalone; } - if ((msg = savehtml(cursheet, name, !standalone, x1, y1, z1, x2, y2, z2, &count))) { + if ((msg = savehtml(cursheet, name, !standalone, + cursheet->mark1, cursheet->mark2, &count))) { line_msg(_("Save in HTML format to file:"),msg); return -2; } @@ -643,6 +640,7 @@ static int do_savehtml(Sheet *cursheet, const char *name) return -1; } /*}}}*/ + /* do_savetext -- save sheet as formatted text file */ /*{{{*/ static int do_savetext(Sheet *cursheet, const char *name) { @@ -651,10 +649,11 @@ static int do_savetext(Sheet *cursheet, const char *name) int x1,y1,z1,x2,y2,z2; unsigned int count; - get_mark(cursheet, &x1, &x2, &y1, &y2, &z1, &z2, 1); + do_mark(cursheet, GET_MARK_ALL); if (!name) name = cursheet->name; - if ((msg = savetext(cursheet, name, x1, y1, z1, x2, y2, z2, &count))) { + if ((msg = savetext(cursheet, name, + cursheet->mark1, cursheet->mark2, &count))) { line_msg(_("Save in plain text format to file:"),msg); return -2; } @@ -664,6 +663,7 @@ static int do_savetext(Sheet *cursheet, const char *name) return -1; } /*}}}*/ + /* do_savecsv -- save sheet as CSV file */ /*{{{*/ static int do_savecsv(Sheet *cursheet, const char *name) { @@ -674,7 +674,7 @@ static int do_savecsv(Sheet *cursheet, const char *name) int sep = 0; const char seps[4] = ",;\t"; - get_mark(cursheet, &x1, &x2, &y1, &y2, &z1, &z2, 1); + do_mark(cursheet, GET_MARK_ALL); if (!name) { MenuChoice menu[4]; name = cursheet->name; @@ -687,7 +687,8 @@ static int do_savecsv(Sheet *cursheet, const char *name) if (sep < 0) return sep; } - if ((msg = savecsv(cursheet, name, seps[sep], x1, y1, z1, x2, y2, z2, &count))) { + if ((msg = savecsv(cursheet, name, seps[sep], + cursheet->mark1, cursheet->mark2, &count))) { line_msg(_("Save in CSV format to file:"),msg); return -2; } @@ -697,6 +698,7 @@ static int do_savecsv(Sheet *cursheet, const char *name) return -1; } /*}}}*/ + /* do_loadxdr -- load sheet from XDR file */ /*{{{*/ static int do_loadxdr(Sheet *cursheet) { @@ -743,39 +745,77 @@ static int do_loadcsv(Sheet *cursheet) return -1; } /*}}}*/ + /* do_mark -- set mark */ /*{{{*/ -void do_mark(Sheet *cursheet, int force) +void do_mark(Sheet *cursheet, MarkState ms) { - if (force==0) + MarkState ps; + Dimensions dim; + + ps = getmarkstate(cursheet); + + if (ms == MARK_CYCLE) { - if (!cursheet->marking && cursheet->mark1x==-1) force=1; - else if (cursheet->marking) force=2; - else force=3; + if (ps == UNMARKED) ms = MARKING; + else ms = ps + 1; } - switch (force) + if (ps == ms) return; + switch (ms) { - case 1: + case MARKING: { - cursheet->mark1x=cursheet->mark2x=cursheet->curx; - cursheet->mark1y=cursheet->mark2y=cursheet->cury; - cursheet->mark1z=cursheet->mark2z=cursheet->curz; - cursheet->marking=1; + LOCATION_GETS(cursheet->mark1, cursheet->cur); + LOCATION_GETS(cursheet->mark2, cursheet->cur); break; } - case 2: - { - cursheet->marking=0; + case UNMARKED: break; - } - case 3: + case MARKED: + case GET_MARK_CUR: + case GET_MARK_ALL: { - cursheet->mark1x=-1; + switch (ps) + { + case MARKED: { + ms = MARKED; + break; + } + case MARKING: + { + for (dim = X; dim < HYPER; ++dim) + posorder(&(cursheet->mark1[dim]), &(cursheet->mark2[dim])); + ms = MARKED; + break; + } + case UNMARKED: + { + if (ms == GET_MARK_CUR) + { + LOCATION_GETS(cursheet->mark1, cursheet->cur); + LOCATION_GETS(cursheet->mark2, cursheet->cur); + ms = UNMARKED; + } + else if (ms == GET_MARK_ALL) + { + OLOCATION(cursheet->mark1); + cursheet->mark2[X] = cursheet->dimx - 1; + cursheet->mark2[Y] = cursheet->dimy - 1; + cursheet->mark2[Z] = cursheet->dimz - 1; + ms = UNMARKED; + } + else assert(ms == MARKED); + break; + } + default: assert(0); + } break; } default: assert(0); } + cursheet->marking = ms; } /*}}}*/ + static int do_name(Sheet *cursheet); /* do_save -- save sheet */ /*{{{*/ static int do_save(Sheet *cursheet) @@ -833,36 +873,41 @@ static int do_load(Sheet *cursheet) static int do_clear(Sheet *sheet) { /* variables */ /*{{{*/ - int x,y,z; - int x1,y1,z1; - int x2,y2,z2; + Location w; + bool onecell; int c; /*}}}*/ - if (sheet->mark1x==-1 && locked(sheet,sheet->curx,sheet->cury,sheet->curz)) line_msg(_("Clear cell:"),_("Cell is locked")); + do_mark(sheet, GET_MARK_CUR); + onecell = SAME_LOC(sheet->mark1, sheet->mark2); + if (onecell && locked(CELL_AT(sheet, sheet->mark1))) + line_msg(_("Clear cell:"),_("Cell is locked")); else { - if (sheet->mark1x!=-1) + if (!onecell) { if ((c=line_ok(_("Clear block:"),0))<0) return c; else if (c!=1) return -1; } - get_mark(sheet, &x1, &x2, &y1, &y2, &z1, &z2, 0); - for (x=x1; x<=x2; ++x) for (y=y1; y<=y2; ++y) for (z=z1; z<=z2; ++z) freecell(sheet,x,y,z); + + for (ALL_LOCS_IN_REGION(sheet, w)) freecell(sheet, w); cachelabels(sheet); forceupdate(sheet); } return -1; } /*}}}*/ + /* do_insert -- insert block */ /*{{{*/ static int do_insert(Sheet *sheet) { /* variables */ /*{{{*/ - int x1,y1,z1,x2,y2,z2,reply; + int reply; + bool onecell; + Location beg, end; /*}}}*/ - /* ask for direction of insertation */ /*{{{*/ + /* ask for direction of insertion */ /*{{{*/ { MenuChoice menu[4]; @@ -877,7 +922,11 @@ static int do_insert(Sheet *sheet) if (reply<0) return reply; } /*}}}*/ - if (sheet->mark1x==-1) + do_mark(sheet, GET_MARK_CUR); + LOCATION_GETS(beg, sheet->mark1); + LOCATION_GETS(end, sheet->mark2); + onecell = SAME_LOC(beg, end); + if (onecell) /* ask if current cell or whole dimension should be used */ /*{{{*/ { /* variables */ /*{{{*/ @@ -909,27 +958,22 @@ static int do_insert(Sheet *sheet) /* 0 -- use whole column */ /*{{{*/ case 0: { - x1=x2=sheet->curx; - y1=0; y2=sheet->dimy; - z1=z2=sheet->curz; + beg[Y] = 0; end[Y] = sheet->dimy; break; } /*}}}*/ /* 1 -- use whole line */ /*{{{*/ case 1: { - x1=0; x2=sheet->dimx; - y1=y2=sheet->cury; - z1=z2=sheet->curz; + beg[X] = 0; end[X] = sheet->dimx; break; } /*}}}*/ /* 2 -- use whole layer */ /*{{{*/ case 2: { - x1=0; x2=sheet->dimx; - y1=0; y2=sheet->dimy; - z1=z2=sheet->curz; + beg[X] = 0; end[X] = sheet->dimx; + beg[Y] = 0; end[Y] = sheet->dimy; break; } /*}}}*/ @@ -941,13 +985,7 @@ static int do_insert(Sheet *sheet) } /*}}}*/ /* 1 -- use current cell */ /*{{{*/ - case 1: - { - x1=x2=sheet->curx; - y1=y2=sheet->cury; - z1=z2=sheet->curz; - break; - } + case 1: break; /*}}}*/ /* -2,-1 -- go up or abort */ /*{{{*/ case -2: @@ -959,32 +997,30 @@ static int do_insert(Sheet *sheet) } } /*}}}*/ - else - /* range is the marked cube */ /*{{{*/ - { - get_mark(sheet, &x1, &x2, &y1, &y2, &z1, &z2, 0); - } /*}}}*/ switch (reply) { /* 0 -- columns */ /*{{{*/ - case 0: insertcube(sheet,x1,y1,z1,x2,y2,z2,IN_X); break; + case 0: insertcube(sheet, beg, end, IN_X); break; /*}}}*/ /* 1 -- rows */ /*{{{*/ - case 1: insertcube(sheet,x1,y1,z1,x2,y2,z2,IN_Y); break; + case 1: insertcube(sheet, beg, end, IN_Y); break; /*}}}*/ /* 2 -- depth */ /*{{{*/ - case 2: insertcube(sheet,x1,y1,z1,x2,y2,z2,IN_Z); break; + case 2: insertcube(sheet, beg, end, IN_Z); break; /*}}}*/ } return 0; } /*}}}*/ + /* do_delete -- delete block */ /*{{{*/ static int do_delete(Sheet *sheet) { /* variables */ /*{{{*/ - int x1,y1,z1,x2,y2,z2,reply; + int reply; + bool onecell; + Location beg, end; /*}}}*/ firstmenu: @@ -1003,7 +1039,12 @@ static int do_delete(Sheet *sheet) if (reply<0) return reply; } /*}}}*/ - if (sheet->mark1x==-1) + + do_mark(sheet, GET_MARK_CUR); + LOCATION_GETS(beg, sheet->mark1); + LOCATION_GETS(end, sheet->mark2); + onecell = SAME_LOC(beg, end); + if (onecell) /* ask if range is the current cell or whole dimension should be used */ /*{{{*/ { /* variables */ /*{{{*/ @@ -1035,27 +1076,22 @@ static int do_delete(Sheet *sheet) /* 0 -- use whole column */ /*{{{*/ case 0: { - x1=x2=sheet->curx; - y1=0; y2=sheet->dimy; - z1=z2=sheet->curz; + beg[Y] = 0; end[Y] = sheet->dimy; break; } /*}}}*/ /* 1 -- use whole line */ /*{{{*/ case 1: { - x1=0; x2=sheet->dimx; - y1=y2=sheet->cury; - z1=z2=sheet->curz; + beg[X] = 0; end[X] = sheet->dimx; break; } /*}}}*/ /* 2 -- use whole layer */ /*{{{*/ case 2: { - x1=0; x2=sheet->dimx; - y1=0; y2=sheet->dimy; - z1=z2=sheet->curz; + beg[X] = 0; end[X] = sheet->dimx; + beg[Y] = 0; end[Y] = sheet->dimy; break; } /*}}}*/ @@ -1067,13 +1103,7 @@ static int do_delete(Sheet *sheet) } /*}}}*/ /* 1 -- use current cell */ /*{{{*/ - case 1: - { - x1=x2=sheet->curx; - y1=y2=sheet->cury; - z1=z2=sheet->curz; - break; - } + case 1: break; /*}}}*/ /* -1 -- abort */ /*{{{*/ case -1: return -1; @@ -1087,22 +1117,17 @@ static int do_delete(Sheet *sheet) } } /*}}}*/ - else - /* range is the marked cube */ /*{{{*/ - { - get_mark(sheet, &x1, &x2, &y1, &y2, &z1, &z2, 0); - } /*}}}*/ switch(reply) { /* 0 -- columns */ /*{{{*/ - case 0: deletecube(sheet,x1,y1,z1,x2,y2,z2,IN_X); break; + case 0: deletecube(sheet, beg, end, IN_X); break; /*}}}*/ /* 1 -- rows */ /*{{{*/ - case 1: deletecube(sheet,x1,y1,z1,x2,y2,z2,IN_Y); break; + case 1: deletecube(sheet, beg, end, IN_Y); break; /*}}}*/ /* 2 -- depth */ /*{{{*/ - case 2: deletecube(sheet,x1,y1,z1,x2,y2,z2,IN_Z); break; + case 2: deletecube(sheet, beg, end, IN_Z); break; /*}}}*/ } return -1; @@ -1114,19 +1139,18 @@ static int do_move(Sheet *sheet, int copy, int force) int c; c=-1; - if (sheet->mark1x==-1) line_msg(copy ? _("Copy block:") : _("Move block:"),_("No block marked")); + + if (getmarkstate(sheet) == UNMARKED) line_msg(copy ? _("Copy block:") : _("Move block:"),_("No block marked")); else if (force || (c=line_ok(copy ? _("Copy block:") : _("Move block:"),0))==1) { - int x1,y1,z1; - int x2,y2,z2; - - get_mark(sheet, &x1, &x2, &y1, &y2, &z1, &z2, 0); - moveblock(sheet,x1,y1,z1,x2,y2,z2,sheet->curx,sheet->cury,sheet->curz,copy); - if (!copy) sheet->mark1x=-1; + do_mark(sheet, MARKED); + moveblock(sheet, sheet->mark1, sheet->mark2, sheet->cur, copy); + if (!copy) sheet->marking = UNMARKED; } if (c<0) return c; else return -1; } /*}}}*/ + /* do_fill -- fill a block */ /*{{{*/ static int do_fill(Sheet *sheet) { @@ -1134,15 +1158,14 @@ static int do_fill(Sheet *sheet) size_t offx,edx; int cols,rows,layers; int x,y,z; - int x1,y1,z1; - int x2,y2,z2; + Location wid, go; int c; /*}}}*/ - if (sheet->mark1x==-1) line_msg(_("Fill block:"),_("No block marked")); + if (getmarkstate(sheet) == UNMARKED) line_msg(_("Fill block:"),_("No block marked")); else { - get_mark(sheet, &x1, &x2, &y1, &y2, &z1, &z2, 0); + do_mark(sheet, MARKED); cols=rows=layers=1; firstmenu: offx=0; @@ -1165,11 +1188,19 @@ static int do_fill(Sheet *sheet) if (c==-1) return -1; else if (c==-2) goto secondmenu; } while (layers<=0); - for (x=0; xcurx+x*(x2-x1+1),sheet->cury+y*(y2-y1+1),sheet->curz+z*(z2-z1+1),1); + LOCATION_GETS(wid, sheet->mark2); + LOCATION_SUB(wid, sheet->mark1); + wid[X]++; wid[Y]++; wid[Z]++; + LOCATION_GETS(go, sheet->cur); + for (z=0; zcur[Y]; ycur[X]; xmark1, sheet->mark2, go, 1); } return -1; } /*}}}*/ + /* do_sort -- sort block */ /*{{{*/ static int do_sort(Sheet *sheet) { @@ -1186,9 +1217,7 @@ static int do_sort(Sheet *sheet) int last; /*}}}*/ - /* note and order block coordinates */ /*{{{*/ - get_mark(sheet, &x1, &x2, &y1, &y2, &z1, &z2, 1); - /*}}}*/ + do_mark(sheet, GET_MARK_ALL); /* build menues */ /*{{{*/ menu1[0].str=mystrmalloc(_("cC)olumn")); menu1[0].c='\0'; menu1[1].str=mystrmalloc(_("rR)ow")); menu1[1].c='\0'; @@ -1355,7 +1384,7 @@ static int do_sort(Sheet *sheet) last=5; } while (!doit); c=-1; - if ((msg=sortblock(sheet,x1,y1,z1,x2,y2,z2,in_dir,sk,key))!=(const char*)0) line_msg(_("Sort block:"),msg); + if ((msg=sortblock(sheet, sheet->mark1, sheet->mark2, in_dir, sk, key))!=(const char*)0) line_msg(_("Sort block:"),msg); greak: /* free menues */ /*{{{*/ free((char*)menu1[0].str); @@ -1371,6 +1400,7 @@ static int do_sort(Sheet *sheet) return c; } /*}}}*/ + /* do_batchsort -- sort block in a batch*/ /*{{{*/ static void do_batchsort(Sheet *sheet, Direction dir, char* arg) { @@ -1392,10 +1422,11 @@ static void do_batchsort(Sheet *sheet, Direction dir, char* arg) if ( *arg != '\0' && dir != IN_Z ) { sk[key].z=strtol(arg, &next, 10); arg = next; } key++; } - get_mark(sheet, &x1, &x2, &y1, &y2, &z1, &z2, 1); - sortblock(sheet, x1, y1, z1, x2, y2, z2, dir, sk, key); + do_mark(sheet, GET_MARK_ALL); + sortblock(sheet, sheet->mark1, sheet->mark2, dir, sk, key); } /*}}}*/ + /* do_mirror -- mirror block */ /*{{{*/ static int do_mirror(Sheet *sheet) { @@ -1403,9 +1434,7 @@ static int do_mirror(Sheet *sheet) int x1,y1,z1,x2,y2,z2,reply; /*}}}*/ - /* note and order block coordinates */ /*{{{*/ - get_mark(sheet, &x1, &x2, &y1, &y2, &z1, &z2, 1); - /*}}}*/ + do_mark(sheet, GET_MARK_ALL); /* ask for direction of mirroring */ /*{{{*/ { MenuChoice menu[4]; @@ -1424,13 +1453,13 @@ static int do_mirror(Sheet *sheet) switch (reply) { /* 0 -- left-right */ /*{{{*/ - case 0: mirrorblock(sheet,x1,y1,z1,x2,y2,z2,IN_X); break; + case 0: mirrorblock(sheet, sheet->mark1, sheet->mark2, IN_X); break; /*}}}*/ /* 1 -- upside-down */ /*{{{*/ - case 1: mirrorblock(sheet,x1,y1,z1,x2,y2,z2,IN_Y); break; + case 1: mirrorblock(sheet, sheet->mark1, sheet->mark2, IN_Y); break; /*}}}*/ /* 2 -- front-back */ /*{{{*/ - case 2: mirrorblock(sheet,x1,y1,z1,x2,y2,z2,IN_Z); break; + case 2: mirrorblock(sheet, sheet->mark1, sheet->mark2, IN_Z); break; /*}}}*/ default: assert(0); } @@ -1459,14 +1488,12 @@ static int do_goto(Sheet *sheet, const char *expr) { Token value; - upd_x=sheet->curx; - upd_y=sheet->cury; - upd_z=sheet->curz; + LOCATION_GETS(upd_l, sheet->cur); upd_sheet=sheet; value=eval(t); tvecfree(t); - if (value.type==LOCATION && value.u.location[0]>=0 && value.u.location[1]>=0 && value.u.location[2]>=0) - moveto(sheet,value.u.location[0],value.u.location[1],value.u.location[2]); + if (value.type==LOCATION && IN_OCTANT(value.u.location)) + movetoloc(sheet, value.u.location); else line_msg(_("Go to location:"),_("Not a valid location")); tfree(&value); @@ -1694,12 +1721,10 @@ int do_sheetcmd(Sheet *cursheet, Key c, int moveonly) /* _("Usage: clock(condition,location[,location])") -- clock */ /*{{{*/ case K_CLOCK: { - int x,y,z; + Location w; - for (x=0; xdimx; ++x) - for (y=0; ydimy; ++y) - for (z=0; zdimz; ++z) - clk(cursheet,x,y,z); + for (ALL_LOCS_IN_SHEET(cursheet, w)) + clk(cursheet, w); update(cursheet); break; } @@ -1716,7 +1741,7 @@ int do_sheetcmd(Sheet *cursheet, Key c, int moveonly) case K_PPAGE: { cursheet->offy = (cursheet->offy>=(cursheet->maxy-3) ? cursheet->offy-(cursheet->maxy-3) : 0); - relmoveto(cursheet, 0, (cursheet->cury>=(cursheet->maxy-3) ? -(cursheet->maxy-3) : -cursheet->cury), 0); + relmoveto(cursheet, 0, (cursheet->cur[Y] >= (cursheet->maxy-3) ? -(cursheet->maxy-3) : -cursheet->cur[Y]), 0); break; } /*}}}*/ @@ -1732,7 +1757,7 @@ int do_sheetcmd(Sheet *cursheet, Key c, int moveonly) case K_BPAGE: { cursheet->offx=(cursheet->offx>=cursheet->width ? cursheet->offx-cursheet->width : 0); - relmoveto(cursheet, (cursheet->curx>=cursheet->width ? -cursheet->width : -cursheet->curx), 0, 0); + relmoveto(cursheet, (cursheet->cur[X]>=cursheet->width ? -cursheet->width : -cursheet->cur[X]), 0, 0); break; } /*}}}*/ @@ -1835,30 +1860,13 @@ int main(int argc, char *argv[]) } /*}}}*/ } - loadfile=(optindcurx=cursheet->cury=cursheet->curz=0; - cursheet->offx=cursheet->offy=0; - cursheet->dimx=cursheet->dimy=cursheet->dimz=0; - cursheet->sheet=(Cell**)0; - cursheet->column=(int*)0; - cursheet->orix=0; - cursheet->oriy=0; - cursheet->maxx=0; - cursheet->maxy=0; - cursheet->name=(char*)0; - cursheet->mark1x=-1; - cursheet->marking=0; - cursheet->changed=0; - cursheet->moveonly=0; - cursheet->clk=0; - (void)memset(cursheet->labelcache,0,sizeof(cursheet->labelcache)); + loadfile = (optindadjust=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; ydimy; ++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; ydimy; ++y) if (CELL_ATC(sheet,x,y,0)) CELL_ATC(sheet,x,y,0)->precision=prec; } /*}}}*/ eek: diff --git a/scanner.c b/scanner.c index b579e32..d984ba1 100644 --- a/scanner.c +++ b/scanner.c @@ -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) { diff --git a/scanner.h b/scanner.h index 6a4721d..d59a993 100644 --- a/scanner.h +++ b/scanner.h @@ -2,6 +2,7 @@ #define SCANNER_H #include +#include #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; diff --git a/sheet.c b/sheet.c index 052ada8..379f47a 100644 --- a/sheet.c +++ b/sheet.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -40,9 +41,7 @@ static int upd_clock; /* evaluate clocked expressions */ /* Used during evaluation of a cell to specify the currently updated cell */ Sheet *upd_sheet; -int upd_x; -int upd_y; -int upd_z; +Location upd_l; int max_eval; /*}}}*/ @@ -50,7 +49,7 @@ int max_eval; static void copytokens(Token*** totoks, Token** fromtoks) { /* variables */ /*{{{*/ - size_t from_len, i; + size_t from_len, to_len; /*}}}*/ from_len = tveclen(fromtoks); @@ -60,16 +59,17 @@ static void copytokens(Token*** totoks, Token** fromtoks) *totoks = EMPTY_TVEC; return; } - from_len; - if (from_len > tveclen(*totoks)) + + to_len = tveclen(*totoks); + if (from_len > to_len || *totoks == fromtoks) { - tvecfree(*totoks); + if (*totoks != fromtoks) tvecfree(*totoks); *totoks = malloc((from_len+1)*sizeof(Token*)); (*totoks)[from_len] = NULLTOKEN; } else { tvecfreetoks(*totoks); } - for (i=0; ichanged=1; - fromcell = CELL_AT(sheet1,x1,y1,z1); - if (fromcell == NULLCELL) freecell(sheet2,x2,y2,z2); - else - /* copy first cell to second */ /*{{{*/ + sheet2->changed = 1; + tocell = initcell(sheet2, to); + memcpy(tocell, fromcell, sizeof(Cell)); + copytokens(&(tocell->contents[BASE]), fromcell->contents[BASE]); + copytokens(&(tocell->contents[ITERATIVE]), fromcell->contents[ITERATIVE]); + if (fromcell->label != (char*)0) { - freecell(sheet2,x2,y2,z2); - initcell(sheet2,x2,y2,z2); - 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; + len = strlen(fromcell->label); + tocell->label = strcpy(malloc(len+2), fromcell->label); + (tocell->label)[len] = '_'; + (tocell->label)[len+1] = '\0'; } - /*}}}*/ + tocell->value.type = EMPTY; + tocell->resvalue.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) { @@ -128,22 +128,22 @@ static void dump_cell(Sheet *sheet, int x, int y, int z) x, y, z); return; } - if (!LOC_WITHIN(sheet, x, y, z)) + if (!LOC_WITHINC(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); + c = CELL_ATC(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); + print(buf, sizeof(buf), 0, 1, 0, -1, c->contents[BASE]); printf(" Base expr: %s.\n", buf); - print(buf, sizeof(buf), 0, 1, 0, -1, c->ccontents); + print(buf, sizeof(buf), 0, 1, 0, -1, c->contents[ITERATIVE]); printf(" Update expr: %s.\n", buf); if (c->label == (char *)0) printf("\n No label.\n"); else printf("\n Label: %s.\n", c->label); @@ -172,13 +172,15 @@ static void dump_cell(Sheet *sheet, int x, int y, int z) 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); + dump_cell(sheet, sheet->cur[X], sheet->cur[Y], sheet->cur[Z]); } /*}}}*/ + /* 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) { @@ -194,9 +196,9 @@ static void swapblock(Sheet *sheet1, int x1, int y1, int z1, Sheet *sheet2, int { Cell *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; + t = CELL_ATC(sheet1,x1+xoff,y1+yoff,z1+zoff); + CELL_ATC(sheet1,x1+xoff,y1+yoff,z1+zoff) = CELL_ATC(sheet2,x2+xoff,y2+yoff,z2+zoff); + CELL_ATC(sheet2,x2+xoff,y2+yoff,z2+zoff) = t; } sheet1->changed=1; sheet2->changed=1; @@ -216,15 +218,15 @@ static int cmpcell(Sheet *sheet1, int x1, int y1, int z1, Sheet *sheet2, int x2, assert(sheet1!=(Sheet*)0); assert(sheet2!=(Sheet*)0); /* empty cells are smaller than any non-empty cell */ /*{{{*/ - if (!CELL_IS_GOOD(sheet1,x1,y1,z1) || CELL_AT(sheet1,x1,y1,z1)->value.type==EMPTY) + if (!CELL_IS_GOODC(sheet1,x1,y1,z1) || CELL_ATC(sheet1,x1,y1,z1)->value.type==EMPTY) { - if (!CELL_IS_GOOD(sheet2,x2,y2,z2) || CELL_AT(sheet2,x2,y2,z2)->value.type==EMPTY) return 0; + if (!CELL_IS_GOODC(sheet2,x2,y2,z2) || CELL_ATC(sheet2,x2,y2,z2)->value.type==EMPTY) return 0; else 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); + if (!CELL_IS_GOODC(sheet2,x2,y2,z2) || CELL_ATC(sheet2,x2,y2,z2)->value.type==EMPTY) return (sortkey&ASCENDING ? 1 : -1); /*}}}*/ - leftcell = CELL_AT(sheet1,x1,y1,z1); - rightcell = CELL_AT(sheet2,x2,y2,z2); + leftcell = CELL_ATC(sheet1,x1,y1,z1); + rightcell = CELL_ATC(sheet2,x2,y2,z2); switch (leftcell->value.type) { /* STRING */ /*{{{*/ @@ -283,6 +285,27 @@ static int cmpcell(Sheet *sheet1, int x1, int y1, int z1, Sheet *sheet2, int x2, } /*}}}*/ +/* initialize_sheet -- fill in fields of a newly allocated Sheet */ /*{{{*/ +void initialize_sheet(Sheet *sheet) { + assert(sheet != (Sheet*)0); + OLOCATION(sheet->cur); + sheet->offx = sheet->offy = 0; + sheet->dimx = sheet->dimy = sheet->dimz = 0; + sheet->sheet = (Cell**)0; + sheet->column = (int*)0; + sheet->orix = sheet->oriy = 0; + sheet->maxx = sheet->maxy = 0; + sheet->name = (char*)0; + OLOCATION(sheet->mark1); + OLOCATION(sheet->mark2); + sheet->marking = UNMARKED; + sheet->changed = 0; + sheet->moveonly = 0; + sheet->clk = 0; + (void)memset(sheet->labelcache, 0, sizeof(sheet->labelcache)); +} +/*}}}*/ + /* resize -- check if sheet needs to be resized in any dimension */ /*{{{*/ void resize(Sheet *sheet, int x, int y, int z) { @@ -290,84 +313,109 @@ void resize(Sheet *sheet, int x, int y, int z) assert(y>=0); assert(z>=0); assert(sheet!=(Sheet*)0); - if (!LOC_WITHIN(sheet,x,y,z)) + + if (!LOC_WITHINC(sheet,x,y,z)) { /* variables */ /*{{{*/ - Cell **newsheet; - int *newcolumn; - unsigned int ndimx,ndimy,ndimz; + Sheet dummy; /*}}}*/ sheet->changed=1; - ndimx=(x>=sheet->dimx ? x+1 : sheet->dimx); - ndimy=(y>=sheet->dimy ? y+1 : sheet->dimy); - ndimz=(z>=sheet->dimz ? z+1 : sheet->dimz); + dummy.dimx = (x >= sheet->dimx ? x+1 : sheet->dimx); + dummy.dimy = (y >= sheet->dimy ? y+1 : sheet->dimy); + dummy.dimz = (z >= sheet->dimz ? z+1 : sheet->dimz); /* allocate new sheet */ /*{{{*/ - newsheet=malloc(ndimx*ndimy*ndimz*sizeof(Cell*)); - for (x=0; xsheet!=(Cell**)0) free(sheet->sheet); - sheet->sheet=newsheet; + sheet->sheet = dummy.sheet; /*}}}*/ /* allocate new columns */ /*{{{*/ if (x>sheet->dimx || z>=sheet->dimz) { - newcolumn=malloc(ndimx*ndimz*sizeof(int)); - for (x=0; xdimx && zdimz) *(newcolumn+x*ndimz+z)=*(sheet->column+x*sheet->dimz+z); - else *(newcolumn+x*ndimz+z)=DEF_COLUMNWIDTH; + if (xdimx && zdimz) + *(dummy.column+x*dummy.dimz+z)=*(sheet->column+x*sheet->dimz+z); + else *(dummy.column+x*dummy.dimz+z)=DEF_COLUMNWIDTH; } if (sheet->column!=(int*)0) free(sheet->column); - sheet->column=newcolumn; + sheet->column = dummy.column; } /*}}}*/ - sheet->dimx=ndimx; - sheet->dimy=ndimy; - sheet->dimz=ndimz; + sheet->dimx = dummy.dimx; + sheet->dimy = dummy.dimy; + sheet->dimz = dummy.dimz; } } /*}}}*/ + +static void preparecell(Cell *c) +{ + (void)memset(c->contents, 0, sizeof(c->contents)); + c->label=(char*)0; + c->adjust=AUTOADJUST; + c->precision=-1; + c->shadowed=0; + c->bold=0; + c->underline=0; + c->scientific=DEF_SCIENTIFIC; + c->value.type=EMPTY; + c->resvalue.type=EMPTY; + c->locked=0; + c->ignored=0; + c->clock_t0=0; + c->clock_t1=0; + c->clock_t2=0; +} + /* initcell -- initialise new cell, if it does not exist yet */ /*{{{*/ -void initcell(Sheet *sheet, int x, int y, int z) +Cell *initcell(Sheet *sheet, const Location at) { Cell *nc; - assert(x>=0); - assert(y>=0); - assert(z>=0); - resize(sheet,x,y,z); - if (CELL_AT(sheet,x,y,z) == NULLCELL) + assert(IN_OCTANT(at)); + resize(sheet, at[X], at[Y], at[Z]); + nc = CELL_AT(sheet,at); + if (nc == NULLCELL) { - sheet->changed=1; + sheet->changed = 1; 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; + CELL_AT(sheet,at) = nc; + preparecell(nc); } + return nc; } /*}}}*/ + +/* safe_cell_at -- returns pointer to the cell at the given location, + even in the face of various edge conditions. +*/ + +Cell *safe_cell_at(Sheet *sheet, const Location at) +{ + if (sheet == (Sheet*)0) return NULLCELL; + if (sheet->sheet == (Cell **)0) return NULLCELL; + if (!LOC_WITHIN(sheet, at)) return NULLCELL; + return CELL_AT(sheet, at); +} + +/* curcell -- return pointer to the current cell */ /*{{{*/ +Cell *curcell(Sheet *sheet) +{ + return safe_cell_at(sheet, sheet->cur); +} + /* cachelabels -- create new label cache */ /*{{{*/ void cachelabels(Sheet *sheet) { - int i,x,y,z; + int i; + Location w; if (sheet==(Sheet*)0) return; for (i=0; ilabelcache[i]=(struct Label*)0; } /*}}}*/ - for (ALL_CELLS_IN_SHEET(sheet,x,y,z)) + for (ALL_LOCS_IN_SHEET(sheet,w)) /* cache all labels */ /*{{{*/ { const char *l; - l=getlabel(sheet,x,y,z); + l = getlabel(CELL_AT(sheet,w)); if (*l) { unsigned long hx; @@ -403,9 +451,7 @@ void cachelabels(Sheet *sheet) *run=malloc(sizeof(struct Label)); (*run)->next=(struct Label*)0; (*run)->label=l; - (*run)->x=x; - (*run)->y=y; - (*run)->z=z; + LOCATION_GETS((*run)->location,w); } /* else we have a duplicate label, which _can_ happen under */ /* unfortunate conditions. Don't tell anybody. */ @@ -418,14 +464,14 @@ void cachelabels(Sheet *sheet) void freesheet(Sheet *sheet, int all) { /* variables */ /*{{{*/ - int x,y,z; + Location w; /*}}}*/ assert(sheet!=(Sheet*)0); sheet->changed=0; - for (ALL_CELLS_IN_SHEET(sheet,x,y,z)) + for (ALL_LOCS_IN_SHEET(sheet,w)) { - freecell(sheet,x,y,z); + freecell(sheet,w); } if (all) { @@ -451,6 +497,8 @@ void freesheet(Sheet *sheet, int all) } else { + int x,z; + for (x=0; xdimx; ++x) for (z=0; zdimz; ++z) { *(sheet->column+x*sheet->dimz+z)=DEF_COLUMNWIDTH; @@ -464,36 +512,36 @@ void freesheet(Sheet *sheet, int all) void forceupdate(Sheet *sheet) { int i; + Cell *cell; assert(sheet!=(Sheet*)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; - (*(sheet->sheet+i))->clock_t1=0; - (*(sheet->sheet+i))->clock_t2=0; - } + for (ALL_CELLS_IN_SHEET(sheet,i,cell)) + if (cell != NULLCELL) + cell->updated = cell->clock_t0 = cell->clock_t1 = cell->clock_t2 = 0; update(sheet); } /*}}}*/ + /* freecell -- free one cell */ /*{{{*/ -void freecell(Sheet *sheet, int x, int y, int z) +void freecell(Sheet *sheet, const Location at) { Cell *c; - assert(sheet!=(Sheet*)0); - if (sheet->sheet!=(Cell**)0 && CELL_IS_GOOD(sheet,x,y,z)) + + assert(sheet != (Sheet*)0); + if (sheet->sheet != (Cell**)0 && CELL_IS_GOOD(sheet,at)) { - c = CELL_AT(sheet,x,y,z); - tvecfree(c->contents); - tvecfree(c->ccontents); + c = CELL_AT(sheet,at); + tvecfree(c->contents[BASE]); + tvecfree(c->contents[ITERATIVE]); tfree(&(c->value)); tfree(&(c->resvalue)); free(c); - CELL_AT(sheet,x,y,z) = NULLCELL; - sheet->changed=1; + CELL_AT(sheet,at) = NULLCELL; + sheet->changed = 1; } } /*}}}*/ + /* columnwidth -- get width of column */ /*{{{*/ int columnwidth(Sheet *sheet, int x, int z) { @@ -512,54 +560,54 @@ void setwidth(Sheet *sheet, int x, int z, int width) } /*}}}*/ /* cellwidth -- get width of a cell */ /*{{{*/ -int cellwidth(Sheet *sheet, int x, int y, int z) +int cellwidth(Sheet *sheet, const Location at) { - int width; + int width,x; - if (SHADOWED(sheet,x,y,z)) return 0; - width=columnwidth(sheet,x,z); - for (++x; SHADOWED(sheet,x,y,z); width+=columnwidth(sheet,x,z),++x); + if (SHADOWED(sheet,at)) return 0; + x = at[X]; + width = columnwidth(sheet,x,at[Z]); + for (++x; SHADOWEDC(sheet,x,at[Y],at[Z]); + width += columnwidth(sheet,x,at[Z]), ++x); return width; } /*}}}*/ + /* putcont -- assign new contents */ /*{{{*/ -void putcont(Sheet *sheet, int x, int y, int z, Token **t, int c) +void putcont(Sheet *sheet, const Location at, Token **t, ContentVariety v) { - assert(sheet!=(Sheet*)0); - sheet->changed=1; - resize(sheet,x,y,z); - initcell(sheet,x,y,z); - if (c) - { - tvecfree(CELL_AT(sheet,x,y,z)->ccontents); - CELL_AT(sheet,x,y,z)->ccontents=t; - } - else - { - tvecfree(CELL_AT(sheet,x,y,z)->contents); - CELL_AT(sheet,x,y,z)->contents=t; - } - redraw_cell(sheet, x, y, z); + Cell *cell; + + assert(sheet != (Sheet*)0); + sheet->changed = 1; + cell = initcell(sheet, at); + tvecfree(cell->contents[v]); + cell->contents[v] = t; + redraw_cell(sheet, at); } /*}}}*/ + /* getcont -- get contents */ /*{{{*/ -Token **getcont(Sheet *sheet, int x, int y, int z, int c) +Token **getcont(const Cell *cell, ContentVariety v) { - 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); + if (cell == NULLCELL) return EMPTY_TVEC; + if (v == CONTINGENT) + v = (cell->clock_t0 && cell->contents[ITERATIVE]) ? ITERATIVE : BASE; + return cell->contents[v]; } /*}}}*/ + /* getvalue -- get tcopy()ed value */ /*{{{*/ -Token getvalue(Sheet *sheet, int x, int y, int z) +Token getvalue(Sheet *sheet, const Location at) { /* variables */ /*{{{*/ Token result; int orig_upd_clock; + Cell* cell; /*}}}*/ assert(sheet!=(Sheet*)0); - if (x<0 || y<0 || z<0) + if (!IN_OCTANT(at)) /* return error */ /*{{{*/ { result.type=EEK; @@ -569,125 +617,124 @@ Token getvalue(Sheet *sheet, int x, int y, int z) /*}}}*/ result.type = EMPTY; /* Can always short-circuit an out-of-bounds or empty cell */ - if (!CELL_IS_GOOD(sheet,x,y,z)) return result; + if (!CELL_IS_GOOD(sheet,at)) 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; + cell = CELL_AT(sheet, at); + if (!upd_clock && getcont(cell,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) + if (cell->ignored) { /* variables */ /*{{{*/ Token oldvalue; /*}}}*/ - 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; + oldvalue = cell->value; + cell->updated = 1; + cell->value.type = EMPTY; tfree(&oldvalue); } - else if (CELL_AT(sheet,x,y,z)->updated==0) + else if (cell->updated == 0) { /* variables */ /*{{{*/ Sheet *old_sheet; - int old_x,old_y,old_z,old_max_eval; + Location old_l; + int 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) + old_sheet = upd_sheet; + LOCATION_GETS(old_l, upd_l); + old_max_eval = max_eval; + upd_sheet = sheet; + LOCATION_GETS(upd_l, at); + max_eval = MAX_EVALNEST; + if (cell->clock_t1 == 0) { - CELL_AT(sheet,x,y,z)->updated = 1; - oldvalue = CELL_AT(sheet,x,y,z)->value; + cell->updated = 1; + oldvalue = cell->value; upd_clock = 0; - CELL_AT(sheet,x,y,z)->value = eval_safe(getcont(sheet, x, y, z, 2)); + cell->value = eval_safe(getcont(cell, 2)); tfree(&oldvalue); } else if (upd_clock) { - 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)); + cell->updated = 1; + upd_clock = 0; + oldvalue = cell->resvalue; + cell->resvalue = eval_safe(getcont(cell,2)); tfree(&oldvalue); } - upd_sheet=old_sheet; - upd_x=old_x; - upd_y=old_y; - upd_z=old_z; - max_eval=old_max_eval; + upd_sheet = old_sheet; + LOCATION_GETS(upd_l, old_l); + max_eval = old_max_eval; } - if (!orig_upd_clock) result=tcopy(CELL_AT(sheet,x,y,z)->value); + if (!orig_upd_clock) result = tcopy(cell->value); /*}}}*/ return result; } /*}}}*/ + /* update -- update all cells that need it */ /*{{{*/ void update(Sheet *sheet) { - int x,y,z,kp,iterating; + Location w; + Cell *cell; + int i,kp,iterating; - assert(sheet!=(Sheet*)0); - kp=0; - iterating=0; + assert(sheet != (Sheet*)0); + kp = 0; + iterating = 0; do { - sheet->clk=0; + sheet->clk = 0; if (iterating==1) { line_msg((const char*)0,_("Calculating running, press Escape to abort it")); ++iterating; } else if (iterating==0) ++iterating; - for (ALL_CELLS_IN_SHEET(sheet,x,y,z)) + for (ALL_CELLS_IN_SHEET(sheet,i,cell)) { - if (CELL_AT(sheet,x,y,z) && CELL_AT(sheet,x,y,z)->clock_t2) + if (cell && cell->clock_t2) { - 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; + cell->updated = 0; + cell->clock_t0 = 1; + cell->clock_t1 = 1; + cell->clock_t2 = 0; } } - for (ALL_CELLS_IN_SHEET(sheet,x,y,z)) + for (ALL_LOCS_IN_SHEET(sheet,w)) { - upd_clock=1; - getvalue(sheet,x,y,z); + upd_clock = 1; + getvalue(sheet, w); } - for (ALL_CELLS_IN_SHEET(sheet,x,y,z)) + for (ALL_CELLS_IN_SHEET(sheet,i,cell)) { - if (CELL_AT(sheet,x,y,z) && CELL_AT(sheet,x,y,z)->clock_t1) + if (cell && cell->clock_t1) { - 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; + tfree(&(cell->value)); + cell->value = cell->resvalue; + cell->resvalue.type = EMPTY; + cell->clock_t1 = 0; } } - upd_clock=0; + upd_clock = 0; } while (sheet->clk && !(kp=keypressed())); - if (iterating==2) line_msg((const char*)0,kp ? _("Calculation aborted") : _("Calculation finished")); - sheet->clk=0; + if (iterating == 2) line_msg((const char*)0,kp ? _("Calculation aborted") : _("Calculation finished")); + sheet->clk = 0; redraw_sheet(sheet); } /*}}}*/ /* geterror -- get malloc()ed error string */ /*{{{*/ -char *geterror(Sheet *sheet, int x, int y, int z) +char *geterror(Sheet *sheet, const Location at) { Token v; assert(sheet!=(Sheet*)0); - if ((v=getvalue(sheet,x,y,z)).type!=EEK) + if ((v = getvalue(sheet,at)).type != EEK) { tfree(&v); return (char*)0; @@ -698,186 +745,205 @@ 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) +void printvalue(char *s, size_t size, size_t chars, int quote, int scientific, int precision, Sheet *sheet, const Location at) { Token t; - assert(sheet!=(Sheet*)0); - t=getvalue(sheet,x,y,z); - printtok(s,size,chars,quote,scientific,precision,0,&t); + assert(sheet != (Sheet*)0); + t = getvalue(sheet, at); + printtok(s, size, chars, quote, scientific, precision, 0, &t); tfree(&t); } /*}}}*/ + /* getadjust -- get cell adjustment */ /*{{{*/ -Adjust getadjust(Sheet *sheet, int x, int y, int z) +Adjust getadjust(const Cell* cell) { - assert(sheet!=(Sheet*)0); - if (!CELL_IS_GOOD(sheet,x,y,z)) - { - return LEFT; - } - 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); + if (cell == NULLCELL) return LEFT; + else if (cell->adjust == AUTOADJUST) + return (cell->value.type == INT || cell->value.type == FLOAT ? RIGHT : LEFT); + else return cell->adjust; } /*}}}*/ + /* setadjust -- set cell adjustment */ /*{{{*/ -void setadjust(Sheet *sheet, int x, int y, int z, Adjust adjust) +void setadjust(Sheet *sheet, const Location at, Adjust adjust) { - assert(sheet!=(Sheet*)0); - sheet->changed=1; - resize(sheet,x,y,z); - initcell(sheet,x,y,z); - CELL_AT(sheet,x,y,z)->adjust=adjust; + assert(sheet != (Sheet*)0); + sheet->changed = 1; + initcell(sheet, at)->adjust = adjust; } /*}}}*/ /* shadow -- shadow cell by left neighbour */ /*{{{*/ -void shadow(Sheet *sheet, int x, int y, int z, int yep) +void shadow(Sheet *sheet, const Location at, int yep) { - sheet->changed=1; - initcell(sheet,x,y,z); - CELL_AT(sheet,x,y,z)->shadowed=yep; + assert(sheet != (Sheet*)0); + sheet->changed = 1; + initcell(sheet, at)->shadowed = yep; } /*}}}*/ + /* shadowed -- is cell shadowed? */ /*{{{*/ -int shadowed(Sheet *sheet, int x, int y, int z) +int shadowed(const Cell *cell) { - return (SHADOWED(sheet,x,y,z)); + return (cell != NULLCELL) && cell->shadowed; } /*}}}*/ + /* bold -- bold font */ /*{{{*/ -void bold(Sheet *sheet, int x, int y, int z, int yep) +void bold(Sheet *sheet, const Location at, int yep) { - sheet->changed=1; - initcell(sheet,x,y,z); - CELL_AT(sheet,x,y,z)->bold=yep; + assert(sheet != (Sheet*)0); + sheet->changed = 1; + initcell(sheet,at)->bold = yep; } /*}}}*/ + /* isbold -- is cell bold? */ /*{{{*/ -int isbold(Sheet *sheet, int x, int y, int z) +int isbold(const Cell* cell) { - return (CELL_IS_GOOD(sheet,x,y,z) && CELL_AT(sheet,x,y,z)->bold); + return (cell != NULLCELL) && cell->bold; } /*}}}*/ + /* underline -- underline */ /*{{{*/ -void underline(Sheet *sheet, int x, int y, int z, int yep) +void underline(Sheet *sheet, const Location at, int yep) { - sheet->changed=1; - initcell(sheet,x,y,z); - CELL_AT(sheet,x,y,z)->underline=yep; + assert(sheet != (Sheet*)0); + sheet->changed = 1; + initcell(sheet,at)->underline = yep; } /*}}}*/ + /* isunderline -- is cell underlined? */ /*{{{*/ -int underlined(Sheet *sheet, int x, int y, int z) +int underlined(const Cell *cell) { - return (CELL_IS_GOOD(sheet,x,y,z) && CELL_AT(sheet,x,y,z)->underline); + return (cell != NULLCELL) && cell->underline; } /*}}}*/ + /* lockcell -- lock cell */ /*{{{*/ -void lockcell(Sheet *sheet, int x, int y, int z, int yep) +void lockcell(Sheet *sheet, const Location at, int yep) { - sheet->changed=1; - initcell(sheet,x,y,z); - CELL_AT(sheet,x,y,z)->locked=yep; + assert(sheet != (Sheet*)0); + sheet->changed = 1; + initcell(sheet,at)->locked = yep; } /*}}}*/ + /* locked -- is cell locked? */ /*{{{*/ -int locked(Sheet *sheet, int x, int y, int z) +int locked(const Cell *cell) { - return (CELL_IS_GOOD(sheet,x,y,z) && CELL_AT(sheet,x,y,z)->locked); + return (cell != NULLCELL) && cell->locked; } /*}}}*/ + /* transparent -- is cell transparent? */ /*{{{*/ -int transparent(Sheet *sheet, int x, int y, int z) +int transparent(const Cell* cell) { - return (CELL_IS_GOOD(sheet,x,y,z) && CELL_AT(sheet,x,y,z)->transparent); + return (cell != NULLCELL) && cell->transparent; } /*}}}*/ + /* maketrans -- make cell transparent */ /*{{{*/ -void maketrans(Sheet *sheet, int x, int y, int z, int yep) +void maketrans(Sheet *sheet, const Location at, int yep) { - sheet->changed=1; - initcell(sheet,x,y,z); - CELL_AT(sheet,x,y,z)->transparent=yep; + assert(sheet != (Sheet*)0); + sheet->changed = 1; + initcell(sheet,at)->transparent = yep; } /*}}}*/ + /* igncell -- ignore cell */ /*{{{*/ -void igncell(Sheet *sheet, int x, int y, int z, int yep) +void igncell(Sheet *sheet, const Location at, int yep) { - sheet->changed=1; - initcell(sheet,x,y,z); - CELL_AT(sheet,x,y,z)->ignored=yep; + assert(sheet != (Sheet*)0); + sheet->changed = 1; + initcell(sheet,at)->ignored = yep; } /*}}}*/ + /* ignored -- is cell ignored? */ /*{{{*/ -int ignored(Sheet *sheet, int x, int y, int z) +int ignored(const Cell *cell) { - return (CELL_IS_GOOD(sheet,x,y,z) && CELL_AT(sheet,x,y,z)->ignored); + return (cell != NULLCELL) && cell->ignored; } /*}}}*/ + /* clk -- clock cell */ /*{{{*/ -void clk(Sheet *sheet, int x, int y, int z) +void clk(Sheet *sheet, const Location at) { - assert(sheet!=(Sheet*)0); - assert(x>=0 && xdimx); - assert(y>=0 && ydimy); - assert(z>=0 && zdimz); - if (CELL_AT(sheet,x,y,z)) + assert(sheet != (Sheet*)0); + assert(IN_OCTANT(at)); + assert(LOC_WITHIN(sheet,at)); + if (CELL_AT(sheet,at)) { - CELL_AT(sheet,x,y,z)->clock_t2=1; - sheet->clk=1; + CELL_AT(sheet,at)->clock_t2 = 1; + sheet->clk = 1; } } /*}}}*/ + /* setscientific -- cell value should be displayed in scientific notation */ /*{{{*/ -void setscientific(Sheet *sheet, int x, int y, int z, int yep) +void setscientific(Sheet *sheet, const Location at, int yep) { - sheet->changed=1; - resize(sheet,x,y,z); - initcell(sheet,x,y,z); - CELL_AT(sheet,x,y,z)->scientific=yep; + assert(sheet != (Sheet*)0); + sheet->changed = 1; + initcell(sheet,at)->scientific = yep; } /*}}}*/ + /* getscientific -- should value be displayed in scientific notation? */ /*{{{*/ -int getscientific(Sheet *sheet, int x, int y, int z) +int getscientific(const Cell *cell ) { - if (CELL_IS_GOOD(sheet,x,y,z)) return CELL_AT(sheet,x,y,z)->scientific; - else return DEF_SCIENTIFIC; + return (cell == NULLCELL) ? DEF_SCIENTIFIC : cell->scientific; } /*}}}*/ + /* setprecision -- set cell precision */ /*{{{*/ -void setprecision(Sheet *sheet, int x, int y, int z, int precision) +void setprecision(Sheet *sheet, const Location at, int precision) { - sheet->changed=1; - resize(sheet,x,y,z); - initcell(sheet,x,y,z); - CELL_AT(sheet,x,y,z)->precision=precision; + assert(sheet != (Sheet*)0); + sheet->changed = 1; + initcell(sheet,at)->precision = precision; } /*}}}*/ + /* getprecision -- get cell precision */ /*{{{*/ -int getprecision(Sheet *sheet, int x, int y, int z) +int getprecision(const Cell *cell) { - 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; + if (cell == NULLCELL || cell->precision == -1) return def_precision; + return cell->precision; } /*}}}*/ + /* getlabel -- get cell label */ /*{{{*/ -const char *getlabel(Sheet *sheet, int x, int y, int z) +const char *getlabel(const Cell* cell) { - 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); + if (cell == NULLCELL || cell->label == (char*)0) return ""; + return cell->label; } /*}}}*/ +/* getmarkstate -- find out where in the marking cycle the sheet is */ /*{{{*/ +MarkState getmarkstate(Sheet *sheet) { + if (sheet == (Sheet*)0) return MARK_CYCLE; + return sheet->marking; +} + /* setlabel -- set cell label */ /*{{{*/ -void setlabel(Sheet *sheet, int x, int y, int z, const char *buf, int update) +void setlabel(Sheet *sheet, const Location at, const char *buf, int update) { - sheet->changed=1; - resize(sheet,x,y,z); - initcell(sheet,x,y,z); - 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; + Cell *cell; + + assert(sheet != (Sheet*)0); + sheet->changed = 1; + cell = initcell(sheet, at); + if (cell->label != (char*)0) free(cell->label); + if (*buf == '\0') cell->label = (char*)0; + else cell->label = strcpy(malloc(strlen(buf)+1), buf); if (update) { cachelabels(sheet); @@ -885,6 +951,7 @@ void setlabel(Sheet *sheet, int x, int y, int z, const char *buf, int update) } } /*}}}*/ + /* findlabel -- return cell location for a given label */ /*{{{*/ Token findlabel(Sheet *sheet, const char *label) { @@ -905,63 +972,48 @@ Token findlabel(Sheet *sheet, const char *label) } if (run) { - result.type=LOCATION; - result.u.location[0]=run->x; - result.u.location[1]=run->y; - result.u.location[2]=run->z; + result.type = LOCATION; + LOCATION_GETS(result.u.location, run->location); } else { - result.type=EEK; - result.u.err=mystrmalloc(_("No such label")); + result.type = EEK; + result.u.err = mystrmalloc(_("No such label")); } return result; } /*}}}*/ + /* relabel -- search and replace for labels */ /*{{{*/ -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) { /* variables */ /*{{{*/ Token **run; + ContentVariety v; + Cell *cell; /*}}}*/ /* asserts */ /*{{{*/ - assert(sheet!=(Sheet*)0); assert(oldlabel!=(const char*)0); assert(newlabel!=(const char*)0); - assert(x>=0); - assert(y>=0); - assert(z>=0); /*}}}*/ - if (CELL_IS_GOOD(sheet,x,y,z)) - { - if (CELL_AT(sheet,x,y,z)->contents != EMPTY_TVEC) - { - for (run=CELL_AT(sheet,x,y,z)->contents; *run!=NULLTOKEN; ++run) - { - if ((*run)->type==LIDENT && strcmp((*run)->u.lident,oldlabel)==0) - { - free((*run)->u.lident); - (*run)->u.lident=mystrmalloc(newlabel); - } - } - } - if (CELL_AT(sheet,x,y,z)->ccontents != EMPTY_TVEC) - { - for (run=CELL_AT(sheet,x,y,z)->ccontents; *run!=NULLTOKEN; ++run) - { - if ((*run)->type==LIDENT && strcmp((*run)->u.lident,oldlabel)==0) - { - free((*run)->u.lident); - (*run)->u.lident=mystrmalloc(newlabel); - } - } - } - } + if (!LOC_WITHIN(sheet, at)) return; + cell = CELL_AT(sheet, at); + if (cell != NULLCELL) + for (v = BASE; v <= ITERATIVE; ++v) + if (cell->contents[v] != EMPTY_TVEC) + for (run = cell->contents[v]; *run != NULLTOKEN; ++run) + if ((*run)->type==LIDENT && strcmp((*run)->u.lident, oldlabel)==0) + { + free((*run)->u.lident); + (*run)->u.lident = mystrmalloc(newlabel); + } cachelabels(sheet); forceupdate(sheet); } /*}}}*/ + /* savexdr -- save a spread sheet in XDR */ /*{{{*/ const char *savexdr(Sheet *sheet, const char *name, unsigned int *count) { @@ -998,10 +1050,10 @@ const char *savexdr(Sheet *sheet, const char *name, unsigned int *count) } for (y=sheet->dimy-1; y>=0; --y) { - if (CELL_AT(sheet,x,y,z)!=NULLCELL) + if (CELL_ATC(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,CELL_AT(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_ATC(sheet,x,y,z))==0) { xdr_destroy(&xdrs); (void)fclose(fp); @@ -1018,14 +1070,17 @@ const char *savexdr(Sheet *sheet, const char *name, unsigned int *count) } /*}}}*/ /* savetbl -- save as tbl tyble */ /*{{{*/ -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 *savetbl(Sheet *sheet, const char *name, int body, + const Location beg, const Location end, + unsigned int *count) { /* variables */ /*{{{*/ FILE *fp=(FILE*)0; /* cause run time error */ - int x,y,z; + Location w; char buf[1024]; char num[20]; char fullname[PATH_MAX]; + Cell *cw; /*}}}*/ /* asserts */ /*{{{*/ @@ -1033,14 +1088,17 @@ const char *savetbl(Sheet *sheet, const char *name, int body, int x1, int y1, in 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); fullname[sizeof(fullname)-1]='\0'; @@ -1050,26 +1108,18 @@ const char *savetbl(Sheet *sheet, const char *name, int body, int x1, int y1, in } /*}}}*/ else if (fputs_close(".TS\n",fp)==EOF) return strerror(errno); - for (y=y1; y<=y2; ++y) + for (w[Y]=beg[Y]; w[Y]<=end[Y]; ++(w[Y])) { /* print format */ /*{{{*/ - if (y>y1 && fputs_close(".T&\n",fp)==EOF) return strerror(errno); - for (x=x1; x<=x2; ++x) + if (w[Y] > beg[Y] && fputs_close(".T&\n",fp)==EOF) return strerror(errno); + for (w[X]=beg[X]; w[X]<=end[X]; ++(w[X])) { - if (x>x1 && fputc_close(' ',fp)==EOF) return strerror(errno); - if (shadowed(sheet,x,y,z)) - { - if (fputc_close('s',fp)==EOF) return strerror(errno); - } - if (isbold(sheet,x,y,z)) - { - if (fputc_close('b',fp)==EOF) return strerror(errno); - } - if (underlined(sheet,x,y,z)) - { - if (fputc_close('u',fp)==EOF) return strerror(errno); - } - else switch (getadjust(sheet,x,y,z)) + if (w[X] > beg [X] && fputc_close(' ',fp)==EOF) return strerror(errno); + cw = CELL_AT(sheet,w); + if (shadowed(cw) && fputc_close('s',fp)==EOF) return strerror(errno); + if (isbold(cw) && fputc_close('b',fp)==EOF) return strerror(errno); + if (underlined(cw) && fputc_close('u',fp)==EOF) return strerror(errno); + switch (getadjust(cw)) { case LEFT: if (fputc_close('l',fp)==EOF) return strerror(errno); break; case RIGHT: if (fputc_close('r',fp)==EOF) return strerror(errno); break; @@ -1080,17 +1130,19 @@ const char *savetbl(Sheet *sheet, const char *name, int body, int x1, int y1, in if (fputs_close(".\n",fp)==EOF) return strerror(errno); /*}}}*/ /* print contents */ /*{{{*/ - for (x=x1; x<=x2; ++x) + for (w[X]=beg[X]; w[X]<=end[X]; ++(w[X])) { - if (!shadowed(sheet,x,y,z)) + cw = CELL_AT(sheet,w); + if (!shadowed(cw)) { - if (x>x1 && fputc_close('\t',fp)==EOF) return strerror(errno); - if (CELL_AT(sheet,x,y,z)!=NULLCELL) + if (w[X] > beg[X] && fputc_close('\t',fp)==EOF) return strerror(errno); + if (cw != NULLCELL) { char *bufp; - 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(cw), + getprecision(cw), sheet, w); + if (transparent(cw)) { if (fputs_close(buf,fp)==EOF) return strerror(errno); } @@ -1108,13 +1160,13 @@ const char *savetbl(Sheet *sheet, const char *name, int body, int x1, int y1, in } case '.': { - if (x==x1 && bufp==buf && (fputc_close('\\',fp)==EOF || fputc_close('&',fp)==EOF)) return strerror(errno); + if (w[X] == beg[X] && bufp==buf && (fputc_close('\\',fp)==EOF || fputc_close('&',fp)==EOF)) return strerror(errno); if (fputc_close('.',fp)==EOF) return strerror(errno); break; } case '\'': { - if (x==x1 && bufp==buf && (fputc_close('\\',fp)==EOF || fputc_close('&',fp)==EOF)) return strerror(errno); + if (w[X] == beg[X] && bufp==buf && (fputc_close('\\',fp)==EOF || fputc_close('&',fp)==EOF)) return strerror(errno); if (fputc_close('\'',fp)==EOF) return strerror(errno); break; } @@ -1140,7 +1192,7 @@ const char *savetbl(Sheet *sheet, const char *name, int body, int x1, int y1, in if (!body) { if (fputs_close(".TE\n",fp)==EOF) return strerror(errno); - if (zx1) if (fputc_close(sep,fp)==EOF) return strerror(errno); - if (CELL_AT(sheet,x,y,z)!=NULLCELL) + if (w[X]>beg[X]) if (fputc_close(sep,fp)==EOF) return strerror(errno); + cw = CELL_AT(sheet,w); + if (cw != 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 (CELL_AT(sheet,x,y,z)->value.type==STRING && fputc_close('"',fp)==EOF) + printvalue(buf, 255*UTF8SZ+1, 255, 0, getscientific(cw), + getprecision(cw), sheet, w); + if (cw->value.type == STRING && fputc_close('"',fp)==EOF) { free(buf); return strerror(errno); @@ -1247,32 +1315,39 @@ const char *savecsv(Sheet *sheet, const char *name, char sep, int x1, int y1, in } } free(buf); - if (CELL_AT(sheet,x,y,z)->value.type==STRING && fputc_close('"',fp)==EOF) return strerror(errno); + if (cw->value.type==STRING && fputc_close('"',fp)==EOF) return strerror(errno); } ++*count; } if (fputc_close('\n',fp)==EOF) return strerror(errno); } - if (zdimz-1; z>=0; --z) { @@ -1280,103 +1355,81 @@ 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 (CELL_AT(sheet,x,y,z)!=NULLCELL) + if (y == 0 && columnwidth(sheet,x,z) != DEF_COLUMNWIDTH) + fprintf(fp,"W%d %d %d\n",x,z,columnwidth(sheet,x,z)); + cell = CELL_ATC(sheet,x,y,z); + if (cell != NULLCELL) { fprintf(fp,"C%d %d %d ",x,y,z); - 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 (cell->adjust != AUTOADJUST) + fprintf(fp,"A%c ","lrc"[cell->adjust]); + if (cell->label) fprintf(fp,"L%s ", cell->label); + if (cell->precision != -1) + fprintf(fp,"P%d ", cell->precision); + if (cell->shadowed) fprintf(fp,"S "); + if (cell->bold) fprintf(fp,"B "); + if (cell->underline) fprintf(fp,"U "); + if (cell->scientific != DEF_SCIENTIFIC) fprintf(fp,"E "); + if (cell->locked) fprintf(fp,"C "); + if (cell->transparent) fprintf(fp,"T "); + for (v = BASE; v <= ITERATIVE; ++v) + if (cell->contents[v]) + { + char buf[4096]; - if (fputc_close(':',fp)==EOF) return strerror(errno); - 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 (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,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); - ++*count; + if (fputs_close(saveport_contentleader[v], fp) == EOF) + return strerror(errno); + print(buf, sizeof(buf), 0, 1, cell->scientific, cell->precision, + cell->contents[v]); + if (fputs_close(buf, fp) == EOF) return strerror(errno); + } } } } } - if (fclose(fp)==EOF) return strerror(errno); + if (fclose(fp) == EOF) return strerror(errno); return (const char*)0; } /*}}}*/ + /* loadport -- load from portable text */ /*{{{*/ const char *loadport(Sheet *sheet, const char *name) { /* variables */ /*{{{*/ static char errbuf[80]; FILE *fp; - int x,y,z; + Location loc; + int cx, cz; char buf[4096]; int line; const char *ns,*os; const char *err; - int precision; - char *label; - Adjust adjust; - int shadowed; - int bold; - int underline; - int scientific; - int locked; - int transparent; - int ignored; - Token **contents,**ccontents; + Cell loaded; int width; /*}}}*/ - if ((fp=fopen(name,"r"))==(FILE*)0) return strerror(errno); - freesheet(sheet,0); - err=(const char*)0; - line=1; - while (fgets(buf,sizeof(buf),fp)!=(char*)0) + if ((fp=fopen(name,"r")) == (FILE*)0) return strerror(errno); + freesheet(sheet, 0); + err = (const char*)0; + line = 1; + while (fgets(buf,sizeof(buf),fp) != (char*)0) { /* remove nl */ /*{{{*/ - width=strlen(buf); - if (width>0 && buf[width-1]=='\n') buf[--width]='\0'; + width = strlen(buf); + if (width>0 && buf[width-1]=='\n') buf[--width] = '\0'; /*}}}*/ switch (buf[0]) { /* C -- parse cell */ /*{{{*/ case 'C': { - int cc=0; + ContentVariety cv = BASE, nextcv = BASE; - if (width>0 && buf[width-1]=='\\') { buf[--width]='\0'; cc=1; } - adjust=AUTOADJUST; - precision=-1; - label=(char*)0; - contents=(Token**)0; - ccontents=(Token**)0; - shadowed=0; - bold=0; - underline=0; - scientific=DEF_SCIENTIFIC; - locked=0; - transparent=0; - ignored=0; + if (width > 0 && buf[width-1]=='\\') { buf[--width]='\0'; ++nextcv; } + preparecell(&loaded); /* parse x y and z */ /*{{{*/ os=ns=buf+1; - x=posnumber(os,&ns); + loc[X] = posnumber(os,&ns); if (os==ns) { sprintf(errbuf,_("Parse error for x position in line %d"),line); @@ -1385,7 +1438,7 @@ const char *loadport(Sheet *sheet, const char *name) } while (*ns==' ') ++ns; os=ns; - y=posnumber(os,&ns); + loc[Y] = posnumber(os,&ns); if (os==ns) { sprintf(errbuf,_("Parse error for y position in line %d"),line); @@ -1394,7 +1447,7 @@ const char *loadport(Sheet *sheet, const char *name) } while (*ns==' ') ++ns; os=ns; - z=posnumber(os,&ns); + loc[Z] = posnumber(os,&ns); if (os==ns) { sprintf(errbuf,_("Parse error for z position in line %d"),line); @@ -1414,9 +1467,9 @@ const char *loadport(Sheet *sheet, const char *name) ++ns; switch (*ns) { - case 'l': adjust=LEFT; ++ns; break; - case 'r': adjust=RIGHT; ++ns; break; - case 'c': adjust=CENTER; ++ns; break; + case 'l': loaded.adjust=LEFT; ++ns; break; + case 'r': loaded.adjust=RIGHT; ++ns; break; + case 'c': loaded.adjust=CENTER; ++ns; break; default: sprintf(errbuf,_("Parse error for adjustment in line %d"),line); err=errbuf; goto eek; } break; @@ -1431,7 +1484,7 @@ const char *loadport(Sheet *sheet, const char *name) ++ns; while (*ns && *ns!=' ') { *p=*ns; ++p; ++ns; } *p='\0'; - label=mystrmalloc(buf); + loaded.label=mystrmalloc(buf); break; } /*}}}*/ @@ -1439,7 +1492,7 @@ const char *loadport(Sheet *sheet, const char *name) case 'P': { os=++ns; - precision=posnumber(os,&ns); + loaded.precision=posnumber(os,&ns); if (os==ns) { sprintf(errbuf,_("Parse error for precision in line %d"),line); @@ -1452,42 +1505,45 @@ const char *loadport(Sheet *sheet, const char *name) /* S -- shadowed */ /*{{{*/ case 'S': { - if (x==0) + if (loc[X]==0) { - sprintf(errbuf,_("Trying to shadow cell (%d,%d,%d) in line %d"),x,y,z,line); + sprintf(errbuf,_("Trying to shadow cell (%d,%d,%d) in line %d"), + loc[X],loc[Y],loc[Z],line); err=errbuf; goto eek; } ++ns; - shadowed=1; + loaded.shadowed=1; break; } /*}}}*/ /* U -- underline */ /*{{{*/ case 'U': { - if (x==0) + if (loc[X]==0) { - sprintf(errbuf,_("Trying to underline cell (%d,%d,%d) in line %d"),x,y,z,line); + sprintf(errbuf,_("Trying to underline cell (%d,%d,%d) in line %d"), + loc[X],loc[Y],loc[Z],line); err=errbuf; goto eek; } ++ns; - underline=1; + loaded.underline=1; break; } /*}}}*/ /* B -- bold */ /*{{{*/ case 'B': { - if (x==0) + if (loc[X]==0) { - sprintf(errbuf,_("Trying to bold cell (%d,%d,%d) in line %d"),x,y,z,line); + sprintf(errbuf,_("Trying to bold cell (%d,%d,%d) in line %d"), + loc[X], loc[Y], loc[Z], line); err=errbuf; goto eek; } ++ns; - bold=1; + loaded.bold=1; break; } /*}}}*/ @@ -1495,7 +1551,7 @@ const char *loadport(Sheet *sheet, const char *name) case 'E': { ++ns; - scientific=1; + loaded.scientific=1; break; } /*}}}*/ @@ -1503,7 +1559,7 @@ const char *loadport(Sheet *sheet, const char *name) case 'O': { ++ns; - locked=1; + loaded.locked=1; break; } /*}}}*/ @@ -1511,7 +1567,7 @@ const char *loadport(Sheet *sheet, const char *name) case 'T': { ++ns; - transparent=1; + loaded.transparent=1; break; } /*}}}*/ @@ -1519,7 +1575,7 @@ const char *loadport(Sheet *sheet, const char *name) case 'I': { ++ns; - ignored=1; + loaded.ignored=1; break; } /*}}}*/ @@ -1533,52 +1589,30 @@ const char *loadport(Sheet *sheet, const char *name) } } while (*ns!=':' && *ns!='\0'); /*}}}*/ - /* convert remaining string into token sequence */ /*{{{*/ - if (*ns) + if (*ns) ++ns; + /* convert remaining string(s) into token sequence */ /*{{{*/ + while (true) { - ++ns; - contents=scan(&ns); - if (contents==(Token**)0) + loaded.contents[cv] = scan(&ns); + if (loaded.contents[cv]==(Token**)0) { - tvecfree(contents); sprintf(errbuf,_("Expression syntax error in line %d"),line); err=errbuf; goto eek; } - } - /*}}}*/ - /* convert remaining string into token sequence */ /*{{{*/ - if (cc && fgets(buf,sizeof(buf),fp)!=(char*)0) - { - ++line; - /* remove nl */ /*{{{*/ - width=strlen(buf); + if (nextcv == cv) break; + cv = nextcv; + if (fgets(buf, sizeof(buf), fp) == (char*)0) break; + ++line; + width = strlen(buf); if (width>0 && buf[width-1]=='\n') buf[width-1]='\0'; - /*}}}*/ - ns=buf; - ccontents=scan(&ns); - if (ccontents==(Token**)0) - { - tvecfree(ccontents); - sprintf(errbuf,_("Expression syntax error in line %d"),line); - err=errbuf; - goto eek; - } + /* More content? */ + if (width > 0 && buf[width-1]=='\\') { buf[--width]='\0'; ++nextcv; } + ns = buf; } /*}}}*/ - initcell(sheet,x,y,z); - 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; + + copycell(&loaded, sheet, loc); break; } /*}}}*/ @@ -1587,7 +1621,7 @@ const char *loadport(Sheet *sheet, const char *name) { /* parse x and z */ /*{{{*/ os=ns=buf+1; - x=posnumber(os,&ns); + cx=posnumber(os,&ns); if (os==ns) { sprintf(errbuf,_("Parse error for x position in line %d"),line); @@ -1596,7 +1630,7 @@ const char *loadport(Sheet *sheet, const char *name) } while (*ns==' ') ++ns; os=ns; - z=posnumber(os,&ns); + cz=posnumber(os,&ns); if (os==ns) { sprintf(errbuf,_("Parse error for z position in line %d"),line); @@ -1615,7 +1649,7 @@ const char *loadport(Sheet *sheet, const char *name) goto eek; } /*}}}*/ - setwidth(sheet,x,z,width); + setwidth(sheet,cx,cz,width); break; } /*}}}*/ @@ -1641,16 +1675,18 @@ const char *loadport(Sheet *sheet, const char *name) return err; } /*}}}*/ + /* loadxdr -- load a spread sheet in XDR */ /*{{{*/ const char *loadxdr(Sheet *sheet, const char *name) { /* variables */ /*{{{*/ FILE *fp; XDR xdrs; - int x,y,z; + Location w; int width; int u; int olderror; + Cell *nc; /*}}}*/ if ((fp=fopen(name,"r"))==(FILE*)0) return strerror(errno); @@ -1673,31 +1709,33 @@ const char *loadxdr(Sheet *sheet, const char *name) /* 0 -- column width element */ /*{{{*/ case 0: { - if (xdr_column(&xdrs,&x,&z,&width)==0) + if (xdr_column(&xdrs,&(w[X]),&(w[Z]),&width)==0) { olderror=errno; xdr_destroy(&xdrs); (void)fclose(fp); return strerror(olderror); } - setwidth(sheet,x,z,width); + setwidth(sheet,w[X],w[Z],width); break; } /*}}}*/ /* 1 -- cell element */ /*{{{*/ case 1: { - if (xdr_int(&xdrs,&x)==0 || xdr_int(&xdrs,&y)==0 || xdr_int(&xdrs,&z)==0) + if (xdr_int(&xdrs,&(w[X]))==0 || + xdr_int(&xdrs,&(w[Y]))==0 || + xdr_int(&xdrs,&(w[Z]))==0) { olderror=errno; xdr_destroy(&xdrs); (void)fclose(fp); return strerror(olderror); } - initcell(sheet,x,y,z); - if (xdr_cell(&xdrs,CELL_AT(sheet,x,y,z))==0) + nc = initcell(sheet, w); + if (xdr_cell(&xdrs, nc)==0) { - freecell(sheet,x,y,z); + freecell(sheet, w); olderror=errno; xdr_destroy(&xdrs); (void)fclose(fp); @@ -1727,6 +1765,7 @@ const char *loadxdr(Sheet *sheet, const char *name) return (const char*)0; } /*}}}*/ + /* loadcsv -- load/merge CSVs */ /*{{{*/ const char *loadcsv(Sheet *sheet, const char *name) { @@ -1734,7 +1773,7 @@ const char *loadcsv(Sheet *sheet, const char *name) FILE *fp; Token **t; const char *err; - int line,x; + Location where; char ln[4096]; const char *str; double value; @@ -1744,7 +1783,8 @@ const char *loadcsv(Sheet *sheet, const char *name) if ((fp=fopen(name,"r"))==(FILE*)0) return strerror(errno); err=(const char*)0; - for (x=0,line=1; fgets(ln,sizeof(ln),fp); ++line) + LOCATION_GETS(where, sheet->cur); + for (; fgets(ln,sizeof(ln),fp); ++(where[Y])) { const char *s; const char *cend; @@ -1760,7 +1800,7 @@ const char *loadcsv(Sheet *sheet, const char *name) } s=cend=ln; - x=0; + where[X] = sheet->cur[X]; do { t=malloc(2*sizeof(Token*)); @@ -1771,7 +1811,7 @@ const char *loadcsv(Sheet *sheet, const char *name) { t[0]->type=INT; t[0]->u.integer=lvalue; - putcont(sheet, sheet->curx+x, sheet->cury+line-1, sheet->curz, t, 0); + putcont(sheet, where, t, BASE); } /*}}}*/ else @@ -1781,7 +1821,7 @@ const char *loadcsv(Sheet *sheet, const char *name) { t[0]->type=FLOAT; t[0]->u.flt=value; - putcont(sheet, sheet->curx+x, sheet->cury+line-1, sheet->curz, t, 0); + putcont(sheet, where, t, BASE); } /*}}}*/ else @@ -1791,7 +1831,7 @@ const char *loadcsv(Sheet *sheet, const char *name) { t[0]->type=STRING; t[0]->u.string=mystrmalloc(str); - putcont(sheet, sheet->curx+x, sheet->cury+line-1, sheet->curz, t, 0); + putcont(sheet, where, t, BASE); } /*}}}*/ else @@ -1807,14 +1847,16 @@ const char *loadcsv(Sheet *sheet, const char *name) } } } - } while (s!=cend ? s=cend,++x,1 : 0); + } while (s!=cend ? s=cend,++(where[X]),1 : 0); } fclose(fp); return err; } /*}}}*/ + /* insertcube -- insert a block */ /*{{{*/ -void insertcube(Sheet *sheet, int x1, int y1, int z1, int x2, int y2, int z2, Direction ins) +void insertcube(Sheet *sheet, const Location beg, const Location end, + Direction ins) { /* variables */ /*{{{*/ int x,y,z; @@ -1827,12 +1869,12 @@ void insertcube(Sheet *sheet, int x1, int y1, int z1, int x2, int y2, int z2, Di { int right; - right=sheet->dimx+x2-x1; - for (z=z1; z<=z2; ++z) for (y=y1; y<=y2; ++y) for (x=right; x>x2; --x) + right=sheet->dimx+end[X]-beg[X]; + for (z=beg[Z]; z<=end[Z]; ++z) for (y=beg[Y]; y<=end[Y]; ++y) for (x=right; x>end[X]; --x) { resize(sheet,x,y,z); - 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; + CELL_ATC(sheet,x,y,z) = CELL_ATC(sheet,x-(end[X]-beg[X]+1),y,z); + CELL_ATC(sheet,x-(end[X]-beg[X]+1),y,z) = NULLCELL; } break; } @@ -1842,12 +1884,12 @@ void insertcube(Sheet *sheet, int x1, int y1, int z1, int x2, int y2, int z2, Di { int down; - down=sheet->dimy+y2-y1; - for (z=z1; z<=z2; ++z) for (x=x1; x<=x2; ++x) for (y=down; y>y2; --y) + down=sheet->dimy+end[Y]-beg[Y]; + for (z=beg[Z]; z<=end[Z]; ++z) for (x=beg[X]; x<=end[X]; ++x) for (y=down; y>end[Y]; --y) { resize(sheet,x,y,z); - 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; + CELL_ATC(sheet,x,y,z) = CELL_ATC(sheet,x,y-(end[Y]-beg[Y]+1),z); + CELL_ATC(sheet,x,y-(end[Y]-beg[Y]+1),z) = NULLCELL; } break; } @@ -1857,12 +1899,12 @@ void insertcube(Sheet *sheet, int x1, int y1, int z1, int x2, int y2, int z2, Di { int bottom; - bottom=sheet->dimz+z2-z1; - for (y=y1; y<=y2; ++y) for (x=x1; x<=x2; ++x) for (z=bottom; z>z2; --z) + bottom=sheet->dimz+end[Z]-beg[Z]; + for (y=beg[Y]; y<=end[Y]; ++y) for (x=beg[X]; x<=end[X]; ++x) for (z=bottom; z>end[Z]; --z) { resize(sheet,x,y,z); - 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; + CELL_ATC(sheet,x,y,z) = CELL_ATC(sheet,x,y,z-(end[Z]-beg[Z]+1)); + CELL_ATC(sheet,x,y,z-(end[Z]-beg[Z]+1)) = NULLCELL; } break; } @@ -1876,60 +1918,75 @@ void insertcube(Sheet *sheet, int x1, int y1, int z1, int x2, int y2, int z2, Di forceupdate(sheet); } /*}}}*/ + /* deletecube -- delete a block */ /*{{{*/ -void deletecube(Sheet *sheet, int x1, int y1, int z1, int x2, int y2, int z2, Direction del) +void deletecube(Sheet *sheet, const Location beg, const Location end, + Direction del) { /* variables */ /*{{{*/ - int x,y,z; + Location w; + Location fm; /*}}}*/ /* free cells in marked block */ /*{{{*/ - for (x=x1; x<=x2; ++x) - for (y=y1; y<=y2; ++y) - for (z=z1; z<=z2; ++z) - freecell(sheet,x,y,z); + for (w[X]=beg[X]; w[X]<=end[X]; ++w[X]) + for (w[Y]=beg[Y]; w[Y]<=end[Y]; ++w[Y]) + for (w[Z]=beg[Z]; w[Z]<=end[Z]; ++w[Z]) + freecell(sheet, w); /*}}}*/ switch (del) { /* IN_X */ /*{{{*/ case IN_X: { - for (z=z1; z<=z2; ++z) for (y=y1; y<=y2; ++y) for (x=x1; x<=sheet->dimx-(x2-x1+1); ++x) - { - if (x+(x2-x1+1)dimx && ydimy && zdimz) - { - 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; - } - } + for (w[Z]=beg[Z]; w[Z]<=end[Z]; ++w[Z]) + for (w[Y]=beg[Y]; w[Y]<=end[Y]; ++w[Y]) + for (w[X]=beg[X]; w[X]<=sheet->dimx-(end[X]-beg[X]+1); ++w[X]) + { + LOCATION_GETS(fm, w); + fm[X] += end[X]-beg[X]+1; + if (LOC_WITHIN(sheet,fm)) + { + CELL_AT(sheet,w) = CELL_AT(sheet,fm); + CELL_AT(sheet,fm) = NULLCELL; + } + } break; } /*}}}*/ /* IN_Y */ /*{{{*/ case IN_Y: { - for (z=z1; z<=z2; ++z) for (x=x1; x<=x2; ++x) for (y=y1; y<=sheet->dimy-(y2-y1+1); ++y) - { - if (xdimx && y+(y2-y1+1)dimy && zdimz) - { - 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; - } - } + for (w[Z]=beg[Z]; w[Z]<=end[Z]; ++w[Z]) + for (w[X]=beg[X]; w[X]<=end[X]; ++w[X]) + for (w[Y]=beg[Y]; w[Y]<=sheet->dimy-(end[Y]-beg[Y]+1); ++w[Y]) + { + LOCATION_GETS(fm, w); + fm[Y] += end[Y]-beg[Y]+1; + if (LOC_WITHIN(sheet,fm)) + { + CELL_AT(sheet,w) = CELL_AT(sheet,fm); + CELL_AT(sheet,fm) = NULLCELL; + } + } break; } /*}}}*/ /* IN_Z */ /*{{{*/ case IN_Z: { - for (y=y1; y<=y2; ++y) for (x=x1; x<=x2; ++x) for (z=z1; z<=sheet->dimz-(z2-z1+1); ++z) - { - if (xdimx && ydimy && z+(z2-z1+1)dimz) - { - 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; - } - } + for (w[Y]=beg[Y]; w[Y]<=end[Y]; ++w[Y]) + for (w[X]=beg[X]; w[X]<=end[X]; ++w[X]) + for (w[Z]=beg[Z]; w[Z]<=sheet->dimz-(end[Z]-beg[Z]+1); ++w[Z]) + { + LOCATION_GETS(fm, w); + fm[Z] += end[Z]-beg[Z]+1; + if (LOC_WITHIN(sheet,fm)) + { + CELL_AT(sheet,w) = CELL_AT(sheet,fm); + CELL_AT(sheet,fm) = NULLCELL; + } + } break; } /*}}}*/ @@ -1942,43 +1999,39 @@ void deletecube(Sheet *sheet, int x1, int y1, int z1, int x2, int y2, int z2, Di forceupdate(sheet); } /*}}}*/ + /* moveblock -- move a block */ /*{{{*/ -void moveblock(Sheet *sheet, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3, int copy) +void moveblock(Sheet *sheet, const Location beg, const Location end, + const Location dest, int copy) { /* variables */ /*{{{*/ - int dirx, diry, dirz; - int widx, widy, widz; - int x, y, z; - int xf, xt, yf, yt, zf, zt; + Location wid, dir, fm, to, get, go; + Dimensions dim; /*}}}*/ - if (x1==x3 && y1==y3 && z1==z3) return; - widx=(x2-x1); - widy=(y2-y1); - widz=(z2-z1); - if (x3>x1) { dirx=-1; xf=widx; xt=-1; } else { dirx=1; xf=0; xt=widx+1; } - if (y3>y1) { diry=-1; yf=widy; yt=-1; } else { diry=1; yf=0; yt=widy+1; } - if (z3>z1) { dirz=-1; zf=widz; zt=-1; } else { dirz=1; zf=0; zt=widz+1; } - for (x=xf; x!=xt; x+=dirx) - for (y=yf; y!=yt; y+=diry) - for (z=zf; z!=zt; z+=dirz) + if (SAME_LOC(beg, dest)) return; + LOCATION_GETS(wid, end); + LOCATION_SUB(wid, beg); + for (dim = X; dim < HYPER; ++dim) { + if (dest[dim] > beg[dim]) + { dir[dim] = -1; fm[dim] = wid[dim]; to[dim] = beg[dim]-1; } + else + { dir[dim] = 1; fm[dim] = 0; to[dim] = beg[dim]+wid[dim]+1; } + } + for (get[Z] = beg[Z]+fm[Z], go[Z] = dest[Z]+fm[Z]; + get[Z] != to[Z]; get[Z] += dir[Z], go[Z] += dir[Z]) + for (get[Y] = beg[Y]+fm[Y], go[Y] = dest[Y]+fm[Y]; + get[Y] != to[Y]; get[Y] += dir[Y], go[Y] += dir[Y]) + for (get[X] = beg[X]+fm[X], go[X] = dest[X]+fm[X]; + get[X] != to[X]; get[X] += dir[X], go[X] += dir[X]) { - if (copy) - { - copycell(sheet,x1+x,y1+y,z1+z,sheet,x3+x,y3+y,z3+z); - } + if (!LOC_WITHIN(sheet, get)) freecell(sheet, go); + else if (copy) { copycell(CELL_AT(sheet, get), sheet, go); } else { - if (x1+xdimx && y1+ydimy && z1+zdimz) - { - resize(sheet,x3+x,y3+y,z3+z); - 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 - { - freecell(sheet,x3+x,y3+y,z3+z); - } + resize(sheet, go[X], go[Y], go[Z]); + CELL_AT(sheet, go) = CELL_AT(sheet, get); + CELL_AT(sheet, get) = NULLCELL; } } sheet->changed=1; @@ -1986,6 +2039,7 @@ void moveblock(Sheet *sheet, int x1, int y1, int z1, int x2, int y2, int z2, int forceupdate(sheet); } /*}}}*/ + /* sortblock -- sort a block */ /*{{{*/ /* Notes */ /*{{{*/ /* @@ -1996,15 +2050,21 @@ You can have multiple sort keys which all have the same direction and you can sort a cube plane-wise. */ /*}}}*/ -const char *sortblock(Sheet *sheet, int x1, int y1, int z1, int x2, int y2, int z2, Direction dir, Sortkey *sk, size_t sklen) +const char *sortblock(Sheet *sheet, const Location beg, const Location end, + Direction dir, Sortkey *sk, size_t sklen) { /* variables */ /*{{{*/ + int x1, y1, z1, x2, y2, z2; int x,y,z; int incx=0,incy=0,incz=0; int distx,disty,distz; int i,r=-3,norel,work; /*}}}*/ + /* unpack corners */ + x1 = beg[X]; y1 = beg[Y]; z1 = beg[Z]; + x2 = end[X]; y2 = end[Y]; z2 = end[Z]; + /* asserts */ /*{{{*/ assert(sklen>0); assert(x1>=0); @@ -2058,37 +2118,39 @@ const char *sortblock(Sheet *sheet, int x1, int y1, int z1, int x2, int y2, int else return (const char*)0; } /*}}}*/ + /* mirrorblock -- mirror a block */ /*{{{*/ -void mirrorblock(Sheet *sheet, int x1, int y1, int z1, int x2, int y2, int z2, Direction dir) +void mirrorblock(Sheet *sheet, const Location beg, const Location end, + Direction dir) { switch (dir) { case IN_X: /* left-right */ /*{{{*/ { - int x,middle=(x2-x1+1)/2; + int x,middle=(end[X]-beg[X]+1)/2; for (x=0; 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; 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) (xdimx && ydimy && zdimz) +#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 } diff --git a/wk1.c b/wk1.c index d51c28f..9ee14da 100644 --- a/wk1.c +++ b/wk1.c @@ -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; } /*}}}*/ diff --git a/xdr.c b/xdr.c index a57f587..20b07e2 100644 --- a/xdr.c +++ b/xdr.c @@ -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);
",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("