Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
ShowIcon7.c
#include <Icons.h> |
#include <OSUtils.h> |
#include <Resources.h> |
#include <Memory.h> |
/* |
ShowIcon7.c |
ShowINIT compatible routine that shows 'ICN#' and 'iclx' flavor icons. |
For use by all INITs in System 7 and beyond. |
This code is based on Patrick C. Beard's ShowIconFamily |
by Patrick C. Beard, which in turn was derived from the |
original ShowInit by Paul Mercer, Darin Adler, |
Paul Snively, and Steve Capps. |
Modified by James W. Walker for compatibility with IconWrap 1.2, |
for use as a separate code resource, and to use the new System 7 |
icon-drawing routines. This code is in the public domain. |
Addresses for James W. Walker: 76367,2271@compuserve.com or |
walkerj@math.scarolina.edu |
Instructions for use: |
¥ Create a family of icons with ResEdit 2.1 or later. This will |
include 'ICN#', 'icl4', & 'icl8' icons, all with the |
same resource ID. |
To use within a larger INIT project: |
¥ #define SEPARATE_CODE 0 below. |
¥ Call ShowIcon7( id, adv ) with the resource id of |
the family that you used. The Boolean parameter adv |
indicates whether you want the next use of ShowIcon7 |
to advance to a new position. Normally you pass TRUE, |
but you can get an animated-icon effect by passing FALSE |
all except the last time you call ShowIcon7. |
To use as a separate code resource: |
¥ #define SEPARATE_CODE 1 below. |
¥ Set the project type to code resource, set the code type |
and resource ID (I use type 'Code', ID -4048 for cdevs), |
compile and merge into your INIT or cdev file. |
Set the resource type to Locked, so you won't have |
to call HLock when you use it. |
¥ In your main INIT code, call ShowIcon7 like so: |
pascal void (*ShowIcon7)( short resid, Boolean adv ); |
Handle show_init; |
show_init = GetResource( 'Code', -4048 ); |
ShowIcon7 = (pascal void (*)(short, Boolean)) |
StripAddress( *show_init ); |
ShowIcon7( iconID, advance ); |
*/ |
#define SEPARATE_CODE 0 |
#if SEPARATE_CODE |
#define ShowIcon7 main /* JWW */ |
#endif |
#ifndef nil |
#define nil ((void*)0L) |
#endif |
#ifndef topLeft |
#define topLeft(r) ((Point*)&r)[0]) |
#endif |
#ifndef botRight |
#define botRight(r) ((Point*)&r)[1]) |
#endif |
typedef struct myQDGlobals { |
char privates[76]; |
long randSeed; |
BitMap screenBits; |
Cursor arrow; |
Pattern dkGray; |
Pattern ltGray; |
Pattern gray; |
Pattern black; |
Pattern white; |
GrafPtr thePort; |
long end; |
} myQDGlobals; |
/* prototypes */ |
pascal void ShowIcon7(short iconId, Boolean advance); |
static void DrawBWIcon( short iconId, Rect *icon_rect, Boolean visible ); |
static void Next_position( void ); |
static void GetIconRect( register Rect* iconRect, Rect *screen_rect ); |
/* this is where it all happens. */ |
pascal void ShowIcon7( short iconId, Boolean advance ) |
{ |
long oldA5; |
myQDGlobals qd; /* our QD globals. */ |
SysEnvRec environment; /* machine configuration. */ |
CGrafPort gp; /* our grafport. */ |
Rect icon_rect; |
OSErr err; |
/* get a value for A5, a structure that mirrors qd globals. */ |
oldA5 = SetA5((long)&qd.end); |
InitGraf(&qd.thePort); |
/* find out what kind of machine this is. */ |
SysEnvirons(curSysEnvVers, &environment); |
GetIconRect( &icon_rect, &qd.screenBits.bounds ); |
/* |
The old IconWrap INIT patches CopyBits but does not know about |
CopyMask or IconDispatch. So in the color case, we draw the |
black and white icon with an empty mask region. |
*/ |
if ( (environment.systemVersion >= 0x0700) && environment.hasColorQD ) |
{ |
OpenCPort(&gp); |
DrawBWIcon( iconId, &icon_rect, false ); |
err = PlotIconID( &icon_rect, atNone, ttNone, iconId ); |
CloseCPort(&gp); |
} |
else |
{ |
OpenPort((GrafPtr)&gp); |
DrawBWIcon( iconId, &icon_rect, true ); |
ClosePort((GrafPtr)&gp); |
} |
if (advance) |
Next_position(); /* JWW */ |
SetA5(oldA5); |
} |
/* |
ShowInit's information is nestled at the tail end of CurApName. |
It consists of a short which encodes the next horizontal offset, |
and another short which is that value checksummed with the function below. |
*/ |
#define CurApName_LM 0x910 |
#define ShowINITTable ((unsigned short*)(CurApName_LM + 32 - 4)) |
#define CheckSumConst 0x1021 /* magic value to check-sum with. */ |
#define InitialXPosition 8 /* initial horizontal offset. */ |
#define YOffset 40 /* constant from bottom to place the icon. */ |
#define XOffset 40 /* amount to change it by. */ |
#define ICON_WIDTH 32 |
#define kDefaultRes 0x00480000 /* Default resolution is 72 DPI; Fixed type */ |
/* CheckSum() computes the magic value to determine if ShowInit's have run already. */ |
static short CheckSum(register unsigned short x) |
{ |
// asm { |
// rol.w #1, x |
// } |
if (x & 0x8000) /* high bit set */ |
return((x << 1) ^ CheckSumConst ^ 0x01); |
else |
return ((x << 1) ^ CheckSumConst); |
} |
/* |
GetIconRect() generates an appropriate rectangle to display the |
next INIT's icon in. |
It is also responsible for updating the horizontal |
position in low memory. This is a departure from |
the original ShowInit code, which updates low |
memory AFTER displaying the icon. -- changed by JWW |
This code won't generate an icon position until it is certain that the icon can be loaded, so the |
same behaviour occurs. |
This routine also generates a rectangle which is guaranteed to be onscreen. It |
does this by taking the horizontal offset modulo the screen width to generate |
the horizontal position of the icon, and the offset divided by the screen |
width to generate the proper row. |
*/ |
static void GetIconRect(register Rect* iconRect, Rect *screen_rect ) |
{ |
register short screenWidth; |
screenWidth = screen_rect->right - screen_rect->left; |
screenWidth -= screenWidth % XOffset; |
/* if we are the first INIT to run we need to initialize the horizontal value. */ |
if (CheckSum(ShowINITTable[0]) != ShowINITTable[1]) |
ShowINITTable[0] = InitialXPosition; |
/* compute top left of icon's rect. */ |
iconRect->left = (ShowINITTable[0] % screenWidth); |
iconRect->top = screen_rect->bottom - |
YOffset * (1 + (ShowINITTable[0] / screenWidth)); |
iconRect->right = iconRect->left + 32; |
iconRect->bottom = iconRect->top + 32; |
} |
/* |
JWW: In Beard's original version, this was done at the end of |
GetIconRect. That caused incorrect behavior when IconWrap 1.2 was |
used to wrap icons. Namely, if an INIT using that version of |
ShowIconFamily was the first in a row, then the second icon in that |
row would land on top of it. |
*/ |
static void Next_position( void ) |
{ |
/* advance the position for the next icon. */ |
ShowINITTable[0] += XOffset; |
/* recompute the checksum. */ |
ShowINITTable[1] = CheckSum(ShowINITTable[0]); |
} |
/* DrawBWIcon() draws the 'ICN#' member of the icon family. */ |
void DrawBWIcon( short iconId, Rect *icon_rect, Boolean visible ) |
{ |
Handle icon; |
BitMap source, destination; |
RgnHandle empty_mask; |
GrafPtr port; |
icon = Get1Resource('ICN#', iconId); |
if (!icon) |
return; |
HLock(icon); |
/* prepare the source and destination bitmaps. */ |
source.baseAddr = *icon + 128; /* mask address. */ |
source.rowBytes = 4; |
SetRect(&source.bounds, 0, 0, 32, 32); |
GetPort( &port ); |
destination = ((GrafPtr)port)->portBits; |
empty_mask = visible? nil : NewRgn(); |
/* transfer the mask. */ |
CopyBits(&source, &destination, &source.bounds, icon_rect, |
srcBic, empty_mask); |
/* and the icon. */ |
source.baseAddr = *icon; |
CopyBits(&source, &destination, &source.bounds, icon_rect, |
srcOr, empty_mask); |
if (empty_mask) DisposeRgn( empty_mask ); |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14