home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.5
/
ffcollection-1-5-1992-11.iso
/
ff_disks
/
200-299
/
ff280.lzh
/
Graph
/
gadgets
/
gadgets.c
Wrap
C/C++ Source or Header
|
1989-11-20
|
38KB
|
1,307 lines
/* Routines to create various types of gadgets, menus, etc
Could do with a few comments and some documentation ...
This code is placed in the public domain.
David Gay, 1989.
*/
#include <proto/exec.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <exec/memory.h>
#include <graphics/gfx.h>
#include <intuition/intuition.h>
#include <proto/graphics.h>
#include <proto/intuition.h>
#include <proto/diskfont.h>
#include "user/gadgets.h"
#include <string.h>
#define XDOUBLEMARGIN 4 /* Margin for "double" border reque
sters */
#define YDOUBLEMARGIN 4
#define GADGTEXTX 4 /* How far away (X) text is from Op
tion/Radio gadgets */
#define GADGTEXTY 4 /* idem, but when text above gadget
*/
#define TEXTBORDERX 2 /* How far out text gadget rectangl
e is */
#define TEXTBORDERY 4
#define MENUMARGIN 20 /* Spacing between menus */
#define TEXTMARGIN 10 /* Space around text items */
#define TEXTGAP 2 /* Space above & below text items *
/
#define RULEHEIGHT 2 /* Height of rules */
#define RULEGAP 6 /* Space above & below rules */
#define RULEMARGIN 10 /* idem, but left & right */
#define MINITEMWIDTH (RULEMARGIN + 10) /* Min. menu item width */
#define SUBX 30 /* Sub item position */
boolean CheckFont(struct Memory *);
struct Memory
{
struct MinList Fonts;
struct MinList Lists;
struct Remember *Mem;
};
struct FontNode
{
struct MinNode fn_Node;
struct TextFont *font;
};
struct ITextNode
{
struct MinNode it_node;
struct IntuiText it;
};
typedef struct Gadget GArray[1];
struct ListInfo
{
struct MinNode li_node;
char *buf;
long len;
struct List *list;
struct MinList ilist;
struct IntuiText *blank;
long nb, current, pos;
struct Gadget *arrow1, *arrow2, *strg, *sld;
GArray *glist;
long visible, exists, dispchars;
ULONG clicksecs, clickmics;
long clickpos;
};
static struct TextAttr topaz8 = { "topaz.font", 8 };
static BYTE fore = 1, back = 0, mode = JAM1, depth = 2;
static struct TextAttr *ta = &topaz8;
static boolean fontopen;
static struct TextFont *font;
static UWORD chip down_data[] = {
0xF83E,0xF83E,0xF83E,0xC006,0xE00E,0xF01E,0xF83E,0xFC7E,
0xFEFE,0xFFFE,0x07C0,0x07C0,0x07C0,0x3FF8,0x1FF0,0x0FE0,
0x07C0,0x0380,0x0100,0x0000
};
static struct Image down_img = {
0, 1,
15, 10,
2,
down_data,
0x0003, 0x0000,
NULL
};
static UWORD chip up_data[] = {
0xFEFE,0xFC7E,0xF83E,0xF01E,0xE00E,0xC006,0xF83E,0xF83E,
0xF83E,0xFFFE,0x0100,0x0380,0x07C0,0x0FE0,0x1FF0,0x3FF8,
0x07C0,0x07C0,0x07C0,0x0000
};
static struct Image up_img = {
0, 1,
15, 10,
2,
up_data,
0x0003, 0x0000,
NULL
};
/* Returns number of nodes, or -1 for failure */
static long build_ilist(struct ListInfo *li)
{
int cnt = 0;
struct Node *scan;
NewList((struct List *)&li->ilist);
for (scan = li->list->lh_Head; scan->ln_Succ; scan = scan->ln_Succ, cnt++)
{
struct ITextNode *in = AllocMem(sizeof(struct ITextNode) + li->dispchar
s + 1, MEMF_CLEAR);
char *str;
struct IntuiText *it;
int j;
if (!in) return -1;
it = (struct IntuiText *)&in->it;
str = (char *)(in + 1);
str[li->dispchars] = '\0';
strncpy(str, scan->ln_Name, li->dispchars);
for (j = strlen(str); j < li->dispchars; j++) str[j] = ' ';
it->FrontPen = fore; it->BackPen = back;
it->DrawMode = JAM2;
it->ITextFont = ta;
it->IText = str;
AddTail((struct List *)&li->ilist, (struct Node *)in);
}
li->exists = li->visible > cnt ? cnt : li->visible;
return cnt;
}
static void free_ilist(struct ListInfo *li)
{
struct MinNode *scan, *next;
for (scan = li->ilist.mlh_Head; next = scan->mln_Succ; scan = next)
FreeMem(scan, sizeof(struct ITextNode) + li->dispchars + 1);
}
static void recalc_glist(struct ListInfo *li)
{
int i;
struct ITextNode *scan;
for (i = 0, scan = (struct ITextNode *)li->ilist.mlh_Head; i < li->pos; i++
, scan = (struct ITextNode *)scan->it_node.mln_Succ)
;
for (i = 0; i < li->exists; i++, scan = (struct ITextNode *)scan->it_node.m
ln_Succ)
(*li->glist)[i].GadgetText = &scan->it;
for (; i < li->visible; i++)
(*li->glist)[i].GadgetText = li->blank;
if (li->current >= li->pos && li->current < li->pos + li->exists)
(*li->glist)[li->current - li->pos].Flags |= SELECTED;
}
struct Memory *NewMemory()
{
struct Memory *mem;
struct Remember *key = NULL;
mem = (struct Memory *)AllocRemember(&key, sizeof(struct Memory), MEMF_CLEA
R);
if (mem)
{
mem->Mem = key;
NewList((struct List *)&mem->Fonts);
NewList((struct List *)&mem->Lists);
}
return(mem);
}
void Free(mem)
struct Memory *mem;
{
struct MinNode *mn;
if (mem)
{
for (mn = mem->Fonts.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
CloseFont(((struct FontNode *)mn)->font);
for (mn = mem->Lists.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
free_ilist((struct ListInfo *)mn);
FreeRemember(&mem->Mem, TRUE);
}
}
void ModSys(f, b, m, font)
long f, b, m;
struct TextAttr *font;
{
if (f != -1) fore = f;
if (b != -1) back = b;
if (m != -1) mode = m;
if (font)
{
ta = font;
fontopen = FALSE;
}
}
void SetDepth(d)
long d;
{
depth = d;
}
struct Requester *InitReq(left, top, width, height, mem)
long left, top, width, height;
struct Memory *mem;
{
struct Requester *req;
req = (struct Requester *)AllocRemember(&mem->Mem, sizeof(struct Requester)
, MEMF_CLEAR);
if (req)
{
req->LeftEdge = left; req->TopEdge = top;
req->Width = width; req->Height = height;
req->BackFill = back;
}
return(req);
}
boolean SetReqBorder(req, type, mem)
struct Requester *req;
LONG type;
struct Memory *mem;
{
struct Border *b = NULL;
switch (type)
{
case 1:
if (!AddRectBorder(&b, XDOUBLEMARGIN / 2, YDOUBLEMARGIN / 2, req->W
idth - XDOUBLEMARGIN, req->Height - YDOUBLEMARGIN, mem))
break;
case 0:
if (!AddRectBorder(&b, 0, 0, req->Width, req->Height, mem))
b = NULL;
break;
default:
b = (struct Border *)type;
break;
}
return((req->ReqBorder = b) != NULL);
}
void SetReqGadgets(req, gl)
struct Requester *req;
struct Gadget *gl;
{
struct Gadget *g;
for (g = gl; g; g = g->NextGadget)
g->GadgetType |= REQGADGET;
req->ReqGadget = gl;
}
void SetReqText(req, it)
struct Requester *req;
struct IntuiText *it;
{
req->ReqText = it;
}
struct Gadget *AddBox(gl, id, text, flags, act, x, y, w, h, thick, mem)
struct Gadget **gl;
char *text;
long id, flags, act, x, y, w, h, thick;
struct Memory *mem;
{
BYTE *data;
struct Gadget *gadg = NULL;
int i, tl, tx, ty, len = strlen(text);
struct RastPort rp, rp2;
struct BitMap bm, bm2;
struct Image *im, *im2;
if (CheckFont(mem) &&
(gadg = (struct Gadget *)AllocRemember(&mem->Mem, sizeof(struct Gadget)
+ 2 * sizeof(struct Image), MEMF_CLEAR)) &&
(data = (BYTE *)AllocRemember(&mem->Mem, 2 * depth * RASSIZE(w, h), MEM
F_CLEAR | MEMF_CHIP)))
{
im2 = (im = (struct Image *)(gadg + 1)) + 1;
InitBitMap(&bm, depth, w, h);
InitBitMap(&bm2, depth, w, h);
for (i = 0; i < depth; i++)
{
bm.Planes[i] = data;
bm2.Planes[i] = data + RASSIZE(w, h) * depth;
data += RASSIZE(w, h);
}
InitRastPort(&rp);
rp.BitMap = &bm;
InitRastPort(&rp2);
rp2.BitMap = &bm2;
SetAPen(&rp, fore);
SetAPen(&rp2, fore);
im->Width = im2->Width = w;
im->Height = im2->Height = h;
im->Depth = im2->Depth = depth;
im->ImageData = (USHORT *)bm.Planes[0];
im2->ImageData = (USHORT *)bm2.Planes[0];
im->PlanePick = im2->PlanePick = 0xff;
SetRast(&rp, back);
SetRast(&rp2, back);
DrawRoundedRect(&rp, 0, 0, w, h);
FillRoundedRect(&rp2, 0, 0, w, h);
if (thick)
{
DrawRoundedRect(&rp, 1, 1, w - 2, h - 2);
DrawRoundedRect(&rp, 1, 0, w - 2, h);
}
SetFont(&rp, font);
SetFont(&rp2, font);
tl = TextLength(&rp, text, len);
tx = (w - tl) / 2;
ty = (h - font->tf_YSize + 1) / 2 + font->tf_Baseline;
SetDrMd(&rp, JAM1);
Move(&rp, tx, ty); Text(&rp, text, len);
SetAPen(&rp2, back); SetDrMd(&rp2, JAM1);
Move(&rp2, tx, ty); Text(&rp2, text, len);
gadg->LeftEdge = x;
gadg->TopEdge = y;
gadg->Width = w;
gadg->Height = h;
gadg->GadgetType = BOOLGADGET;
gadg->GadgetRender = (APTR)im;
gadg->SelectRender = (APTR)im2;
gadg->GadgetID = id;
gadg->Flags = GADGHIMAGE | GADGIMAGE | flags;
gadg->Activation = act;
AppendGadget(gl, gadg);
}
return(gadg);
}
struct Gadget *AddRadio(gl, id, text, side, flags, act, mutex, x, y, w, h, mem)
struct Gadget **gl;
char *text;
long id, side, flags, act, x, y, w, h, mutex;
struct Memory *mem;
{
BYTE *data;
struct Gadget *gadg = NULL;
struct IntuiText *it = NULL;
struct RastPort rp, rp2;
struct BitMap bm, bm2;
struct Image *im, *im2;
int tl, bx, i;
struct AreaInfo areainf;
struct TmpRas tmpras;
BYTE areabuf[4 * 5];
PLANEPTR plane;
if (AddIntuiText(&it, text, side ? w + GADGTEXTX : 0, 0, mem) &&
(gadg = (struct Gadget *)AllocRemember(&mem->Mem, sizeof(struct Gadget)
+ 2 * sizeof(struct Image), MEMF_CLEAR)) &&
(data = (BYTE *)AllocRemember(&mem->Mem, 2 * depth * RASSIZE(w, h), MEM
F_CLEAR | MEMF_CHIP)))
{
tl = IntuiTextLength(it);
it->TopEdge = (h - font->tf_YSize) / 2;
gadg->LeftEdge = side ? x : x - tl - GADGTEXTX;
gadg->TopEdge = y;
gadg->Width = tl + GADGTEXTX + w;
gadg->Height = h;
gadg->GadgetType = BOOLGADGET;
gadg->MutualExclude = mutex;
bx = side ? 0 : tl + GADGTEXTX;
im2 = (im = (struct Image *)(gadg + 1)) + 1;
InitBitMap(&bm, depth, w, h);
InitBitMap(&bm2, depth, w, h);
for (i = 0; i < depth; i++)
{
bm.Planes[i] = data;
bm2.Planes[i] = data + RASSIZE(w, h) * depth;
data += RASSIZE(w, h);
}
InitRastPort(&rp);
rp.BitMap = &bm;
InitRastPort(&rp2);
rp2.BitMap = &bm2;
if (plane = (PLANEPTR)AllocRaster(w, h))
{
InitTmpRas(&tmpras, plane, RASSIZE(w, h));
rp2.TmpRas = &tmpras;
memset(areabuf, 0, sizeof(areabuf));
InitArea(&areainf, (short *)areabuf, 4);
rp2.AreaInfo = &areainf;
SetAPen(&rp, fore);
SetAPen(&rp2, fore);
im->Width = im2->Width = w;
im->Height = im2->Height = h;
im->LeftEdge = im2->LeftEdge = bx;
im->Depth = im2->Depth = depth;
im->ImageData = (USHORT *)bm.Planes[0];
im2->ImageData = (USHORT *)bm2.Planes[0];
im->PlanePick = im2->PlanePick = 0xff;
SetRast(&rp, back);
SetRast(&rp2, back);
DrawEllipse(&rp, w/2, h/2, w/2 - 1, h/2 - 1);
DrawEllipse(&rp2, w/2, h/2, w/2 - 1, h/2 - 1);
AreaEllipse(&rp2, w/2, h/2, w/4, h/4);
AreaEnd(&rp2);
FreeRaster(plane, w, h);
rp2.TmpRas = NULL;
rp2.AreaInfo = NULL;
gadg->GadgetRender = (APTR)im;
gadg->SelectRender = (APTR)im2;
gadg->GadgetText = it;
gadg->GadgetID = id;
gadg->Flags = GADGHIMAGE | GADGIMAGE | flags;
gadg->Activation = act;
AppendGadget(gl, gadg);
}
else
gadg = NULL;
}
return(gadg);
}
struct Gadget *AddOption(gl, id, text, side, flags, act, x, y, w, h, mem)
struct Gadget **gl;
char *text;
long id, side, flags, act, x, y, w, h;
struct Memory *mem;
{
struct Gadget *gadg = NULL;
struct IntuiText *it = NULL;
struct Border *b = NULL, *b2 = NULL;
int tl, bx, f = fore, ba = back;
if (AddIntuiText(&it, text, side ? w + GADGTEXTX : 0, 0, mem) &&
(gadg = (struct Gadget *)AllocRemember(&mem->Mem, sizeof(struct Gadget)
, MEMF_CLEAR)))
{
gadg->Height = h;
tl = IntuiTextLength(it);
it->TopEdge = (h - font->tf_YSize) / 2;
gadg->LeftEdge = side ? x : x - tl - GADGTEXTX;
gadg->TopEdge = y;
gadg->Width = tl + 4 + w;
gadg->GadgetType = BOOLGADGET;
bx = side ? 0 : tl + GADGTEXTX;
if (AddLineBorder(&b, bx, 0, bx + w - 1, h - 1, mem) &&
AddLineBorder(&b, bx + w - 1, 0, bx, h - 1, mem) &&
AddRectBorder(&b, bx, 0, w, h, mem) &&
(fore = ba, back = f, AddLineBorder(&b2, bx, 0, bx + w - 1, h - 1,
mem)) &&
AddLineBorder(&b2, bx + w - 1, 0, bx, h - 1, mem) &&
(fore = f, back = ba, AddRectBorder(&b2, bx, 0, w, h, mem)))
{
gadg->GadgetRender = (APTR)b2;
gadg->SelectRender = (APTR)b;
gadg->GadgetText = it;
gadg->GadgetID = id;
gadg->Flags = GADGHIMAGE | flags;
gadg->Activation = TOGGLESELECT | act;
AppendGadget(gl, gadg);
}
else
gadg = NULL;
}
fore = f; back = ba;
return(gadg);
}
struct Gadget *AddText(struct Gadget **gl, long id, char *text, long above, cha
r *buf, long maxlen, long undo, long flags, long act, long x, long y, long w, lo
ng h, long noborder, struct Memory *mem)
{
BYTE *data;
struct StringInfo *si;
struct Gadget *gadg = NULL;
struct IntuiText *it = NULL;
int tl;
struct Border *b = NULL;
char *undobuf;
data = (BYTE *)AllocRemember(&mem->Mem, sizeof(struct Gadget) + sizeof(stru
ct StringInfo) + (undo ? maxlen + 1: 0), MEMF_CLEAR);
if (data)
{
gadg = (struct Gadget *)data;
si = (struct StringInfo *)(gadg + 1);
undobuf = undo ? data + sizeof(struct Gadget) + sizeof(struct StringInf
o) : NULL;
if (AddIntuiText(&it, text, 0, 0, mem))
{
tl = IntuiTextLength(it);
if (above)
{
it->TopEdge = -font->tf_YSize - GADGTEXTY;
it->LeftEdge = 0;
}
else
{
it->TopEdge = h - font->tf_YSize - 2;
it->LeftEdge = -tl - GADGTEXTX;
}
gadg->LeftEdge = x;
gadg->TopEdge = y;
gadg->Width = w;
gadg->Height = h;
gadg->GadgetType = STRGADGET;
if (noborder || AddRectBorder(&b, -TEXTBORDERX + 1, -TEXTBORDERY +
1, w + TEXTBORDERX, h + TEXTBORDERY, mem))
{
gadg->GadgetRender = (APTR)b;
gadg->GadgetText = it;
gadg->GadgetID = id;
gadg->Flags = GADGHCOMP | flags;
gadg->Activation = act;
gadg->SpecialInfo = (APTR)si;
si->Buffer = buf;
si->UndoBuffer = undobuf;
si->MaxChars = maxlen;
AppendGadget(gl, gadg);
}
else
gadg = NULL;
}
else
gadg = NULL;
}
return(gadg);
}
struct Gadget *AddSlider(struct Gadget **gl, long id, long act, long x, long y,
long w, long h, long vert, long knobsize, struct Memory *mem)
{
BYTE *data;
struct Gadget *gg = NULL;
struct PropInfo *info;
struct Image *im;
data = (BYTE *)AllocRemember(&mem->Mem, sizeof(struct Gadget) + sizeof(stru
ct PropInfo) + sizeof(struct Image), MEMF_CLEAR);
if (data)
{
gg = (struct Gadget *)data;
info = (struct PropInfo *)(data + sizeof(struct Gadget));
im = (struct Image *)(data + sizeof(struct Gadget) + sizeof(struct Prop
Info));
gg->LeftEdge = x;
gg->TopEdge = y;
gg->Width = w;
gg->Height = h;
gg->Flags = GADGHCOMP | GADGIMAGE |
(y < 0 ? GRELBOTTOM : 0) |
(x < 0 ? GRELRIGHT : 0) |
(w < 0 ? GRELWIDTH : 0) |
(h < 0 ? GRELHEIGHT : 0);
gg->Activation = act;
gg->GadgetType = PROPGADGET;
gg->GadgetRender = (APTR)im; /* dummy image, why ? */
gg->SpecialInfo = (APTR)info;
gg->GadgetID = id;
info->Flags = AUTOKNOB |
(vert ? FREEVERT : FREEHORIZ);
if (vert) info->VertBody = knobsize;
else info->HorizBody = knobsize;
AppendGadget(gl, gg);
}
return(gg);
}
/* BUG: Arrows don't use selected colours */
struct ListInfo *AddList(struct Gadget **gl, long id, char *text, struct List *
list, char *buf, long len, long flags, long act, long x, long y, long w, long h,
long noborder, struct Memory *mem)
{
long ok = FALSE;
struct ListInfo *li;
int i;
long nb;
int a = font->tf_YSize;
int dispchars = (w - 15 - 3) / font->tf_XSize;
int nblines = (h - 2) / a;
if (CheckFont(mem) &&
(li = (struct ListInfo *)AllocRemember(&mem->Mem, sizeof(struct ListInf
o) + dispchars + 1, MEMF_CLEAR)))
{
char *spaces = (char *)(li + 1);
memset(spaces, ' ', dispchars);
spaces[dispchars] = '\0';
AddHead((struct List *)&mem->Lists, (struct Node *)li);
if (nblines >= 5 && a * (nblines - 2) - 26 > 20 && w > 15 + 3 + 32)
{
w = font->tf_XSize * dispchars + 15 + 3;
h = a * nblines + 2;
li->buf = buf;
li->len = len;
li->list = list;
li->pos = 0;
li->current = -1;
li->visible = nblines - 2;
li->dispchars = dispchars;
li->clickpos = -1;
if ((li->nb = nb = build_ilist(li)) != -1 &&
AddIntuiText(&li->blank, spaces, 0, 0, mem))
{
struct Gadget *arrow1, *arrow2, *sld;
struct Border *b = NULL;
long knobsize;
if (nb == 0)
knobsize = 0xffff;
else
{
knobsize = 0xffff * li->exists;
knobsize /= nb;
}
if ((sld = AddSlider(gl, id, RELVERIFY, x + w - 16, y + 13, 15,
h - 2 * a - 26, TRUE, knobsize, mem)) &&
(arrow1 = (struct Gadget *)AllocRemember(&mem->Mem, 3 * siz
eof(struct Gadget), MEMF_CLEAR)) &&
AddRectBorder(&b, 0, 0, w, h - 2 * a, mem) &&
AddRectBorder(&b, w - 17, 12, 17, h - 2 * a - 24, mem) &&
AddLineBorder(&b, w - 17, 0, w - 17, h - 2 * a - 1, mem))
{
struct Gadget *strg, *cadre;
int tx;
sld->UserData = (APTR)li;
li->sld = sld;
arrow2 = arrow1 + 1;
arrow1->TopEdge = y + 1;
arrow1->LeftEdge = x + w - 16;
arrow1->Width = 15;
arrow1->Height = 11;
arrow1->Flags = GADGHCOMP | GADGIMAGE;
arrow1->Activation = GADGIMMEDIATE | RELVERIFY;
arrow1->GadgetType = BOOLGADGET;
arrow1->GadgetRender = (APTR)&up_img;
arrow1->UserData = (APTR)li;
arrow1->GadgetID = id;
AppendGadget(gl, arrow1);
li->arrow1 = arrow1;
arrow2->LeftEdge = x + w - 16;
arrow2->TopEdge = y + h - 2 * a - 1 - 11;
arrow2->Width = 15;
arrow2->Height = 11;
arrow2->Flags = GADGHCOMP | GADGIMAGE;
arrow2->Activation = GADGIMMEDIATE | RELVERIFY;
arrow2->GadgetType = BOOLGADGET;
arrow2->GadgetRender = (APTR)&down_img;
arrow2->UserData = (APTR)li;
arrow2->GadgetID = id;
AppendGadget(gl, arrow2);
li->arrow2 = arrow2;
cadre = arrow2 + 1;
cadre->LeftEdge = x;
cadre->TopEdge = y;
cadre->Width = 1;
cadre->Height = 1;
cadre->Flags = GADGHNONE;
cadre->GadgetType = BOOLGADGET;
cadre->GadgetRender = (APTR)b;
cadre->UserData = (APTR)li;
cadre->GadgetID = id;
AppendGadget(gl, cadre);
tx = font->tf_XSize * strlen(text);
if (tx > w - 32) tx = w - 32;
if (strg = AddText(gl, id, text, FALSE, buf, len, TRUE, fla
gs, act | GADGIMMEDIATE, x + tx + GADGTEXTX, y + h - a - 2, w - tx - GADGTEXTX,
a + 2, noborder, mem))
{
GArray *bl;
strg->UserData = (APTR)li;
li->strg = strg;
if (bl = (GArray *)AllocRemember(&mem->Mem, li->visible
* sizeof(struct Gadget), MEMF_CLEAR))
{
li->glist = bl;
for (i = 0; i < li->visible; i++)
{
struct Gadget *gg = &(*bl)[i];
gg->LeftEdge = x + 1;
gg->TopEdge = y + i * a + 1;
gg->Width = w - 18;
gg->Height = a;
gg->Flags = GADGHCOMP;
gg->Activation = GADGIMMEDIATE;
gg->GadgetType = BOOLGADGET;
gg->UserData = (APTR)li;
gg->GadgetID = id;
AppendGadget(gl, gg);
}
recalc_glist(li);
ok = TRUE;
}
}
}
}
}
}
return ok ? li : NULL;
}
long ModifyList(struct Gadget *gg, struct Requester *req, struct Window *win, l
ong up)
{
struct ListInfo *li = (struct ListInfo *)gg->UserData;
int change = FALSE, ret = 0;
switch (gg->GadgetType & ~GADGETTYPE)
{
case STRGADGET:
if (!up && li->current != -1)
{
change = TRUE;
(*li->glist)[li->current - li->pos].Flags &= ~SELECTED;
li->current = li->clickpos = -1;
}
else if (up) ret = 1;
break;
case PROPGADGET:
{
struct PropInfo *pi = (struct PropInfo *)gg->SpecialInfo;
if (li->current != -1) (*li->glist)[li->current - li->pos].Flag
s &= ~SELECTED;
li->pos = (pi->VertPot + 1) * (li->nb - li->exists) >> 16;
recalc_glist(li);
change = TRUE;
}
break;
case BOOLGADGET:
if (gg == li->arrow1 || gg == li->arrow2)
{
if (up)
{
long newpos;
if (li->current != -1) (*li->glist)[li->current - li->pos].
Flags &= ~SELECTED;
newpos = li->pos + (gg == li->arrow1 ? -1 : 1);
if (newpos >= 0 && newpos <= li->nb - li->exists)
{
struct PropInfo *pi = (struct PropInfo *)li->sld->Speci
alInfo;
long newpot;
li->pos = newpos;
newpot = 0xffff * li->pos;
newpot /= li->nb - li->exists;
NewModifyProp(li->sld, win, req, pi->Flags, 0, newpot,
0, pi->VertBody, 1);
recalc_glist(li);
change = TRUE;
}
}
}
else
{
int i, pos = -1;
for (i = 0; i < li->exists; i++)
if (gg == &(*li->glist)[i])
{
pos = i;
break;
}
if (pos != -1)
{
ULONG secs, micros;
struct Node *scan;
CurrentTime(&secs, µs);
if (li->current != -1) (*li->glist)[li->current - li->pos].
Flags &= ~SELECTED;
li->current = li->pos + pos;
(*li->glist)[pos].Flags |= SELECTED;
change = TRUE;
li->buf[li->len - 1] = '\0';
for (i = 0, scan = li->list->lh_Head; i < li->current; i++,
scan = scan->ln_Succ)
;
strncpy(li->buf, scan->ln_Name, li->len - 1);
RefreshGList(li->strg, win, req, 1);
ret = li->clickpos == li->current && DoubleClick(li->clicks
ecs, li->clickmics, secs, micros) ? 2 : 1;
li->clickpos = li->current;
li->clicksecs = secs;
li->clickmics = micros;
}
}
}
if (change) RefreshGList(&(*li->glist)[0], win, req, li->exists);
return ret;
}
long ChangeList(struct ListInfo *li, struct List *list, struct Requester *req,
struct Window *win)
{
struct PropInfo *pi = (struct PropInfo *)li->sld->SpecialInfo;
long knobsize;
free_ilist(li);
li->list = list;
if ((li->nb = build_ilist(li)) != -1)
{
if (li->current != -1) (*li->glist)[li->current - li->pos].Flags &= ~SE
LECTED;
li->pos = 0;
li->current = -1;
li->clickpos = -1;
if (li->nb == 0)
knobsize = 0xffff;
else
{
knobsize = 0xffff * li->exists;
knobsize /= li->nb;
}
NewModifyProp(li->sld, win, req, pi->Flags, 0, 0, 0, knobsize, 1);
recalc_glist(li);
RefreshGList(&(*li->glist)[0], win, req, li->visible);
return TRUE;
}
return FALSE;
}
struct Gadget *ListStr(struct ListInfo *li)
{
return li->strg;
}
struct IntuiText *AddIntuiText(it, str, x, y, mem)
struct IntuiText **it;
char *str;
long x, y;
struct Memory *mem;
{
struct IntuiText *intui = NULL;
if (CheckFont(mem))
{
intui = (struct IntuiText *)AllocRemember(&mem->Mem, sizeof(struct Intu
iText), MEMF_CLEAR);
if (intui)
{
intui->FrontPen = fore; intui->BackPen = back;
intui->DrawMode = mode;
intui->LeftEdge = x; intui->TopEdge = y;
intui->ITextFont = ta;
intui->IText = str;
AppendText(it, intui);
}
}
return(intui);
}
struct Border *AddLineBorder(struct Border **border, long x0, long y0, long x1,
long y1, struct Memory *mem)
{
BYTE *data;
struct Border *bb = NULL;
WORD *vert;
data = (BYTE *)AllocRemember(&mem->Mem, sizeof(struct Border) + 2 * 2 * siz
eof(WORD), MEMF_CLEAR);
if (data) {
bb = (struct Border *)data;
vert = (WORD *)(data + sizeof(struct Border));
bb->FrontPen = fore; bb->BackPen = back;
bb->DrawMode = mode;
bb->LeftEdge = 0; bb->TopEdge = 0;
bb->Count = 2;
bb->XY = vert;
vert[0] = x0; vert[1] = y0;
vert[2] = x1; vert[3] = y1;
AppendBorder(border, bb);
}
return(bb);
}
struct Border *AddRectBorder(border, x, y, w, h, mem)
struct Border **border;
long x, y, w, h;
struct Memory *mem;
{
BYTE *data;
struct Border *bb = NULL;
WORD *vert;
data = (BYTE *)AllocRemember(&mem->Mem, sizeof(struct Border) + 5 * 2 * siz
eof(WORD), MEMF_CLEAR);
if (data) {
bb = (struct Border *)data;
vert = (WORD *)(data + sizeof(struct Border));
bb->FrontPen = fore; bb->BackPen = back;
bb->DrawMode = mode;
bb->LeftEdge = x; bb->TopEdge = y;
bb->Count = 5;
bb->XY = vert;
vert[1 * 2 + 0] = w - 1;
vert[2 * 2 + 0] = w - 1;
vert[2 * 2 + 1] = h - 1;
vert[3 * 2 + 1] = h - 1;
AppendBorder(border, bb);
}
return(bb);
}
struct Menu *AddMenu(struct Menu **ml, struct Screen *scr, char *text, long fla
gs, struct Memory *mem)
{
struct Screen look;
struct TextFont *scrfont;
struct Menu *menu = NULL, *prev;
if (GetScreenData((char *)&look, sizeof(struct Screen), scr == NULL ? WBENC
HSCREEN : CUSTOMSCREEN, scr))
if (scrfont = OpenDiskFont(look.Font))
{
if (menu = (struct Menu *)AllocRemember(&mem->Mem, sizeof(struct Me
nu), MEMF_CLEAR))
{
menu->MenuName = text;
menu->Flags = flags;
menu->Height = scrfont->tf_YSize + 1;
menu->Width = scrfont->tf_XSize * strlen(text) + MENUMARGIN / 2
;
if (*ml == NULL)
{
menu->LeftEdge = 0;
*ml = menu;
}
else
{
for (prev = *ml; prev->NextMenu; prev = prev->NextMenu) ;
prev->NextMenu = menu;
menu->LeftEdge = prev->LeftEdge + prev->Width + MENUMARGIN;
}
}
CloseFont(scrfont);
}
return menu;
}
/* Assumes HIRES screen (for COMMWIDTH) */
struct MenuItem *AddItem(struct Menu *menu, char *text, long flags, long mutex,
long cmd, long sub, struct Memory *mem)
{
struct MenuItem *item = NULL, *prev;
struct IntuiText *it = NULL;
WORD width;
if (AddIntuiText(&it, text, TEXTMARGIN / 2, TEXTGAP / 2, mem))
{
if (item = (struct MenuItem *)AllocRemember(&mem->Mem, sizeof(struct Me
nuItem), MEMF_CLEAR))
{
item->LeftEdge = 0;
width = IntuiTextLength(it) + TEXTMARGIN;
item->Flags = flags | ITEMTEXT;
item->Height = font->tf_YSize + TEXTGAP;
item->MutualExclude = mutex;
item->ItemFill = (APTR)it;
if (cmd)
{
item->Flags |= COMMSEQ;
width += COMMWIDTH + font->tf_XSize;
item->Command = cmd;
}
if (sub)
width += 2 * font->tf_XSize + TEXTMARGIN / 2;
if (width < MINITEMWIDTH) width = MINITEMWIDTH;
if (menu->FirstItem)
{
for (prev = menu->FirstItem; prev->NextItem; prev = prev->NextI
tem) ;
item->TopEdge = prev->TopEdge + prev->Height;
prev->NextItem = item;
if (prev->Width > width)
item->Width = prev->Width;
else
for (prev = menu->FirstItem; prev; prev = prev->NextItem)
{
struct IntuiText *msg;
if ((prev->Flags & ITEMTEXT) == 0) /* A rule */
((struct Image *)(prev->ItemFill))->Width = width -
RULEMARGIN;
else if ((msg = ((struct IntuiText *)(prev->ItemFill))-
>NextText) != NULL) /* A SubItem header */
msg->LeftEdge += width - prev->Width;
prev->Width = width;
}
}
else
{
menu->FirstItem = item;
item->TopEdge = 0;
item->Width = width;
}
if (sub && !AddIntuiText(&it, ".", item->Width - TEXTMARGIN / 2 - f
ont->tf_XSize, TEXTGAP / 2, mem))
item = NULL;
}
}
return item;
}
/* Assumes HIRES screen (for COMMWIDTH) */
struct MenuItem *AddSub(struct MenuItem *item, char *text, long flags, long mut
ex, long cmd, struct Memory *mem)
{
struct MenuItem *subitem = NULL, *prev;
struct IntuiText *it = NULL;
WORD width;
if (AddIntuiText(&it, text, TEXTMARGIN / 2, TEXTGAP / 2, mem))
{
if (subitem = (struct MenuItem *)AllocRemember(&mem->Mem, sizeof(struct
MenuItem), MEMF_CLEAR))
{
subitem->LeftEdge = SUBX;
width = IntuiTextLength(it) + TEXTMARGIN;
subitem->Flags = flags | ITEMTEXT;
subitem->Height = font->tf_YSize + TEXTGAP;
subitem->MutualExclude = mutex;
subitem->ItemFill = (APTR)it;
if (cmd)
{
subitem->Flags |= COMMSEQ;
width += COMMWIDTH + font->tf_XSize;
subitem->Command = cmd;
}
if (width < MINITEMWIDTH) width = MINITEMWIDTH;
if (item->SubItem)
{
for (prev = item->SubItem; prev->NextItem; prev = prev->NextIte
m) ;
subitem->TopEdge = prev->TopEdge + prev->Height;
prev->NextItem = subitem;
if (prev->Width > width)
subitem->Width = prev->Width;
else
for (prev = item->SubItem; prev; prev = prev->NextItem)
prev->Width = width;
}
else
{
item->SubItem = subitem;
subitem->TopEdge = font->tf_YSize / 2 + 1;
subitem->Width = width;
}
}
}
return subitem;
}
/* Inspired by Stuart Ferguson's code */
struct MenuItem *AddRule(struct Menu *menu, struct Memory *mem)
{
struct MenuItem *item = NULL, *prev;
struct Image *img;
if ((img = (struct Image *)AllocRemember(&mem->Mem, sizeof(struct Image), M
EMF_CLEAR)) &&
(item = (struct MenuItem *)AllocRemember(&mem->Mem, sizeof(struct MenuI
tem), MEMF_CLEAR)))
{
item->LeftEdge = 0;
item->Flags = ITEMENABLED | HIGHNONE;
item->Height = RULEGAP + RULEHEIGHT;
item->MutualExclude = 0;
item->ItemFill = (APTR)img;
if (menu->FirstItem)
{
for (prev = menu->FirstItem; prev->NextItem; prev = prev->NextItem)
;
item->TopEdge = prev->TopEdge + prev->Height;
prev->NextItem = item;
item->Width = prev->Width;
}
else
{
menu->FirstItem = item;
item->TopEdge = 0;
item->Width = MINITEMWIDTH;
}
img->LeftEdge = RULEMARGIN / 2;
img->TopEdge = RULEGAP / 2;
img->Width = item->Width - RULEMARGIN;
img->Height = RULEHEIGHT;
img->Depth = depth;
img->ImageData = NULL;
img->PlanePick = 0;
img->PlaneOnOff = fore;
}
return item;
}
boolean CheckFont(mem)
struct Memory *mem;
{
struct FontNode *fn;
if (ta == NULL) fontopen = TRUE;
if (!fontopen)
{
font = (struct TextFont *)OpenDiskFont(ta);
if (font)
{
fn = (struct FontNode *)AllocRemember(&mem->Mem, sizeof(struct Font
Node), MEMF_CLEAR);
if (fn)
{
fn->font = font;
AddHead((struct List *)&mem->Fonts, (struct Node *)fn);
fontopen = TRUE;
}
else CloseFont(font);
}
}
return(fontopen);
}
void AppendGadget(gl, gg)
struct Gadget **gl, *gg;
{
struct Gadget *gadg;
if (*gl == NULL) *gl = gg;
else
{
gadg = *gl;
while (gadg->NextGadget) gadg = gadg->NextGadget;
gadg->NextGadget = gg;
}
}
void AppendBorder(bl, bb)
struct Border **bl, *bb;
{
struct Border *bord;
if (*bl == NULL) *bl = bb;
else
{
bord = *bl;
while (bord->NextBorder) bord = bord->NextBorder;
bord->NextBorder = bb;
}
}
void AppendText(itl, txt)
struct IntuiText **itl, *txt;
{
struct IntuiText *intui;
if (*itl == NULL) *itl = txt;
else
{
intui = *itl;
while (intui->NextText) intui = intui->NextText;
intui->NextText = txt;
}
}
#define Line(rp, x1, y1, x2, y2) { Move((rp), (x1), (y1)); Draw((rp), (x2), (y2
)); }
void DrawRect(rp, x, y, w, h)
struct RastPort *rp;
long x, y, w, h;
{
Move(rp, x, y);
Draw(rp, x + w - 1, y);
Draw(rp, x + w - 1, y + h - 1);
Draw(rp, x, y + h - 1);
Draw(rp, x, y);
}
void DrawRoundedRect(rp, x, y, w, h)
struct RastPort *rp;
long x, y, w, h;
{
int x2 = x + w - 1, y2 = y + h - 1;
Line(rp, x + 5, y, x2 - 5, y); Line(rp, x + 5, y2, x2 - 5, y2);
Line(rp, x, y + 5, x, y2 - 4); Line(rp, x2, y + 5, x2, y2 - 4);
WritePixel(rp, x + 4, y + 1); WritePixel(rp, x + 3, y + 1); WritePixel(rp,
x + 2, y + 2); WritePixel(rp, x + 1, y + 3); WritePixel(rp, x + 1, y + 4);
WritePixel(rp, x + 4, y2 - 1); WritePixel(rp, x + 3, y2 - 1); WritePixel(rp
, x + 2, y2 - 2); WritePixel(rp, x + 1, y2 - 3); WritePixel(rp, x + 1, y2 - 4);
WritePixel(rp, x2 - 4, y + 1); WritePixel(rp, x2 - 3, y + 1); WritePixel(rp
, x2 - 2, y + 2); WritePixel(rp, x2 - 1, y + 3); WritePixel(rp, x2 - 1, y + 4);
WritePixel(rp, x2 - 4, y2 - 1); WritePixel(rp, x2 - 3, y2 - 1); WritePixel(
rp, x2 - 2, y2 - 2); WritePixel(rp, x2 - 1, y2 - 3); WritePixel(rp, x2 - 1, y2 -
4);
}
void FillRoundedRect(rp, x, y, w, h)
struct RastPort *rp;
long x, y, w, h;
{
int x2 = x + w - 1, y2 = y + h - 1;
RectFill(rp, x, y + 5, x2, y2 - 5);
Line(rp, x + 1, y + 4, x2 - 1, y + 4); Line(rp, x + 1, y + 3, x2 - 1, y + 3
); Line(rp, x + 2, y + 2, x2 - 2, y + 2); Line(rp, x + 4, y + 1, x2 - 4, y + 1);
Line(rp, x + 1, y2 - 4, x2 - 1, y2 - 4); Line(rp, x + 1, y2 - 3, x2 - 1, y2
- 3); Line(rp, x + 2, y2 - 2, x2 - 2, y2 - 2); Line(rp, x + 4, y2 - 1, x2 - 4,
y2 - 1);
}