home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (C) 1990 Free Software Foundation, Inc.
-
- This file is part of Oleo, the GNU Spreadsheet.
-
- Oleo is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 1, or (at your option)
- any later version.
-
- Oleo is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Oleo; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- #include "funcdef.h"
-
- #include <stdio.h>
- #include <ctype.h>
-
- #include "sysdef.h"
-
- #include "global.h"
- #include "cell.h"
-
- extern VOIDSTAR ck_malloc EXT1(size_t);
- extern VOIDSTAR ck_realloc EXT2(void *,size_t);
- extern double astof EXT1(char **);
- extern long astol EXT1(char **);
-
- extern unsigned short default_width;
-
- extern CELLREF curow,cucol;
-
- extern struct rng screen;
-
- extern int default_fmt;
- extern char numb_oflo[];
-
- #ifdef TEST
-
- extern void panic EXT1N(const char *);
- #endif
-
- char *bname[] = {
- "#FALSE","#TRUE"
- };
-
- #ifndef ASM_INF
- #ifdef __GNUC__
- __asm(".globl ___plinf");
- __asm("___plinf: .double 0rinf");
- __asm(".globl ___neinf");
- __asm("___neinf: .double 0r-inf");
- __asm(".globl ___nan");
- __asm("___nan: .double 0rnan");
- #else
- double __plinf = 1e500;
- double __neinf = -1e500;
- double __nan = 1e500/ -1e500;
- #endif
- #endif
-
- const char nname[] = "#NOT_A_NUMBER";
- const char iname[] = "#INFINITY";
- const char mname[] = "#MINUS_INFINITY";
-
-
- /* Slightly larger than the maximum exponent we ever expect to see */
- #define BIGFLT 309
- #ifdef TEST
- char print_buf[1024*8];
- #else
- char print_buf[BIGFLT+20];
- #endif
-
-
- /* Functions, etc for dealing with cell contents being displayed
- on top of other cells. */
-
- struct slops {
- int s_alloc,s_used;
- struct s {
- CELLREF row,clo,chi;
- } s_b[1];
- };
-
- void
- flush_slops FUN1(VOIDSTAR,where)
- {
- struct slops *s;
-
- s=where;
- if(s)
- s->s_used=0;
- }
-
- int
- find_slop FUN5(VOIDSTAR, where, CELLREF,r, CELLREF,c, CELLREF *,cclp, CELLREF *,cchp)
- {
- int n;
- struct slops *s;
-
- s= where;
- if(!s)
- return 0;
- for(n=0;n<s->s_used;n++) {
- if(s->s_b[n].row==r && s->s_b[n].clo<=c && s->s_b[n].chi>=c) {
- *cclp=s->s_b[n].clo;
- *cchp=s->s_b[n].chi;
- return 1;
- }
- }
- return 0;
- }
-
- void
- kill_slop FUN4(VOIDSTAR,where, CELLREF,r, CELLREF,clo, CELLREF,chi)
- {
- int n;
- struct slops *s;
-
- s=where;
- for(n=0;n<s->s_used;n++) {
- if(s->s_b[n].row==r && s->s_b[n].clo==clo && s->s_b[n].chi==chi) {
- --(s->s_used);
- s->s_b[n]=s->s_b[s->s_used];
- return;
- }
- }
- }
-
- void
- set_slop FUN4(VOIDSTAR *,wherep, CELLREF,r, CELLREF,clo, CELLREF,chi)
- {
- int n;
- struct slops **sp;
-
- sp= (struct slops **)wherep;
- if(!*sp) {
- (*sp)=ck_malloc(sizeof(struct slops)+2*sizeof(struct s));
- (*sp)->s_alloc=2;
- (*sp)->s_used=1;
- n=0;
- } else {
- n= (*sp)->s_used++;
- if((*sp)->s_alloc==n) {
- (*sp)->s_alloc=n*2;
-
- (*sp)=ck_realloc((*sp),sizeof(struct slops)+n*2*sizeof(struct s));
- }
- }
- (*sp)->s_b[n].row=r;
- (*sp)->s_b[n].clo=clo;
- (*sp)->s_b[n].chi=chi;
- }
-
- void
- change_slop FUN6(VOIDSTAR,where, CELLREF,r, CELLREF,olo, CELLREF,ohi, CELLREF,lo, CELLREF,hi)
- {
- int n;
- struct slops *s;
-
- s= where;
- for(n=0;n<s->s_used;n++) {
- if(s->s_b[n].row==r && s->s_b[n].clo==olo && s->s_b[n].chi==ohi) {
- s->s_b[n].clo=lo;
- s->s_b[n].chi=hi;
- return;
- }
- }
- }
-
- /* Stuff for dealing with width of columns */
- /* This isn't the best place for it, but here it is. . . */
-
- struct width {
- struct width *prev,*next;
- CELLREF w_low,w_high;
- unsigned short wids[1];
- };
-
- struct width *wid_beg = 0;
- struct width *wid_end = 0;
-
- #define WID_BUF 1;
-
- unsigned short
- get_width FUN1(CELLREF, col)
- {
- struct width *my_width;
- unsigned short n;
-
- if(!wid_beg) {
- n=default_width;
- } else {
- for(my_width=wid_beg;my_width && col>my_width->w_high;my_width=my_width->next)
- ;
- if(!my_width || col<my_width->w_low)
- n=default_width;
- else {
- if(col<=my_width->w_high) {
- n=my_width->wids[col-my_width->w_low];
- if(n==0)
- n=default_width;
- else
- --n;
- } else
- n=default_width;
- }
- }
- /* if(n>numc)
- n=numc; */
- return n;
- }
-
- /* This is like get_width, but it returns width+1, or zero if the width is default */
- unsigned short
- get_nodef_width FUN1(CELLREF, col)
- {
- struct width *my_width;
- unsigned short n;
-
- if(!wid_beg)
- return 0;
-
- for(my_width=wid_beg;my_width && col>my_width->w_high;my_width=my_width->next)
- ;
- if(!my_width || col<my_width->w_low)
- return 0;
- if(col<=my_width->w_high) {
- n=my_width->wids[col-my_width->w_low];
- if(n==0)
- return 0;
- return n;
- }
- return 0;
- }
-
- void
- set_width FUN2(CELLREF, col, unsigned short, wid)
- {
- struct width *my_wid;
- struct width *tmp_wid;
-
- if(!wid_beg) {
- wid_beg=wid_end=(struct width *)ck_malloc(sizeof(struct width));
- wid_beg->prev=0;
- wid_beg->next=0;
- wid_beg->w_low=col;
- wid_beg->w_high=col;
- wid_beg->wids[0]=wid;
- return;
- }
-
- for(tmp_wid=wid_beg;tmp_wid;tmp_wid=tmp_wid->next)
- if(col<=tmp_wid->w_high)
- break;
-
- if(!tmp_wid) {
- if(wid_end->w_high==col-1) {
- wid_end->w_high++;
-
- wid_end=ck_realloc(wid_end,sizeof(struct width)+(wid_end->w_high-wid_end->w_low)*sizeof(unsigned short));
- wid_end->wids[col-wid_end->w_low]=wid;
- if(wid_end->prev)
- wid_end->prev->next=wid_end;
- else
- wid_beg=wid_end;
- } else {
- my_wid=(struct width *)ck_malloc(sizeof(struct width));
- my_wid->w_high=col;
- my_wid->w_low=col;
- my_wid->wids[0]=wid;
- my_wid->next=0;
- my_wid->prev=wid_end;
- wid_end->next=my_wid;
- wid_end=my_wid;
- }
- return;
- }
-
- if(col>=tmp_wid->w_low) {
- tmp_wid->wids[col-tmp_wid->w_low]=wid;
- return;
- }
-
- if(tmp_wid->prev && tmp_wid->prev->w_high==col-1) {
- if(col+1==tmp_wid->w_low) {
- struct width *w1,*w2;
-
- w1=tmp_wid->prev;
- w2=tmp_wid;
- my_wid=(struct width *)ck_malloc(sizeof(struct width)+(w2->w_high-w1->w_low)*sizeof(unsigned short));
- my_wid->prev=w1->prev;
- my_wid->next=w2->next;
- my_wid->w_high=w2->w_high;
- my_wid->w_low=w1->w_low;
-
- bcopy(w1->wids,&(my_wid->wids[0]),(1+w1->w_high-w1->w_low)*sizeof(unsigned short));
- bcopy(w2->wids,&(my_wid->wids[w2->w_low-my_wid->w_low]),(1+w2->w_high-w2->w_low)*sizeof(unsigned short));
- my_wid->wids[col-my_wid->w_low]=wid;
-
- if(my_wid->prev)
- my_wid->prev->next=my_wid;
- else
- wid_beg=my_wid;
- if(my_wid->next)
- my_wid->next->prev=my_wid;
- else
- wid_end=my_wid;
- free(w1);
- free(w2);
- } else {
- tmp_wid=tmp_wid->prev;
- tmp_wid->w_high++;
-
- tmp_wid=(struct width *)ck_realloc(tmp_wid,sizeof(struct width)+(tmp_wid->w_high-tmp_wid->w_low)*sizeof(unsigned short));
- tmp_wid->wids[tmp_wid->w_high-tmp_wid->w_low]=wid;
- tmp_wid->next->prev=tmp_wid;
- if(tmp_wid->prev)
- tmp_wid->prev->next=tmp_wid;
- else
- wid_beg=tmp_wid;
- }
- return;
- }
- if(col+1==tmp_wid->w_low) {
- my_wid=(struct width *)ck_malloc(sizeof(struct width)+(1+tmp_wid->w_high-tmp_wid->w_low)*sizeof(unsigned short));
- my_wid->w_high=tmp_wid->w_high;
- my_wid->w_low=col;
- my_wid->wids[0]=wid;
- bcopy(&(tmp_wid->wids[0]),&(my_wid->wids[1]),(tmp_wid->w_high-tmp_wid->w_low)*sizeof(unsigned short));
- my_wid->prev=tmp_wid->prev;
- my_wid->next=tmp_wid->next;
- if(my_wid->next)
- my_wid->next->prev=my_wid;
- else
- wid_end=my_wid;
- if(my_wid->prev)
- my_wid->prev->next=my_wid;
- else
- wid_beg=my_wid;
- free(tmp_wid);
- return;
- }
- my_wid=(struct width *)ck_malloc(sizeof(struct width));
- my_wid->w_high=col;
- my_wid->w_low=col;
- my_wid->wids[0]=wid;
- my_wid->next=tmp_wid;
- my_wid->prev=tmp_wid->prev;
- tmp_wid->prev=my_wid;
- if(my_wid->prev)
- my_wid->prev->next=my_wid;
- else
- wid_beg=my_wid;
- return;
- }
-
- unsigned short
- next_widths FUN2(CELLREF *,c1, CELLREF *,c2)
- {
- static struct width *wid;
- static int n;
- static int nhi;
-
- unsigned short ret;
- int m;
-
- if(c1==0) {
- wid=wid_beg;
- n=0;
- if(wid)
- nhi=wid->w_high-wid->w_low;
- return 0;
- }
- for(;wid;wid=wid->next,n=0,nhi=wid->w_high-wid->w_low) {
- for(;n<=nhi;n++) {
- if(wid->wids[n]==0)
- continue;
- ret=wid->wids[n];
- for(m=n+1;m<=nhi && wid->wids[m]==ret;m++)
- ;
- *c1=wid->w_low+n;
- *c2=wid->w_low+m-1;
- n=m;
- if(n>nhi) {
- n=0;
- wid=wid->next;
- if(wid)
- nhi=wid->w_high-wid->w_low;
- }
- return ret;
- }
- }
- return 0;
- }
-
- void
- flush_widths FUN0()
- {
- struct width *w,*wn;
-
- for(w=wid_beg;w;w=wn) {
- wn=w->next;
- free(w);
- }
- wid_beg=0;
- }
-
- void
- shift_widths FUN1(int, over)
- {
- struct width *w, *wtmp;
-
- for(w=wid_beg;w;w=w->next) {
- if(over<0 && w->w_low<= -over) {
- if(w->w_high<=MIN_COL-over) {
- if(w->prev)
- w->prev->next=w->next;
- else
- wid_beg=w->next;
- if(w->next)
- w->next=w->prev;
- else
- wid_end=w->prev;
- } else {
- wtmp=ck_malloc(sizeof(struct width)+(w->w_high+over-MIN_COL)*sizeof(unsigned short));
-
- if(w->next) {
- wtmp->next=w->next;
- w->next->prev=wtmp;
- } else
- wid_end=wtmp;
- if(w->prev) {
- wtmp->prev=w->prev;
- w->prev->next=wtmp;
- } else
- wid_beg=wtmp;
- wtmp->w_low=MIN_COL;
- wtmp->w_high=w->w_high+over;
- bcopy(&(w->wids[MIN_COL-over-w->w_low]),&(wtmp->wids[0]),(wtmp->w_high+1-wtmp->w_low)*sizeof(unsigned short));
- }
- free(w);
- } else if(over>0 && w->w_high>=MAX_COL-over) {
- if(w->w_low>=MAX_COL-over) {
- if(w->prev)
- w->prev->next=w->next;
- else
- wid_beg=w->next;
- if(w->next)
- w->next=w->prev;
- else
- wid_end=w->prev;
- free(w);
- } else {
- w->w_high=MAX_COL;
- w->w_low+=over;
-
- w=ck_realloc(w,sizeof(struct width)+(w->w_high-w->w_low)*sizeof(unsigned short));
- if(w->next)
- w->next->prev=w;
- else
- wid_end=w;
- if(w->prev)
- w->prev->next=w;
- else
- wid_beg=w;
- }
- } else {
- w->w_low+=over;
- w->w_high+=over;
- }
- }
- }
-
- /* Structures/vars/functions for dealing with formatting floating-point
- numbers, etc */
-
- struct user_fmt {
- char *p_hdr,*n_hdr;
- char *p_trl,*n_trl;
- char *zero,*comma,*decpt;
- unsigned char prec;
- double scale;
- };
-
- /* Routines for formatting cell values */
- static char *pr_flt EXT3(double, struct user_fmt *, int);
- static char *pr_int EXT3(long, struct user_fmt *, int);
-
- struct user_fmt dol = {
- "$","($", 0,")", "$0",",", ".", PRC_FLT, 1 };
-
- struct user_fmt cma = {
- 0, "(", 0,")", "0", ",", ".", PRC_FLT, 1 };
-
- struct user_fmt pct = {
- 0, "-", "%","%", "0%", 0, ".", PRC_FLT, 100 };
-
- struct user_fmt fxt = {
- 0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1 };
-
- /* Variables */
-
- struct user_fmt u[16] = {
- { 0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1 },
- { 0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1 },
- { 0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1 },
- { 0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1 },
- { 0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1 },
- { 0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1 },
- { 0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1 },
- { 0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1 },
- { 0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1 },
- { 0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1 },
- { 0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1 },
- { 0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1 },
- { 0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1 },
- { 0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1 },
- { 0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1 },
- { 0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1 },
- };
-
-
- /* Turn a floating-point number into the canonical text form. This scribbles
- on print_buf */
- char *
- flt_to_str FUN1(double, val)
- {
- double f;
- extern double fabs();
-
- if(val==__plinf)
- return iname;
- if(val==__neinf)
- return mname;
- f=fabs(val);
- if(f>=1e6 || (f>0 && f<=9.9999e-6)) {
- sprintf(print_buf,"%e",val);
- return print_buf;
- }
- return pr_flt(val,&fxt,PRC_FLT);
- }
-
- /* create the human-readable version of the contents of a cell
- This scribbles on print-buf bigtime */
-
- char *
- print_cell FUN1(CELL *,cp)
- {
- int j;
- int p;
- long num;
- static char zeroes[] = "000000000000000";
-
- j=GET_FMT(cp);
-
- if(j==FMT_DEF)
- j=default_fmt;
- if(j==FMT_HID || GET_TYP(cp)==0)
- return "";
-
- if(GET_TYP(cp)==TYP_STR)
- return cp->cell_str;
- if(GET_TYP(cp)==TYP_BOL) {
- #ifdef TEST
- if(cp->cell_bol<0 || cp->cell_bol>1)
- panic("Bool %d out of range",cp->cell_bol);
- #endif
- return bname[cp->cell_bol];
- }
- if(GET_TYP(cp)==TYP_ERR) {
- #ifdef TEST
- if(cp->cell_err>ERR_MAX || cp->cell_err<0)
- panic("Error %d out of range",cp->cell_err);
- #endif
- return ename[cp->cell_err];
- }
- if(GET_TYP(cp)==TYP_FLT) {
- p=GET_PRC(j);
- switch(j|PRC_FLT) {
- case FMT_GPH:
- if(cp->cell_flt<0) {
- j='-';
- num = -(cp->cell_flt);
- } else if(cp->cell_flt>=1) {
- j='+';
- num= (cp->cell_flt);
- } else {
- j='0';
- num=1;
- }
- graph:
- if(num>=sizeof(print_buf)) {
- error_msg("Cannot graph %d '%c'",p,j);
- num=sizeof(print_buf)-1;
- }
- print_buf[num]='\0';
- while(--num>=0)
- print_buf[num]=j;
- return print_buf;
-
- case FMT_USR:
- return pr_flt(cp->cell_flt,&u[p],u[p].prec);
-
- case FMT_GEN:
- {
- double f;
- extern double fabs();
-
- f=fabs(cp->cell_flt);
- if(f>=1e6 || (f>0 && f<=9.9999e-6))
- goto handle_exp;
- return pr_flt(cp->cell_flt,&fxt,p);
- }
-
- case FMT_DOL:
- return pr_flt(cp->cell_flt,&dol,p);
-
- case FMT_CMA:
- return pr_flt(cp->cell_flt,&cma,p);
-
- case FMT_PCT:
- return pr_flt(cp->cell_flt,&pct,p);
-
- case FMT_FXT:
- return pr_flt(cp->cell_flt,&fxt,p);
-
- case FMT_EXP:
- handle_exp:
- if(cp->cell_flt==__plinf)
- return iname;
- if(cp->cell_flt==__neinf)
- return mname;
- if(p==PRC_FLT)
- sprintf(print_buf,"%e",cp->cell_flt);
- else
- sprintf(print_buf,"%.*e",p,cp->cell_flt);
- return print_buf;
- #ifdef TEST
- default:
- panic("Unknown format %d",j);
- return 0;
- #endif
- }
- }
-
- if(GET_TYP(cp)==TYP_INT) {
- p=GET_PRC(j);
- switch(j|PRC_FLT) {
- case FMT_GPH:
- if(cp->cell_int<0) {
- j='-';
- num = -(cp->cell_int);
- } else if(cp->cell_int>=1) {
- j='+';
- num = (cp->cell_int);
- } else {
- j='0';
- num = 1;
- }
- goto graph;
-
- case FMT_USR:
- return pr_int(cp->cell_int,&u[p],u[p].prec);
-
- case FMT_GEN:
- sprintf(print_buf,"%ld",cp->cell_int);
- return print_buf;
-
- case FMT_DOL:
- return pr_int(cp->cell_int,&dol,p);
-
- case FMT_CMA:
- return pr_int(cp->cell_int,&cma,p);
-
- case FMT_PCT:
- return pr_int(cp->cell_int,&pct,p);
-
- case FMT_FXT:
- if(p!=PRC_FLT && p!=0)
- sprintf(print_buf,"%ld.%.*s",cp->cell_int,p,zeroes);
- else
- sprintf(print_buf,"%ld",cp->cell_int);
- return print_buf;
-
- case FMT_EXP:
- if(p!=PRC_FLT)
- sprintf(print_buf,"%.*e",p,(double)(cp->cell_int));
- else
- sprintf(print_buf,"%e",(double)(cp->cell_int));
- return print_buf;
- #ifdef TEST
- default:
- panic("Unknown format %d",j);
- return 0;
- #endif
- }
- }
- #ifdef TEST
- panic("Unknown cell type %d",GET_TYP(cp));
- #endif
- return 0;
- }
-
- /* Return the value of ROW,COL in a human-readable fashion
- In paticular, strings have "" around them, and are \\ed
- */
- char *
- cell_value_string FUN2(CELLREF, row, CELLREF, col)
- {
- CELL *cp;
- extern char *bname[];
- extern char print_buf[];
- extern char *flt_to_str();
- extern char *backslash_a_string();
-
- cp=find_cell(row,col);
- if(!cp || !GET_TYP(cp))
- return "";
- switch(GET_TYP(cp)) {
- case TYP_FLT:
- return flt_to_str(cp->cell_flt);
-
- case TYP_INT:
- sprintf(print_buf,"%ld",cp->cell_int);
- return print_buf;
-
- case TYP_STR:
- return backslash_a_string(cp->cell_str,1);
-
- case TYP_BOL:
- return bname[cp->cell_bol];
-
- case TYP_ERR:
- return ename[cp->cell_err];
- #ifdef TEST
- default:
- panic("unknown type %d in cell_value_string",GET_TYP(cp));
- #endif
- }
- return 0;
- }
-
- static char *
- pr_int FUN3(long,val, struct user_fmt *,fmt, int,prec)
- {
- char *pf, *pff, *pt;
- long int n;
- int nn=0;
-
- pt= &print_buf[sizeof(print_buf)-1];
- *pt='\0';
-
- n= fmt->scale * ((val<0) ? -val : val);
- if(n==0)
- return fmt->zero ? fmt->zero : "";
-
- pf=pff= (val<0) ? fmt->n_trl : fmt->p_trl;
- if(pf && *pf) {
- while(*pf)
- pf++;
- do
- *--pt= *--pf;
- while(pf!=pff);
- }
-
- if(prec!=PRC_FLT && prec!=0) {
- while(prec-->0)
- *--pt='0';
- pf=pff=fmt->decpt;
- if(pf) {
- while(*pf)
- pf++;
- do *--pt= *--pf;
- while(pf!=pff);
- }
- /* *--pt='.'; */
- }
- do {
- *--pt= (n%10)+'0';
- n/=10;
- if(nn++==2 && n>0) {
- if(fmt->comma && *(fmt->comma)) {
- for(pf=pff=fmt->comma;*pf;pf++)
- ;
- do *--pt= *--pf;
- while(pf!=pff);
- }
- nn=0;
- }
- } while(n>0);
-
- pf=pff= (val<0) ? fmt->n_hdr : fmt->p_hdr;
- if(pf && *pf) {
- while(*pf)
- pf++;
- do *--pt= *--pf;
- while(pf!=pff);
- }
- return pt;
- }
-
- static char *
- pr_flt FUN3(double,val, struct user_fmt *,fmt, int,prec)
- {
- char *iptr;
- char *fptr;
- char *pptr;
- char *pf,*pff;
- double fract, integer, tmpval;
- int n;
- int isneg;
- int comlen;
-
- val*=fmt->scale;
-
- if(val==__plinf)
- return iname;
- if(val==__neinf)
- return mname;
- if(val!=val)
- return nname;
-
- iptr= &print_buf[BIGFLT];
- fptr= &print_buf[BIGFLT];
-
-
- if(val<0) {
- isneg=1;
- val = -val;
- } else
- isneg=0;
-
- if(val==0)
- return fmt->zero ? fmt->zero : "";
-
- comlen=0;
- if(fmt->comma && *(fmt->comma))
- for(pf=fmt->comma;*pf;comlen++,pf++)
- ;
-
- fract=modf(val,&integer);
- n=0;
- do {
- if(iptr< &print_buf[comlen])
- return numb_oflo;
- tmpval=modf(integer/10,&integer);
- *--iptr='0'+(int)((tmpval+.01)*10);
- if(n++==2 && integer) {
- n=0;
- if(comlen) {
- pff=fmt->comma;
- pf=pff+comlen;
- do *--iptr= *--pf;
- while(pf!=pff);
- }
- }
- } while(integer);
-
- if(prec) {
- int p1;
-
- p1= (prec==PRC_FLT) ? 15 : (prec>0) ? prec : -prec;
- pf=fmt->decpt;
- while(pf && *pf)
- *fptr++= *pf++;
- /* *fptr++='.'; */
- if(fract) {
- do {
- fract = modf(fract * 10,&tmpval);
- *fptr++ = '0' + (int)tmpval;
- } while (--p1 && fract);
- }
- if(prec>0 && prec!=PRC_FLT)
- while(p1--)
- *fptr++='0';
- else {
- while(fptr[-1]=='0')
- --fptr;
- while(!isdigit(fptr[-1]))
- --fptr;
- *fptr='\0';
- }
- }
- if(fract) {
- (void)modf(fract * 10, &tmpval);
- if(tmpval>4) {
- iptr[-1]='0';
- for(pptr=fptr-1;;--pptr) {
- if(!isdigit(*pptr))
- continue;
- else if(*pptr=='9') {
- if(pptr==fptr-1 && pptr>&print_buf[BIGFLT] && (prec<0 || prec==PRC_FLT)) {
- --fptr;
- while(!isdigit(pptr[-1])) {
- --fptr;
- --pptr;
- }
- *pptr='\0';
- } else
- *pptr='0';
- } else {
- (*pptr)++;
- break;
- }
- }
- if(pptr<iptr) {
- --iptr;
- if(n==3) {
- n= *iptr++;
- for(pf=pff=fmt->comma;*pf;pf++)
- ;
- do *--iptr= *--pf;
- while(pf!=pff);
- *--iptr=n;
- }
- }
- }
- }
- pf=pff= (isneg) ? fmt->n_hdr : fmt->p_hdr;
- if(pf && *pf) {
- while(*pf)
- pf++;
- do *--iptr= *--pf;
- while(pf!=pff);
- }
-
- pf=(isneg) ? fmt->n_trl : fmt->p_trl;
- while(pf && *pf)
- *fptr++ = *pf++;
- *fptr=0;
- return iptr;
- }
-
- char *
- adjust_prc FUN5(char *,oldp, CELL *,cp, int,width, int,smallwid, int,just)
- {
- int fmt;
- int prc;
- struct user_fmt *ufmt;
- char *bptr;
- char *eptr;
- int len;
-
- fmt=GET_FMT(cp);
- if(fmt==FMT_DEF)
- fmt=default_fmt;
- prc=GET_PRC(fmt);
- switch(fmt|PRC_FLT) {
- case FMT_GPH:
- case FMT_HID:
- return numb_oflo;
- case FMT_DOL:
- ufmt= &dol;
- goto deal_fmt;
-
- case FMT_CMA:
- ufmt= &cma;
- goto deal_fmt;
-
- case FMT_PCT:
- ufmt= &cma;
- goto deal_fmt;
-
- case FMT_FXT:
- ufmt= &fxt;
- goto deal_fmt;
-
- case FMT_USR:
- ufmt= &u[prc];
- prc=ufmt->prec;
- goto deal_fmt;
-
- case FMT_GEN:
- if(prc!=PRC_FLT)
- return numb_oflo;
- if(index(oldp,'e') || !index(oldp,'.'))
- goto handle_exp;
-
- ufmt= &fxt;
- prc=PRC_FLT;
- goto deal_fmt;
-
- deal_fmt:
- if(prc!=PRC_FLT)
- return numb_oflo;
- len=strlen(oldp);
- bptr=strstr(oldp,ufmt->decpt);
- if(!bptr)
- return numb_oflo;
- while(eptr=strstr(bptr+1,ufmt->decpt))
- bptr=eptr;
-
- if(width<bptr-oldp)
- return numb_oflo;
- if(bptr-oldp+strlen(ufmt->decpt)>=width)
- prc=0;
- else {
- prc=width-(strlen(ufmt->decpt)+bptr-oldp);
- }
- bptr=pr_flt(cp->cell_flt,ufmt,-prc);
- len=strlen(bptr);
- if(len>width && prc>0) {
- bptr=pr_flt(cp->cell_flt,ufmt,-(prc-1));
- len=strlen(bptr);
- }
- if(len>width)
- return numb_oflo;
- break;
-
- case FMT_EXP:
- handle_exp:
- {
- double f;
- extern double fabs EXT1(double);
-
- f=fabs(cp->cell_flt);
- if(f>9.99999e99 || f<1e-99)
- len=width-7;
- else /* if(f>9.9999999e9 || f<1e-9) */
- len=width-6;
- /* else
- len=width-5; */
- if(cp->cell_flt<0)
- --len;
- if(len>0) {
- sprintf(oldp,"%.*e",len,cp->cell_flt);
- len=strlen(oldp);
- if(len<=width) {
- bptr=oldp;
- break;
- }
- }
- }
- return numb_oflo;
- #ifdef TEST
- default:
- panic("Unknown format %d in adjust_prc()",fmt);
- bptr=0;
- len=0;
- break;
- #endif
- }
-
- /* If we get here, bptr points to a a string of len characters
- (len<=width) that we want to output */
- if(len<smallwid) {
- if(just==JST_RGT || just==JST_CNT) {
- int n;
-
- n= (just==JST_RGT) ? smallwid-len : (1+smallwid-len)/2;
- for(;;) {
- bptr[len+n]=bptr[len];
- if(len--==0)
- break;
- }
- while(n-->=0)
- bptr[n]=' ';
- }
- }
- return bptr;
- }
-
-
- void
- set_usr_stats FUN2(int,usr_n, char **,usr_buf)
- {
- int len;
- int i;
- char *p_in,*p_out;
-
- len=0;
- for(i=0;i<7;i++)
- len+=strlen(usr_buf[i]);
- u[usr_n].p_hdr=ck_malloc(len+7);
- p_out=u[usr_n].p_hdr;
- if(usr_buf[0][0]) {
- p_in=usr_buf[0];
- while(*p_out++= *p_in++)
- ;
- } else
- *p_out++='\0';
-
- if(usr_buf[1][0]) {
- p_in=usr_buf[1];
- u[usr_n].n_hdr=p_out;
- while(*p_out++= *p_in++)
- ;
- } else
- u[usr_n].n_hdr=0;
-
- if(usr_buf[2][0]) {
- p_in=usr_buf[2];
- u[usr_n].p_trl=p_out;
- while(*p_out++= *p_in++)
- ;
- } else
- u[usr_n].p_trl=0;
-
- if(usr_buf[3][0]) {
- p_in=usr_buf[3];
- u[usr_n].n_trl=p_out;
- while(*p_out++= *p_in++)
- ;
- } else
- u[usr_n].n_trl=0;
-
- if(usr_buf[4][0]) {
- p_in=usr_buf[4];
- u[usr_n].zero=p_out;
- while(*p_out++= *p_in++)
- ;
- } else
- u[usr_n].zero=0;
-
- if(usr_buf[5][0]) {
- p_in=usr_buf[5];
- u[usr_n].comma=p_out;
- while(*p_out++= *p_in++)
- ;
- } else
- u[usr_n].comma=0;
-
- if(usr_buf[6][0]) {
- p_in=usr_buf[6];
- u[usr_n].decpt=p_out;
- while(*p_out++= *p_in++)
- ;
- } else
- u[usr_n].decpt=0;
-
- if(!stricmp(usr_buf[7],"float") || !stricmp(usr_buf[7],"f"))
- u[usr_n].prec=15;
- else
- u[usr_n].prec=astol(&usr_buf[7]);
-
- u[usr_n].scale=astof(&usr_buf[8]);
- }
-
- int
- usr_set_fmts FUN0()
- {
- int n;
- int ret = 0;
-
- for(n=0;n<16;n++)
- if(u[n].p_hdr)
- ret|=1<<n;
- return ret;
- }
-
- void
- get_usr_stats FUN2(int,usr_num, char **,usr_buf)
- {
- static char buf1[30];
- static char buf2[30];
- static char NullStr[]="";
-
- usr_buf[0]= u[usr_num].p_hdr ? u[usr_num].p_hdr : NullStr;
- usr_buf[1]= u[usr_num].n_hdr ? u[usr_num].n_hdr : NullStr;
- usr_buf[2]= u[usr_num].p_trl ? u[usr_num].p_trl : NullStr;
- usr_buf[3]= u[usr_num].n_trl ? u[usr_num].n_trl : NullStr;
- usr_buf[4]= u[usr_num].zero ? u[usr_num].zero : NullStr;
- usr_buf[5]= u[usr_num].comma ? u[usr_num].comma : NullStr;
- usr_buf[6]= u[usr_num].decpt ? u[usr_num].decpt : NullStr;
- if(u[usr_num].prec==15)
- usr_buf[7]="float";
- else {
- sprintf(buf1,"%u",u[usr_num].prec);
- usr_buf[7]=buf1;
- }
- sprintf(buf2,"%.12g",u[usr_num].scale);
- usr_buf[8]=buf2;
- }
-
- /* Functions for printing out the names of cells and ranges */
-
- char *
- cell_name FUN2(CELLREF,rr, CELLREF,cc)
- {
- static char strs[2][20];
- static num = 0;
- char *ptr;
-
- num = num ? 0 : 1;
-
- #ifdef A0_REFS
- ptr= &strs[num][9];
- sprintf(ptr,"%u",rr);
- if(cc<MIN_COL+26)
- *--ptr='A'-MIN_COL+cc;
- else if(cc<MIN_COL+702) {
- cc-=MIN_COL+26;
- *--ptr='A'+cc%26;
- *--ptr='A'+cc/26;
- }
- #if MAX_COL>702
- else if(cc<MIN_COL+18278) {
- cc-=MIN_COL+702;
- *--ptr='A'+cc%26;
- cc/=26;
- *--ptr='A'+cc%26;
- *--ptr='A'+cc/26;
- } else {
- cc-=MIN_COL+18278;
- *--ptr='A'+cc%26;
- cc/=26;
- *--ptr='A'+cc%26;
- cc/=26;
- *--ptr='A'+cc%26;
- *--ptr='A'+cc/26;
- }
- #else
- else
- panic("Col %u out of range in cell_name()",cc);
- #endif
- #else
- ptr= &strs[num][0];
- sprintf(ptr,"r%uc%u",rr,cc);
- #endif
- return ptr;
- }
-
- char *
- range_name FUN1(struct rng *,rng)
- {
- CELLREF lr,lc,hr,hc;
- static char buf[2][40];
- static num;
- char *ptr;
-
- ptr= &buf[num][0];
- num = num ? 0 : 1;
-
- lr=rng->lr;
- lc=rng->lc;
- hr=rng->hr;
- hc=rng->hc;
-
- #ifdef A0_REFS
- sprintf(ptr,"%s:%s",cell_name(lr,lc),cell_name(hr,hc));
- return ptr;
- #else
- if(lr==hr && lc==hc)
- sprintf(ptr,"r%uc%u",lr,lc);
- else if(lr==hr && lc!=hc)
- sprintf(ptr,"r%uc%u:%u",lr,lc,hc);
- else if(lr!=hr && lc==hc)
- sprintf(ptr,"r%u:%uc%u",lr,hr,lc);
- else
- sprintf(ptr,"r%u:%uc%u:%u",lr,hr,lc,hc);
- return ptr;
- #endif
- }
-
-
- #ifdef A0_REFS
- char *
- col_to_str FUN1(CELLREF, col)
- {
- static char strs[2][10];
- static num;
- char *ptr;
-
- ptr= &strs[num][9];
- num = num ? 0 : 1;
-
- if(col<MIN_COL+26)
- *--ptr='A'-MIN_COL+col;
- else if(col<MIN_COL+702) {
- col-=MIN_COL+26;
- *--ptr='A'+col%26;
- *--ptr='A'+col/26;
- } else if(col<MIN_COL+18278) {
- col-=MIN_COL+702;
- *--ptr='A'+col%26;
- col/=26;
- *--ptr='A'+col%26;
- *--ptr='A'+col/26;
- } else {
- col-=MIN_COL+18278;
- *--ptr='A'+col%26;
- col/=26;
- *--ptr='A'+col%26;
- col/=26;
- *--ptr='A'+col%26;
- *--ptr='A'+col/26;
- }
- return ptr;
- }
- #endif
-
-
- void
- clear_spreadsheet FUN0()
- {
- int n;
- extern int default_jst;
- extern int default_lock;
- extern void flush_widths EXT0();
- extern void flush_everything EXT0();
- extern void flush_all_timers EXT0();
-
- flush_everything();
- flush_widths();
- flush_all_timers();
- for(n=0;n<16;n++) {
- if(u[n].p_hdr) {
- free(u[n].p_hdr);
- u[n].p_hdr=0;
- u[n].prec=PRC_FLT;
- u[n].scale=1;
- }
- }
- default_width=8;
- default_jst=JST_LFT;
- default_fmt=FMT_GEN;
- default_lock=LCK_UNL;
- }
-
-