teapot-spreadsheet/src/common/cell.c

183 lines
4.6 KiB
C

#include "cell.h"
#include <assert.h>
#include <string.h>
#include "default.h"
#include "eval.h"
#include "main.h"
const ColorNum DefaultCN[] =
{ [FOREGROUND] = 0, [BACKGROUND] = 16, [NUM_COLOR_ASPECTS] = 255 };
/* 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;
for (ColorAspect a = FOREGROUND; a < NUM_COLOR_ASPECTS; ++a)
fresh->aspect[a] = DefaultCN[a];
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;
}
/* getcolor -- a color associated to cell */
ColorNum getcolor(const Cell* cell, ColorAspect aspect)
{
return cell == NULLCELL ? DefaultCN[aspect] : cell->aspect[aspect];
}
/* 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);
if (to == fromcell) return;
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);
}
}