1 /*
2 * $Id: io-utils.c,v 1.39 2001/02/13 23:38:06 danny Exp $
3 *
4 * Copyright � 1990, 1992, 1993, 2000, 2001 Free Software Foundation, Inc.
5 *
6 * This file is part of Oleo, the GNU Spreadsheet.
7 *
8 * Oleo is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
11 * any later version.
12 *
13 * Oleo is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along with
19 * Oleo; see the file COPYING. If not, write to the Free Software Foundation, 675
20 * Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 static char *rcsid = "$Id: ";
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #ifdef WITH_DMALLOC
30 #include <dmalloc.h>
31 #endif
32
33 #include <stdio.h>
34 #include <ctype.h>
35 #include "sysdef.h"
36 #include "io-utils.h"
37 #include "cell.h"
38 #include "ref.h"
39 #include "decompile.h"
40 #include "io-generic.h"
41 #include "io-abstract.h"
42 #include "lists.h"
43 #include "io-term.h"
44 #include "cmd.h"
45 #include "sylk.h"
46 #ifdef HAVE_MOTIF
47 #include "io-motif.h"
48 #endif
49 #include "basic.h"
50 #include "oleofile.h"
51 #include "sc.h"
52 #include "list.h"
53
54 #ifdef HAVE_TIME_H
55 #include <time.h>
56 #endif
57
58
59 /* Routines for formatting cell values */
60 struct user_fmt;
61 static char *pr_flt (double, struct user_fmt *, int);
62 static char *pr_int (long, struct user_fmt *, int);
63
64 /* Constants */
65 char *bname[] =
66 {
67 "#FALSE", "#TRUE"
68 };
69
70 char numb_oflo[] = "########################################";
71
72 double __plinf;
73 double __neinf;
74 double ___nan;
75
76 char nname[] = "#NOT_A_NUMBER";
77 char iname[] = "#INFINITY";
78 char mname[] = "#MINUS_INFINITY";
79
80 char *date_formats[] = {
81 "%Y/%m/%d", /* YYYY/MM/DD */
82 "%Y-%m-%d", /* YYYY-MM-DD */
83 "%d/%m/%Y", /* European style */
84 "%m/%d/%Y", /* American style */
85 "%d/%m",
86 "%Y%m",
87 "%m%Y",
88 "%B %d, %Y", /* Month, day, year */
89 "%d %B %Y", /* Day, month, year */
90 "%b %d, %Y", /* Mon, day, year */
91 "%d %b %Y", /* Day, mon, year */
92 NULL
93 };
94
95 static double
divide(a,b)96 divide (a, b)
97 double a;
98 double b;
99 {
100 return a / b;
101 }
102
103 static RETSIGTYPE
ignore_sig(sig)104 ignore_sig (sig)
105 int sig;
106 {
107 (void) signal (SIGFPE, ignore_sig);
108 }
109
110 /* It's ok of this fails and generates signals. In that case,
111 * the same signal will occur when evaluating formulas and a
112 * (less informative) error value substituted. Note that this
113 * should be called before init_eval.
114 */
115 void
init_infinity(void)116 init_infinity (void)
117 {
118 #ifdef MAXFLOAT
119 __plinf = MAXFLOAT;
120 __neinf = - MAXFLOAT;
121 #else
122 (void) signal (SIGFPE, ignore_sig);
123 __plinf = divide (1., 0.);
124 (void) signal (SIGFPE, ignore_sig);
125 __neinf = divide (-1., 0.);
126 (void) signal (SIGFPE, ignore_sig);
127 #endif
128 ___nan = __plinf + __neinf;
129 }
130
131
132
133 /* Slightly larger than the maximum exponent we ever expect to see */
134 #define BIGFLT 309
135 #ifdef TEST
136 char print_buf[1024 * 8];
137 #else
138 char print_buf[BIGFLT + 20];
139 #endif
140
141
142
143 /* Structures/vars/functions for dealing with formatting floating-point
144 numbers, etc */
145
146 struct user_fmt {
147 char *name, /* Format name */
148 *p_hdr, /* Positive header */
149 *n_hdr, /* Negative header */
150 *p_trl, /* Positive trailer */
151 *n_trl, /* Negative trailer */
152 *zero, /* How to represent a 0 */
153 *comma, /* Thousands separator */
154 *decpt; /* Decimal point */
155 unsigned char prec; /* Precision */
156 double scale; /* Scale */
157 };
158
159
160 struct user_fmt dol =
161 { "dollar", "$", "($", 0, ")", "$0", ",", ".", FLOAT_PRECISION, 1};
162
163 struct user_fmt cma =
164 { "comma", 0, "(", 0, ")", "0", ",", ".", FLOAT_PRECISION, 1};
165
166 struct user_fmt pct =
167 #if 0
168 { "percent", 0, "-", "%", "%", "0%", 0, ".", 3, 100};
169 #else
170 { "percent", 0, "-", "%", "%", "0%", 0, ".", FLOAT_PRECISION, 100};
171 #endif
172
173 struct user_fmt fxt =
174 { "fixed", 0, "-", 0, 0, "0", 0, ".", FLOAT_PRECISION, 1};
175
176 /* Variables */
177
178 #define NUM_USER_FMT (16)
179 struct user_fmt u[NUM_USER_FMT] =
180 {
181 {"user1", 0, "-", 0, 0, "0", 0, ".", FLOAT_PRECISION, 1},
182 {"user2", 0, "-", 0, 0, "0", 0, ".", FLOAT_PRECISION, 1},
183 {"user3", 0, "-", 0, 0, "0", 0, ".", FLOAT_PRECISION, 1},
184 {"user4", 0, "-", 0, 0, "0", 0, ".", FLOAT_PRECISION, 1},
185 {"user5", 0, "-", 0, 0, "0", 0, ".", FLOAT_PRECISION, 1},
186 {"user6", 0, "-", 0, 0, "0", 0, ".", FLOAT_PRECISION, 1},
187 {"user7", 0, "-", 0, 0, "0", 0, ".", FLOAT_PRECISION, 1},
188 {"user8", 0, "-", 0, 0, "0", 0, ".", FLOAT_PRECISION, 1},
189 {"user9", 0, "-", 0, 0, "0", 0, ".", FLOAT_PRECISION, 1},
190 {"user10", 0, "-", 0, 0, "0", 0, ".", FLOAT_PRECISION, 1},
191 {"user11", 0, "-", 0, 0, "0", 0, ".", FLOAT_PRECISION, 1},
192 {"user12", 0, "-", 0, 0, "0", 0, ".", FLOAT_PRECISION, 1},
193 {"user13", 0, "-", 0, 0, "0", 0, ".", FLOAT_PRECISION, 1},
194 {"user14", 0, "-", 0, 0, "0", 0, ".", FLOAT_PRECISION, 1},
195 {"user15", 0, "-", 0, 0, "0", 0, ".", FLOAT_PRECISION, 1},
196 {"user16", 0, "-", 0, 0, "0", 0, ".", FLOAT_PRECISION, 1},
197 };
198
199
200 /* Turn a floating-point number into the canonical text form. This scribbles
201 on print_buf */
202
203 char *
flt_to_str(double val)204 flt_to_str (double val)
205 {
206 double f;
207
208 if (val == __plinf)
209 return iname;
210 if (val == __neinf)
211 return mname;
212 f = fabs (val);
213 if (f >= 1e6 || (f > 0 && f <= 9.9999e-6))
214 {
215 sprintf (print_buf, "%e", val);
216 return print_buf;
217 }
218 return pr_flt (val, &fxt, FLOAT_PRECISION);
219 }
220
221 /* This is used to return a formatted float for editing.
222 * It is called as an alternative to flt_to_str, but
223 * requires the cell array instead of the value to
224 * do its work. POSSIBLY this could be merged with
225 * flt_to_str, if the cell arraw cp is available wherever
226 * flt_to_str is used. For now, though, this does the job.
227 */
228
229 char *
flt_to_str_fmt(CELL * cp)230 flt_to_str_fmt (CELL *cp)
231 {
232 int j = GET_FORMAT(cp); /* Only format, not precision */
233 int p;
234 double f;
235
236 if (j == FMT_DEF)
237 j = default_fmt;
238
239 p = GET_PRECISION(cp);
240
241 if (cp->cell_flt == __plinf)
242 return iname;
243 if (cp->cell_flt == __neinf)
244 return mname;
245 f = fabs (cp->cell_flt);
246 if (f >= 1e6 || (f > 0 && f <= 9.9999e-6))
247 {
248 sprintf (print_buf, "%e", cp->cell_flt);
249 return print_buf;
250 }
251 switch (j)
252 {
253 case FMT_FXT:
254 case FMT_DOL:
255 case FMT_PCT:
256 return pr_flt (cp->cell_flt, &fxt, p);
257 default:
258 return flt_to_str (cp->cell_flt);
259 }
260 }
261
262 char *
long_to_str(long val)263 long_to_str (long val)
264 {
265 sprintf (print_buf, "%ld", val);
266 return print_buf;
267 }
268
269 /* create the human-readable version of the contents of a cell
270 This scribbles on print-buf bigtime */
271
272 char *
print_cell(CELL * cp)273 print_cell (CELL * cp)
274 {
275 int j;
276 int p;
277 long num;
278 static char zeroes[] = "000000000000000";
279
280 if (!cp)
281 return "";
282
283 j = GET_FORMAT (cp);
284
285 p = GET_PRECISION (cp);
286 if (j == FMT_DEF) {
287 j = default_fmt;
288 p = default_prc;
289 }
290 if (j == FMT_HID || GET_TYP (cp) == 0)
291 return "";
292
293 if (GET_TYP (cp) == TYP_STR)
294 return cp->cell_str;
295
296 if (GET_TYP (cp) == TYP_BOL) {
297 #ifdef TEST
298 if (cp->cell_bol < 0 || cp->cell_bol > 1)
299 panic ("Bool %d out of range", cp->cell_bol);
300 #endif
301 return bname[cp->cell_bol];
302 }
303 if (GET_TYP (cp) == TYP_ERR) {
304 #ifdef TEST
305 if (cp->cell_err > ERR_MAX || cp->cell_err < 0)
306 panic ("Error %d out of range", cp->cell_err);
307 #endif
308 return ename[cp->cell_err];
309 }
310 if (GET_TYP (cp) == TYP_FLT) {
311 switch (j)
312 {
313 case FMT_GPH:
314 if (cp->cell_flt < 0)
315 {
316 j = '-';
317 num = -(cp->cell_flt);
318 }
319 else if (cp->cell_flt >= 1)
320 {
321 j = '+';
322 num = (cp->cell_flt);
323 }
324 else
325 {
326 j = '0';
327 num = 1;
328 }
329 graph:
330 if (num >= sizeof (print_buf))
331 {
332 io_error_msg ("Cannot graph %d '%c'", p, j);
333 num = sizeof (print_buf) - 1;
334 }
335 print_buf[num] = '\0';
336 while (--num >= 0)
337 print_buf[num] = j;
338 return print_buf;
339
340 case FMT_USR:
341 return pr_flt (cp->cell_flt, &u[p], u[p].prec);
342
343 case FMT_GEN:
344 {
345 double f;
346
347 f = fabs (cp->cell_flt);
348
349 if (f >= 1e6 || (f > 0 && f <= 9.9999e-6))
350 goto handle_exp;
351 return pr_flt (cp->cell_flt, &fxt, p);
352 }
353
354 case FMT_DOL:
355 return pr_flt (cp->cell_flt, &dol, p);
356
357 case FMT_CMA:
358 return pr_flt (cp->cell_flt, &cma, p);
359
360 case FMT_PCT:
361 return pr_flt (cp->cell_flt, &pct, p);
362
363 case FMT_FXT:
364 return pr_flt (cp->cell_flt, &fxt, p);
365
366 case FMT_EXP:
367 handle_exp:
368 if (cp->cell_flt == __plinf)
369 return iname;
370 if (cp->cell_flt == __neinf)
371 return mname;
372 if (p == FLOAT_PRECISION)
373 sprintf (print_buf, "%e", cp->cell_flt);
374 else
375 sprintf (print_buf, "%.*e", p, cp->cell_flt);
376 return print_buf;
377 #ifdef TEST
378 default:
379 panic ("Unknown format %d", j);
380 return 0;
381 #endif
382 }
383 }
384
385 if (GET_TYP (cp) == TYP_INT) {
386 p = GET_PRECISION (cp);
387 switch (j)
388 {
389 case FMT_GPH:
390 if (cp->cell_int < 0)
391 {
392 j = '-';
393 num = -(cp->cell_int);
394 }
395 else if (cp->cell_int >= 1)
396 {
397 j = '+';
398 num = (cp->cell_int);
399 }
400 else
401 {
402 j = '0';
403 num = 1;
404 }
405 goto graph;
406
407 #ifdef FMT_DATE /* Still depends on new style cell_flags */
408 case FMT_DATE:
409 {
410 time_t t = cp->cell_int;
411 int f = GET_PRECISION(cp); /* Determines date format */
412 struct tm *tmp = localtime(&t);
413
414 #ifdef HAVE_STRFTIME
415 (void)strftime(print_buf, sizeof(print_buf),
416 date_formats[f], tmp);
417 #else
418 sprintf(print_buf,
419 "%04d/%02d/%02d",
420 tmp->tm_year + 1900,
421 tmp->tm_mon + 1,
422 tmp->tm_mday);
423 #endif
424 return print_buf;
425 }
426 #endif
427
428 case FMT_USR:
429 return pr_int (cp->cell_int, &u[p], u[p].prec);
430
431 case FMT_GEN:
432 sprintf (print_buf, "%ld", cp->cell_int);
433 return print_buf;
434
435 case FMT_DOL:
436 return pr_int (cp->cell_int, &dol, p);
437
438 case FMT_CMA:
439 return pr_int (cp->cell_int, &cma, p);
440
441 case FMT_PCT:
442 return pr_int (cp->cell_int, &pct, p);
443
444 case FMT_FXT:
445 if (p != FLOAT_PRECISION && p != 0)
446 sprintf (print_buf, "%ld.%.*s", cp->cell_int, p, zeroes);
447 else
448 sprintf (print_buf, "%ld", cp->cell_int);
449 return print_buf;
450
451 case FMT_EXP:
452 if (p != FLOAT_PRECISION)
453 sprintf (print_buf, "%.*e", p, (double) (cp->cell_int));
454 else
455 sprintf (print_buf, "%e", (double) (cp->cell_int));
456 return print_buf;
457 #ifdef TEST
458 default:
459 panic ("Unknown format %d", j);
460 return 0;
461 #endif
462 }
463 }
464 #ifdef TEST
465 panic ("Unknown cell type %d", GET_TYP (cp));
466 #endif
467 return 0;
468 }
469
470 /* Return the value of ROW,COL in a human-readable fashion
471 * In particular, strings are \\ed, and if add_quote is true,
472 * they will have "" around them.
473 */
474 char *
cell_value_string(CELLREF row,CELLREF col,int add_quote)475 cell_value_string (CELLREF row, CELLREF col, int add_quote)
476 {
477 CELL *cp;
478
479 cp = find_cell (row, col);
480 if (!cp || !GET_TYP (cp))
481 return "";
482 switch (GET_TYP (cp))
483 {
484 case TYP_FLT:
485 return flt_to_str (cp->cell_flt);
486
487 case TYP_INT:
488 sprintf (print_buf, "%ld", cp->cell_int);
489 return print_buf;
490
491 case TYP_STR:
492 return backslash_a_string (cp->cell_str, add_quote);
493
494 case TYP_BOL:
495 return bname[cp->cell_bol];
496
497 case TYP_ERR:
498 return ename[cp->cell_err];
499 #ifdef TEST
500 default:
501 panic ("unknown type %d in cell_value_string", GET_TYP (cp));
502 #endif
503 }
504 return 0;
505 }
506
507 static char *
pr_int(val,fmt,prec)508 pr_int (val, fmt, prec)
509 long val;
510 struct user_fmt *fmt;
511 int prec;
512 {
513 char *pf, *pff, *pt;
514 long int n;
515 int nn = 0;
516
517 pt = &print_buf[sizeof (print_buf) - 1];
518 *pt = '\0';
519
520 n = fmt->scale * ((val < 0) ? -val : val);
521 if (n == 0)
522 return fmt->zero ? fmt->zero : "";
523
524 pf = pff = (val < 0) ? fmt->n_trl : fmt->p_trl;
525 if (pf && *pf)
526 {
527 while (*pf)
528 pf++;
529 do
530 *--pt = *--pf;
531 while (pf != pff);
532 }
533
534 if (prec != FLOAT_PRECISION && prec != 0)
535 {
536 while (prec-- > 0)
537 *--pt = '0';
538 pf = pff = fmt->decpt;
539 if (pf)
540 {
541 while (*pf)
542 pf++;
543 do
544 *--pt = *--pf;
545 while (pf != pff);
546 }
547 /* *--pt='.'; */
548 }
549 do
550 {
551 *--pt = (n % 10) + '0';
552 n /= 10;
553 if (nn++ == 2 && n > 0)
554 {
555 if (fmt->comma && *(fmt->comma))
556 {
557 for (pf = pff = fmt->comma; *pf; pf++)
558 ;
559 do
560 *--pt = *--pf;
561 while (pf != pff);
562 }
563 nn = 0;
564 }
565 }
566 while (n > 0);
567
568 pf = pff = (val < 0) ? fmt->n_hdr : fmt->p_hdr;
569 if (pf && *pf)
570 {
571 while (*pf)
572 pf++;
573 do
574 *--pt = *--pf;
575 while (pf != pff);
576 }
577 return pt;
578 }
579
580 static char *
pr_flt(val,fmt,prec)581 pr_flt (val, fmt, prec)
582 double val;
583 struct user_fmt *fmt;
584 int prec;
585 {
586 char *iptr;
587 char *fptr;
588 char *pptr;
589 char *pf, *pff;
590 double fract, integer, tmpval;
591 int n;
592 int isneg;
593 int comlen;
594
595 val *= fmt->scale;
596
597 if (val == __plinf)
598 return iname;
599 if (val == __neinf)
600 return mname;
601 if (val != val)
602 return nname;
603
604 iptr = &print_buf[BIGFLT];
605 fptr = &print_buf[BIGFLT];
606
607
608 if (val == 0)
609 return fmt->zero ? fmt->zero : "";
610
611 if (val < 0)
612 {
613 isneg = 1;
614 val = -val;
615 }
616 else
617 isneg = 0;
618
619 comlen = 0;
620 if (fmt->comma && *(fmt->comma))
621 for (pf = fmt->comma; *pf; comlen++, pf++)
622 ;
623
624 fract = modf (val, &integer);
625 n = 0;
626 do
627 {
628 if (iptr < &print_buf[comlen])
629 return numb_oflo;
630 tmpval = modf (integer / 10, &integer);
631 *--iptr = '0' + (int) ((tmpval + .01) * 10);
632 if (comlen && n++ == 2 && integer)
633 {
634 n = 0;
635 pff = fmt->comma;
636 pf = pff + comlen;
637 do
638 *--iptr = *--pf;
639 while (pf != pff);
640 }
641 }
642 while (integer);
643
644 if (prec)
645 {
646 int p1;
647
648 p1 = (prec == FLOAT_PRECISION) ? 15 : (prec > 0) ? prec : -prec;
649 pf = fmt->decpt;
650 while (pf && *pf)
651 *fptr++ = *pf++;
652 /* *fptr++='.'; */
653 if (fract)
654 {
655 do
656 {
657 fract = modf (fract * 10, &tmpval);
658 *fptr++ = '0' + (int) tmpval;
659 }
660 while (--p1 && fract);
661 }
662 if (prec > 0 && prec != FLOAT_PRECISION)
663 while (p1--)
664 *fptr++ = '0';
665 else
666 {
667 fract = 0;
668 while (fptr[-1] == '0')
669 --fptr;
670 while (!isdigit (fptr[-1]))
671 --fptr;
672 *fptr = '\0';
673 }
674 }
675 if (fract)
676 {
677 (void) modf (fract * 10, &tmpval);
678 if (tmpval > 4)
679 {
680 iptr[-1] = '0';
681 for (pptr = fptr - 1;; --pptr)
682 {
683 if (!isdigit (*pptr))
684 continue;
685 else if (*pptr == '9')
686 {
687 if (pptr == fptr - 1 && pptr > &print_buf[BIGFLT] && (prec < 0 || prec == FLOAT_PRECISION))
688 {
689 --fptr;
690 while (!isdigit (pptr[-1]))
691 {
692 --fptr;
693 --pptr;
694 }
695 *pptr = '\0';
696 }
697 else
698 *pptr = '0';
699 }
700 else
701 {
702 (*pptr)++;
703 break;
704 }
705 }
706 if (pptr < iptr)
707 {
708 --iptr;
709 if (n == 3)
710 {
711 char tmpch;
712
713 tmpch = *iptr++;
714 for (pf = pff = fmt->comma; *pf; pf++)
715 ;
716 do
717 *--iptr = *--pf;
718 while (pf != pff);
719 *--iptr = tmpch;
720 }
721 }
722 }
723 }
724 pf = pff = (isneg) ? fmt->n_hdr : fmt->p_hdr;
725 if (pf && *pf)
726 {
727 while (*pf)
728 pf++;
729 do
730 *--iptr = *--pf;
731 while (pf != pff);
732 }
733
734 pf = (isneg) ? fmt->n_trl : fmt->p_trl;
735 while (pf && *pf)
736 *fptr++ = *pf++;
737 *fptr = 0;
738 return iptr;
739 }
740
741 char *
adjust_prc(char * oldp,CELL * cp,int width,int smallwid,int just)742 adjust_prc (char *oldp, CELL * cp, int width, int smallwid, int just)
743 {
744 int fmt;
745 int prc;
746 struct user_fmt *ufmt;
747 char *bptr;
748 char *eptr;
749 int len;
750
751 fmt = GET_FORMAT (cp);
752 if (fmt == FMT_DEF)
753 fmt = default_fmt;
754 prc = GET_PRECISION (cp);
755 switch (fmt)
756 {
757 case FMT_GPH:
758 case FMT_HID:
759 return numb_oflo;
760 case FMT_DOL:
761 ufmt = &dol;
762 goto deal_fmt;
763
764 case FMT_CMA:
765 ufmt = &cma;
766 goto deal_fmt;
767
768 case FMT_PCT:
769 ufmt = &cma;
770 goto deal_fmt;
771
772 case FMT_FXT:
773 ufmt = &fxt;
774 goto deal_fmt;
775
776 case FMT_USR:
777 ufmt = &u[prc];
778 prc = ufmt->prec;
779 goto deal_fmt;
780
781 case FMT_GEN:
782 if (prc != FLOAT_PRECISION)
783 return numb_oflo;
784 if (index (oldp, 'e') || !index (oldp, '.'))
785 goto handle_exp;
786
787 ufmt = &fxt;
788 prc = FLOAT_PRECISION;
789 goto deal_fmt;
790
791 deal_fmt:
792 if (prc != FLOAT_PRECISION)
793 return numb_oflo;
794 len = strlen (oldp);
795 bptr = (char *) strstr (oldp, ufmt->decpt);
796 if (!bptr)
797 return numb_oflo;
798 while ((eptr = (char *) strstr (bptr + 1, ufmt->decpt)))
799 bptr = eptr;
800
801 if (width < bptr - oldp)
802 return numb_oflo;
803 if (bptr - oldp + strlen (ufmt->decpt) >= width)
804 prc = 0;
805 else
806 {
807 prc = width - (strlen (ufmt->decpt) + bptr - oldp);
808 }
809 bptr = pr_flt (cp->cell_flt, ufmt, -prc);
810 len = strlen (bptr);
811 if (len > width && prc > 0)
812 {
813 bptr = pr_flt (cp->cell_flt, ufmt, -(prc - 1));
814 len = strlen (bptr);
815 }
816 if (len > width)
817 return numb_oflo;
818 break;
819
820 case FMT_EXP:
821 handle_exp:
822 {
823 double f;
824
825 f = fabs (cp->cell_flt);
826 if (f > 9.99999e99 || f < 1e-99)
827 len = width - 7;
828 else /* if(f>9.9999999e9 || f<1e-9) */
829 len = width - 6;
830 /* else
831 len=width-5; */
832 if (cp->cell_flt < 0)
833 --len;
834 if (len > 0)
835 {
836 sprintf (oldp, "%.*e", len, cp->cell_flt);
837 len = strlen (oldp);
838 if (len <= width)
839 {
840 bptr = oldp;
841 break;
842 }
843 }
844 }
845 return numb_oflo;
846 default:
847 bptr = 0;
848 len = 0;
849 #ifdef TEST
850 panic ("Unknown format %d in adjust_prc()", fmt);
851 #endif
852 break;
853 }
854
855 /* If we get here, bptr points to a a string of len characters
856 (len<=width) that we want to output */
857 if (len < smallwid)
858 {
859 if (just == JST_RGT || just == JST_CNT)
860 {
861 int n;
862
863 n = (just == JST_RGT) ? smallwid - len : (1 + smallwid - len) / 2;
864 for (;;)
865 {
866 bptr[len + n] = bptr[len];
867 if (len-- == 0)
868 break;
869 }
870 while (n-- >= 0)
871 bptr[n] = ' ';
872 }
873 }
874 return bptr;
875 }
876
877
878 void
set_usr_stats(int usr_n,char ** usr_buf)879 set_usr_stats (int usr_n, char **usr_buf)
880 {
881 int len;
882 int i;
883 char *p_in, *p_out;
884
885 len = 0;
886 for (i = 0; i < 7; i++)
887 len += strlen (usr_buf[i]);
888 u[usr_n].p_hdr = ck_malloc (len + 7);
889 p_out = u[usr_n].p_hdr;
890 if (usr_buf[0][0])
891 {
892 p_in = usr_buf[0];
893 while ((*p_out++ = *p_in++))
894 ;
895 }
896 else
897 *p_out++ = '\0';
898
899 if (usr_buf[1][0])
900 {
901 p_in = usr_buf[1];
902 u[usr_n].n_hdr = p_out;
903 while ((*p_out++ = *p_in++))
904 ;
905 }
906 else
907 u[usr_n].n_hdr = 0;
908
909 if (usr_buf[2][0])
910 {
911 p_in = usr_buf[2];
912 u[usr_n].p_trl = p_out;
913 while ((*p_out++ = *p_in++))
914 ;
915 }
916 else
917 u[usr_n].p_trl = 0;
918
919 if (usr_buf[3][0])
920 {
921 p_in = usr_buf[3];
922 u[usr_n].n_trl = p_out;
923 while ((*p_out++ = *p_in++))
924 ;
925 }
926 else
927 u[usr_n].n_trl = 0;
928
929 if (usr_buf[4][0])
930 {
931 p_in = usr_buf[4];
932 u[usr_n].zero = p_out;
933 while ((*p_out++ = *p_in++))
934 ;
935 }
936 else
937 u[usr_n].zero = 0;
938
939 if (usr_buf[5][0])
940 {
941 p_in = usr_buf[5];
942 u[usr_n].comma = p_out;
943 while ((*p_out++ = *p_in++))
944 ;
945 }
946 else
947 u[usr_n].comma = 0;
948
949 if (usr_buf[6][0])
950 {
951 p_in = usr_buf[6];
952 u[usr_n].decpt = p_out;
953 while ((*p_out++ = *p_in++))
954 ;
955 }
956 else
957 u[usr_n].decpt = 0;
958
959 if (!stricmp (usr_buf[7], "float") || !stricmp (usr_buf[7], "f"))
960 u[usr_n].prec = 15;
961 else
962 u[usr_n].prec = astol (&usr_buf[7]);
963
964 u[usr_n].scale = astof (&usr_buf[8]);
965 }
966
967 int
usr_set_fmts(void)968 usr_set_fmts (void)
969 {
970 int n;
971 int ret = 0;
972
973 for (n = 0; n < NUM_USER_FMT; n++)
974 if (u[n].p_hdr)
975 ret |= 1 << n;
976 return ret;
977 }
978
979 void
get_usr_stats(int usr_num,char ** usr_buf)980 get_usr_stats (int usr_num, char **usr_buf)
981 {
982 static char buf1[30];
983 static char buf2[30];
984 static char NullStr[] = "";
985
986 usr_buf[0] = u[usr_num].p_hdr ? u[usr_num].p_hdr : NullStr;
987 usr_buf[1] = u[usr_num].n_hdr ? u[usr_num].n_hdr : NullStr;
988 usr_buf[2] = u[usr_num].p_trl ? u[usr_num].p_trl : NullStr;
989 usr_buf[3] = u[usr_num].n_trl ? u[usr_num].n_trl : NullStr;
990 usr_buf[4] = u[usr_num].zero ? u[usr_num].zero : NullStr;
991 usr_buf[5] = u[usr_num].comma ? u[usr_num].comma : NullStr;
992 usr_buf[6] = u[usr_num].decpt ? u[usr_num].decpt : NullStr;
993 if (u[usr_num].prec == 15)
994 usr_buf[7] = "float";
995 else
996 {
997 sprintf (buf1, "%u", u[usr_num].prec);
998 usr_buf[7] = buf1;
999 }
1000 sprintf (buf2, "%.12g", u[usr_num].scale);
1001 usr_buf[8] = buf2;
1002 }
1003
1004 /* Functions for printing out the names of cells and ranges */
1005
1006 char *
cell_name(CELLREF rr,CELLREF cc)1007 cell_name (CELLREF rr, CELLREF cc)
1008 {
1009 static char strs[2][20];
1010 static int num = 0;
1011 char *ptr;
1012
1013 num = num ? 0 : 1;
1014
1015 if (Global->a0)
1016 {
1017 ptr = &strs[num][9];
1018 sprintf (ptr, "%u", rr);
1019 if (cc < MIN_COL + 26)
1020 *--ptr = 'A' - MIN_COL + cc;
1021 #if MAX_COL>702
1022 else if (cc < MIN_COL + 702)
1023 {
1024 cc -= MIN_COL + 26;
1025 *--ptr = 'A' + cc % 26;
1026 *--ptr = 'A' + cc / 26;
1027 }
1028 else if (cc < MIN_COL + 18278)
1029 {
1030 cc -= MIN_COL + 702;
1031 *--ptr = 'A' + cc % 26;
1032 cc /= 26;
1033 *--ptr = 'A' + cc % 26;
1034 *--ptr = 'A' + cc / 26;
1035 }
1036 else
1037 {
1038 cc -= MIN_COL + 18278;
1039 *--ptr = 'A' + cc % 26;
1040 cc /= 26;
1041 *--ptr = 'A' + cc % 26;
1042 cc /= 26;
1043 *--ptr = 'A' + cc % 26;
1044 *--ptr = 'A' + cc / 26;
1045 }
1046 #else
1047 else
1048 {
1049 cc -= MIN_COL + 26;
1050 *--ptr = 'A' + cc % 26;
1051 *--ptr = 'A' + cc / 26;
1052 }
1053 #endif
1054 }
1055 else
1056 {
1057 ptr = &strs[num][0];
1058 sprintf (ptr, "r%uc%u", rr, cc);
1059 }
1060 return ptr;
1061 }
1062
1063 char *
range_name(struct rng * rng)1064 range_name (struct rng *rng)
1065 {
1066 CELLREF lr, lc, hr, hc;
1067 static char buf[2][40];
1068 static int num;
1069 char *ptr;
1070
1071 ptr = &buf[num][0];
1072 num = num ? 0 : 1;
1073
1074 lr = rng->lr;
1075 lc = rng->lc;
1076 hr = rng->hr;
1077 hc = rng->hc;
1078
1079 /* Return empty string when invalid */
1080 if (lr == 0 || lc == 0 || hc == 0 || hr == 0 ||
1081 lr >= MAX_ROW || lc >= MAX_COL || hc >= MAX_COL || hr >= MAX_ROW) {
1082 ptr[0] = '\0';
1083 return ptr;
1084 }
1085
1086 if ((lr == hr) && (lc == hc)) {
1087 sprintf (ptr, "%s", cell_name (lr, lc));
1088 } else {
1089 if (Global->a0)
1090 sprintf (ptr, "%s:%s", cell_name (lr, lc), cell_name (hr, hc));
1091 else {
1092 if (lr == hr && lc != hc)
1093 sprintf (ptr, "r%uc%u:%u", lr, lc, hc);
1094 else if (lr != hr && lc == hc)
1095 sprintf (ptr, "r%u:%uc%u", lr, hr, lc);
1096 else
1097 sprintf (ptr, "r%u:%uc%u:%u", lr, hr, lc, hc);
1098 }
1099 }
1100 return ptr;
1101 }
1102
1103
1104 /* Parse a range, allowing variable names.
1105 * Return 1 on failure, 0 on succes.
1106 */
1107 int
get_abs_rng(char ** pptr,struct rng * retp)1108 get_abs_rng (char **pptr, struct rng *retp)
1109 {
1110 unsigned char n;
1111 struct rng ignored;
1112
1113 if (!retp)
1114 retp = &ignored;
1115
1116 while (**pptr == ' ')
1117 (*pptr)++;
1118 if (!**pptr)
1119 return 1;
1120 cur_row = curow;
1121 cur_col = cucol;
1122 n = parse_cell_or_range (pptr, retp);
1123 if (!n)
1124 {
1125 struct var *v;
1126 char *ptr;
1127
1128 ptr = *pptr;
1129 while (ptr[n] && ptr[n] != ' ')
1130 n++;
1131 v = find_var (ptr, n);
1132 if (!v)
1133 return 1;
1134 (*pptr) += n;
1135 *retp = v->v_rng;
1136 }
1137 return 0;
1138 }
1139
1140
1141 char *
col_to_str(CELLREF col)1142 col_to_str (CELLREF col)
1143 {
1144 static char strs[2][10];
1145 static int num;
1146 char *ptr;
1147
1148 ptr = &strs[num][9];
1149 num = num ? 0 : 1;
1150
1151 if (col < MIN_COL + 26)
1152 *--ptr = 'A' - MIN_COL + col;
1153 #if MAX_COL>702
1154 else if (col < MIN_COL + 702)
1155 {
1156 col -= MIN_COL + 26;
1157 *--ptr = 'A' + col % 26;
1158 *--ptr = 'A' + col / 26;
1159 }
1160 else if (col < MIN_COL + 18278)
1161 {
1162 col -= MIN_COL + 702;
1163 *--ptr = 'A' + col % 26;
1164 col /= 26;
1165 *--ptr = 'A' + col % 26;
1166 *--ptr = 'A' + col / 26;
1167 }
1168 else
1169 {
1170 col -= MIN_COL + 18278;
1171 *--ptr = 'A' + col % 26;
1172 col /= 26;
1173 *--ptr = 'A' + col % 26;
1174 col /= 26;
1175 *--ptr = 'A' + col % 26;
1176 *--ptr = 'A' + col / 26;
1177 }
1178 #else
1179 else
1180 {
1181 col -= MIN_COL + 26;
1182 *--ptr = 'A' + col % 26;
1183 *--ptr = 'A' + col / 26;
1184 }
1185 #endif
1186 return ptr;
1187 }
1188
1189 void
clear_spreadsheet(void)1190 clear_spreadsheet (void)
1191 {
1192 int n;
1193
1194 flush_everything ();
1195 /* flush_widths(); */
1196 flush_all_timers ();
1197 for (n = 0; n < NUM_USER_FMT; n++)
1198 {
1199 if (u[n].p_hdr)
1200 {
1201 free (u[n].p_hdr);
1202 u[n].p_hdr = 0;
1203 u[n].prec = FLOAT_PRECISION;
1204 u[n].scale = 1;
1205 }
1206 }
1207 default_width = saved_default_width;
1208 default_height = saved_default_height;
1209 default_jst = JST_LFT;
1210 default_fmt = FMT_GEN;
1211 default_lock = LCK_UNL;
1212 }
1213
1214 char *ename[] =
1215 {
1216 "#WHAT?",
1217 "#ERROR", "#BAD_INPUT", "#NON_NUMBER", "#NON_STRING",
1218 "#NON_BOOL", "#NON_RANGE", "#OUT_OF_RANGE", "#NO_VALUES",
1219 "#DIV_BY_ZERO", "#BAD_NAME", "#NOT_AVAIL", "#PARSE_ERROR",
1220 "#NEED_OPEN", "#NEED_CLOSE", "#NEED_QUOTE", "#UNK_CHAR",
1221 "#UNK_FUNC",
1222 0
1223 };
1224
1225 char tname[] = "#TRUE";
1226 char fname[] = "#FALSE";
1227
1228
1229 int
words_imatch(char ** ptr,char * key)1230 words_imatch (char **ptr, char *key)
1231 {
1232 char *str = *ptr;
1233
1234 while (isspace (*str))
1235 ++str;
1236 while (isspace (*key))
1237 ++key;
1238
1239 while (1)
1240 {
1241 while (*str && *key && (toupper (*str) == toupper (*key)))
1242 {
1243 ++str;
1244 ++key;
1245 }
1246 /* If we're not at word breaks in both strings... */
1247 if (!((!*str || isspace (*str)) && (!*key || isspace (*key))))
1248 return 0;
1249 else
1250 {
1251 while (isspace (*key))
1252 ++key;
1253 while (isspace (*str))
1254 ++str;
1255 if (!*key)
1256 {
1257 *ptr = str;
1258 return 1;
1259 }
1260 }
1261 }
1262 }
1263
1264 int
parray_len(char ** array)1265 parray_len (char **array)
1266 {
1267 int x;
1268 for (x = 0; array[x]; ++x);
1269 return x;
1270 }
1271
1272
1273 /* Return the index of CHECK in KEYS or -1. Case and whitespeace insenstive.
1274 */
1275
1276 int
words_member(char ** keys,int len,char * check)1277 words_member (char **keys, int len, char *check)
1278 {
1279 int x;
1280 for (x = 0; x < len; ++x)
1281 {
1282 char *ch = check;
1283 if (words_imatch (&ch, keys[x]))
1284 if (!*ch)
1285 return x;
1286 }
1287 return -1;
1288 }
1289
1290 int
prompt_len(char * prompt)1291 prompt_len (char *prompt)
1292 {
1293 char *pos;
1294 if (!prompt)
1295 return 0;
1296 for (pos = prompt; *pos && (*pos != '\n'); ++pos)
1297 ;
1298 return pos - prompt;
1299 }
1300
1301
1302 int
says_default(char * str)1303 says_default (char *str)
1304 {
1305 char *key = "ault";
1306 if (strincmp (str, "def", 3))
1307 return 0;
1308 str += 3;
1309 while (*str && *key)
1310 {
1311 int c = isupper (*str) ? tolower (*str) : *str;
1312 if (c != *key)
1313 return 0;
1314 ++key;
1315 ++str;
1316 }
1317 while (isspace (*str))
1318 ++str;
1319 return !*str;
1320 }
1321
1322 static char *defaultformat = NULL;
1323
1324 void
file_set_default_format(char * s)1325 file_set_default_format(char *s)
1326 {
1327 if (defaultformat)
1328 free(defaultformat);
1329
1330 if (s == NULL)
1331 defaultformat = strdup("oleo");
1332 else
1333 defaultformat = s;
1334 }
1335
1336 char *
file_get_default_format(void)1337 file_get_default_format(void)
1338 {
1339 return defaultformat;
1340 }
1341
1342 int
write_file_generic_2(FILE * fp,struct rng * rng,char * format)1343 write_file_generic_2(FILE *fp, struct rng *rng, char *format)
1344 {
1345 if (!stricmp ("oleo", format)) {
1346 oleo_write_file(fp, rng);
1347 } else if (!stricmp ("sylk", format)) {
1348 Global->sylk_a0 = 1;
1349 sylk_write_file(fp, rng);
1350 } else if (!stricmp ("sylk-noa0", format)) {
1351 Global->sylk_a0 = 0;
1352 sylk_write_file(fp, rng);
1353 } else if (!stricmp ("sc", format)) {
1354 sc_write_file(fp, rng);
1355 #ifdef HAVE_PANIC_SAVE
1356 } else if (!stricmp ("panic", format)) {
1357 panic_write_file(fp, rng);
1358 #endif
1359 } else if (!stricmp ("list", format)) {
1360 list_write_file(fp, rng);
1361 } else {
1362 return -1;
1363 }
1364
1365 return 0;
1366 }
1367
1368 void
write_file_generic(FILE * fp,struct rng * rng,char * format)1369 write_file_generic(FILE *fp, struct rng *rng, char *format)
1370 {
1371 if (format == NULL) {
1372 if (defaultformat)
1373 (void) write_file_generic_2(fp, rng, defaultformat);
1374 else
1375 oleo_write_file(fp, rng);
1376
1377 return;
1378 }
1379 #if 0
1380 fprintf(stderr, PACKAGE " write_file_generic : format %s\n", format);
1381 #endif
1382 if (write_file_generic_2(fp, rng, format) != 0) {
1383 if (write_file_generic_2(fp, rng, defaultformat) != 0)
1384 oleo_write_file(fp, rng);
1385 }
1386 }
1387
1388 int
read_file_generic_2(FILE * fp,int ismerge,char * format,char * name)1389 read_file_generic_2(FILE *fp, int ismerge, char *format, char *name)
1390 {
1391 if (stricmp ("oleo", format) == 0) {
1392 oleo_read_file(fp, ismerge);
1393 } else if (stricmp ("sylk", format) == 0 || stricmp ("slk", format) == 0) {
1394 Global->sylk_a0 = 0; /* FIX ME */
1395 sylk_read_file(fp, ismerge);
1396 } else if (stricmp ("sylk-noa0", format) == 0) {
1397 Global->sylk_a0 = 0;
1398 sylk_read_file(fp, ismerge);
1399 } else if (stricmp ("sc", format) == 0) {
1400 sc_read_file(fp, ismerge);
1401 #ifdef HAVE_PANIC_SAVE
1402 } else if (stricmp ("panic", format) == 0) {
1403 panic_read_file(fp, ismerge);
1404 #endif
1405 } else if (stricmp ("list", format) == 0) {
1406 list_read_file(fp, ismerge);
1407 } else if (stricmp("csv", format) == 0) {
1408 list_set_separator(',');
1409 list_read_file(fp, ismerge);
1410 } else if (stricmp("dbf", format) == 0) {
1411 #if defined(HAVE_LIBXBASE) || defined(HAVE_LIBXDB)
1412 ReadXbaseFile(name, ismerge);
1413 #else
1414 io_error_msg ("Cannot read XBASE file (xbase not compiled into " PACKAGE ")");
1415 return -1;
1416 #endif
1417 } else {
1418 return -1;
1419 }
1420 return 0;
1421 }
1422
1423 static struct file_formats_s {
1424 char *name;
1425 char *format;
1426 } file_formats[] = {
1427 { "oleo", "oleo" },
1428 { "sylk", "[sS]*[lL][kK]" },
1429 { "sc", "sc" },
1430 { "list", "list" },
1431 { "csv", "[cC][sS][vV]" },
1432 { "dbf", "[dD][bB][fF]" },
1433 #ifdef HAVE_PANIC_SAVE
1434 { "panic", "panic" },
1435 #endif
1436 { "sylk-noa0", "sylk" },
1437 { NULL, NULL }
1438 };
1439
1440 char *
file_get_format(int i)1441 file_get_format(int i)
1442 {
1443 int m = sizeof(file_formats) / sizeof(struct file_formats_s) - 1;
1444
1445 if (i > m || i <= 0)
1446 return NULL;
1447
1448 return file_formats[i-1].name;
1449 }
1450
1451 char *
file_get_pattern(char * fmt)1452 file_get_pattern(char *fmt)
1453 {
1454 int i, m = sizeof(file_formats) / sizeof(struct file_formats_s) - 1;
1455
1456 for (i=0; i<m; i++) {
1457 if (strcmp(fmt, file_formats[i].name) == 0)
1458 return file_formats[i].format;
1459 }
1460 return NULL;
1461 }
1462
1463 void
read_file_generic(FILE * fp,int ismerge,char * format,char * name)1464 read_file_generic(FILE *fp, int ismerge, char *format, char *name)
1465 {
1466 if (format == NULL) {
1467 if (defaultformat)
1468 (void) read_file_generic_2(fp, ismerge, defaultformat, name);
1469 else
1470 oleo_read_file(fp, ismerge);
1471
1472 return;
1473 }
1474 #if 0
1475 fprintf(stderr, PACKAGE " read_file_generic : format %s\n", format);
1476 #endif
1477 if (read_file_generic_2(fp, ismerge, format, name) != 0) {
1478 if (defaultformat && read_file_generic_2(fp, ismerge, defaultformat, name) != 0)
1479 oleo_read_file(fp, ismerge);
1480 }
1481
1482 recalculate(1);
1483 }
1484
1485 void
fmt_set_format()1486 fmt_set_format()
1487 {
1488 }
1489
1490 void
fmt_get_format()1491 fmt_get_format()
1492 {
1493 }
1494
FileSetCurrentFileName(const char * s)1495 void FileSetCurrentFileName(const char *s)
1496 {
1497 if (Global->FileName)
1498 free(Global->FileName);
1499 Global->FileName = NULL;
1500 if (s)
1501 Global->FileName = strdup(s);
1502
1503 #if HAVE_MOTIF
1504 if (using_motif)
1505 MotifSetWindowName(Global->FileName);
1506 #endif
1507 }
1508
FileGetCurrentFileName(void)1509 char *FileGetCurrentFileName(void)
1510 {
1511 return Global->FileName;
1512 }
1513
FileCloseCurrentFile(void)1514 void FileCloseCurrentFile(void)
1515 {
1516 if (Global->FileName)
1517 free(Global->FileName);
1518 Global->FileName = NULL;
1519
1520 #if HAVE_MOTIF
1521 if (using_motif)
1522 MotifSetWindowName("");
1523 #endif
1524 }
1525
OleoSetEncoding(char * s)1526 void OleoSetEncoding(char *s)
1527 {
1528 extern void PrintSetEncoding(char *encoding); /* in print.c */
1529
1530 if (Global && Global->encoding)
1531 free(Global->encoding);
1532 Global->encoding = strdup(s);
1533
1534 PrintSetEncoding(s);
1535 }
1536
OleoGetEncoding(void)1537 char *OleoGetEncoding(void)
1538 {
1539 return Global->encoding;
1540 }
1541
OleoUserPrefEncoding(char * s)1542 void OleoUserPrefEncoding(char *s)
1543 {
1544 char *p = s + 9; /* Get past "encoding" */
1545
1546 for (; *p && isspace(*p); p++) ;
1547 OleoSetEncoding(p);
1548 }
1549