home *** CD-ROM | disk | FTP | other *** search
- /*
- 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();
- }
-
-
-