home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Computer Club Elmshorn Atari PD
/
CCE_PD.iso
/
pc
/
0400
/
CCE_0423.ZIP
/
CCE_0423.PD
/
GEM.ZOO
/
gemfw.cc
< prev
next >
Wrap
C/C++ Source or Header
|
1992-04-26
|
6KB
|
299 lines
/////////////////////////////////////////////////////////////////////////////
//
// This file is Copyright 1992 by Warwick W. Allison,
// and is freely distributable providing no charge is made.
//
/////////////////////////////////////////////////////////////////////////////
#include <aesbind.h>
#include <osbind.h>
#include "gemfw.h"
#include "gemo.h"
#include "scancode.h"
// The global int "StartObject" links the call to RedrawOverlaps
// with RedrawOverlaps' calls to Redraw. An alternative solution
// would be to have RedrawOverlaps accept a parameter which it
// just blindly passed to Redraw, however this would involve a
// void* pointer, and would delocalize the issue. When setting
// the StartObject, be sure to reset it to ROOT, since redraw
// events, etc. will also call RedrawOverlaps.
int StartObject=ROOT;
bool GetKey(int& Key)
{
/***** BIOS or GEMDOS based... but both lose characters!
int X,Y,Buttons,Metas;
do {
graf_mkstate(&X,&Y,&Buttons,&Metas);
} while (!Bconstat(2) && !Buttons);
if (Bconstat(2)) {
Key=Bconin(2);
Key=((Key>>8)&0xFF00)|(Key&0xFF);
return TRUE;
} else return FALSE;
*************/
//***** Event-based... but how do we recycle events?
int Pipe[32];
int mx,my,button,meta,count;
ClickResult r=ContinueInteraction;
wind_update(BEG_MCTRL); // So disable those events... POOR SOLUTION!
int got=evnt_multi(MU_KEYBD|MU_BUTTON,
1,1,1,0,0,0,0,0,0,0,0,0,0,
Pipe,0,&mx,&my,&button,&meta,&Key,&count
);
wind_update(END_MCTRL);
if (got&MU_KEYBD) {
return TRUE;
}
return FALSE;
}
void GEMformwindow::Redraw(GRECT& area)
{
objc_draw(Obj, StartObject, MAX_DEPTH, area.g_x, area.g_y, area.g_w, area.g_h);
}
void GEMformwindow::move(int x, int y)
{
// Snap, since forms use 2x2 shades
x=x&~1;
y=y&~1;
GEMwindow::move(x,y);
int X,Y,W,H;
wind_get(Handle,WF_WORKXYWH,&X,&Y,&W,&H);
Obj[0].ob_x=X;
Obj[0].ob_y=Y;
}
GRECT WorkToBorder(int Parts, GEMrealobject& O)
{
GRECT R;
if (Parts>0) {
wind_calc(0,Parts,O.ob_x,O.ob_y,O.ob_width,O.ob_height,&R.g_x,&R.g_y,&R.g_w,&R.g_h);
} else {
R.g_x=0;
R.g_y=0;
R.g_w=0;
R.g_h=0;
}
return R;
}
GEMformwindow::GEMformwindow(int RSCindex, int Parts=NAME|CLOSER|MOVER) :
GEMform(RSCindex),
GEMwindow(Parts, WorkToBorder(Parts,Obj[0]))
{
}
int Parent(GEMrealobject* Form, int o)
{
int n=o;
do {
o=n;
n=Form[n].ob_next;
} while (n>=0 && Form[n].ob_tail!=o);
return n;
}
void WaitForNoButton()
{
int X,Y,Buttons,Metas;
do graf_mkstate(&X,&Y,&Buttons,&Metas); while (Buttons);
}
// Any point in making this a method of GEMrealobjects?
void WatchBox(GEMobject *O)
{
int X,Y,Buttons,Metas;
bool OldOn=O->Selected();
bool On=FALSE;
do {
graf_mkstate(&X,&Y,&Buttons,&Metas);
On=O->ContainsPoint(X,Y);
if (On!=OldOn) {
OldOn=On;
O->Selected(On);
O->Redraw();
}
} while (Buttons && X>10);
}
int FindEditable(GEMrealobject *Obj, int Object, int way)
{
int c=Object+way;
while (1) {
if (c<0) while (!(Obj[++c].ob_flags&LASTOB));
else if (Obj[c].ob_flags&EDITABLE || c==Object) return c;
else if (Obj[c].ob_flags&LASTOB && way>0) c=0;
else c+=way;
}
}
void GEMformwindow::Edit(int Object, int Index)
{
int X,Y,Buttons,Metas;
objc_edit(Obj,Object,0,Index,EDSTART,&Index);
objc_edit(Obj,Object,0,Index,EDINIT,&Index);
do graf_mkstate(&X,&Y,&Buttons,&Metas); while (Buttons);
while (1) {
int Key;
if (!GetKey(Key)) {
objc_edit(Obj,Object,0,Index,EDEND,&Index);
return;
}
switch (Key>>8) {
case KEY_RETURN:
objc_edit(Obj,Object,0,Index,EDEND,&Index);
return;
break; case KEY_UP:
objc_edit(Obj,Object,0,Index,EDEND,&Index);
Object=FindEditable(Obj,Object,-1);
objc_edit(Obj,Object,0,Index,EDINIT,&Index);
break; case KEY_DOWN:
objc_edit(Obj,Object,0,Index,EDEND,&Index);
Object=FindEditable(Obj,Object,+1);
objc_edit(Obj,Object,0,Index,EDINIT,&Index);
break; default:
objc_edit(Obj,Object,Key,Index,EDCHAR,&Index);
}
}
}
bool inside(int x, int y, const GRECT& pt)
{
return ( x>=pt.g_x && y>=pt.g_y && x<pt.g_x+pt.g_w && y<pt.g_y+pt.g_h );
}
void GEMformwindow::top(int x, int y)
{
GRECT R;
wind_calc(1,parts,Pos.g_x,Pos.g_y,Pos.g_w,Pos.g_h,&R.g_x,&R.g_y,&R.g_w,&R.g_h);
if (inside(x,y,R)) click(x,y);
else GEMwindow::top(x,y);
}
ClickResult GEMformwindow::click(int x, int y)
{
int o=objc_find(Obj,ROOT,MAX_DEPTH,x,y);
if (o<0) return ContinueInteraction;
while (o>=0 && !Obj[o].Disabled() && !Obj[o].RadioButton()
&& !Obj[o].TouchExit() && !Obj[o].Editable()
&& !Obj[o].Exit() && !Obj[o].Selectable()) {
o=Parent(Obj,o);
}
if (o<0) o=0;
GEMobject *O=Caller(o);
int Dummy=O==0;
if (Dummy) O=new GEMobject(o,this);
if (O->Disabled()) {
if (Dummy) delete O;
return ContinueInteraction;
}
if (O->RadioButton()) {
if (!O->Selected()) {
int p=Parent(Obj,o);
int c=Obj[p].ob_head;
while (c!=p) {
GEMobject P(c,this);
if (P.Selected()) {
P.Deselect();
P.Redraw();
}
c=Obj[c].ob_next;
}
O->Select();
O->Redraw();
}
} else {
if (O->Selectable()) {
if (O->Selected()) O->Deselect();
else O->Select();
O->Redraw();
}
}
if (O->TouchExit()) {
int X,Y;
objc_offset(Obj,o,&X,&Y);
O->touch(x-X,y-Y);
}
if (O->Editable()) {
Edit(o,1/* Column */);
}
if (O->Exit()) {
if (O->Selectable()) {
WatchBox(O);
if (O->Selected()) {
O->Deselect();
O->Redraw();
}
} else {
WaitForNoButton();
}
} else {
if (O->Selectable() && !O->RadioButton()) {
WaitForNoButton();
}
}
if (Dummy) delete O;
return ContinueInteraction;
}
void GEMformwindow::RedrawObject(int RSCindex)
{
GRECT R;
objc_offset(Obj,RSCindex,&R.g_x,&R.g_y);
R.g_w=Obj[RSCindex].ob_width;
R.g_h=Obj[RSCindex].ob_height;
StartObject=RSCindex;
RedrawOverlaps(R);
StartObject=ROOT;
}
void GEMformwindow::RedrawObject(int RSCindex,int Cx,int Cy,int Cw,int Ch) // Clipped
{
GRECT R;
objc_offset(Obj,RSCindex,&R.g_x,&R.g_y);
R.g_x+=Cx;
R.g_y+=Cy;
R.g_w=Cw;
R.g_h=Ch;
StartObject=RSCindex;
RedrawOverlaps(R);
StartObject=ROOT;
}