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 
52 
53 
54 
55 
56 #include "cell_vb.h"
57 #include "formula_interpret.h"
58 #include "libfct.h"
59 #include "application.h"
60 #include "worksheet.h"
61 #include "node.h"
62 #include "border_vb.h"
63 #include "memory.h"
64 #include "util.h"
65 #include "print.h"
66 
67 obj
vb_absnewcell(narg,arg)68 vb_absnewcell (narg, arg)
69      int narg;
70      obj *arg;
71 {
72   obj o;
73   Cell *cell = NULL;
74   if (arg[0].type == INTEGER && arg[1].type == INTEGER
75       && arg[2].type == STRING_CONSTANT)
76     {
77       cell = applicationcell (obj2int (arg[0]), obj2int (arg[1]), 1);
78       cell_setformula (cell, obj2string (arg[2]));
79     }
80   o.rec.s = (char *) cell;
81   o.type = CELL;
82   o.label = arrayclass[CELL].name;
83   return o;
84 }
85 
86 obj
vb_getcell(narg,arg)87 vb_getcell (narg, arg)
88      int narg;
89      obj *arg;
90 {
91   obj o;
92   Cell *cell;
93 
94   o.rec.s = (char *) applicationcell (obj2int (arg[0]), obj2int (arg[1]), 1);
95   cell = (Cell *) o.rec.s;
96 
97   o.type = CELL;
98   o.label = arrayclass[CELL].name;
99   return o;
100 }
101 
102 obj
vb_getrange1(narg,arg)103 vb_getrange1 (narg, arg)
104      int narg;
105      obj *arg;
106 {
107   obj o;
108 
109 
110   if (narg == 1)
111     {
112       if (arg[0].type == RANGE)
113 	return arg[0];
114 
115       o.rec.s = obj2string (arg[0]);
116       o.type = RANGE;
117       o.label = NULL;
118       return o;
119     }
120   return o;
121 }
122 
123 obj
vb_get_ActiveCell()124 vb_get_ActiveCell ()
125 {
126   obj o;
127   o.rec.s = (char *) ActiveCell;
128   o.type = CELL;
129   o.label = NULL;
130   return o;
131 }
132 
133 extern int getselection (int *i1, int *j1, int *i2, int *j2);
134 
135 obj
vb_get_Selection()136 vb_get_Selection ()
137 {
138   obj o;
139   int i1, i2, j1, j2;
140   getselection (&i1, &j1, &i2, &j2);
141   if (i1 == i2 && j1 == j2)
142     {
143       o.rec.s = (char *) applicationcell (i1, j1, 1);
144       o.type = CELL;
145     }
146   else
147     {
148 
149 
150     }
151   o.label = NULL;
152   return o;
153 }
154 
155 
156 obj
vb_cell_setobj(narg,arg)157 vb_cell_setobj (narg, arg)
158      int narg;
159      obj *arg;
160 {
161   obj o;
162   int r, c;
163   tmpRange *ran;
164 
165 
166   if (arg[0].type == CELL)
167     {
168       cell_setobj ((Cell *) arg[0].rec.s, arg[1]);
169       return o;
170     }
171 
172   if (arg[0].type == RANGE)
173     {
174       ran = (tmpRange *) arg[0].rec.s;
175       if (ran->wks == NULL)
176 	{
177 	  for (r = ran->r1; r <= ran->r2; r++)
178 	    for (c = ran->c1; c <= ran->c2; c++)
179 	      cell_setobj (applicationcell (r, c, 1), arg[1]);
180 	}
181       else
182 	{
183 	  for (r = ran->r1; r <= ran->r2; r++)
184 	    for (c = ran->c1; c <= ran->c2; c++)
185 	      cell_setobj (worksheet_getcell (ran->wks, r, c, 1), arg[1]);
186 	}
187     }
188 
189 
190   return o;
191 }
192 
193 obj
vb_cell_getobj(narg,arg)194 vb_cell_getobj (narg, arg)
195      int narg;
196      obj *arg;
197 {
198   obj o;
199   o = cell_getobj ((Cell *) arg[0].rec.s);
200   return o;
201 }
202 
203 obj
vb_cell_setvalue(narg,arg)204 vb_cell_setvalue (narg, arg)
205      int narg;
206      obj *arg;
207 {
208   obj o;
209   int r, c;
210   tmpRange *ran;
211   obj *cellORrange = (obj *) arg[0].rec.s;
212 
213 
214   if (cellORrange->type == CELL)
215     {
216       cell_setobj ((Cell *) cellORrange->rec.s, arg[1]);
217       return o;
218     }
219 
220   if (cellORrange->type == RANGE)
221     {
222       ran = (tmpRange *) cellORrange->rec.s;
223       if (ran->wks == NULL)
224 	{
225 	  for (r = ran->r1; r <= ran->r2; r++)
226 	    for (c = ran->c1; c <= ran->c2; c++)
227 	      cell_setobj (applicationcell (r, c, 1), arg[1]);
228 	}
229       else
230 	{
231 	  for (r = ran->r1; r <= ran->r2; r++)
232 	    for (c = ran->c1; c <= ran->c2; c++)
233 	      cell_setobj (worksheet_getcell (ran->wks, r, c, 1), arg[1]);
234 	}
235     }
236 
237 
238 
239 
240   return o;
241 }
242 
243 obj
vb_cell_getvalue(narg,arg)244 vb_cell_getvalue (narg, arg)
245      int narg;
246      obj *arg;
247 {
248   obj o;
249   obj *cell = (obj *) arg[0].rec.s;
250 
251   o = cell_getobj ((Cell *) cell->rec.s);
252 
253   return o;
254 }
255 
256 obj
vb_cell_setformula(narg,arg)257 vb_cell_setformula (narg, arg)
258      int narg;
259      obj *arg;
260 {
261   obj o;
262   obj *cell = (obj *) arg[0].rec.s;
263 
264   if (arg[1].type == STRING_CONSTANT)
265     {
266       cell_setformula ((Cell *) cell->rec.s, obj2string (arg[1]));
267     }
268   return o;
269 }
270 
271 obj
vb_cell_getformula(narg,arg)272 vb_cell_getformula (narg, arg)
273      int narg;
274      obj *arg;
275 {
276   obj o;
277   o.rec.d = cell_getvalue ((Cell *) arg[0].rec.s);
278   o.type = DOUBLE;
279   return o;
280 
281 }
282 
283 obj
vb_cell_sethalign(narg,arg)284 vb_cell_sethalign (narg, arg)
285      int narg;
286      obj *arg;
287 {
288   obj o;
289   obj *cell = (obj *) arg[0].rec.s;
290 
291 
292   cell_setjust ((Cell *) cell->rec.s, obj2int (arg[1]));
293   return o;
294 }
295 
296 obj
vb_cell_gethalign(narg,arg)297 vb_cell_gethalign (narg, arg)
298      int narg;
299      obj *arg;
300 {
301   obj o;
302   o.rec.d = cell_getvalue ((Cell *) arg[0].rec.s);
303   o.type = DOUBLE;
304   return o;
305 
306 }
307 
308 obj
vb_cell_setnumform(narg,arg)309 vb_cell_setnumform (narg, arg)
310      int narg;
311      obj *arg;
312 {
313   obj o;
314   obj *cell = (obj *) arg[0].rec.s;
315 
316 
317   cell_setnumberformat ((Cell *) cell->rec.s, obj2string (arg[1]));
318   return o;
319 }
320 
321 obj
vb_cell_getnumform(narg,arg)322 vb_cell_getnumform (narg, arg)
323      int narg;
324      obj *arg;
325 {
326   obj o;
327   o.rec.d = cell_getvalue ((Cell *) arg[0].rec.s);
328   o.type = DOUBLE;
329   return o;
330 
331 }
332 
333 obj
vb_cell_setinterior(narg,arg)334 vb_cell_setinterior (narg, arg)
335      int narg;
336      obj *arg;
337 {
338   obj o;
339   obj *cell = (obj *) arg[0].rec.s;
340   cell_setbg ((Cell *) cell->rec.s, obj2int (arg[1]));
341   return o;
342 }
343 
344 obj
vb_cell_getinterior(narg,arg)345 vb_cell_getinterior (narg, arg)
346      int narg;
347      obj *arg;
348 {
349   obj o;
350   o.rec.d = cell_getvalue ((Cell *) arg[0].rec.s);
351   o.type = DOUBLE;
352   return o;
353 
354 }
355 
356 static Border bord;
357 
358 obj
vb_cell_getborder(narg,arg)359 vb_cell_getborder (narg, arg)
360      int narg;
361      obj *arg;
362 {
363   obj o;
364 
365 
366   bord.which = obj2int (arg[1]);
367   bord.object = arg[0];
368 
369   o.type = BORDER;
370   o.label = NULL;
371   o.rec.s = (char *) &bord;
372   return o;
373 }
374 
375 obj
vb_cell_getborders(narg,arg)376 vb_cell_getborders (narg, arg)
377      int narg;
378      obj *arg;
379 {
380   obj o;
381   bord.which = 0;
382   bord.object = arg[0];
383   o.type = BORDER;
384   o.label = NULL;
385   o.rec.s = (char *) &bord;
386   return o;
387 }
388 
389 obj
vb_cell_setborders(narg,arg)390 vb_cell_setborders (narg, arg)
391      int narg;
392      obj *arg;
393 {
394   obj o;
395   bord.which = 0;
396   bord.object = arg[0];
397   o.type = BORDER;
398   o.label = NULL;
399   o.rec.s = (char *) &bord;
400   return o;
401 }
402 
403 
404 
405 
406 obj
vb_cell_assign(narg,arg)407 vb_cell_assign (narg, arg)
408      int narg;
409      obj *arg;
410 {
411   obj o;
412   if (arg[0].type != CELL)
413     return o;
414 
415   if (arg[1].type == CELL)
416     {
417       obj val = cell_getobj ((Cell *) arg[1].rec.s);
418       cell_setobj ((Cell *) arg[0].rec.s, val);
419     }
420   else
421     {
422       cell_setobj ((Cell *) arg[0].rec.s, arg[1]);
423     }
424 
425   return o;
426 }
427 
428 obj
vb_cell_print(narg,arg)429 vb_cell_print (narg, arg)
430      int narg;
431      obj *arg;
432 {
433   obj o = arg[0];
434   if (arg[0].type == CELL)
435     {
436       printparam.print2file = 1;
437       printparam.language = "ps";
438       printparam.print2file = PORTRAIT;
439       printparam.center = FLUSH_TOP_LEFT;
440       printparam.magnification = 1.0;
441       printparam.copies = 1;
442       printparam.papertype = "A4";
443       printparam.xshift = 0;
444       printparam.yshift = 0;
445       printparam.multiplepage = 0;
446       printparam.filename = "output.ps";
447       printfile (printparam);
448       return o;
449     }
450   o.type = INTEGER;
451   return o;
452 }
453 
454 extern int setselection (int i1, int j1, int i2, int j2);
455 
456 obj
vb_cell_select(narg,arg)457 vb_cell_select (narg, arg)
458      int narg;
459      obj *arg;
460 {
461   obj o = arg[0];
462   if (arg[0].type == CELL)
463     {
464       Cell *cell = (Cell *) arg[0].rec.s;
465       setselection (cell->r, cell->c, cell->r, cell->c);
466       return o;
467     }
468   if (arg[0].type == RANGE)
469     {
470       char *valuerange = arg[0].rec.s;
471       char *i1j1;
472       char *i2j2;
473       char *separ;
474       int r1, c1, r2, c2;
475       if (valuerange == NULL)
476 	return o;
477       separ = strchr (valuerange, ':');
478       if (separ == NULL)
479 	return o;
480       i1j1 = valuerange;
481       i2j2 = separ + 1;
482       separ[0] = '\0';
483       alphatonum (i1j1, &r1, &c1);
484       alphatonum (i2j2, &r2, &c2);
485       setselection (r1, c1, r2, c2);
486     }
487   return o;
488 }
489 
490 
491 
492 
493 
494 static int rrr, ccc;
495 static nodeType *wksname = NULL;
496 static int dr = 0;
497 static int dc = 0;
498 static int sr = -1;
499 static int sc = -1;
500 
501 int
get_id2row()502 get_id2row ()
503 {
504   return rrr;
505 }
506 int
get_id2col()507 get_id2col ()
508 {
509   return ccc;
510 }
511 
512 int
setdi(int i)513 setdi (int i)
514 {
515   dr = i;
516   return 0;
517 }
518 int
setdj(int j)519 setdj (int j)
520 {
521   dc = j;
522   return 0;
523 }
524 int
setsi(int i)525 setsi (int i)
526 {
527   sr = i;
528   return 0;
529 }
530 int
setsj(int j)531 setsj (int j)
532 {
533   sc = j;
534   return 0;
535 }
536 
537 char *
newformula(str)538 newformula (str)
539      char *str;
540 {
541 
542 
543 
544 
545   char tok;
546   char token[32];
547   char newstr[512];
548   int letter, number;
549   int lval, nval, v;
550   int found;
551   int i, j, k, spc, newj;
552   int dollet, dolnum;
553 
554   j = 0;
555   newj = 0;
556   while (j < strlen (str))
557     {
558       found = 0;
559       dolnum = dollet = 0;
560       lval = nval = 0;
561 
562 
563       if (str[j] == '\"')
564 	{
565 	  do
566 	    {
567 	      newstr[newj] = str[j];
568 	      j++;
569 	      newj++;
570 	    }
571 	  while (str[j] != '\"' && j < strlen (str));
572 
573 	  if (str[j] == '\"')
574 	    {
575 	      newstr[newj] = str[j];
576 	      j++;
577 	      newj++;
578 	    }
579 	}
580 
581       i = j;
582       tok = str[i];
583 
584       if (tok == '$')
585 	{
586 	  dollet = 1;
587 	  i++;
588 	}
589 
590       letter = 0;
591       do
592 	{
593 	  tok = str[i];
594 	  v = isletter (tok);
595 	  if (v)
596 	    {
597 	      lval = lval * 26 + v;
598 	      letter = 1;
599 	      i++;
600 	    }
601 	  else
602 	    {
603 	      letter = 0;
604 	    }
605 	}
606       while (letter);
607 
608       if (lval > 0)
609 	{
610 
611 
612 
613 	  if (tok == '$')
614 	    {
615 	      dolnum = 1;
616 	      i++;
617 	    }
618 
619 	  do
620 	    {
621 	      tok = str[i];
622 	      v = isnumber (tok);
623 	      if (v >= 0)
624 		{
625 		  nval = nval * 10 + v;
626 		  number = 1;
627 		  i++;
628 		}
629 	      else
630 		{
631 		  number = 0;
632 		}
633 	    }
634 	  while (number);
635 
636 	  if (nval > 0)
637 	    {
638 
639 
640 
641 	      spc = 0;
642 	      while (tok == ' ')
643 		{
644 		  i++;
645 		  spc++;
646 		  tok = str[i];
647 		}
648 
649 	      if (tok != '!' && tok != '(')
650 		{
651 
652 		  found = 1;
653 		  if (!dollet && lval > sc)
654 		    lval += dc;
655 		  if (!dolnum && nval > sr)
656 		    nval += dr;
657 
658 		  if (nval < 1)
659 		    nval = 1;
660 		  if (lval < 1)
661 		    lval = 1;
662 		  if (nval > ActiveWorksheet->nblin - 1)
663 		    nval = ActiveWorksheet->nblin - 1;
664 		  if (lval > ActiveWorksheet->nbcol - 1)
665 		    nval = ActiveWorksheet->nbcol - 1;
666 
667 		  numtoalpha2 (token, nval, lval, dolnum, dollet);
668 		  for (k = 0; k < strlen (token); k++)
669 		    {
670 		      newstr[newj] = token[k];
671 		      newj++;
672 
673 		    }
674 		  for (k = 0; k < spc; k++)
675 		    {
676 		      newstr[newj] = ' ';
677 		      newj++;
678 		    }
679 		  j = i;
680 		}
681 
682 	    }
683 
684 	}
685 
686       if (!found)
687 	{
688 	  for (k = j; k <= i; k++)
689 	    {
690 	      newstr[newj] = str[k];
691 	      newj++;
692 	    }
693 	  j = i + 1;
694 	}
695     }
696   newstr[newj] = '\0';
697 
698   str = (char *) absrealloc (str, strlen (newstr) + 5, "newformula");
699   strcpy (str, newstr);
700 
701 
702   return str;
703 
704 }
705 
706 
707 int
check_if_id_is_cell(o)708 check_if_id_is_cell (o)
709      obj o;
710 {
711   int v;
712   int i;
713   char tok;
714   char *str = o.label;
715   int dollet = 0;
716   int dolnum = 0;
717   int letter, number;
718   int nval = 0;
719   int lval = 0;
720 
721 
722   i = 0;
723   tok = str[i];
724   if (tok == '$')
725     {
726       dollet = 1;
727       i++;
728     }
729   letter = 0;
730   do
731     {
732       tok = str[i];
733       v = isletter (tok);
734       if (v)
735 	{
736 	  lval = lval * 26 + v;
737 	  letter = 1;
738 	  i++;
739 	}
740       else
741 	{
742 	  letter = 0;
743 	}
744     }
745   while (letter);
746 
747   if (lval > 0 && lval <= NB_COLUMN)
748     {
749 
750 
751 
752       if (tok == '$')
753 	{
754 	  dolnum = 1;
755 	  i++;
756 	}
757 
758       do
759 	{
760 	  tok = str[i];
761 	  v = isnumber (tok);
762 	  if (v >= 0)
763 	    {
764 	      nval = nval * 10 + v;
765 	      number = 1;
766 	      i++;
767 	    }
768 	  else
769 	    {
770 	      number = 0;
771 	    }
772 	}
773       while (number);
774 
775       if (nval > 0)
776 	{
777 
778 	  if (!dolnum)
779 	    rrr = nval + dr;
780 	  else
781 	    rrr = nval;
782 	  if (!dollet)
783 	    ccc = lval + dc;
784 	  else
785 	    ccc = lval;
786 	  return 1;
787 	}
788     }
789 
790   return 0;
791 
792 }
793 
794 static int rangeopr = 0;
795 static nodeType *sheet1 = NULL;
796 static int r1 = -1;
797 static int c1 = -1;
798 static nodeType *sheet2 = NULL;
799 static int r2 = -1;
800 static int c2 = -1;
801 
802 obj
modcelltree(nodeType ** p)803 modcelltree (nodeType ** p)
804 {
805   int i, nops;
806   obj o;
807   nodeType *wks;
808   if (!*p)
809     return o;
810 
811 
812 
813   switch ((*p)->type)
814     {
815     case typeCon:
816       {
817 	return o;
818       }
819     case typeId:
820       {
821 	if (check_if_id_is_cell ((*p)->id.id))
822 	  {
823 	    obj r, c;
824 	    nodeType *argu;
825 	    c.type = r.type = INTEGER;
826 	    c.label = r.label = NULL;
827 	    r.rec.i = get_id2row ();
828 	    c.rec.i = get_id2col ();
829 	    if (rangeopr == 1)
830 	      {
831 		r1 = get_id2row ();
832 		c1 = get_id2col ();
833 		sheet1 = wksname;
834 
835 	      }
836 	    if (rangeopr == 2)
837 	      {
838 		r2 = get_id2row ();
839 		c2 = get_id2col ();
840 		sheet2 = wksname;
841 
842 	      }
843 
844 
845 
846 	    if (ActiveWorksheet != NULL && wksname == NULL)
847 	      wks = id (createidentifier (ActiveWorksheet->Name));
848 	    else
849 	      wks = wksname;
850 
851 
852 	    if (wks == NULL)
853 	      {
854 		cell1isfcell2 (ActiveCell, applicationcell (r.rec.i, c.rec.i, 1));
855 
856 		(*p)->id.id.label = "cells";
857 		(*p)->id.id.type = BUILTINFUNCTION;
858 		(*p)->id.id.rec.i = 0;
859 
860 
861 
862 
863 		argu = opr (ARG, "Arg", 1, con (r));
864 		argu = opr (ARG, "Arg", 2, argu, con (c));
865 	      }
866 	    else
867 	      {
868 		cell1isfcell2 (ActiveCell, applicationwkscell (wks->id.id.label, r.rec.i, c.rec.i, 1));
869 
870 		(*p)->id.id.label = "wkscells";
871 		(*p)->id.id.type = BUILTINFUNCTION;
872 		(*p)->id.id.rec.i = 1;
873 
874 
875 
876 
877 		argu = opr (ARG, "Arg", 1, wks);
878 		argu = opr (ARG, "Arg", 2, argu, con (r));
879 		argu = opr (ARG, "Arg", 2, argu, con (c));
880 	      }
881 
882 	    (*p) = opr (BUILTINFUNCTION, "call", 2, *p, argu);
883 
884 
885 
886 	    return o;
887 	  }
888 	return o;
889       }
890     case typeOpr1:
891       {
892 	o = modcelltree (&((*p)->opr1.op1));
893 	return o;
894       }
895     case typeOpr2:
896       {
897 	o = modcelltree (&((*p)->opr2.op1));
898 	o = modcelltree (&((*p)->opr2.op2));
899 	return o;
900       }
901     case typeOpr:
902       switch ((*p)->opr.oper.rec.i)
903 	{
904 	case '!':
905 	  {
906 	    wksname = ((*p)->opr.op[0]);
907 
908 
909 	    modcelltree (&(*p)->opr.op[1]);
910 
911 	    *p = (*p)->opr.op[1];
912 	    wksname = NULL;
913 	    return o;
914 	  }
915 	case ':':
916 	  {
917 	    int rr, cc;
918 	    obj tmp;
919 	    nodeType *argu;
920 	    nodeType *ranfct = id (o);
921 	    tmpRange *ran;
922 	    ranfct->id.id.label = "range_old";
923 	    ranfct->id.id.type = BUILTINFUNCTION;
924 	    ranfct->id.id.rec.i = 2;
925 	    rangeopr = 1;
926 	    modcelltree (&(*p)->opr.op[0]);
927 	    rangeopr = 2;
928 	    modcelltree (&(*p)->opr.op[1]);
929 	    rangeopr = 0;
930 
931 
932 	    if (r1 < 0 || r2 < 0 || c1 < 0 || c2 < 0)
933 	      return o;
934 	    if (r2 < r1)
935 	      {
936 		rr = r2;
937 		r2 = r1;
938 		r1 = rr;
939 	      }
940 	    if (c2 < c1)
941 	      {
942 		cc = c2;
943 		c2 = c1;
944 		c1 = cc;
945 	      }
946 	    for (rr = r1; rr <= r2; rr++)
947 	      for (cc = c1; cc <= c2; cc++)
948 		if (sheet1 != NULL)
949 		  cell1isfcell2 (ActiveCell, applicationwkscell (sheet1->id.id.label, rr, cc, 1));
950 		else
951 		  cell1isfcell2 (ActiveCell, applicationcell (rr, cc, 1));
952 
953 
954 	    ran = (tmpRange *) absmalloc (sizeof (tmpRange), "cell_range:tmpRange");
955 	    if (sheet1 != NULL)
956 	      ran->wks = (Worksheet *) workbook_getsheet (ActiveWorkbook, sheet1->id.id.label);
957 	    else
958 	      ran->wks = ActiveCell->worksheet;
959 	    ran->r1 = r1;
960 	    ran->c1 = c1;
961 	    ran->r2 = r2;
962 	    ran->c2 = c2;
963 	    tmp.type = RANGE;
964 	    tmp.rec.s = (char *) ran;
965 	    tmp.label = NULL;
966 	    argu = opr (ARG, "Arg", 1, con (tmp));
967 
968 
969 
970 	    (*p) = opr (BUILTINFUNCTION, "call", 2, ranfct, argu);
971 	    sheet1 = NULL;
972 	    sheet2 = NULL;
973 	    r1 = c1 = r2 = c2 = -1;
974 	    return o;
975 	  }
976 	default:
977 	  {
978 	    nops = (*p)->opr.nops;
979 	    for (i = 0; i < nops; i++)
980 	      {
981 
982 		o = modcelltree (&((*p)->opr.op[i]));
983 
984 	      }
985 	  }
986 	  return o;
987 	}
988 
989     default:
990       break;
991     }
992   return o;
993 }
994 
995 
996 int
cell_is_constant(Cell * cell)997 cell_is_constant (Cell * cell)
998 {
999   nodeType *p;
1000 
1001   if (cell == NULL)
1002     return 0;
1003   if (cell->tree == NULL)
1004     return 0;
1005   p = cell->tree;
1006   switch (p->type)
1007     {
1008     case typeCon:
1009       {
1010 	if (p->con.value.type == INTEGER)
1011 	  {
1012 	    cell->val = p->con.value;
1013 	    return 1;
1014 	  }
1015 	if (p->con.value.type == DOUBLE)
1016 	  {
1017 	    cell->val = p->con.value;
1018 	    return 1;
1019 	  }
1020       }
1021     case typeOpr1:
1022       {
1023 	if (p->opr1.op1->type == typeCon)
1024 	  {
1025 	    if (p->con.value.type == INTEGER)
1026 	      {
1027 		cell->val = p->con.value;
1028 		cell->val.rec.i = -cell->val.rec.i;
1029 		return 1;
1030 	      }
1031 	    if (p->con.value.type == DOUBLE)
1032 	      {
1033 		cell->val = p->con.value;
1034 		cell->val.rec.d = -cell->val.rec.d;
1035 		return 1;
1036 	      }
1037 	  }
1038       }
1039     default:
1040       return 0;
1041     }
1042   return 0;
1043 
1044 }
1045 
1046 
1047 int
setcelltree(tree)1048 setcelltree (tree)
1049      nodeType *tree;
1050 {
1051   modcelltree (&tree);
1052 
1053   ActiveCell->tree = tree;
1054   if (dr || dc)
1055     ActiveCell->formula = newformula (ActiveCell->formula);
1056 
1057   return 0;
1058 }
1059 
1060 int
execcelltree(cell)1061 execcelltree (cell)
1062      Cell *cell;
1063 {
1064   obj o2;
1065 
1066 
1067   o2 = exform (cell->tree);
1068 
1069 
1070 
1071   if (o2.type == IDENTIFIER)
1072     o2 = id2val (o2);
1073 
1074   if (o2.type == CELL)
1075     cell_setresval (cell, ((Cell *) o2.rec.s)->val);
1076   else
1077     cell_setresval (cell, o2);
1078   freenocstobj (o2);
1079 
1080   return 0;
1081 }
1082 
1083 
1084 
1085 static double *arraydouble = NULL;
1086 static int dimarraydouble = 0;
1087 
1088 double *
getarraydouble()1089 getarraydouble ()
1090 {
1091   return arraydouble;
1092 }
1093 int
freearraydouble()1094 freearraydouble ()
1095 {
1096   if (arraydouble != NULL)
1097     absfree (arraydouble, "freearraydouble");
1098   arraydouble = NULL;
1099   return 0;
1100 }
1101 
1102 int
sortarraydouble()1103 sortarraydouble ()
1104 {
1105   int i, k;
1106   if (arraydouble == NULL)
1107     {
1108       return -1;
1109     }
1110   for (i = 0; i < dimarraydouble; i++)
1111     {
1112       for (k = i; k < dimarraydouble; k++)
1113 	if (arraydouble[k] < arraydouble[i])
1114 	  {
1115 	    double l = arraydouble[k];
1116 	    arraydouble[k] = arraydouble[i];
1117 	    arraydouble[i] = l;
1118 	  }
1119     }
1120   return 0;
1121 }
1122 
1123 
1124 int
arg2arraydouble(int narg,obj * arg)1125 arg2arraydouble (int narg, obj * arg)
1126 {
1127   int dim = 0;
1128   int pos = 0;
1129   int i, r, c;
1130 
1131   for (i = 0; i < narg; i++)
1132     {
1133       if (arg[i].type == RANGE)
1134 	{
1135 	  tmpRange *ran = (tmpRange *) arg[i].rec.s;
1136 	  dim += (ran->r2 - ran->r1 + 1) * (ran->c2 - ran->c1 + 1);
1137 	  if (dim != 0);
1138 	  arraydouble = (double *) absrealloc (arraydouble, dim * sizeof (double), "arg2arraydouble");
1139 	  if (ran->wks == NULL)
1140 	    {
1141 	      for (r = ran->r1; r <= ran->r2; r++)
1142 		for (c = ran->c1; c <= ran->c2; c++)
1143 		  {
1144 		    arraydouble[pos] = get_value (r, c);
1145 		    pos++;
1146 		  }
1147 	    }
1148 	  else
1149 	    {
1150 	      for (r = ran->r1; r <= ran->r2; r++)
1151 		for (c = ran->c1; c <= ran->c2; c++)
1152 		  {
1153 		    arraydouble[pos] = get_value_wks (ran->wks, r, c);
1154 		    pos++;
1155 		  }
1156 	    }
1157 	}
1158       else
1159 	{
1160 	  dim++;
1161 	  arraydouble = (double *) absrealloc (arraydouble, dim * sizeof (double), "arg2arraydouble");
1162 	  arraydouble[pos] = obj2double (arg[i]);
1163 	  pos++;
1164 	}
1165     }
1166   dimarraydouble = dim;
1167   return dim;
1168 }
1169