home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
191.lha
/
Snip_It_sources_v1.2
/
hand.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-04-28
|
12KB
|
574 lines
/* :ts=4
*
* Amiga SnipIt 1.2
* (c) (opyright 1987,1988 - Scott Evernden - All Rights Reserved
*
* hand.c - input event handler & snipper & lib function replacements
*
*/
#include "hs.h"
int state; /* mouse state */
int snip; /* container type which is highlighted */
int maxx, maxy; /* maximum cells in snipped layer */
int origx, origy; /* pixel origin in conunit */
int charx, chary; /* pixel size of char cell of conunit */
int lastx, lasty; /* last cell highlighted */
int con_offx, con_offy; /* correction offsets for console windows */
int win_offx, win_offy; /* correction offsets for non-console windows */
int snipx[2], snipy[2]; /* snip area; top/left to bottom/right */
int left, right; /* sides of snip area, irrespective of rows */
struct TextFont *capttf; /* non-NULL indicates recognition required */
struct Window *snipw; /* clipped text window */
struct RastPort *sniprp; /* rastport of clipped text window */
struct RastPort captrp; /* rastport holding clipped snip area */
struct BitMap captbm; /* bitmap into which snipped area is copied */
int captx, capty; /* dimensions of capture map */
int jobFlag; /* flag input handler to ignore mouse events */
int lock_layer; /* lock window/console layer while snipping */
int windows=1; /* include windows in layer search */
int cmd1 = IEQUALIFIER_LCOMMAND;
int cmd2 = IEQUALIFIER_LALT;
extern struct IntuitionBase *IntuitionBase;
extern struct ConsoleBase *ConsoleBase;
extern struct Task *myTask;
extern int mySignal;
/* this does one at a time */
struct InputEvent *doEvent();
/*********************************************/
#asm
public _geta4
; Trap these Gfx/Intui functions; purpose is to remove hilighting, if nec.
; Not all possible cases are handled (window resizing, for example), but
; the most common ones are.
public _myRectFill
public _myScrollRaster
public _myCloseWindow
public _oldRectFill
public _oldScrollRaster
public _oldCloseWindow
_myRectFill: ; pardon me
move.l a4,-(sp)
jsr _geta4 ; establish addressing
tst.w _snip
beq.s 1$ ; no highlighted area; get out
cmpa.l _sniprp,a1
bne.s 1$ ; not the same RastPort; get out
movem.l a1/d0-d5,-(sp)
jsr _clearHi ; de-highlight
movem.l (sp)+,a1/d0-d5
1$: movea.l _oldRectFill,a0
movea.l (sp)+,a4
jmp (a0) ; continue into library
_myScrollRaster: ; 'scuse
move.l a4,-(sp)
jsr _geta4
tst.w _snip
beq.s 1$
cmpa.l _sniprp,a1
bne.s 1$
movem.l a1/d0-d5,-(sp)
jsr _clearHi
movem.l (sp)+,a1/d0-d5
1$: movea.l _oldScrollRaster,a0
movea.l (sp)+,a4
jmp (a0)
_myCloseWindow:
move.l a4,-(sp)
jsr _geta4
tst.w _snip
beq.s 1$
cmpa.l _snipw,a0
bne.s 1$ ; not the same Window; get out
clr.w _snip
clr.l _capttf ; Window closing; reset indicators
1$: movea.l _oldCloseWindow,a1
movea.l (sp)+,a4
jmp (a1)
;************************
; input event stream glue
public _handlerCode
_handlerCode:
movem.l d2/d3/a0/a1/a4/a6,-(sp) ; i think this is right
jsr _geta4
jsr _myHandler
movem.l (sp)+,d2/d3/a0/a1/a4/a6
rts
#endasm
/*********************************************/
/* SnipIt's input event handler */
struct InputEvent *myHandler(d2, d3, ev)
long d2, d3;
register struct InputEvent *ev;
{
register struct InputEvent *inev, **evp;
struct InputEvent *outev;
if (jobFlag)
return ev;
inev = ev;
outev = NULL;
/* back-pointer */
evp = &outev;
/*
* Loop thru the possibly linked list of events.
* We remove the ones having meaning to SnipIt, and leave the others
*/
while (inev) {
ev = inev;
inev = ev->ie_NextEvent;
/* ensure that main code isn't running and this is a mouse event */
if (ev->ie_Class == IECLASS_RAWMOUSE)
ev = doEvent(ev);
/* patch back-pointer */
if (*evp = ev)
evp = &ev->ie_NextEvent;
}
/* pass 'em along */
return outev;
}
/*********************************************/
/* handle a single (mouse) input event */
struct InputEvent *doEvent(ev)
register struct InputEvent *ev;
{
static int lflag, rflag, cmd;
register UWORD code;
register int x, y;
x = ev->ie_X;
y = ev->ie_Y;
code = ev->ie_Code;
/* in mid-snip? */
if (lflag && code == IECODE_NOBUTTON &&
(ev->ie_Qualifier & IEQUALIFIER_LEFTBUTTON)) {
mouse(M_MOVE, x, y);
return ev;
}
/* button transition event... */
code &= ~IECODE_UP_PREFIX;
/* mouse button down event? */
if ((ev->ie_Code & IECODE_UP_PREFIX) == 0) {
if (cmd = ev->ie_Qualifier & (cmd1 | cmd2)) {
if (!rflag && code == IECODE_LBUTTON) {
lflag++;
mouse(M_DOWN, x, y);
}
else if (!lflag && code == IECODE_RBUTTON)
rflag++; /* note transition */
return NULL;
}
}
/* release of left mouse button? */
else if (lflag && code == IECODE_LBUTTON) {
lflag = 0;
mouse(M_UP, x, y);
return NULL;
}
/* release of right mouse button? */
else if (rflag && code == IECODE_RBUTTON) {
rflag = 0;
/* kick main code */
jobFlag = cmd;
Signal(myTask, 1L << mySignal);
return NULL;
}
/* event back into stream */
return ev;
}
/*********************************************/
/* find a console containing the layer holding (x,y); return success flag */
int whichConsole(layer, x, y)
struct Layer *layer;
int x, y;
{
register struct ConUnit *cu, *rcu;
register struct Node *node;
/* result conunit */
rcu = NULL;
_Forbid();
/* begin at the beginning */
node = ConsoleBase->conUnits.lh_Head;
/* next is NULL when back at listhead */
while (node->ln_Succ) {
cu = (struct ConUnit *) node;
/* see if console window's layer is the same */
if (cu && cu->cu_Window && cu->cu_Window->RPort->Layer == layer) {
rcu = cu; /* found it */
break;
}
node = node->ln_Succ;
}
Permit();
if (rcu) {
snip = CON_SNIP;
snipw = rcu->cu_Window;
sniprp = snipw->RPort;
charx = rcu->cu_XRSize;
chary = rcu->cu_YRSize;
origx = rcu->cu_XROrigin;
origy = rcu->cu_YROrigin;
maxx = rcu->cu_XMax;
maxy = rcu->cu_YMax;
}
return rcu != NULL;
}
/*********************************************/
/* find a window containing the layer holding (x,y); return success flag */
int whichWindow(s, layer, x, y)
struct Screen *s;
struct Layer *layer;
int x, y;
{
register struct Window *w, *rw;
if (!windows)
return NULL;
/* result window */
rw = NULL;
_Forbid();
w = s->FirstWindow;
while (w) {
if (w->WLayer == layer) {
rw = w;
break;
}
w = w->NextWindow;
}
Permit();
if (rw) {
snip = WIN_SNIP;
snipw = rw;
sniprp = snipw->RPort;
charx = sniprp->Font->tf_XSize;
chary = sniprp->Font->tf_YSize;
origx = rw->BorderLeft;
origy = rw->BorderTop;
maxx = (rw->Width - rw->BorderRight - origx) / charx - 1;
maxy = (rw->Height - rw->BorderBottom - origy) / chary - 1;
}
return rw != NULL;
}
/*********************************************/
/* handle meaningful mouse activity */
mouse(event, mx, my)
int event;
register int mx, my;
{
static struct Screen *s;
static struct Layer *layer;
if (event == M_DOWN)
s = IntuitionBase->FirstScreen;
/* correct raw positions according to this screen */
if (!(s->ViewPort.Modes & LACE))
my /= 2;
mx += s->MouseX - 2; /* accumulate deltas */
my += s->MouseY - 1; /* x,y adjusted for feel */
if (event == M_DOWN) {
/* de-hilight, if nec. */
if (snip)
hiSnip(0);
/* turn flag off */
snip = 0;
/* locate pointed-at layer */
if ((layer = WhichLayer(&s->LayerInfo, (long) mx, (long) my)) &&
(whichConsole(layer, mx, my) || whichWindow(s, layer, mx, my))) {
/* if mouse down in title line area, remain clear */
if (my - snipw->TopEdge < origy)
snip = 0;
}
}
/* nothing interesting */
if (!snip)
return;
/* mouse to window-relative cell coordinates */
mx = (mx - snipw->LeftEdge - origx) / charx;
if (mx < 0)
mx = 0;
else if (maxx < mx)
mx = maxx;
my = (my - snipw->TopEdge - origy) / chary;
if (my < 0)
my = 0;
else if (maxy < my)
my = maxy;
/* highlighting games ahead */
if (event == M_DOWN) {
state = M_DOWN;
if (lock_layer)
LockLayerRom(layer);
snipx[0] = mx;
snipy[0] = my;
hiLite(mx, my, 1, 1);
}
else if (event == M_UP) {
snipx[1] = mx;
snipy[1] = my;
if (state == M_MOVE)
hiLite(lastx, lasty, 1, 1);
hiLite(snipx[0], snipy[0], 1, 1);
hiSnip(charx == 8);
state = M_UP;
if (charx != 8) /* only able to do 8 pixel wide fonts */
clearHi();
if (lock_layer)
UnlockLayerRom(layer);
}
else if (mx != lastx || my != lasty) {
if (state == M_MOVE)
hiLite(lastx, lasty, 1, 1);
hiLite(lastx = mx, lasty = my, 1, 1);
state = M_MOVE;
}
}
/*********************************************/
/* de-highlight; snip is known to be set */
clearHi()
{
if (state == M_UP)
hiSnip(0);
else if (lock_layer)
return;
else {
hiLite(snipx[0], snipy[0], 1, 1);
if (state == M_MOVE)
hiLite(lastx, lasty, 1, 1);
}
snip = 0;
}
/*********************************************/
/* local cleanup for this module */
finiHand()
{
int i;
PLANEPTR p;
if (snip)
clearHi();
if (p = captbm.Planes[0])
FreeRaster(p, (long) captx, (long) capty);
}
/*********************************************/
/* manufacture rastport with bitmap, ready to receive captured bitmap */
int allocMap(sx, sy)
int sx, sy;
{
PLANEPTR p;
/* release previous, if any */
if (p = captbm.Planes[0]) {
FreeRaster(p, (long) captx, (long) capty);
captbm.Planes[0] = NULL;
}
/* record new map size */
captx = sx;
capty = sy;
/* build new bitmap to contain snipped area */
InitBitMap(&captbm, 1L, (long) captx, (long) capty);
InitRastPort(&captrp);
captrp.BitMap = &captbm;
/* allocate bitmap planes */
p = (PLANEPTR) AllocRaster((long) captx, (long) capty);
if (!p)
return 0;
captbm.Planes[0] = p;
return 1;
}
/*********************************************/
/* video reverse the capture area; perform capture if flagged */
hiSnip(capt)
int capt;
{
register int px, py, qx, qy, tx, ty;
long ox, oy;
/* need these vars to be handy */
tx = maxx;
/* take care of backward snip areas */
if (snipy[0] < snipy[1] ||
snipy[0] == snipy[1] && snipx[0] <= snipx[1]) {
px = snipx[0];
py = snipy[0];
qx = snipx[1];
qy = snipy[1];
}
else {
px = snipx[1];
py = snipy[1];
qx = snipx[0];
qy = snipy[0];
}
/* only if capturing more than 1 cell... */
if (capt && (px != qx || py != qy)) {
/* left and right sides */
left = px;
right = qx;
/* get a new bitmap */
if (allocMap((tx + 1) * charx, (qy - py + 1) * chary)) {
/* copy console contents into snip-map */
ox = origx;
oy = origy + py * chary;
if (snip == CON_SNIP) { /* user-specified corrections */
ox += con_offx;
oy += con_offy;
}
else {
ox += win_offx;
oy += win_offy;
}
ClipBlit(sniprp, ox, oy, &captrp, 0L, 0L,
(long) captx, (long) capty, 0xC0L);
/* note new info in snip-map */
capttf = sniprp->Font;
}
else {
/* no memory, act dumb */
snip = captx = capty = 0;
return;
}
}
/* perform hilighting */
while (py <= qy) {
if (py == qy)
tx = qx;
hiLite(px, py, tx - px + 1, 1);
px = 0;
py++;
}
}
/*********************************************/
/* low-lever video reverser */
hiLite(x, y, xs, ys)
int x, y, xs, ys;
{
register long ox, oy;
ox = origx + x * charx;
oy = origy + y * chary;
if (snip == CON_SNIP) { /* user-specified corrections */
ox += con_offx;
oy += con_offy;
}
else {
ox += win_offx;
oy += win_offy;
}
ClipBlit(sniprp, ox, oy, sniprp, ox, oy,
(long) (xs * charx), (long) (ys * chary), 0x50L);
}
/*********************************************/