[comp.sources.amiga] v89i205: graph - plot mathematical functions, Part02/07

page%swap@Sun.COM (Bob Page) (11/13/89)

Submitted-by: dg3i+@andrew.cmu.edu (David Gay)
Posting-number: Volume 89, Issue 205
Archive-name: applications/graph.2

# This is a shell archive.
# Remove anything above and including the cut line.
# Then run the rest of the file through 'sh'.
# Unpacked files will be owned by you and have default permissions.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar: SHell ARchive
# Run the following text through 'sh' to create:
#	file.h
#	function.c
#	function.h
#	gadgets.c
#	gadgets.h
# This is archive 2 of a 7-part kit.
# This archive created: Sun Nov 12 18:23:29 1989
echo "extracting file.h"
sed 's/^X//' << \SHAR_EOF > file.h
X/*
X *                 GRAPH, Version 1.00 - 4 August 1989
X *
X *            Copyright 1989, David Gay. All Rights Reserved.
X *            This software is freely redistrubatable.
X */
X
X/* Tags for use in files */
X#ifndef FILE_H
X#define FILE_H
X
X#define FILE_TAG 114 /* Variable file */
X#define FILE_END 115
X#define VAR_TAG 116  /* Each variable */
X#define VAR_END 117
X#define GRAPH_TAG 100 /* Tag to recognise graphs in files */
X#define GRAPH_END 101 /* End of graph */
X#define LABEL_TAG 102 /* Labels */
X#define LABEL_END 103
X#define FUNCTION_TAG 104 /* Functions */
X#define FUNCTION_END 105
X#define F_OF_X_TAG 106 /* In each function, you have one of the following */
X#define F_OF_X_END 107
X#define X_Y_TAG 108
X#define X_Y_END 109
X#define R_OF_T_TAG 110
X#define R_OF_T_END 111
X#define R_T_TAG 112
X#define R_T_END 113
X
X/* Read/Write raw object from file */
X#define WRITE(file, what) fwrite((char *)&(what), sizeof(what), 1, (file))
X#define READ(file, what) fread((char *)&(what), sizeof(what), 1, (file))
X
X#endif
SHAR_EOF
echo "extracting function.c"
sed 's/^X//' << \SHAR_EOF > function.c
X/*
X *                 GRAPH, Version 1.00 - 4 August 1989
X *
X *            Copyright 1989, David Gay. All Rights Reserved.
X *            This software is freely redistrubatable.
X */
X
X/* The default/non virtual methods for class function */
X#include <exec/types.h>
X#include <intuition/intuition.h>
X#include <graphics/text.h>
X#include <math.h>
X#include <string.h>
X
X#include "object.h"
X#include "object/default.h"
X#include "object/function.h"
X#include "file.h"
X#include "graph.h"
X#include "uio.h"
X#include "coords.h"
X#include "list.h"
X#include "grph.h"
X#include "user/eval.h"
X#include "user/gadgets.h"
X#include "tracker.h"
X
X#include <proto/exec.h>
X#include <proto/intuition.h>
X#include <proto/graphics.h>
X
X/* Draw a function */
Xvoid display_function(struct function *this)
X{
X    int up;
X    point *pt;
X    struct RWindow *const rwin = this->o.g->io.rw;
X    int pen = this->selected ? (this->colour == 3 ? 2 : 3) : this->colour;
X
X    up = TRUE;
X
X    SetAPen(rwin->rp, pen);
X    SetDrMd(rwin->rp, JAM1);
X
X    /* Scan points (note that all types of function points have point as base c
Xlass) */
X    for (pt = first(&this->pts); succ(pt); pt = succ(pt))
X    {
X        if (pt->state & EXISTS)
X        {
X            if (up) RMove(rwin, pt->x, pt->y);
X            else RDraw(rwin, pt->x, pt->y);
X            up = this->showdisc && (pt->state & DISC);
X        }
X        else
X            up = TRUE;
X    }
X}
X
X/* Select function, redraw in new colour */
Xstatic void select_function(struct function *this)
X{
X    this->selected = TRUE;
X    if (this->o.ok && this->o.g->ok && this->o.g->io.rw && this->calc)
X        display_function(this);
X}
X
X/* Deselect function */
Xstatic struct Region *deselect_function(struct function *this)
X{
X    this->selected = FALSE;
X    if (this->o.ok && this->o.g->ok && this->o.g->io.rw && this->calc)
X        display_function(this);
X    return NULL; /* No refresh needed */
X}
X
X/* Did user press mouse on function ? */
Xstatic int down_function(struct function *this)
X{
X    int inside = FALSE;
X
X    if (this->o.ok && this->calc)
X    {
X        struct graph *g = this->o.g;
X        point *pt;
X        long sx = ftol(g->io.rw->sx(g->io.rw, g->s.x));
X        long sy = ftol(g->io.rw->sy(g->io.rw, g->s.y));
X        long x0, y0, x1, y1;
X        int up = TRUE;
X
X        /* Check if mouse "near" drawn line */
X        for (pt = first(&this->pts); succ(pt); pt = succ(pt))
X        {
X            if (pt->state & EXISTS)
X            {
X                x1 = ftol(g->io.rw->sx(g->io.rw, pt->x));
X                y1 = ftol(g->io.rw->sy(g->io.rw, pt->y));
X
X                if (!up) /* segment exists, calc distance to it */
X                {
X                    /* A little vectorial algebra */
X                    long ab_x, ab_y, u_x, u_y, h, hd, dist_x, dist_y, dist;
X
X                    ab_x = sx - x0; ab_y = sy - y0;
X                    u_x = x1 - x0; u_y = y1 - y0;
X                    h = (ab_x * u_x + ab_y * u_y);
X                    hd = (u_x * u_x + u_y * u_y);
X                    if (hd != 0 && 0 <= h && h <= hd) /* intersection on segmen
Xt */
X                    {
X                        dist_x = (hd * ab_x - h * u_x) / hd; dist_y = (hd * ab_
Xy - h * u_y) / hd;
X                        dist = dist_x * dist_x + dist_y * dist_y;
X                        if (dist < (FDIST * FDIST))
X                        {
X                            /* We're near segment ! */
X                            inside = TRUE;
X                            break;
X                        }
X                    }
X                    /* Near point ? */
X                    else if ((x1 - sx) * (x1 - sx) + (y1 - sy) * (y1 - sy) <= F
XDIST * FDIST)
X                    {
X                        inside = TRUE;
X                        break;
X                    }
X                }
X
X                up = this->showdisc && (pt->state & DISC);
X                x0 = x1; y0 = y1;
X            }
X            else
X                up = TRUE;
X
X        }
X    }
X    return inside;
X}
X
X/* Impossible ... */
Xstatic void move_function(struct function *this)
X{
X}
X
X/* Nothing to do */
Xstatic struct Region *up_function(struct function *this)
X{
X    return NULL;
X}
X
X/* redraw function, calc if necessary */
Xstatic void draw_function(struct function *this, int allow_mes)
X{
X    if (!this->calc) this->calc = this->calcf(this, allow_mes);
X    if (this->calc) display_function(this);
X}
X
X/* variable name changed. recalc necessary ? */
Xstatic void var_change_function(struct function *this, char *name)
X{
X    if (this->calc && FindName(&this->used, name))
X    {
X        free_list(&this->pts, this->sizept);
X        this->calc = FALSE;
X    }
X}
X
X/* Write function to file */
Xstatic int save_function(struct function *this, FILE *f)
X{
X    short tag = FUNCTION_TAG;
X    short end = FUNCTION_END;
X    short showdisc = this->showdisc; /* Can't write bitfields directly ... */
X    short nicedisc = this->nicedisc;
X
X    return WRITE(f, tag) &&
X           this->save(this, f) &&    /* Easier than rewriting this for each fun
Xction */
X           WRITE(f, this->o.name) &&
X           WRITE(f, this->vname) &&
X           WRITE(f, this->min) &&
X           WRITE(f, this->max) &&
X           WRITE(f, this->steps) &&
X           WRITE(f, this->colour) &&
X           WRITE(f, showdisc) &&
X           WRITE(f, nicedisc) &&
X           WRITE(f, end);
X}
X
X/* Read a function from a file */
Xstruct function *load_function(struct graph *g, FILE *f)
X{
X    short tag;
X    struct function *this;
X
X    if (READ(f, tag)) /* Determine which type of function */
X        switch (tag)
X        {
X            case F_OF_X_TAG:
X                this = (struct function *)load_f_of_x(g, f);
X                break;
X            case X_Y_TAG:
X                this = (struct function *)load_x_y(g, f);
X                break;
X            case R_OF_T_TAG:
X                this = (struct function *)load_r_of_t(g, f);
X                break;
X            case R_T_TAG:
X                this = (struct function *)load_r_t(g, f);
X                break;
X            default:
X                message(g, "Not a graph file", (char *)NULL);
X        }
X    return this;
X}
X
X/* Read "standard" part of function from file */
Xint load_rest(struct function *this, FILE *f)
X{
X    short showdisc, nicedisc, end;
X
X    if (READ(f, this->o.name) &&
X        READ(f, this->vname) &&
X        READ(f, this->min) &&
X        READ(f, this->max) &&
X        READ(f, this->steps) &&
X        READ(f, this->colour) &&
X        READ(f, showdisc) && /* Can't read bitfields directly */
X        READ(f, nicedisc) &&
X        READ(f, end) &&
X        end == FUNCTION_END)
X    {
X        this->showdisc = showdisc;
X        this->nicedisc = nicedisc;
X        return TRUE;
X    }
X    return FALSE;
X}
X
X/* Nothing to do (don't care about resolution) */
Xstatic int inform_function(struct function *this)
X{
X    return TRUE;
X}
X
X/* idem */
Xstatic void confirm_function(struct object *this, int ok)
X{
X}
X
X/* Standard function init */
Xvoid init_function(struct function *this, struct graph *g, char *name)
X{
X    const static struct function def_f =
X    {
X        {
X            { NULL }, NULL, "", FALSE, 0, 0,
X            /* Default methods */
X            (void *)uncalled, (void *)select_function, (void *)deselect_functio
Xn,
X            (void *)down_function, (void *)move_function, (void *)up_function,
X            (void *)uncalled, (void *)draw_function, (void *)ref_uncalled,
X            (void *)uncalled, (void *)var_change_function, (void *)save_functio
Xn,
X            (void *)inform_function, (void *)confirm_function
X        },
X        (void *)uncalled, (void *)uncalled,
X        "", NOVAL, NOVAL, INOVAL,
X        1, TRUE, TRUE, FALSE, FALSE
X    };
X
X    *this = def_f;
X    this->o.g = g;
X    strcpy(this->o.name, name);
X    init_var_list(&this->used);
X}
X
X/* Create a new function (ask user which type he wants) */
Xstruct function *new_function(struct graph *g)
X{
X    struct Requester *req;
X    struct Memory *m;
X    struct Gadget *gl = NULL, *fx, *xy, *rt, *r2;
X    char name[FNAMELEN];
X    int ret = FALSE;
X    struct function *o = NULL;
X
X    name[0] = '\0';
X
X    if ((m = NewMemory()) &&
X        (req = InitReq(50, 20, 230, 105, m)) &&
X        SetReqBorder(req, 1, m) &&
X        AddIntuiText(&req->ReqText, "Add Function", 67, 6, m) &&
X        AddText(&gl, 0, "Name ", FALSE, name, FNAMELEN, TRUE, 0, RELVERIFY, 51,
X 20, 100, 10, TRUE, m) &&
X        (fx = AddRadio(&gl, 0, "f(x)", TRUE, SELECTED, RELVERIFY, 28, 11, 40, 1
X0, 10, m)) &&
X        (rt = AddRadio(&gl, 0, "r(theta)", TRUE, 0, RELVERIFY, 26, 105, 40, 10,
X 10, m)) &&
X        (xy = AddRadio(&gl, 0, "x(t),y(t)", TRUE, 0, RELVERIFY, 22, 11, 60, 10,
X 10, m)) &&
X        (r2 = AddRadio(&gl, 0, "r(t),theta(t)", TRUE, 0, RELVERIFY, 14, 105, 60
X, 10, 10, m)) &&
X        AddBox(&gl, TRUE, "Ok", 0, RELVERIFY | ENDGADGET, 25, 80, 65, 15, FALSE
X, m) &&
X        AddBox(&gl, FALSE, "Cancel", 0, RELVERIFY | ENDGADGET, 140, 80, 65, 15,
X FALSE, m))
X    {
X        SetReqGadgets(req, gl);
X        if (ret = DoRequest(req, g, std_ghandler))
X        {
X            strip(name);
X            if (*name)
X            {
X                if (fx->Flags & SELECTED) o = (struct function *)new_f_of_x(g,
Xname);
X                else if (xy->Flags & SELECTED) o = (struct function *)new_x_y(g
X, name);
X                else if (rt->Flags & SELECTED) o = (struct function *)new_r_of_
Xt(g, name);
X                else o = (struct function *)new_r_t(g, name);
X            }
X            else
X                message(g, "Blank names not allowed", (char *)NULL);
X        }
X    }
X    Free(m);
X    return o;
X}
X
SHAR_EOF
echo "extracting function.h"
sed 's/^X//' << \SHAR_EOF > function.h
X/*
X *                 GRAPH, Version 1.00 - 4 August 1989
X *
X *            Copyright 1989, David Gay. All Rights Reserved.
X *            This software is freely redistrubatable.
X */
X
X/* class function, inherits from class object. The actual function types are su
Xb-classes of this one */
X#ifndef FUNCTION_H
X#define FUNCTION_H
X
X#include "list.h"
X#include "object.h"
X#include "graph.h"
X#include "user/eval.h"
X#include <stddef.h>
X
X#define MAXERROR 0.2 /* For discontinuities */
X#define MAXITER 4    /* In improvement algo */
X#define FLAT 2       /* number of pixels allowed in "flat" discontinuities */
X#define DEFSTEPS 100 /* Default number of steps */
X#define FDIST 5      /* Max (y) distance for function select */
X
X/* class function (inherited from class object). Fields are public. */
Xstruct function {
X    struct object o;
X    int (*calcf)(struct function *this, int allow_mes); /* Recalculate values o
Xf points */
X    int (*save)(struct function *this, FILE *f);        /* Save function specif
Xic info. to file */
X
X    /* Information global to all types of functions */
X    char vname[VARLEN]; /* name of variable */
X    double min, max;    /* Limits for variable */
X    int steps;          /* Number of points to calculate */
X    BYTE colour;        /* Colour in which to draw */
X    int showdisc : 1;   /* Show discontinuities ? */
X    int nicedisc : 1;   /* Allow "nice" discontinuities */
X
X    /* State info */
X    int calc : 1;       /* Points calculated ? */
X    int selected : 1;   /* function selected ? */
X    variable var;       /* Actual variable */
X    var_list used;      /* Vars this function depends on */
X    list pts;           /* Points composing this, different structure for each
Xtype of function */
X    size_t sizept;      /* Size of one point (for delete) */
X};
X
X/* Flags for point state */
X#define EXISTS 1  /* Function is defined here */
X#define DISC 2    /* This is a discontinuity */
X#define OK 4      /* All is well */
X
X/* The base class for a point */
Xstruct point {
X    node node;
X    char state;
X    double x, y;
X};
X
Xtypedef struct point point;
X
X/* Create/load the various types of function */
Xstruct f_of_x *new_f_of_x(struct graph *g, char *name);
Xstruct x_y *new_x_y(struct graph *g, char *name);
Xstruct r_of_t *new_r_of_t(struct graph *g, char *name);
Xstruct r_t *new_r_t(struct graph *g, char *name);
Xstruct f_of_x *load_f_of_x(struct graph *g, FILE *f);
Xstruct x_y *load_x_y(struct graph *g, FILE *f);
Xstruct r_of_t *load_r_of_t(struct graph *g, FILE *f);
Xstruct r_t *load_r_t(struct graph *g, FILE *f);
X
X/* A few useful functions ... */
Xvoid display_function(struct function *this); /* Draws a function */
Xvoid init_function(struct function *this, struct graph *g, char *name); /* Stan
Xdard init. */
Xint load_rest(struct function *this, FILE *f); /* Load public part of function
X*/
X
X#endif
X
SHAR_EOF
echo "extracting gadgets.c"
sed 's/^X//' << \SHAR_EOF > gadgets.c
X/* Routines to create various types of gadgets, menus, etc
X   Could do with a few comments and some documentation ...
X   This code is placed in the public domain.
X   David Gay, 1989.
X*/
X
X#include <proto/exec.h>
X#include <exec/nodes.h>
X#include <exec/lists.h>
X#include <exec/memory.h>
X#include <graphics/gfx.h>
X#include <intuition/intuition.h>
X#include <proto/graphics.h>
X#include <proto/intuition.h>
X#include <proto/diskfont.h>
X#include "user/gadgets.h"
X#include <string.h>
X
X#define XDOUBLEMARGIN   4                   /* Margin for "double" border reque
Xsters */
X#define YDOUBLEMARGIN   4
X#define GADGTEXTX       4                   /* How far away (X) text is from Op
Xtion/Radio gadgets */
X#define GADGTEXTY       4                   /* idem, but when text above gadget
X */
X#define TEXTBORDERX     2                   /* How far out text gadget rectangl
Xe is */
X#define TEXTBORDERY     4
X#define MENUMARGIN      20                  /* Spacing between menus */
X#define TEXTMARGIN      10                  /* Space around text items */
X#define TEXTGAP         2                   /* Space above & below text items *
X/
X#define RULEHEIGHT      2                   /* Height of rules */
X#define RULEGAP         6                   /* Space above & below rules */
X#define RULEMARGIN      10                  /* idem, but left & right */
X#define MINITEMWIDTH    (RULEMARGIN + 10)   /* Min. menu item width */
X#define SUBX            30                  /* Sub item position */
X
Xboolean CheckFont(struct Memory *);
X
Xstruct Memory
X{
X    struct MinList Fonts;
X    struct MinList Lists;
X    struct Remember *Mem;
X};
X
Xstruct FontNode
X{
X    struct MinNode fn_Node;
X    struct TextFont *font;
X};
X
Xstruct ITextNode
X{
X    struct MinNode it_node;
X    struct IntuiText it;
X};
X
Xtypedef struct Gadget GArray[1];
X
Xstruct ListInfo
X{
X    struct MinNode li_node;
X    char *buf;
X    long len;
X    struct List *list;
X    struct MinList ilist;
X    struct IntuiText *blank;
X    long nb, current, pos;
X    struct Gadget *arrow1, *arrow2, *strg, *sld;
X    GArray *glist;
X    long visible, exists, dispchars;
X    ULONG clicksecs, clickmics;
X    long clickpos;
X};
X
Xstatic struct TextAttr topaz8 = { "topaz.font", 8 };
Xstatic BYTE fore = 1, back = 0, mode = JAM1, depth = 2;
Xstatic struct TextAttr *ta = &topaz8;
Xstatic boolean fontopen;
Xstatic struct TextFont *font;
X
X
Xstatic UWORD chip down_data[] = {
X        0xF83E,0xF83E,0xF83E,0xC006,0xE00E,0xF01E,0xF83E,0xFC7E,
X        0xFEFE,0xFFFE,0x07C0,0x07C0,0x07C0,0x3FF8,0x1FF0,0x0FE0,
X        0x07C0,0x0380,0x0100,0x0000
X};
X
Xstatic struct Image down_img = {
X        0, 1,
X        15, 10,
X        2,
X        down_data,
X        0x0003, 0x0000,
X        NULL
X};
X
Xstatic UWORD chip up_data[] = {
X        0xFEFE,0xFC7E,0xF83E,0xF01E,0xE00E,0xC006,0xF83E,0xF83E,
X        0xF83E,0xFFFE,0x0100,0x0380,0x07C0,0x0FE0,0x1FF0,0x3FF8,
X        0x07C0,0x07C0,0x07C0,0x0000
X};
X
Xstatic struct Image up_img = {
X        0, 1,
X        15, 10,
X        2,
X        up_data,
X        0x0003, 0x0000,
X        NULL
X};
X
X/* Returns number of nodes, or -1 for failure */
Xstatic long build_ilist(struct ListInfo *li)
X{
X    int cnt = 0;
X    struct Node *scan;
X
X    NewList((struct List *)&li->ilist);
X
X    for (scan = li->list->lh_Head; scan->ln_Succ; scan = scan->ln_Succ, cnt++)
X    {
X        struct ITextNode *in = AllocMem(sizeof(struct ITextNode) + li->dispchar
Xs + 1, MEMF_CLEAR);
X        char *str;
X        struct IntuiText *it;
X        int j;
X
X        if (!in) return -1;
X        it = (struct IntuiText *)&in->it;
X        str = (char *)(in + 1);
X
X        str[li->dispchars] = '\0';
X
X        strncpy(str, scan->ln_Name, li->dispchars);
X        for (j = strlen(str); j < li->dispchars; j++) str[j] = ' ';
X
X        it->FrontPen = fore; it->BackPen = back;
X        it->DrawMode = JAM2;
X        it->ITextFont = ta;
X        it->IText = str;
X
X        AddTail((struct List *)&li->ilist, (struct Node *)in);
X    }
X    li->exists = li->visible > cnt ? cnt : li->visible;
X    return cnt;
X}
X
Xstatic void free_ilist(struct ListInfo *li)
X{
X    struct MinNode *scan, *next;
X
X    for (scan = li->ilist.mlh_Head; next = scan->mln_Succ; scan = next)
X        FreeMem(scan, sizeof(struct ITextNode) + li->dispchars + 1);
X}
X
Xstatic void recalc_glist(struct ListInfo *li)
X{
X    int i;
X    struct ITextNode *scan;
X
X    for (i = 0, scan = (struct ITextNode *)li->ilist.mlh_Head; i < li->pos; i++
X, scan = (struct ITextNode *)scan->it_node.mln_Succ)
X        ;
X    for (i = 0; i < li->exists; i++, scan = (struct ITextNode *)scan->it_node.m
Xln_Succ)
X        (*li->glist)[i].GadgetText = &scan->it;
X    for (; i < li->visible; i++)
X        (*li->glist)[i].GadgetText = li->blank;
X
X    if (li->current >= li->pos && li->current < li->pos + li->exists)
X        (*li->glist)[li->current - li->pos].Flags |= SELECTED;
X}
X
Xstruct Memory *NewMemory()
X{
X    struct Memory *mem;
X    struct Remember *key = NULL;
X
X    mem = (struct Memory *)AllocRemember(&key, sizeof(struct Memory), MEMF_CLEA
XR);
X    if (mem)
X    {
X        mem->Mem = key;
X        NewList((struct List *)&mem->Fonts);
X        NewList((struct List *)&mem->Lists);
X    }
X
X    return(mem);
X}
X
Xvoid Free(mem)
Xstruct Memory *mem;
X{
X    struct MinNode *mn;
X
X    if (mem)
X    {
X        for (mn = mem->Fonts.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
X            CloseFont(((struct FontNode *)mn)->font);
X        for (mn = mem->Lists.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
X            free_ilist((struct ListInfo *)mn);
X
X        FreeRemember(&mem->Mem, TRUE);
X    }
X}
X
Xvoid ModSys(f, b, m, font)
Xlong f, b, m;
Xstruct TextAttr *font;
X{
X    if (f != -1) fore = f;
X    if (b != -1) back = b;
X    if (m != -1) mode = m;
X    if (font)
X    {
X        ta = font;
X        fontopen = FALSE;
X    }
X}
X
Xvoid SetDepth(d)
Xlong d;
X{
X   depth = d;
X}
X
Xstruct Requester *InitReq(left, top, width, height, mem)
Xlong left, top, width, height;
Xstruct Memory *mem;
X{
X    struct Requester *req;
X
X    req = (struct Requester *)AllocRemember(&mem->Mem, sizeof(struct Requester)
X, MEMF_CLEAR);
X    if (req)
X    {
X        req->LeftEdge = left; req->TopEdge = top;
X        req->Width = width; req->Height = height;
X        req->BackFill = back;
X    }
X
X    return(req);
X}
X
Xboolean SetReqBorder(req, type, mem)
Xstruct Requester *req;
XLONG type;
Xstruct Memory *mem;
X{
X    struct Border *b = NULL;
X
X    switch (type)
X    {
X        case 1:
X            if (!AddRectBorder(&b, XDOUBLEMARGIN / 2, YDOUBLEMARGIN / 2, req->W
Xidth - XDOUBLEMARGIN, req->Height - YDOUBLEMARGIN, mem))
X                break;
X        case 0:
X            if (!AddRectBorder(&b, 0, 0, req->Width, req->Height, mem))
X                b = NULL;
X            break;
X        default:
X            b = (struct Border *)type;
X            break;
X    }
X
X    return((req->ReqBorder = b) != NULL);
X}
X
Xvoid SetReqGadgets(req, gl)
Xstruct Requester *req;
Xstruct Gadget *gl;
X{
X    struct Gadget *g;
X
X    for (g = gl; g; g = g->NextGadget)
X        g->GadgetType |= REQGADGET;
X
X    req->ReqGadget = gl;
X}
X
Xvoid SetReqText(req, it)
Xstruct Requester *req;
Xstruct IntuiText *it;
X{
X    req->ReqText = it;
X}
X
Xstruct Gadget *AddBox(gl, id, text, flags, act, x, y, w, h, thick, mem)
Xstruct Gadget **gl;
Xchar *text;
Xlong id, flags, act, x, y, w, h, thick;
Xstruct Memory *mem;
X{
X    BYTE *data;
X    struct Gadget *gadg = NULL;
X    int i, tl, tx, ty, len = strlen(text);
X    struct RastPort rp, rp2;
X    struct BitMap bm, bm2;
X    struct Image *im, *im2;
X
X    if (CheckFont(mem) &&
X        (gadg = (struct Gadget *)AllocRemember(&mem->Mem, sizeof(struct Gadget)
X + 2 * sizeof(struct Image), MEMF_CLEAR)) &&
X        (data = (BYTE *)AllocRemember(&mem->Mem, 2 * depth * RASSIZE(w, h), MEM
XF_CLEAR | MEMF_CHIP)))
X    {
X        im2 = (im = (struct Image *)(gadg + 1)) + 1;
X
X        InitBitMap(&bm, depth, w, h);
X        InitBitMap(&bm2, depth, w, h);
X        for (i = 0; i < depth; i++)
X        {
X            bm.Planes[i] = data;
X            bm2.Planes[i] = data + RASSIZE(w, h) * depth;
X            data += RASSIZE(w, h);
X        }
X        InitRastPort(&rp);
X        rp.BitMap = &bm;
X        InitRastPort(&rp2);
X        rp2.BitMap = &bm2;
X        SetAPen(&rp, fore);
X        SetAPen(&rp2, fore);
X
X        im->Width = im2->Width = w;
X        im->Height = im2->Height = h;
X        im->Depth = im2->Depth = depth;
X        im->ImageData = (USHORT *)bm.Planes[0];
X        im2->ImageData = (USHORT *)bm2.Planes[0];
X        im->PlanePick = im2->PlanePick = 0xff;
X
X        SetRast(&rp, back);
X        SetRast(&rp2, back);
X        DrawRoundedRect(&rp, 0, 0, w, h);
X        FillRoundedRect(&rp2, 0, 0, w, h);
X        if (thick)
X        {
X            DrawRoundedRect(&rp, 1, 1, w - 2, h - 2);
X            DrawRoundedRect(&rp, 1, 0, w - 2, h);
X        }
X
X        SetFont(&rp, font);
X        SetFont(&rp2, font);
X        tl = TextLength(&rp, text, len);
X        tx = (w - tl) / 2;
X        ty = (h - font->tf_YSize + 1) / 2 + font->tf_Baseline;
X        SetDrMd(&rp, JAM1);
X        Move(&rp, tx, ty); Text(&rp, text, len);
X        SetAPen(&rp2, back); SetDrMd(&rp2, JAM1);
X        Move(&rp2, tx, ty); Text(&rp2, text, len);
X
X        gadg->LeftEdge = x;
X        gadg->TopEdge = y;
X        gadg->Width = w;
X        gadg->Height = h;
X        gadg->GadgetType = BOOLGADGET;
X
X        gadg->GadgetRender = (APTR)im;
X        gadg->SelectRender = (APTR)im2;
X        gadg->GadgetID = id;
X        gadg->Flags = GADGHIMAGE | GADGIMAGE | flags;
X        gadg->Activation = act;
X
X        AppendGadget(gl, gadg);
X    }
X
X    return(gadg);
X}
X
Xstruct Gadget *AddRadio(gl, id, text, side, flags, act, mutex, x, y, w, h, mem)
X     
Xstruct Gadget **gl;
Xchar *text;
Xlong id, side, flags, act, x, y, w, h, mutex;
Xstruct Memory *mem;
X{
X    BYTE *data;
X    struct Gadget *gadg = NULL;
X    struct IntuiText *it = NULL;
X    struct RastPort rp, rp2;
X    struct BitMap bm, bm2;
X    struct Image *im, *im2;
X    int tl, bx, i;
X    struct AreaInfo areainf;
X    struct TmpRas tmpras;
X    BYTE areabuf[4 * 5];
X    PLANEPTR plane;
X
X    if (AddIntuiText(&it, text, side ? w + GADGTEXTX : 0, 0, mem) &&
X        (gadg = (struct Gadget *)AllocRemember(&mem->Mem, sizeof(struct Gadget)
X + 2 * sizeof(struct Image), MEMF_CLEAR)) &&
X        (data = (BYTE *)AllocRemember(&mem->Mem, 2 * depth * RASSIZE(w, h), MEM
XF_CLEAR | MEMF_CHIP)))
X    {
X        tl = IntuiTextLength(it);
X        it->TopEdge = (h - font->tf_YSize) / 2;
X
X        gadg->LeftEdge = side ? x : x - tl - GADGTEXTX;
X        gadg->TopEdge = y;
X        gadg->Width = tl + GADGTEXTX + w;
X        gadg->Height = h;
X        gadg->GadgetType = BOOLGADGET;
X        gadg->MutualExclude = mutex;
X
X        bx = side ? 0 : tl + GADGTEXTX;
X
X        im2 = (im = (struct Image *)(gadg + 1)) + 1;
X
X        InitBitMap(&bm, depth, w, h);
X        InitBitMap(&bm2, depth, w, h);
X        for (i = 0; i < depth; i++)
X        {
X            bm.Planes[i] = data;
X            bm2.Planes[i] = data + RASSIZE(w, h) * depth;
X            data += RASSIZE(w, h);
X        }
X        InitRastPort(&rp);
X        rp.BitMap = &bm;
X        InitRastPort(&rp2);
X        rp2.BitMap = &bm2;
X        if (plane = (PLANEPTR)AllocRaster(w, h))
X        {
X            InitTmpRas(&tmpras, plane, RASSIZE(w, h));
X            rp2.TmpRas = &tmpras;
X            memset(areabuf, 0, sizeof(areabuf));
X            InitArea(&areainf, (short *)areabuf, 4);
X            rp2.AreaInfo = &areainf;
X
X            SetAPen(&rp, fore);
X            SetAPen(&rp2, fore);
X
X            im->Width = im2->Width = w;
X            im->Height = im2->Height = h;
X            im->LeftEdge = im2->LeftEdge = bx;
X            im->Depth = im2->Depth = depth;
X            im->ImageData = (USHORT *)bm.Planes[0];
X            im2->ImageData = (USHORT *)bm2.Planes[0];
X            im->PlanePick = im2->PlanePick = 0xff;
X
X            SetRast(&rp, back);
X            SetRast(&rp2, back);
X            DrawEllipse(&rp, w/2, h/2, w/2 - 1, h/2 - 1);
X            DrawEllipse(&rp2, w/2, h/2, w/2 - 1, h/2 - 1);
X            AreaEllipse(&rp2, w/2, h/2, w/4, h/4);
X            AreaEnd(&rp2);
X            FreeRaster(plane, w, h);
X            rp2.TmpRas = NULL;
X            rp2.AreaInfo = NULL;
X
X            gadg->GadgetRender = (APTR)im;
X            gadg->SelectRender = (APTR)im2;
X            gadg->GadgetText = it;
X            gadg->GadgetID = id;
X            gadg->Flags = GADGHIMAGE | GADGIMAGE | flags;
X            gadg->Activation = act;
X
X            AppendGadget(gl, gadg);
X        }
X        else
X            gadg = NULL;
X    }
X    return(gadg);
X}
X
Xstruct Gadget *AddOption(gl, id, text, side, flags, act, x, y, w, h, mem)
Xstruct Gadget **gl;
Xchar *text;
Xlong id, side, flags, act, x, y, w, h;
Xstruct Memory *mem;
X{
X    struct Gadget *gadg = NULL;
X    struct IntuiText *it = NULL;
X    struct Border *b = NULL, *b2 = NULL;
X    int tl, bx, f = fore, ba = back;
X
X    if (AddIntuiText(&it, text, side ? w + GADGTEXTX : 0, 0, mem) &&
X        (gadg = (struct Gadget *)AllocRemember(&mem->Mem, sizeof(struct Gadget)
X, MEMF_CLEAR)))
X    {
X        gadg->Height = h;
X        tl = IntuiTextLength(it);
X        it->TopEdge = (h - font->tf_YSize) / 2;
X
X        gadg->LeftEdge = side ? x : x - tl - GADGTEXTX;
X        gadg->TopEdge = y;
X        gadg->Width = tl + 4 + w;
X        gadg->GadgetType = BOOLGADGET;
X
X        bx = side ? 0 : tl + GADGTEXTX;
X        if (AddLineBorder(&b, bx, 0, bx + w - 1, h - 1, mem) &&
X            AddLineBorder(&b, bx + w - 1, 0, bx, h - 1, mem) &&
X            AddRectBorder(&b, bx, 0, w, h, mem) &&
X            (fore = ba, back = f, AddLineBorder(&b2, bx, 0, bx + w - 1, h - 1,
Xmem)) &&
X            AddLineBorder(&b2, bx + w - 1, 0, bx, h - 1, mem) &&
X            (fore = f, back = ba, AddRectBorder(&b2, bx, 0, w, h, mem)))
X        {
X            gadg->GadgetRender = (APTR)b2;
X            gadg->SelectRender = (APTR)b;
X            gadg->GadgetText = it;
X            gadg->GadgetID = id;
X            gadg->Flags = GADGHIMAGE | flags;
X            gadg->Activation = TOGGLESELECT | act;
X
X            AppendGadget(gl, gadg);
X        }
X        else
X            gadg = NULL;
X    }
X
X    fore = f; back = ba;
X    return(gadg);
X}
X
Xstruct Gadget *AddText(struct Gadget **gl, long id, char *text, long above, cha
Xr *buf, long maxlen, long undo, long flags, long act, long x, long y, long w, lo
Xng h, long noborder, struct Memory *mem)
X{
X    BYTE *data;
X    struct StringInfo *si;
X    struct Gadget *gadg = NULL;
X    struct IntuiText *it = NULL;
X    int tl;
X    struct Border *b = NULL;
X    char *undobuf;
X
X    data = (BYTE *)AllocRemember(&mem->Mem, sizeof(struct Gadget) + sizeof(stru
Xct StringInfo) + (undo ? maxlen + 1: 0), MEMF_CLEAR);
X    if (data)
X    {
X        gadg = (struct Gadget *)data;
X        si = (struct StringInfo *)(gadg + 1);
X        undobuf = undo ? data + sizeof(struct Gadget) + sizeof(struct StringInf
Xo) : NULL;
X
X        if (AddIntuiText(&it, text, 0, 0, mem))
X        {
X            tl = IntuiTextLength(it);
X            if (above)
X            {
X                it->TopEdge = -font->tf_YSize - GADGTEXTY;
X                it->LeftEdge = 0;
X            }
X            else
X            {
X                it->TopEdge = h - font->tf_YSize - 2;
X                it->LeftEdge = -tl - GADGTEXTX;
X            }
X
X            gadg->LeftEdge = x;
X            gadg->TopEdge = y;
X            gadg->Width = w;
X            gadg->Height = h;
X            gadg->GadgetType = STRGADGET;
X
X            if (noborder || AddRectBorder(&b, -TEXTBORDERX + 1, -TEXTBORDERY +
X1, w + TEXTBORDERX, h + TEXTBORDERY, mem))
X            {
X                gadg->GadgetRender = (APTR)b;
X                gadg->GadgetText = it;
X                gadg->GadgetID = id;
X                gadg->Flags = GADGHCOMP | flags;
X                gadg->Activation = act;
X                gadg->SpecialInfo = (APTR)si;
X
X                si->Buffer = buf;
X                si->UndoBuffer = undobuf;
X                si->MaxChars = maxlen;
X
X                AppendGadget(gl, gadg);
X            }
X            else
X                gadg = NULL;
X        }
X        else
X            gadg = NULL;
X    }
X
X    return(gadg);
X}
X
Xstruct Gadget *AddSlider(struct Gadget **gl, long id, long act, long x, long y,
X long w, long h, long vert, long knobsize, struct Memory *mem)
X{
X    BYTE *data;
X    struct Gadget *gg = NULL;
X    struct PropInfo *info;
X    struct Image *im;
X
X    data = (BYTE *)AllocRemember(&mem->Mem, sizeof(struct Gadget) + sizeof(stru
Xct PropInfo) + sizeof(struct Image), MEMF_CLEAR);
X    if (data)
X    {
X        gg = (struct Gadget *)data;
X        info = (struct PropInfo *)(data + sizeof(struct Gadget));
X        im = (struct Image *)(data + sizeof(struct Gadget) + sizeof(struct Prop
XInfo));
X
X        gg->LeftEdge = x;
X        gg->TopEdge = y;
X        gg->Width = w;
X        gg->Height = h;
X        gg->Flags = GADGHCOMP | GADGIMAGE |
X                    (y < 0 ? GRELBOTTOM : 0) |
X                    (x < 0 ? GRELRIGHT : 0) |
X                    (w < 0 ? GRELWIDTH : 0) |
X                    (h < 0 ? GRELHEIGHT : 0);
X        gg->Activation = act;
X        gg->GadgetType = PROPGADGET;
X        gg->GadgetRender = (APTR)im; /* dummy image, why ? */
X        gg->SpecialInfo = (APTR)info;
X        gg->GadgetID = id;
X
X        info->Flags = AUTOKNOB |
X                      (vert ? FREEVERT : FREEHORIZ);
X        if (vert) info->VertBody = knobsize;
X        else info->HorizBody = knobsize;
X
X        AppendGadget(gl, gg);
X    }
X    return(gg);
X}
X
X/* BUG: Arrows don't use selected colours */
Xstruct ListInfo *AddList(struct Gadget **gl, long id, char *text, struct List *
Xlist, char *buf, long len, long flags, long act, long x, long y, long w, long h,
X long noborder, struct Memory *mem)
X{
X    long ok = FALSE;
X    struct ListInfo *li;
X    int i;
X    long nb;
X    int a = font->tf_YSize;
X    int dispchars = (w - 15 - 3) / font->tf_XSize;
X    int nblines = (h - 2) / a;
X
X    if (CheckFont(mem) &&
X        (li = (struct ListInfo *)AllocRemember(&mem->Mem, sizeof(struct ListInf
Xo) + dispchars + 1, MEMF_CLEAR)))
X    {
X        char *spaces = (char *)(li + 1);
X
X        memset(spaces, ' ', dispchars);
X        spaces[dispchars] = '\0';
X
X        AddHead((struct List *)&mem->Lists, (struct Node *)li);
X        if (nblines >= 5 && a * (nblines - 2) - 26 > 20 && w > 15 + 3 + 32)
X        {
X            w = font->tf_XSize * dispchars + 15 + 3;
X            h = a * nblines + 2;
X
X            li->buf = buf;
X            li->len = len;
X            li->list = list;
X            li->pos = 0;
X            li->current = -1;
X            li->visible = nblines - 2;
X            li->dispchars = dispchars;
X            li->clickpos = -1;
X
X            if ((li->nb = nb = build_ilist(li)) != -1 &&
X                AddIntuiText(&li->blank, spaces, 0, 0, mem))
X            {
X                struct Gadget *arrow1, *arrow2, *sld;
X                struct Border *b = NULL;
X                long knobsize;
X
X                if (nb == 0)
X                    knobsize = 0xffff;
X                else
X                {
X                    knobsize = 0xffff * li->exists;
X                    knobsize /= nb;
X                }
X
X                if ((sld = AddSlider(gl, id, RELVERIFY, x + w - 16, y + 13, 15,
X h - 2 * a - 26, TRUE, knobsize, mem)) &&
X                    (arrow1 = (struct Gadget *)AllocRemember(&mem->Mem, 3 * siz
Xeof(struct Gadget), MEMF_CLEAR)) &&
X                    AddRectBorder(&b, 0, 0, w, h - 2 * a, mem) &&
X                    AddRectBorder(&b, w - 17, 12, 17, h - 2 * a - 24, mem) &&
X                    AddLineBorder(&b, w - 17, 0, w - 17, h - 2 * a - 1, mem))
X                {
X                    struct Gadget *strg, *cadre;
X                    int tx;
X
X                    sld->UserData = (APTR)li;
X                    li->sld = sld;
X                    arrow2 = arrow1 + 1;
X                    arrow1->TopEdge = y + 1;
X                    arrow1->LeftEdge = x + w - 16;
X                    arrow1->Width = 15;
X                    arrow1->Height = 11;
X                    arrow1->Flags = GADGHCOMP | GADGIMAGE;
X                    arrow1->Activation = GADGIMMEDIATE | RELVERIFY;
X                    arrow1->GadgetType = BOOLGADGET;
X                    arrow1->GadgetRender = (APTR)&up_img;
X                    arrow1->UserData = (APTR)li;
X                    arrow1->GadgetID = id;
X                    AppendGadget(gl, arrow1);
X
X                    li->arrow1 = arrow1;
X                    arrow2->LeftEdge = x + w - 16;
X                    arrow2->TopEdge = y + h - 2 * a - 1 - 11;
X                    arrow2->Width = 15;
X                    arrow2->Height = 11;
X                    arrow2->Flags = GADGHCOMP | GADGIMAGE;
X                    arrow2->Activation = GADGIMMEDIATE | RELVERIFY;
X                    arrow2->GadgetType = BOOLGADGET;
X                    arrow2->GadgetRender = (APTR)&down_img;
X                    arrow2->UserData = (APTR)li;
X                    arrow2->GadgetID = id;
X                    AppendGadget(gl, arrow2);
X                    li->arrow2 = arrow2;
X
X                    cadre = arrow2 + 1;
X                    cadre->LeftEdge = x;
X                    cadre->TopEdge = y;
X                    cadre->Width = 1;
X                    cadre->Height = 1;
X                    cadre->Flags = GADGHNONE;
X                    cadre->GadgetType = BOOLGADGET;
X                    cadre->GadgetRender = (APTR)b;
X                    cadre->UserData = (APTR)li;
X                    cadre->GadgetID = id;
X                    AppendGadget(gl, cadre);
X
X                    tx = font->tf_XSize * strlen(text);
X                    if (tx > w - 32) tx = w - 32;
X                    if (strg = AddText(gl, id, text, FALSE, buf, len, TRUE, fla
Xgs, act | GADGIMMEDIATE, x + tx + GADGTEXTX, y + h - a - 2, w - tx - GADGTEXTX,
Xa + 2, noborder, mem))
X                    {
X                        GArray *bl;
X
X                        strg->UserData = (APTR)li;
X                        li->strg = strg;
X
X                        if (bl = (GArray *)AllocRemember(&mem->Mem, li->visible
X * sizeof(struct Gadget), MEMF_CLEAR))
X                        {
X                            li->glist = bl;
X                            for (i = 0; i < li->visible; i++)
X                            {
X                                struct Gadget *gg = &(*bl)[i];
X
X                                gg->LeftEdge = x + 1;
X                                gg->TopEdge = y + i * a + 1;
X                                gg->Width = w - 18;
X                                gg->Height = a;
X                                gg->Flags = GADGHCOMP;
X                                gg->Activation = GADGIMMEDIATE;
X                                gg->GadgetType = BOOLGADGET;
X                                gg->UserData = (APTR)li;
X                                gg->GadgetID = id;
X                                AppendGadget(gl, gg);
X                            }
X                            recalc_glist(li);
X                            ok = TRUE;
X                        }
X                    }
X                }
X            }
X        }
X    }
X    return ok ? li : NULL;
X}
X
Xlong ModifyList(struct Gadget *gg, struct Requester *req, struct Window *win, l
Xong up)
X{
X    struct ListInfo *li = (struct ListInfo *)gg->UserData;
X    int change = FALSE, ret = 0;
X
X    switch (gg->GadgetType & ~GADGETTYPE)
X    {
X        case STRGADGET:
X            if (!up && li->current != -1)
X            {
X                change = TRUE;
X                (*li->glist)[li->current - li->pos].Flags &= ~SELECTED;
X                li->current = li->clickpos = -1;
X            }
X            else if (up) ret = 1;
X            break;
X        case PROPGADGET:
X            {
X                struct PropInfo *pi = (struct PropInfo *)gg->SpecialInfo;
X
X                if (li->current != -1) (*li->glist)[li->current - li->pos].Flag
Xs &= ~SELECTED;
X
X                li->pos = (pi->VertPot + 1) * (li->nb - li->exists) >> 16;
X                recalc_glist(li);
X                change = TRUE;
X            }
X            break;
X        case BOOLGADGET:
X            if (gg == li->arrow1 || gg == li->arrow2)
X            {
X                if (up)
X                {
X                    long newpos;
X
X                    if (li->current != -1) (*li->glist)[li->current - li->pos].
XFlags &= ~SELECTED;
X                    newpos = li->pos + (gg == li->arrow1 ? -1 : 1);
X                    if (newpos >= 0 && newpos <= li->nb - li->exists)
X                    {
X                        struct PropInfo *pi = (struct PropInfo *)li->sld->Speci
XalInfo;
X                        long newpot;
X
X                        li->pos = newpos;
X                        newpot = 0xffff * li->pos;
X                        newpot /= li->nb - li->exists;
X                        NewModifyProp(li->sld, win, req, pi->Flags, 0, newpot,
X0, pi->VertBody, 1);
X                        recalc_glist(li);
X                        change = TRUE;
X                    }
X                }
X            }
X            else
X            {
X                int i, pos = -1;
X
X                for (i = 0; i < li->exists; i++)
X                    if (gg == &(*li->glist)[i])
X                    {
X                        pos = i;
X                        break;
X                    }
X                if (pos != -1)
X                {
X                    ULONG secs, micros;
X                    struct Node *scan;
X
X                    CurrentTime(&secs, &micros);
X                    if (li->current != -1) (*li->glist)[li->current - li->pos].
XFlags &= ~SELECTED;
X                    li->current = li->pos + pos;
X                    (*li->glist)[pos].Flags |= SELECTED;
X                    change = TRUE;
X                    li->buf[li->len - 1] = '\0';
X                    for (i = 0, scan = li->list->lh_Head; i < li->current; i++,
X scan = scan->ln_Succ)
X                        ;
X                    strncpy(li->buf, scan->ln_Name, li->len - 1);
X                    RefreshGList(li->strg, win, req, 1);
X
X                    ret = li->clickpos == li->current && DoubleClick(li->clicks
Xecs, li->clickmics, secs, micros) ? 2 : 1;
X                    li->clickpos = li->current;
X                    li->clicksecs = secs;
X                    li->clickmics = micros;
X                }
X            }
X    }
X    if (change) RefreshGList(&(*li->glist)[0], win, req, li->exists);
X
X    return ret;
X}
X
Xlong ChangeList(struct ListInfo *li, struct List *list, struct Requester *req,
Xstruct Window *win)
X{
X    struct PropInfo *pi = (struct PropInfo *)li->sld->SpecialInfo;
X    long knobsize;
X
X    free_ilist(li);
X    li->list = list;
X    if ((li->nb = build_ilist(li)) != -1)
X    {
X        if (li->current != -1) (*li->glist)[li->current - li->pos].Flags &= ~SE
XLECTED;
X
X        li->pos = 0;
X        li->current = -1;
X        li->clickpos = -1;
X
X        if (li->nb == 0)
X            knobsize = 0xffff;
X        else
X        {
X            knobsize = 0xffff * li->exists;
X            knobsize /= li->nb;
X        }
X        NewModifyProp(li->sld, win, req, pi->Flags, 0, 0, 0, knobsize, 1);
X
X        recalc_glist(li);
X        RefreshGList(&(*li->glist)[0], win, req, li->visible);
X
X        return TRUE;
X    }
X    return FALSE;
X}
X
Xstruct Gadget *ListStr(struct ListInfo *li)
X{
X    return li->strg;
X}
X
Xstruct IntuiText *AddIntuiText(it, str, x, y, mem)
Xstruct IntuiText **it;
Xchar *str;
Xlong x, y;
Xstruct Memory *mem;
X{
X    struct IntuiText *intui = NULL;
X
X    if (CheckFont(mem))
X    {
X        intui = (struct IntuiText *)AllocRemember(&mem->Mem, sizeof(struct Intu
XiText), MEMF_CLEAR);
X        if (intui)
X        {
X            intui->FrontPen = fore; intui->BackPen = back;
X            intui->DrawMode = mode;
X            intui->LeftEdge = x; intui->TopEdge = y;
X            intui->ITextFont = ta;
X            intui->IText = str;
X
X            AppendText(it, intui);
X        }
X    }
X
X    return(intui);
X}
X
Xstruct Border *AddLineBorder(struct Border **border, long x0, long y0, long x1,
X long y1, struct Memory *mem)
X{
X    BYTE *data;
X    struct Border *bb = NULL;
X    WORD *vert;
X
X    data = (BYTE *)AllocRemember(&mem->Mem, sizeof(struct Border) + 2 * 2 * siz
Xeof(WORD), MEMF_CLEAR);
X    if (data) {
X        bb = (struct Border *)data;
X        vert = (WORD *)(data + sizeof(struct Border));
X
X        bb->FrontPen = fore; bb->BackPen = back;
X        bb->DrawMode = mode;
X        bb->LeftEdge = 0; bb->TopEdge = 0;
X        bb->Count = 2;
X        bb->XY = vert;
X
X        vert[0] = x0; vert[1] = y0;
X        vert[2] = x1; vert[3] = y1;
X
X        AppendBorder(border, bb);
X    }
X
X    return(bb);
X}
X
Xstruct Border *AddRectBorder(border, x, y, w, h, mem)
Xstruct Border **border;
Xlong x, y, w, h;
Xstruct Memory *mem;
X{
X    BYTE *data;
X    struct Border *bb = NULL;
X    WORD *vert;
X
X    data = (BYTE *)AllocRemember(&mem->Mem, sizeof(struct Border) + 5 * 2 * siz
Xeof(WORD), MEMF_CLEAR);
X    if (data) {
X        bb = (struct Border *)data;
X        vert = (WORD *)(data + sizeof(struct Border));
X
X        bb->FrontPen = fore; bb->BackPen = back;
X        bb->DrawMode = mode;
X        bb->LeftEdge = x; bb->TopEdge = y;
X        bb->Count = 5;
X        bb->XY = vert;
X
X        vert[1 * 2 + 0] = w - 1;
X        vert[2 * 2 + 0] = w - 1;
X        vert[2 * 2 + 1] = h - 1;
X        vert[3 * 2 + 1] = h - 1;
X
X        AppendBorder(border, bb);
X    }
X
X    return(bb);
X}
X
Xstruct Menu *AddMenu(struct Menu **ml, struct Screen *scr, char *text, long fla
Xgs, struct Memory *mem)
X{
X    struct Screen look;
X    struct TextFont *scrfont;
X    struct Menu *menu = NULL, *prev;
X
X    if (GetScreenData((char *)&look, sizeof(struct Screen), scr == NULL ? WBENC
XHSCREEN : CUSTOMSCREEN, scr))
X        if (scrfont = OpenDiskFont(look.Font))
X        {
X            if (menu = (struct Menu *)AllocRemember(&mem->Mem, sizeof(struct Me
Xnu), MEMF_CLEAR))
X            {
X                menu->MenuName = text;
X                menu->Flags = flags;
X                menu->Height = scrfont->tf_YSize + 1;
X                menu->Width = scrfont->tf_XSize * strlen(text) + MENUMARGIN / 2
X;
X
X                if (*ml == NULL)
X                {
X                    menu->LeftEdge = 0;
X                    *ml = menu;
X                }
X                else
X                {
X                    for (prev = *ml; prev->NextMenu; prev = prev->NextMenu) ;
X                    prev->NextMenu = menu;
X                    menu->LeftEdge = prev->LeftEdge + prev->Width + MENUMARGIN;
X     
X                }
X            }
X            CloseFont(scrfont);
X        }
X    return menu;
X}
X
X/* Assumes HIRES screen (for COMMWIDTH) */
Xstruct MenuItem *AddItem(struct Menu *menu, char *text, long flags, long mutex,
X long cmd, long sub, struct Memory *mem)
X{
X    struct MenuItem *item = NULL, *prev;
X    struct IntuiText *it = NULL;
X    WORD width;
X
X    if (AddIntuiText(&it, text, TEXTMARGIN / 2, TEXTGAP / 2, mem))
X    {
X        if (item = (struct MenuItem *)AllocRemember(&mem->Mem, sizeof(struct Me
XnuItem), MEMF_CLEAR))
X        {
X            item->LeftEdge = 0;
X            width = IntuiTextLength(it) + TEXTMARGIN;
X            item->Flags = flags | ITEMTEXT;
X            item->Height = font->tf_YSize + TEXTGAP;
X            item->MutualExclude = mutex;
X            item->ItemFill = (APTR)it;
X            if (cmd)
X            {
X                item->Flags |= COMMSEQ;
X                width += COMMWIDTH + font->tf_XSize;
X                item->Command = cmd;
X            }
X            if (sub)
X                width += 2 * font->tf_XSize + TEXTMARGIN / 2;
X
X            if (width < MINITEMWIDTH) width = MINITEMWIDTH;
X
X            if (menu->FirstItem)
X            {
X                for (prev = menu->FirstItem; prev->NextItem; prev = prev->NextI
Xtem) ;
X                item->TopEdge = prev->TopEdge + prev->Height;
X                prev->NextItem = item;
X                if (prev->Width > width)
X                    item->Width = prev->Width;
X                else
X                    for (prev = menu->FirstItem; prev; prev = prev->NextItem)
X                    {
X                        struct IntuiText *msg;
X
X                        if ((prev->Flags & ITEMTEXT) == 0) /* A rule */
X                            ((struct Image *)(prev->ItemFill))->Width = width -
X RULEMARGIN;
X                        else if ((msg = ((struct IntuiText *)(prev->ItemFill))-
X>NextText) != NULL) /* A SubItem header */
X                            msg->LeftEdge += width - prev->Width;
X
X                        prev->Width = width;
X                    }
X            }
X            else
X            {
X                menu->FirstItem = item;
X                item->TopEdge = 0;
X                item->Width = width;
X            }
X            if (sub && !AddIntuiText(&it, ".", item->Width - TEXTMARGIN / 2 - f
Xont->tf_XSize, TEXTGAP / 2, mem))
X                item = NULL;
X        }
X    }
X    return item;
X}
X
X/* Assumes HIRES screen (for COMMWIDTH) */
Xstruct MenuItem *AddSub(struct MenuItem *item, char *text, long flags, long mut
Xex, long cmd, struct Memory *mem)
X{
X    struct MenuItem *subitem = NULL, *prev;
X    struct IntuiText *it = NULL;
X    WORD width;
X
X    if (AddIntuiText(&it, text, TEXTMARGIN / 2, TEXTGAP / 2, mem))
X    {
X        if (subitem = (struct MenuItem *)AllocRemember(&mem->Mem, sizeof(struct
X MenuItem), MEMF_CLEAR))
X        {
X            subitem->LeftEdge = SUBX;
X            width = IntuiTextLength(it) + TEXTMARGIN;
X            subitem->Flags = flags | ITEMTEXT;
X            subitem->Height = font->tf_YSize + TEXTGAP;
X            subitem->MutualExclude = mutex;
X            subitem->ItemFill = (APTR)it;
X            if (cmd)
X            {
X                subitem->Flags |= COMMSEQ;
X                width += COMMWIDTH + font->tf_XSize;
X                subitem->Command = cmd;
X            }
X            if (width < MINITEMWIDTH) width = MINITEMWIDTH;
X
X            if (item->SubItem)
X            {
X                for (prev = item->SubItem; prev->NextItem; prev = prev->NextIte
Xm) ;
X                subitem->TopEdge = prev->TopEdge + prev->Height;
X                prev->NextItem = subitem;
X                if (prev->Width > width)
X                    subitem->Width = prev->Width;
X                else
X                    for (prev = item->SubItem; prev; prev = prev->NextItem)
X                        prev->Width = width;
X            }
X            else
X            {
X                item->SubItem = subitem;
X                subitem->TopEdge = font->tf_YSize / 2 + 1;
X                subitem->Width = width;
X            }
X        }
X    }
X    return subitem;
X}
X/* Inspired by Stuart Ferguson's code */
Xstruct MenuItem *AddRule(struct Menu *menu, struct Memory *mem)
X{
X    struct MenuItem *item = NULL, *prev;
X    struct Image *img;
X
X    if ((img = (struct Image *)AllocRemember(&mem->Mem, sizeof(struct Image), M
XEMF_CLEAR)) &&
X        (item = (struct MenuItem *)AllocRemember(&mem->Mem, sizeof(struct MenuI
Xtem), MEMF_CLEAR)))
X    {
X        item->LeftEdge = 0;
X        item->Flags = ITEMENABLED | HIGHNONE;
X        item->Height = RULEGAP + RULEHEIGHT;
X        item->MutualExclude = 0;
X        item->ItemFill = (APTR)img;
X
X        if (menu->FirstItem)
X        {
X            for (prev = menu->FirstItem; prev->NextItem; prev = prev->NextItem)
X ;
X            item->TopEdge = prev->TopEdge + prev->Height;
X            prev->NextItem = item;
X            item->Width = prev->Width;
X        }
X        else
X        {
X            menu->FirstItem = item;
X            item->TopEdge = 0;
X            item->Width = MINITEMWIDTH;
X        }
X        img->LeftEdge = RULEMARGIN / 2;
X        img->TopEdge = RULEGAP / 2;
X        img->Width = item->Width - RULEMARGIN;
X        img->Height = RULEHEIGHT;
X        img->Depth = depth;
X        img->ImageData = NULL;
X        img->PlanePick = 0;
X        img->PlaneOnOff = fore;
X    }
X    return item;
X}
X
Xboolean CheckFont(mem)
Xstruct Memory *mem;
X{
X    struct FontNode *fn;
X
X    if (ta == NULL) fontopen = TRUE;
X    if (!fontopen)
X    {
X        font = (struct TextFont *)OpenDiskFont(ta);
X        if (font)
X        {
X            fn = (struct FontNode *)AllocRemember(&mem->Mem, sizeof(struct Font
XNode), MEMF_CLEAR);
X            if (fn)
X            {
X                fn->font = font;
X                AddHead((struct List *)&mem->Fonts, (struct Node *)fn);
X                fontopen = TRUE;
X            }
X            else CloseFont(font);
X        }
X    }
X
X    return(fontopen);
X}
X
Xvoid AppendGadget(gl, gg)
Xstruct Gadget **gl, *gg;
X{
X    struct Gadget *gadg;
X
X    if (*gl == NULL) *gl = gg;
X    else
X    {
X        gadg = *gl;
X        while (gadg->NextGadget) gadg = gadg->NextGadget;
X        gadg->NextGadget = gg;
X    }
X}
X
Xvoid AppendBorder(bl, bb)
Xstruct Border **bl, *bb;
X{
X    struct Border *bord;
X
X    if (*bl == NULL) *bl = bb;
X    else
X    {
X        bord = *bl;
X        while (bord->NextBorder) bord = bord->NextBorder;
X        bord->NextBorder = bb;
X    }
X}
X
Xvoid AppendText(itl, txt)
Xstruct IntuiText **itl, *txt;
X{
X    struct IntuiText *intui;
X
X    if (*itl == NULL) *itl = txt;
X    else
X    {
X        intui = *itl;
X        while (intui->NextText) intui = intui->NextText;
X        intui->NextText = txt;
X    }
X}
X
X#define Line(rp, x1, y1, x2, y2) { Move((rp), (x1), (y1)); Draw((rp), (x2), (y2
X)); }
X
Xvoid DrawRect(rp, x, y, w, h)
Xstruct RastPort *rp;
Xlong x, y, w, h;
X{
X    Move(rp, x, y);
X    Draw(rp, x + w - 1, y);
X    Draw(rp, x + w - 1, y + h - 1);
X    Draw(rp, x, y + h - 1);
X    Draw(rp, x, y);
X}
X
Xvoid DrawRoundedRect(rp, x, y, w, h)
Xstruct RastPort *rp;
Xlong x, y, w, h;
X{
X    int x2 = x + w - 1, y2 = y + h - 1;
X
X    Line(rp, x + 5, y, x2 - 5, y); Line(rp, x + 5, y2, x2 - 5, y2);
X    Line(rp, x, y + 5, x, y2 - 4); Line(rp, x2, y + 5, x2, y2 - 4);
X    WritePixel(rp, x + 4, y + 1); WritePixel(rp, x + 3, y + 1); WritePixel(rp,
Xx + 2, y + 2); WritePixel(rp, x + 1, y + 3); WritePixel(rp, x + 1, y + 4);
X    WritePixel(rp, x + 4, y2 - 1); WritePixel(rp, x + 3, y2 - 1); WritePixel(rp
X, x + 2, y2 - 2); WritePixel(rp, x + 1, y2 - 3); WritePixel(rp, x + 1, y2 - 4);
X    WritePixel(rp, x2 - 4, y + 1); WritePixel(rp, x2 - 3, y + 1); WritePixel(rp
X, x2 - 2, y + 2); WritePixel(rp, x2 - 1, y + 3); WritePixel(rp, x2 - 1, y + 4);
X    WritePixel(rp, x2 - 4, y2 - 1); WritePixel(rp, x2 - 3, y2 - 1); WritePixel(
Xrp, x2 - 2, y2 - 2); WritePixel(rp, x2 - 1, y2 - 3); WritePixel(rp, x2 - 1, y2 -
X 4);
X}
X
Xvoid FillRoundedRect(rp, x, y, w, h)
Xstruct RastPort *rp;
Xlong x, y, w, h;
X{
X    int x2 = x + w - 1, y2 = y + h - 1;
X
X    RectFill(rp, x, y + 5, x2, y2 - 5);
X    Line(rp, x + 1, y + 4, x2 - 1, y + 4); Line(rp, x + 1, y + 3, x2 - 1, y + 3
X); Line(rp, x + 2, y + 2, x2 - 2, y + 2); Line(rp, x + 4, y + 1, x2 - 4, y + 1);
X     
X    Line(rp, x + 1, y2 - 4, x2 - 1, y2 - 4); Line(rp, x + 1, y2 - 3, x2 - 1, y2
X - 3); Line(rp, x + 2, y2 - 2, x2 - 2, y2 - 2); Line(rp, x + 4, y2 - 1, x2 - 4,
Xy2 - 1);
X}
X
SHAR_EOF
echo "extracting gadgets.h"
sed 's/^X//' << \SHAR_EOF > gadgets.h
X/* Routines to create various types of gadgets, menus, etc
X   Could do with a few comments and some documentation ...
X   This code is placed in the public domain.
X   David Gay, 1989.
X*/
X
X#ifndef GADGETS_H
X#define GADGETS_H
X
Xtypedef long boolean;
X
Xstruct Memory *NewMemory(void);
Xvoid Free(struct Memory *);
Xvoid ModSys(long, long, long, struct TextAttr *);
Xvoid SetDepth(long);
X
Xstruct Requester *InitReq(long, long, long, long, struct Memory *);
Xboolean SetReqBorder(struct Requester *, long, struct Memory *);
Xvoid SetReqGadgets(struct Requester *, struct Gadget *);
Xvoid SetReqText(struct Requester *, struct IntuiText *);
X
Xstruct Gadget *AddBox(struct Gadget **, long, char *, long, long, long, long, l
Xong, long, long, struct Memory *);
Xstruct Gadget *AddOption(struct Gadget **, long, char *, long, long, long, long
X, long, long, long, struct Memory *);
Xstruct Gadget *AddRadio(struct Gadget **, long, char *, long, long, long, long,
X long, long, long, long, struct Memory *);
Xstruct Gadget *AddText(struct Gadget **gl, long id, char *text, long above, cha
Xr *buf,
X                       long maxlen, long undo, long flags, long act,
X                       long x, long y, long w, long h, long noborder, struct Me
Xmory *mem);
Xstruct Gadget *AddSlider(struct Gadget **gl, long id, long act,
X                         long x, long y, long w, long h, long vert,
X                         long knobsize, struct Memory *mem);
Xstruct ListInfo *AddList(struct Gadget **gl, long id, char *text, struct List *
Xlist, char *buf, long len, long flags, long act, long x, long y, long w, long h,
X long noborder, struct Memory *mem);
Xlong ModifyList(struct Gadget *gg, struct Requester *req, struct Window *win, l
Xong up);
Xlong ChangeList(struct ListInfo *li, struct List *list, struct Requester *req,
Xstruct Window *win);
Xstruct Gadget *ListStr(struct ListInfo *li);
Xvoid AppendGadget(struct Gadget **, struct Gadget *);
X
Xstruct IntuiText *AddIntuiText(struct IntuiText **, char *, long, long, struct
XMemory *);
Xvoid AppendText(struct IntuiText **, struct IntuiText *);
X
Xstruct Border *AddLineBorder(struct Border **, long, long, long, long, struct M
Xemory *);
Xstruct Border *AddRectBorder(struct Border **, long, long, long, long, struct M
Xemory *);
Xvoid AppendBorder(struct Border **, struct Border *);
X
Xvoid DrawRect(struct RastPort *, long, long, long, long);
Xvoid DrawRoundedRect(struct RastPort *, long, long, long, long);
Xvoid FillRoundedRect(struct RastPort *, long, long, long, long);
X
Xstruct Menu *AddMenu(struct Menu **ml, struct Screen *scr, char *text, long fla
Xgs, struct Memory *mem);
Xstruct MenuItem *AddItem(struct Menu *menu, char *text, long flags, long mutex,
X long cmd, long sub, struct Memory *mem);
Xstruct MenuItem *AddRule(struct Menu *menu, struct Memory *mem);
Xstruct MenuItem *AddSub(struct MenuItem *item, char *text, long flags, long mut
Xex, long cmd, struct Memory *mem);
X
X#endif
X
SHAR_EOF
echo "End of archive 2 (of 7)"
# if you want to concatenate archives, remove anything after this line
exit