executor/src/listMouse.c

427 lines
12 KiB
C

/* Copyright 1989, 1990 by Abacus Research and
* Development, Inc. All rights reserved.
*/
#if !defined (OMIT_RCSID_STRINGS)
char ROMlib_rcsid_listMouse[] =
"$Id: listMouse.c 63 2004-12-24 18:19:43Z ctm $";
#endif
/* Forward declarations in ListMgr.h (DO NOT DELETE THIS LINE) */
#include "rsys/common.h"
#include "EventMgr.h"
#include "ToolboxEvent.h"
#include "ToolboxUtil.h"
#include "OSEvent.h"
#include "ControlMgr.h"
#include "ListMgr.h"
#include "rsys/cquick.h"
#include "rsys/list.h"
#include "rsys/pstuff.h"
#include "rsys/hook.h"
A2(PRIVATE, void, findcell, Cell *, cp, ListHandle, list)
{
cp->h = CW((CW(cp->h) - Hx(list, rView.left)) / Hx(list, cellSize.h) +
Hx(list, visible.left));
cp->v = CW((CW(cp->v) - Hx(list, rView.top)) / Hx(list, cellSize.v) +
Hx(list, visible.top));
if (CW(cp->h) >= Hx(list, visible.right))
cp->h = CWC(32767);
if (CW(cp->v) >= Hx(list, visible.bottom))
cp->v = CWC(32767);
}
A4(PRIVATE, void, setselectnilflag, BOOLEAN, setit, Cell, cell,
ListHandle, list, BOOLEAN, hiliteempty)
{
GrafPtr saveport;
RgnHandle saveclip;
Rect r;
INTEGER *ip, off0wbit, off0, off1;
LISTDECL();
if ((ip = ROMlib_getoffp(cell, list))) {
off0wbit = CW(*ip);
if (setit)
*ip = CW(off0wbit | 0x8000);
else
*ip = CW(off0wbit & 0x7FFF);
if (PtInRect(cell, &HxX(list, visible)) &&
(!(off0wbit & 0x8000) ^ !setit)) {
off0 = off0wbit & 0x7FFF;
off1 = CW(ip[1]) & 0x7FFF;
if (hiliteempty || off0 != off1) {
C_LRect(&r, cell, list);
saveport = thePort;
SetPort(HxP(list, port));
saveclip = PORT_CLIP_REGION_X (thePort);
PORT_CLIP_REGION_X (thePort) = RM (NewRgn ());
ClipRect(&r);
LISTBEGIN(list);
/* #define TEMPORARY_HACK_DO_NOT_CHECK_IN */
#if !defined(TEMPORARY_HACK_DO_NOT_CHECK_IN)
LISTCALL(lHiliteMsg, setit, &r, cell, off0, off1 - off0, list);
#endif
LISTEND(list);
DisposeRgn (PORT_CLIP_REGION (thePort));
PORT_CLIP_REGION_X (thePort) = saveclip;
SetPort (saveport);
}
}
}
}
A4(PRIVATE, void, rectvalue, register Rect *, rp, register INTEGER, value,
register ListHandle, list, BOOLEAN, hiliteempty)
{
register INTEGER *ip, *ep;
register INTEGER *sp;
Cell c;
LISTDECL();
LISTBEGIN(list);
for (c.v = CW(rp->top) ; c.v < CW(rp->bottom); c.v++) {
c.h = CW(rp->left);
if ((sp = ip = ROMlib_getoffp(c, list))) {
for (ep = ip + (CW(rp->right) - CW(rp->left)); ip != ep; ip++)
if (!(CW(*ip) & 0x8000) ^ !value) {
c.h = CW(rp->left) + (ip - sp);
setselectnilflag(value, c, list, hiliteempty);
}
}
}
LISTEND(list);
}
A5(PRIVATE, void, rect2value, register Rect *, in, register Rect *, butnotin,
register INTEGER, value, register ListHandle, list,
BOOLEAN, hiliteempty)
{
register INTEGER *ip;
Cell c;
for (c.v = CW(in->top) ; c.v < CW(in->bottom); c.v++)
for (c.h = CW(in->left) ; c.h < CW(in->right); c.h++)
if (!PtInRect(c, butnotin) && (ip = ROMlib_getoffp(c, list)))
if (!(CW(*ip) & 0x8000) ^ !value)
setselectnilflag(value, c, list, hiliteempty);
}
A1(PRIVATE, void, scrollbyvalues, ListHandle, list)
{
INTEGER h, v;
ControlHandle ch;
Point p;
h = (ch = HxP(list, hScroll)) ? GetCtlValue(ch) : Hx(list, visible.left);
v = (ch = HxP(list, vScroll)) ? GetCtlValue(ch) : Hx(list, visible.top);
C_LScroll(h - Hx(list, visible.left), v - Hx(list, visible.top), list);
HxX(list, visible.left) = CW(h);
HxX(list, visible.top) = CW(v);
p.h = Hx(list, cellSize.h);
p.v = Hx(list, cellSize.v);
C_LCellSize(p, list);
}
P2(PUBLIC, pascal void, ROMlib_mytrack, ControlHandle, ch, INTEGER, part)
{
INTEGER quant, page;
ListPtr lp;
lp = (ListPtr) (long) STARH((Handle) (long) MR(HxX(ch, contrlRfCon)));
page = ch == MR(lp->hScroll) ?
CW(lp->visible.right) - CW(lp->visible.left) - 1
:
CW(lp->visible.bottom) - CW(lp->visible.top) - 1;
switch (part) {
case inUpButton:
quant = -1;
break;
case inDownButton:
quant = 1;
break;
case inPageUp:
quant = -page;
break;
case inPageDown:
quant = page;
break;
default:
gui_assert(0);
quant = 0;
break;
}
SetCtlValue(ch, GetCtlValue(ch) + quant);
scrollbyvalues((ListHandle) (long) MR(HxX(ch, contrlRfCon)));
}
#if !defined (BINCOMPAT)
#define CALLCLICK(f) (CallPascalB(f))
#else /* BINCOMPAT */
typedef pascal BOOLEAN (*clickproc)( void );
#define CALLCLICK(f) ROMlib_CALLCLICK((clickproc)(f))
A1(static inline, BOOLEAN, ROMlib_CALLCLICK, clickproc, fp)
{
BOOLEAN retval;
ROMlib_hook(list_clicknumber);
HOOKSAVEREGS();
retval = CToPascalCall(fp, CTOP_Button);
HOOKRESTOREREGS();
return retval;
}
#endif /* BINCOMPAT */
P3(PUBLIC pascal trap, BOOLEAN, LClick, Point, pt, /* IMIV-273 */
INTEGER, mods, ListHandle, list)
{
ControlHandle ch, scrollh, scrollv;
Rect r, rswapped;
BOOLEAN doubleclick, ctlchanged;
BOOLEAN hiliteempty, onlyone, userects, disjoint, extend;
BOOLEAN initial;
enum { Off, On, UseSense } cellvalue; /* order is important here */
Byte flags;
EventRecord evt;
Rect anchor, oldselrect, newselrect, newcellr, pinrect;
Cell oldcell, newcell, c, cswapped, oldcellunswapped, newcellunswapped;
LONGINT l;
INTEGER dh, dv;
Point p;
doubleclick = FALSE;
if (PtInRect(pt, &HxX(list, rView))) {
TRAPBEGIN();
flags = Hx(list, selFlags);
newcell.h = CW(pt.h);
newcell.v = CW(pt.v);
findcell(&newcell, list);
if (newcell.h == HxX(list, lastClick.h) &&
newcell.v == HxX(list, lastClick.v) &&
TickCount() < Hx(list, clikTime) + CL(DoubleTime))
doubleclick = TRUE;
HxX(list, lastClick) = newcell;
hiliteempty = !(flags & lNoNilHilite);
if (((mods & shiftKey) || (flags & lExtendDrag)) &&
!(flags & lOnlyOne)) {
onlyone = FALSE;
disjoint = !(flags & lNoDisjoint);
userects = !(flags & lNoRect);
cellvalue = (flags & lUseSense) ? UseSense : On;
extend = (flags & lUseSense) ? FALSE : !(flags & lNoExtend);
} else if ((mods & cmdKey) && !(flags & lOnlyOne)) {
onlyone = FALSE;
disjoint = !(flags & lNoDisjoint);
userects = FALSE;
cellvalue = UseSense;
extend = FALSE;
} else {
onlyone = TRUE;
disjoint = FALSE;
userects = FALSE;
cellvalue = On;
extend = FALSE;
}
initial = C_LGetSelect(FALSE, &newcell, list);
if (cellvalue == UseSense)
cellvalue = initial ? Off : On;
if (!disjoint && !initial)
rectvalue(&HxX(list, dataBounds), Off, list, hiliteempty);
if (userects) {
anchor.top = anchor.bottom = 0;
if (extend) {
rswapped = HxX(list, dataBounds);
r.top = CW(rswapped.top);
r.left = CW(rswapped.left);
r.bottom = CW(rswapped.bottom);
r.right = CW(rswapped.right);
for (c.h = r.left; c.h < r.right ; c.h++)
for (c.v = r.top; c.v < r.bottom ; c.v++) {
cswapped.h = CW(c.h);
cswapped.v = CW(c.v);
if (C_LGetSelect(FALSE, &cswapped, list))
goto out1;
}
out1:
c.h = CW(cswapped.h);
c.v = CW(cswapped.v);
if (c.h != r.right) {
anchor.left = CW(c.h);
for (c.h = r.right-1; c.h >= r.left ; c.h--)
for (c.v = r.top; c.v < r.bottom ; c.v++) {
cswapped.h = CW(c.h);
cswapped.v = CW(c.v);
if (C_LGetSelect(FALSE, &cswapped, list))
goto out2;
}
out2:
c.h = CW(cswapped.h);
c.v = CW(cswapped.v);
anchor.right = CW(c.h + 1);
cswapped.h = CW(r.left);
cswapped.v = CW(r.top);
C_LGetSelect(TRUE, &cswapped, list);
anchor.top = cswapped.v;
for (c.v = r.bottom - 1; c.v >= r.top ; c.v--)
for (c.h = r.left; c.h < r.right ; c.h++) {
cswapped.h = CW(c.h);
cswapped.v = CW(c.v);
if (C_LGetSelect(FALSE, &cswapped, list))
goto out3;
}
out3:
anchor.bottom = CW(CW(cswapped.v) + 1);
}
}
if (anchor.top == anchor.bottom) {
anchor.top = newcell.v;
anchor.left = newcell.h;
anchor.bottom = CW(CW(anchor.top) + 1);
anchor.right = CW(CW(anchor.left) + 1);
}
c.h = CW(anchor.left);
c.v = CW(anchor.top);
C_LRect(&rswapped, c, list);
if (pt.h < CW(rswapped.right) && pt.v < CW(rswapped.bottom)) {
anchor.top = CW(CW(anchor.bottom) - 1);
anchor.left = CW(CW(anchor.right) - 1);
} else {
anchor.bottom = CW(CW(anchor.top) + 1);
anchor.right = CW(CW(anchor.left) + 1);
}
oldselrect = (flags & lUseSense) ? anchor : HxX(list, dataBounds);
}
HxX(list, clikTime) = CL(TickCount());
HxX(list, clikLoc.h) = CW(pt.h);
HxX(list, clikLoc.v) = CW(pt.v);
oldcell.h = CWC(32767);
evt.where.h = CW(pt.h);
evt.where.v = CW(pt.v);
pinrect = HxX(list, rView);
pinrect.left = CW(CW(pinrect.left) - 1);
pinrect.bottom = CW(CW(pinrect.bottom) - 1);
do {
HxX(list, mouseLoc) = evt.where;
if (HxP(list, lClikLoop))
if (CALLCLICK(HxP(list, lClikLoop)))
/*-->*/ break;
p.h = CW(evt.where.h);
p.v = CW(evt.where.v);
if (!PtInRect(p, &HxX(list, rView))) {
ctlchanged = FALSE;
scrollh = HxP(list, hScroll);
scrollv = HxP(list, vScroll);
dh = 0;
dv = 0;
if (CW(evt.where.h) < Hx(list, rView.left)) {
if (scrollh) {
SetCtlValue(scrollh, GetCtlValue(scrollh)-1);
ctlchanged = TRUE;
} else
dh = -1;
} else if (CW(evt.where.h) > Hx(list, rView.right)) {
if (scrollh) {
SetCtlValue(scrollh, GetCtlValue(scrollh)+1);
ctlchanged = TRUE;
} else
dh = 1;
}
if (CW(evt.where.v) < Hx(list, rView.top)) {
if (scrollv) {
SetCtlValue(scrollv, GetCtlValue(scrollv)-1);
ctlchanged = TRUE;
} else
dv = -1;
} else if (CW(evt.where.v) > Hx(list, rView.bottom)) {
if (scrollv) {
SetCtlValue(scrollv, GetCtlValue(scrollv)+1);
ctlchanged = TRUE;
} else
dv = 1;
}
if (ctlchanged)
scrollbyvalues(list);
else
C_LScroll(dh, dv, list);
}
p.h = CW(evt.where.h);
p.v = CW(evt.where.v);
l = PinRect(&pinrect, p);
newcell.h = CW(LoWord(l));
newcell.v = CW(HiWord(l));
findcell(&newcell, list);
if (userects) {
newcellr.top = newcell.v;
newcellr.left = newcell.h;
newcellr.bottom = CW(CW(newcellr.top) + 1);
newcellr.right = CW(CW(newcellr.left) + 1);
UnionRect(&anchor, &newcellr, &newselrect);
rect2value(&oldselrect, &newselrect, !cellvalue, list,
hiliteempty);
rectvalue(&newselrect, cellvalue, list, hiliteempty);
oldselrect = newselrect;
} else {
if (newcell.h != oldcell.h ||
newcell.v != oldcell.v) {
if (onlyone && oldcell.h != 32767) {
oldcellunswapped.h = CW(oldcell.h);
oldcellunswapped.v = CW(oldcell.v);
setselectnilflag(FALSE, oldcellunswapped, list,
hiliteempty);
}
newcellunswapped.h = CW(newcell.h);
newcellunswapped.v = CW(newcell.v);
setselectnilflag(cellvalue, newcellunswapped, list,
hiliteempty);
oldcell = newcell;
}
}
} while (!OSEventAvail(mUpMask, &evt) &&
(GlobalToLocal(&evt.where), TRUE));
TRAPEND();
} else if (((ch = HxP(list, hScroll)) && PtInRect(pt, &HxX(ch, contrlRect))) ||
((ch = HxP(list, vScroll)) && PtInRect(pt, &HxX(ch, contrlRect)))) {
if (TestControl(ch, pt) == inThumb) {
TrackControl(ch, pt, (ProcPtr) 0);
scrollbyvalues(list);
} else
TrackControl(ch, pt, (ProcPtr) P_ROMlib_mytrack);
}
return doubleclick;
return 0;
}
P1(PUBLIC pascal trap, LONGINT, LLastClick, ListHandle, list) /* IMIV-273 */
{
return ((LONGINT) Hx(list, lastClick.v) << 16) |
(unsigned short) Hx(list, lastClick.h);
}
P3(PUBLIC pascal trap, void, LSetSelect, BOOLEAN, setit, /* IMIV-273 */
Cell, cell, ListHandle, list)
{
setselectnilflag(setit, cell, list, TRUE);
}