home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / mac / source / cshowint.sit / IconWrap.c < prev    next >
C/C++ Source or Header  |  1989-10-13  |  8KB  |  224 lines

  1. /*
  2.     FILENAME:    IconWrap.c (for LightspeedC 3.02)
  3.     
  4.     This file is copyright ⌐1989 by Ken McLeod.
  5.     Permission is granted to use and distribute this code freely.
  6.     
  7.     DESCRIPTION:
  8.         This INIT patches _CopyBits (and _PlotCIcon, if present) to
  9.         intercept and change the destRect parameter, based on the current
  10.         ShowINIT checksum, before calling the "real" CopyBits. The purpose
  11.         of this is to wrap ShowINIT icons around to create a new row
  12.         above the current one when the edge of the screen has been reached.
  13.         
  14.         Currently, we assume that if CopyBits is called with a 32x32
  15.         rect AND the undocumented global WWExist (at 0x8F2) has a non-zero
  16.         value, we are being called from ShowINIT, so we modify the rect.
  17.         Be aware that this code will 'break' if a future version of the
  18.         System decides to use 0x8F2 before INIT time. (Hopefully, a future
  19.         version of the System will obviate the need for IconWrap anyway!)
  20.     
  21.     CREDITS:
  22.       written by Ken McLeod:
  23.       UUCP:    {zardoz, felix}!dhw68k!thecloud
  24.       INTERNET:    thecloud@dhw68k.cts.com
  25.     
  26.     HISTORY:
  27.       started 11/21/88; based on an idea by David Phillip Oster
  28.       1.0     11/24/88: got it working, but Moire and Backdrop crash.
  29.       1.01    11/27/88: fixed the problem by saving and restoring A5
  30.                         in main(); InitGraf() was trashing the real QD
  31.                         globals. (reported by John Lim)
  32.       1.1            3/3/89:        fixed bizarre problem with HyperCard fields on
  33.                                           II-series machines; changed jsr's to jmp's
  34.       1.2            4/4/89:        now patching both _PlotCIcon and _CopyBits on
  35.                                           CQD machines to handle 'cicn's
  36. */
  37.  
  38. /* #include <MacHeaders> */
  39. /* inline A4-relative storage for our globals... */
  40. #include <SetUpA4.h>
  41.  
  42. typedef struct QuickDraw {        /* QuickDraw globals */
  43.         char private[76];
  44.         long randSeed;
  45.         BitMap screenBits;
  46.         Cursor arrow;
  47.         Pattern dkGray;
  48.         Pattern ltGray;
  49.         Pattern gray;
  50.         Pattern black;
  51.         Pattern white;
  52.         GrafPtr thePort;
  53. } QuickDraw;
  54.  
  55. typedef    struct    ShowParams    {        /* ShowInit data structure */
  56.         short h;
  57.         short check;
  58. }    ShowParams;
  59.  
  60. extern    ShowParams showData : 0x92C;
  61. extern    Boolean    WMgrInited    : 0x8F2;
  62.  
  63. long    OldCopyBits;                /* pointer to "real" CopyBits */
  64. long    OldPlotCicn;                /* pointer to "real" PlotCIcon */
  65. short    currRowBase;                /* current vertical row offset */
  66. short    maxEdge;                        /* for checking if rect is off edge of screen */
  67. Rect    *dstRect;                        /* pointer to rect argument */
  68.  
  69. #define    COPYBITSNUM    0xA8EC
  70. #define    PLOTCICNNUM    0xAA1F
  71. #define CHECSUMMASK    0x1021
  72. #define    CBRECTOFF        14            /* offset from stack ptr to dstRect */
  73. #define    PCRECTOFF        12            /* same as above, but for PlotCIcon */
  74. #define LEFTMARGIN    8                /* distance from left edge of screen */
  75. #define    ICONWIDTH        32            /* icons are 32x32 pixels */
  76. #define ICONSPACE        40            /* 32 + 8 pixel margin */
  77. #define    hasCQDBit        6                /* bit in ROM85 cleared if CQD available */
  78.  
  79. /*===================================================================
  80.   this is our "wrapping" function. It checks to see if the current
  81.     icon position will be off the screen, and if so, updates the
  82.     h & v offsets, recalculates the checksum, and alters "dstRect".
  83.  ====================================================================*/
  84. void    icon_wrap()
  85. {
  86.     if (((dstRect->right - dstRect->left) == ICONWIDTH) && (WMgrInited))    {
  87.         /*    only mess with it if it's potentially an icon, and    */
  88.         /*    then only if the Window Manager is uninitialized        */
  89.         if (showData.h > maxEdge)    {
  90.             /* we're going to be off the edge; time to add a new row */
  91.             showData.h = LEFTMARGIN;    /* reset horizontal counter */
  92.             showData.check  =  (LEFTMARGIN << 1) ^ CHECSUMMASK;
  93.             currRowBase -= ICONSPACE;        /* offset to next row */
  94.             dstRect->left = LEFTMARGIN;
  95.             dstRect->right = LEFTMARGIN + ICONWIDTH;
  96.         }
  97.         dstRect->bottom = currRowBase;
  98.         dstRect->top = dstRect->bottom - ICONWIDTH;
  99.     }
  100. }
  101.  
  102. /*===================================================================
  103.   this is our replacement for PlotCIcon.
  104.   It calls icon_wrap() and then jumps to the "real" PlotCIcon.
  105.  ====================================================================*/
  106. /* pascal void NuPlotCIcon(theRect, theIcon)
  107. Rect *theRect;
  108. CIconHandle theIcon;    */
  109.  
  110. pascal    void    NuPlotCIcon()
  111. {
  112.     SetUpA4();    /*    save A4 on stack, and put our globals ptr in A4    */
  113.     asm    {
  114.     move.l    PCRECTOFF(sp),dstRect    ; get a copy of the rect ptr
  115.         movem.l    D3-D7/A2-A6,-(sp)            ; save non-trashable registers
  116.     }
  117.     icon_wrap();        /* check dstRect and alter if necessary */
  118.  
  119.     asm    {
  120.         movem.l    (sp)+,D3-D7/A2-A6            ; restore saved registers
  121.         move.l    dstRect,PCRECTOFF(sp)    ; replace dstRect parameter
  122.         move.l    OldPlotCicn,A0                ;    prepare to jmp
  123.         move.l    (sp)+,A4                            ;    restore A4 (undoes SetUpA4)
  124.         jmp            (A0)                                    ;    jump to the "real" PlotCIcon
  125.     }
  126. }
  127.  
  128. /*===================================================================
  129.   this is our replacement for CopyBits.
  130.   It calls icon_wrap() and then jumps to the "real" CopyBits.
  131.  ====================================================================*/
  132. /* pascal void NewCopyBits(srcBits,dstBits,srcRect,dstRect,mode,maskRgn)
  133. BitMap *srcBits,*dstBits;
  134. Rect *srcRect,*dstRect;
  135. short mode;
  136. RgnHandle maskRgn; */
  137.  
  138. pascal    void    NewCopyBits()
  139. {
  140.     SetUpA4();    /*    save A4 on stack, and put our globals ptr in A4    */
  141.     asm    {
  142.     move.l    CBRECTOFF(sp),dstRect    ; get a copy of the rect ptr
  143.         movem.l    D3-D7/A2-A6,-(sp)            ; save non-trashable registers
  144.     }
  145.     icon_wrap();        /* check dstRect and alter if necessary */
  146.  
  147.     asm    {
  148.         movem.l    (sp)+,D3-D7/A2-A6            ; restore saved registers
  149.         move.l    dstRect,CBRECTOFF(sp)    ; replace dstRect parameter
  150.         move.l    OldCopyBits,A0                ;    prepare to jmp
  151.         move.l    (sp)+,A4                            ;    restore A4 (undoes SetUpA4)
  152.         jmp            (A0)                                    ;    jump to the "real" CopyBits
  153.     }
  154. }
  155.  
  156. /*===================================================================
  157.         our main function -- only gets called once.  What this function
  158.         *should* do is copy the previous three functions (and inline
  159.         storage) into the System heap, to use only as much memory as
  160.         necessary.  However, since the following code is fairly small,
  161.         we use the lazy method:  our 'System Heap' and 'Locked' bits are
  162.         set, so when our INIT resource gets loaded, we just call
  163.         DetachResource on it, and it stays locked in the heap.
  164.  ====================================================================*/
  165. void    main()
  166. {
  167.     Handle    ourH;                /* handle to our code resource */
  168.     Handle  procH;            /* handle to external PROC resource */
  169.     QuickDraw    qdGlobs;    /* our own copy of the qd globals */
  170.   Ptr localA5;        /* pointer to qdGlobs.thePort */
  171.   Ptr    savedA5;                /* storage for saved contents of A5 */
  172.  
  173. #define    PROC_ID    128
  174. #define    ICON_ID    128
  175.  
  176.     RememberA0();
  177.     SetUpA4();
  178.     asm    {
  179.         _RecoverHandle                ; A0 points to our code
  180.         move.l        A0,ourH            ; get handle to us
  181.     }
  182.     if(Button())
  183.         SysBeep(10);    /* cancel install if mouse button down */
  184.     else {
  185.         DetachResource(ourH);
  186.         HLock(ourH);
  187.  
  188.         /* initialize our globals */
  189.         /* need to call InitGraf() so we can get screenBits.bounds */
  190.         asm {
  191.             move.l    A5,savedA5        ;save "real" QD globals ptr
  192.             lea            localA5,A5        ;set up A5 to point to our globals
  193.             move.l    A5,CurrentA5
  194.         }
  195.         InitGraf(&qdGlobs.thePort);
  196.         asm {
  197.             move.l    savedA5,A5
  198.             move.l    A5,CurrentA5
  199.         }
  200.         currRowBase = qdGlobs.screenBits.bounds.bottom - 8;
  201.         maxEdge = qdGlobs.screenBits.bounds.right - ICONSPACE;
  202.  
  203.         /* install the patches */
  204.         OldCopyBits = NGetTrapAddress(COPYBITSNUM, ToolTrap);
  205.         NSetTrapAddress(NewCopyBits, COPYBITSNUM, ToolTrap);
  206.         
  207.       if (!(BitTst(&ROM85, 7-hasCQDBit))) {
  208.           /* CQD exists, so patch PlotCIcon as well */
  209.             OldPlotCicn = NGetTrapAddress(PLOTCICNNUM, ToolTrap);
  210.             NSetTrapAddress(NuPlotCIcon, PLOTCICNNUM, ToolTrap);
  211.         }
  212.         /* load the CShowINIT 'PROC' and call it */
  213.         if ((procH = GetResource('PROC', PROC_ID)) != 0L)    {
  214.             HLock(procH);
  215.             CallPascal(ICON_ID, -1, *procH);
  216.             HUnlock(procH);
  217.         }
  218.     }
  219.     /* no need to unlock handle; we'll be around for a while */
  220.     RestoreA4();
  221. }
  222.  
  223.  
  224.