AmendHub

Download

vkoskiv

/

MacNTP

/

ShowInitIcon.c

 

(View History)

vkoskiv   Implement a very rough first-pass control panel + fallback option Latest amendment: 16 on 2023-09-13

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 }