| 1 |
// ShowInitIcon - version 1.0.1, May 30th, 1995 |
| 2 |
// This code is intended to let INIT writers easily display an icon at startup time. |
| 3 |
// View in Geneva 9pt, 4-space tabs |
| 4 |
|
| 5 |
// Written by: Peter N Lewis <peter@mail.peter.com.au>, Jim Walker <JWWalker@aol.com> |
| 6 |
// and François Pottier <pottier@dmi.ens.fr>, with thanks to previous ShowINIT authors. |
| 7 |
// Send comments and bug reports to François Pottier. |
| 8 |
|
| 9 |
// Hacked a bit by Valtteri Koskivuori on 08.09.2023: |
| 10 |
// * Removed Sys7/Color QD code |
| 11 |
// * Added missing QDGlobals struct |
| 12 |
// * Now compiles in Think C 5.0.1 under System 6 |
| 13 |
|
| 14 |
|
| 15 |
// This version features: |
| 16 |
// - Short and readable code. |
| 17 |
// - Correctly wraps around when more than one row of icons has been displayed. |
| 18 |
// - works with System 6 |
| 19 |
// - Built with Universal Headers & CodeWarrior. Should work with other headers/compilers. |
| 20 |
|
| 21 |
#include <Memory.h> |
| 22 |
#include <Resources.h> |
| 23 |
#include <Icons.h> |
| 24 |
#include <OSUtils.h> |
| 25 |
#include <Quickdraw.h> |
| 26 |
#include "ShowInitIcon.h" |
| 27 |
|
| 28 |
// You should set SystemSixOrLater in your headers to avoid including glue for SysEnvirons. |
| 29 |
|
| 30 |
// --------------------------------------------------------------------------------------------------------------------- |
| 31 |
// Set this flag to 1 if you want to compile this file into a stand-alone resource (see note below). |
| 32 |
// Set it to 0 if you want to include this source file into your INIT project. |
| 33 |
|
| 34 |
#if 0 |
| 35 |
#define ShowInitIcon main |
| 36 |
#endif |
| 37 |
|
| 38 |
// --------------------------------------------------------------------------------------------------------------------- |
| 39 |
// The ShowINIT mechanism works by having each INIT read/write data from these globals. |
| 40 |
// The MPW C compiler doesn't accept variables declared at an absolute address, so I use these macros instead. |
| 41 |
// Only one macro is defined per variable; there is no need to define a Set and a Get accessor like in <LowMem.h>. |
| 42 |
|
| 43 |
#define LMVCoord (* (short*) 0x92A) |
| 44 |
#define LMVCheckSum (* (short*) 0x928) |
| 45 |
#define LMHCoord (* (short*) 0x92C) |
| 46 |
#define LMHCheckSum (* (short*) 0x92E) |
| 47 |
|
| 48 |
// --------------------------------------------------------------------------------------------------------------------- |
| 49 |
// Prototypes for the subroutines. The main routine comes first; this is necessary to make THINK C's "Custom Header" option work. |
| 50 |
|
| 51 |
static unsigned short CheckSum (unsigned short x); |
| 52 |
static void ComputeIconRect (Rect* iconRect, Rect* screenBounds); |
| 53 |
static void AdvanceIconPosition (Rect* iconRect); |
| 54 |
static void DrawBWIcon (short iconID, Rect *iconRect); |
| 55 |
|
| 56 |
// --------------------------------------------------------------------------------------------------------------------- |
| 57 |
// Main routine. |
| 58 |
|
| 59 |
// vkoskiv 08.09.2023: |
| 60 |
// This file is probably too new for our Sys6 environment, since Think C 5 |
| 61 |
// doesn't know about QDGlobals. Luckily they document it, so I'll just patch |
| 62 |
// in a suitable struct. |
| 63 |
|
| 64 |
// The offsets from A5 are negative, so we flip the order they appear in the doc |
| 65 |
typedef struct { |
| 66 |
char privates[76]; // No idea what this is, spotted it elsewhere |
| 67 |
long randSeed; |
| 68 |
BitMap screenBits; |
| 69 |
Cursor arrow; |
| 70 |
Pattern dkGray; |
| 71 |
Pattern ltGray; |
| 72 |
Pattern gray; |
| 73 |
Pattern black; |
| 74 |
Pattern white; |
| 75 |
GrafPtr thePort; |
| 76 |
} QDGlobals; |
| 77 |
|
| 78 |
typedef struct { |
| 79 |
QDGlobals qd; // Storage for the QuickDraw globals |
| 80 |
long qdGlobalsPtr; // A5 points to this place; it will contain a pointer to qd |
| 81 |
} QDStorage; |
| 82 |
|
| 83 |
pascal void ShowInitIcon (short iconFamilyID, Boolean advance) |
| 84 |
{ |
| 85 |
long oldA5; // Original value of register A5 |
| 86 |
QDStorage qds; // Fake QD globals |
| 87 |
CGrafPort colorPort; |
| 88 |
GrafPort bwPort; |
| 89 |
Rect destRect; |
| 90 |
|
| 91 |
oldA5 = SetA5((long) &qds.qdGlobalsPtr); // Tell A5 to point to the end of the fake QD Globals |
| 92 |
InitGraf(&qds.qd.thePort); // Initialize the fake QD Globals |
| 93 |
|
| 94 |
ComputeIconRect(&destRect, &qds.qd.screenBits.bounds); // Compute where the icon should be drawn |
| 95 |
|
| 96 |
OpenPort(&bwPort); |
| 97 |
DrawBWIcon(iconFamilyID, &destRect); |
| 98 |
ClosePort(&bwPort); |
| 99 |
|
| 100 |
if (advance) AdvanceIconPosition (&destRect); |
| 101 |
|
| 102 |
SetA5(oldA5); // Restore A5 to its previous value |
| 103 |
} |
| 104 |
|
| 105 |
// --------------------------------------------------------------------------------------------------------------------- |
| 106 |
// A checksum is used to make sure that the data in there was left by another ShowINIT-aware INIT. |
| 107 |
|
| 108 |
static unsigned short CheckSum (unsigned short x) |
| 109 |
{ |
| 110 |
return ((x << 1) | (x >> 15)) ^ 0x1021; |
| 111 |
} |
| 112 |
|
| 113 |
// --------------------------------------------------------------------------------------------------------------------- |
| 114 |
// ComputeIconRect computes where the icon should be displayed. |
| 115 |
|
| 116 |
static void ComputeIconRect (Rect* iconRect, Rect* screenBounds) |
| 117 |
{ |
| 118 |
if (CheckSum(LMHCoord) != LMHCheckSum) // If we are first, we need to initialize the shared data. |
| 119 |
LMHCoord = 8; |
| 120 |
if (CheckSum(LMVCoord) != LMVCheckSum) |
| 121 |
LMVCoord = screenBounds->bottom - 40; |
| 122 |
|
| 123 |
if (LMHCoord + 34 > screenBounds->right) { // Check whether we must wrap |
| 124 |
iconRect->left = 8; |
| 125 |
iconRect->top = LMVCoord - 40; |
| 126 |
} |
| 127 |
else { |
| 128 |
iconRect->left = LMHCoord; |
| 129 |
iconRect->top = LMVCoord; |
| 130 |
} |
| 131 |
iconRect->right = iconRect->left + 32; |
| 132 |
iconRect->bottom = iconRect->top + 32; |
| 133 |
} |
| 134 |
|
| 135 |
// AdvanceIconPosition updates the shared global variables so that the next extension will draw its icon beside ours. |
| 136 |
|
| 137 |
static void AdvanceIconPosition (Rect* iconRect) |
| 138 |
{ |
| 139 |
LMHCoord = iconRect->left + 40; // Update the shared data |
| 140 |
LMVCoord = iconRect->top; |
| 141 |
LMHCheckSum = CheckSum(LMHCoord); |
| 142 |
LMVCheckSum = CheckSum(LMVCoord); |
| 143 |
} |
| 144 |
|
| 145 |
// DrawBWIcon draws the 'ICN#' member of the icon family. It works under System 6. |
| 146 |
|
| 147 |
static void DrawBWIcon (short iconID, Rect *iconRect) |
| 148 |
{ |
| 149 |
Handle icon; |
| 150 |
BitMap source, destination; |
| 151 |
GrafPtr port; |
| 152 |
|
| 153 |
icon = Get1Resource('ICN#', iconID); |
| 154 |
if (icon != NULL) { |
| 155 |
HLock(icon); |
| 156 |
// Prepare the source and destination bitmaps. |
| 157 |
source.baseAddr = *icon + 128; // Mask address. |
| 158 |
source.rowBytes = 4; |
| 159 |
SetRect(&source.bounds, 0, 0, 32, 32); |
| 160 |
GetPort(&port); |
| 161 |
destination = port->portBits; |
| 162 |
// Transfer the mask. |
| 163 |
CopyBits(&source, &destination, &source.bounds, iconRect, srcBic, nil); |
| 164 |
// Then the icon. |
| 165 |
source.baseAddr = *icon; |
| 166 |
CopyBits(&source, &destination, &source.bounds, iconRect, srcOr, nil); |
| 167 |
//HUnlock(icon); |
| 168 |
} |
| 169 |
} |