executor/packages/go/mouse.c

425 lines
8.5 KiB
C

#include "go.h"
#include "display.h"
#include "mouse.proto.h"
#include "init.proto.h"
#include "window.proto.h"
#include "launch.proto.h"
#include "inithotband.proto.h"
#include "iconmanip.proto.h"
#include "misc.proto.h"
#include "menu.proto.h"
#include "view.proto.h"
ControlHandle (**g_selection)[];
int is_file (ControlHandle c)
{
enum actions action;
action = (*(item **) (*c)->contrlData)->action;
return action != OPENDIR && action != NOACTION;
}
int
is_on_hot_band (ControlHandle c)
{
return (*c)->contrlOwner == g_hotband;
}
int
is_volume (ControlHandle c)
{
StringPtr sp;
sp = (*c)->contrlTitle;
return sp[sp[0]] == ':';
}
#define NON_EJECTABLE_BIT (1 << 5)
int
is_ejectable (ControlHandle c)
{
HParamBlockRec hpb;
int retval;
OSErr e;
if (is_volume (c))
{
e = get_HParamBlockRec_from_ControlHandle (&hpb, c);
retval = e == noErr && !(hpb.volumeParam.ioVAtrb & NON_EJECTABLE_BIT);
}
else
retval = false;
return retval;
}
void
replaceselected (ControlHandle c)
{
if ((**g_selection)[0] != 0)
{
(*(item **) ((*(**g_selection)[0])->contrlData))->selected = false;
Draw1Control ((**g_selection)[0]);
}
(**g_selection)[0] = c;
if (c != 0)
{
(*(item **) (*c)->contrlData)->selected = true;
Draw1Control (c);
menuchoices (true);
if (!is_file (c))
disable_menu_item (get_info_menuid);
if (is_on_hot_band (c))
disable_menu_item (send_to_hotband_menuid);
if (!is_ejectable (c))
disable_menu_item (eject_menuid);
if (is_volume (c))
disable_menu_item (duplicate_menuid);
}
else
{
menuchoices (false);
}
}
short
dirwindowexists (Rect * r)
{
WindowPeek wp;
#ifdef THINK_C
for (wp = WindowList; wp != 0; wp = wp->nextWindow)
#else
for (wp = LMGetWindowList (); wp != 0; wp = wp->nextWindow)
#endif
if (((wp->port.portBits.rowBytes & 0xC000) == 0xC000) &&
-r->top == (**(*(CGrafPtr) wp).portPixMap).bounds.top &&
-r->left == (**(*(CGrafPtr) wp).portPixMap).bounds.left)
return true;
return false;
}
void
windfromicon (ControlHandle c)
{
CWindowPtr wp;
Handle h;
Rect r;
OSErr e;
CInfoPBRec dir;
/* TODO: move to .h file */
#define DEFAULTWINDOWWIDTH 5
#define DEFAULTWINDOWHEIGHT 4
enum
{
HORIZONTAL_START = 20,
VERTICAL_START = 40,
HORIZONTAL_STAGGER = 15,
VERTICAL_STAGGER = 15
};
wp = (CWindowPtr) (*c)->contrlOwner;
h = (*(item **) (*c)->contrlData)->path;
HandToHand (&h);
if (wp == (CWindowPtr) g_hotband)
{
SetRect (&r, 100, HOTBANDBOTTOM + VERTICAL_START,
100 + DEFAULTWINDOWWIDTH * ICONWIDTHUSED + HORIZONTAL_START,
100 + DEFAULTWINDOWHEIGHT * ICONHEIGHTUSED);
}
else
{
r = (*c)->contrlOwner->portRect;
OffsetRect (&r, -(*wp->portPixMap)->bounds.left,
-(*wp->portPixMap)->bounds.top + VERTICAL_STAGGER);
appenddir (&h, (*c)->contrlTitle);
}
while (dirwindowexists (&r))
{
OffsetRect (&r, 0, VERTICAL_STAGGER);
if (r.top > qd.screenBits.bounds.bottom)
OffsetRect (&r, HORIZONTAL_STAGGER,
HOTBANDBOTTOM - r.top + VERTICAL_START);
}
if (r.left > qd.screenBits.bounds.right)
OffsetRect (&r, -r.left + HORIZONTAL_STAGGER,
HOTBANDBOTTOM - r.top + VERTICAL_START);
dir.hFileInfo.ioVRefNum = (*(item **) (*c)->contrlData)->vrefnum;
dir.hFileInfo.ioDirID = (*(item **) (*c)->contrlData)->ioparid;
dir.hFileInfo.ioFDirIndex = 0;
dir.hFileInfo.ioNamePtr = (*c)->contrlTitle;
e = PBGetCatInfo (&dir, false);
wp = createdirwindow (&dir, &r, h, (*(item **) (*c)->contrlData)->vrefnum);
SelectWindow ((WindowPtr) wp);
showviewmenu (true);
ShowWindow ((WindowPtr) wp);
}
void
activateicon (ControlHandle c)
{
switch ((*(item **) (*c)->contrlData)->action)
{
case LAUNCH:
launchapp (c);
break;
case OPENDIR:
windfromicon (c);
break;
case LAUNCHCREATOR:
launchcreator (c, appOpen);
/* TODO */
break;
case OPENDA:
launchda (c);
break;
case NOACTION:
/* Do nothing */
break;
default:
break;
}
}
pascal void
scrollicons (ControlHandle c, short part)
{
bandinfo *p;
short shown;
p = &bands[g_currentband];
shown = p->bandpos + g_numdispinhotband;
if (part == inDownButton)
{
if (shown < p->numitems)
{
HideControl ((**p->items)[p->bandpos]);
p->bandpos++;
shiftband (p->bandpos, -1);
}
/* shift everything over */
}
else if (part == inUpButton)
{
if (p->bandpos > 0)
{
if (shown <= p->numitems)
HideControl ((**p->items)[shown - 1]);
p->bandpos--;
shiftband (p->bandpos + 1, 1);
}
}
else
/*-->*/ return;
}
void
offsetwindow (ControlHandle c, short offset)
{
short old, new;
RgnHandle rgn;
Rect r;
rgn = NewRgn ();
old = GetCtlValue (c);
SetCtlValue (c, old + offset);
new = GetCtlValue (c);
SetOrigin (0, new);
r = (*c)->contrlOwner->portRect;
r.right -= SCROLLBARWIDTH;
#if 1
++r.right;
#endif
ScrollRect (&r, 0, old - new, rgn);
#if 1
/* TODO: figure out why this isn't a movecontrol */
OffsetRect (&(*c)->contrlRect, 0, new - old);
UpdtControl ((*c)->contrlOwner, rgn);
#else /* 0 */
MoveControl (c, (*c)->contrlRect.left, (*c)->contrlRect.top + new - old);
#endif /* 0 */
DisposeRgn (rgn);
}
pascal void
windowscroller (ControlHandle c, short part)
{
switch (part)
{
case inUpButton:
offsetwindow (c, -SCROLLSPEED);
break;
case inDownButton:
offsetwindow (c, SCROLLSPEED);
break;
case inPageUp:
offsetwindow (c, (*c)->contrlRect.top - (*c)->contrlRect.bottom);
break;
case inPageDown:
offsetwindow (c, (*c)->contrlRect.bottom - (*c)->contrlRect.top);
break;
default:
break;
}
}
void
actoncontrol (ControlHandle c, short part, EventRecord * ev)
{
short before, after;
switch (part)
{
case inButton:
case INSELECTEDICON:
case INTEXT:
part = followcontrol (c, part);
if (part == inButton || part == INTEXT)
{
replaceselected (c);
}
else if (part == INSELECTEDICON)
{
if (ev->when - g_lastclick < GetDblTime ())
activateicon (c);
} /* else if (part == INTEXT) {
} */
break;
case inThumb:
before = GetCtlValue (c);
if (TrackControl (c, ev->where, 0))
{
after = GetCtlValue (c);
/* I don't like this, but it's the best way I could think of to avoid writing a
* duplicate function
*/
SetCtlValue (c, before);
offsetwindow (c, after - before);
}
break;
case inUpButton:
case inDownButton:
case inPageUp:
case inPageDown:
TrackControl (c, ev->where, windowscroller);
break;
default:
break;
}
}
void
checkcontrol (EventRecord * ev, WindowPtr wp)
{
short part;
ControlHandle c;
GrafPtr saveport;
GetPort (&saveport);
SetPort (wp);
GlobalToLocal (&ev->where);
part = FindControl (ev->where, wp, &c);
if (c != (ControlHandle) 0)
{
actoncontrol (c, part, ev);
}
else if ((**g_selection)[0] != (ControlHandle) 0)
{
replaceselected (c);
}
SetPort (saveport);
}
void
mouseinhotband (EventRecord * ev)
{
DialogPtr dp;
short item, part;
ControlHandle c;
Point p;
GrafPtr saveport;
GetPort (&saveport);
SetPort (g_hotband);
p = ev->where;
GlobalToLocal (&p);
if ((part = FindControl (p, g_hotband, &c)) != 0)
{
if ((*c)->contrlDefProc != g_iconcdefproc)
{ /* see if it's an icon control */
if (DialogSelect (ev, &dp, &item) && (item <= NUMBANDS))
{
setband (item - 1);
((WindowPeek) g_hotband)->refCon |= WIPEBIT;
InvalRect (&g_hotband->portRect);
}
else if (item == SORTBUTTON)
{
defaultsort ();
}
else if (item == HELPBUTTON)
{
help ();
}
}
else
actoncontrol (c, part, ev);
}
SetPort (saveport);
}
void
domousedown (EventRecord * ev)
{
WindowPtr wp;
short where;
where = FindWindow (ev->where, &wp);
if (wp && ((WindowPeek) wp)->windowKind == userKind)
{
SelectWindow (wp);
replaceselected ((ControlHandle) 0);
showviewmenu (wp != g_hotband);
}
if (wp == g_hotband)
{
mouseinhotband (ev);
}
else
{
switch (where)
{
case inDesk:
/* DO NOTHING */
break;
case inMenuBar:
domenu (MenuSelect (ev->where));
break;
case inSysWindow:
SystemClick (ev, wp);
break;
case inContent:
checkcontrol (ev, wp);
break;
case inDrag:
dodragwin (ev->where, wp);
break;
case inGrow:
dogrowwin (ev->where, wp);
break;
case inGoAway:
dogoaway (ev->where, wp);
break;
default:
break;
}
}
g_lastclick = ev->when;
}