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.
- */
-
- /* User interface routines */
-
- #include <exec/types.h>
- #include <exec/interrupts.h>
- #include <exec/ports.h>
- #include <exec/io.h>
- #include <exec/interrupts.h>
- #include <devices/input.h>
- #include <devices/inputevent.h>
- #define INTUITIONPRIVATE
- #include <intuition/intuitionbase.h>
- #include <intuition/intuition.h>
- #include <graphics/text.h>
- #include <libraries/diskfont.h>
- #include "libraries/arpbase.h"
- #include <math.h>
- #include <stdio.h>
- #include <string.h>
- #include <assert.h>
- #include <dos.h>
- #include <stdarg.h>
- #include <ctype.h>
-
- #include "uio.h"
- #include "graph.h"
- #include "grph.h"
- #include "list.h"
- #include "object.h"
- #include "user/gadgets.h"
- #include "tracker.h"
-
- #include <proto/exec.h>
- #include <proto/intuition.h>
- #include <proto/graphics.h>
- #include <proto/diskfont.h>
- #define NODOS
- #include "proto/arp.h"
-
- #define DEFAVAILSIZE 2048 /* Default space reserved for AvailFonts */
- #define ARROW 42 /* Identifier of arrow gadget */
- #define CROSS 666 /* Identifer of cross gadget */
-
- struct fnode /* font node */
- {
- tnode node;
- char name[FONTLEN];
- };
-
- tlist flist;
-
- extern struct IntuitionBase *IntuitionBase;
-
- /* Default graph window */
- static struct NewWindow graph_win = {
- 0, 0,
- 640, 200,
- -1, -1,
- RAWKEY | REFRESHWINDOW | CLOSEWINDOW | MENUPICK | GADGETDOWN | GADGETUP | R
- EQCLEAR | REQSET | MOUSEBUTTONS | MOUSEMOVE,
- WINDOWSIZING | WINDOWDRAG | WINDOWDEPTH | WINDOWCLOSE | SIMPLE_REFRESH | AC
- TIVATE,
- NULL,
- NULL,
- "Graph",
- NULL,
- NULL,
- 85, 60,
- -1, -1,
- WBENCHSCREEN
- };
-
- /* The two icon images */
- static UWORD chip arrow_data[] = {
- 0x7fff, 0x7fff, 0x601f, 0x603f, 0x607f, 0x607f, 0x603f, 0x661f, 0x6f0f, 0x7
- f87, 0x7fc3, 0x7fe3, 0x7fff,
- 0x0000, 0x0000, 0x1fe0, 0x1fc0, 0x1f80, 0x1f80, 0x1fc0, 0x19e0, 0x10f0, 0x0
- 078, 0x003c, 0x001c, 0x0000
- };
-
- static struct Image arrow_image = {
- -1, 0, 16, 13, 2,
- arrow_data,
- 3, 0
- };
-
- static struct Gadget arrow = {
- NULL,
- -18, 18, 15, 13,
- GADGHCOMP | GADGIMAGE | GRELRIGHT,
- RELVERIFY | RIGHTBORDER | TOGGLESELECT,
- BOOLGADGET,
- (APTR)&arrow_image, NULL, NULL,
- 2,
- NULL,
- ARROW
- };
-
- static UWORD chip cross_data[] = {
- 0x7fff, 0x7f7f, 0x7f7f, 0x7f7f, 0x7f7f, 0x7e3f, 0x4081, 0x7e3f, 0x7f7f, 0x7
- f7f, 0x7f7f, 0x7f7f, 0x7fff,
- 0x0000, 0x0080, 0x0080, 0x0080, 0x0080, 0x01c0, 0x3f7e, 0x01c0, 0x0080, 0x0
- 080, 0x0080, 0x0080, 0x0000
- };
-
- static struct Image cross_image = {
- -1, 0, 16, 13, 2,
- cross_data,
- 3, 0
- };
-
- static struct Gadget cross = {
- NULL,
- -18, 36, 15, 13,
- GADGHCOMP | GADGIMAGE | GRELRIGHT | SELECTED,
- RELVERIFY | RIGHTBORDER | TOGGLESELECT,
- BOOLGADGET,
- (APTR)&cross_image, NULL, NULL,
- 1,
- NULL,
- CROSS
- };
-
- static struct Memory *abort_mem; /* for abort requester */
-
- static struct TextAttr alert_attr = { "topaz.font", 8 };
- static struct TextFont *alert_font;
-
- static struct Task *me;
- static struct MsgPort *inputDevPort; /* for input device */
- static struct IOStdReq *inputRequestBlock;
- static struct Interrupt handlerStuff;
- static int inputOpen;
-
- static long window_sigs; /* Combined sigs of all windows */
-
- static struct TextAttr font = { "topaz.font", 8 }; /* font for menus, requester
- s, etc */
- static struct Requester *req; /* Current requester */
- static int ok; /* Value of last GadgetID */
- static short reqdone; /* Req must go away. Don't activate next str g
- adget */
- static gadgevent *gadgethandler; /* Handler for gadget events */
-
- /* Add .font extension to fname (assumed of size FONTLEN) */
- char *addfont(char *fname)
- {
- return strncat(fname, ".font", FONTLEN - 1 - strlen(fname));
- }
-
- /* Removes .font extension if present */
- char *remfont(char *fname)
- {
- int l = strlen(fname);
-
- if (l >= 5 && strcmp(&fname[l - 5], ".font") == 0) fname[l - 5] = '\0';
-
- return fname;
- }
-
- /* Make a list of font names, one entry per font. Sizes, etc ignored. */
- int make_font_list(void)
- {
- int ok = FALSE;
- char *abuf;
-
- new_list(&flist);
- if (abuf = AllocMem(DEFAVAILSIZE, 0L)) /* Alloc default avail buffer */
- {
- int needs = AvailFonts(abuf, DEFAVAILSIZE, AFF_MEMORY | AFF_DISK);
-
- ok = TRUE;
- if (needs != 0) /* Need a bigger buffer */
- {
- FreeMem(abuf, DEFAVAILSIZE);
- if (abuf = AllocMem(DEFAVAILSIZE + needs, 0L))
- if (AvailFonts(abuf, DEFAVAILSIZE + needs, AFF_MEMORY | AFF_DIS
- K))
- ok = FALSE; /* Definite failure */
- }
- if (ok) /* Construct font list */
- {
- struct AvailFontsHeader *hdr = (struct AvailFontsHeader *)abuf;
- struct AvailFonts *fl = (struct AvailFonts *)(hdr + 1);
- int i;
-
- /* Add font entries to sorted list, by name. Duplicate entries remo
- ved */
- for (i = hdr->afh_NumEntries; i > 0; i--, fl++)
- {
- struct fnode *scan;
- char *name = fl->af_Attr.ta_Name;
- int cmp = -1;
-
- remfont(name); /* remove extension */
-
- /* Find insertion position */
- for (scan = first(&flist); succ(scan) && (cmp = strcmp(name, sc
- an->name)) > 0; scan = succ(scan))
- ;
- if (cmp != 0) /* Not already present, add to list */
- {
- struct fnode *n = alloc_node(sizeof(struct fnode));
-
- if (!n)
- {
- ok = FALSE;
- break;
- }
- n->node.ln_Name = n->name;
- n->name[FONTLEN - 1] = '\0';
- strncpy(n->name, name, FONTLEN - 1);
-
- /* Add at correct position */
- insert(&flist, n, scan->node.ln_Pred);
- }
- }
- if (!ok)
- {
- free_list((list *)&flist, sizeof(struct fnode));
- new_list(&flist);
- }
- }
- FreeMem(abuf, DEFAVAILSIZE + needs);
- }
- if (!ok) nomem(NULL);
- return ok;
- }
-
-
- /* Implement mutual exclude seeing Intuition is lazy */
- /* (for border gadgets) */
- /* ------------------------------------------------- */
- static void MutualExclude(struct Gadget *us, struct Gadget *gadg, struct Window
- *win)
- {
- register int i;
- register struct Gadget *gp;
- register LONG mutex = us->MutualExclude;
- UWORD pos;
-
- /* scan gadget list */
- for (i = 1, gp = gadg; gp && i != 0; i <<= 1, gp = gp->NextGadget)
- if (i & mutex)
- {
- pos = RemoveGadget(win, gp);
- gp->Flags &= ~SELECTED; /* unselect */
- AddGadget(win, gp, pos);
- }
- pos = RemoveGadget(win, us);
- us->Flags |= SELECTED;
- AddGadget(win, us, pos);
-
- RefreshWindowFrame(win); /* This works for border gadgets */
- }
-
- /* Implement mutual exclude seeing Intuition is lazy */
- /* (for requester gadgets) */
- static void MutEx(struct Gadget *us, struct Requester *req)
- {
- register int nb = 0, doneus = FALSE;
- register struct Gadget *gp, *first = NULL;
- register LONG mutex = us->MutualExclude;
- UWORD pos;
-
- /* scan gadget list */
- for (gp = req->ReqGadget; gp && (mutex != 0 || !doneus); mutex >>= 1, gp =
- gp->NextGadget)
- {
- if ((mutex & 1) || (doneus = gp == us))
- {
- if (!first) first = gp;
- pos = RemoveGList(req->RWindow, gp, 1);
- if (gp == us)
- gp->Flags |= SELECTED; /* select */
- else
- gp->Flags &= ~SELECTED; /* unselect */
- AddGList(req->RWindow, gp, pos, 1, req);
- }
- if (first) nb++;
- }
- if (first) RefreshGList(first, req->RWindow, req, nb);
- }
-
- /* Display requester, & handle everything until it goes away */
- int DoRequest(struct Requester *r, struct graph *g, gadgevent *handle)
- {
- r->Flags |= NOISYREQ; /* We want keystrokes */
-
- ok = FALSE;
- if (Request(r, g->io.win))
- {
- /* setup vital info */
- gadgethandler = handle;
- req = r;
- reqdone = FALSE;
- while (next_command().command != reqgone) ; /* Wait till it leaves */
- req = NULL; /* No req. present */
- gadgethandler = NULL;
- }
- return ok;
- }
-
- /* Find first string gadget */
- static struct Gadget *NextText(struct Gadget *look)
- {
- while (look && (look->GadgetType & ~GADGETTYPE) != STRGADGET) look = look->
- NextGadget;
- return look;
- }
-
- /* Default gadget handler, activates string gadgets in sequence & handles
- mutual exclude. Will normally be called by custom handlers if they don't
- have anything special to do.
- Returens the new value of ok */
- int std_ghandler(struct Gadget *gg, ULONG class, struct Requester *req, struct
- graph *g)
- {
- if ((gg->GadgetType & ~GADGETTYPE) == STRGADGET && !reqdone) /* Activate ne
- xt one */
- {
- struct Gadget *ng = NextText(gg->NextGadget);
- if (!ng) ng = NextText(req->ReqGadget);
- if (ng) ActivateGadget(ng, req->RWindow, req);
- }
- else if (gg->MutualExclude != 0) MutEx(gg, req);
-
- return gg->GadgetID != 0;
- }
-
- /* Insert ins in front of into, checking for string overflow
- ( sizeof(into)=maxlen ) */
- static char *strinsert(char *into, char *ins, int maxlen)
- {
- int delta = strlen(ins);
- int start = strlen(into);
- int i;
-
- if (start + delta >= maxlen) start = maxlen - delta - 1;
-
- for (i = start - 1; i >= 0; i--) into[i + delta] = into[i];
- into[start + delta] = '\0';
- memcpy(into, ins, delta);
-
- return into;
- }
-
- /* Convert a lock to a path, store in to (maxlen chars long) */
- static char *pathstr(char *to, long l, int maxlen)
- {
- long tl;
- int notfirst = FALSE;
- struct FileInfoBlock *fib = (struct FileInfoBlock *)AllocMem(sizeof(struct
- FileInfoBlock), 0);
-
- if (!fib) return(NULL);
- to[0] = '\0';
-
- do {
- if (!Examine(l, fib))
- {
- to = NULL;
- goto error;
- }
- if (fib->fib_DirEntryType > 0) strinsert(to, "/", maxlen);
- /* Is this still necessary ? */
- if (fib->fib_FileName[0] == '\0') strinsert(to, "RAM", maxlen);
- else strinsert(to, fib->fib_FileName, maxlen);
- tl = l;
- l = ParentDir(l);
- if (notfirst) UnLock(tl); /* Release allocated locks */
- notfirst = TRUE;
- } while (l);
-
- *(strchr(to, '/')) = ':'; /* First name is disk name */
-
- error:
- FreeMem((char *)fib, sizeof(struct FileInfoBlock));
- return(to);
- }
-
- /* Request a file from the user (save in file), return TRUE if OK,
- FALSE if cancelled or failed. Currently uses arp file requester. */
- int getfile(char *file, char *msg)
- {
- static char directory[DSIZE + 1];
- static struct FileRequester FR;
- char filename[FCHARS + 1];
-
- filename[0] = '\0';
- FR.fr_Hail = msg;
- FR.fr_File = filename;
- FR.fr_Dir = directory;
-
- if (FileRequest(&FR))
- {
- long lock = Lock(directory, SHARED_LOCK);
-
- if (lock)
- {
- if (!pathstr(file, lock, FILELEN)) /* get dir path */
- {
- UnLock(lock);
- return FALSE;
- }
- strncat(file, filename, FILELEN - 1 - strlen(file));
-
- UnLock(lock);
- return TRUE;
- }
- else
- alert(NULL, "Failed to lock directory", directory);
- }
- return FALSE;
- }
-
- /* Setup an "abort" requester, in graph g with text msg (must be as long as max
- message) */
- struct Requester *abort_request(struct graph *g, char *msg)
- {
- int len = strlen(msg);
- struct Requester *req;
- struct Gadget *gl = NULL;
- int height, width;
- static struct Gadget text = {
- NULL,
- 10, 10, 1, 1,
- GADGHNONE, 0L, BOOLGADGET | REQGADGET
- };
-
- /* Construct requester */
- height = 8 * 1 + 10 + 12 + 25;
- width = 8 * len + 2 * 10;
- if (width < 85) width = 85;
-
- text.GadgetText = NULL;
- if ((abort_mem = NewMemory()) &&
- (req = InitReq(50, 15, width, height, abort_mem)) &&
- SetReqBorder(req, 1, abort_mem) &&
- AddBox(&gl, TRUE, "Stop!", 0, RELVERIFY, (width - 65) / 2, height - 25,
- 65, 15, FALSE, abort_mem) &&
- AddIntuiText(&text.GadgetText, msg, 0, 0, abort_mem))
- {
- SetReqGadgets(req, gl);
- text.NextGadget = req->ReqGadget;
- req->ReqGadget = &text;
- if (!Request(req, g->io.win)) req = NULL; /* display req */
- }
- else
- req = NULL;
-
- if (!req) Free(abort_mem);
-
- return req;
- }
-
- /* Change abort requester message. msg must not be longer than the first msg */
-
- void set_abort_msg(struct Requester *req, char *msg)
- {
- req->ReqGadget->GadgetText->IText = msg;
- RefreshGList(req->ReqGadget, req->RWindow, req, 1);
- }
-
- /* Clear abort requester */
- void end_abort_request(struct Requester *req)
- {
- EndRequest(req, req->RWindow);
- Free(abort_mem);
- }
-
- /* Has the user asked for an abort ? */
- int aborted(struct Requester *req)
- {
- int abort = FALSE;
- struct IntuiMessage *msg;
-
- while (msg = (struct IntuiMessage *)GetMsg(req->RWindow->UserPort))
- {
- ULONG class = msg->Class;
-
- ReplyMsg((struct Message *)msg);
-
- if (class == REFRESHWINDOW) /* Ignore refreshes at this time */
- {
- BeginRefresh(req->RWindow);
- EndRefresh(req->RWindow, TRUE);
- }
- else if (class == GADGETUP) abort = TRUE;
- }
- return abort;
- }
-
- /* Display a message in graph g. You pass as many string as you want, followed
- by (char *)NULL. This will try very hard to actually display it, calling
- alert with the first two strings if it fails. */
- void message(struct graph *g, ...)
- {
- int nb, len;
- va_list msgs;
- char *scan;
- struct Memory *m;
- struct Requester *req;
- struct Gadget *gl = NULL;
- int height, width;
- int ok = FALSE;
-
- /* Find number of lines and maxmimum length */
- nb = 0; len = 0;
- va_start(msgs, g);
- while (scan = va_arg(msgs, char *))
- {
- int nl = strlen(scan);
-
- nb++;
- if (nl > len) len = nl;
- }
- va_end(msgs);
-
- /* Construct requester */
- height = 8 * nb + 10 + 12 + 25;
- width = 8 * len + 2 * 10;
- if (width < 85) width = 85;
-
- if ((m = NewMemory()) &&
- (req = InitReq(50, 15, width, height, m)) &&
- SetReqBorder(req, 1, m) &&
- AddBox(&gl, TRUE, "Ok", 0, RELVERIFY | ENDGADGET, (width - 65) / 2, hei
- ght - 25, 65, 15, FALSE, m))
- {
- int y = 10 - 8;
-
- ok = TRUE;
- SetReqGadgets(req, gl);
-
- /* Add message strings */
- va_start(msgs, g);
- while (ok && (scan = va_arg(msgs, char *)))
- ok = ok && AddIntuiText(&req->ReqText, scan, 10, (y += 8), m);
- va_end(msgs);
-
- /* You'll have a surprise if you press Amiga-B ... */
- if (ok && g) ok = DoRequest(req, g, std_ghandler);
- }
- Free(m);
- if (!ok || !g) /* call alert */
- {
- va_start(msgs, g);
- if (nb == 1)
- alert(g ? g->io.win : NULL, va_arg(msgs, char *), NULL);
- else if (nb >= 2)
- {
- char *m1 = va_arg(msgs, char *);
- char *m2 = va_arg(msgs, char *);
-
- alert(g ? g->io.win : NULL, m1, m2);
- }
- }
- }
-
- /* Display a two line auto request. Doesn't alloc any resources */
- void alert(struct Window *win, char *msg1, char *msg2)
- {
- struct IntuiText text1, text2, negative;
- const static struct IntuiText template = {
- 0, 1, JAM1,
- 8, 0,
- &alert_attr
- };
- int width, height;
- int ysize = alert_font ? alert_font->tf_YSize : 8;
-
- text1 = text2 = negative = template;
- text1.TopEdge = 8;
- text1.IText = msg1;
- width = IntuiTextLength(&text1) + 20;
- height = 37 + 2 * ysize;
- if (msg2 != NULL)
- {
- int w;
-
- text1.NextText = &text2;
- text2.TopEdge = text1.TopEdge + ysize;
- text2.IText = msg2;
-
- height += ysize;
- w = IntuiTextLength(&text2) + 20;
- if (w > width) width = w;
- }
- negative.LeftEdge = 6;
- negative.TopEdge = 4;
- negative.IText = "Ok";
-
- AutoRequest(win, &text1, NULL, &negative, 0L, 0L, width, height);
- }
-
- /* Easy no mem requester */
- void nomem(struct Window *win)
- {
- alert(win, "No memory !", NULL);
- }
-
- /* Return next menu selection that is a command (in graph g).
- *choice is the item number of the next menu selection */
- static struct cmd process(UWORD *choice, struct graph *g)
- {
- struct MenuItem *item;
- UWORD itemnb, subnb;
- struct cmd cmd;
- struct pos *rect = (struct pos *)g->s.current;
-
- /* Prepare command */
- cmd.command = none;
- cmd.g = g;
-
- /* Try & find a command */
- while (cmd.command == none && *choice != MENUNULL)
- {
- item = ItemAddress(g->io.menu, *choice);
- itemnb = ITEMNUM(*choice);
- subnb = SUBNUM(*choice);
-
- /* Rem: illegal choices are disabled ==> no checking here */
- switch (MENUNUM(*choice)) {
- case 0 : switch (itemnb) { /* Project */
- case 0 : /* New Graph */
- cmd.command = _new_graph;
- break;
- case 1 : /* Delete Graph */
- cmd.command = close;
- break;
- case 2 : /* Load Graph */
- cmd.command = _load_graph;
- break;
- case 3 : /* Save Graph */
- cmd.command = _save_graph;
- break;
- case 4 : /* Output Graph */
- switch (subnb)
- {
- case 0 : /* To Printer */
- cmd.command = print_graph;
- break;
- case 1 : /* To Disk */
- cmd.command = iff_graph;
- break;
- }
- break;
- case 6 : /* Load Variables */
- cmd.command = load_vars;
- break;
- case 7 : /* Save Variables */
- cmd.command = save_vars;
- break;
- case 9 : /* Quit */
- cmd.command = quit;
- break;
- } break;
-
- case 1 : switch (itemnb) { /* Graph */
- case 0 : /* Scale */
- deselect(g);
- cmd.command = limits;
- break;
- case 1 : /* Axes */
- deselect(g);
- cmd.command = axes;
- break;
- case 2 : /* Zoom */
- cmd.command = zoom;
- cmd.data.zoom_in.x0 = rect->x0;
- cmd.data.zoom_in.y0 = rect->y0;
- cmd.data.zoom_in.x1 = rect->x1;
- cmd.data.zoom_in.y1 = rect->y1;
- deselect(g);
- break;
- case 3 : /* Zoom Out */
- cmd.command = zoom_out;
- cmd.data.zoom_out = 2.0;
- break;
- case 4 : /* Center */
- cmd.command = center;
- cmd.data.pt.x = rect->x0;
- cmd.data.pt.y = rect->y0;
- deselect(g);
- break;
- } break;
-
- case 2 : switch (itemnb) { /* Add */
- case 0 : /* Function */
- deselect(g);
- cmd.command = add_function;
- break;
- case 1 : /* Label */
- cmd.command = add_label;
- cmd.data.pt.x = rect->x0;
- cmd.data.pt.y = rect->y0;
- deselect(g);
- break;
- } break;
-
- case 3 : switch (itemnb) { /* Edit */
- case 0 : /* Variables */
- cmd.command = edit_vars;
- break;
- case 2 : /* Select function */
- { /* Processed locally */
- struct object *o;
-
- if (o = choose_object(g, "Select"))
- {
- deselect(g);
- select_object(g, o);
- }
- }
- break;
- case 3 : /* Deselect */
- /* Processed locally */
- deselect(g);
- break;
- case 5 : /* Edit */
- cmd.data.o = g->s.current;
- cmd.command = edit;
- break;
- case 6 : /* Improve */
- cmd.data.f = g->s.current;
- cmd.command = improve;
- break;
- case 7 : /* Delete */
- cmd.data.o = g->s.current;
- cmd.command = del_object;
- break;
- } break;
- }
- *choice = item->NextSelect;
- *choice = MENUNULL;
- }
- return cmd;
- }
-
- /* Return next command (in any graph) */
- struct cmd next_command(void)
- {
- struct cmd cmd;
- static int gone = FALSE;
-
- cmd.command = none;
-
- while (cmd.command == none) /* Wait for one */
- {
- struct graph *g;
-
- /* Scan all graphs, checking for commands */
- for (g = first(&graph_list); cmd.command == none && succ(g); g = succ(g
- ))
- {
- int moved = FALSE;
- struct IntuiMessage *msg;
- WORD sx, sy;
-
- cmd.g = g;
- /* Any pending menu selections ? */
- if (!req && g->io.nextmenu != MENUNULL) cmd = process(&g->io.nextme
- nu, g);
-
- /* Check for messages on window */
- while (cmd.command == none && (msg = (struct IntuiMessage *)GetMsg(
- g->io.win->UserPort)))
- {
- /* Save interesting info */
- ULONG class = msg->Class;
- UWORD code = msg->Code;
- UWORD qualifier = msg->Qualifier;
- struct Gadget *gg = (struct Gadget *)msg->IAddress, *gadg;
-
- sx = msg->MouseX; sy = msg->MouseY;
- ReplyMsg((struct Message *)msg);
-
- if (class == MOUSEMOVE) /* Accumulate moves */
- moved = TRUE;
- else
- {
- if (moved) mouse_move(g, sx, sy); /* process any mouse move
- ment */
- moved = FALSE;
- /* Most messages imply that the mouse button is released. M
- ake sure that the program thinks so */
- if (class != MOUSEBUTTONS && class != REFRESHWINDOW) mouse_
- up(g, sx, sy);
-
- switch (class)
- {
- /* Note that most messages are ignored while a
- requester is up in *any* window */
-
- case RAWKEY:
- /* Check for Amiga-V/B (Ok, Cancel shortcut) */
- if (req && (qualifier & AMIGALEFT) && (code == KEYC
- ODE_V || code == KEYCODE_B))
- {
- ok = code == KEYCODE_V;
- /* Never let this happen while a string gadget
- is active ... */
- EndRequest(req, req->RWindow);
- }
- break;
- case CLOSEWINDOW:
- if (!req) cmd.command = close;
- break;
- case MENUPICK:
- if (!req)
- {
- g->io.nextmenu = code;
- cmd = process(&g->io.nextmenu, g);
- }
- break;
- case REFRESHWINDOW:
- {
- int changed;
-
- /* Refresh partially only if size hasn't change
- d */
- BeginRefresh(g->io.win);
- changed = g->io.win->Width != g->io.oldwidth ||
- g->io.win->Height != g->io.oldheight;
- if (!changed) draw_graph(g, FALSE); /* No messa
- ges during refresh !!! */
- EndRefresh(g->io.win, TRUE);
- if (changed)
- {
- set_scale(g);
- draw_graph(g, TRUE);
- }
- /* Wait for refresh after requester's disappear
- ance
- before signaling it */
- if (gone)
- {
- gone = FALSE;
- cmd.command = reqgone;
- }
- }
- break;
- case REQSET: /* Activate first string gadget */
- gadg = NextText(req->ReqGadget);
- if (gadg && !reqdone) ActivateGadget(gadg, g->io.wi
- n, req);
- break;
- case REQCLEAR:
- /* Allow 1 refresh before signaling this. There is
- probably a better way ! */
- gone = TRUE;
- break;
- case GADGETUP: case GADGETDOWN:
- /* Ack! Hack to avoid bug in string gadget activati
- on (V1.2-1.3) */
- if (class == GADGETUP && (gg->GadgetType & STRGADGE
- T) != 0 && IntuitionBase->LibNode.lib_Version <= 34) IntuitionBase->ActiveGadget
- = NULL;
-
- /* Handle requester hgadgets */
- if (gadgethandler) ok = gadgethandler(gg, class, re
- q, g);
- else if (gg->GadgetID == ARROW || gg->GadgetID == C
- ROSS)
- { /* Select new mode */
- MutualExclude(gg, g->io.gadgets, g->io.win);
- set_mode(g, gg->GadgetID == ARROW);
- }
- break;
- case MOUSEBUTTONS: /* Pass on to graph */
- if (code == SELECTDOWN)
- mouse_down(g, sx, sy);
- else
- mouse_up(g, sx, sy);
- break;
- }
- }
- }
- /* Handle any pending moves */
- if (moved) mouse_move(g, sx, sy);
- }
- /* Wait for something to happen */
- if (cmd.command == none) Wait(window_sigs);
- }
- return cmd;
- }
-
-
- /* Enable/Disable various menus */
-
- void disable_rect_menus(struct graph *g)
- {
- struct Window *win = g->io.win;
-
- OffMenu(win, SHIFTMENU(1) | SHIFTITEM(2) | SHIFTSUB(NOSUB)); /* Zoom */
- OffMenu(win, SHIFTMENU(1) | SHIFTITEM(4) | SHIFTSUB(NOSUB)); /* Center */
- OffMenu(win, SHIFTMENU(2) | SHIFTITEM(1) | SHIFTSUB(NOSUB)); /* Label */
- OffMenu(win, SHIFTMENU(3) | SHIFTITEM(3) | SHIFTSUB(NOSUB)); /* Deselect */
-
- }
-
- void enable_rect_menus(struct graph *g)
- {
- struct Window *win = g->io.win;
-
- OnMenu(win, SHIFTMENU(1) | SHIFTITEM(2) | SHIFTSUB(NOSUB)); /* Zoom */
- OnMenu(win, SHIFTMENU(1) | SHIFTITEM(4) | SHIFTSUB(NOSUB)); /* Center */
- OnMenu(win, SHIFTMENU(2) | SHIFTITEM(1) | SHIFTSUB(NOSUB)); /* Label */
- OnMenu(win, SHIFTMENU(3) | SHIFTITEM(3) | SHIFTSUB(NOSUB)); /* Deselect */
- }
-
- void disable_object_menus(struct graph *g)
- {
- struct Window *win = g->io.win;
-
- OffMenu(win, SHIFTMENU(3) | SHIFTITEM(3) | SHIFTSUB(NOSUB)); /* Deselect */
-
- OffMenu(win, SHIFTMENU(3) | SHIFTITEM(5) | SHIFTSUB(NOSUB)); /* Edit */
- OffMenu(win, SHIFTMENU(3) | SHIFTITEM(6) | SHIFTSUB(NOSUB)); /* Improve */
- OffMenu(win, SHIFTMENU(3) | SHIFTITEM(7) | SHIFTSUB(NOSUB)); /* Delete */
- }
-
- void enable_object_menus(struct graph *g)
- {
- struct Window *win = g->io.win;
-
- OnMenu(win, SHIFTMENU(3) | SHIFTITEM(3) | SHIFTSUB(NOSUB)); /* Deselect */
- OnMenu(win, SHIFTMENU(3) | SHIFTITEM(5) | SHIFTSUB(NOSUB)); /* Edit */
- OnMenu(win, SHIFTMENU(3) | SHIFTITEM(6) | SHIFTSUB(NOSUB)); /* Improve */
- OnMenu(win, SHIFTMENU(3) | SHIFTITEM(7) | SHIFTSUB(NOSUB)); /* Delete */
- }
-
- /* Convert double to nice string (must be of size NBLEN) */
- char *double2str(char *to, double x)
- {
- int l;
-
- if (x == NOVAL) to[0] = '\0';
- else sprintf(to, "%-5.3g", x);
-
- l = strlen(to);
- while (l > 0 && to[--l] == ' ') to[l] = '\0';
-
- return to;
- }
-
-
- /* Convert string to double */
- double str2double(char *from)
- {
- double x;
-
- if (sscanf(from, "%lf", &x) != 1) x = NOVAL;
-
- return x;
- }
-
- /* convert x to a string (must be of size INTLEN) */
- char *int2str(char *to, int x)
- {
- if (x == INOVAL) to[0] = '\0';
- else sprintf(to, "%d", x);
-
- return to;
- }
-
- /* convert string to integer */
- int str2int(char *from)
- {
- int x;
-
- if (sscanf(from, "%d", &x) != 1) x = INOVAL;
-
- return x;
- }
-
- /* Removes leading & trailing blanks fron name. Returns name */
- char *strip(char *name)
- {
- char *scan = name;
-
- while (isspace(*scan)) scan++;
-
- if (*scan)
- {
- char *copy = name;
-
- while (*scan) *(copy++) = *(scan++);
-
- while (isspace(*--copy))
- ;
- *(copy + 1) = '\0';
- }
- else
- *name = '\0';
-
- return name;
- }
-
- /* Hack to allow you to press Amiga-V/B even while entering a string in a
- string requester */
- static long __saveds __asm handle_ok_cancel(register __a0 struct InputEvent *ev
- , register __a1 void *dummy)
- {
- struct InputEvent *ep, *laste;
- static struct InputEvent retkey;
-
- if (req)
- /* run down the list of events to see if they pressed the magic key */
- for (ep = ev, laste = NULL; ep != NULL; ep = ep->ie_NextEvent)
- {
- if (ep->ie_Class == IECLASS_RAWKEY && (ep->ie_Qualifier & AMIGALEFT
- ) && (ep->ie_Code == KEYCODE_V || ep->ie_Code == KEYCODE_B) && IntuitionBase->Ac
- tiveWindow == req->RWindow)
- {
- reqdone = TRUE; /* The requester is going away */
- /* Add an extra "return key" event */
- retkey.ie_Class = IECLASS_RAWKEY;
- retkey.ie_SubClass = 0;
- retkey.ie_Code = 0x44; /* return key */
- retkey.ie_Qualifier = 0;
- retkey.ie_position = ep->ie_position;
- retkey.ie_TimeStamp = ep->ie_TimeStamp;
- retkey.ie_NextEvent = ep;
- /* we can handle this event so take it off the chain */
- if (laste == NULL)
- ev = &retkey;
- else
- laste->ie_NextEvent = &retkey;
- break;
- }
- else
- laste = ep;
- }
-
- /* pass on the pointer to the event */
- return (long)ev;
- }
-
- /* Create window, menus for a new graph */
- int init_uio(struct graph *g)
- {
- /* Create mode select gadgets */
- struct Gadget *a = AllocMem(sizeof(struct Gadget), 0L);
- struct Gadget *c = AllocMem(sizeof(struct Gadget), 0L);
-
- ModSys(0, 1, JAM2, &font);
- if (a && c)
- {
- struct Menu *ml = NULL, *project, *edit, *add, *graph;
- struct MenuItem *print;
-
- *a = arrow;
- *c = cross;
- a->NextGadget = c;
- g->io.gadgets = graph_win.FirstGadget = a;
- g->io.mem = NULL;
-
- /* Create window & menus */
- if (g->io.win = OpenWindow(&graph_win))
- if ((g->io.mem = NewMemory()) &&
- (project = AddMenu(&ml, NULL, "Project", MENUENABLED, g->io.mem
- )) &&
- AddItem(project, "New Graph", ITEMENABLED | HIGHCOMP, 0, 'N
- ', FALSE, g->io.mem) &&
- AddItem(project, "Delete Graph", ITEMENABLED | HIGHCOMP, 0,
- 0, FALSE, g->io.mem) &&
- AddItem(project, "Load Graph...", ITEMENABLED | HIGHCOMP, 0
- , 'O', FALSE, g->io.mem) &&
- AddItem(project, "Save Graph...", ITEMENABLED | HIGHCOMP, 0
- , 'S', FALSE, g->io.mem) &&
- (print = AddItem(project, "Output Graph", ITEMENABLED | HIG
- HCOMP, 0, 0, TRUE, g->io.mem)) &&
- AddSub(print, "To Printer", ITEMENABLED | HIGHCOMP, 0,
- 'P', g->io.mem) &&
- AddSub(print, "To Disk...", ITEMENABLED | HIGHCOMP, 0,
- 0, g->io.mem) &&
- AddRule(project, g->io.mem) &&
- AddItem(project, "Load Variables...", ITEMENABLED | HIGHCOM
- P, 0, 0, FALSE, g->io.mem) &&
- AddItem(project, "Save Variables...", ITEMENABLED | HIGHCOM
- P, 0, 0, FALSE, g->io.mem) &&
- AddRule(project, g->io.mem) &&
- AddItem(project, "Quit", ITEMENABLED | HIGHCOMP, 0, 'Q', FA
- LSE, g->io.mem) &&
- (graph = AddMenu(&ml, NULL, "Graph", MENUENABLED, g->io.mem)) &
- &
- AddItem(graph, "Scale...", ITEMENABLED | HIGHCOMP, 0, 'L',
- FALSE, g->io.mem) &&
- AddItem(graph, "Axes...", ITEMENABLED | HIGHCOMP, 0, 'X', F
- ALSE, g->io.mem) &&
- AddItem(graph, "Zoom", ITEMENABLED | HIGHCOMP, 0, 'Z', FALS
- E, g->io.mem) &&
- AddItem(graph, "Zoom out", ITEMENABLED | HIGHCOMP, 0, 0, FA
- LSE, g->io.mem) &&
- AddItem(graph, "Centre", ITEMENABLED | HIGHCOMP, 0, 'C', FA
- LSE, g->io.mem) &&
- (add = AddMenu(&ml, NULL, "Add", MENUENABLED, g->io.mem)) &&
- AddItem(add, "Function...", ITEMENABLED | HIGHCOMP, 0, 'F',
- FALSE, g->io.mem) &&
- AddItem(add, "Label...", ITEMENABLED | HIGHCOMP, 0, 0, FALS
- E, g->io.mem) &&
- (edit = AddMenu(&ml, NULL, "Edit", MENUENABLED, g->io.mem)) &&
- AddItem(edit, "Variables...", ITEMENABLED | HIGHCOMP, 0, 'V
- ', FALSE, g->io.mem) &&
- AddRule(edit, g->io.mem) &&
- AddItem(edit, "Select function...", ITEMENABLED | HIGHCOMP,
- 0, 0, FALSE, g->io.mem) &&
- AddItem(edit, "Deselect", ITEMENABLED | HIGHCOMP, 0, 0, FAL
- SE, g->io.mem) &&
- AddRule(edit, g->io.mem) &&
- AddItem(edit, "Edit...", ITEMENABLED | HIGHCOMP, 0, 'E', FA
- LSE, g->io.mem) &&
- AddItem(edit, "Improve", ITEMENABLED | HIGHCOMP, 0, 'I', FA
- LSE, g->io.mem) &&
- AddItem(edit, "Delete", ITEMENABLED | HIGHCOMP, 0, 0, FALSE
- , g->io.mem))
- {
- SetMenuStrip(g->io.win, ml);
- g->io.menu = ml;
- disable_rect_menus(g);
- disable_object_menus(g);
- /* Add signal bit */
- window_sigs |= 1 << g->io.win->UserPort->mp_SigBit;
-
- return TRUE; /* all done ok */
- }
- else
- {
- Free(g->io.mem);
- CloseWindow(g->io.win);
- alert(NULL, "No memory !", NULL);
- }
- else alert(NULL, "Couldn't open window", NULL);
- }
- else
- alert(NULL, "No memory !", NULL);
-
- if (a) FreeMem(a, sizeof(struct Gadget));
- if (c) FreeMem(c, sizeof(struct Gadget));
-
- return FALSE;
- }
-
- /* Close window, etc */
- void cleanup_uio(struct graph *g)
- {
- struct Gadget *gg, *next;
-
- ClearMenuStrip(g->io.win);
- CloseWindow(g->io.win);
- Free(g->io.mem);
- for (gg = g->io.gadgets; gg; gg = next)
- {
- next = gg->NextGadget;
- FreeMem(gg, sizeof(struct Gadget));
- }
- /* Construct new signal list */
- window_sigs = 0;
- for (g = first(&graph_list); succ(g); g = succ(g))
- window_sigs |= 1 << g->io.win->UserPort->mp_SigBit;
- }
-
- /* Global initialisation */
- int init_user()
- {
- if (!make_font_list()) return FALSE;
- /* Open alert font */
- alert_font = OpenFont(&alert_attr);
-
- /* Install input handler */
- me = FindTask(0);
- inputDevPort = CreatePort(0,0);
- if (inputDevPort)
- {
- if (inputRequestBlock = CreateStdIO(inputDevPort))
- {
-
- handlerStuff.is_Data = NULL;
- handlerStuff.is_Code = (void *)handle_ok_cancel;
- handlerStuff.is_Node.ln_Pri = 51;
-
- if (OpenDevice("input.device", 0, inputRequestBlock, 0) == 0)
- {
- inputOpen = TRUE;
- inputRequestBlock->io_Command = IND_ADDHANDLER;
- inputRequestBlock->io_Data = (APTR)&handlerStuff;
-
- DoIO(inputRequestBlock);
- return TRUE;
- }
- }
- }
- alert(NULL, "Couldn't install input handler", NULL);
- return FALSE;
- }
-
- /* Global cleanup */
- void cleanup_user()
- {
- if (inputOpen)
- {
- inputRequestBlock->io_Command = IND_REMHANDLER;
- inputRequestBlock->io_Data = (APTR)&handlerStuff;
- DoIO(inputRequestBlock);
- CloseDevice(inputRequestBlock);
- }
- if (inputRequestBlock) DeleteStdIO(inputRequestBlock);
- if (inputDevPort) DeletePort(inputDevPort);
- free_list((list *)&flist, sizeof(struct fnode));
- }
-
-