1 /********************************************************************
2 This file is part of the abs 0.907 distribution.  abs is a spreadsheet
3 with graphical user interface.
4 
5 Copyright (C) 1998-2001  Andr� Bertin (Andre.Bertin@ping.be)
6 
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version if in the same spirit as version 2.
11 
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 Concact: abs@pi.be
22          http://home.pi.be/bertin/abs.shtml
23 
24 *********************************************************************/
25 
26 
27 
28 
29 
30 
31 
32 
33 
34 
35 
36 
37 
38 
39 
40 
41 
42 
43 
44 
45 
46 
47 
48 
49 
50 
51 #include "cell.h"
52 #include "worksheet.h"
53 #include "workbook.h"
54 #include "style.h"
55 #include "y.tab.h"
56 #include "memory.h"
57 #include "date.h"
58 #include "cell_vb.h"
59 #include "gram_ext.h"
60 #include "application.h"
61 
62 #include <string.h>
63 
64 
65 static int updating = 0;
66 static int parsing = 0;
67 static int setting_formula = 0;
68 static int ncell = 0;
69 static int parsingmacro;
70 
71 static Cell **toredraw = NULL;
72 static int ntoredraw = 0;
73 
74 
75 
76 
77 
78 static char tmpbuf[256];
79 
80 Cell *ActiveCell;
81 
82 Cell *
cell_activate(Cell * cell)83 cell_activate (Cell * cell)
84 {
85   ActiveCell = cell;
86   if (ActiveWorksheet != NULL)
87     {
88       ActiveWorksheet->activecell = cell;
89       if (ActiveWorksheet->cur_r != cell->r && ActiveWorksheet->cur_c != cell->c)
90 	worksheet_setcursor (ActiveWorksheet, cell->r, cell->c);
91     }
92   return ActiveCell;
93 }
94 
95 Cell *
newcell(r,c)96 newcell (r, c)
97      int r, c;
98 {
99   Cell *nc;
100   nc = (Cell *) absmalloc (sizeof (Cell), "newcell:Cell ");
101   if (nc == NULL)
102     {
103       fprintf (stderr, "Cell: not allocated!");
104       return NULL;
105     }
106 
107   nc->val.rec.d = 0.0;
108   nc->val.type = DOUBLE;
109   nc->formula = NULL;
110 
111   nc->style = NULL;
112   nc->r = r;
113   nc->c = c;
114 
115   nc->familly = NULL;
116   nc->worksheet = ActiveWorksheet;
117   nc->tree = NULL;
118 
119 
120   nc->type = undef;
121 
122   nc->objnum = ncell++;
123 
124   return nc;
125 }
126 
127 int
clear_cell(Cell * cell)128 clear_cell (Cell * cell)
129 {
130   if (cell == NULL)
131     return 1;
132 
133 
134 
135 
136   if (cell->val.type == STRING_CONSTANT && cell->val.rec.s != cell->formula + 1)
137     if (cell->val.rec.s != NULL)
138       absfree (cell->val.rec.s, "freecell:cell->val.rec.s ");
139 
140   if (cell->formula != NULL)
141     absfree (cell->formula, "freecell:cell->formula ");
142   if (cell->tree != NULL)
143     {
144       freenode (cell->tree);
145       cell->tree = NULL;
146     }
147   if (cell->style != NULL)
148     {
149       freestyle (cell->style);
150       cell->style = NULL;
151     }
152   cell->val.rec.d = 0.0;
153   cell->val.type = DOUBLE;
154   cell->formula = NULL;
155 
156   cell_isnew (cell);
157   nupdate2 (cell, 1);
158 
159   cell->type = undef;
160   return 0;
161 }
162 int
freecell(cell)163 freecell (cell)
164      Cell *cell;
165 {
166   if (cell == NULL)
167     return 1;
168 
169 
170 
171 
172   if (cell->val.type == STRING_CONSTANT && cell->val.rec.s != cell->formula + 1)
173     if (cell->val.rec.s != NULL)
174       absfree (cell->val.rec.s, "freecell:cell->val.rec.s ");
175 
176   if (cell->formula != NULL)
177     absfree (cell->formula, "freecell:cell->formula ");
178   if (cell->tree != NULL)
179     {
180       freenode (cell->tree);
181       cell->tree = NULL;
182     }
183   if (cell->style != NULL)
184     {
185       freestyle (cell->style);
186       cell->style = NULL;
187     }
188   absfree (cell, "freecell:cell ");
189 
190   return 0;
191 }
192 
193 
194 int
cell_write(cell,fp)195 cell_write (cell, fp)
196      Cell *cell;
197      FILE *fp;
198 {
199 
200   int deci, format;
201   char *end = NULL;
202   char chr[2];
203   int len = 0;
204   int i;
205 
206   if (cell == NULL)
207     return -1;
208 
209   if (cell->type == constant)
210     {
211       fprintf (fp, "absnc(%d,%d,\"", cell->r, cell->c);
212       fprintf (fp, "%g", cell_getvalue (cell));
213       fprintf (fp, "\")\n");
214     }
215   else if (cell->type == text || cell->type == formula)
216     {
217       fprintf (fp, "absnc(%d,%d,\"", cell->r, cell->c);
218       if (cell->formula != NULL)
219 	{
220 	  chr[1] = '\0';
221 	  end = strchr (cell->formula, '\n');
222 	  if (end != NULL)
223 	    end[0] = '\0';
224 	  len = strlen (cell->formula);
225 
226 
227 
228 	  if (cell->formula[0] != '\'' && cell->formula[0] != '-'
229 	      && cell->formula[0] != '=' && cell->formula[0] != '+'
230 	      && !('0' <= cell->formula[0] && cell->formula[0] <= '9'))
231 	    fprintf (fp, "=");
232 
233 	  for (i = 0; i < len; i++)
234 	    {
235 	      if (cell->formula[i] == '\"')
236 		fprintf (fp, "\"");
237 	      chr[0] = cell->formula[i];
238 	      fprintf (fp, "%s", chr);
239 	    }
240 	  fprintf (fp, "\")\n");
241 	}
242     }
243 
244   if (cell->style != NULL)
245     {
246       if (getstyle (cell->style, STY_BORDER_TOP) &&
247 	  getstyle (cell->style, STY_BORDER_BOT) &&
248 	  getstyle (cell->style, STY_BORDER_RIG) &&
249 	  getstyle (cell->style, STY_BORDER_LEF)
250 	)
251 	{
252 	  fprintf (fp, "Cells(%d,%d).Borders.LineStyle = xlLineStyleContinuous\n", cell->r, cell->c);
253 	}
254       else
255 	{
256 	  if (getstyle (cell->style, STY_BORDER_TOP))
257 	    fprintf (fp, "Cells(%d,%d).Borders(xlEdgeTop).LineStyle = xlLineStyleContinuous\n", cell->r, cell->c);
258 	  if (getstyle (cell->style, STY_BORDER_BOT))
259 	    fprintf (fp, "Cells(%d,%d).Borders(xlEdgeBottom).LineStyle = xlLineStyleContinuous\n", cell->r, cell->c);
260 	  if (getstyle (cell->style, STY_BORDER_RIG))
261 	    fprintf (fp, "Cells(%d,%d).Borders(xlEdgeRight).LineStyle = xlLineStyleContinuous\n", cell->r, cell->c);
262 	  if (getstyle (cell->style, STY_BORDER_LEF))
263 	    fprintf (fp, "Cells(%d,%d).Borders(xlEdgeLeft).LineStyle = xlLineStyleContinuous\n", cell->r, cell->c);
264 	}
265 
266 
267       if (getstyle (cell->style, STY_FONT) != getstyle (ActiveWorkbook->style, STY_FONT))
268 	switch (getstyle (cell->style, STY_FONT))
269 	  {
270 	  case 0:
271 	    fprintf (fp, "Cells(%d,%d).Font.Name = \"Fixed\"\n", cell->r, cell->c);
272 	    break;
273 	  case 1:
274 	    fprintf (fp, "Cells(%d,%d).Font.Name = \"Courier\"\n", cell->r, cell->c);
275 	    break;
276 	  case 2:
277 	    fprintf (fp, "Cells(%d,%d).Font.Name = \"Helvetica\"\n", cell->r, cell->c);
278 	    break;
279 	  case 3:
280 	    fprintf (fp, "Cells(%d,%d).Font.Name = \"Times\"\n", cell->r, cell->c);
281 	    break;
282 	  case 4:
283 	    fprintf (fp, "Cells(%d,%d).Font.Name = \"Symbol\"\n", cell->r, cell->c);
284 	    break;
285 	  }
286 
287       if (getstyle (cell->style, STY_FONTS) != getstyle (ActiveWorkbook->style, STY_FONTS))
288 	switch (getstyle (cell->style, STY_FONTS))
289 	  {
290 	  case 0:
291 	    fprintf (fp, "Cells(%d,%d).Font.Size = 6\n", cell->r, cell->c);
292 	    break;
293 	  case 1:
294 	    fprintf (fp, "Cells(%d,%d).Font.Size = 8\n", cell->r, cell->c);
295 	    break;
296 	  case 2:
297 	    fprintf (fp, "Cells(%d,%d).Font.Size = 10\n", cell->r, cell->c);
298 	    break;
299 	  case 3:
300 	    fprintf (fp, "Cells(%d,%d).Font.Size = 12\n", cell->r, cell->c);
301 	    break;
302 	  case 4:
303 	    fprintf (fp, "Cells(%d,%d).Font.Size = 14\n", cell->r, cell->c);
304 	    break;
305 	  case 5:
306 	    fprintf (fp, "Cells(%d,%d).Font.Size = 18\n", cell->r, cell->c);
307 	    break;
308 	  case 6:
309 	    fprintf (fp, "Cells(%d,%d).Font.Size = 24\n", cell->r, cell->c);
310 	    break;
311 	  }
312       if (getstyle (cell->style, STY_FONTW) == 1 || getstyle (cell->style, STY_FONTW) == 3)
313 	fprintf (fp, "Cells(%d,%d).Font.Bold = True \n", cell->r, cell->c);
314 
315       if (getstyle (cell->style, STY_FONTW) == 2 || getstyle (cell->style, STY_FONTW) == 3)
316 	fprintf (fp, "Cells(%d,%d).Font.Italic = True \n", cell->r, cell->c);
317 
318 
319       if (getstyle (cell->style, STY_JUSTIF) != getstyle (ActiveWorkbook->style, STY_JUSTIF))
320 	switch (getstyle (cell->style, STY_JUSTIF))
321 	  {
322 	  case 0:
323 	    fprintf (fp, "Cells(%d,%d).HorizontalAlignment = xlLeft\n",
324 		     cell->r, cell->c);
325 	    break;
326 	  case 1:
327 	    fprintf (fp, "Cells(%d,%d).HorizontalAlignment = xlCenter\n",
328 		     cell->r, cell->c);
329 	    break;
330 	  case 2:
331 	    fprintf (fp, "Cells(%d,%d).HorizontalAlignment = xlRight\n",
332 		     cell->r, cell->c);
333 	    break;
334 	  }
335 
336       if (getstyle (cell->style, STY_BG) != getstyle (ActiveWorkbook->style, STY_BG))
337 	fprintf (fp, "Cells(%d,%d).Interior.ColorIndex = %d\n",
338 		 cell->r, cell->c, getstyle (cell->style, STY_BG) - 5);
339       if (getstyle (cell->style, STY_FG) != getstyle (ActiveWorkbook->style, STY_FG))
340 	fprintf (fp, "Cells(%d,%d).Font.ColorIndex = %d\n",
341 		 cell->r, cell->c, getstyle (cell->style, STY_FG) - 5);
342 
343 
344       format = getstyle (cell->style, STY_FORMAT);
345       deci = getstyle (cell->style, STY_DECIMAL);
346       if ((format != getstyle (ActiveWorkbook->style, STY_FORMAT) ||
347 	   deci != getstyle (ActiveWorkbook->style, STY_DECIMAL)) &&
348 	  format != 0)
349 	{
350 	  if (format >= 2 && format <= 4)
351 	    {
352 	      fprintf (fp, "Cells(%d,%d).NumberFormat = \"0", cell->r, cell->c);
353 	      if (deci)
354 		fprintf (fp, ".");
355 	      while (deci > 0)
356 		{
357 		  fprintf (fp, "0");
358 		  deci--;
359 		};
360 	    }
361 	  switch (format)
362 	    {
363 	    case 2:
364 	      fprintf (fp, "\"\n");
365 	      break;
366 	    case 3:
367 	      fprintf (fp, "E+00\"\n");
368 	      break;
369 	    case 4:
370 	      fprintf (fp, "%%\"\n");
371 	      break;
372 	    case 5:
373 	      {
374 		fprintf (fp, "Cells(%d,%d).NumberFormat = \"", cell->r, cell->c);
375 		fprintf (fp, "dd/mm/yy\"\n");
376 		break;
377 	      }
378 	    default:
379 	      fprintf (fp, "\"\n");
380 	    }
381 	}
382 
383 
384     }
385   return 0;
386 }
387 
388 int
cell_setnumberformat(cell,buf)389 cell_setnumberformat (cell, buf)
390      Cell *cell;
391      char *buf;
392 {
393 
394 
395   int deci = 0;
396   char *dot;
397   char *token;
398 
399   if (strstr (buf, "General"))
400     return 0;
401 
402   token = strchr (buf, ';');
403   if (token != NULL)
404     {
405       token[0] = '\0';
406       token++;
407     }
408 
409   if (buf == NULL)
410     return 1;
411 
412   if (strchr (buf, '/'))
413     {
414       cell_setformat (cell, 5, 0);
415       return 0;
416     }
417 
418   dot = strchr (buf, '.');
419 
420   if (dot != NULL)
421     while (dot[deci + 1] == '0' && deci < strlen (dot))
422       {
423 	deci++;
424       }
425 
426   if (strchr (buf, 'E') || strchr (buf, 'e'))
427     {
428       cell_setformat (cell, 3, deci);
429     }
430   else if (strchr (buf, '%'))
431     {
432       cell_setformat (cell, 4, deci);
433     }
434   else
435     {
436       cell_setformat (cell, 2, deci);
437     }
438 
439   return 0;
440 }
441 
442 
443 int
cell_setformula(cell,str)444 cell_setformula (cell, str)
445      Cell *cell;
446      char *str;
447 {
448   int format, deci, date;
449 
450   int ret;
451   int len;
452   int second = 0;
453   char *buf = NULL;
454 
455 
456   if (cell == NULL)
457     {
458       return 1;
459     }
460 
461   if (cell->formula != NULL)
462     {
463       if (str != NULL)
464 	if (strcmp (cell->formula, str) == 0)
465 	  return 1;
466 
467       if (cell->val.type == STRING_CONSTANT &&
468 	  cell->val.rec.s == cell->formula + 1)
469 	cell->val.rec.s = NULL;
470 
471       absfree (cell->formula, "cell_setformula:cell->formula ");
472       cell->formula = NULL;
473     }
474 
475   if (cell->tree != NULL)
476     {
477       freenode (cell->tree);
478       cell->tree = NULL;
479     };
480 
481   cell_isnew (cell);
482 
483   if (str == NULL)
484     {
485       cell->formula = NULL;
486       cell->val.rec.d = 0.0;
487       cell->val.type = DOUBLE;
488 
489       cell->type = undef;
490       return -1;
491     };
492 
493   while (str[0] == ' ' && str[0] != '\0' && str[0] != '\n')
494     str++;
495   len = strlen (str);
496   if (len < 1)
497     {
498       cell->formula = NULL;
499       cell->val.rec.d = 0.0;
500       cell->val.type = DOUBLE;
501 
502       cell->type = undef;
503       return -1;
504     };
505 
506   {
507     buf = (char *) absmalloc (sizeof (char) * (len + 3), "cell_setformula:buf");
508 
509     if (len > 1)
510       if ('0' <= str[1] && str[1] <= '9')
511 	{
512 	  second = 1;
513 	}
514 
515     if (str[0] == '=' ||
516 	str[0] == '+' ||
517 	str[0] == '-' ||
518 	str[0] == '\'' ||
519 	('0' <= str[0] && str[0] <= '9') ||
520 	(len > 1 && str[0] == '.' && second == 1)
521       )
522       {
523 	strcpy (buf, str);
524       }
525     else
526       {
527 	buf[0] = '\'';
528 	strcpy (buf + 1, str);
529       }
530 
531 
532 
533     cell->formula = (char *) absmalloc (sizeof (char) * (strlen (buf) + 5), "cell_setformula:cell->formula ");
534     if (cell->formula == NULL)
535       {
536 	fprintf (stderr, "formula not allocated\n");
537 	absfree (buf, "cell_setformula:buf");
538 	return -2;
539       }
540 
541 
542     cell_getformat (cell, &format, &deci);
543     if (format == 5)
544       {
545 	date = scandate (buf);
546 	if (date)
547 	  sprintf (buf, "%d\n", date);
548       };
549 
550     len = strlen (buf);
551     strcpy (cell->formula, buf);
552     cell->formula[len] = '\0';
553 
554     if (strncmp (cell->formula, "'", 1) == 0)
555       {
556 
557 
558 
559 
560 
561 	cell->val.type = STRING_CONSTANT;
562 	cell->val.rec.s = cell->formula + 1;
563 
564 	cell->type = text;
565 	nupdate2 (cell, 1);
566 	absfree (buf, "cell_setformula:buf");
567 	return 1;
568       }
569     cell->type = constant;
570 
571 
572     ActiveCell = cell;
573     setting_formula = 1;
574 
575 
576     ret = parsecell (cell);
577 
578 
579     if (ret)
580       {
581 	cell->val.type = STRING_CONSTANT;
582 	cell->val.rec.s = "ERR!";
583 
584 	cell->type = text;
585       }
586     else
587       {
588 	if (cell_is_constant (cell))
589 	  {
590 	    freenode (cell->tree);
591 	    cell->tree = NULL;
592 	    absfree (cell->formula, "cell_setformula:cell->formula ");
593 	    cell->formula = NULL;
594 
595 	  }
596 	else
597 	  {
598 	    execcelltree (cell);
599 	    cell->type = formula;
600 	  }
601       }
602 
603     setting_formula = 0;
604     nupdate2 (cell, 1);
605     absfree (buf, "cell_setformula:buf");
606     return 0;
607   }
608   cell->formula = NULL;
609   cell->val.type = STRING_CONSTANT;
610   cell->val.rec.s = NULL;
611 
612   cell->type = text;
613   absfree (buf, "cell_setformula:buf");
614   return 0;
615 }
616 
617 int
cell_settext(cell,buf)618 cell_settext (cell, buf)
619      Cell *cell;
620      char *buf;
621 {
622   char *end;
623   char *first;
624 
625 
626 
627 
628   if (cell == NULL)
629     {
630       return 1;
631     }
632   if (cell->val.type == STRING_CONSTANT)
633     if (cell->val.rec.s != NULL)
634       {
635 	absfree (cell->val.rec.s, "cell_settext:cell->val.rec.s ");
636 	cell->val.rec.s = NULL;
637       }
638 
639 
640   if (strlen (buf) > 0)
641     {
642 
643       end = strchr (buf, '\n');
644       if (end != NULL)
645 	end = '\0';
646 
647       cell->val.rec.s = (char *) absmalloc (sizeof (char) * (strlen (buf) + 5), "cell_settext:cell->formula ");
648       if (cell->val.rec.s == NULL)
649 	fprintf (stderr, "val.rec.s not allocated\n");
650 
651 
652       first = buf;
653       while (*first == ' ' && first < buf + strlen (buf))
654 	first++;
655       if (*first == '\'')
656 	{
657 	  strcpy (cell->val.rec.s, "'");
658 	  strcat (cell->val.rec.s, first + 1);
659 	  cell->formula = cell->val.rec.s;
660 	  cell->val.rec.s = cell->formula + 1;
661 	}
662       else
663 	strcpy (cell->val.rec.s, buf);
664 
665     }
666   else
667     cell->val.rec.s = NULL;
668 
669   cell->val.type = STRING_CONSTANT;
670 
671   cell->type = text;
672 
673   return 0;
674 }
675 
676 
677 char *
cell_getformula(cell)678 cell_getformula (cell)
679      Cell *cell;
680 {
681   if (cell != NULL)
682     switch (cell->type)
683       {
684       case constant:
685 	{
686 	  double val = cell_getvalue (cell);
687 	  if (val != 0.0)
688 	    {
689 	      sprintf (tmpbuf, "%g", cell_getvalue (cell));
690 	      return tmpbuf;
691 	    }
692 	  break;
693 	}
694       case text:
695 	return cell->formula;
696       case formula:
697 	return cell->formula;
698       case undef:
699 	return NULL;
700       }
701   return NULL;
702 }
703 
704 char *
cell_getnumberformat(cell)705 cell_getnumberformat (cell)
706      Cell *cell;
707 {
708 
709 
710   return NULL;
711 }
712 
713 double
cell_setvalue(cell,val)714 cell_setvalue (cell, val)
715      Cell *cell;
716      double val;
717 {
718   if (cell != NULL)
719     {
720       obj o;
721       o.rec.d = val;
722       o.type = DOUBLE;
723       cell_setobj (cell, o);
724     }
725   return 0.0;
726 }
727 
728 obj
cell_setobj(cell,o)729 cell_setobj (cell, o)
730      Cell *cell;
731      obj o;
732 {
733 
734 
735 
736 
737 
738 
739 
740 
741 
742 
743   char tmp[64];
744   char *buf;
745 
746   if (o.type == STRING)
747     o.type = STRING_CONSTANT;
748 
749   if (cell != NULL)
750     {
751       switch (o.type)
752 	{
753 	case STRING_CONSTANT:
754 	  {
755 	    if (o.rec.s == NULL)
756 	      {
757 		clear_cell (cell);
758 		return o;
759 	      }
760 	    buf = absmalloc (sizeof (char) * (strlen (o.rec.s) + 2), "cell_setobj:buf");
761 	    if (o.rec.s[0] == '\'')
762 	      strcpy (buf, o.rec.s);
763 	    else
764 	      sprintf (buf, "'%s", o.rec.s);
765 	    cell_setformula (cell, buf);
766 	    absfree (buf, "cell_setobj:buf");
767 	    break;
768 	  };
769 	case DOUBLE:
770 	  sprintf (tmp, "%f", o.rec.d);
771 	  cell_setformula (cell, tmp);
772 	  break;
773 	case INTEGER:
774 	  sprintf (tmp, "%d", o.rec.i);
775 	  cell_setformula (cell, tmp);
776 	  break;
777 	}
778     }
779   return o;
780 }
781 
782 obj
cell_setresval(cell,o)783 cell_setresval (cell, o)
784      Cell *cell;
785      obj o;
786 {
787 
788 
789 
790 
791 
792   int len = 0;
793 
794   if (o.type == STRING)
795     o.type = STRING_CONSTANT;
796 
797 
798   if (cell != NULL)
799     {
800 
801       if (o.type == STRING_CONSTANT && o.rec.s != NULL)
802 	{
803 	  len = strlen (o.rec.s);
804 	}
805 
806 
807       if (o.type == STRING_CONSTANT && len == 0)
808 	{
809 	  if (cell->val.type == STRING_CONSTANT && cell->val.rec.s != NULL)
810 	    absfree (cell->val.rec.s, "cell->val.rec.s:null_str");
811 	  cell->val.rec.s = NULL;
812 	  cell->val.type = STRING_CONSTANT;
813 	  return o;
814 	}
815 
816 
817       if (cell->val.type == STRING_CONSTANT)
818 	{
819 	  if (o.type == STRING_CONSTANT)
820 	    {
821 	      cell->val.rec.s = (char *) absrealloc (cell->val.rec.s, (len + 1) * sizeof (char),
822 					       "cell_setresobj::val.rec.s");
823 	      strcpy (cell->val.rec.s, o.rec.s);
824 	      return cell->val;
825 	    }
826 	  else
827 	    {
828 	      if (cell->val.rec.s != NULL)
829 		absfree (cell->val.rec.s, "cell_setresobj::val.rec.s");
830 	      cell->val.rec.s = NULL;
831 	    }
832 	}
833 
834       if (o.type == STRING_CONSTANT)
835 	{
836 	  cell->val.type = STRING_CONSTANT;
837 	  cell->val.rec.s = (char *) absmalloc ((len + 1) * sizeof (char), "cell_setresobj::val.rec.s");
838 	  strcpy (cell->val.rec.s, o.rec.s);
839 	  return cell->val;
840 	};
841 
842 
843       cell->val = o;
844       return cell->val;
845     }
846   return o;
847 }
848 
849 
850 double
cell_getvalue(cell)851 cell_getvalue (cell)
852      Cell *cell;
853 {
854   if (cell == NULL)
855     {
856       return 0.0;
857     }
858 
859   switch (cell->val.type)
860     {
861     case DOUBLE:
862       return cell->val.rec.d;
863     case INTEGER:
864       {
865 	double val = cell->val.rec.i;
866 	return val;
867       }
868     }
869   return 0.0;
870 }
871 
872 obj
cell_getobj(cell)873 cell_getobj (cell)
874      Cell *cell;
875 {
876   if (cell == NULL)
877     {
878       obj o;
879       printf ("getvalue for NULL cell\n");
880       o.type = INTEGER;
881       o.rec.i = 0;
882       return o;
883     }
884   return cell->val;
885 }
886 
887 int
cell_istext(cell)888 cell_istext (cell)
889      Cell *cell;
890 {
891   if (cell == NULL)
892     return 0;
893   if (cell->type == text)
894     return 1;
895   return 0;
896 
897 }
898 
899 char *
cell_gettext(cell)900 cell_gettext (cell)
901      Cell *cell;
902 {
903   char form[8];
904   int format, deci;
905   int dd, mm, yy;
906   double value;
907   if (cell == NULL)
908     {
909       return NULL;
910     }
911   if (cell->type != constant && cell->formula == NULL)
912     {
913       return NULL;
914     }
915 
916 
917   if (cell->type == text || cell->val.type == STRING_CONSTANT)
918     return cell->val.rec.s;
919 
920   cell_getformat (cell, &format, &deci);
921 
922   value = cell_getvalue (cell);
923 
924   switch (format)
925     {
926     case 1:
927       {
928 	sprintf (form, "%%g");
929 	sprintf (tmpbuf, form, value);
930 	break;
931       }
932     case 2:
933       {
934 	sprintf (form, "%%.%dlf", deci);
935 	sprintf (tmpbuf, form, value);
936 	break;
937       }
938     case 3:
939       {
940 	sprintf (form, "%%.%de", deci);
941 	sprintf (tmpbuf, form, value);
942 	break;
943       }
944     case 4:
945       {
946 	sprintf (form, "%%.%dlf%%%%", deci);
947 	sprintf (tmpbuf, form, value * 100.);
948 	break;
949       }
950     case 5:
951       {
952 	int date = value;
953 	num2date (date, &dd, &mm, &yy);
954 	sprintf (tmpbuf, "%2d/%2d/%4d", dd, mm, yy);
955 	break;
956       }
957 
958     }
959 
960   return tmpbuf;
961 }
962 
963 
964 
965 
966 
967 
968 int
cell_setfg(cell,f)969 cell_setfg (cell, f)
970      Cell *cell;
971      int f;
972 {
973   if (cell == NULL)
974     return -1;
975   if (cell->style == NULL)
976     cell->style = newstyle (STY_CELL);
977   setstyle (cell->style, STY_FG, f + 5);
978   return 0;
979 }
980 int
cell_getfg(cell)981 cell_getfg (cell)
982      Cell *cell;
983 {
984   if (cell == NULL || cell->style == NULL)
985     return getstyle (ActiveWorkbook->style, STY_FG);
986 
987   return getstyle (cell->style, STY_FG);
988 }
989 
990 int
cell_setbg(cell,f)991 cell_setbg (cell, f)
992      Cell *cell;
993      int f;
994 {
995   if (cell == NULL)
996     return -1;
997   if (cell->style == NULL)
998     cell->style = newstyle (STY_CELL);
999 
1000   setstyle (cell->style, STY_BG, f + 5);
1001   return 0;
1002 }
1003 
1004 int
cell_getbg(cell)1005 cell_getbg (cell)
1006      Cell *cell;
1007 {
1008   if (cell == NULL || cell->style == NULL)
1009     return getstyle (ActiveWorkbook->style, STY_BG);
1010   return getstyle (cell->style, STY_BG);
1011 }
1012 
1013 
1014 int
cell_gettop(cell)1015 cell_gettop (cell)
1016      Cell *cell;
1017 {
1018   if (cell == NULL || cell->style == NULL)
1019     return getstyle (ActiveWorkbook->style, STY_BORDER_TOP);
1020   return getstyle (cell->style, STY_BORDER_TOP);
1021 }
1022 int
cell_getbot(cell)1023 cell_getbot (cell)
1024      Cell *cell;
1025 {
1026   if (cell == NULL || cell->style == NULL)
1027     return getstyle (ActiveWorkbook->style, STY_BORDER_BOT);
1028   return getstyle (cell->style, STY_BORDER_BOT);
1029 }
1030 int
cell_getrig(cell)1031 cell_getrig (cell)
1032      Cell *cell;
1033 {
1034   if (cell == NULL || cell->style == NULL)
1035     return getstyle (ActiveWorkbook->style, STY_BORDER_RIG);
1036   return getstyle (cell->style, STY_BORDER_RIG);
1037 }
1038 int
cell_getlef(cell)1039 cell_getlef (cell)
1040      Cell *cell;
1041 {
1042   if (cell == NULL || cell->style == NULL)
1043     return getstyle (ActiveWorkbook->style, STY_BORDER_LEF);
1044   return getstyle (cell->style, STY_BORDER_LEF);
1045 }
1046 
1047 int
cell_settop(cell,v)1048 cell_settop (cell, v)
1049      Cell *cell;
1050      int v;
1051 {
1052   if (cell == NULL)
1053     return -1;
1054   if (cell->style == NULL)
1055     cell->style = newstyle (STY_CELL);
1056   setstyle (cell->style, STY_BORDER_TOP, v);
1057   return 0;
1058 }
1059 int
cell_setbot(cell,v)1060 cell_setbot (cell, v)
1061      Cell *cell;
1062      int v;
1063 {
1064   if (cell == NULL)
1065     return -1;
1066   if (cell->style == NULL)
1067     cell->style = newstyle (STY_CELL);
1068   setstyle (cell->style, STY_BORDER_BOT, v);
1069   return 0;
1070 }
1071 int
cell_setrig(cell,v)1072 cell_setrig (cell, v)
1073      Cell *cell;
1074      int v;
1075 {
1076   if (cell == NULL)
1077     return -1;
1078   if (cell->style == NULL)
1079     cell->style = newstyle (STY_CELL);
1080   setstyle (cell->style, STY_BORDER_RIG, v);
1081   return 0;
1082 }
1083 
1084 int
cell_setlef(cell,v)1085 cell_setlef (cell, v)
1086      Cell *cell;
1087      int v;
1088 {
1089   if (cell == NULL)
1090     return -1;
1091   if (cell->style == NULL)
1092     cell->style = newstyle (STY_CELL);
1093   setstyle (cell->style, STY_BORDER_LEF, v);
1094   return 0;
1095 }
1096 
1097 
1098 
1099 
1100 
1101 
1102 int
cell_setformat(cell,format,deci)1103 cell_setformat (cell, format, deci)
1104      Cell *cell;
1105      int format, deci;
1106 {
1107   double date;
1108 
1109   if (cell == NULL)
1110     return -1;
1111   if (cell->style == NULL)
1112     cell->style = newstyle (STY_CELL);
1113 
1114 
1115   if (format == 5 && getstyle (cell->style, STY_FORMAT) != 5)
1116     {
1117       date = scandate (cell_getformula (cell));
1118       if (date)
1119 	cell_setvalue (cell, date);
1120     }
1121 
1122   setstyle (cell->style, STY_FORMAT, format);
1123   setstyle (cell->style, STY_DECIMAL, deci);
1124   return 0;
1125 
1126 }
1127 
1128 int
cell_getformat(cell,format,decimal)1129 cell_getformat (cell, format, decimal)
1130      Cell *cell;
1131      int *format, *decimal;
1132 {
1133   if (cell == NULL)
1134     return -1;
1135   if (cell->style == NULL)
1136     {
1137       *format = getstyle (ActiveWorkbook->style, STY_FORMAT);
1138       *decimal = getstyle (ActiveWorkbook->style, STY_DECIMAL);
1139       return 0;
1140     }
1141   *format = getstyle (cell->style, STY_FORMAT);
1142   *decimal = getstyle (cell->style, STY_DECIMAL);
1143   return 0;
1144 }
1145 
1146 
1147 int
cell_setjust(cell,just)1148 cell_setjust (cell, just)
1149      Cell *cell;
1150      int just;
1151 {
1152   if (cell == NULL)
1153     return -1;
1154   if (cell->style == NULL)
1155     cell->style = newstyle (STY_CELL);
1156   setstyle (cell->style, STY_JUSTIF, just);
1157   return 0;
1158 }
1159 
1160 int
cell_getjust(cell)1161 cell_getjust (cell)
1162      Cell *cell;
1163 {
1164   if (cell == NULL || cell->style == NULL)
1165     return getstyle (ActiveWorkbook->style, STY_JUSTIF);
1166   return getstyle (cell->style, STY_JUSTIF);
1167 }
1168 
1169 
1170 
1171 int
cell_setfont(cell,font,weight,size)1172 cell_setfont (cell, font, weight, size)
1173      Cell *cell;
1174      int font;
1175 {
1176   if (cell == NULL)
1177     return -1;
1178   if (cell->style == NULL)
1179     cell->style = newstyle (STY_CELL);
1180   if (font >= 0)
1181     setstyle (cell->style, STY_FONT, font);
1182   if (weight >= 0)
1183     setstyle (cell->style, STY_FONTW, weight);
1184   if (size >= 0)
1185     setstyle (cell->style, STY_FONTS, size);
1186   return 0;
1187 }
1188 
1189 int
cell_fontname(Cell * cell,char * name)1190 cell_fontname (Cell * cell, char *name)
1191 {
1192 
1193   if (cell->style == NULL)
1194     cell->style = newstyle (STY_CELL);
1195   if (!strcasecmp (name, "fixed"))
1196     setstyle (cell->style, STY_FONT, 0);
1197   if (!strcasecmp (name, "courier"))
1198     setstyle (cell->style, STY_FONT, 1);
1199   if (!strcasecmp (name, "helvetica"))
1200     setstyle (cell->style, STY_FONT, 2);
1201   if (!strcasecmp (name, "times"))
1202     setstyle (cell->style, STY_FONT, 3);
1203   if (!strcasecmp (name, "symbol"))
1204     setstyle (cell->style, STY_FONT, 4);
1205   return 0;
1206 }
1207 
1208 int
cell_fontsize(cell,v)1209 cell_fontsize (cell, v)
1210      Cell *cell;
1211      int v;
1212 {
1213 
1214   if (cell->style == NULL)
1215     cell->style = newstyle (STY_CELL);
1216   switch (v)
1217     {
1218     case 6:
1219       setstyle (cell->style, STY_FONTS, 0);
1220       break;
1221     case 8:
1222       setstyle (cell->style, STY_FONTS, 1);
1223       break;
1224     case 10:
1225       setstyle (cell->style, STY_FONTS, 2);
1226       break;
1227     case 12:
1228       setstyle (cell->style, STY_FONTS, 3);
1229       break;
1230     case 14:
1231       setstyle (cell->style, STY_FONTS, 4);
1232       break;
1233     case 18:
1234       setstyle (cell->style, STY_FONTS, 5);
1235       break;
1236     case 24:
1237       setstyle (cell->style, STY_FONTS, 6);
1238       break;
1239     }
1240   return 0;
1241 }
1242 
1243 int
cell_fontbold(cell,v)1244 cell_fontbold (cell, v)
1245      Cell *cell;
1246      int v;
1247 {
1248 
1249   if (cell->style == NULL)
1250     cell->style = newstyle (STY_CELL);
1251   if (v == 0)
1252     {
1253       if (getstyle (cell->style, STY_FONTW) > 1)
1254 	setstyle (cell->style, STY_FONTW, 2);
1255       else
1256 	setstyle (cell->style, STY_FONTW, 0);
1257     }
1258   else
1259     {
1260       if (getstyle (cell->style, STY_FONTW) > 1)
1261 	setstyle (cell->style, STY_FONTW, 3);
1262       else
1263 	setstyle (cell->style, STY_FONTW, 1);
1264     }
1265   return 0;
1266 }
1267 
1268 int
cell_fontitalic(cell,v)1269 cell_fontitalic (cell, v)
1270      Cell *cell;
1271      int v;
1272 {
1273   int w;
1274 
1275   if (cell->style == NULL)
1276     cell->style = newstyle (STY_CELL);
1277   w = getstyle (cell->style, STY_FONTW);
1278   if (v == 0)
1279     {
1280       if (w == 1 || w == 3)
1281 	setstyle (cell->style, STY_FONTW, 1);
1282       else
1283 	setstyle (cell->style, STY_FONTW, 0);
1284     }
1285   else
1286     {
1287       if (w == 1 || w == 3)
1288 	setstyle (cell->style, STY_FONTW, 3);
1289       else
1290 	setstyle (cell->style, STY_FONTW, 2);
1291     }
1292   return 0;
1293 }
1294 
1295 int
cell_getfont(cell)1296 cell_getfont (cell)
1297      Cell *cell;
1298 {
1299   if (cell == NULL || cell->style == NULL)
1300     return getstyle (ActiveWorkbook->style, STY_FONT);
1301   return getstyle (cell->style, STY_FONT);
1302   return 0;
1303 }
1304 
1305 int
cell_getfontw(cell)1306 cell_getfontw (cell)
1307      Cell *cell;
1308 {
1309   if (cell == NULL || cell->style == NULL)
1310     return getstyle (ActiveWorkbook->style, STY_FONTW);
1311   return getstyle (cell->style, STY_FONTW);
1312   return 0;
1313 }
1314 int
cell_getfonts(cell)1315 cell_getfonts (cell)
1316      Cell *cell;
1317 {
1318   if (cell == NULL || cell->style == NULL)
1319     return getstyle (ActiveWorkbook->style, STY_FONTS);
1320   return getstyle (cell->style, STY_FONTS);
1321   return 0;
1322 }
1323 
1324 
1325 int
cell_setborders(cell,border,type)1326 cell_setborders (cell, border, type)
1327      Cell *cell;
1328      int border;
1329      int type;
1330 {
1331   if (cell == NULL)
1332     return -1;
1333   if (cell->style == NULL)
1334     cell->style = newstyle (STY_CELL);
1335 
1336   if (border == 8 || border == 0)
1337     setstyle (cell->style, STY_BORDER_TOP, type);
1338   if (border == 7 || border == 0)
1339     setstyle (cell->style, STY_BORDER_LEF, type);
1340   if (border == 9 || border == 0)
1341     setstyle (cell->style, STY_BORDER_BOT, type);
1342   if (border == 10 || border == 0)
1343     setstyle (cell->style, STY_BORDER_RIG, type);
1344   return 0;
1345 }
1346 
1347 
1348 int
cell_setborder(cell,border)1349 cell_setborder (cell, border)
1350      Cell *cell;
1351      int border;
1352 {
1353   if (cell == NULL)
1354     return -1;
1355   if (cell->style == NULL)
1356     cell->style = newstyle (STY_CELL);
1357 
1358   setstyle (cell->style, STY_BORDER, border);
1359   return 0;
1360 }
1361 
1362 int
cell_getborder(cell)1363 cell_getborder (cell)
1364      Cell *cell;
1365 {
1366   if (cell == NULL || cell->style == NULL)
1367     return getstyle (ActiveWorkbook->style, STY_BORDER);
1368   return getstyle (cell->style, STY_BORDER);
1369   return 0;
1370 }
1371 
1372 
1373 
1374 int
parsecell(cell)1375 parsecell (cell)
1376      Cell *cell;
1377 {
1378   ActiveCell = cell;
1379   if (cell == NULL)
1380     return -1;
1381   if (cell->formula == NULL)
1382     return -2;
1383 
1384   cell->tree = parseexpression (cell->formula);
1385 
1386   if (cell->tree == NULL)
1387     return 1;
1388 
1389   setcelltree (cell->tree);
1390   return 0;
1391 }
1392 
1393 int
copymod(ii,jj,i,j,incr)1394 copymod (ii, jj, i, j, incr)
1395      int i, j, ii, jj, incr;
1396 {
1397   Cell *cell1;
1398   Cell *cell2;
1399   cell1 = (Cell *) applicationcell (i, j, 1);
1400   cell2 = (Cell *) applicationcell (ii, jj, 1);
1401   return copymod2 (cell1, cell2, i, j, (i - ii) * incr, (j - jj) * incr);
1402 }
1403 
1404 
1405 
1406 int
copymod2(cell1,cell2,_curi,_curj,_di,_dj)1407 copymod2 (cell1, cell2, _curi, _curj, _di, _dj)
1408      Cell *cell1;
1409      Cell *cell2;
1410      int _curi, _curj, _di, _dj;
1411 {
1412   setdi (_di);
1413   setdj (_dj);
1414   cell_setformula (cell1, cell_getformula (cell2));
1415   setdi (0);
1416   setdj (0);
1417 
1418   return 0;
1419 }
1420 
1421 int
copymod3(cell1,cell2,incr)1422 copymod3 (cell1, cell2, incr)
1423      Cell *cell1;
1424      Cell *cell2;
1425      int incr;
1426 {
1427   if (cell1 == NULL || cell2 == NULL)
1428     return -1;
1429 
1430   setdi ((cell1->r - cell2->r) * incr);
1431   setdj ((cell1->c - cell2->c) * incr);
1432   cell_setformula (cell1, cell_getformula (cell2));
1433   setdi (0);
1434   setdj (0);
1435 
1436   return 0;
1437   return 0;
1438 }
1439 
1440 
1441 
1442 
1443 
1444 
1445 
1446 char *
tolower(char * s)1447 tolower (char *s)
1448 {
1449   int j;
1450   int len;
1451   len = strlen (s);
1452   for (j = 0; j < len; j++)
1453     if (s[j] >= 'A' && s[j] <= 'Z')
1454       s[j] = 'a' + s[j] - 'A';
1455   return s;
1456 }
1457 
1458 char *
sstrcasestr_(char * str1,char * str2)1459 sstrcasestr_ (char *str1, char *str2)
1460 {
1461   char *s1;
1462   char *s2;
1463   char *pos = NULL;
1464   int l1;
1465   s1 = strdup (str1);
1466   if (s1 == NULL)
1467     return NULL;
1468   s2 = strdup (str2);
1469   if (s2 == NULL)
1470     {
1471       free (s1);
1472       return NULL;
1473     }
1474 
1475   tolower (s1);
1476   tolower (s2);
1477   pos = strstr (s1, s2);
1478   l1 = pos - s1;
1479   free (s1);
1480   free (s2);
1481   if (pos == NULL)
1482     return NULL;
1483 
1484   return str1 + l1;
1485 }
1486 
1487 int
cell_chgwksname(Cell * cell,char * oldname,char * newname)1488 cell_chgwksname (Cell * cell, char *oldname, char *newname)
1489 {
1490   int len = 0;
1491   int i = 0;
1492   int diffsize;
1493   char *newformula = NULL;
1494   char *old, *pos, *end;
1495   if (cell == NULL)
1496     return -1;
1497   if (cell->formula == NULL)
1498     return 0;
1499   if (cell->tree == NULL)
1500     return 0;
1501   if (oldname == NULL || newname == NULL)
1502     return -1;
1503   if (strlen (oldname) < 1 || strlen (newname) < 1)
1504     return -1;
1505   if (!strcmp (oldname, newname))
1506     return 0;
1507   if (sstrcasestr_ (cell->formula, oldname) == NULL)
1508     return 0;
1509 
1510 
1511   diffsize = strlen (oldname) - strlen (newname);
1512   old = absmalloc ((strlen (oldname) + 2) * sizeof (char), "cell_chgwksname:old");
1513   sprintf (old, "%s!", oldname);
1514 
1515   pos = sstrcasestr_ (cell->formula, old);
1516   while (pos != NULL)
1517     {
1518       len = strlen (cell->formula);
1519       newformula = (char *) absmalloc ((len + 1 + diffsize) * sizeof (char), "cell_chgwksname:newformula");
1520       end = strchr (pos, '!');
1521       pos[0] = '\0';
1522       i = strlen (cell->formula) + strlen (newname) + 1;
1523       sprintf (newformula, "%s%s%s", cell->formula, newname, end);
1524       absfree (cell->formula, "cell_chgwksname:cell->formula");
1525       cell->formula = newformula;
1526       end = sstrcasestr_ (cell->formula, old);
1527       if (end > cell->formula + i)
1528 	pos = end;
1529       else
1530 	pos = NULL;
1531     }
1532 
1533 
1534   return 0;
1535 }
1536 
1537 int
cell1isfcell2(cell1,cell2)1538 cell1isfcell2 (cell1, cell2)
1539      Cell *cell1;
1540      Cell *cell2;
1541 {
1542   int numpar1;
1543   int numchi2;
1544   int k;
1545   Cell **tmp;
1546 
1547 
1548 
1549 
1550 
1551 
1552   if (cell1 == cell2)
1553     return 1;
1554 
1555   if (cell1->familly == NULL)
1556     {
1557       cell1->familly = (Familly *) absmalloc (sizeof (Familly), "cell1isfcell2:cell1->familly ");
1558       if (cell1->familly == NULL)
1559 	fprintf (stderr, "cell1->familly not allocated!\n");
1560       cell1->familly->numpar = 0;
1561       cell1->familly->dimparlist = 0;
1562       cell1->familly->parentlist = NULL;
1563       cell1->familly->numchi = 0;
1564       cell1->familly->dimchilist = 0;
1565       cell1->familly->childlist = NULL;
1566     }
1567   if (cell2->familly == NULL)
1568     {
1569       cell2->familly = (Familly *) absmalloc (sizeof (Familly), "cell1isfcell2:cell2->familly ");
1570       if (cell2->familly == NULL)
1571 	fprintf (stderr, "cell2->familly not allocated!\n");
1572       cell2->familly->numpar = 0;
1573       cell2->familly->dimparlist = 0;
1574       cell2->familly->parentlist = NULL;
1575       cell2->familly->numchi = 0;
1576       cell2->familly->dimchilist = 0;
1577       cell2->familly->childlist = NULL;
1578     }
1579 
1580   numpar1 = cell1->familly->numpar;
1581   numchi2 = cell2->familly->numchi;
1582 
1583   if (cell1->familly->dimparlist < numpar1 + 1)
1584     {
1585       tmp = (Cell **) absmalloc (sizeof (Cell *) * (2 * numpar1 + 2), "cell1isfcell2:tmp ");
1586       if (tmp == NULL)
1587 	fprintf (stderr, "tmp  not allocated!\n");
1588       for (k = 0; k < numpar1; k++)
1589 	tmp[k] = cell1->familly->parentlist[k];
1590       if (cell1->familly->parentlist != NULL)
1591 	absfree (cell1->familly->parentlist, "cell1isfcell2:cell1->familly->parentlist ");
1592       cell1->familly->parentlist = tmp;
1593       cell1->familly->dimparlist = 2 * numpar1 + 2;
1594     }
1595 
1596   if (cell2->familly->dimchilist < numchi2 + 1)
1597     {
1598       tmp = (Cell **) absmalloc (sizeof (Cell *) * (2 * numchi2 + 2), "cell1isfcell2:tmp ");
1599       if (tmp == NULL)
1600 	fprintf (stderr, "tmp  not allocated!\n");
1601       for (k = 0; k < numchi2; k++)
1602 	{
1603 	  tmp[k] = cell2->familly->childlist[k];
1604 
1605 	}
1606       if (cell2->familly->dimchilist > 0 && cell2->familly->childlist != NULL)
1607 	absfree (cell2->familly->childlist, "cell1isfcell2:cell2->familly->childlist ");
1608       cell2->familly->childlist = tmp;
1609       cell2->familly->dimchilist = 2 * numchi2 + 2;
1610     }
1611 
1612   for (k = 0; k < numpar1; k++)
1613     {
1614 
1615       if (cell2 == cell1->familly->parentlist[k])
1616 	return 2;
1617     }
1618   cell1->familly->parentlist[numpar1] = cell2;
1619   cell1->familly->numpar++;
1620   cell2->familly->childlist[numchi2] = cell1;
1621   cell2->familly->numchi++;
1622 
1623 
1624 
1625 
1626   return 0;
1627 }
1628 
1629 int
pfamilly2(cell)1630 pfamilly2 (cell)
1631      Cell *cell;
1632 {
1633   int k;
1634   Cell *cell2;
1635   if (cell == NULL)
1636     fprintf (stderr, "pfamilly of null cell\n");
1637 
1638   if (cell->familly == NULL)
1639     return 1;
1640 
1641 
1642   printf ("cell %d (r=%d c=%d)\n", cell->objnum, cell->r, cell->c);
1643 
1644 
1645   for (k = 0; k < cell->familly->numchi; k++)
1646     {
1647       cell2 = cell->familly->childlist[k];
1648       if (cell2)
1649 	printf ("   - child %d: %d (wks=%s r=%d c=%d)\n", k, cell2->objnum, cell2->worksheet->Name, cell2->r, cell2->c);
1650       else
1651 	printf ("   - child %d: NULL\n", k);
1652     }
1653 
1654   for (k = 0; k < cell->familly->numpar; k++)
1655     {
1656       cell2 = cell->familly->parentlist[k];
1657       if (cell2)
1658 	printf ("   - parent %d: %d (wks=%s r=%d c=%d)\n", k, cell2->objnum, cell2->worksheet->Name, cell2->r, cell2->c);
1659       else
1660 	printf ("   - parent %d: NULL\n", k);
1661 
1662     }
1663 
1664   return 0;
1665 }
1666 
1667 void
cell_auditcell(Cell * cell)1668 cell_auditcell (Cell * cell)
1669 {
1670   pfamilly2 (cell);
1671 }
1672 
1673 int
cell_isnew(cell)1674 cell_isnew (cell)
1675      Cell *cell;
1676 {
1677   int k;
1678   Cell *i2j2;
1679   int l, found;
1680 
1681   if (updating || parsing)
1682     return 1;
1683 
1684   if (cell->familly == NULL)
1685     return 2;
1686 
1687   for (k = 0; k < cell->familly->numpar; k++)
1688     {
1689       i2j2 = cell->familly->parentlist[k];
1690 
1691 
1692       found = 0;
1693       if (i2j2->familly != NULL)
1694 	{
1695 	  for (l = 0; l < i2j2->familly->numchi; l++)
1696 	    {
1697 	      if (i2j2->familly->childlist[l] == cell)
1698 		found = 1;
1699 	      if (found)
1700 		{
1701 		  i2j2->familly->childlist[l] = i2j2->familly->childlist[l + 1];
1702 		}
1703 	    }
1704 	  i2j2->familly->numchi--;
1705 	}
1706     }
1707 
1708 
1709   if (cell->familly->numpar > 0)
1710     {
1711       cell->familly->numpar = 0;
1712       absfree (cell->familly->parentlist, "cell_isnew:cell->familly->parentlist ");
1713       cell->familly->parentlist = NULL;
1714       cell->familly->dimparlist = 0;
1715     }
1716   cell->familly->numpar = 0;
1717 
1718   if (cell->familly->numchi == 0)
1719     {
1720       if (cell->familly->dimchilist > 0)
1721 	absfree (cell->familly->childlist, "cell_isnew:cell->familly->childlist ");
1722       absfree (cell->familly, "cell_isnew:cell->familly ");
1723       cell->familly = NULL;
1724     }
1725 
1726 
1727 
1728 
1729   return 0;
1730 
1731 }
1732 
1733 extern int xdrawcell ();
1734 static Cell *iterbase;
1735 int
nupdate2(Cell * cell,int redraw)1736 nupdate2 (Cell * cell, int redraw)
1737 {
1738   int k;
1739   Cell *cell2;
1740 
1741   if (parsing)
1742     return 1;
1743 
1744   if (cell == NULL)
1745     return 2;
1746 
1747   if (cell->familly == NULL)
1748     {
1749       return 3;
1750     }
1751   if (updating == 0)
1752     iterbase = cell;
1753   else if (cell == iterbase)
1754     {
1755       fprintf (stderr, "circular reference in cell %d %d\n", cell->r, cell->c);
1756       return 0;
1757     }
1758 
1759   updating++;
1760 
1761   for (k = 0; k < cell->familly->numchi; k++)
1762     {
1763       cell2 = cell->familly->childlist[k];
1764       if (cell2->formula != NULL && cell2->tree != NULL)
1765 	{
1766 	  int exist = 0;
1767 	  int i;
1768 	  execcelltree (cell2);
1769 	  nupdate2 (cell2, redraw);
1770 	  if (redraw)
1771 	    for (i = 0; i < ntoredraw; i++)
1772 	      {
1773 		if (toredraw[i] == cell2)
1774 		  {
1775 		    exist = 1;
1776 		    i = ntoredraw;
1777 		  }
1778 	      }
1779 
1780 	  if (!exist)
1781 	    {
1782 	      toredraw = (Cell **) absrealloc (toredraw, sizeof (Cell *) * (ntoredraw + 1), "nupdate2:toredraw ");
1783 	      toredraw[ntoredraw] = cell2;
1784 	      ntoredraw++;
1785 	    }
1786 	}
1787     }
1788   updating--;
1789 
1790 
1791   if (updating == 0 && ntoredraw > 0)
1792     {
1793       for (k = 0; k < ntoredraw; k++)
1794 	xdrawcell (toredraw[k]->r, toredraw[k]->c, 0);
1795       absfree (toredraw, "nupdate2:toredraw ");
1796       toredraw = NULL;
1797       ntoredraw = 0;
1798     }
1799   return 0;
1800 }
1801 
1802 
1803 extern char *obj2string (obj o);
1804 extern obj getidval3 (int i);
1805 extern int findid (char *s);
1806 
1807 
1808 char *
textparsing(buf)1809 textparsing (buf)
1810      char *buf;
1811 {
1812   Cell *cell;
1813   Cell *activecell = ActiveCell;
1814   if (parsingmacro)
1815     {
1816       sprintf (tmpbuf, "to update");
1817       return tmpbuf;
1818     }
1819   cell = newcell (0, 1);
1820 
1821   cell_setformula (cell, buf);
1822   strcpy (tmpbuf, cell_gettext (cell));
1823 
1824   cell_isnew (cell);
1825   freecell (cell);
1826   ActiveCell = activecell;
1827   return tmpbuf;
1828 }
1829 
1830 
1831 Cell *
cell_cpy(cell1,cell2)1832 cell_cpy (cell1, cell2)
1833      Cell *cell1;
1834      Cell *cell2;
1835 {
1836   int len;
1837 
1838   if (cell1 == NULL || cell2 == NULL)
1839     return NULL;
1840 
1841   if (cell2->val.type == DOUBLE)
1842     {
1843       cell1->val.rec.d = cell2->val.rec.d;
1844       cell1->val.type = DOUBLE;
1845     }
1846 
1847   if (cell2->val.type == INTEGER)
1848     {
1849       cell1->val.rec.i = cell2->val.rec.i;
1850       cell1->val.type = INTEGER;
1851     }
1852 
1853 
1854 
1855 
1856   if (cell2->formula != NULL)
1857     {
1858       len = strlen (cell2->formula);
1859       if (len > 0)
1860 	{
1861 	  cell1->formula = (char *) absmalloc (sizeof (char) * len, "cell_cpy:cell1->formula ");
1862 	  if (cell1->formula == NULL)
1863 	    fprintf (stderr, "cell1->formula  not allocated!\n");
1864 	  strcpy (cell1->formula, cell2->formula);
1865 	  cell1->formula[len] = '\0';
1866 	}
1867     }
1868 
1869   cell1->type = cell2->type;
1870 
1871   if (cell2->style != NULL)
1872     {
1873       if (cell1->style == NULL)
1874 	cell1->style = newstyle (STY_CELL);
1875       style_cpy (cell1->style, cell2->style);
1876     }
1877   else
1878     {
1879       if (cell1->style != NULL)
1880 	{
1881 	  freestyle (cell1->style);
1882 	  cell1->style = NULL;
1883 	}
1884     }
1885   return cell1;
1886 }
1887 
1888 Cell *
cell_stycpy(cell1,cell2)1889 cell_stycpy (cell1, cell2)
1890      Cell *cell1;
1891      Cell *cell2;
1892 {
1893 
1894   if (cell1 == NULL || cell2 == NULL)
1895     return NULL;
1896 
1897   if (cell2->style != NULL)
1898     {
1899       if (cell1->style == NULL)
1900 	cell1->style = newstyle (STY_CELL);
1901       style_cpy (cell1->style, cell2->style);
1902     }
1903   else
1904     {
1905       if (cell1->style != NULL)
1906 	{
1907 	  freestyle (cell1->style);
1908 	  cell1->style = NULL;
1909 	}
1910     }
1911   return cell1;
1912 }
1913 
1914 int
cell_calculate(Cell * cell)1915 cell_calculate (Cell * cell)
1916 {
1917   return nupdate2 (cell, 0);
1918 }
1919 
1920 int
cell_print(Cell * cell)1921 cell_print (Cell * cell)
1922 {
1923   if (cell == NULL)
1924     fprintf (stderr, "cell is NULL!\n");
1925   else
1926     fprintf (stderr, "cell %d %d formula %s\n", cell->r, cell->c, cell_getformula (cell));
1927   return 0;
1928 }
1929