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("