2019-07-22 20:32:33 +00:00
|
|
|
/* #includes */ /*{{{C}}}*//*{{{*/
|
|
|
|
#ifdef DMALLOC
|
|
|
|
#include "dmalloc.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <assert.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <limits.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
|
|
#include "csv.h"
|
|
|
|
#include "default.h"
|
|
|
|
#include "display.h"
|
|
|
|
#include "eval.h"
|
|
|
|
#include "main.h"
|
|
|
|
#include "misc.h"
|
|
|
|
#include "parser.h"
|
|
|
|
#include "scanner.h"
|
|
|
|
#include "sheet.h"
|
|
|
|
#include "utf8.h"
|
|
|
|
#include "xdr.h"
|
|
|
|
|
|
|
|
/*}}}*/
|
|
|
|
/* #defines */ /*{{{*/
|
|
|
|
#define HASH(x,s) \
|
|
|
|
{ \
|
|
|
|
const unsigned char *S=(const unsigned char*)s; \
|
|
|
|
\
|
|
|
|
x=0; \
|
|
|
|
while (*S) { x=(x<<5)+((x>>27)^*S); ++S; } \
|
|
|
|
x%=LABEL_CACHE; \
|
|
|
|
}
|
|
|
|
|
|
|
|
/*}}}*/
|
|
|
|
|
|
|
|
/* variables */ /*{{{*/
|
|
|
|
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;
|
|
|
|
int max_eval;
|
|
|
|
/*}}}*/
|
|
|
|
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
/* copytokens -- copy a sequence of tokens, possibly reallocating dest */ /*{{{*/
|
|
|
|
static void copytokens(Token*** totoks, Token** fromtoks)
|
|
|
|
{
|
|
|
|
/* variables */ /*{{{*/
|
|
|
|
size_t from_len, i;
|
|
|
|
/*}}}*/
|
|
|
|
|
|
|
|
from_len = tveclen(fromtoks);
|
|
|
|
if (from_len == 0)
|
|
|
|
{
|
|
|
|
tvecfree(*totoks);
|
|
|
|
*totoks = EMPTY_TVEC;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
from_len;
|
|
|
|
if (from_len > tveclen(*totoks))
|
|
|
|
{
|
|
|
|
tvecfree(*totoks);
|
|
|
|
*totoks = malloc((from_len+1)*sizeof(Token*));
|
|
|
|
(*totoks)[from_len] = NULLTOKEN;
|
|
|
|
} else {
|
|
|
|
tvecfreetoks(*totoks);
|
|
|
|
}
|
|
|
|
for (i=0; i<from_len; ++i) /* destination already has NULLTOKEN at end */
|
|
|
|
{
|
|
|
|
if (fromtoks[i] == NULLTOKEN) (*totoks)[i] = NULLTOKEN;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
(*totoks)[i] = malloc(sizeof(Token));
|
|
|
|
*((*totoks)[i]) = tcopy(*(fromtoks[i]));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*}}}*/
|
2019-07-22 20:32:33 +00:00
|
|
|
/* copycell -- copy a cell */ /*{{{*/
|
|
|
|
static void copycell(Sheet *sheet1, int x1, int y1, int z1, Sheet *sheet2, int x2, int y2, int z2)
|
|
|
|
{
|
|
|
|
/* variables */ /*{{{*/
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
Cell *fromcell, *tocell;
|
2019-07-22 20:32:33 +00:00
|
|
|
Token **run;
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
int i;
|
2019-07-22 20:32:33 +00:00
|
|
|
/*}}}*/
|
|
|
|
|
|
|
|
assert(sheet1!=(Sheet*)0);
|
|
|
|
assert(sheet2!=(Sheet*)0);
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
if (LOC_WITHIN(sheet1,x1,y1,z1))
|
2019-07-22 20:32:33 +00:00
|
|
|
{
|
|
|
|
sheet2->changed=1;
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
fromcell = CELL_AT(sheet1,x1,y1,z1);
|
|
|
|
if (fromcell == NULLCELL) freecell(sheet2,x2,y2,z2);
|
2019-07-22 20:32:33 +00:00
|
|
|
else
|
|
|
|
/* copy first cell to second */ /*{{{*/
|
|
|
|
{
|
|
|
|
freecell(sheet2,x2,y2,z2);
|
|
|
|
initcell(sheet2,x2,y2,z2);
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
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;
|
2019-07-22 20:32:33 +00:00
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
}
|
|
|
|
else freecell(sheet2,x2,y2,z2);
|
|
|
|
}
|
|
|
|
/*}}}*/
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
/* dump_cell -- write internal contents of cell to standard out */ /*{{{*/
|
|
|
|
static void dump_cell(Sheet *sheet, int x, int y, int z)
|
|
|
|
{
|
|
|
|
Cell* c;
|
|
|
|
char buf[2048];
|
|
|
|
|
|
|
|
assert(sheet != (Sheet*)0);
|
|
|
|
if (x < 0 || y < 0 || z < 0)
|
|
|
|
{
|
|
|
|
printf("TEADUMP: Requested cell &(%d,%d,%d) has negative coordinates.\n",
|
|
|
|
x, y, z);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!LOC_WITHIN(sheet, x, y, z))
|
|
|
|
{
|
|
|
|
printf("TEADUMP: Requested cell &(%d,%d,%d) outside sheet dims %d,%d,%d.\n",
|
|
|
|
x, y, z, sheet->dimx, sheet->dimy, sheet->dimz);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
c = CELL_AT(sheet, x, y, z);
|
|
|
|
if (c == NULLCELL)
|
|
|
|
{
|
|
|
|
printf("TEADUMP: Cell at &(%d,%d,%d) is empty.\n", x, y, z);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
printf("TEADUMP of &(%d,%d,%d):\n", x, y, z);
|
|
|
|
print(buf, sizeof(buf), 0, 1, 0, -1, c->contents);
|
|
|
|
printf(" Base expr: %s.\n", buf);
|
|
|
|
print(buf, sizeof(buf), 0, 1, 0, -1, c->ccontents);
|
|
|
|
printf(" Update expr: %s.\n", buf);
|
|
|
|
if (c->label == (char *)0) printf("\n No label.\n");
|
|
|
|
else printf("\n Label: %s.\n", c->label);
|
|
|
|
printtok(buf, sizeof(buf), 0, 1, 0, -1, 1, &(c->value));
|
|
|
|
printf(" Current value: %s.\n", buf);
|
|
|
|
printtok(buf, sizeof(buf), 0, 1, 0, -1, 1, &(c->resvalue));
|
|
|
|
printf(" Stored result value: %s.\n Adjustment: ", buf);
|
|
|
|
switch (c->adjust) {
|
|
|
|
case LEFT: printf("LEFT\n"); break;
|
|
|
|
case RIGHT: printf("RIGHT\n"); break;
|
|
|
|
case CENTER: printf("CENTER\n"); break;
|
|
|
|
case AUTOADJUST: printf("AUTO\n"); break;
|
|
|
|
}
|
|
|
|
printf(" Precision: %d\n Attributes: ", c->precision);
|
|
|
|
if (c->updated) printf("updated ");
|
|
|
|
if (c->shadowed) printf("shadowed ");
|
|
|
|
if (c->scientific) printf("scientific ");
|
|
|
|
if (c->locked) printf("locked ");
|
|
|
|
if (c->transparent) printf("transparent ");
|
|
|
|
if (c->ignored) printf("ignored ");
|
|
|
|
if (c->clock_t0) printf("clock_t0 ");
|
|
|
|
if (c->clock_t1) printf("clock_t1 ");
|
|
|
|
if (c->clock_t2) printf("clock_t2 ");
|
|
|
|
if (c->bold) printf("bold ");
|
|
|
|
if (c->underline) printf("underline ");
|
|
|
|
printf("\n\n");
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* dump_current_cell -- dump_cell of the current_cell */ /*{{{*/
|
|
|
|
void dump_current_cell(Sheet *sheet)
|
|
|
|
{
|
|
|
|
assert(sheet != (Sheet *)0);
|
|
|
|
dump_cell(sheet, sheet->curx, sheet->cury, sheet->curz);
|
|
|
|
}
|
|
|
|
/*}}}*/
|
2019-07-22 20:32:33 +00:00
|
|
|
/* 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)
|
|
|
|
{
|
|
|
|
int xoff, yoff, zoff;
|
|
|
|
|
|
|
|
assert(sheet1!=(Sheet*)0);
|
|
|
|
assert(sheet2!=(Sheet*)0);
|
|
|
|
resize(sheet1,x1+xdist-1,y1+ydist-1,z1+zdist-1);
|
|
|
|
resize(sheet2,x2+xdist-1,y2+ydist-1,z2+zdist-1);
|
|
|
|
for (xoff=0; xoff<xdist; ++xoff)
|
|
|
|
for (yoff=0; yoff<ydist; ++yoff)
|
|
|
|
for (zoff=0; zoff<zdist; ++zoff)
|
|
|
|
{
|
|
|
|
Cell *t;
|
|
|
|
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
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;
|
2019-07-22 20:32:33 +00:00
|
|
|
}
|
|
|
|
sheet1->changed=1;
|
|
|
|
sheet2->changed=1;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* cmpcell -- compare to cells with given order flags */ /*{{{*/
|
|
|
|
/* Notes */ /*{{{*/
|
|
|
|
/*
|
|
|
|
Compare the _values_ of two cells. The result is -1 if first is smaller
|
|
|
|
than second, 0 if they are equal and 1 if the first is bigger than the
|
|
|
|
second. A result of 2 means they are not comparable.
|
|
|
|
*/
|
|
|
|
/*}}}*/
|
|
|
|
static int cmpcell(Sheet *sheet1, int x1, int y1, int z1, Sheet *sheet2, int x2, int y2, int z2, int sortkey)
|
|
|
|
{
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
Cell *leftcell, *rightcell;
|
2019-07-22 20:32:33 +00:00
|
|
|
assert(sheet1!=(Sheet*)0);
|
|
|
|
assert(sheet2!=(Sheet*)0);
|
|
|
|
/* empty cells are smaller than any non-empty cell */ /*{{{*/
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
if (!CELL_IS_GOOD(sheet1,x1,y1,z1) || CELL_AT(sheet1,x1,y1,z1)->value.type==EMPTY)
|
2019-07-22 20:32:33 +00:00
|
|
|
{
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
if (!CELL_IS_GOOD(sheet2,x2,y2,z2) || CELL_AT(sheet2,x2,y2,z2)->value.type==EMPTY) return 0;
|
2019-07-22 20:32:33 +00:00
|
|
|
else return (sortkey&ASCENDING ? -1 : 1);
|
|
|
|
}
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
if (!CELL_IS_GOOD(sheet2,x2,y2,z2) || CELL_AT(sheet2,x2,y2,z2)->value.type==EMPTY) return (sortkey&ASCENDING ? 1 : -1);
|
2019-07-22 20:32:33 +00:00
|
|
|
/*}}}*/
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
leftcell = CELL_AT(sheet1,x1,y1,z1);
|
|
|
|
rightcell = CELL_AT(sheet2,x2,y2,z2);
|
|
|
|
switch (leftcell->value.type)
|
2019-07-22 20:32:33 +00:00
|
|
|
{
|
|
|
|
/* STRING */ /*{{{*/
|
|
|
|
case STRING:
|
|
|
|
{
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
if (rightcell->value.type==STRING)
|
2019-07-22 20:32:33 +00:00
|
|
|
{
|
|
|
|
int r;
|
|
|
|
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
r=strcmp(leftcell->value.u.string, rightcell->value.u.string);
|
2019-07-22 20:32:33 +00:00
|
|
|
if (r<0) return (sortkey&ASCENDING ? -1 : 1);
|
|
|
|
else if (r==0) return 0;
|
|
|
|
else return (sortkey&ASCENDING ? 1 : -1);
|
|
|
|
}
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* FLOAT */ /*{{{*/
|
|
|
|
case FLOAT:
|
|
|
|
{
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
if (rightcell->value.type==FLOAT)
|
2019-07-22 20:32:33 +00:00
|
|
|
{
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
if (leftcell->value.u.flt<rightcell->value.u.flt) return (sortkey&ASCENDING ? -1 : 1);
|
|
|
|
else if (leftcell->value.u.flt==rightcell->value.u.flt) return 0;
|
2019-07-22 20:32:33 +00:00
|
|
|
else return (sortkey&ASCENDING ? 1 : -1);
|
|
|
|
}
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
if (rightcell->value.type==INT)
|
2019-07-22 20:32:33 +00:00
|
|
|
{
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
if (leftcell->value.u.flt<rightcell->value.u.integer) return (sortkey&ASCENDING ? -1 : 1);
|
|
|
|
else if (leftcell->value.u.flt==rightcell->value.u.integer) return 0;
|
2019-07-22 20:32:33 +00:00
|
|
|
else return (sortkey&ASCENDING ? 1 : -1);
|
|
|
|
}
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* INT */ /*{{{*/
|
|
|
|
case INT:
|
|
|
|
{
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
if (rightcell->value.type==INT)
|
2019-07-22 20:32:33 +00:00
|
|
|
{
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
if (leftcell->value.u.integer<rightcell->value.u.integer) return (sortkey&ASCENDING ? -1 : 1);
|
|
|
|
else if (leftcell->value.u.integer==rightcell->value.u.integer) return 0;
|
2019-07-22 20:32:33 +00:00
|
|
|
else return (sortkey&ASCENDING ? 1 : -1);
|
|
|
|
}
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
if (rightcell->value.type==FLOAT)
|
2019-07-22 20:32:33 +00:00
|
|
|
{
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
if (leftcell->value.u.integer<rightcell->value.u.flt) return (sortkey&ASCENDING ? -1 : 1);
|
|
|
|
else if (leftcell->value.u.integer==rightcell->value.u.flt) return 0;
|
2019-07-22 20:32:33 +00:00
|
|
|
else return (sortkey&ASCENDING ? 1 : -1);
|
|
|
|
}
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
default: return 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
|
|
|
|
/* resize -- check if sheet needs to be resized in any dimension */ /*{{{*/
|
|
|
|
void resize(Sheet *sheet, int x, int y, int z)
|
|
|
|
{
|
|
|
|
assert(x>=0);
|
|
|
|
assert(y>=0);
|
|
|
|
assert(z>=0);
|
|
|
|
assert(sheet!=(Sheet*)0);
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
if (!LOC_WITHIN(sheet,x,y,z))
|
2019-07-22 20:32:33 +00:00
|
|
|
{
|
|
|
|
/* variables */ /*{{{*/
|
|
|
|
Cell **newsheet;
|
|
|
|
int *newcolumn;
|
|
|
|
unsigned int ndimx,ndimy,ndimz;
|
|
|
|
/*}}}*/
|
|
|
|
|
|
|
|
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);
|
|
|
|
/* allocate new sheet */ /*{{{*/
|
|
|
|
newsheet=malloc(ndimx*ndimy*ndimz*sizeof(Cell*));
|
|
|
|
for (x=0; x<ndimx; ++x) for (y=0; y<ndimy; ++y) for (z=0; z<ndimz; ++z)
|
|
|
|
{
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
if (LOC_WITHIN(sheet,x,y,z)) *(newsheet+x*ndimz*ndimy+y*ndimz+z)=CELL_AT(sheet,x,y,z);
|
|
|
|
else *(newsheet+x*ndimz*ndimy+y*ndimz+z)= NULLCELL;
|
2019-07-22 20:32:33 +00:00
|
|
|
}
|
|
|
|
if (sheet->sheet!=(Cell**)0) free(sheet->sheet);
|
|
|
|
sheet->sheet=newsheet;
|
|
|
|
/*}}}*/
|
|
|
|
/* allocate new columns */ /*{{{*/
|
|
|
|
if (x>sheet->dimx || z>=sheet->dimz)
|
|
|
|
{
|
|
|
|
newcolumn=malloc(ndimx*ndimz*sizeof(int));
|
|
|
|
for (x=0; x<ndimx; ++x) for (z=0; z<ndimz; ++z)
|
|
|
|
{
|
|
|
|
if (x<sheet->dimx && z<sheet->dimz) *(newcolumn+x*ndimz+z)=*(sheet->column+x*sheet->dimz+z);
|
|
|
|
else *(newcolumn+x*ndimz+z)=DEF_COLUMNWIDTH;
|
|
|
|
}
|
|
|
|
if (sheet->column!=(int*)0) free(sheet->column);
|
|
|
|
sheet->column=newcolumn;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
sheet->dimx=ndimx;
|
|
|
|
sheet->dimy=ndimy;
|
|
|
|
sheet->dimz=ndimz;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* initcell -- initialise new cell, if it does not exist yet */ /*{{{*/
|
|
|
|
void initcell(Sheet *sheet, int x, int y, int z)
|
|
|
|
{
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
Cell *nc;
|
|
|
|
|
2019-07-22 20:32:33 +00:00
|
|
|
assert(x>=0);
|
|
|
|
assert(y>=0);
|
|
|
|
assert(z>=0);
|
|
|
|
resize(sheet,x,y,z);
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
if (CELL_AT(sheet,x,y,z) == NULLCELL)
|
2019-07-22 20:32:33 +00:00
|
|
|
{
|
|
|
|
sheet->changed=1;
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
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;
|
2019-07-22 20:32:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* cachelabels -- create new label cache */ /*{{{*/
|
|
|
|
void cachelabels(Sheet *sheet)
|
|
|
|
{
|
|
|
|
int i,x,y,z;
|
|
|
|
|
|
|
|
if (sheet==(Sheet*)0) return;
|
|
|
|
for (i=0; i<LABEL_CACHE; ++i) /* free bucket */ /*{{{*/
|
|
|
|
{
|
|
|
|
struct Label *run;
|
|
|
|
|
|
|
|
for (run=sheet->labelcache[i]; run!=(struct Label*)0;)
|
|
|
|
{
|
|
|
|
struct Label *runnext;
|
|
|
|
|
|
|
|
runnext=run->next;
|
|
|
|
free(run);
|
|
|
|
run=runnext;
|
|
|
|
}
|
|
|
|
sheet->labelcache[i]=(struct Label*)0;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
for (ALL_CELLS_IN_SHEET(sheet,x,y,z))
|
2019-07-22 20:32:33 +00:00
|
|
|
/* cache all labels */ /*{{{*/
|
|
|
|
{
|
|
|
|
const char *l;
|
|
|
|
|
|
|
|
l=getlabel(sheet,x,y,z);
|
|
|
|
if (*l)
|
|
|
|
{
|
|
|
|
unsigned long hx;
|
|
|
|
struct Label **run;
|
|
|
|
|
|
|
|
HASH(hx,l);
|
|
|
|
for (run=&sheet->labelcache[(unsigned int)hx]; *run!=(struct Label*)0 && strcmp(l,(*run)->label); run=&((*run)->next));
|
|
|
|
if (*run==(struct Label*)0)
|
|
|
|
{
|
|
|
|
*run=malloc(sizeof(struct Label));
|
|
|
|
(*run)->next=(struct Label*)0;
|
|
|
|
(*run)->label=l;
|
|
|
|
(*run)->x=x;
|
|
|
|
(*run)->y=y;
|
|
|
|
(*run)->z=z;
|
|
|
|
}
|
|
|
|
/* else we have a duplicate label, which _can_ happen under */
|
|
|
|
/* unfortunate conditions. Don't tell anybody. */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* freesheet -- free all cells of an entire spread sheet */ /*{{{*/
|
|
|
|
void freesheet(Sheet *sheet, int all)
|
|
|
|
{
|
|
|
|
/* variables */ /*{{{*/
|
|
|
|
int x,y,z;
|
|
|
|
/*}}}*/
|
|
|
|
|
|
|
|
assert(sheet!=(Sheet*)0);
|
|
|
|
sheet->changed=0;
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
for (ALL_CELLS_IN_SHEET(sheet,x,y,z))
|
2019-07-22 20:32:33 +00:00
|
|
|
{
|
|
|
|
freecell(sheet,x,y,z);
|
|
|
|
}
|
|
|
|
if (all)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i=0; i<LABEL_CACHE; ++i) /* free all buckets */ /*{{{*/
|
|
|
|
{
|
|
|
|
struct Label *run;
|
|
|
|
|
|
|
|
for (run=sheet->labelcache[i]; run!=(struct Label*)0;)
|
|
|
|
{
|
|
|
|
struct Label *runnext;
|
|
|
|
|
|
|
|
runnext=run->next;
|
|
|
|
free(run);
|
|
|
|
run=runnext;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
if (sheet->sheet) free(sheet->sheet);
|
|
|
|
if (sheet->column) free(sheet->column);
|
|
|
|
if (sheet->name) free(sheet->name);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (x=0; x<sheet->dimx; ++x) for (z=0; z<sheet->dimz; ++z)
|
|
|
|
{
|
|
|
|
*(sheet->column+x*sheet->dimz+z)=DEF_COLUMNWIDTH;
|
|
|
|
}
|
|
|
|
cachelabels(sheet);
|
|
|
|
forceupdate(sheet);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* forceupdate -- clear all clock and update flags */ /*{{{*/
|
|
|
|
void forceupdate(Sheet *sheet)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
assert(sheet!=(Sheet*)0);
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
for (i=0; i<sheet->dimx*sheet->dimy*sheet->dimz; ++i) if (*(sheet->sheet+i) != NULLCELL)
|
2019-07-22 20:32:33 +00:00
|
|
|
{
|
|
|
|
(*(sheet->sheet+i))->updated=0;
|
|
|
|
(*(sheet->sheet+i))->clock_t0=0;
|
|
|
|
(*(sheet->sheet+i))->clock_t1=0;
|
|
|
|
(*(sheet->sheet+i))->clock_t2=0;
|
|
|
|
}
|
|
|
|
update(sheet);
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* freecell -- free one cell */ /*{{{*/
|
|
|
|
void freecell(Sheet *sheet, int x, int y, int z)
|
|
|
|
{
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
Cell *c;
|
2019-07-22 20:32:33 +00:00
|
|
|
assert(sheet!=(Sheet*)0);
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
if (sheet->sheet!=(Cell**)0 && CELL_IS_GOOD(sheet,x,y,z))
|
2019-07-22 20:32:33 +00:00
|
|
|
{
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
c = CELL_AT(sheet,x,y,z);
|
|
|
|
tvecfree(c->contents);
|
|
|
|
tvecfree(c->ccontents);
|
|
|
|
tfree(&(c->value));
|
|
|
|
tfree(&(c->resvalue));
|
|
|
|
free(c);
|
|
|
|
CELL_AT(sheet,x,y,z) = NULLCELL;
|
2019-07-22 20:32:33 +00:00
|
|
|
sheet->changed=1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* columnwidth -- get width of column */ /*{{{*/
|
|
|
|
int columnwidth(Sheet *sheet, int x, int z)
|
|
|
|
{
|
|
|
|
assert(sheet!=(Sheet*)0);
|
|
|
|
if (x<sheet->dimx && z<sheet->dimz) return (*(sheet->column+x*sheet->dimz+z));
|
|
|
|
else return DEF_COLUMNWIDTH;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* setwidth -- set width of column */ /*{{{*/
|
|
|
|
void setwidth(Sheet *sheet, int x, int z, int width)
|
|
|
|
{
|
|
|
|
assert(sheet!=(Sheet*)0);
|
|
|
|
resize(sheet,x,1,z);
|
|
|
|
sheet->changed=1;
|
|
|
|
*(sheet->column+x*sheet->dimz+z)=width;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* cellwidth -- get width of a cell */ /*{{{*/
|
|
|
|
int cellwidth(Sheet *sheet, int x, int y, int z)
|
|
|
|
{
|
|
|
|
int width;
|
|
|
|
|
|
|
|
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);
|
|
|
|
return width;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* putcont -- assign new contents */ /*{{{*/
|
|
|
|
void putcont(Sheet *sheet, int x, int y, int z, Token **t, int c)
|
|
|
|
{
|
|
|
|
assert(sheet!=(Sheet*)0);
|
|
|
|
sheet->changed=1;
|
|
|
|
resize(sheet,x,y,z);
|
|
|
|
initcell(sheet,x,y,z);
|
|
|
|
if (c)
|
|
|
|
{
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
tvecfree(CELL_AT(sheet,x,y,z)->ccontents);
|
|
|
|
CELL_AT(sheet,x,y,z)->ccontents=t;
|
2019-07-22 20:32:33 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
tvecfree(CELL_AT(sheet,x,y,z)->contents);
|
|
|
|
CELL_AT(sheet,x,y,z)->contents=t;
|
2019-07-22 20:32:33 +00:00
|
|
|
}
|
|
|
|
redraw_cell(sheet, x, y, z);
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* getcont -- get contents */ /*{{{*/
|
|
|
|
Token **getcont(Sheet *sheet, int x, int y, int z, int c)
|
|
|
|
{
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
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);
|
2019-07-22 20:32:33 +00:00
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* getvalue -- get tcopy()ed value */ /*{{{*/
|
|
|
|
Token getvalue(Sheet *sheet, int x, int y, int z)
|
|
|
|
{
|
|
|
|
/* variables */ /*{{{*/
|
|
|
|
Token result;
|
|
|
|
int orig_upd_clock;
|
|
|
|
/*}}}*/
|
|
|
|
|
|
|
|
assert(sheet!=(Sheet*)0);
|
|
|
|
if (x<0 || y<0 || z<0)
|
|
|
|
/* return error */ /*{{{*/
|
|
|
|
{
|
|
|
|
result.type=EEK;
|
|
|
|
result.u.err=mystrmalloc(_("Negative index"));
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
return result;
|
2019-07-22 20:32:33 +00:00
|
|
|
}
|
|
|
|
/*}}}*/
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
result.type = EMPTY;
|
|
|
|
/* Can always short-circuit an out-of-bounds or empty cell */
|
|
|
|
if (!CELL_IS_GOOD(sheet,x,y,z)) return result;
|
|
|
|
/* only short-circuit on empty contents of a good cell if we are NOT
|
|
|
|
depending on this call to update the current value
|
|
|
|
*/
|
|
|
|
if (!upd_clock && getcont(sheet,x,y,z,2) == EMPTY_TVEC) return result;
|
2019-07-22 20:32:33 +00:00
|
|
|
/* update value of this cell if needed and return it */ /*{{{*/
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
orig_upd_clock = upd_clock;
|
|
|
|
if (CELL_AT(sheet,x,y,z)->ignored)
|
2019-07-22 20:32:33 +00:00
|
|
|
{
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
/* 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;
|
|
|
|
tfree(&oldvalue);
|
|
|
|
}
|
|
|
|
else if (CELL_AT(sheet,x,y,z)->updated==0)
|
|
|
|
{
|
|
|
|
/* variables */ /*{{{*/
|
|
|
|
Sheet *old_sheet;
|
|
|
|
int old_x,old_y,old_z,old_max_eval;
|
|
|
|
Token oldvalue;
|
|
|
|
/*}}}*/
|
2019-07-22 20:32:33 +00:00
|
|
|
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
old_sheet=upd_sheet;
|
|
|
|
old_x=upd_x;
|
|
|
|
old_y=upd_y;
|
|
|
|
old_z=upd_z;
|
|
|
|
old_max_eval=max_eval;
|
|
|
|
upd_sheet=sheet;
|
|
|
|
upd_x=x;
|
|
|
|
upd_y=y;
|
|
|
|
upd_z=z;
|
|
|
|
max_eval=MAX_EVALNEST;
|
|
|
|
if (CELL_AT(sheet,x,y,z)->clock_t1==0)
|
|
|
|
{
|
|
|
|
CELL_AT(sheet,x,y,z)->updated = 1;
|
|
|
|
oldvalue = CELL_AT(sheet,x,y,z)->value;
|
|
|
|
upd_clock = 0;
|
|
|
|
CELL_AT(sheet,x,y,z)->value = eval_safe(getcont(sheet, x, y, z, 2));
|
2019-07-22 20:32:33 +00:00
|
|
|
tfree(&oldvalue);
|
|
|
|
}
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
else if (upd_clock)
|
2019-07-22 20:32:33 +00:00
|
|
|
{
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
CELL_AT(sheet,x,y,z)->updated=1;
|
|
|
|
upd_clock=0;
|
|
|
|
oldvalue=CELL_AT(sheet,x,y,z)->resvalue;
|
|
|
|
CELL_AT(sheet,x,y,z)->resvalue = eval_safe(getcont(sheet,x,y,z,2));
|
|
|
|
tfree(&oldvalue);
|
2019-07-22 20:32:33 +00:00
|
|
|
}
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
upd_sheet=old_sheet;
|
|
|
|
upd_x=old_x;
|
|
|
|
upd_y=old_y;
|
|
|
|
upd_z=old_z;
|
|
|
|
max_eval=old_max_eval;
|
2019-07-22 20:32:33 +00:00
|
|
|
}
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
if (!orig_upd_clock) result=tcopy(CELL_AT(sheet,x,y,z)->value);
|
2019-07-22 20:32:33 +00:00
|
|
|
/*}}}*/
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* update -- update all cells that need it */ /*{{{*/
|
|
|
|
void update(Sheet *sheet)
|
|
|
|
{
|
|
|
|
int x,y,z,kp,iterating;
|
|
|
|
|
|
|
|
assert(sheet!=(Sheet*)0);
|
|
|
|
kp=0;
|
|
|
|
iterating=0;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
sheet->clk=0;
|
|
|
|
if (iterating==1)
|
|
|
|
{
|
|
|
|
line_msg((const char*)0,_("Calculating running, press Escape to abort it"));
|
|
|
|
++iterating;
|
|
|
|
}
|
|
|
|
else if (iterating==0) ++iterating;
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
for (ALL_CELLS_IN_SHEET(sheet,x,y,z))
|
2019-07-22 20:32:33 +00:00
|
|
|
{
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
if (CELL_AT(sheet,x,y,z) && CELL_AT(sheet,x,y,z)->clock_t2)
|
2019-07-22 20:32:33 +00:00
|
|
|
{
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
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;
|
2019-07-22 20:32:33 +00:00
|
|
|
}
|
|
|
|
}
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
for (ALL_CELLS_IN_SHEET(sheet,x,y,z))
|
2019-07-22 20:32:33 +00:00
|
|
|
{
|
|
|
|
upd_clock=1;
|
|
|
|
getvalue(sheet,x,y,z);
|
|
|
|
}
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
for (ALL_CELLS_IN_SHEET(sheet,x,y,z))
|
2019-07-22 20:32:33 +00:00
|
|
|
{
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
if (CELL_AT(sheet,x,y,z) && CELL_AT(sheet,x,y,z)->clock_t1)
|
2019-07-22 20:32:33 +00:00
|
|
|
{
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
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;
|
2019-07-22 20:32:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
upd_clock=0;
|
|
|
|
} while (sheet->clk && !(kp=keypressed()));
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
Token v;
|
|
|
|
|
|
|
|
assert(sheet!=(Sheet*)0);
|
|
|
|
if ((v=getvalue(sheet,x,y,z)).type!=EEK)
|
|
|
|
{
|
|
|
|
tfree(&v);
|
|
|
|
return (char*)0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return (v.u.err);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* 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)
|
|
|
|
{
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
Token t;
|
2019-07-22 20:32:33 +00:00
|
|
|
|
|
|
|
assert(sheet!=(Sheet*)0);
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
t=getvalue(sheet,x,y,z);
|
|
|
|
printtok(s,size,chars,quote,scientific,precision,0,&t);
|
2019-07-22 20:32:33 +00:00
|
|
|
tfree(&t);
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* getadjust -- get cell adjustment */ /*{{{*/
|
|
|
|
Adjust getadjust(Sheet *sheet, int x, int y, int z)
|
|
|
|
{
|
|
|
|
assert(sheet!=(Sheet*)0);
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
if (!CELL_IS_GOOD(sheet,x,y,z))
|
2019-07-22 20:32:33 +00:00
|
|
|
{
|
|
|
|
return LEFT;
|
|
|
|
}
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
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);
|
2019-07-22 20:32:33 +00:00
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* setadjust -- set cell adjustment */ /*{{{*/
|
|
|
|
void setadjust(Sheet *sheet, int x, int y, int z, Adjust adjust)
|
|
|
|
{
|
|
|
|
assert(sheet!=(Sheet*)0);
|
|
|
|
sheet->changed=1;
|
|
|
|
resize(sheet,x,y,z);
|
|
|
|
initcell(sheet,x,y,z);
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
CELL_AT(sheet,x,y,z)->adjust=adjust;
|
2019-07-22 20:32:33 +00:00
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
|
|
|
|
/* shadow -- shadow cell by left neighbour */ /*{{{*/
|
|
|
|
void shadow(Sheet *sheet, int x, int y, int z, int yep)
|
|
|
|
{
|
|
|
|
sheet->changed=1;
|
|
|
|
initcell(sheet,x,y,z);
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
CELL_AT(sheet,x,y,z)->shadowed=yep;
|
2019-07-22 20:32:33 +00:00
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* shadowed -- is cell shadowed? */ /*{{{*/
|
|
|
|
int shadowed(Sheet *sheet, int x, int y, int z)
|
|
|
|
{
|
|
|
|
return (SHADOWED(sheet,x,y,z));
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* bold -- bold font */ /*{{{*/
|
|
|
|
void bold(Sheet *sheet, int x, int y, int z, int yep)
|
|
|
|
{
|
|
|
|
sheet->changed=1;
|
|
|
|
initcell(sheet,x,y,z);
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
CELL_AT(sheet,x,y,z)->bold=yep;
|
2019-07-22 20:32:33 +00:00
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* isbold -- is cell bold? */ /*{{{*/
|
|
|
|
int isbold(Sheet *sheet, int x, int y, int z)
|
|
|
|
{
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
return (CELL_IS_GOOD(sheet,x,y,z) && CELL_AT(sheet,x,y,z)->bold);
|
2019-07-22 20:32:33 +00:00
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* underline -- underline */ /*{{{*/
|
|
|
|
void underline(Sheet *sheet, int x, int y, int z, int yep)
|
|
|
|
{
|
|
|
|
sheet->changed=1;
|
|
|
|
initcell(sheet,x,y,z);
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
CELL_AT(sheet,x,y,z)->underline=yep;
|
2019-07-22 20:32:33 +00:00
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* isunderline -- is cell underlined? */ /*{{{*/
|
|
|
|
int underlined(Sheet *sheet, int x, int y, int z)
|
|
|
|
{
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
return (CELL_IS_GOOD(sheet,x,y,z) && CELL_AT(sheet,x,y,z)->underline);
|
2019-07-22 20:32:33 +00:00
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* lockcell -- lock cell */ /*{{{*/
|
|
|
|
void lockcell(Sheet *sheet, int x, int y, int z, int yep)
|
|
|
|
{
|
|
|
|
sheet->changed=1;
|
|
|
|
initcell(sheet,x,y,z);
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
CELL_AT(sheet,x,y,z)->locked=yep;
|
2019-07-22 20:32:33 +00:00
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* locked -- is cell locked? */ /*{{{*/
|
|
|
|
int locked(Sheet *sheet, int x, int y, int z)
|
|
|
|
{
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
return (CELL_IS_GOOD(sheet,x,y,z) && CELL_AT(sheet,x,y,z)->locked);
|
2019-07-22 20:32:33 +00:00
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* transparent -- is cell transparent? */ /*{{{*/
|
|
|
|
int transparent(Sheet *sheet, int x, int y, int z)
|
|
|
|
{
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
return (CELL_IS_GOOD(sheet,x,y,z) && CELL_AT(sheet,x,y,z)->transparent);
|
2019-07-22 20:32:33 +00:00
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* maketrans -- make cell transparent */ /*{{{*/
|
|
|
|
void maketrans(Sheet *sheet, int x, int y, int z, int yep)
|
|
|
|
{
|
|
|
|
sheet->changed=1;
|
|
|
|
initcell(sheet,x,y,z);
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
CELL_AT(sheet,x,y,z)->transparent=yep;
|
2019-07-22 20:32:33 +00:00
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* igncell -- ignore cell */ /*{{{*/
|
|
|
|
void igncell(Sheet *sheet, int x, int y, int z, int yep)
|
|
|
|
{
|
|
|
|
sheet->changed=1;
|
|
|
|
initcell(sheet,x,y,z);
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
CELL_AT(sheet,x,y,z)->ignored=yep;
|
2019-07-22 20:32:33 +00:00
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* ignored -- is cell ignored? */ /*{{{*/
|
|
|
|
int ignored(Sheet *sheet, int x, int y, int z)
|
|
|
|
{
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
return (CELL_IS_GOOD(sheet,x,y,z) && CELL_AT(sheet,x,y,z)->ignored);
|
2019-07-22 20:32:33 +00:00
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* clk -- clock cell */ /*{{{*/
|
|
|
|
void clk(Sheet *sheet, int x, int y, int z)
|
|
|
|
{
|
|
|
|
assert(sheet!=(Sheet*)0);
|
|
|
|
assert(x>=0 && x<sheet->dimx);
|
|
|
|
assert(y>=0 && y<sheet->dimy);
|
|
|
|
assert(z>=0 && z<sheet->dimz);
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
if (CELL_AT(sheet,x,y,z))
|
2019-07-22 20:32:33 +00:00
|
|
|
{
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
CELL_AT(sheet,x,y,z)->clock_t2=1;
|
2019-07-22 20:32:33 +00:00
|
|
|
sheet->clk=1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* setscientific -- cell value should be displayed in scientific notation */ /*{{{*/
|
|
|
|
void setscientific(Sheet *sheet, int x, int y, int z, int yep)
|
|
|
|
{
|
|
|
|
sheet->changed=1;
|
|
|
|
resize(sheet,x,y,z);
|
|
|
|
initcell(sheet,x,y,z);
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
CELL_AT(sheet,x,y,z)->scientific=yep;
|
2019-07-22 20:32:33 +00:00
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* getscientific -- should value be displayed in scientific notation? */ /*{{{*/
|
|
|
|
int getscientific(Sheet *sheet, int x, int y, int z)
|
|
|
|
{
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
if (CELL_IS_GOOD(sheet,x,y,z)) return CELL_AT(sheet,x,y,z)->scientific;
|
2019-07-22 20:32:33 +00:00
|
|
|
else return DEF_SCIENTIFIC;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* setprecision -- set cell precision */ /*{{{*/
|
|
|
|
void setprecision(Sheet *sheet, int x, int y, int z, int precision)
|
|
|
|
{
|
|
|
|
sheet->changed=1;
|
|
|
|
resize(sheet,x,y,z);
|
|
|
|
initcell(sheet,x,y,z);
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
CELL_AT(sheet,x,y,z)->precision=precision;
|
2019-07-22 20:32:33 +00:00
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* getprecision -- get cell precision */ /*{{{*/
|
|
|
|
int getprecision(Sheet *sheet, int x, int y, int z)
|
|
|
|
{
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
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);
|
2019-07-22 20:32:33 +00:00
|
|
|
else return def_precision;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* getlabel -- get cell label */ /*{{{*/
|
|
|
|
const char *getlabel(Sheet *sheet, int x, int y, int z)
|
|
|
|
{
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
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);
|
2019-07-22 20:32:33 +00:00
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* setlabel -- set cell label */ /*{{{*/
|
|
|
|
void setlabel(Sheet *sheet, int x, int y, int z, const char *buf, int update)
|
|
|
|
{
|
|
|
|
sheet->changed=1;
|
|
|
|
resize(sheet,x,y,z);
|
|
|
|
initcell(sheet,x,y,z);
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
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;
|
2019-07-22 20:32:33 +00:00
|
|
|
if (update)
|
|
|
|
{
|
|
|
|
cachelabels(sheet);
|
|
|
|
forceupdate(sheet);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* findlabel -- return cell location for a given label */ /*{{{*/
|
|
|
|
Token findlabel(Sheet *sheet, const char *label)
|
|
|
|
{
|
|
|
|
/* variables */ /*{{{*/
|
|
|
|
Token result;
|
|
|
|
unsigned long hx;
|
|
|
|
struct Label *run;
|
|
|
|
/*}}}*/
|
|
|
|
|
|
|
|
assert(sheet!=(Sheet*)0);
|
|
|
|
/*
|
|
|
|
if (sheet==(Sheet*)0) run=(struct Label*)0;
|
|
|
|
else
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
HASH(hx,label);
|
|
|
|
for (run=sheet->labelcache[(unsigned int)hx]; run!=(struct Label*)0 && strcmp(label,run->label); run=run->next);
|
|
|
|
}
|
|
|
|
if (run)
|
|
|
|
{
|
|
|
|
result.type=LOCATION;
|
|
|
|
result.u.location[0]=run->x;
|
|
|
|
result.u.location[1]=run->y;
|
|
|
|
result.u.location[2]=run->z;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
/* variables */ /*{{{*/
|
|
|
|
Token **run;
|
|
|
|
/*}}}*/
|
|
|
|
|
|
|
|
/* asserts */ /*{{{*/
|
|
|
|
assert(sheet!=(Sheet*)0);
|
|
|
|
assert(oldlabel!=(const char*)0);
|
|
|
|
assert(newlabel!=(const char*)0);
|
|
|
|
assert(x>=0);
|
|
|
|
assert(y>=0);
|
|
|
|
assert(z>=0);
|
|
|
|
/*}}}*/
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
if (CELL_IS_GOOD(sheet,x,y,z))
|
2019-07-22 20:32:33 +00:00
|
|
|
{
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
if (CELL_AT(sheet,x,y,z)->contents != EMPTY_TVEC)
|
2019-07-22 20:32:33 +00:00
|
|
|
{
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
for (run=CELL_AT(sheet,x,y,z)->contents; *run!=NULLTOKEN; ++run)
|
2019-07-22 20:32:33 +00:00
|
|
|
{
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
if ((*run)->type==LIDENT && strcmp((*run)->u.lident,oldlabel)==0)
|
|
|
|
{
|
|
|
|
free((*run)->u.lident);
|
|
|
|
(*run)->u.lident=mystrmalloc(newlabel);
|
|
|
|
}
|
2019-07-22 20:32:33 +00:00
|
|
|
}
|
|
|
|
}
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
if (CELL_AT(sheet,x,y,z)->ccontents != EMPTY_TVEC)
|
2019-07-22 20:32:33 +00:00
|
|
|
{
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
for (run=CELL_AT(sheet,x,y,z)->ccontents; *run!=NULLTOKEN; ++run)
|
2019-07-22 20:32:33 +00:00
|
|
|
{
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
if ((*run)->type==LIDENT && strcmp((*run)->u.lident,oldlabel)==0)
|
|
|
|
{
|
|
|
|
free((*run)->u.lident);
|
|
|
|
(*run)->u.lident=mystrmalloc(newlabel);
|
|
|
|
}
|
2019-07-22 20:32:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
cachelabels(sheet);
|
|
|
|
forceupdate(sheet);
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* savexdr -- save a spread sheet in XDR */ /*{{{*/
|
|
|
|
const char *savexdr(Sheet *sheet, const char *name, unsigned int *count)
|
|
|
|
{
|
|
|
|
/* variables */ /*{{{*/
|
|
|
|
FILE *fp;
|
|
|
|
XDR xdrs;
|
|
|
|
int x,y,z;
|
|
|
|
/*}}}*/
|
|
|
|
|
|
|
|
*count=0;
|
|
|
|
if ((fp=fopen(name,"w"))==(FILE*)0) return strerror(errno);
|
|
|
|
xdrstdio_create(&xdrs,fp,XDR_ENCODE);
|
|
|
|
if (!xdr_magic(&xdrs))
|
|
|
|
{
|
|
|
|
xdr_destroy(&xdrs);
|
|
|
|
(void)fclose(fp);
|
|
|
|
return strerror(errno);
|
|
|
|
}
|
|
|
|
for (x=sheet->dimx-1; x>=0; --x) for (z=sheet->dimz-1; z>=0; --z)
|
|
|
|
{
|
|
|
|
int width;
|
|
|
|
int u;
|
|
|
|
|
|
|
|
width=columnwidth(sheet,x,z);
|
|
|
|
if (width!=DEF_COLUMNWIDTH)
|
|
|
|
{
|
|
|
|
u=0;
|
|
|
|
if (xdr_int(&xdrs,&u)==0 || xdr_column(&xdrs,&x,&z,&width)==0)
|
|
|
|
{
|
|
|
|
xdr_destroy(&xdrs);
|
|
|
|
(void)fclose(fp);
|
|
|
|
return strerror(errno);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (y=sheet->dimy-1; y>=0; --y)
|
|
|
|
{
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
if (CELL_AT(sheet,x,y,z)!=NULLCELL)
|
2019-07-22 20:32:33 +00:00
|
|
|
{
|
|
|
|
u=1;
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
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)
|
2019-07-22 20:32:33 +00:00
|
|
|
{
|
|
|
|
xdr_destroy(&xdrs);
|
|
|
|
(void)fclose(fp);
|
|
|
|
return strerror(errno);
|
|
|
|
}
|
|
|
|
++*count;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
xdr_destroy(&xdrs);
|
|
|
|
if (fclose(fp)==EOF) return strerror(errno);
|
|
|
|
sheet->changed=0;
|
|
|
|
return (const char*)0;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* 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)
|
|
|
|
{
|
|
|
|
/* variables */ /*{{{*/
|
|
|
|
FILE *fp=(FILE*)0; /* cause run time error */
|
|
|
|
int x,y,z;
|
|
|
|
char buf[1024];
|
|
|
|
char num[20];
|
|
|
|
char fullname[PATH_MAX];
|
|
|
|
/*}}}*/
|
|
|
|
|
|
|
|
/* 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");
|
|
|
|
if (!body && (fp=fopen(name,"w"))==(FILE*)0) return strerror(errno);
|
|
|
|
for (z=z1; z<=z2; ++z)
|
|
|
|
{
|
|
|
|
if (body)
|
|
|
|
/* open new file */ /*{{{*/
|
|
|
|
{
|
|
|
|
sprintf(num,".%d",z);
|
|
|
|
fullname[sizeof(fullname)-strlen(num)-1]='\0';
|
|
|
|
(void)strncpy(fullname,name,sizeof(fullname)-strlen(num)-1);
|
|
|
|
fullname[sizeof(fullname)-1]='\0';
|
|
|
|
(void)strncat(fullname,num,sizeof(fullname)-strlen(num)-1);
|
|
|
|
fullname[sizeof(fullname)-1]='\0';
|
|
|
|
if ((fp=fopen(fullname,"w"))==(FILE*)0) return strerror(errno);
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
else if (fputs_close(".TS\n",fp)==EOF) return strerror(errno);
|
|
|
|
for (y=y1; y<=y2; ++y)
|
|
|
|
{
|
|
|
|
/* print format */ /*{{{*/
|
|
|
|
if (y>y1 && fputs_close(".T&\n",fp)==EOF) return strerror(errno);
|
|
|
|
for (x=x1; x<=x2; ++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))
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (fputs_close(".\n",fp)==EOF) return strerror(errno);
|
|
|
|
/*}}}*/
|
|
|
|
/* print contents */ /*{{{*/
|
|
|
|
for (x=x1; x<=x2; ++x)
|
|
|
|
{
|
|
|
|
if (!shadowed(sheet,x,y,z))
|
|
|
|
{
|
|
|
|
if (x>x1 && fputc_close('\t',fp)==EOF) return strerror(errno);
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
if (CELL_AT(sheet,x,y,z)!=NULLCELL)
|
2019-07-22 20:32:33 +00:00
|
|
|
{
|
|
|
|
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))
|
|
|
|
{
|
|
|
|
if (fputs_close(buf,fp)==EOF) return strerror(errno);
|
|
|
|
}
|
|
|
|
else for (bufp=buf; *bufp; ++bufp) switch (*bufp)
|
|
|
|
{
|
|
|
|
case '\\':
|
|
|
|
{
|
|
|
|
if (fputc_close('\\',fp)==EOF || fputc_close('e',fp)==EOF) return strerror(errno);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case '_':
|
|
|
|
{
|
|
|
|
if (fputc_close('\\',fp)==EOF || fputc_close('&',fp)==EOF || 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 (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 (fputc_close('\'',fp)==EOF) return strerror(errno);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case '-':
|
|
|
|
{
|
|
|
|
if (*(bufp+1)=='-')
|
|
|
|
{
|
|
|
|
if (fputc_close('-',fp)==EOF) return strerror(errno);
|
|
|
|
else ++bufp;
|
|
|
|
}
|
|
|
|
else if (fputs_close("\\-",fp)==EOF) return strerror(errno);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default: if (fputc_close(*bufp,fp)==EOF) return strerror(errno);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (fputc_close('\n',fp)==EOF) return strerror(errno);
|
|
|
|
/*}}}*/
|
|
|
|
++*count;
|
|
|
|
}
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
if (fputs_close(".TE\n",fp)==EOF) return strerror(errno);
|
|
|
|
if (z<z2 && fputs_close(".bp\n",fp)==EOF) return strerror(errno);
|
|
|
|
}
|
|
|
|
if (body && fclose(fp)==EOF) return strerror(errno);
|
|
|
|
}
|
|
|
|
if (!body && fclose(fp)==EOF) return strerror(errno);
|
|
|
|
return (const char*)0;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* savetext -- save as text */ /*{{{*/
|
|
|
|
const char *savetext(Sheet *sheet, const char *name, int x1, int y1, int z1, int x2, int y2, int z2, unsigned int *count)
|
|
|
|
{
|
|
|
|
/* variables */ /*{{{*/
|
|
|
|
FILE *fp;
|
|
|
|
int x,y,z;
|
|
|
|
/*}}}*/
|
|
|
|
|
|
|
|
/* 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");
|
|
|
|
if ((fp=fopen(name,"w"))==(FILE*)0) return strerror(errno);
|
|
|
|
for (z=z1; z<=z2; ++z)
|
|
|
|
{
|
|
|
|
for (y=y1; y<=y2; ++y)
|
|
|
|
{
|
|
|
|
size_t size,fill;
|
|
|
|
|
|
|
|
for (x=x1; x<=x2; ++x)
|
|
|
|
{
|
|
|
|
size=cellwidth(sheet,x,y,z);
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
if (CELL_AT(sheet,x,y,z)!=NULLCELL)
|
2019-07-22 20:32:33 +00:00
|
|
|
{
|
|
|
|
char *buf;
|
|
|
|
|
|
|
|
buf=malloc(size*UTF8SZ+1);
|
|
|
|
printvalue(buf,size*UTF8SZ+1,size,0,getscientific(sheet,x,y,z),getprecision(sheet,x,y,z),sheet,x,y,z);
|
|
|
|
adjust(getadjust(sheet,x,y,z),buf,size);
|
|
|
|
if (fputs_close(buf,fp)==EOF)
|
|
|
|
{
|
|
|
|
free(buf);
|
|
|
|
return strerror(errno);
|
|
|
|
}
|
|
|
|
for (fill=strlen(buf); fill<size; ++fill) if (fputc_close(' ',fp)==EOF)
|
|
|
|
{
|
|
|
|
free(buf);
|
|
|
|
return strerror(errno);
|
|
|
|
}
|
|
|
|
free(buf);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (fill=0; fill<size; ++fill) if (fputc_close(' ',fp)==EOF) return strerror(errno);
|
|
|
|
}
|
|
|
|
++*count;
|
|
|
|
}
|
|
|
|
if (fputc_close('\n',fp)==EOF) return strerror(errno);
|
|
|
|
}
|
|
|
|
if (z<z2 && fputs_close("\f",fp)==EOF) return strerror(errno);
|
|
|
|
}
|
|
|
|
if (fclose(fp)==EOF) return strerror(errno);
|
|
|
|
return (const char*)0;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* savecsv -- save as CSV */ /*{{{*/
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
/* variables */ /*{{{*/
|
|
|
|
FILE *fp;
|
|
|
|
int x,y,z;
|
|
|
|
/*}}}*/
|
|
|
|
|
|
|
|
/* 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");
|
|
|
|
if ((fp=fopen(name,"w"))==(FILE*)0) return strerror(errno);
|
|
|
|
for (z=z1; z<=z2; ++z)
|
|
|
|
{
|
|
|
|
for (y=y1; y<=y2; ++y)
|
|
|
|
{
|
|
|
|
for (x=x1; x<=x2; ++x)
|
|
|
|
{
|
|
|
|
if (x>x1) if (fputc_close(sep,fp)==EOF) return strerror(errno);
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
if (CELL_AT(sheet,x,y,z)!=NULLCELL)
|
2019-07-22 20:32:33 +00:00
|
|
|
{
|
|
|
|
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);
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
if (CELL_AT(sheet,x,y,z)->value.type==STRING && fputc_close('"',fp)==EOF)
|
2019-07-22 20:32:33 +00:00
|
|
|
{
|
|
|
|
free(buf);
|
|
|
|
return strerror(errno);
|
|
|
|
}
|
|
|
|
for (s=buf; *s; ++s)
|
|
|
|
{
|
|
|
|
if (fputc_close(*s,fp)==EOF || (*s=='"' && fputc_close(*s,fp)==EOF))
|
|
|
|
{
|
|
|
|
free(buf);
|
|
|
|
return strerror(errno);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
free(buf);
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
if (CELL_AT(sheet,x,y,z)->value.type==STRING && fputc_close('"',fp)==EOF) return strerror(errno);
|
2019-07-22 20:32:33 +00:00
|
|
|
}
|
|
|
|
++*count;
|
|
|
|
}
|
|
|
|
if (fputc_close('\n',fp)==EOF) return strerror(errno);
|
|
|
|
}
|
|
|
|
if (z<z2 && fputs_close("\f",fp)==EOF) return strerror(errno);
|
|
|
|
}
|
|
|
|
if (fclose(fp)==EOF) return strerror(errno);
|
|
|
|
return (const char*)0;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* saveport -- save as portable text */ /*{{{*/
|
|
|
|
const char *saveport(Sheet *sheet, const char *name, unsigned int *count)
|
|
|
|
{
|
|
|
|
/* variables */ /*{{{*/
|
|
|
|
FILE *fp;
|
|
|
|
int x,y,z;
|
|
|
|
/*}}}*/
|
|
|
|
|
|
|
|
/* asserts */ /*{{{*/
|
|
|
|
assert(sheet!=(Sheet*)0);
|
|
|
|
assert(name!=(const char*)0);
|
|
|
|
/*}}}*/
|
|
|
|
*count=0;
|
|
|
|
if ((fp=fopen(name,"w"))==(FILE*)0) return strerror(errno);
|
|
|
|
fprintf(fp,"# This is a work sheet generated with teapot %s.\n",VERSION);
|
|
|
|
for (z=sheet->dimz-1; z>=0; --z)
|
|
|
|
{
|
|
|
|
for (y=sheet->dimy-1; y>=0; --y)
|
|
|
|
{
|
|
|
|
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));
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
if (CELL_AT(sheet,x,y,z)!=NULLCELL)
|
2019-07-22 20:32:33 +00:00
|
|
|
{
|
|
|
|
fprintf(fp,"C%d %d %d ",x,y,z);
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
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)
|
2019-07-22 20:32:33 +00:00
|
|
|
{
|
|
|
|
char buf[4096];
|
|
|
|
|
|
|
|
if (fputc_close(':',fp)==EOF) return strerror(errno);
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
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);
|
2019-07-22 20:32:33 +00:00
|
|
|
if (fputs_close(buf,fp)==EOF) return strerror(errno);
|
|
|
|
}
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
if (CELL_AT(sheet,x,y,z)->ccontents)
|
2019-07-22 20:32:33 +00:00
|
|
|
{
|
|
|
|
char buf[4096];
|
|
|
|
|
|
|
|
if (fputs_close("\\\n",fp)==EOF) return strerror(errno);
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
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);
|
2019-07-22 20:32:33 +00:00
|
|
|
if (fputs_close(buf,fp)==EOF) return strerror(errno);
|
|
|
|
}
|
|
|
|
if (fputc_close('\n',fp)==EOF) return strerror(errno);
|
|
|
|
++*count;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
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;
|
|
|
|
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;
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
/* remove nl */ /*{{{*/
|
|
|
|
width=strlen(buf);
|
|
|
|
if (width>0 && buf[width-1]=='\n') buf[--width]='\0';
|
|
|
|
/*}}}*/
|
|
|
|
switch (buf[0])
|
|
|
|
{
|
|
|
|
/* C -- parse cell */ /*{{{*/
|
|
|
|
case 'C':
|
|
|
|
{
|
|
|
|
int cc=0;
|
|
|
|
|
|
|
|
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;
|
|
|
|
/* parse x y and z */ /*{{{*/
|
|
|
|
os=ns=buf+1;
|
|
|
|
x=posnumber(os,&ns);
|
|
|
|
if (os==ns)
|
|
|
|
{
|
|
|
|
sprintf(errbuf,_("Parse error for x position in line %d"),line);
|
|
|
|
err=errbuf;
|
|
|
|
goto eek;
|
|
|
|
}
|
|
|
|
while (*ns==' ') ++ns;
|
|
|
|
os=ns;
|
|
|
|
y=posnumber(os,&ns);
|
|
|
|
if (os==ns)
|
|
|
|
{
|
|
|
|
sprintf(errbuf,_("Parse error for y position in line %d"),line);
|
|
|
|
err=errbuf;
|
|
|
|
goto eek;
|
|
|
|
}
|
|
|
|
while (*ns==' ') ++ns;
|
|
|
|
os=ns;
|
|
|
|
z=posnumber(os,&ns);
|
|
|
|
if (os==ns)
|
|
|
|
{
|
|
|
|
sprintf(errbuf,_("Parse error for z position in line %d"),line);
|
|
|
|
err=errbuf;
|
|
|
|
goto eek;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* parse optional attributes */ /*{{{*/
|
|
|
|
do
|
|
|
|
{
|
|
|
|
while (*ns==' ') ++ns;
|
|
|
|
switch (*ns)
|
|
|
|
{
|
|
|
|
/* A -- adjustment */ /*{{{*/
|
|
|
|
case 'A':
|
|
|
|
{
|
|
|
|
++ns;
|
|
|
|
switch (*ns)
|
|
|
|
{
|
|
|
|
case 'l': adjust=LEFT; ++ns; break;
|
|
|
|
case 'r': adjust=RIGHT; ++ns; break;
|
|
|
|
case 'c': adjust=CENTER; ++ns; break;
|
|
|
|
default: sprintf(errbuf,_("Parse error for adjustment in line %d"),line); err=errbuf; goto eek;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* L -- label */ /*{{{*/
|
|
|
|
case 'L':
|
|
|
|
{
|
|
|
|
char buf[1024],*p;
|
|
|
|
|
|
|
|
p=buf;
|
|
|
|
++ns;
|
|
|
|
while (*ns && *ns!=' ') { *p=*ns; ++p; ++ns; }
|
|
|
|
*p='\0';
|
|
|
|
label=mystrmalloc(buf);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* P -- precision */ /*{{{*/
|
|
|
|
case 'P':
|
|
|
|
{
|
|
|
|
os=++ns;
|
|
|
|
precision=posnumber(os,&ns);
|
|
|
|
if (os==ns)
|
|
|
|
{
|
|
|
|
sprintf(errbuf,_("Parse error for precision in line %d"),line);
|
|
|
|
err=errbuf;
|
|
|
|
goto eek;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* S -- shadowed */ /*{{{*/
|
|
|
|
case 'S':
|
|
|
|
{
|
|
|
|
if (x==0)
|
|
|
|
{
|
|
|
|
sprintf(errbuf,_("Trying to shadow cell (%d,%d,%d) in line %d"),x,y,z,line);
|
|
|
|
err=errbuf;
|
|
|
|
goto eek;
|
|
|
|
}
|
|
|
|
++ns;
|
|
|
|
shadowed=1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* U -- underline */ /*{{{*/
|
|
|
|
case 'U':
|
|
|
|
{
|
|
|
|
if (x==0)
|
|
|
|
{
|
|
|
|
sprintf(errbuf,_("Trying to underline cell (%d,%d,%d) in line %d"),x,y,z,line);
|
|
|
|
err=errbuf;
|
|
|
|
goto eek;
|
|
|
|
}
|
|
|
|
++ns;
|
|
|
|
underline=1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* B -- bold */ /*{{{*/
|
|
|
|
case 'B':
|
|
|
|
{
|
|
|
|
if (x==0)
|
|
|
|
{
|
|
|
|
sprintf(errbuf,_("Trying to bold cell (%d,%d,%d) in line %d"),x,y,z,line);
|
|
|
|
err=errbuf;
|
|
|
|
goto eek;
|
|
|
|
}
|
|
|
|
++ns;
|
|
|
|
bold=1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* E -- scientific */ /*{{{*/
|
|
|
|
case 'E':
|
|
|
|
{
|
|
|
|
++ns;
|
|
|
|
scientific=1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* O -- locked */ /*{{{*/
|
|
|
|
case 'O':
|
|
|
|
{
|
|
|
|
++ns;
|
|
|
|
locked=1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* T -- transparent */ /*{{{*/
|
|
|
|
case 'T':
|
|
|
|
{
|
|
|
|
++ns;
|
|
|
|
transparent=1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* I -- ignored */ /*{{{*/
|
|
|
|
case 'I':
|
|
|
|
{
|
|
|
|
++ns;
|
|
|
|
ignored=1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* : \0 -- do nothing */ /*{{{*/
|
|
|
|
case ':':
|
|
|
|
case '\0': break;
|
|
|
|
/*}}}*/
|
|
|
|
/* default -- error */ /*{{{*/
|
|
|
|
default: sprintf(errbuf,_("Invalid option %c in line %d"),*ns,line); err=errbuf; goto eek;
|
|
|
|
/*}}}*/
|
|
|
|
}
|
|
|
|
} while (*ns!=':' && *ns!='\0');
|
|
|
|
/*}}}*/
|
|
|
|
/* convert remaining string into token sequence */ /*{{{*/
|
|
|
|
if (*ns)
|
|
|
|
{
|
|
|
|
++ns;
|
|
|
|
contents=scan(&ns);
|
|
|
|
if (contents==(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 (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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
initcell(sheet,x,y,z);
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
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;
|
2019-07-22 20:32:33 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* W -- column width */ /*{{{*/
|
|
|
|
case 'W':
|
|
|
|
{
|
|
|
|
/* parse x and z */ /*{{{*/
|
|
|
|
os=ns=buf+1;
|
|
|
|
x=posnumber(os,&ns);
|
|
|
|
if (os==ns)
|
|
|
|
{
|
|
|
|
sprintf(errbuf,_("Parse error for x position in line %d"),line);
|
|
|
|
err=errbuf;
|
|
|
|
goto eek;
|
|
|
|
}
|
|
|
|
while (*ns==' ') ++ns;
|
|
|
|
os=ns;
|
|
|
|
z=posnumber(os,&ns);
|
|
|
|
if (os==ns)
|
|
|
|
{
|
|
|
|
sprintf(errbuf,_("Parse error for z position in line %d"),line);
|
|
|
|
err=errbuf;
|
|
|
|
goto eek;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* parse width */ /*{{{*/
|
|
|
|
while (*ns==' ') ++ns;
|
|
|
|
os=ns;
|
|
|
|
width=posnumber(os,&ns);
|
|
|
|
if (os==ns)
|
|
|
|
{
|
|
|
|
sprintf(errbuf,_("Parse error for width in line %d"),line);
|
|
|
|
err=errbuf;
|
|
|
|
goto eek;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
setwidth(sheet,x,z,width);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* # -- comment */ /*{{{*/
|
|
|
|
case '#': break;
|
|
|
|
/*}}}*/
|
|
|
|
/* default -- error */ /*{{{*/
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
sprintf(errbuf,_("Unknown tag %c in line %d"),buf[0],line);
|
|
|
|
err=errbuf;
|
|
|
|
goto eek;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
}
|
|
|
|
++line;
|
|
|
|
}
|
|
|
|
eek:
|
|
|
|
if (fclose(fp)==EOF && err==(const char*)0) err=strerror(errno);
|
|
|
|
sheet->changed=0;
|
|
|
|
cachelabels(sheet);
|
|
|
|
forceupdate(sheet);
|
|
|
|
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;
|
|
|
|
int width;
|
|
|
|
int u;
|
|
|
|
int olderror;
|
|
|
|
/*}}}*/
|
|
|
|
|
|
|
|
if ((fp=fopen(name,"r"))==(FILE*)0) return strerror(errno);
|
|
|
|
xdrstdio_create(&xdrs,fp,XDR_DECODE);
|
|
|
|
if (!xdr_magic(&xdrs))
|
|
|
|
{
|
|
|
|
#if 0
|
|
|
|
xdr_destroy(&xdrs);
|
|
|
|
fclose(fp);
|
|
|
|
return _("This is not a teapot worksheet in XDR format");
|
|
|
|
#else
|
|
|
|
xdr_destroy(&xdrs);
|
|
|
|
rewind(fp);
|
|
|
|
xdrstdio_create(&xdrs,fp,XDR_DECODE);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
freesheet(sheet,0);
|
|
|
|
while (xdr_int(&xdrs,&u)) switch (u)
|
|
|
|
{
|
|
|
|
/* 0 -- column width element */ /*{{{*/
|
|
|
|
case 0:
|
|
|
|
{
|
|
|
|
if (xdr_column(&xdrs,&x,&z,&width)==0)
|
|
|
|
{
|
|
|
|
olderror=errno;
|
|
|
|
xdr_destroy(&xdrs);
|
|
|
|
(void)fclose(fp);
|
|
|
|
return strerror(olderror);
|
|
|
|
}
|
|
|
|
setwidth(sheet,x,z,width);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* 1 -- cell element */ /*{{{*/
|
|
|
|
case 1:
|
|
|
|
{
|
|
|
|
if (xdr_int(&xdrs,&x)==0 || xdr_int(&xdrs,&y)==0 || xdr_int(&xdrs,&z)==0)
|
|
|
|
{
|
|
|
|
olderror=errno;
|
|
|
|
xdr_destroy(&xdrs);
|
|
|
|
(void)fclose(fp);
|
|
|
|
return strerror(olderror);
|
|
|
|
}
|
|
|
|
initcell(sheet,x,y,z);
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
if (xdr_cell(&xdrs,CELL_AT(sheet,x,y,z))==0)
|
2019-07-22 20:32:33 +00:00
|
|
|
{
|
|
|
|
freecell(sheet,x,y,z);
|
|
|
|
olderror=errno;
|
|
|
|
xdr_destroy(&xdrs);
|
|
|
|
(void)fclose(fp);
|
|
|
|
return strerror(olderror);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* default -- should not happen */ /*{{{*/
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
xdr_destroy(&xdrs);
|
|
|
|
fclose(fp);
|
|
|
|
sheet->changed=0;
|
|
|
|
cachelabels(sheet);
|
|
|
|
forceupdate(sheet);
|
|
|
|
return _("Invalid record, loading aborted");
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
}
|
|
|
|
xdr_destroy(&xdrs);
|
|
|
|
if (fclose(fp)==EOF) return strerror(errno);
|
|
|
|
sheet->changed=0;
|
|
|
|
cachelabels(sheet);
|
|
|
|
forceupdate(sheet);
|
|
|
|
redraw_sheet(sheet);
|
|
|
|
return (const char*)0;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* loadcsv -- load/merge CSVs */ /*{{{*/
|
|
|
|
const char *loadcsv(Sheet *sheet, const char *name)
|
|
|
|
{
|
|
|
|
/* variables */ /*{{{*/
|
|
|
|
FILE *fp;
|
|
|
|
Token **t;
|
|
|
|
const char *err;
|
|
|
|
int line,x;
|
|
|
|
char ln[4096];
|
|
|
|
const char *str;
|
|
|
|
double value;
|
|
|
|
long lvalue;
|
|
|
|
int separator = 0;
|
|
|
|
/*}}}*/
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
const char *s;
|
|
|
|
const char *cend;
|
|
|
|
|
|
|
|
if (!separator) { /* FIXME: find a better way to autodetect */
|
|
|
|
int ccnt = 0, scnt = 0;
|
|
|
|
char *pos = ln;
|
|
|
|
while ((pos = strchr(pos, ','))) pos++, ccnt++;
|
|
|
|
pos = ln;
|
|
|
|
while ((pos = strchr(pos, ';'))) pos++, scnt++;
|
|
|
|
if (ccnt || scnt) separator = 1;
|
|
|
|
csv_setopt(scnt > ccnt);
|
|
|
|
}
|
|
|
|
|
|
|
|
s=cend=ln;
|
|
|
|
x=0;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
t=malloc(2*sizeof(Token*));
|
|
|
|
t[0]=malloc(sizeof(Token));
|
|
|
|
t[1]=(Token*)0;
|
|
|
|
lvalue=csv_long(s,&cend);
|
|
|
|
if (s!=cend) /* ok, it is a integer */ /*{{{*/
|
|
|
|
{
|
|
|
|
t[0]->type=INT;
|
|
|
|
t[0]->u.integer=lvalue;
|
|
|
|
putcont(sheet, sheet->curx+x, sheet->cury+line-1, sheet->curz, t, 0);
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
else
|
|
|
|
{
|
|
|
|
value=csv_double(s,&cend);
|
|
|
|
if (s!=cend) /* ok, it is a double */ /*{{{*/
|
|
|
|
{
|
|
|
|
t[0]->type=FLOAT;
|
|
|
|
t[0]->u.flt=value;
|
|
|
|
putcont(sheet, sheet->curx+x, sheet->cury+line-1, sheet->curz, t, 0);
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
else
|
|
|
|
{
|
|
|
|
str=csv_string(s,&cend);
|
|
|
|
if (s!=cend) /* ok, it is a string */ /*{{{*/
|
|
|
|
{
|
|
|
|
t[0]->type=STRING;
|
|
|
|
t[0]->u.string=mystrmalloc(str);
|
|
|
|
putcont(sheet, sheet->curx+x, sheet->cury+line-1, sheet->curz, t, 0);
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tvecfree(t);
|
|
|
|
csv_separator(s,&cend);
|
|
|
|
while (s==cend && *s && *s!='\n')
|
|
|
|
{
|
|
|
|
err=_("unknown values ignored");
|
|
|
|
csv_separator(++s,&cend);
|
|
|
|
}
|
|
|
|
/* else it is nothing, which does not need to be stored :) */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} while (s!=cend ? s=cend,++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)
|
|
|
|
{
|
|
|
|
/* variables */ /*{{{*/
|
|
|
|
int x,y,z;
|
|
|
|
/*}}}*/
|
|
|
|
|
|
|
|
switch (ins)
|
|
|
|
{
|
|
|
|
/* IN_X */ /*{{{*/
|
|
|
|
case IN_X:
|
|
|
|
{
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
resize(sheet,x,y,z);
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
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;
|
2019-07-22 20:32:33 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* IN_Y */ /*{{{*/
|
|
|
|
case IN_Y:
|
|
|
|
{
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
resize(sheet,x,y,z);
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
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;
|
2019-07-22 20:32:33 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* IN_Z */ /*{{{*/
|
|
|
|
case IN_Z:
|
|
|
|
{
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
resize(sheet,x,y,z);
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
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;
|
2019-07-22 20:32:33 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* default */ /*{{{*/
|
|
|
|
default: assert(0);
|
|
|
|
/*}}}*/
|
|
|
|
}
|
|
|
|
sheet->changed=1;
|
|
|
|
cachelabels(sheet);
|
|
|
|
forceupdate(sheet);
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* deletecube -- delete a block */ /*{{{*/
|
|
|
|
void deletecube(Sheet *sheet, int x1, int y1, int z1, int x2, int y2, int z2, Direction del)
|
|
|
|
{
|
|
|
|
/* variables */ /*{{{*/
|
|
|
|
int x,y,z;
|
|
|
|
/*}}}*/
|
|
|
|
|
|
|
|
/* 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);
|
|
|
|
/*}}}*/
|
|
|
|
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)<sheet->dimx && y<sheet->dimy && z<sheet->dimz)
|
|
|
|
{
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
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;
|
2019-07-22 20:32:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
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 (x<sheet->dimx && y+(y2-y1+1)<sheet->dimy && z<sheet->dimz)
|
|
|
|
{
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
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;
|
2019-07-22 20:32:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
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 (x<sheet->dimx && y<sheet->dimy && z+(z2-z1+1)<sheet->dimz)
|
|
|
|
{
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
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;
|
2019-07-22 20:32:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* default */ /*{{{*/
|
|
|
|
default: assert(0);
|
|
|
|
/*}}}*/
|
|
|
|
}
|
|
|
|
sheet->changed=1;
|
|
|
|
cachelabels(sheet);
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
/* variables */ /*{{{*/
|
|
|
|
int dirx, diry, dirz;
|
|
|
|
int widx, widy, widz;
|
|
|
|
int x, y, z;
|
|
|
|
int xf, xt, yf, yt, zf, zt;
|
|
|
|
/*}}}*/
|
|
|
|
|
|
|
|
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 (copy)
|
|
|
|
{
|
|
|
|
copycell(sheet,x1+x,y1+y,z1+z,sheet,x3+x,y3+y,z3+z);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (x1+x<sheet->dimx && y1+y<sheet->dimy && z1+z<sheet->dimz)
|
|
|
|
{
|
|
|
|
resize(sheet,x3+x,y3+y,z3+z);
|
Prevent phantom values when clocking, resetting, and clocking again
In the end it turned out that the cause of the phantom values was
short-cutting in getvalue() when the contents of a cell were empty,
preventing the update of the internal cache of the value of the cell.
However, tracking this down (and getting the associated memory management
correct) necessitated implementing a debugging mode in which I could
dump the internal states of cells and print various other stuff to standard
output. It also involved understanding the meaning of various pointers in
the code, in the process of which I renamed some commonly used macros,
particularly the former SHEET(s,x,y,z) which was not returning a Sheet at
all but rather a pointer to a Cell. So this macro is now called CELL_AT. I
also replaced several very repeatedly used patterns of checking the validity
of locations and pointers with macros, now defined in sheet.h.
Therefore, unfortunately the (relatively small in the end) bugfix for this
major issue is entangled with numerous textual changes to the code made
in tracking it down.
Fixes #18.
Closes #19.
2019-07-24 17:47:39 +00:00
|
|
|
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;
|
2019-07-22 20:32:33 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
freecell(sheet,x3+x,y3+y,z3+z);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sheet->changed=1;
|
|
|
|
cachelabels(sheet);
|
|
|
|
forceupdate(sheet);
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
/* sortblock -- sort a block */ /*{{{*/
|
|
|
|
/* Notes */ /*{{{*/
|
|
|
|
/*
|
|
|
|
The idea is to sort a block of cells in one direction by swapping the
|
|
|
|
planes which are canonical to the sort key vectors. An example is to
|
|
|
|
sort a two dimensional block line-wise with one column as sort key.
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
/* variables */ /*{{{*/
|
|
|
|
int x,y,z;
|
|
|
|
int incx=0,incy=0,incz=0;
|
|
|
|
int distx,disty,distz;
|
|
|
|
int i,r=-3,norel,work;
|
|
|
|
/*}}}*/
|
|
|
|
|
|
|
|
/* asserts */ /*{{{*/
|
|
|
|
assert(sklen>0);
|
|
|
|
assert(x1>=0);
|
|
|
|
assert(x2>=0);
|
|
|
|
assert(y1>=0);
|
|
|
|
assert(y2>=0);
|
|
|
|
assert(z1>=0);
|
|
|
|
assert(z2>=0);
|
|
|
|
/*}}}*/
|
|
|
|
norel=0;
|
|
|
|
posorder(&x1,&x2);
|
|
|
|
posorder(&y1,&y2);
|
|
|
|
posorder(&z1,&z2);
|
|
|
|
distx=(x2-x1+1);
|
|
|
|
disty=(y2-y1+1);
|
|
|
|
distz=(z2-z1+1);
|
|
|
|
switch (dir)
|
|
|
|
{
|
|
|
|
case IN_X: incx=1; --x2; incy=0; incz=0; distx=1; break;
|
|
|
|
case IN_Y: incx=0; incy=1; --y2; incz=0; disty=1; break;
|
|
|
|
case IN_Z: incx=0; incy=0; incz=1; --z2; distz=1; break;
|
|
|
|
default: assert(0);
|
|
|
|
}
|
|
|
|
assert(incx || incy || incz);
|
|
|
|
do
|
|
|
|
{
|
|
|
|
work=0;
|
|
|
|
for (x=x1,y=y1,z=z1; x<=x2&&y<=y2&&z<=z2; x+=incx,y+=incy,z+=incz)
|
|
|
|
{
|
|
|
|
for (i=0; i<sklen; ++i)
|
|
|
|
{
|
|
|
|
r=cmpcell(sheet,x+sk[i].x,y+sk[i].y,z+sk[i].z,sheet,x+incx+sk[i].x,y+incy+sk[i].y,z+incz+sk[i].z,sk[i].sortkey);
|
|
|
|
if (r==2) norel=1;
|
|
|
|
else if (r==-1 || r==1) break;
|
|
|
|
else assert(r==0);
|
|
|
|
}
|
|
|
|
if (r==1)
|
|
|
|
{
|
|
|
|
swapblock(sheet,dir==IN_X ? x : x1,dir==IN_Y ? y : y1,dir==IN_Z ? z : z1,sheet,dir==IN_X ? x+incx : x1,dir==IN_Y ? y+incy : y1,dir==IN_Z ? z+incz : z1,distx,disty,distz);
|
|
|
|
work=1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
x2-=incx;
|
|
|
|
y2-=incy;
|
|
|
|
z2-=incz;
|
|
|
|
} while (work);
|
|
|
|
cachelabels(sheet);
|
|
|
|
forceupdate(sheet);
|
|
|
|
sheet->changed=1;
|
|
|
|
if (norel) return _("uncomparable elements");
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
switch (dir)
|
|
|
|
{
|
|
|
|
case IN_X: /* left-right */ /*{{{*/
|
|
|
|
{
|
|
|
|
int x,middle=(x2-x1+1)/2;
|
|
|
|
for (x=0; x<middle; ++x)
|
|
|
|
{
|
|
|
|
swapblock(sheet,x1+x,y1,z1,sheet,x2-x,y1,z1, 1,y2-y1+1,z2-z1+1);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
case IN_Y: /* upside-down */ /*{{{*/
|
|
|
|
{
|
|
|
|
int y,middle=(y2-y1+1)/2;
|
|
|
|
for (y=0; y<middle; ++y)
|
|
|
|
{
|
|
|
|
swapblock(sheet,x1,y1+y,z1,sheet,x1,y2-y,z1, x2-x1+1,1,z2-z1+1);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
case IN_Z: /* front-back */ /*{{{*/
|
|
|
|
{
|
|
|
|
int z,middle=(z2-z1+1)/2;
|
|
|
|
for (z=0; z<middle; ++z)
|
|
|
|
{
|
|
|
|
swapblock(sheet,x1,y1,z1+z,sheet,x1,y1,z2-z, x2-x1+1,y2-y1+1,1);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
default: assert(0);
|
|
|
|
}
|
|
|
|
sheet->changed=1;
|
|
|
|
cachelabels(sheet);
|
|
|
|
forceupdate(sheet);
|
|
|
|
}
|
|
|
|
/*}}}*/
|