home *** CD-ROM | disk | FTP | other *** search
- /*
- * GRAPH, Version 1.00 - 4 August 1989
- *
- * Copyright 1989, David Gay. All Rights Reserved.
- * This software is freely redistrubatable.
- */
-
- /* Main program */
-
- #include <exec/types.h>
- #include <libraries/dos.h>
- #include <stdio.h>
- #include <string.h>
- #include <math.h>
-
- #include "graph.h"
- #include "file.h"
- #include "object.h"
- #include "uio.h"
- #include "list.h"
- #include "grph.h"
- #include "user/eval.h"
- #include "tracker.h"
-
- #include <proto/exec.h>
- #include <proto/dos.h>
-
- /* Gadget ids for variables requester */
- #define VARSLIST 2
- #define VARSDEL 3
-
- const char *eval_messages[] = {
- "No error",
- "Syntax error",
- "Out of memory",
- "Right bracket expected",
- "Obsolete",
- "Left bracket expected",
- "Function not differentiable",
- "Recursion detected",
- "Result not numeric"
- };
-
- /* The various libraries used */
- struct LayersBase *LayersBase;
- extern struct DiskfontBase *DiskfontBase;
- extern struct GfxBase *GfxBase;
- extern struct IntuitionBase *IntuitionBase;
- struct ArpBase *ArpBase;
-
- list graph_list; /* List of graphs */
- context vars; /* List of variables */
-
- static int vars_saved = TRUE;
- /* Used by variable requester */
- static char var[VARLEN], val[EXPRLEN];
- static struct Gadget *valg, *delg;
- static struct ListInfo *var_info;
-
- /* Inform objects that variable var has changed value. They may need to
- recalculate */
- static void check_vars(char *var)
- {
- struct graph *scan;
- struct object *o;
-
- /* Variables are global ==> for all graphs, all objects */
- for (scan = first(&graph_list); succ(scan); scan = succ(scan))
- for (o = first(&scan->o_list); succ(o); o = succ(o))
- o->var_change(o, var);
- }
-
- /* Redraw all graphs (eg after variables have changed) */
- static void draw_all(void)
- {
- struct graph *g;
-
- for (g = first(&graph_list); succ(g); g = succ(g))
- draw_graph(g, TRUE);
- }
-
- /* Load a graph from a file into a new graph. See file format. */
- static void load_file(struct graph *from)
- {
- FILE *f;
- char file[FILELEN];
-
- if (getfile(file, "Load graph"))
- if (f = fopen(file, "r"))
- {
- short tag;
-
- if (READ(f, tag) && tag == GRAPH_TAG)
- {
- struct graph *g = load_graph(from, f);
-
- if (g) add_head(&graph_list, g);
- }
- else
- message(from, "File is not a graph", (char *)NULL);
- fclose(f);
- }
- else
- message(from, "Couldn't open file", file, (char *)NULL);
- }
-
- /* Save current graph to a file. See file format. */
- /* TBD: Provide some default file name */
- static void save_file(struct graph *g)
- {
- FILE *f;
- char file[FILELEN];
-
- if (getfile(file, "Save graph"))
- if (f = fopen(file, "w"))
- {
- save_graph(g, f);
- fclose(f);
- }
- else
- message(g, "Couldn't open file", file, (char *)NULL);
- }
-
- /* Read variables from a file. See file format. This adds variables to the
- current context, it doesn't eliminate the old ones. */
- static void load_variables(struct graph *from)
- {
- FILE *f;
- char file[FILELEN];
-
- if (getfile(file, "Load variables"))
- if (f = fopen(file, "r"))
- {
- short tag;
- int ok = FALSE;
-
- if (READ(f, tag) && tag == FILE_TAG) /* This is a variable file */
- {
- int done = FALSE;
-
- ok = TRUE;
- do /* Read all the file */
- {
- short tag;
-
- if (READ(f, tag))
- {
- switch (tag)
- {
- case FILE_END:
- done = TRUE;
- break;
- case VAR_TAG: /* Another variable */
- {
- char name[VARLEN], val[EXPRLEN];
-
- if (READ(f, name) &&
- READ(f, val) &&
- READ(f, tag) && tag == VAR_END)
- {
- value vv = compile(val);
-
- if (!vv || !set_var_name(name, vv))
- message(from, "Failed to set variab
- le(no memory ?)", (char *)NULL);
- check_vars(name);
- }
- else
- ok = FALSE;
- }
- break;
- default:
- ok = FALSE;
- break;
- }
- }
- else
- ok = FALSE;
- } while (!done && ok);
- }
- fclose(f);
- if (!ok)
- message(from, "File does not contain variables", (char *)NULL);
-
- else draw_all();
- }
- else
- message(from, "Couldn't open file", file, (char *)NULL);
- }
-
- /* Save variables. See file format. */
- static void save_variables(struct graph *g)
- {
- FILE *f;
- char file[FILELEN];
-
- if (getfile(file, "Save variables"))
- if (f = fopen(file, "w"))
- {
- short tag = FILE_TAG;
- int ok = FALSE;
-
- if (WRITE(f, tag))
- {
- tnode *var;
-
- ok = TRUE;
- /* For all variables */
- for (var = first(&vars); ok && succ(var); var = succ(var))
- {
- short end = VAR_END;
- char name[VARLEN], expr[EXPRLEN];
- value vv = get_var_name(var->ln_Name);
-
- name[VARLEN - 1] = '\0';
- strncpy(name, var->ln_Name, VARLEN - 1);
- if (vv) decompile(vv, expr, EXPRLEN);
- else expr[0] = '\0';
-
- tag = VAR_TAG;
-
- ok = WRITE(f, tag) &&
- WRITE(f, name) &&
- WRITE(f, expr) &&
- WRITE(f, end);
- }
- tag = FILE_END;
- if (ok) ok = WRITE(f, tag);
- }
- fclose(f);
- if (!ok) message(g, "Error writing file", (char *)NULL);
- else vars_saved = TRUE;
- }
- else
- message(g, "Couldn't open file", file, (char *)NULL);
- }
-
- /* Handle variable requester. Could it be cleaned up ??? */
- int vars_handler(struct Gadget *gg, ULONG class, struct Requester *req, struct
- graph *g)
- {
- int id = gg->GadgetID;
- int change = FALSE; /* Has the list changed ? */
- int actval = FALSE; /* Activate variable value gadget */
- int actvar = FALSE; /* " " name " */
- int refresh = FALSE; /* value & name gadgets have changed */
- UWORD valpos, varpos;
- struct Gadget *varg = ListStr(var_info); /* The lists string gadget */
-
- if (gg == valg) /* Value gadget message, class is always GADGETUP */
- {
- valpos = RemoveGList(req->RWindow, valg, 1);
- varpos = RemoveGList(req->RWindow, varg, 1);
- refresh = TRUE;
- strip(var); /* remove blanks */
- strlwr(var);
- if (*var)
- {
- value vv = compile(val), old;
-
- if (eval_error != 0) /* Invalid value, allow correction */
- {
- DisplayBeep(req->RWindow->WScreen);
- actval = TRUE;
- }
- else /* Try & set variable */
- {
- if (old = get_var_name(var)) free_expr(old);
- else /* list changes, there will be an extra var */
- change = TRUE;
-
- check_vars(var);
- if (!set_var_name(var, vv))
- {
- alert(g->io.win, "Couldn't create variable", NULL);
- change = FALSE;
- }
- val[0] = var[0] = '\0';
- actvar = TRUE;
- }
- }
- else /* blank var name -- erase val */
- {
- DisplayBeep(req->RWindow->WScreen);
- actvar = TRUE;
- }
- }
- else if (id == VARSDEL) /* Delete selected */
- {
- value vv;
-
- valpos = RemoveGList(req->RWindow, valg, 1);
- varpos = RemoveGList(req->RWindow, varg, 1);
- refresh = TRUE;
- strip(var);
- strlwr(var);
- if (*var && (vv = get_var_name(var)))
- {
- free_expr(vv);
- free_var_name(var);
- change = TRUE;
- check_vars(var);
- }
- var[0] = val[0] = '\0';
- actvar = TRUE;
- }
- else if (id == VARSLIST) /* Something in list selected */
- {
- if (ModifyList(gg, req, req->RWindow, class == GADGETUP) != 0 && *var)
- { /* New value selected from list or typed, ie new name. Switch to va
- lue gadget */
- value vv;
-
- valpos = RemoveGList(req->RWindow, valg, 1);
- varpos = RemoveGList(req->RWindow, varg, 1);
- refresh = TRUE;
- strip(var);
-
- if (!(vv = get_var_name(var)) || !decompile(vv, val, EXPRLEN)) val[
- 0] = '\0';
- actval = TRUE;
- }
- }
- else
- return std_ghandler(gg, class, req, g);
-
- /* Handle requester services */
- if (refresh)
- {
- AddGList(req->RWindow, varg, varpos, 1, req);
- AddGList(req->RWindow, valg, valpos, 1, req);
- RefreshGList(valg, req->RWindow, req, 1);
- RefreshGList(varg, req->RWindow, req, 1);
- }
-
- if (change) /* Variable list changed */
- if (!ChangeList(var_info, &vars, req, req->RWindow))
- {
- EndRequest(req, req->RWindow);
- /* Not enough memory ... */
- actval = actvar = FALSE;
- }
-
- if (actval) ActivateGadget(valg, req->RWindow, req);
- if (actvar) ActivateGadget(varg, req->RWindow, req);
- vars_saved = FALSE;
-
- return FALSE;
- }
-
- /* Setup variables requester */
- void enter_vars(struct graph *g)
- {
- struct Requester *req;
- struct Memory *m;
- struct Gadget *gl = NULL;
-
- if ((m = NewMemory()) &&
- (req = InitReq(50, 20, 285, 126, m)) &&
- SetReqBorder(req, 1, m) &&
- AddIntuiText(&req->ReqText, "Edit variables", 86, 6, m) &&
- (var_info = AddList(&gl, VARSLIST, "Variables", &vars, var, VARLEN, 0,
- RELVERIFY, 20, 20, 160, 80, TRUE, m)) &&
- (valg = AddText(&gl, VARSLIST, "Value", FALSE, val, EXPRLEN, TRUE, 0, R
- ELVERIFY, 64, 110, 116, 10, TRUE, m)) &&
- AddBox(&gl, TRUE, "Ok", 0, RELVERIFY | ENDGADGET, 200, 23, 65, 15, FALS
- E, m) &&
- AddBox(&gl, VARSDEL, "Delete", 0, RELVERIFY, 200, 86, 65, 15, FALSE, m)
- )
- {
- var[0] = val[0] = '\0';
- SetReqGadgets(req, gl);
- DoRequest(req, g, vars_handler);
- /* vars_handler called for every gadget event */
- }
- Free(m);
- }
-
- /* Create a new graph */
- static struct graph *add_graph(struct graph *from)
- {
- struct graph *g = new_graph(from);
-
- if (g) add_head(&graph_list, g);
-
- return g;
- }
-
- /* Delete a graph, checking for save */
- static void remove_graph(struct graph *g)
- {
- if (!g->saved) save_file(g);
- remove(g);
- delete_graph(g);
- }
-
- /* Global initialisation */
- static int init(void)
- {
- if (GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 0))
- if (DiskfontBase = (struct Library *)OpenLibrary("diskfont.library", 0)
- )
- if (IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.
- library", 33))
- if (LayersBase = (struct LayersBase *)OpenLibrary("layers.libra
- ry", 33))
- if (ArpBase = (struct ArpBase *)OpenLibrary("arp.library",
- 0))
- {
- new_list(&graph_list);
- if (init_user() && init_grph() && add_graph(NULL))
- if (init_expr())
- {
- init_context(&vars);
- set_context(&vars);
- return TRUE;
- }
- else alert(NULL, "Expression init failed", "No memo
- ry ?");
- }
- else alert(NULL, "arp.library required", NULL);
- else alert(NULL, "layers.library V1.2 required", NULL);
- else alert(NULL, "intuition.library V1.2 required", NULL);
- else alert(NULL, "diskfont.library required", NULL);
- else alert(NULL, "graphics.library required", NULL);
-
- return FALSE;
- }
-
- /* Free ALL resources ! */
- static void clean_up(void)
- {
- struct graph *g, *next;
-
- cleanup_expr();
- cleanup_grph();
- cleanup_user();
-
- for (g = first(&graph_list); next = succ(g); g = next) remove_graph(g);
-
- if (ArpBase) CloseLibrary((struct Library *)ArpBase);
- if (LayersBase) CloseLibrary((struct Library *)LayersBase);
- if (IntuitionBase) CloseLibrary((struct Library *)IntuitionBase);
- if (DiskfontBase) CloseLibrary((struct Library *)DiskfontBase);
- if (GfxBase) CloseLibrary((struct Library *)GfxBase);
-
- #ifdef DEBUG
- TrackerExitReport();
- #endif
- }
-
- void main(int argc, char **argv)
- {
- struct cmd cmd;
- int done = FALSE;
-
- if (init())
- do
- switch ((cmd = next_command()).command)
- {
- case close:
- done = succ(succ(first(&graph_list))) == NULL; /* one graph
- left ? */
- if (done && !vars_saved) save_variables(cmd.g);
- remove_graph(cmd.g);
- break;
- case _new_graph:
- add_graph(cmd.g);
- break;
- case _load_graph:
- load_file(cmd.g);
- break;
- case _save_graph:
- save_file(cmd.g);
- break;
- case print_graph:
- prt_graph(cmd.g);
- break;
- case iff_graph:
- iff_todisk(cmd.g);
- break;
- case save_vars:
- save_variables(cmd.g);
- break;
- case load_vars:
- load_variables(cmd.g);
- break;
- case quit:
- if (!vars_saved) save_variables(cmd.g);
- done = TRUE;
- break;
- case add_function:
- select_object(cmd.g, add_object(cmd.g, new_function(cmd.g))
- );
- break;
- case add_label:
- add_object(cmd.g, (struct object *)new_label(cmd.g, cmd.dat
- a.pt.x, cmd.data.pt.y));
- break;
- case del_object:
- remove_object(cmd.g, cmd.data.o);
- break;
- case limits:
- enter_limits(cmd.g);
- break;
- case axes:
- enter_axes(cmd.g);
- break;
- case zoom:
- zoom_in(cmd.g, cmd.data.zoom_in.x0, cmd.data.zoom_in.y0, cm
- d.data.zoom_in.x1, cmd.data.zoom_in.y1);
- break;
- case zoom_out:
- zoom_factor(cmd.g, cmd.data.zoom_out);
- break;
- case center:
- center_graph(cmd.g, cmd.data.pt.x, cmd.data.pt.y);
- break;
- case edit:
- {
- struct Region *ref;
-
- if (cmd.data.o->edit(cmd.data.o, &ref))
- {
- cmd.g->saved = FALSE;
- refresh_graph(cmd.g, TRUE, ref);
- }
- }
- break;
- case improve:
- refresh_graph(cmd.g, TRUE, cmd.data.o->improve(cmd.data.o))
- ;
- break;
- case edit_vars:
- enter_vars(cmd.g);
- draw_all();
- break;
- }
- while (!done);
-
- clean_up();
- }
-
-