home *** CD-ROM | disk | FTP | other *** search
- /*--------------------------------------------------------------------
- Alged: Algebra Editor henckel@vnet.ibm.com
-
- Copyright (c) 1994 John Henckel
- Permission to use, copy, modify, distribute and sell this software
- and its documentation for any purpose is hereby granted without fee,
- provided that the above copyright notice appear in all copies.
- */
- #include "alged.h"
- #include <alloc.h>
- /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- The following functions relate to displaying expressions on the
- screen.
- */
-
- /*-----------------------------------------------------------------
- twirl - this spins a little status indicator on the bottom
- of the display to reassure the user in long calculations.
- */
- void twirl(void) {
- static char c[] = "/-\\|";
- static int i=0;
- gotoxy(5,ti.screenheight);
- putch(c[i]);
- if (++i > 3) i=0;
- }
- /*--------------------------------------------------------------------
- debug dump
- */
- void dumpnode(node *p,int tab) {
- int i;
- for (i=0; i<tab; ++i) putch(' ');
- cprintf("%p %d %d (%d %d) %d '%s'\r\n",p,p->kind,p->nump,
- p->px,p->py,p->sy,p->name);
- for (i=0; i<p->nump; ++i)
- dumpnode(p->parm[i],tab+2);
- }
-
- /*--------------------------------------------------------------------
- re compute size of each node
- */
- void resize(node *p,int ppr) {
- double x;
- int mpr,i;
- mpr = pr[p->kind];
- p->ay = 0;
- switch (p->kind) {
- case NUM:
- x = fabs(p->value);
- p->name[0] = 0;
- if (p->value<0) strcat(p->name,"-");
- if (x==M_PI) strcat(p->name,piname);
- else if (x==M_E) strcat(p->name,ename);
- else if (x==HUGE_VAL) strcat(p->name,infname);
- else if (ch8 && x==0.5) strcat(p->name,halfname);
- else if (ch8 && x==0.25) strcat(p->name,qtrname);
- else sprintf(p->name,"%1.15G",p->value);
- p->sy=1;
- p->sx=strlen(p->name);
- if (!point && strchr(p->name,'.')) *strchr(p->name,'.') = ',';
- break;
- case BAD:
- strcpy(p->name,errname); /* fall thru */
- case VAR:
- p->sy=1;
- p->sx=strlen(p->name);
- break;
- case EQU:
- case ADD:
- case SUB:
- p->sx = 3;
- if (mpr<ppr) p->sx += 2; /* parens */
- resize(p->lf,mpr);
- resize(p->rt,mpr+1); /* +1 = a hack */
- p->sy = max(p->lf->sy,p->rt->sy);
- p->sx += p->lf->sx + p->rt->sx;
- strcpy(p->name,kname[p->kind]);
- break;
- case MUL:
- p->sx = 1;
- if (mpr<ppr) p->sx += 2; /* parens */
- resize(p->lf,mpr);
- resize(p->rt,mpr+1); /* +1 = a hack */
- p->sy = max(p->lf->sy,p->rt->sy);
- p->sx += p->lf->sx + p->rt->sx;
- strcpy(p->name,kname[p->kind]);
- break;
- case DIV:
- resize(p->lf,1); /* 1 = div suppresses parens */
- resize(p->rt,1);
- p->sx = max(p->lf->sx,p->rt->sx) + 2;
- p->sy = p->lf->sy + p->rt->sy + 1;
- p->ay = p->lf->sy - p->rt->sy;
- if (p->ay <0) p->ay--;
- p->ay /= 2;
- if (mpr<ppr) p->sx += 2; /* parens */
- strcpy(p->name,kname[p->kind]);
- break;
- case EXP:
- resize(p->lf,mpr+1);
- resize(p->rt,mpr);
- p->sx = p->lf->sx + p->rt->sx;
- p->sy = p->lf->sy + p->rt->sy;
- p->ay = p->rt->sy - p->lf->sy;
- if (p->ay >0) p->ay++;
- p->ay /= 2;
- if (mpr<ppr) p->sx += 2; /* parens */
- strcpy(p->name,kname[p->kind]);
- break;
- case FUN:
- p->sx = strlen(p->name) + 1; /* 2 parens JDH check this! */
- p->sy = 0;
- for (i=0; i<p->nump; ++i) {
- resize(p->parm[i],mpr);
- setmax(p->sy,p->parm[i]->sy);
- p->sx += 1 + p->parm[i]->sx; /* 1 comma */
- }
- break;
- default:
- printf(msg[14]);
- pause;
- }
- }
- /*--------------------------------------------------------------------
- leftpar - print a left parenthesis
- */
- void leftpar(int h) {
- int i;
- if (h<2) {
- putch('('); return; }
- relxy(0,-h/2);
- putch(ulc);
- for (i=0; i<h-2; ++i) {
- relxy(-1,1);
- putch(vline);
- }
- relxy(-1,1);
- putch(llc);
- }
- /*--------------------------------------------------------------------
- rightpar - print a right parenthesis
- */
- void rightpar(int h) {
- int i;
- if (h<2) {
- putch(')'); return; }
- relxy(0,-h/2);
- putch(urc);
- for (i=0; i<h-2; ++i) {
- relxy(-1,1);
- putch(vline);
- }
- relxy(-1,1);
- putch(lrc);
- }
- /*-----------------------------------------------------------------
- fix attributes
- */
- int fixattr(node *p) {
- gettextinfo(&ti);
- if (p==src) textattr(bold1);
- return ti.attribute;
- }
-
- #define seen (x > 0 && x < ti.screenwidth)
-
- /*--------------------------------------------------------------------
- print expression
- */
- void show(node *p,int ppr,int x,int y) {
- int mpr,i,z,s0,s1,attr;
- mpr = pr[p->kind];
-
- if (yadj) y = y + p->ay; /* adjust y */
- gotoxy(x,y);
- attr=fixattr(p); /* save old attribute */
-
- switch (p->kind) {
- case NUM:
- case BAD:
- case VAR:
- p->px = x; p->py = y;
- i = strlen(p->name); z = 0;
- if (x > ti.screenwidth) break;
- if (i+x > ti.screenwidth) i = ti.screenwidth - x;
- if (x < 1) { gotoxy(1,y); z = -x; }
- if (z < i) cprintf("%.*s",i-z,p->name+z);
- break;
- case EQU:
- case ADD:
- case SUB:
- if (mpr<ppr) { if (seen) leftpar(p->sy); ++x; } /* parens */
- show(p->lf,mpr,x,y);
- x += p->lf->sx + 1;
- gotoxy(x-1,y);
- fixattr(p);
- if (seen) cprintf(" %s ",kname[p->kind]);
- show(p->rt,mpr+1,x+2,y);
- p->px = x; p->py = y;
- if (mpr<ppr) {
- x += 2+p->rt->sx;
- gotoxy(x,y);
- fixattr(p);
- if (seen) rightpar(p->sy); /* parens */
- }
- break;
- case MUL:
- if (mpr<ppr) { if (seen) leftpar(p->sy); ++x; } /* parens */
- show(p->lf,mpr,x,y);
- x += p->lf->sx;
- gotoxy(x,y);
- fixattr(p);
- if (seen) cputs(ch8 ? kname[p->kind] : "*");
- show(p->rt,mpr+1,x+1,y);
- p->px = x; p->py = y;
- if (mpr<ppr) {
- x += 1+p->rt->sx;
- gotoxy(x,y);
- fixattr(p);
- if (seen) rightpar(p->sy); /* parens */
- }
- break;
- case DIV:
- if (seen) for (i=0; i<p->sx; ++i) {
- if (x+i < ti.screenwidth) putch(hline);
- }
- else if (x<1 && 0<(i=x+p->sx)) {
- gotoxy(1,y); while (--i) putch(hline);
- }
- p->px = x; p->py = y;
- if (mpr<ppr) {
- gotoxy(x,y);
- if (seen) leftpar(p->sy); /* parens */
- }
- show(p->lf,1,x + (p->sx - p->lf->sx)/2,
- y - (p->lf->sy + 1)/2);
- fixattr(p);
- show(p->rt,1,x + (p->sx - p->rt->sx)/2,
- y + (p->rt->sy + 2)/2);
- if (mpr<ppr) {
- x+=p->sx-1;
- gotoxy(x,y);
- fixattr(p);
- if (seen) rightpar(p->sy); /* parens */
- }
- break;
- case EXP:
- if (mpr<ppr) { if (seen) leftpar(p->sy); ++x; } /* parens */
- show(p->rt,mpr ,x + p->lf->sx,y - (p->rt->sy + 1)/2);
- fixattr(p);
- show(p->lf,mpr+1,x, y + (p->lf->sy + 0)/2);
- p->px = x + p->lf->sx - 1;
- p->py = y - 1;
- if (mpr<ppr) {
- x += p->sx-2;
- gotoxy(x,y);
- fixattr(p);
- if (seen) rightpar(p->sy); /* parens */
- }
- break;
- case FUN:
- p->px = x; p->py = y;
- if (seen) {
- cputs(p->name);
- leftpar(p->sy);
- }
- x += strlen(p->name) + 1;
- for (i=0; ; ) {
- show(p->parm[i],mpr,x,y);
- x += p->parm[i]->sx;
- gotoxy(x,y);
- fixattr(p);
- if (++i >= p->nump) break;
- if (seen) putch(comma);
- ++x;
- }
- if (seen) rightpar(p->sy); /* parens */
- break;
- default:
- printf(msg[15]);
- pause;
- }
- textattr(attr);
- }
- /*-----------------------------------------------------------------
- This test the integrity of the heap and returns the amount of
- space USED.
- */
- long heapused() {
- struct heapinfo hi; long t=0;
- if (heapcheck()<0) {
- printf(msg[28]); pause;
- return -1;
- }
- hi.ptr=NULL;
- while (heapwalk(&hi)==2)
- if (hi.in_use) t+=hi.size;
- return t;
- }
-
- /*-----------------------------------------------------------------
- display menu
- if the corner is 200, then no redraw is necessary.
- */
- void show_menu(void) {
- int i,j,x=999,y=0; time_t t;
- textattr(mcolor);
- gettext(1,ti.screenheight,1,ti.screenheight,&i);
- if ((i&255)!=200 || rand()<6000) {
- for (i=0; i<numm; ++i) if (menu[i].name[0]!='.') {
- if (x > ti.screenwidth-mwidth+1) { x=1; ++y; }
- menu[i].x = x;
- menu[i].y = y;
- gotoxy(x,y);
- if (x>1) putch(vline); else putch(' ');
- cputs(menu[i].name);
- for (j=strlen(menu[i].name)+1; j<mwidth; ++j) putch(' ');
- x+=mwidth;
- }
- mheight = y+1; /* number of lines used by the menu */
- relxy(-1,0);
- for (x=wherex(); x>1 && x<=ti.screenwidth; ++x)
- if (x%mwidth!=1) putch(' '); else putch(vline);
-
- /* MAKE THE BOX AROUND THE FORMULA */
- if (ch8) {
- gotoxy(1,y+1);
- putch(201);
- for (i=2; i<ti.screenwidth; ++i) putch(205);
- putch(187);
- gotoxy(1,ti.screenheight);
- putch(200);
- for (i=2; i<ti.screenwidth; ++i) putch(205);
- putch(188);
- }
- gotoxy((ti.screenwidth-strlen(top))/2,mheight);
- cputs(top);
- }
- if (ch8)
- for (i=mheight+1; i<ti.screenheight; ++i) {
- gotoxy(1,i); putch(186); gotoxy(ti.screenwidth,i); putch(186);
- }
- gotoxy(5,ti.screenheight);
- t=time(0);
- cprintf(" %.5s %2lu%% ",ctime(&t)+11,100*heapused()/heapsz);
- cputs(bottom);
- gotoxy(2,ti.screenheight-1);
- }
- /*-----------------------------------------------------------------
- Check for menu select
- */
- int selection(int x, int y) {
- int i;
- for (i=0; i<numm; ++i)
- if (x>=menu[i].x && x<menu[i].x+mwidth && y==menu[i].y)
- return menu[i].fid;
- if (y==mheight) return PRV;
- if (x==1) return PPL;
- if (x==ti.screenwidth) return PPR;
- if (y==ti.screenheight) return NXT;
- return -1;
- }
- /*--------------------------------------------------------------------
- display expressions (as many as possible) starting at p.
- */
- void display(node *p) {
- int x,y,i,ts=0;
-
- if (tgt) {
- resize(tgt,0);
- ts = ti.screenheight/2;
- if (ts > tgt->sy) ts=tgt->sy;
- }
- y=mheight+1;
- numsee = 0;
- while (p) {
- resize(p,0);
- x = (ti.screenwidth-2 - p->sx)/2 + 2 + panx;
- if (p->msg && y+ts+1+p->sy < ti.screenheight) {
- gotoxy(1,y);
- textattr(bold2); cprintf("%s",p->msg); textattr(norm);
- y = wherey()-1;
- }
- y += p->sy+1;
- if (y+ts >= ti.screenheight) break;
- show(p,0,x,y - (p->sy+1)/2);
- p = p->next;
- ++numsee;
- }
- if (!p && y+ts+1 < ti.screenheight) { /* end of list */
- gotoxy((ti.screenwidth-strlen(endlist))/2,y+1);
- cputs(endlist);
- }
- if (ts) {
- x = (ti.screenwidth-2 - tgt->sx)/2 + 2 + panx;
- y = ti.screenheight - ts + tgt->sy/2;
- show(tgt,0,x,y);
- textattr(mcolor);
- gotoxy(2,ti.screenheight-ts-1);
- for (i=2; i<ti.screenwidth; ++i) putch(hline);
- gotoxy(4,ti.screenheight-ts-1);
- cputs(keyname);
- textattr(norm);
- }
- }
-
- /*--------------------------------------------------------------------
- debug print out -- return 0 if 'g' is pressed
- */
- int debug(node *p) {
- int x,y;
- window(1,mheight+1,ti.screenwidth,ti.screenheight-1);
- textattr(norm);
- clrscr();
- cprintf(msg[35]);
- resize(p,0);
- x = (ti.screenwidth-2 - p->sx)/2 + 2 + panx;
- y = ti.screenheight/2;
- show(p,0,x,y);
- window(1,1,ti.screenwidth,ti.screenheight);
- return 'g'!=getch();
- }
- /*-----------------------------------------------------------------
- which node is pointed to?
- */
- node *find_node(node *p,int x,int y) {
- int i; node *t;
- switch (p->kind) {
- case ADD: case MUL: case EQU:
- case EXP: case SUB:
- if (x == p->px && y==p->py) {
- return p;
- }
- break;
- case DIV:
- if (x >= p->px && y==p->py &&
- x < (p->px+p->sx)) {
- return p;
- }
- break;
- case FUN:
- if (x >= p->px && y==p->py &&
- x < (p->px+strlen(p->name))) {
- return p;
- }
- break;
- default:
- if (x >= p->px && y==p->py &&
- x < (p->px + p->sx)) {
- return p;
- }
- }
- for (i=0; i<p->nump; ++i)
- if (!!(t=find_node(p->parm[i],x,y))) return t;
- return NULL;
- }
-
- /*-----------------------------------------------------------------
- prompt the user for oneline input
- return value is non-reuseable!
- */
- char *keyin(char *pmt) {
- static char buf[160]; int i;
- window(1,ti.screenheight-4,ti.screenwidth-1,ti.screenheight-1);
- textattr(norm);
- clrscr();
- cputs(pmt);
- cputs("\r\n");
- buf[0] = sizeof buf - 7;
- cgets(buf); buf[0]=buf[1]=' ';
- window(1,1,ti.screenwidth,ti.screenheight);
- if (!buf[2]) strcpy(buf+2,"*.ae");
- i = strlen(buf);
- while (strchr(buf+2,'*') || strchr(buf+2,'?') || buf[i-1]=='\\') {
- clrscr();
- memmove(buf+7,buf+2,i-1);
- memcpy(buf,"dir /w ",7);
- printf("'%s'\n",buf);
- system(buf);
- printf("%s",pmt);
- gets(buf+2);
- i = strlen(buf);
- }
- if (i<4 || !strchr(buf+i-4,'.')) strcat(buf,".ae");
- return buf+2;
- }
- /*-----------------------------------------------------------------
- show help file
- */
- void showhelp(char *argv0) {
- FILE *f;
- int i,c=0;
- static char s[85];
-
- /* strcpy(s,argv0);
- strcpy(s+strlen(argv0)-4,lang); don't use exe path */
- i=*argv0;
- strcpy(s,"alged");
- strcat(s,lang);
- strcat(s,".hlp");
- f = fopen(s,"r");
- if (!f) { printf(msg[16],s);
- pause; return;
- }
- textattr(norm);
- clrscr();
- i = ti.screenheight-1;
- while (!feof(f)) {
- printf(fgets(s,80,f));
- if (!--i) {
- i = ti.screenheight-4;
- while (!(c=getch()));
- if (c==27) break;
- }
- }
- if (c!=27) getch();
- fclose(f);
- }
-
- /*-----------------------------------------------------------------
- load menu def
- */
- int loadmenu(char *argv0) {
- FILE *f;
- int i,c=0;
- static char s[85];
-
- i=*argv0;
- /*
- strcpy(s,argv0);
- strcpy(s+strlen(argv0)-4,lang); don't use exe path */
- strcpy(s,"alged");
- strcat(s,lang);
- strcat(s,".mnu");
- f = fopen(s,"r");
- if (!f) { printf(msg[16],s);
- pause; return 1;
- }
- for (i=0; i<MAXM; ++i) msg[i]="[message not found]\n";
- while (!feof(f)) {
- fscanf(f,"%s",s);
- if (!strcmp(s,"item")) {
- c=0;
- fscanf(f," \"%[^\"]\" %d %d",s,&i,&c);
- if (!c) fscanf(f," '%c'",&c);
- strcpy(menu[numm].name,s);
- menu[numm].fid=i;
- menu[numm++].hot=c;
- }
- else if (*s==';') {
- fgets(s,sizeof s,f);
- }
- else if (!strcmp(s,"bottom")) {
- fscanf(f," \"%[^\"]\"",bottom);
- }
- else if (!strcmp(s,"key")) {
- fscanf(f," \"%[^\"]\"",keyname);
- }
- else if (!strcmp(s,"top")) {
- fscanf(f," \"%[^\"]\"",top);
- }
- else if (!strcmp(s,"endlist")) {
- fscanf(f," \"%[^\"]\"",endlist);
- }
- else if (!strcmp(s,"width")) {
- fscanf(f,"%d",&mwidth);
- }
- else if (!strcmp(s,"msg")) {
- fscanf(f,"%d ",&i);
- fgets(s,sizeof s,f);
- c = strlen(s);
- if (s[c-2]=='$') s[c-2]=0;
- if (i>=0&&i<MAXM) {
- msg[i]=malloc(strlen(s)+1);
- strcpy(msg[i++],s);
- }
- }
- }
- fclose(f);
- return 0;
- }
-