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 | // This version features: |
---|
10 | // - Short and readable code. |
---|
11 | // - Correctly wraps around when more than one row of icons has been displayed. |
---|
12 | // - works with System 6 |
---|
13 | // - Built with Universal Headers & CodeWarrior. Should work with other headers/compilers. |
---|
14 | |
---|
15 | #include <Memory.h> |
---|
16 | #include <Resources.h> |
---|
17 | #include <Icons.h> |
---|
18 | #include <OSUtils.h> |
---|
19 | #include "ShowInitIcon.h" |
---|
20 | |
---|
21 | // You should set SystemSixOrLater in your headers to avoid including glue for SysEnvirons. |
---|
22 | |
---|
23 | // --------------------------------------------------------------------------------------------------------------------- |
---|
24 | // Set this flag to 1 if you want to compile this file into a stand-alone resource (see note below). |
---|
25 | // Set it to 0 if you want to include this source file into your INIT project. |
---|
26 | |
---|
27 | #if 0 |
---|
28 | #define ShowInitIcon main |
---|
29 | #endif |
---|
30 | |
---|
31 | // --------------------------------------------------------------------------------------------------------------------- |
---|
32 | // The ShowINIT mechanism works by having each INIT read/write data from these globals. |
---|
33 | // The MPW C compiler doesn't accept variables declared at an absolute address, so I use these macros instead. |
---|
34 | // Only one macro is defined per variable; there is no need to define a Set and a Get accessor like in <LowMem.h>. |
---|
35 | |
---|
36 | #define LMVCheckSum (*(unsigned short*) 0x928) |
---|
37 | #define LMVCoord (*( short*) 0x92A) |
---|
38 | #define LMHCoord (*( short*) 0x92C) |
---|
39 | #define LMHCheckSum (*(unsigned short*) 0x92E) |
---|
40 | |
---|
41 | // --------------------------------------------------------------------------------------------------------------------- |
---|
42 | // Prototypes for the subroutines. The main routine comes first; this is necessary to make THINK C's "Custom Header" option work. |
---|
43 | |
---|
44 | static unsigned short CheckSum (short x); |
---|
45 | static void ComputeIconRect (Rect* iconRect, Rect* screenBounds); |
---|
46 | static void AdvanceIconPosition (Rect* iconRect); |
---|
47 | static void DrawBWIcon (short iconID, Rect *iconRect); |
---|
48 | |
---|
49 | // --------------------------------------------------------------------------------------------------------------------- |
---|
50 | // Main routine. |
---|
51 | |
---|
52 | typedef struct { |
---|
53 | QDGlobals qd; // Storage for the QuickDraw globals |
---|
54 | long qdGlobalsPtr; // A5 points to this place; it will contain a pointer to qd |
---|
55 | } QDStorage; |
---|
56 | |
---|
57 | pascal void ShowInitIcon (short iconFamilyID, Boolean advance) |
---|
58 | { |
---|
59 | long oldA5; // Original value of register A5 |
---|
60 | QDStorage qds; // Fake QD globals |
---|
61 | CGrafPort colorPort; |
---|
62 | GrafPort bwPort; |
---|
63 | Rect destRect; |
---|
64 | SysEnvRec environment; // Machine configuration. |
---|
65 | |
---|
66 | oldA5 = SetA5((long) &qds.qdGlobalsPtr); // Tell A5 to point to the end of the fake QD Globals |
---|
67 | InitGraf(&qds.qd.thePort); // Initialize the fake QD Globals |
---|
68 | |
---|
69 | SysEnvirons(curSysEnvVers, &environment); // Find out what kind of machine this is |
---|
70 | |
---|
71 | ComputeIconRect(&destRect, &qds.qd.screenBits.bounds); // Compute where the icon should be drawn |
---|
72 | |
---|
73 | if (environment.systemVersion >= 0x0700 && environment.hasColorQD) { |
---|
74 | OpenCPort(&colorPort); |
---|
75 | PlotIconID(&destRect, atNone, ttNone, iconFamilyID); |
---|
76 | CloseCPort(&colorPort); |
---|
77 | } |
---|
78 | else { |
---|
79 | OpenPort(&bwPort); |
---|
80 | DrawBWIcon(iconFamilyID, &destRect); |
---|
81 | ClosePort(&bwPort); |
---|
82 | } |
---|
83 | |
---|
84 | if (advance) |
---|
85 | AdvanceIconPosition (&destRect); |
---|
86 | |
---|
87 | SetA5(oldA5); // Restore A5 to its previous value |
---|
88 | } |
---|
89 | |
---|
90 | // --------------------------------------------------------------------------------------------------------------------- |
---|
91 | // A checksum is used to make sure that the data in there was left by another ShowINIT-aware INIT. |
---|
92 | |
---|
93 | static unsigned short CheckSum (short x) |
---|
94 | { |
---|
95 | return (unsigned short)(((x << 1) | (x >> 15)) ^ 0x1021); |
---|
96 | } |
---|
97 | |
---|
98 | // --------------------------------------------------------------------------------------------------------------------- |
---|
99 | // ComputeIconRect computes where the icon should be displayed. |
---|
100 | |
---|
101 | static void ComputeIconRect (Rect* iconRect, Rect* screenBounds) |
---|
102 | { |
---|
103 | if (CheckSum(LMHCoord) != LMHCheckSum) // If we are first, we need to initialize the shared data. |
---|
104 | LMHCoord = 8; |
---|
105 | if (CheckSum(LMVCoord) != LMVCheckSum) |
---|
106 | LMVCoord = (short)(screenBounds->bottom - 40); |
---|
107 | |
---|
108 | if (LMHCoord + 34 > screenBounds->right) { // Check whether we must wrap |
---|
109 | iconRect->left = 8; |
---|
110 | iconRect->top = (short)(LMVCoord - 40); |
---|
111 | } |
---|
112 | else { |
---|
113 | iconRect->left = LMHCoord; |
---|
114 | iconRect->top = LMVCoord; |
---|
115 | } |
---|
116 | iconRect->right = (short)(iconRect->left + 32); |
---|
117 | iconRect->bottom = (short)(iconRect->top + 32); |
---|
118 | } |
---|
119 | |
---|
120 | // AdvanceIconPosition updates the shared global variables so that the next extension will draw its icon beside ours. |
---|
121 | |
---|
122 | static void AdvanceIconPosition (Rect* iconRect) |
---|
123 | { |
---|
124 | LMHCoord = (short)(iconRect->left + 40); // Update the shared data |
---|
125 | LMVCoord = iconRect->top; |
---|
126 | LMHCheckSum = CheckSum(LMHCoord); |
---|
127 | LMVCheckSum = CheckSum(LMVCoord); |
---|
128 | } |
---|
129 | |
---|
130 | // DrawBWIcon draws the 'ICN#' member of the icon family. It works under System 6. |
---|
131 | |
---|
132 | static void DrawBWIcon (short iconID, Rect *iconRect) |
---|
133 | { |
---|
134 | Handle icon; |
---|
135 | BitMap source, destination; |
---|
136 | GrafPtr port; |
---|
137 | |
---|
138 | icon = Get1Resource('ICN#', iconID); |
---|
139 | if (icon != NULL) { |
---|
140 | HLock(icon); |
---|
141 | // Prepare the source and destination bitmaps. |
---|
142 | source.baseAddr = *icon + 128; // Mask address. |
---|
143 | source.rowBytes = 4; |
---|
144 | SetRect(&source.bounds, 0, 0, 32, 32); |
---|
145 | GetPort(&port); |
---|
146 | destination = port->portBits; |
---|
147 | // Transfer the mask. |
---|
148 | CopyBits(&source, &destination, &source.bounds, iconRect, srcBic, nil); |
---|
149 | // Then the icon. |
---|
150 | source.baseAddr = *icon; |
---|
151 | CopyBits(&source, &destination, &source.bounds, iconRect, srcOr, nil); |
---|
152 | } |
---|
153 | } |
---|
154 | |
---|
155 | // --------------------------------------------------------------------------------------------------------------------- |
---|
156 | // Notes |
---|
157 | |
---|
158 | // Checking for PlotIconID: |
---|
159 | // We (PNL) now check for system 7 and colour QD, and use colour graf ports and PlotIconID only if both are true |
---|
160 | // Otherwise we use B&W grafport and draw using PlotBWIcon. |
---|