/******************************************************************** This file is part of the abs 0.907 distribution. abs is a spreadsheet with graphical user interface. Copyright (C) 1998-2001 André Bertin (Andre.Bertin@ping.be) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version if in the same spirit as version 2. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Concact: abs@pi.be http://home.pi.be/bertin/abs.shtml *********************************************************************/ #include "cell.h" #include "worksheet.h" #include "workbook.h" #include "style.h" #include "y.tab.h" #include "memory.h" #include "date.h" #include "cell_vb.h" #include "gram_ext.h" #include "application.h" #include static int updating = 0; static int parsing = 0; static int setting_formula = 0; static int ncell = 0; static int parsingmacro; static Cell **toredraw = NULL; static int ntoredraw = 0; static char tmpbuf[256]; Cell *ActiveCell; Cell * cell_activate (Cell * cell) { ActiveCell = cell; if (ActiveWorksheet != NULL) { ActiveWorksheet->activecell = cell; if (ActiveWorksheet->cur_r != cell->r && ActiveWorksheet->cur_c != cell->c) worksheet_setcursor (ActiveWorksheet, cell->r, cell->c); } return ActiveCell; } Cell * newcell (r, c) int r, c; { Cell *nc; nc = (Cell *) absmalloc (sizeof (Cell), "newcell:Cell "); if (nc == NULL) { fprintf (stderr, "Cell: not allocated!"); return NULL; } nc->val.rec.d = 0.0; nc->val.type = DOUBLE; nc->formula = NULL; nc->style = NULL; nc->r = r; nc->c = c; nc->familly = NULL; nc->worksheet = ActiveWorksheet; nc->tree = NULL; nc->type = undef; nc->objnum = ncell++; return nc; } int clear_cell (Cell * cell) { if (cell == NULL) return 1; if (cell->val.type == STRING_CONSTANT && cell->val.rec.s != cell->formula + 1) if (cell->val.rec.s != NULL) absfree (cell->val.rec.s, "freecell:cell->val.rec.s "); if (cell->formula != NULL) absfree (cell->formula, "freecell:cell->formula "); if (cell->tree != NULL) { freenode (cell->tree); cell->tree = NULL; } if (cell->style != NULL) { freestyle (cell->style); cell->style = NULL; } cell->val.rec.d = 0.0; cell->val.type = DOUBLE; cell->formula = NULL; cell_isnew (cell); nupdate2 (cell, 1); cell->type = undef; return 0; } int freecell (cell) Cell *cell; { if (cell == NULL) return 1; if (cell->val.type == STRING_CONSTANT && cell->val.rec.s != cell->formula + 1) if (cell->val.rec.s != NULL) absfree (cell->val.rec.s, "freecell:cell->val.rec.s "); if (cell->formula != NULL) absfree (cell->formula, "freecell:cell->formula "); if (cell->tree != NULL) { freenode (cell->tree); cell->tree = NULL; } if (cell->style != NULL) { freestyle (cell->style); cell->style = NULL; } absfree (cell, "freecell:cell "); return 0; } int cell_write (cell, fp) Cell *cell; FILE *fp; { int deci, format; char *end = NULL; char chr[2]; int len = 0; int i; if (cell == NULL) return -1; if (cell->type == constant) { fprintf (fp, "absnc(%d,%d,\"", cell->r, cell->c); fprintf (fp, "%g", cell_getvalue (cell)); fprintf (fp, "\")\n"); } else if (cell->type == text || cell->type == formula) { fprintf (fp, "absnc(%d,%d,\"", cell->r, cell->c); if (cell->formula != NULL) { chr[1] = '\0'; end = strchr (cell->formula, '\n'); if (end != NULL) end[0] = '\0'; len = strlen (cell->formula); if (cell->formula[0] != '\'' && cell->formula[0] != '-' && cell->formula[0] != '=' && cell->formula[0] != '+' && !('0' <= cell->formula[0] && cell->formula[0] <= '9')) fprintf (fp, "="); for (i = 0; i < len; i++) { if (cell->formula[i] == '\"') fprintf (fp, "\""); chr[0] = cell->formula[i]; fprintf (fp, "%s", chr); } fprintf (fp, "\")\n"); } } if (cell->style != NULL) { if (getstyle (cell->style, STY_BORDER_TOP) && getstyle (cell->style, STY_BORDER_BOT) && getstyle (cell->style, STY_BORDER_RIG) && getstyle (cell->style, STY_BORDER_LEF) ) { fprintf (fp, "Cells(%d,%d).Borders.LineStyle = xlLineStyleContinuous\n", cell->r, cell->c); } else { if (getstyle (cell->style, STY_BORDER_TOP)) fprintf (fp, "Cells(%d,%d).Borders(xlEdgeTop).LineStyle = xlLineStyleContinuous\n", cell->r, cell->c); if (getstyle (cell->style, STY_BORDER_BOT)) fprintf (fp, "Cells(%d,%d).Borders(xlEdgeBottom).LineStyle = xlLineStyleContinuous\n", cell->r, cell->c); if (getstyle (cell->style, STY_BORDER_RIG)) fprintf (fp, "Cells(%d,%d).Borders(xlEdgeRight).LineStyle = xlLineStyleContinuous\n", cell->r, cell->c); if (getstyle (cell->style, STY_BORDER_LEF)) fprintf (fp, "Cells(%d,%d).Borders(xlEdgeLeft).LineStyle = xlLineStyleContinuous\n", cell->r, cell->c); } if (getstyle (cell->style, STY_FONT) != getstyle (ActiveWorkbook->style, STY_FONT)) switch (getstyle (cell->style, STY_FONT)) { case 0: fprintf (fp, "Cells(%d,%d).Font.Name = \"Fixed\"\n", cell->r, cell->c); break; case 1: fprintf (fp, "Cells(%d,%d).Font.Name = \"Courier\"\n", cell->r, cell->c); break; case 2: fprintf (fp, "Cells(%d,%d).Font.Name = \"Helvetica\"\n", cell->r, cell->c); break; case 3: fprintf (fp, "Cells(%d,%d).Font.Name = \"Times\"\n", cell->r, cell->c); break; case 4: fprintf (fp, "Cells(%d,%d).Font.Name = \"Symbol\"\n", cell->r, cell->c); break; } if (getstyle (cell->style, STY_FONTS) != getstyle (ActiveWorkbook->style, STY_FONTS)) switch (getstyle (cell->style, STY_FONTS)) { case 0: fprintf (fp, "Cells(%d,%d).Font.Size = 6\n", cell->r, cell->c); break; case 1: fprintf (fp, "Cells(%d,%d).Font.Size = 8\n", cell->r, cell->c); break; case 2: fprintf (fp, "Cells(%d,%d).Font.Size = 10\n", cell->r, cell->c); break; case 3: fprintf (fp, "Cells(%d,%d).Font.Size = 12\n", cell->r, cell->c); break; case 4: fprintf (fp, "Cells(%d,%d).Font.Size = 14\n", cell->r, cell->c); break; case 5: fprintf (fp, "Cells(%d,%d).Font.Size = 18\n", cell->r, cell->c); break; case 6: fprintf (fp, "Cells(%d,%d).Font.Size = 24\n", cell->r, cell->c); break; } if (getstyle (cell->style, STY_FONTW) == 1 || getstyle (cell->style, STY_FONTW) == 3) fprintf (fp, "Cells(%d,%d).Font.Bold = True \n", cell->r, cell->c); if (getstyle (cell->style, STY_FONTW) == 2 || getstyle (cell->style, STY_FONTW) == 3) fprintf (fp, "Cells(%d,%d).Font.Italic = True \n", cell->r, cell->c); if (getstyle (cell->style, STY_JUSTIF) != getstyle (ActiveWorkbook->style, STY_JUSTIF)) switch (getstyle (cell->style, STY_JUSTIF)) { case 0: fprintf (fp, "Cells(%d,%d).HorizontalAlignment = xlLeft\n", cell->r, cell->c); break; case 1: fprintf (fp, "Cells(%d,%d).HorizontalAlignment = xlCenter\n", cell->r, cell->c); break; case 2: fprintf (fp, "Cells(%d,%d).HorizontalAlignment = xlRight\n", cell->r, cell->c); break; } if (getstyle (cell->style, STY_BG) != getstyle (ActiveWorkbook->style, STY_BG)) fprintf (fp, "Cells(%d,%d).Interior.ColorIndex = %d\n", cell->r, cell->c, getstyle (cell->style, STY_BG) - 5); if (getstyle (cell->style, STY_FG) != getstyle (ActiveWorkbook->style, STY_FG)) fprintf (fp, "Cells(%d,%d).Font.ColorIndex = %d\n", cell->r, cell->c, getstyle (cell->style, STY_FG) - 5); format = getstyle (cell->style, STY_FORMAT); deci = getstyle (cell->style, STY_DECIMAL); if ((format != getstyle (ActiveWorkbook->style, STY_FORMAT) || deci != getstyle (ActiveWorkbook->style, STY_DECIMAL)) && format != 0) { if (format >= 2 && format <= 4) { fprintf (fp, "Cells(%d,%d).NumberFormat = \"0", cell->r, cell->c); if (deci) fprintf (fp, "."); while (deci > 0) { fprintf (fp, "0"); deci--; }; } switch (format) { case 2: fprintf (fp, "\"\n"); break; case 3: fprintf (fp, "E+00\"\n"); break; case 4: fprintf (fp, "%%\"\n"); break; case 5: { fprintf (fp, "Cells(%d,%d).NumberFormat = \"", cell->r, cell->c); fprintf (fp, "dd/mm/yy\"\n"); break; } default: fprintf (fp, "\"\n"); } } } return 0; } int cell_setnumberformat (cell, buf) Cell *cell; char *buf; { int deci = 0; char *dot; char *token; if (strstr (buf, "General")) return 0; token = strchr (buf, ';'); if (token != NULL) { token[0] = '\0'; token++; } if (buf == NULL) return 1; if (strchr (buf, '/')) { cell_setformat (cell, 5, 0); return 0; } dot = strchr (buf, '.'); if (dot != NULL) while (dot[deci + 1] == '0' && deci < strlen (dot)) { deci++; } if (strchr (buf, 'E') || strchr (buf, 'e')) { cell_setformat (cell, 3, deci); } else if (strchr (buf, '%')) { cell_setformat (cell, 4, deci); } else { cell_setformat (cell, 2, deci); } return 0; } int cell_setformula (cell, str) Cell *cell; char *str; { int format, deci, date; int ret; int len; int second = 0; char *buf = NULL; if (cell == NULL) { return 1; } if (cell->formula != NULL) { if (str != NULL) if (strcmp (cell->formula, str) == 0) return 1; if (cell->val.type == STRING_CONSTANT && cell->val.rec.s == cell->formula + 1) cell->val.rec.s = NULL; absfree (cell->formula, "cell_setformula:cell->formula "); cell->formula = NULL; } if (cell->tree != NULL) { freenode (cell->tree); cell->tree = NULL; }; cell_isnew (cell); if (str == NULL) { cell->formula = NULL; cell->val.rec.d = 0.0; cell->val.type = DOUBLE; cell->type = undef; return -1; }; while (str[0] == ' ' && str[0] != '\0' && str[0] != '\n') str++; len = strlen (str); if (len < 1) { cell->formula = NULL; cell->val.rec.d = 0.0; cell->val.type = DOUBLE; cell->type = undef; return -1; }; { buf = (char *) absmalloc (sizeof (char) * (len + 3), "cell_setformula:buf"); if (len > 1) if ('0' <= str[1] && str[1] <= '9') { second = 1; } if (str[0] == '=' || str[0] == '+' || str[0] == '-' || str[0] == '\'' || ('0' <= str[0] && str[0] <= '9') || (len > 1 && str[0] == '.' && second == 1) ) { strcpy (buf, str); } else { buf[0] = '\''; strcpy (buf + 1, str); } cell->formula = (char *) absmalloc (sizeof (char) * (strlen (buf) + 5), "cell_setformula:cell->formula "); if (cell->formula == NULL) { fprintf (stderr, "formula not allocated\n"); absfree (buf, "cell_setformula:buf"); return -2; } cell_getformat (cell, &format, &deci); if (format == 5) { date = scandate (buf); if (date) sprintf (buf, "%d\n", date); }; len = strlen (buf); strcpy (cell->formula, buf); cell->formula[len] = '\0'; if (strncmp (cell->formula, "'", 1) == 0) { cell->val.type = STRING_CONSTANT; cell->val.rec.s = cell->formula + 1; cell->type = text; nupdate2 (cell, 1); absfree (buf, "cell_setformula:buf"); return 1; } cell->type = constant; ActiveCell = cell; setting_formula = 1; ret = parsecell (cell); if (ret) { cell->val.type = STRING_CONSTANT; cell->val.rec.s = "ERR!"; cell->type = text; } else { if (cell_is_constant (cell)) { freenode (cell->tree); cell->tree = NULL; absfree (cell->formula, "cell_setformula:cell->formula "); cell->formula = NULL; } else { execcelltree (cell); cell->type = formula; } } setting_formula = 0; nupdate2 (cell, 1); absfree (buf, "cell_setformula:buf"); return 0; } cell->formula = NULL; cell->val.type = STRING_CONSTANT; cell->val.rec.s = NULL; cell->type = text; absfree (buf, "cell_setformula:buf"); return 0; } int cell_settext (cell, buf) Cell *cell; char *buf; { char *end; char *first; if (cell == NULL) { return 1; } if (cell->val.type == STRING_CONSTANT) if (cell->val.rec.s != NULL) { absfree (cell->val.rec.s, "cell_settext:cell->val.rec.s "); cell->val.rec.s = NULL; } if (strlen (buf) > 0) { end = strchr (buf, '\n'); if (end != NULL) end = '\0'; cell->val.rec.s = (char *) absmalloc (sizeof (char) * (strlen (buf) + 5), "cell_settext:cell->formula "); if (cell->val.rec.s == NULL) fprintf (stderr, "val.rec.s not allocated\n"); first = buf; while (*first == ' ' && first < buf + strlen (buf)) first++; if (*first == '\'') { strcpy (cell->val.rec.s, "'"); strcat (cell->val.rec.s, first + 1); cell->formula = cell->val.rec.s; cell->val.rec.s = cell->formula + 1; } else strcpy (cell->val.rec.s, buf); } else cell->val.rec.s = NULL; cell->val.type = STRING_CONSTANT; cell->type = text; return 0; } char * cell_getformula (cell) Cell *cell; { if (cell != NULL) switch (cell->type) { case constant: { double val = cell_getvalue (cell); if (val != 0.0) { sprintf (tmpbuf, "%g", cell_getvalue (cell)); return tmpbuf; } break; } case text: return cell->formula; case formula: return cell->formula; case undef: return NULL; } return NULL; } char * cell_getnumberformat (cell) Cell *cell; { return NULL; } double cell_setvalue (cell, val) Cell *cell; double val; { if (cell != NULL) { obj o; o.rec.d = val; o.type = DOUBLE; cell_setobj (cell, o); } return 0.0; } obj cell_setobj (cell, o) Cell *cell; obj o; { char tmp[64]; char *buf; if (o.type == STRING) o.type = STRING_CONSTANT; if (cell != NULL) { switch (o.type) { case STRING_CONSTANT: { if (o.rec.s == NULL) { clear_cell (cell); return o; } buf = absmalloc (sizeof (char) * (strlen (o.rec.s) + 2), "cell_setobj:buf"); if (o.rec.s[0] == '\'') strcpy (buf, o.rec.s); else sprintf (buf, "'%s", o.rec.s); cell_setformula (cell, buf); absfree (buf, "cell_setobj:buf"); break; }; case DOUBLE: sprintf (tmp, "%f", o.rec.d); cell_setformula (cell, tmp); break; case INTEGER: sprintf (tmp, "%d", o.rec.i); cell_setformula (cell, tmp); break; } } return o; } obj cell_setresval (cell, o) Cell *cell; obj o; { int len = 0; if (o.type == STRING) o.type = STRING_CONSTANT; if (cell != NULL) { if (o.type == STRING_CONSTANT && o.rec.s != NULL) { len = strlen (o.rec.s); } if (o.type == STRING_CONSTANT && len == 0) { if (cell->val.type == STRING_CONSTANT && cell->val.rec.s != NULL) absfree (cell->val.rec.s, "cell->val.rec.s:null_str"); cell->val.rec.s = NULL; cell->val.type = STRING_CONSTANT; return o; } if (cell->val.type == STRING_CONSTANT) { if (o.type == STRING_CONSTANT) { cell->val.rec.s = (char *) absrealloc (cell->val.rec.s, (len + 1) * sizeof (char), "cell_setresobj::val.rec.s"); strcpy (cell->val.rec.s, o.rec.s); return cell->val; } else { if (cell->val.rec.s != NULL) absfree (cell->val.rec.s, "cell_setresobj::val.rec.s"); cell->val.rec.s = NULL; } } if (o.type == STRING_CONSTANT) { cell->val.type = STRING_CONSTANT; cell->val.rec.s = (char *) absmalloc ((len + 1) * sizeof (char), "cell_setresobj::val.rec.s"); strcpy (cell->val.rec.s, o.rec.s); return cell->val; }; cell->val = o; return cell->val; } return o; } double cell_getvalue (cell) Cell *cell; { if (cell == NULL) { return 0.0; } switch (cell->val.type) { case DOUBLE: return cell->val.rec.d; case INTEGER: { double val = cell->val.rec.i; return val; } } return 0.0; } obj cell_getobj (cell) Cell *cell; { if (cell == NULL) { obj o; printf ("getvalue for NULL cell\n"); o.type = INTEGER; o.rec.i = 0; return o; } return cell->val; } int cell_istext (cell) Cell *cell; { if (cell == NULL) return 0; if (cell->type == text) return 1; return 0; } char * cell_gettext (cell) Cell *cell; { char form[8]; int format, deci; int dd, mm, yy; double value; if (cell == NULL) { return NULL; } if (cell->type != constant && cell->formula == NULL) { return NULL; } if (cell->type == text || cell->val.type == STRING_CONSTANT) return cell->val.rec.s; cell_getformat (cell, &format, &deci); value = cell_getvalue (cell); switch (format) { case 1: { sprintf (form, "%%g"); sprintf (tmpbuf, form, value); break; } case 2: { sprintf (form, "%%.%dlf", deci); sprintf (tmpbuf, form, value); break; } case 3: { sprintf (form, "%%.%de", deci); sprintf (tmpbuf, form, value); break; } case 4: { sprintf (form, "%%.%dlf%%%%", deci); sprintf (tmpbuf, form, value * 100.); break; } case 5: { int date = value; num2date (date, &dd, &mm, &yy); sprintf (tmpbuf, "%2d/%2d/%4d", dd, mm, yy); break; } } return tmpbuf; } int cell_setfg (cell, f) Cell *cell; int f; { if (cell == NULL) return -1; if (cell->style == NULL) cell->style = newstyle (STY_CELL); setstyle (cell->style, STY_FG, f + 5); return 0; } int cell_getfg (cell) Cell *cell; { if (cell == NULL || cell->style == NULL) return getstyle (ActiveWorkbook->style, STY_FG); return getstyle (cell->style, STY_FG); } int cell_setbg (cell, f) Cell *cell; int f; { if (cell == NULL) return -1; if (cell->style == NULL) cell->style = newstyle (STY_CELL); setstyle (cell->style, STY_BG, f + 5); return 0; } int cell_getbg (cell) Cell *cell; { if (cell == NULL || cell->style == NULL) return getstyle (ActiveWorkbook->style, STY_BG); return getstyle (cell->style, STY_BG); } int cell_gettop (cell) Cell *cell; { if (cell == NULL || cell->style == NULL) return getstyle (ActiveWorkbook->style, STY_BORDER_TOP); return getstyle (cell->style, STY_BORDER_TOP); } int cell_getbot (cell) Cell *cell; { if (cell == NULL || cell->style == NULL) return getstyle (ActiveWorkbook->style, STY_BORDER_BOT); return getstyle (cell->style, STY_BORDER_BOT); } int cell_getrig (cell) Cell *cell; { if (cell == NULL || cell->style == NULL) return getstyle (ActiveWorkbook->style, STY_BORDER_RIG); return getstyle (cell->style, STY_BORDER_RIG); } int cell_getlef (cell) Cell *cell; { if (cell == NULL || cell->style == NULL) return getstyle (ActiveWorkbook->style, STY_BORDER_LEF); return getstyle (cell->style, STY_BORDER_LEF); } int cell_settop (cell, v) Cell *cell; int v; { if (cell == NULL) return -1; if (cell->style == NULL) cell->style = newstyle (STY_CELL); setstyle (cell->style, STY_BORDER_TOP, v); return 0; } int cell_setbot (cell, v) Cell *cell; int v; { if (cell == NULL) return -1; if (cell->style == NULL) cell->style = newstyle (STY_CELL); setstyle (cell->style, STY_BORDER_BOT, v); return 0; } int cell_setrig (cell, v) Cell *cell; int v; { if (cell == NULL) return -1; if (cell->style == NULL) cell->style = newstyle (STY_CELL); setstyle (cell->style, STY_BORDER_RIG, v); return 0; } int cell_setlef (cell, v) Cell *cell; int v; { if (cell == NULL) return -1; if (cell->style == NULL) cell->style = newstyle (STY_CELL); setstyle (cell->style, STY_BORDER_LEF, v); return 0; } int cell_setformat (cell, format, deci) Cell *cell; int format, deci; { double date; if (cell == NULL) return -1; if (cell->style == NULL) cell->style = newstyle (STY_CELL); if (format == 5 && getstyle (cell->style, STY_FORMAT) != 5) { date = scandate (cell_getformula (cell)); if (date) cell_setvalue (cell, date); } setstyle (cell->style, STY_FORMAT, format); setstyle (cell->style, STY_DECIMAL, deci); return 0; } int cell_getformat (cell, format, decimal) Cell *cell; int *format, *decimal; { if (cell == NULL) return -1; if (cell->style == NULL) { *format = getstyle (ActiveWorkbook->style, STY_FORMAT); *decimal = getstyle (ActiveWorkbook->style, STY_DECIMAL); return 0; } *format = getstyle (cell->style, STY_FORMAT); *decimal = getstyle (cell->style, STY_DECIMAL); return 0; } int cell_setjust (cell, just) Cell *cell; int just; { if (cell == NULL) return -1; if (cell->style == NULL) cell->style = newstyle (STY_CELL); setstyle (cell->style, STY_JUSTIF, just); return 0; } int cell_getjust (cell) Cell *cell; { if (cell == NULL || cell->style == NULL) return getstyle (ActiveWorkbook->style, STY_JUSTIF); return getstyle (cell->style, STY_JUSTIF); } int cell_setfont (cell, font, weight, size) Cell *cell; int font; { if (cell == NULL) return -1; if (cell->style == NULL) cell->style = newstyle (STY_CELL); if (font >= 0) setstyle (cell->style, STY_FONT, font); if (weight >= 0) setstyle (cell->style, STY_FONTW, weight); if (size >= 0) setstyle (cell->style, STY_FONTS, size); return 0; } int cell_fontname (Cell * cell, char *name) { if (cell->style == NULL) cell->style = newstyle (STY_CELL); if (!strcasecmp (name, "fixed")) setstyle (cell->style, STY_FONT, 0); if (!strcasecmp (name, "courier")) setstyle (cell->style, STY_FONT, 1); if (!strcasecmp (name, "helvetica")) setstyle (cell->style, STY_FONT, 2); if (!strcasecmp (name, "times")) setstyle (cell->style, STY_FONT, 3); if (!strcasecmp (name, "symbol")) setstyle (cell->style, STY_FONT, 4); return 0; } int cell_fontsize (cell, v) Cell *cell; int v; { if (cell->style == NULL) cell->style = newstyle (STY_CELL); switch (v) { case 6: setstyle (cell->style, STY_FONTS, 0); break; case 8: setstyle (cell->style, STY_FONTS, 1); break; case 10: setstyle (cell->style, STY_FONTS, 2); break; case 12: setstyle (cell->style, STY_FONTS, 3); break; case 14: setstyle (cell->style, STY_FONTS, 4); break; case 18: setstyle (cell->style, STY_FONTS, 5); break; case 24: setstyle (cell->style, STY_FONTS, 6); break; } return 0; } int cell_fontbold (cell, v) Cell *cell; int v; { if (cell->style == NULL) cell->style = newstyle (STY_CELL); if (v == 0) { if (getstyle (cell->style, STY_FONTW) > 1) setstyle (cell->style, STY_FONTW, 2); else setstyle (cell->style, STY_FONTW, 0); } else { if (getstyle (cell->style, STY_FONTW) > 1) setstyle (cell->style, STY_FONTW, 3); else setstyle (cell->style, STY_FONTW, 1); } return 0; } int cell_fontitalic (cell, v) Cell *cell; int v; { int w; if (cell->style == NULL) cell->style = newstyle (STY_CELL); w = getstyle (cell->style, STY_FONTW); if (v == 0) { if (w == 1 || w == 3) setstyle (cell->style, STY_FONTW, 1); else setstyle (cell->style, STY_FONTW, 0); } else { if (w == 1 || w == 3) setstyle (cell->style, STY_FONTW, 3); else setstyle (cell->style, STY_FONTW, 2); } return 0; } int cell_getfont (cell) Cell *cell; { if (cell == NULL || cell->style == NULL) return getstyle (ActiveWorkbook->style, STY_FONT); return getstyle (cell->style, STY_FONT); return 0; } int cell_getfontw (cell) Cell *cell; { if (cell == NULL || cell->style == NULL) return getstyle (ActiveWorkbook->style, STY_FONTW); return getstyle (cell->style, STY_FONTW); return 0; } int cell_getfonts (cell) Cell *cell; { if (cell == NULL || cell->style == NULL) return getstyle (ActiveWorkbook->style, STY_FONTS); return getstyle (cell->style, STY_FONTS); return 0; } int cell_setborders (cell, border, type) Cell *cell; int border; int type; { if (cell == NULL) return -1; if (cell->style == NULL) cell->style = newstyle (STY_CELL); if (border == 8 || border == 0) setstyle (cell->style, STY_BORDER_TOP, type); if (border == 7 || border == 0) setstyle (cell->style, STY_BORDER_LEF, type); if (border == 9 || border == 0) setstyle (cell->style, STY_BORDER_BOT, type); if (border == 10 || border == 0) setstyle (cell->style, STY_BORDER_RIG, type); return 0; } int cell_setborder (cell, border) Cell *cell; int border; { if (cell == NULL) return -1; if (cell->style == NULL) cell->style = newstyle (STY_CELL); setstyle (cell->style, STY_BORDER, border); return 0; } int cell_getborder (cell) Cell *cell; { if (cell == NULL || cell->style == NULL) return getstyle (ActiveWorkbook->style, STY_BORDER); return getstyle (cell->style, STY_BORDER); return 0; } int parsecell (cell) Cell *cell; { ActiveCell = cell; if (cell == NULL) return -1; if (cell->formula == NULL) return -2; cell->tree = parseexpression (cell->formula); if (cell->tree == NULL) return 1; setcelltree (cell->tree); return 0; } int copymod (ii, jj, i, j, incr) int i, j, ii, jj, incr; { Cell *cell1; Cell *cell2; cell1 = (Cell *) applicationcell (i, j, 1); cell2 = (Cell *) applicationcell (ii, jj, 1); return copymod2 (cell1, cell2, i, j, (i - ii) * incr, (j - jj) * incr); } int copymod2 (cell1, cell2, _curi, _curj, _di, _dj) Cell *cell1; Cell *cell2; int _curi, _curj, _di, _dj; { setdi (_di); setdj (_dj); cell_setformula (cell1, cell_getformula (cell2)); setdi (0); setdj (0); return 0; } int copymod3 (cell1, cell2, incr) Cell *cell1; Cell *cell2; int incr; { if (cell1 == NULL || cell2 == NULL) return -1; setdi ((cell1->r - cell2->r) * incr); setdj ((cell1->c - cell2->c) * incr); cell_setformula (cell1, cell_getformula (cell2)); setdi (0); setdj (0); return 0; return 0; } char * tolower (char *s) { int j; int len; len = strlen (s); for (j = 0; j < len; j++) if (s[j] >= 'A' && s[j] <= 'Z') s[j] = 'a' + s[j] - 'A'; return s; } char * strcasestr (char *str1, char *str2) { char *s1; char *s2; char *pos = NULL; int l1; s1 = strdup (str1); if (s1 == NULL) return NULL; s2 = strdup (str2); if (s2 == NULL) { free (s1); return NULL; } tolower (s1); tolower (s2); pos = strstr (s1, s2); l1 = pos - s1; free (s1); free (s2); if (pos == NULL) return NULL; return str1 + l1; } int cell_chgwksname (Cell * cell, char *oldname, char *newname) { int len = 0; int i = 0; int diffsize; char *newformula = NULL; char *old, *pos, *end; if (cell == NULL) return -1; if (cell->formula == NULL) return 0; if (cell->tree == NULL) return 0; if (oldname == NULL || newname == NULL) return -1; if (strlen (oldname) < 1 || strlen (newname) < 1) return -1; if (!strcmp (oldname, newname)) return 0; if (strcasestr (cell->formula, oldname) == NULL) return 0; diffsize = strlen (oldname) - strlen (newname); old = absmalloc ((strlen (oldname) + 2) * sizeof (char), "cell_chgwksname:old"); sprintf (old, "%s!", oldname); pos = strcasestr (cell->formula, old); while (pos != NULL) { len = strlen (cell->formula); newformula = (char *) absmalloc ((len + 1 + diffsize) * sizeof (char), "cell_chgwksname:newformula"); end = strchr (pos, '!'); pos[0] = '\0'; i = strlen (cell->formula) + strlen (newname) + 1; sprintf (newformula, "%s%s%s", cell->formula, newname, end); absfree (cell->formula, "cell_chgwksname:cell->formula"); cell->formula = newformula; end = strcasestr (cell->formula, old); if (end > cell->formula + i) pos = end; else pos = NULL; } return 0; } int cell1isfcell2 (cell1, cell2) Cell *cell1; Cell *cell2; { int numpar1; int numchi2; int k; Cell **tmp; if (cell1 == cell2) return 1; if (cell1->familly == NULL) { cell1->familly = (Familly *) absmalloc (sizeof (Familly), "cell1isfcell2:cell1->familly "); if (cell1->familly == NULL) fprintf (stderr, "cell1->familly not allocated!\n"); cell1->familly->numpar = 0; cell1->familly->dimparlist = 0; cell1->familly->parentlist = NULL; cell1->familly->numchi = 0; cell1->familly->dimchilist = 0; cell1->familly->childlist = NULL; } if (cell2->familly == NULL) { cell2->familly = (Familly *) absmalloc (sizeof (Familly), "cell1isfcell2:cell2->familly "); if (cell2->familly == NULL) fprintf (stderr, "cell2->familly not allocated!\n"); cell2->familly->numpar = 0; cell2->familly->dimparlist = 0; cell2->familly->parentlist = NULL; cell2->familly->numchi = 0; cell2->familly->dimchilist = 0; cell2->familly->childlist = NULL; } numpar1 = cell1->familly->numpar; numchi2 = cell2->familly->numchi; if (cell1->familly->dimparlist < numpar1 + 1) { tmp = (Cell **) absmalloc (sizeof (Cell *) * (2 * numpar1 + 2), "cell1isfcell2:tmp "); if (tmp == NULL) fprintf (stderr, "tmp not allocated!\n"); for (k = 0; k < numpar1; k++) tmp[k] = cell1->familly->parentlist[k]; if (cell1->familly->parentlist != NULL) absfree (cell1->familly->parentlist, "cell1isfcell2:cell1->familly->parentlist "); cell1->familly->parentlist = tmp; cell1->familly->dimparlist = 2 * numpar1 + 2; } if (cell2->familly->dimchilist < numchi2 + 1) { tmp = (Cell **) absmalloc (sizeof (Cell *) * (2 * numchi2 + 2), "cell1isfcell2:tmp "); if (tmp == NULL) fprintf (stderr, "tmp not allocated!\n"); for (k = 0; k < numchi2; k++) { tmp[k] = cell2->familly->childlist[k]; } if (cell2->familly->dimchilist > 0 && cell2->familly->childlist != NULL) absfree (cell2->familly->childlist, "cell1isfcell2:cell2->familly->childlist "); cell2->familly->childlist = tmp; cell2->familly->dimchilist = 2 * numchi2 + 2; } for (k = 0; k < numpar1; k++) { if (cell2 == cell1->familly->parentlist[k]) return 2; } cell1->familly->parentlist[numpar1] = cell2; cell1->familly->numpar++; cell2->familly->childlist[numchi2] = cell1; cell2->familly->numchi++; return 0; } int pfamilly2 (cell) Cell *cell; { int k; Cell *cell2; if (cell == NULL) fprintf (stderr, "pfamilly of null cell\n"); if (cell->familly == NULL) return 1; printf ("cell %d (r=%d c=%d)\n", cell->objnum, cell->r, cell->c); for (k = 0; k < cell->familly->numchi; k++) { cell2 = cell->familly->childlist[k]; if (cell2) printf (" - child %d: %d (wks=%s r=%d c=%d)\n", k, cell2->objnum, cell2->worksheet->Name, cell2->r, cell2->c); else printf (" - child %d: NULL\n", k); } for (k = 0; k < cell->familly->numpar; k++) { cell2 = cell->familly->parentlist[k]; if (cell2) printf (" - parent %d: %d (wks=%s r=%d c=%d)\n", k, cell2->objnum, cell2->worksheet->Name, cell2->r, cell2->c); else printf (" - parent %d: NULL\n", k); } return 0; } void cell_auditcell (Cell * cell) { pfamilly2 (cell); } int cell_isnew (cell) Cell *cell; { int k; Cell *i2j2; int l, found; if (updating || parsing) return 1; if (cell->familly == NULL) return 2; for (k = 0; k < cell->familly->numpar; k++) { i2j2 = cell->familly->parentlist[k]; found = 0; if (i2j2->familly != NULL) { for (l = 0; l < i2j2->familly->numchi; l++) { if (i2j2->familly->childlist[l] == cell) found = 1; if (found) { i2j2->familly->childlist[l] = i2j2->familly->childlist[l + 1]; } } i2j2->familly->numchi--; } } if (cell->familly->numpar > 0) { cell->familly->numpar = 0; absfree (cell->familly->parentlist, "cell_isnew:cell->familly->parentlist "); cell->familly->parentlist = NULL; cell->familly->dimparlist = 0; } cell->familly->numpar = 0; if (cell->familly->numchi == 0) { if (cell->familly->dimchilist > 0) absfree (cell->familly->childlist, "cell_isnew:cell->familly->childlist "); absfree (cell->familly, "cell_isnew:cell->familly "); cell->familly = NULL; } return 0; } extern int xdrawcell (); static Cell *iterbase; int nupdate2 (Cell * cell, int redraw) { int k; Cell *cell2; if (parsing) return 1; if (cell == NULL) return 2; if (cell->familly == NULL) { return 3; } if (updating == 0) iterbase = cell; else if (cell == iterbase) { fprintf (stderr, "circular reference in cell %d %d\n", cell->r, cell->c); return 0; } updating++; for (k = 0; k < cell->familly->numchi; k++) { cell2 = cell->familly->childlist[k]; if (cell2->formula != NULL && cell2->tree != NULL) { int exist = 0; int i; execcelltree (cell2); nupdate2 (cell2, redraw); if (redraw) for (i = 0; i < ntoredraw; i++) { if (toredraw[i] == cell2) { exist = 1; i = ntoredraw; } } if (!exist) { toredraw = (Cell **) absrealloc (toredraw, sizeof (Cell *) * (ntoredraw + 1), "nupdate2:toredraw "); toredraw[ntoredraw] = cell2; ntoredraw++; } } } updating--; if (updating == 0 && ntoredraw > 0) { for (k = 0; k < ntoredraw; k++) xdrawcell (toredraw[k]->r, toredraw[k]->c, 0); absfree (toredraw, "nupdate2:toredraw "); toredraw = NULL; ntoredraw = 0; } return 0; } extern char *obj2string (obj o); extern obj getidval3 (int i); extern int findid (char *s); char * textparsing (buf) char *buf; { Cell *cell; Cell *activecell = ActiveCell; if (parsingmacro) { sprintf (tmpbuf, "to update"); return tmpbuf; } cell = newcell (0, 1); cell_setformula (cell, buf); strcpy (tmpbuf, cell_gettext (cell)); cell_isnew (cell); freecell (cell); ActiveCell = activecell; return tmpbuf; } Cell * cell_cpy (cell1, cell2) Cell *cell1; Cell *cell2; { int len; if (cell1 == NULL || cell2 == NULL) return NULL; if (cell2->val.type == DOUBLE) { cell1->val.rec.d = cell2->val.rec.d; cell1->val.type = DOUBLE; } if (cell2->val.type == INTEGER) { cell1->val.rec.i = cell2->val.rec.i; cell1->val.type = INTEGER; } if (cell2->formula != NULL) { len = strlen (cell2->formula); if (len > 0) { cell1->formula = (char *) absmalloc (sizeof (char) * len, "cell_cpy:cell1->formula "); if (cell1->formula == NULL) fprintf (stderr, "cell1->formula not allocated!\n"); strcpy (cell1->formula, cell2->formula); cell1->formula[len] = '\0'; } } cell1->type = cell2->type; if (cell2->style != NULL) { if (cell1->style == NULL) cell1->style = newstyle (STY_CELL); style_cpy (cell1->style, cell2->style); } else { if (cell1->style != NULL) { freestyle (cell1->style); cell1->style = NULL; } } return cell1; } Cell * cell_stycpy (cell1, cell2) Cell *cell1; Cell *cell2; { if (cell1 == NULL || cell2 == NULL) return NULL; if (cell2->style != NULL) { if (cell1->style == NULL) cell1->style = newstyle (STY_CELL); style_cpy (cell1->style, cell2->style); } else { if (cell1->style != NULL) { freestyle (cell1->style); cell1->style = NULL; } } return cell1; } int cell_calculate (Cell * cell) { return nupdate2 (cell, 0); } int cell_print (Cell * cell) { if (cell == NULL) fprintf (stderr, "cell is NULL!\n"); else fprintf (stderr, "cell %d %d formula %s\n", cell->r, cell->c, cell_getformula (cell)); return 0; }