UPLOAD - DOSUIT07.ZIP - EVENT.CPP

 
Output of file : EVENT.CPP contained in archive : DOSUIT07.ZIP

#include
#include
#include
#include
#ifdef __ZTC__
#include
#include
#include
#endif
#include "event.hpp"
#include "applic.hpp"
#include "command.hpp"
#ifdef __TURBOC__
#include
#ifdef enable
#undef enable
#endif
#ifdef disable
#undef disable
#endif
#endif

#ifdef __TURBOC__
extern int disp_numrows, disp_numcols, disp_mode, disp_mono;

static union REGS mouse_regs;

static void mousecall(int callno)
{
mouse_regs.x.ax = callno;
int86(0x33,&mouse_regs,&mouse_regs);
}

static int msm_inited;

int msm_init()
{
mousecall(0);
msm_inited = (mouse_regs.x.ax == 0xffff);
return msm_inited;
}

int msm_getstatus(unsigned *x,unsigned *y)
{
if(!msm_inited)
{
*x = *y = 0;
return 0;
}
mousecall(3);
*x = mouse_regs.x.cx;
*y = mouse_regs.x.dx;
return mouse_regs.x.bx;
}

void msm_setareax(unsigned minx,unsigned maxx)
{
mouse_regs.x.cx = minx;
mouse_regs.x.dx = maxx;
mousecall(7);
}

void msm_setareay(unsigned miny,unsigned maxy)
{
mouse_regs.x.cx = miny;
mouse_regs.x.dx = maxy;
mousecall(8);
}

void msm_setcurpos(unsigned x, unsigned y)
{
mouse_regs.x.cx = x;
mouse_regs.x.dx = y;
mousecall(4);
}

void msm_showcursor()
{
if(msm_inited)
mousecall(1);
}

void msm_hidecursor()
{
if(msm_inited)
mousecall(2);
}

void msm_term()
{
if(msm_inited)
{
mousecall(0);
msm_inited = 0;
}
}

#endif

Event::~Event()
{
}

int FocusEvent::despatch(Window *)
{
int result = 0;
VObject *f;

for(f = Application::kbdfocus();
f && (result = handle(f)) == 0;
f = f->getcontainer())
;
if(!result)
result = handle(0);
return result;
}

PositionEvent::PositionEvent(const Point &here)
: p(here)
{
}

int PositionEvent::despatch(Window *)
{
if(Application::moufocus())
{
Application::moufocus()->getwindow()->windowCoords(p);
return handle(Application::moufocus());
}

Window *w = application->containingWindow(p);
int result = 0;

if(w)
{
w->windowCoords(p);

VObject *f = w->containingObject(p);

for( ; f && f != w; f = f->getcontainer())
{
result = handle(f);
if(result)
break;
}
if(result)
return result;
w->screenCoords(p);
result = handle(w);
if(result)
return result;
}
return 0;
}

EventSource::EventSource(const char *name)
: NamedProtected(name), enabledOK(0)
{
}

EventSource::~EventSource()
{
disable(); // Must be repeated in derived classes
eventQueue.remove(this);
}

int EventSource::v_enable()
{
return 1;
}

void EventSource::v_disable()
{
}

KeyboardEvent::KeyboardEvent()
: val(0), shstate(0)
{
}

int KeyboardEvent::despatch(Window *w)
{
int result = FocusEvent::despatch(w);

if(result || !value())
return result;

for(VObject *f = Application::kbdfocus();
f && (result = f->dohotkey(*this)) == 0;
f = f->getcontainer())
;
if(!result)
result = application->dohotkey(*this);
return result;
}

int KeyboardEvent::handle(VObject *o)
{
return (o && o->testcFlag(CFactive)) ? o->kbdevent(*this) : application->kbdevent(*this);
}

class Keyboard : public EventSource {
virtual Event *v_poll();
public:
Keyboard();
};

static KeyboardEvent kbdEvent;
static Keyboard keyboard;

Keyboard::Keyboard()
: EventSource("Keyboard")
{
}

Event *Keyboard::v_poll()
{
if(!bioskey(1))
return 0;
kbdEvent.shstate = bioskey(2);
kbdEvent.val = bioskey(0);
if(kbdEvent.val == 0) // CtrlBreak - will be got by Interrupt
return 0;
if(kbdEvent.val & 0xff)
kbdEvent.val &= 0xff;
#ifndef NDEBUG
if(VObject::debug)
fprintf(VObject::debug,"KeyboardEvent %d %04x\n", kbdEvent.val, kbdEvent.shstate);
#endif
return &kbdEvent;
}

static Point lastpos;
static MouseButtons lastbuttons = MBnone;
static int dmode;
static int clicked = 0, doubleclicked = 0;
static long lasttime;

MouseEvent::MouseEvent(mouseEventFunc handler,const char *name,
const Point &here, MouseButtons buttons)
: PositionEvent(here), func(handler), namestring(name), btns(buttons)
{
}

int MouseEvent::handle(VObject *o)
{
if(o && o->testcFlag(CFactive) && o->handle(*this))
{
clicked = 0;
doubleclicked = 0;
return 1;
}
return 0;
}

MouseMovement::MouseMovement(const Point &here)
: MouseEvent(&VObject::mousemove,"move",here)
{
}

MouseMovement::MouseMovement()
: MouseEvent(&VObject::mousemove,"move",lastpos)
{
}

int MouseMovement::handle(VObject *o)
{
int r = 0;

if(o && o == Application::moufocus())
{
if((r = MouseEvent::handle(o)) == 0)
r = o->mousemove(*this);
}
return r;
}

#ifndef NINSPECT
MouseInspect::MouseInspect(const Point &here)
: MouseEvent(&VObject::inspectclick,"inspect",here)
{
}

int MouseInspect::handle(VObject *o)
{
return (o) ? o->handle(*this) : 0;
}
#endif

class Mouse : public EventSource {
virtual Event *v_poll();
virtual int v_enable();
virtual void v_disable();
public:
Mouse();
~Mouse();
};

static MouseEvent *mouEvent;
static MouseMovement mouMovement;
static MouseInspect mouInspect;
static MouseEvent leftdown(&VObject::leftdown,"leftdown");
static MouseEvent leftup(&VObject::leftup,"leftup");
static MouseEvent leftclick(&VObject::leftclick,"leftclick");
static MouseEvent leftdoubleclick(&VObject::leftdoubleclick,"leftdoubleclick");
static MouseEvent rightdown(&VObject::rightdown,"rightdown");
static MouseEvent rightup(&VObject::rightup,"rightup");
static MouseEvent rightclick(&VObject::rightclick,"rightclick");
static MouseEvent rightdoubleclick(&VObject::rightdoubleclick,"rightdoubleclick");
static MouseEvent middledown(&VObject::middledown,"middledown");
static MouseEvent middleup(&VObject::middleup,"middleup");
static MouseEvent middleclick(&VObject::middleclick,"middleclick");
static MouseEvent middledoubleclick(&VObject::middledoubleclick,"middledoubleclick");
static MouseEvent *mouseEvents[] =
{
&leftdown,
&leftup,
&leftclick,
&leftdoubleclick,
&rightdown,
&rightup,
&rightclick,
&rightdoubleclick,
&middledown,
&middleup,
&middleclick,
&middledoubleclick
};

static Mouse mouse;
int MouseEvent::doubleClickTime = 50;

Mouse::Mouse()
: EventSource("Mouse")
{
}

Mouse::~Mouse()
{
disable();
}

Event *Mouse::v_poll()
{
static int moved = 1, lastclick = 0;
long now;
static MouseButtons buttons;
static unsigned int changes, x, y;

if(doubleclicked)
{
mouEvent = mouseEvents[doubleclicked];
lasttime = 0;
lastclick = 0;
doubleclicked = 0;
}
else if(clicked)
{
mouEvent = mouseEvents[clicked];
if(lastclick == clicked)
{
now = clock();
if(now - lasttime <= MouseEvent::doubleClickTime)
doubleclicked = clicked + 1;
}
lastclick = clicked;
clicked = 0;
lasttime = clock();
}
else
{
buttons = (MouseButtons)(msm_getstatus(&x,&y) & (MBleft|MBright|MBmiddle));
if(dmode == 0 || dmode == 1)
x /= 16;
else // Translate to disp package coordinates (row, col)
x /= 8;
y /= 8;
if(lastpos.x != x || lastpos.y != y)
{
mouEvent = &mouMovement;
lastpos.x = x;
lastpos.y = y;
moved = 1;
lasttime = 0;
}
else if((changes = buttons ^ lastbuttons) != 0)
{
unsigned int t = 1;
int v;

for(v = 0; !(t & changes); t <<= 1)
v += 4;
if(!(buttons & t))
{
v++;
if(!moved)
clicked = v + 1;
}
else
moved = 0;
lastbuttons = buttons;
mouEvent = mouseEvents[v];
#ifndef NINSPECT
if(v == 0 && (bioskey(2) & 8))
{
clicked = 0;
doubleclicked = 0;
mouEvent = &mouInspect;
buttons = MouseButtons(buttons | MBinspect);
}
#endif
}
else
return 0; // Nothing has changed
}
mouEvent->btns = buttons;
mouEvent->p.x = x;
mouEvent->p.y = y;
#ifndef NDEBUG
if(VObject::debug)
fprintf(VObject::debug,"MouseEvent %s[%d,%d] %x\n",
mouEvent->name(), x, y, buttons);
#endif
return mouEvent;
}

static unsigned int mousavedx = 0, mousavedy = 0;

int Mouse::v_enable()
{
#ifdef __ZTC__
dmode = disp_getmode();
#endif
#ifdef __TURBOC__
dmode = disp_mode;
#endif
lastbuttons = MBnone;
if(msm_init()) // returns non-zero on success, despite documentation !
{
int maxy = (disp_numrows - 1) * 8;
int maxx = (disp_numcols - 1) * ((dmode == 0 || dmode == 1) ? 16 : 8);

// Mouse driver sometimes gets the number of screen rows wrong,
// so here we force it to whatever disp_open() discovered.
msm_setareay(0,maxy);
msm_setareax(0,maxx);
if(mousavedx < maxx && mousavedy < maxy)
msm_setcurpos(mousavedx, mousavedy);
msm_showcursor(); // turn mouse cursor on
return 1;
}
return 0;
}

void Mouse::v_disable()
{
msm_getstatus(&mousavedx, &mousavedy);
msm_term();
}

extern "C"
{ // Interrupt handlers need C linkage

static volatile int intflag;
#ifdef __ZTC__
static int ctrl_break_handler(INT_DATA *id)
{
int bb = 0;

poke(0x40,0x71,&bb,1); // Clear BIOS break flag
intflag = 1;
return 1; // Don't chain the DOS version
}
#endif
}

int InterruptEvent::handle(VObject *o)
{
return (o ? o->interruptevent(*this) : application->interruptevent(*this));
}

class Interrupt : public EventSource {
virtual Event *v_poll();
virtual int v_enable();
virtual void v_disable();
public:
Interrupt();
~Interrupt();
};

static InterruptEvent intEvent;
static Interrupt anInterupt;

Interrupt::Interrupt()
: EventSource("Interrupt")
{
}

Interrupt::~Interrupt()
{
disable();
}

Event *Interrupt::v_poll()
{
if(!intflag)
return 0;
while(bioskey(1))
bioskey(0); // Remove any dummy key press
intflag = 0;
#ifndef NDEBUG
if(VObject::debug)
fprintf(VObject::debug,"InterruptEvent\n");
#endif
return &intEvent;
}

int Interrupt::v_enable()
{
#ifdef __ZTC__
int_intercept(0x1b,ctrl_break_handler,128); // Trap DOS ^C
#endif
return 1;
}

void Interrupt::v_disable()
{
#ifdef __ZTC__
int_restore(0x1b);
#endif
}

declare(GQueue,Event);

class UEventQueue : public EventSource /* , private GQueue(UserEvent) */ {
virtual Event *v_poll();
public: // commented out items show bug in 2.xx compiler
UEventQueue();
// GQueue(Event)::put;
void put(Event *e) { queue.put(e); } // ZTC bug
private: // ZTC bug
GQueue(Event) queue;// ZTC bug
};

static UEventQueue user;

UEventQueue::UEventQueue()
: EventSource("UEventQueue")
{
}

Event *UEventQueue::v_poll()
{
// Event *e = get();
Event *e = queue.get(); // ZTC bug
#ifndef NDEBUG
if(e && VObject::debug)
fprintf(VObject::debug,"UEvent @%p\n", e);
#endif
return e;
}

CommandEvent::CommandEvent(Command *command)
: cmd(command)
{
user.put(this);
}

int CommandEvent::despatch(Window *control)
{
int r = handle(control);

delete this;
return r;
}

int CommandEvent::handle(VObject *o)
{
return cmd->doit(o->name());
}

int EventQueue::cons = 0;

EventQueue::EventQueue()
{
cons = 1;
add(&user);
add(&anInterupt);
add(&keyboard);
add(&mouse);
}

EventQueue::~EventQueue()
{
cons = 0;
}

void EventQueue::enable()
{
VALIDATE(this);
GIterator(EventSource) next(*this);
EventSource *s;

while((s = next()) != 0)
s->enable();
}

void EventQueue::disable()
{
VALIDATE(this);
GIterator(EventSource) next(*this);
EventSource *s;

while((s = next()) != 0)
s->disable();
}

int EventQueue::add(EventSource *item)
{
if(!constructed())
return 0;
VALIDATE(this);
return GCollection(EventSource)::add(item);
}

int EventQueue::remove(EventSource *item)
{
if(!constructed())
return 0;
VALIDATE(this);
return GCollection(EventSource)::remove(item);
}

Event *EventQueue::operator() ()
{
VALIDATE(this);
GIterator(EventSource) next(*this);
EventSource *s;
Event *e;

while((s = next()) != 0)
if((e = s->poll()) != 0)
return e;
return 0;
}