home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Garbo
/
Garbo.cdr
/
mac
/
source
/
cshowint.sit
/
IconWrap.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-10-13
|
8KB
|
224 lines
/*
FILENAME: IconWrap.c (for LightspeedC 3.02)
This file is copyright ⌐1989 by Ken McLeod.
Permission is granted to use and distribute this code freely.
DESCRIPTION:
This INIT patches _CopyBits (and _PlotCIcon, if present) to
intercept and change the destRect parameter, based on the current
ShowINIT checksum, before calling the "real" CopyBits. The purpose
of this is to wrap ShowINIT icons around to create a new row
above the current one when the edge of the screen has been reached.
Currently, we assume that if CopyBits is called with a 32x32
rect AND the undocumented global WWExist (at 0x8F2) has a non-zero
value, we are being called from ShowINIT, so we modify the rect.
Be aware that this code will 'break' if a future version of the
System decides to use 0x8F2 before INIT time. (Hopefully, a future
version of the System will obviate the need for IconWrap anyway!)
CREDITS:
written by Ken McLeod:
UUCP: {zardoz, felix}!dhw68k!thecloud
INTERNET: thecloud@dhw68k.cts.com
HISTORY:
started 11/21/88; based on an idea by David Phillip Oster
1.0 11/24/88: got it working, but Moire and Backdrop crash.
1.01 11/27/88: fixed the problem by saving and restoring A5
in main(); InitGraf() was trashing the real QD
globals. (reported by John Lim)
1.1 3/3/89: fixed bizarre problem with HyperCard fields on
II-series machines; changed jsr's to jmp's
1.2 4/4/89: now patching both _PlotCIcon and _CopyBits on
CQD machines to handle 'cicn's
*/
/* #include <MacHeaders> */
/* inline A4-relative storage for our globals... */
#include <SetUpA4.h>
typedef struct QuickDraw { /* QuickDraw globals */
char private[76];
long randSeed;
BitMap screenBits;
Cursor arrow;
Pattern dkGray;
Pattern ltGray;
Pattern gray;
Pattern black;
Pattern white;
GrafPtr thePort;
} QuickDraw;
typedef struct ShowParams { /* ShowInit data structure */
short h;
short check;
} ShowParams;
extern ShowParams showData : 0x92C;
extern Boolean WMgrInited : 0x8F2;
long OldCopyBits; /* pointer to "real" CopyBits */
long OldPlotCicn; /* pointer to "real" PlotCIcon */
short currRowBase; /* current vertical row offset */
short maxEdge; /* for checking if rect is off edge of screen */
Rect *dstRect; /* pointer to rect argument */
#define COPYBITSNUM 0xA8EC
#define PLOTCICNNUM 0xAA1F
#define CHECSUMMASK 0x1021
#define CBRECTOFF 14 /* offset from stack ptr to dstRect */
#define PCRECTOFF 12 /* same as above, but for PlotCIcon */
#define LEFTMARGIN 8 /* distance from left edge of screen */
#define ICONWIDTH 32 /* icons are 32x32 pixels */
#define ICONSPACE 40 /* 32 + 8 pixel margin */
#define hasCQDBit 6 /* bit in ROM85 cleared if CQD available */
/*===================================================================
this is our "wrapping" function. It checks to see if the current
icon position will be off the screen, and if so, updates the
h & v offsets, recalculates the checksum, and alters "dstRect".
====================================================================*/
void icon_wrap()
{
if (((dstRect->right - dstRect->left) == ICONWIDTH) && (WMgrInited)) {
/* only mess with it if it's potentially an icon, and */
/* then only if the Window Manager is uninitialized */
if (showData.h > maxEdge) {
/* we're going to be off the edge; time to add a new row */
showData.h = LEFTMARGIN; /* reset horizontal counter */
showData.check = (LEFTMARGIN << 1) ^ CHECSUMMASK;
currRowBase -= ICONSPACE; /* offset to next row */
dstRect->left = LEFTMARGIN;
dstRect->right = LEFTMARGIN + ICONWIDTH;
}
dstRect->bottom = currRowBase;
dstRect->top = dstRect->bottom - ICONWIDTH;
}
}
/*===================================================================
this is our replacement for PlotCIcon.
It calls icon_wrap() and then jumps to the "real" PlotCIcon.
====================================================================*/
/* pascal void NuPlotCIcon(theRect, theIcon)
Rect *theRect;
CIconHandle theIcon; */
pascal void NuPlotCIcon()
{
SetUpA4(); /* save A4 on stack, and put our globals ptr in A4 */
asm {
move.l PCRECTOFF(sp),dstRect ; get a copy of the rect ptr
movem.l D3-D7/A2-A6,-(sp) ; save non-trashable registers
}
icon_wrap(); /* check dstRect and alter if necessary */
asm {
movem.l (sp)+,D3-D7/A2-A6 ; restore saved registers
move.l dstRect,PCRECTOFF(sp) ; replace dstRect parameter
move.l OldPlotCicn,A0 ; prepare to jmp
move.l (sp)+,A4 ; restore A4 (undoes SetUpA4)
jmp (A0) ; jump to the "real" PlotCIcon
}
}
/*===================================================================
this is our replacement for CopyBits.
It calls icon_wrap() and then jumps to the "real" CopyBits.
====================================================================*/
/* pascal void NewCopyBits(srcBits,dstBits,srcRect,dstRect,mode,maskRgn)
BitMap *srcBits,*dstBits;
Rect *srcRect,*dstRect;
short mode;
RgnHandle maskRgn; */
pascal void NewCopyBits()
{
SetUpA4(); /* save A4 on stack, and put our globals ptr in A4 */
asm {
move.l CBRECTOFF(sp),dstRect ; get a copy of the rect ptr
movem.l D3-D7/A2-A6,-(sp) ; save non-trashable registers
}
icon_wrap(); /* check dstRect and alter if necessary */
asm {
movem.l (sp)+,D3-D7/A2-A6 ; restore saved registers
move.l dstRect,CBRECTOFF(sp) ; replace dstRect parameter
move.l OldCopyBits,A0 ; prepare to jmp
move.l (sp)+,A4 ; restore A4 (undoes SetUpA4)
jmp (A0) ; jump to the "real" CopyBits
}
}
/*===================================================================
our main function -- only gets called once. What this function
*should* do is copy the previous three functions (and inline
storage) into the System heap, to use only as much memory as
necessary. However, since the following code is fairly small,
we use the lazy method: our 'System Heap' and 'Locked' bits are
set, so when our INIT resource gets loaded, we just call
DetachResource on it, and it stays locked in the heap.
====================================================================*/
void main()
{
Handle ourH; /* handle to our code resource */
Handle procH; /* handle to external PROC resource */
QuickDraw qdGlobs; /* our own copy of the qd globals */
Ptr localA5; /* pointer to qdGlobs.thePort */
Ptr savedA5; /* storage for saved contents of A5 */
#define PROC_ID 128
#define ICON_ID 128
RememberA0();
SetUpA4();
asm {
_RecoverHandle ; A0 points to our code
move.l A0,ourH ; get handle to us
}
if(Button())
SysBeep(10); /* cancel install if mouse button down */
else {
DetachResource(ourH);
HLock(ourH);
/* initialize our globals */
/* need to call InitGraf() so we can get screenBits.bounds */
asm {
move.l A5,savedA5 ;save "real" QD globals ptr
lea localA5,A5 ;set up A5 to point to our globals
move.l A5,CurrentA5
}
InitGraf(&qdGlobs.thePort);
asm {
move.l savedA5,A5
move.l A5,CurrentA5
}
currRowBase = qdGlobs.screenBits.bounds.bottom - 8;
maxEdge = qdGlobs.screenBits.bounds.right - ICONSPACE;
/* install the patches */
OldCopyBits = NGetTrapAddress(COPYBITSNUM, ToolTrap);
NSetTrapAddress(NewCopyBits, COPYBITSNUM, ToolTrap);
if (!(BitTst(&ROM85, 7-hasCQDBit))) {
/* CQD exists, so patch PlotCIcon as well */
OldPlotCicn = NGetTrapAddress(PLOTCICNNUM, ToolTrap);
NSetTrapAddress(NuPlotCIcon, PLOTCICNNUM, ToolTrap);
}
/* load the CShowINIT 'PROC' and call it */
if ((procH = GetResource('PROC', PROC_ID)) != 0L) {
HLock(procH);
CallPascal(ICON_ID, -1, *procH);
HUnlock(procH);
}
}
/* no need to unlock handle; we'll be around for a while */
RestoreA4();
}