home *** CD-ROM | disk | FTP | other *** search
- /*--------------------------------------------------------------------
- Alged: Algebra Editor
-
- Copyright (c) 1994,1996 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.
-
- Notes;
- This was written using the excellent Borland Turbo C++ 3.0 Compiler.
- One of the concepts that occurs regularly in this program is the clag.
- A clag is a commutative-left-associative-group. For instance,
- x+y+z is a clag, but x-y-z is not, because SUB doesn't commute.
- And x+(y+z) is not a clag because it is right associative. Clags are
- either additive or multiplicative. You can sort, cancel, and combine
- elements of a clag. You can move numbers to the bottom (front) or
- top (end) of a clag. You can split and join clags by converting
- MUL and ADD to/from DIV and SUB. I think most people think in terms
- of clags, though they don't call them that.
-
- Notes: The following compiler flags are required:
- word alignment off, memory large, signed chars, enums as int.
- These are recommended: floating point emulation, fast float, 8086 inst.
-
- If you make any enhancements to this code, please comment them well and
- make a note below. I would appreciate it if you send me your enhancements
- also! There are a number of utility function you should be aware of,
- look at cons, newoper, newnode, freenode, freetree, debug, dumpnode.
- I added cons just lately so you may see cases where I should have used
- cons but didn't.
-
- Change log:
- 12/94 JDH first version henckel@vnet.ibm.com
- 1/95 JDH second version
- 2/95 JDH vers 2.2 make xlatable, visible comments, tidy up menu
- 8/95 JDH vers 3.0 complete and uploaded to simtel
- 2/96 JDH vers 3.2 add palette management, Dutch, other fixes
- 4/96 JDH vers 3.3 French, focal length control, fill modes
- 6/96 JDH vers 3.4 autokey, autopick, 3D cylindrical mode, brightness
- fix exponential in calcnode, set k=1 (no calc) in poly3,
- add combine to expjoin, make factpoly smarter.
- */
- #define MAIN
- #include "alged.h"
-
- long heapused();
-
- /*--------------------------------------------------------------------
- autosrc
-
- This little helper function will set/reset the default source
- and target. If src is and equation, it reassigns it to one
- side or the other. If tgt is NULL, it assigns it to a var.
- The default is 'x' if it exists, else it is the first var found
- in src.
- */
- node *findvar(node *s, char *name) {
- int i; node *t;
- if (s->kind==VAR && (!name || !strcmp(name,s->name)))
- return s;
- for (i=0; i<s->nump; ++i)
- if (!!(t=findvar(s->parm[i],name))) return t;
- return NULL;
- }
- void autosrc(int unset) {
- static node* oldsrc;
- static int fixtgt;
- node *tmp;
-
- if (unset!=1) { // SET
- oldsrc = NULL;
- if (src->kind==EQU) {
- oldsrc = src;
- if (unset==2 && src->lf->kind==DIV) // this is a hack for polydiv
- src = src->lf;
- else if (unset==2 && src->rt->kind==DIV)
- src = src->rt;
- else if (src->rt->kind < src->lf->kind && src->rt->kind != FUN)
- src = src->rt;
- else
- src = src->lf;
- }
- fixtgt = !tgt;
- if (tgt && tgt->kind==VAR && !findvar(src,tgt->name)) {
- freetree(tgt);
- tgt = NULL;
- }
- if (!tgt) {
- tmp = findvar(src,"x");
- if (tmp) tgt = newvar("x");
- else {
- tmp = findvar(src,NULL);
- if (tmp) tgt = deepcopy(tmp);
- else tgt = newvar("x"); // if all else fails, set tgt = x
- }
- }
- }
- else { // RESET
- if (oldsrc) src = oldsrc;
- if (fixtgt && tgt) { freetree(tgt); tgt = NULL; }
- oldsrc = NULL;
- fixtgt = 0;
- }
- }
-
- /*--------------------------------------------------------------------
- main
- */
- void main(int argc,char *argv[]) {
- int i,x,y,b,done=0,mous=1;
- node *tmp,*p;
-
- directvideo = 1; /* don't use bios */
- _wscroll = 0; /* disable scrolling */
-
- gettextinfo(&ti);
- heapsz = allocmem(32767,NULL); /* find memory available */
- heapsz *= 16;
- if (heapsz<1) heapsz=400000L; // default
-
- printf("ALGED: Algebra Editor, ver "__DATE__"\n\n");
- printf("Copyright (c) 1994,1996 John Henckel\n");
- printf("Permission to use, copy, modify, distribute and sell this software\n");
- printf("and its documentation for any purpose is hereby granted without fee,\n");
- printf("provided that the above copyright notice appear in all copies.\n");
-
- /*-----------------------------------------------------------------
- initialize some critical messages to english
- */
- msg[1]="parser stack underflow.";
- msg[2]="parser r-stack underflow.";
- msg[3]="unable to open %s for infix read.";
- msg[4]="Unexpected ) or ,";
- msg[5]="unable to open %s for postfix read.";
- msg[6]="missing function arity %s.";
- msg[7]="too few args to %s.";
- msg[8]="too many args to %s.";
- msg[12]="mouse driver not found in memory.";
- msg[13]="option not recognized %d.";
- msg[16]="Unable to find menu file '%s'.";
- /*-----------------------------------------------------------------
- load data files
- */
- firf = NULL;
- loadfile("alged.1st");
- for (i=1; i<argc; ++i)
- loadfile(argv[i]);
- curf = firf;
- if (loadmenu(argv[0])) return;
- /*-----------------------------------------------------------------
- init mouse
- */
- if (init_mouse() != -1) {
- printf(msg[12]);
- mous=0;
- }
- /*-----------------------------------------------------------------
- main loop
- */
- src = curf;
- show_menu(); // to establish mheight
- while (!done) {
- window(2,mheight+1,ti.screenwidth-1,ti.screenheight-1);
- textattr(norm);
- clrscr();
- window(1,1,ti.screenwidth,ti.screenheight); /* full */
- display(curf);
- show_menu();
- _setcursortype(_NOCURSOR);
- if (mous) show_mouse();
- if (mous) while (!!(b = get_mouse(&x,&y)));
- while (!mous || !(b = get_mouse(&x,&y)))
- if (kbhit()) {
- b = getch();
- if (!b && kbhit()) b=300+getch();
- break;
- }
- if (mous) hide_mouse();
- _setcursortype(_NORMALCURSOR);
- /*-----------------------------------------------------------------
- check for keypresses
- */
- i=PP0; /* default = do nothing */
- if (b==27) break; /* escape */
- if (b==332 && src) { /* dump */
- putch('\r'); putch('\n');
- putch('\n'); putch('\n');
- dumpnode(src,1);
- do { getch(); } while (kbhit());
- continue;
- }
- else if (b > 7) {
- for (i=0; i<numm; ++i)
- if (menu[i].hot==b) {
- i=menu[i].fid;
- break;
- }
- if (i==numm) continue; /* invalid key */
- }
- else { /* mouse click */
- x=x/8+1; y=y/8+1;
- i = selection(x,y);
- }
- if (i>=0) {
- if (i==ESC) break; /* escape */
- switch (i) {
- case HLP: showhelp(argv[0]); break;
- case EQK:
- if (src && tgt && src->kind!=EQU && tgt->kind!=EQU) {
- tmp = newoper(EQU);
- tmp->rt = tgt;
- tmp->lf = deepcopy(src);
- tgt = tmp;
- }
- break;
- case DIS: if (src) while(distribute(src)); break;
- case DI2: if (src) while(distribute_c(src)); break;
- case CAL:
- if (src) {
- while(movenums(src,1,MUL)); /* move up for stretch rule */
- while(calcnode(src,0));
- while(movenums(src,0,MUL));
- while(calcnode(src,0)); // alright, this is a hack for exp.
- } break;
- case COD:
- if (src)
- if (src->kind==DIV) while (distribute2(src));
- else while (comdeno(src));
- break;
- case SIM: if (src) simplify(src); break;
- case SI2: if (src) simplify2(src,1); break;
- case ASS: if (src) associate(src); break;
- case PCO: if (src) { autosrc(0); polycoef(tgt,src);} break;
- case RAT: if (src) ration(src); break;
- case EXX: if (src) while (exexpand(src)); break;
- case EXJ: if (src) {
- while (combine(src));
- while (expjoin(src)); } break;
- case SBS: if (src && tgt && tgt->kind==EQU) substitution(src); break;
- case QUA: if (src) { autosrc(0); quadratic(tgt,src); autosrc(1);} break;
- case FAP: if (src) { autosrc(0); factrpoly(tgt,src); autosrc(1);} break;
- case PRI: if (src) primefact(src); break;
- case CUB: if (src) { autosrc(0); cubic(tgt,src); autosrc(1);} break;
- case GRF: if (src) graph(tgt,src); break;
- case XE0: if (src) cross_eq(src,0); break;
- case XE1: if (src) cross_eq(src,1); break;
- case P2T: src=curf; break;
- case P2L: if (src && src->nump>0) src = src->lf; break;
- case P2R: if (src && src->nump>1) src = src->rt; break;
- case P2K:
- if (src) { /* copy pick to key */
- p = deepcopy(src);
- if (tgt) freetree(tgt);
- tgt = p;
- } break;
- case PLY:
- if (src) {
- autosrc(2);
- if (src->kind==DIV) {
- tmp = polydiv(tgt,src->lf,src->rt);
- if (tmp) movenode(src,tmp);
- while (calcnode(src,1)); /* rmv 0+x and 0*x */
- }
- autosrc(1);
- }
- break;
- case PPR: panx -= 10; break;
- case PP0: panx = 0; break;
- case PPL: panx += 10; break;
- case CH8: ch8=1-ch8;
- if (ch8) {
- hline = 196; vline = 179;
- urc = 191; llc = 192;
- lrc = 217; ulc = 218;
- strcpy(piname,msg[33]);
- }
- else {
- hline = '-'; vline = '|';
- urc = '\\'; llc = '\\';
- lrc = '/'; ulc = '/';
- strcpy(piname,msg[32]);
- }
- clrscr();
- break;
- case WRI: writefile(keyin(msg[24])); break; /* infix */
- case LOD:
- loadfile(keyin(msg[25]));
- src = curf;
- break;
- case SAV: savefile(keyin(msg[26])); break; /* postfix only */
- case CLR:
- while (firf) {
- tmp = firf;
- firf = firf->next;
- freetree(tmp);
- } curf = src = NULL;
- break;
- case ADZ: insertkey(ADD); break;
- case SUZ: insertkey(SUB); break;
- case MUZ: insertkey(MUL); break;
- case DIZ: insertkey(DIV); break;
- case EXZ: insertkey(EXP); break;
- case DEK: if (tgt) freetree(tgt); tgt=NULL; break;
- case DEL:
- tmp = curf;
- if (!curf) break;
- if (curf==firf) curf = firf = firf->next;
- else curf = prevnode(curf)->next = curf->next;
- freetree(tmp);
- break;
- case INK:
- if (!tgt) break;
- tgt->next = curf;
- if (curf==firf) curf=firf=tgt;
- else {
- curf = prevnode(curf);
- curf->next = tgt;
- curf = tgt;
- }
- src = curf;
- tgt = deepcopy(tgt);
- break;
- case ENT:
- window(1,ti.screenheight-4,ti.screenwidth-1,ti.screenheight-1);
- textattr(norm);
- clrscr();
- if (postfix) cputs(msg[30]); else cputs(msg[31]); putch('\r');
- if (tgt) freetree(tgt);
- if (postfix) tgt = load("con");
- else tgt = loadinfix("con");
- window(1,1,ti.screenwidth,ti.screenheight);
- break;
- case NXT:
- if (curf) curf = curf->next;
- if (!curf) curf = firf;
- src = curf;
- break;
- case PRV:
- if (curf==firf) curf = lastnode(curf);
- else curf = prevnode(curf);
- src = curf;
- break;
- default:
- printf(msg[13],i); pause;
- }
- }
- else { /* not a menu selection */
- tmp = curf;
- p = NULL;
- for (i=0; i<numsee && tmp; ++i) {
- if (!!(p=find_node(tmp,x,y))) break;
- tmp = tmp->next;
- }
- if (!p && tgt)
- p = find_node(tgt,x,y);
- if (b==1) /* LMB */
- src = p;
- else if (p) { /* RMB on an expression */
- p = deepcopy(p);
- if (tgt) freetree(tgt);
- tgt = p;
- }
- else { /* RMB on nothing */
- if (tgt) freetree(tgt);
- tgt=NULL;
- }
- }
- }
- textattr(7);
- clrscr();
- }
-
-