2019-07-27 07:00:03 +00:00
|
|
|
#include "cell.h"
|
|
|
|
|
|
|
|
#include <assert.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "default.h"
|
|
|
|
#include "eval.h"
|
|
|
|
#include "main.h"
|
|
|
|
|
|
|
|
/* initcellcontents - make a fresh cell into the "empty" one; don't worry
|
|
|
|
about freeing anything there, that will have been handled. */
|
|
|
|
void initcellcontents(Cell *fresh)
|
|
|
|
{
|
|
|
|
(void)memset(fresh->contents, 0, sizeof(fresh->contents));
|
|
|
|
fresh->label=(char*)0;
|
|
|
|
fresh->adjust=AUTOADJUST;
|
|
|
|
fresh->precision=-1;
|
|
|
|
fresh->shadowed=0;
|
|
|
|
fresh->bold=0;
|
|
|
|
fresh->underline=0;
|
|
|
|
fresh->scientific=DEF_SCIENTIFIC;
|
|
|
|
fresh->value.type=EMPTY;
|
|
|
|
fresh->resvalue.type=EMPTY;
|
|
|
|
fresh->locked=0;
|
|
|
|
fresh->ignored=0;
|
|
|
|
fresh->clock_t0=0;
|
|
|
|
fresh->clock_t1=0;
|
|
|
|
fresh->clock_t2=0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* getcont -- get contents */
|
|
|
|
Token **getcont(const Cell *cell, ContentVariety v)
|
|
|
|
{
|
|
|
|
if (cell == NULLCELL) return EMPTY_TVEC;
|
|
|
|
if (v == CONTINGENT)
|
|
|
|
v = (cell->clock_t0 && cell->contents[ITERATIVE]) ? ITERATIVE : BASE;
|
|
|
|
return cell->contents[v];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* getadjust -- get cell adjustment */
|
|
|
|
Adjust getadjust(const Cell* cell)
|
|
|
|
{
|
|
|
|
if (cell == NULLCELL) return LEFT;
|
|
|
|
else if (cell->adjust == AUTOADJUST)
|
|
|
|
return (cell->value.type == INT || cell->value.type == FLOAT ? RIGHT : LEFT);
|
|
|
|
else return cell->adjust;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* shadowed -- is cell shadowed? */
|
|
|
|
bool shadowed(const Cell *cell)
|
|
|
|
{
|
|
|
|
return (cell != NULLCELL) && cell->shadowed;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* isbold -- is cell bold? */
|
|
|
|
bool isbold(const Cell* cell)
|
|
|
|
{
|
|
|
|
return (cell != NULLCELL) && cell->bold;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* isunderline -- is cell underlined? */
|
|
|
|
bool underlined(const Cell *cell)
|
|
|
|
{
|
|
|
|
return (cell != NULLCELL) && cell->underline;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* locked -- is cell locked? */
|
|
|
|
bool locked(const Cell *cell)
|
|
|
|
{
|
|
|
|
return (cell != NULLCELL) && cell->locked;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* transparent -- is cell transparent? */
|
|
|
|
bool transparent(const Cell* cell)
|
|
|
|
{
|
|
|
|
return (cell != NULLCELL) && cell->transparent;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ignored -- is cell ignored? */
|
|
|
|
bool ignored(const Cell *cell)
|
|
|
|
{
|
|
|
|
return (cell != NULLCELL) && cell->ignored;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* getscientific -- should value be displayed in scientific notation? */
|
|
|
|
bool getscientific(const Cell *cell )
|
|
|
|
{
|
|
|
|
return (cell == NULLCELL) ? DEF_SCIENTIFIC : cell->scientific;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* getprecision -- get cell precision */
|
|
|
|
int getprecision(const Cell *cell)
|
|
|
|
{
|
|
|
|
if (cell == NULLCELL || cell->precision == -1) return def_precision;
|
|
|
|
return cell->precision;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* getlabel -- get cell label */
|
|
|
|
const char *getlabel(const Cell* cell)
|
|
|
|
{
|
|
|
|
if (cell == NULLCELL || cell->label == (char*)0) return "";
|
|
|
|
return cell->label;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* copytokens -- copy a sequence of tokens, possibly reallocating dest */
|
|
|
|
static void copytokens(Token*** totoks, Token** fromtoks)
|
|
|
|
{
|
|
|
|
size_t from_len = tveclen(fromtoks);
|
|
|
|
if (from_len == 0)
|
|
|
|
{
|
|
|
|
tvecfree(*totoks);
|
|
|
|
*totoks = EMPTY_TVEC;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t to_len = tveclen(*totoks);
|
|
|
|
if (from_len > to_len || *totoks == fromtoks)
|
|
|
|
{
|
|
|
|
if (*totoks != fromtoks) tvecfree(*totoks);
|
|
|
|
*totoks = malloc((from_len+1)*sizeof(Token*));
|
|
|
|
(*totoks)[from_len] = NULLTOKEN;
|
|
|
|
} else {
|
|
|
|
tvecfreetoks(*totoks);
|
|
|
|
}
|
|
|
|
for (size_t 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]));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* freecellcontents -- free the resources of the cell at destruction time */
|
|
|
|
void freecellcontents(Cell *faded)
|
|
|
|
{
|
|
|
|
tvecfree(faded->contents[BASE]);
|
|
|
|
tvecfree(faded->contents[ITERATIVE]);
|
|
|
|
tfree(&(faded->value));
|
|
|
|
tfree(&(faded->resvalue));
|
|
|
|
if (faded->label != (char*)0) {
|
|
|
|
free(faded->label);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* copycell - copies one Cell to another, handling any allocation issues */
|
|
|
|
void copycell(Cell *to, const Cell *fromcell)
|
|
|
|
{
|
|
|
|
assert(to != NULLCELL);
|
2019-07-27 08:08:42 +00:00
|
|
|
if (to == fromcell) return;
|
2019-07-27 07:00:03 +00:00
|
|
|
|
|
|
|
freecellcontents(to);
|
|
|
|
if (fromcell != NULLCELL) {
|
|
|
|
memcpy(to, fromcell, sizeof(Cell));
|
|
|
|
copytokens(&(to->contents[BASE]), fromcell->contents[BASE]);
|
|
|
|
copytokens(&(to->contents[ITERATIVE]), fromcell->contents[ITERATIVE]);
|
|
|
|
if (fromcell->label != (char*)0) {
|
|
|
|
size_t len = strlen(fromcell->label);
|
|
|
|
to->label = strcpy(malloc(len+2), fromcell->label);
|
|
|
|
(to->label)[len] = '_';
|
|
|
|
(to->label)[len+1] = '\0';
|
|
|
|
}
|
|
|
|
to->value.type = EMPTY;
|
|
|
|
to->resvalue.type = EMPTY;
|
|
|
|
} else {
|
|
|
|
initcellcontents(to);
|
|
|
|
}
|
|
|
|
}
|