/******************************************************************************* * Copyright (c) 2013-2021, Andrés Martinelli * * All rights reserved. * * * * This file is a part of sc-im * * * * sc-im is a spreadsheet program that is based on sc. The original authors * * of sc are James Gosling and Mark Weiser, and mods were later added by * * Chuck Martin. * * * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * 3. All advertising materials mentioning features or use of this software * * must display the following acknowledgement: * * This product includes software developed by Andrés Martinelli * * . * * 4. Neither the name of the Andrés Martinelli nor the * * names of other contributors may be used to endorse or promote products * * derived from this software without specific prior written permission. * * * * THIS SOFTWARE IS PROVIDED BY ANDRES MARTINELLI ''AS IS'' AND ANY * * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * * DISCLAIMED. IN NO EVENT SHALL ANDRES MARTINELLI BE LIABLE FOR ANY * * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;* * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *******************************************************************************/ /** * \file vmtbl.c * \author Andrés Martinelli * \date 2017-07-18 * \brief TODO Write a tbrief file description. */ #include #include // for atoi #include #include "vmtbl.h" #include "sc.h" #include "macros.h" #include "conf.h" #include "trigger.h" #include "tui.h" #define ATBL_P(tbl, row, col) (*(tbl + row) + (col)) extern struct session * session; /* * check to see if *rowp && *colp are currently allocated, if not expand the * current size if we can. */ #ifndef PSC /** * \brief TODO Document checkbounds() * * \param[in] rowp * \param[in] colp * * \return none */ void checkbounds(struct sheet * sh, int * rowp, int * colp) { if (*rowp < 0) *rowp = 0; else if (*rowp >= sh->maxrows) { if (*colp >= sh->maxcols) { if (!growtbl(sh, GROWBOTH, *rowp, *colp)) { *rowp = sh->maxrows - 1; *colp = sh->maxcols - 1; } return; } else { if (!growtbl(sh, GROWROW, *rowp, 0)) *rowp = sh->maxrows - 1; return; } } if (*colp < 0) *colp = 0; else if (*colp >= sh->maxcols) { if (!growtbl(sh, GROWCOL, 0, *colp)) *colp = sh->maxcols - 1; } } #endif /* ! PSC */ /* scxrealloc will just scxmalloc if oldptr is == NULL */ #define GROWALLOC(newptr, oldptr, nelem, type, msg) \ newptr = (type *) scxrealloc((char *) oldptr, \ (unsigned)(nelem * sizeof(type))); \ if (newptr == (type *)NULL) { \ sc_error(msg); \ return (FALSE); \ } \ oldptr = newptr /* wait in case we can't alloc */ #ifndef PSC static char nolonger[] = "The table can't be any longer"; #endif /* !PSC */ static char nowider[] = "The table can't be any wider"; /** * \brief TODO Document growtbl() * * \details Grow the main && auxiliary tables (reset maxrows/mascols * as needed). toprow &&/|| topcol tells us a better guess of how big * to become. We return TRUE if we could grow, FALSE if not. * \param[in] rowcol * \param[in] toprow * \param[in] topcol * * \return TRUE if we could grow * \return FALSE if we cannot grow */ int growtbl(struct sheet * sh, int rowcol, int toprow, int topcol) { int * fwidth2; int * precision2; int * realfmt2; int newcols; #ifndef PSC struct ent *** tbl2; struct ent ** nullit; int cnt; unsigned char * col_hidden2; unsigned char * row_hidden2; unsigned char * col_frozen2; unsigned char * row_frozen2; unsigned char * row_format2; int newrows; int i; newrows = sh->maxrows; #endif /* ! PSC */ newcols = sh->maxcols; if (rowcol == GROWNEW) { #ifndef PSC sh->maxrows = toprow = 0; /* when we first start up, fill the screen w/ cells */ { int startval; startval = SC_DISPLAY_ROWS; newrows = startval > MINROWS ? startval : MINROWS; startval = SC_DISPLAY_COLS / DEFWIDTH; newcols = startval > MINCOLS ? startval : MINCOLS; } #else newcols = MINCOLS; #endif /* !PSC */ sh->maxcols = topcol = 0; } #ifndef PSC /* set how much to grow */ if ((rowcol == GROWROW) || (rowcol == GROWBOTH)) { if ((sh->maxcols == MAXROWS) || (toprow >= MAXROWS)) { sc_error(nolonger); return (FALSE); } if (toprow > sh->maxrows) newrows = GROWAMT + toprow; else newrows += GROWAMT; /* If we're close but less than MAXROWS, clip to max value */ if ( newrows > MAXROWS ) newrows = MAXROWS; } #endif /* !PSC */ if ((rowcol == GROWCOL) || (rowcol == GROWBOTH)) { if ((sh->maxcols == ABSMAXCOLS) || (topcol >= ABSMAXCOLS)) { sc_error(nowider); return (FALSE); } if (topcol > sh->maxcols) newcols = GROWAMT + topcol; else newcols += GROWAMT; if (newcols > ABSMAXCOLS) newcols = ABSMAXCOLS; } #ifndef PSC if ((rowcol == GROWROW) || (rowcol == GROWBOTH) || (rowcol == GROWNEW)) { struct ent *** lnullit; int lcnt; GROWALLOC(row_hidden2, sh->row_hidden, newrows, unsigned char, nolonger); memset(sh->row_hidden + sh->maxrows, 0, (newrows - sh->maxrows) * sizeof(unsigned char)); GROWALLOC(row_format2, sh->row_format, newrows, unsigned char, nolonger); memset(sh->row_format + sh->maxrows, 1, (newrows - sh->maxrows) * sizeof(unsigned char)); GROWALLOC(row_frozen2, sh->row_frozen, newrows, unsigned char, nolonger); memset(sh->row_frozen + sh->maxrows, 0, (newrows - sh->maxrows) * sizeof(unsigned char)); /* * alloc tbl row pointers, per net.lang.c, calloc does not * necessarily fill in NULL pointers */ GROWALLOC(tbl2, sh->tbl, newrows, struct ent **, nolonger); for (lnullit = sh->tbl + sh->maxrows, lcnt = 0; lcnt < newrows - sh->maxrows; lcnt++, lnullit++) *lnullit = (struct ent **)NULL; /* memset(tbl + maxrows, (char *) NULL, (newrows - maxrows) * (sizeof(struct ent **)));*/ } #endif /* !PSC */ if ((rowcol == GROWCOL) || (rowcol == GROWBOTH) || (rowcol == GROWNEW)) { GROWALLOC(fwidth2, sh->fwidth, newcols, int, nowider); GROWALLOC(precision2, sh->precision, newcols, int, nowider); GROWALLOC(realfmt2, sh->realfmt, newcols, int, nowider); #ifdef PSC memset(sh->fwidth + sh->maxcols, 0, (newcols - sh->maxcols) * sizeof(int)); memset(sh->precision + sh->maxcols, 0, (newcols - sh->maxcols) * sizeof(int)); memset(sh->realfmt + sh->maxcols, 0, (newcols - sh->maxcols) * sizeof(int)); } #else GROWALLOC(col_hidden2, sh->col_hidden, newcols, unsigned char, nowider); memset(sh->col_hidden + sh->maxcols, 0, (newcols - sh->maxcols) * sizeof(unsigned char)); for (i = sh->maxcols; i < newcols; i++) { sh->fwidth[i] = DEFWIDTH; sh->precision[i] = DEFPREC; sh->realfmt[i] = DEFREFMT; } GROWALLOC(col_frozen2, sh->col_frozen, newcols, unsigned char, nolonger); memset(sh->col_frozen + sh->maxcols, 0, (newcols - sh->maxcols) * sizeof(unsigned char)); /* [re]alloc the space for each row */ for (i = 0; i < sh->maxrows; i++) { if ((sh->tbl[i] = (struct ent **) scxrealloc((char *)sh->tbl[i], (unsigned) (newcols * sizeof(struct ent **)))) == (struct ent **)0) { sc_error(nowider); return(FALSE); } for (nullit = ATBL_P(sh->tbl, i, sh->maxcols), cnt = 0; cnt < newcols - sh->maxcols; cnt++, nullit++) *nullit = (struct ent *)NULL; /* memset((char *) ATBL(tbl,i, sh->maxcols), 0, (newcols - sh->maxcols) * sizeof(struct ent **)); */ } } else i = sh->maxrows; /* fill in the bottom of the table */ for (; i < newrows; i++) { if ((sh->tbl[i] = (struct ent **) scxmalloc((unsigned)(newcols * sizeof(struct ent **)))) == (struct ent **) 0) { sc_error(nowider); return(FALSE); } for (nullit = sh->tbl[i], cnt = 0; cnt < newcols; cnt++, nullit++) *nullit = (struct ent *)NULL; /* memset((char *) sh->tbl[i], 0, newcols * sizeof(struct ent **));*/ } sh->maxrows = newrows; #endif /* PSC */ sh->rescol = 2; if (sh->maxrows > 10) sh->rescol = 3; if (sh->maxrows > 100) sh->rescol = 4; if (sh->maxrows > 1000) sh->rescol = 5; if (sh->maxrows > 10000) sh->rescol = 6; if (sh->maxrows > 100000) sh->rescol = 7; if (sh->maxrows > 1000000) sh->rescol = 8; sh->maxcols = newcols; return (TRUE); } /** * \brief ATBL(): function to get ent from grid * * \param[in] tlb * \param[in] row * \param[in] col * * \return none */ struct ent ** ATBL(struct sheet * sh, struct ent ***tbl, int row, int col) { struct ent **ent=(*(sh->tbl+row)+(col)); struct ent *v= *ent; if ((v) && (v->trigger) && ((v->trigger->flag & TRG_READ) == TRG_READ)) { //sc_debug("row:%d %d", v->row, v->col); do_trigger(v,TRG_READ); } return ent; }