thecloud@dhw68k.cts.com (Ken McLeod) (05/26/89)
In article <KSITZE.89May24132947@picuris.nmsu.edu> ksitze@nmsu.edu (Kevin Sitze) writes: [an INIT installer & icon drawing routine in C...] Some of the ShowINIT translations I've seen have subtle differences from Paul Mercer's original assembly version, and the icons aren't drawn correctly if IconWrap is installed. Others try to add functionality for their own icon that creates problems for subsequent INITs' icons. Consider what happens when the following block is executed: > if (icnHorz > myPort->portBits.bounds.right - 32) { > icnHChk = Chk(icnHorz = 8); > icnVChk = Chk(icnVert -= 40); > } This code resets the horizontal drawing position (in low-memory) to 8, and bumps the icon up a row. Unfortunately, this INIT is the only one that knows about "icnVert". The next INIT comes along, sees that the horizontal drawing position is now (8 + 40), and promptly clobbers the the second icon on the bottom row. The next INIT draws over the third icon, and so on. The problem is not in Kevin's code; rather, the problem is that other INITs don't use his scheme. Paul Mercer's version is the defacto standard, and any enhancement to it has to think carefully about its effect on "H-Only Aware" INITs (i.e. the vast majority!) which run subsequently. The following code is a literal translation of ShowINIT (and supports color icons). It's implemented as a separate 'PROC' resource, although it could be included within your own code easily. /*------------------------------------------------------------------------- Filename: CShowINIT.c Color ShowINIT, for use with LightspeedC This translation by Ken McLeod (thecloud@dhw68k.cts.com) Version of: Thursday, April 6, 1989 3:30:00 PM INIT notification routine by Paul Mercer, Darin Adler, and Paul Snively from an idea by Steve Capps Version of: Friday, July 15, 1988 12:08:09 AM (1.1B1) -revved back to previous calling interface. -you only need to call ShowINIT now and due to popular demand, deltaX is back! -also due to popular demand, color icons are now done automatically. -note that the color icon is only used if 4 bits or more is available on the main graphics device; the normal #ICN is used for all other cases. Build & save this file as a 'PROC' resource, and include it in your INIT's resource file. Use the following code within your INIT to load the 'PROC' and call CShowINIT: Handle procH; if ((procH = GetResource('PROC', PROC_ID)) != 0L) { HLock(procH); CallPascal(ICON_ID, -1, *procH); HUnlock(procH); } -------------------------------------------------------------------------*/ /* #include <MacHeaders> */ #include <Color.h> typedef struct QuickDraw { /* struct to hold QuickDraw globals */ char private[76]; long randSeed; BitMap screenBits; Cursor arrow; Pattern dkGray; Pattern ltGray; Pattern gray; Pattern black; Pattern white; GrafPtr thePort; } QuickDraw; /*extern short ROM85 : 0x28E;*/ /*extern GDHandle MainDevice : 0x8A4;*/ extern short myH : 0x92C; /* CurApName+28 */ extern short myCheck: 0x92E; /* CurApName+30 */ #define firstX 8 /* left margin - offset to first icon */ #define bottomEdge 8 /* this far from bottom of screen */ #define iconWidth 32 /* size of icon (square normally) */ #define defaultMoveX 40 /* default amount to move icons */ #define checksumConst 0x1021 /* constant used for computing checksum */ #define minColorDepth 4 /* min. bits/pixel for drawing color icons */ #define maskOffset 128 /* offset to mask in ICN# resource */ #define iconRowBytes 32/8 /* 32/8 bits */ #define hasCQDBit 6 /* bit in ROM85 cleared if CQD available */ /*------------------------------------------------------------------------- Display the ICN# (cicn when in 4 bit mode or higher) specified by iconID and move the pen horizontally by moveX. Pass a -1 in moveX to move the standard amount (40 pixels). pascal void ShowINIT(iconID, moveX) short iconID, moveX; extern; -------------------------------------------------------------------------*/ pascal void main(iconID, moveX) short iconID, moveX; { Handle theIconHdl; /* handle to the icon (or cicn) */ short i; /* for calculating X offset */ short colorFlag; /* set if drawing a color icon */ short theDepth; /* depth of main screen; used for CQD only */ GDHandle theMainDevice; /* handle to main screen device; CQD only */ Rect srcRect, destRect; /* source & destination rectangles */ BitMap myBitMap; /* icon bitmap; used for b/w icon only */ GrafPort myPort; /* port we draw into */ QuickDraw qdGlobals; /* our own personal QD globals... */ Ptr localA5; /* pointer to qdGlobals.thePort */ Ptr savedA5; /* storage for saved contents of A5 */ asm { move.l A5,savedA5 /* save "real" QD globals ptr, NOT on stack */ lea localA5,A5 /* set up A5 to point to our globals */ move.l A5,CurrentA5 } InitGraf(&qdGlobals.thePort); OpenPort(&myPort); colorFlag = 0; /* default: no color */ if (!(BitTst(&ROM85, 7-hasCQDBit))) { /* does CQD exist? */ theMainDevice = MainDevice; /* yes; get handle to main device */ theDepth = (*(*theMainDevice)->gdPMap)->pixelSize; if (theDepth >= minColorDepth) { /* deep enough to draw in color? */ if ((theIconHdl = (Handle)GetCIcon(iconID)) != 0L) colorFlag = 1; /* found a color icon; set flag */ } } if (!(colorFlag)) { /* no CQD, insufficient depth, or lack of 'cicn' */ if (!(theIconHdl = GetResource('ICN#',iconID))) { SysBeep(3); /* can't get b/w icon; signal error and bail out */ goto out; } } i = (myH << 1) ^ checksumConst; /* checksum to find X */ myH = ((i == myCheck) ? (myH):(firstX)); /* reset if necessary */ destRect.bottom = myPort.portRect.bottom - bottomEdge; destRect.left = myPort.portRect.left + myH; destRect.top = destRect.bottom - iconWidth; destRect.right = destRect.left + iconWidth; if (colorFlag) { /* draw color icon */ PlotCIcon(&destRect,(CIconHandle)theIconHdl); DisposCIcon((CIconHandle)theIconHdl); } else { /* draw b/w icon */ HLock(theIconHdl); srcRect.top = srcRect.left = 0; srcRect.bottom = srcRect.right = iconWidth; myBitMap.rowBytes = iconRowBytes; myBitMap.bounds = srcRect; myBitMap.baseAddr = *theIconHdl + maskOffset; /* punch hole with mask */ CopyBits(&myBitMap, &myPort.portBits, &srcRect, &destRect, srcBic, 0L); myBitMap.baseAddr = *theIconHdl; /* now draw the icon */ CopyBits(&myBitMap, &myPort.portBits, &srcRect, &destRect, srcOr, 0L); HUnlock(theIconHdl); ReleaseResource(theIconHdl); } myH += ((moveX == -1) ? (defaultMoveX):(moveX)); /* advance for next time */ myCheck = (myH << 1) ^ checksumConst; /* calc new checksum */ out: ClosePort(&myPort); asm { move.l savedA5,A5 move.l A5,CurrentA5 } } /*-------------------------------------------------------------------------*/ -- ========== ....... ============================================= Ken McLeod :. .: UUCP: ...{spsd,zardoz,felix}!dhw68k!thecloud ========== :::.. ..::: INTERNET: thecloud@dhw68k.cts.com //// =============================================