Corners
Volume Number: | | 5
|
Issue Number: | | 4
|
Column Tag: | | Advanced Mac'ing
|
Related Info: Window Manager
Re-sizing with Window Corners
By Clifford Story, Goleta, CA
Note: Source code files accompanying article are located on MacTech CD-ROM or source code disks.
I suppose youve probably heard of the new Open Look interface for Unix. (Not so new anymore, actually!) The thing looks pretty familiar -- windows, scroll bars, menus. Everything has some kind of a twist on it, though. The menus are all pop-ups; the scroll bars include the up and down arrows as part of the indicator; and the windows can be re-sized from any corner, not just the lower right corner.
Thats an interesting idea, re-sizing from any corner. I wonder if you could do that on the Mac... I held a long argument with myself on that topic, and the affirmative finally won. You can do it on the Mac; heres one way.
Before I get started, let me thank Tom Leonard, who encouraged me, and Don Melton and Mike Ritter, whose article in the April MacTutor inspired me.
THE WINDOW
The first half of the problem is to draw the window with appropriate grow brackets in the corners, and to have it return the wInGrow message when the user clicks in one of them. This is done in a window definition procedure, or WDEF.
WDEFs have been pretty well covered in MacTutor; I refer you to the Window Manager chapter of Inside Macintosh, and to Melton and Ritters WDEF discussed in their April article and published in May.
By the way, an earlier version used WDEF 0 to do most of the work. Apple, however, has declared its intention to remove WDEF 0 from the System file (it hasnt done it yet). So I figured I had better do it myself. One thing led to another, and this program now supports zoom windows on the old 64K ROM.
THE PATCH
If all I did was insert the WDEF, Id get a nice looking window with some funny behavior (try it! nothing bad will happen). I need to make the Window Manager respond appropriately to mouse downs in a grow bracket.
So taking the hint from Melton and Ritter, I replaced the GrowWindow and SizeWindow routines. And while I was at it, I made my new sizethewindow routine a replacement for ZoomWindow as well, and added a replacement for TrackBox, so I could zoom windows as well as grow them.
Figure 1. Growing the window
BLOW-BY-BLOW
The program is contained in the file Corners.p, the replacement routines in the unit Patches.p, and the WDEF in the file WDEF.p (Okay, so I lack imagination!). Theres another unit Common.p that at one time was substantial but now has only some minor type and constant declarations. The resource source file is Corners.r.
When the user clicks in one of the corner brackets, the program calls FindWindow, which in turn calls the WDEF. The WDEF returns wInGrow if the click was close to any of the corners. Simple so far. FindWindow tells the program the click was in the grow box, and the program calls the Patches routine growthewindow in place of the ROMs GrowWindow.
Growthewindow has a lot of work to do. It must track the mouse, and draw a gray outline of the re-sized window as it does so. When the mouse is released, it must return not just the new dimensions of the window but the new location as well.
Growthewindow doesnt actually draw the gray outline; that is done by the WDEF. But it must tell the WDEF the rectangle to use when drawing. The basic method of computing this rectangle is (1) find the fixed corner of the window (the one opposite the corner being dragged), which I call the pivot; (2) track the mouse in a loop, each time getting the current mouse position; (3) use the wonderful Toolbox routine Pt2Rect to convert the mouse position and the pivot into a rectangle; and (4) call the WDEF to draw the gray outline from that rectangle.
That sounds simple but there are a lot of small things that cloud the picture. For example, the old gray outline must be erased before the new is drawn. And the mouse will rarely start out at the corner of the portrect, so a correction must be applied. And then there are various constraints on the rectangle, e.g., those imposed by the SizeRect parameter. Also, the rectangle must be in global coordinates.
When all this is done, and the user releases the mouse button, the routine must return the windows new size and location. What could be easier than just returning the last rectangle?
Now were back to the Corners program. It has the new portrect, in global coordinates, as returned by growthewindow. It calls another Patches routine, sizethewindow, which makes the actual changes in the window.
Sizethewindow does more than just re-size the window. Since the top left corner may have moved, the window must be moved as well. My first version of this routine called MoveWindow and SizeWindow but this resulted in two updates. Nesting the calls within ShowHide calls solved that but... I wanted something that would look just as smooth as the normal grow. ZoomWindow worked but limited the program to machines with the new ROM. Finally I discovered the QD routine MovePortTo, which does not update the screen! It is amazing what you can find, overlooked for years, in the QD chapter!
When I made that discovery, I realized that my sizethewindow routine could easily pinch-hit for ZoomWindow, giving me zoom windows on the old ROM. So for our next adventure, we will ask the user to click on the zoom box...
BLOWS AGAINST THE ZOOM BOX
Once again, the program calls FindWindow, which calls the WDEF, which returns wInZoomIn (I might note here that the WDEF could return anything I want, since this is all done privately). The program than calls the Patches routine trackthebox.
Trackthebox is kinda rough; I think it could be slimmed down but why bother? The time it takes is entirely determined by the user. Anyway, it goes into a loop, getting the mouse location, calling the WDEF to find out where that is, and calling the WDEF to highlight the zoom box if the mouse had just moved either in or out. When the button is released, the routine returns true if the mouse is still in the zoom box, false otherwise.
Now the program gets busy. First, note that one field of the record whose handle is stored in the refcon field of the window record is called zoomrect. Suggestive, huh? It gets the portrect of the window and compares it with a full screen portrect (this is done in global coordinates, of course). If the window is not at full screen, then its current portrect is saved in the zoomrect field, and sizethewindow zooms it to full screen. If it is at full screen, then the zoomrect is used to size it back down.
PUTTING IT TOGETHER
To add four-cornered windows to your program, add the Patches unit to your uses clause and the WDEF to the resource file. Then change the type of your windows from zoomDocProc or whatever to 800. Finally, change calls to GrowWindow and SizeWindow to growthewindow and sizethewindow (this will require more than just a name change but not much more).
If you want to support zooming, youll have to hack a little further. Let the description above be your guide.
Listing: Common.p
(************************************************************)
unit Common;
(************************************************************)
interface
(*********************************************************
key codes:
*************************************************************)
const
enterkey = 3;
backspace= 8;
tabkey = 9;
returnkey= 13;
clearkey = 27;
leftarrow= 28;
rightarrow = 29;
uparrow= 30;
downarrow= 31;
periodkey= 46;
(*************************************************************
Dialog items:
*************************************************************)
themask= 3;
(************************************************************
Low-memory globals:
*************************************************************)
applscratch= $A78;
bootdrive= $210;
curappname = $910;
curdirstore= $398;
currenta5= $904;
findername = $2E0;
fsfcblen = $3F6;
grayrgn= $9EE;
iaznotify= $33C;
mbarheight = $BAA;
menuflash= $A24;
resload= $A5E;
rom85 = $28E;
sfsavedisk = $214;
sysmap = $A58;
windowlist = $9D6;
(**********************************************************
Standard types:
*************************************************************)
type
logical= boolean;
long = longint;
shortpointer = ^integer;
longpointer= ^long;
(************************************************************)
end.
(************************************************************)
Listing: Corners.p
(*************************************************************
Corners.p
Shell program for four-cornered windows.
(c) 1988, by Clifford Story & Attic Software
*************************************************************)
program Corners;
(************************************************************)
uses memtypes, quickdraw, osintf, toolintf, Common, Patches;
(*************************************************************
Program constants:
*************************************************************)
const
applenum = 1001;
aboutitem= 1;
atticitem= 2;
filenum= 1002;
newitem= 1;
closeitem= 2;
quititem = 4;
editnum= 1003;
undoitem = 1;
cutitem= 3;
copyitem = 4;
pasteitem= 5;
clearitem= 6;
windownum= 1001;
scrollnum= 1001;
hoffset= 32;
voffset= 20;
(**************************************************************
Program types:
*************************************************************)
type
wrecord= record
window : WindowPtr;
zoomrect : Rect;
hscroll: ControlHandle;
vscroll: ControlHandle;
disprect : Rect;
end;
wpointer = ^wrecord;
whandle= ^wpointer;
(*************************************************************
Program variables:
*************************************************************)
var
APPLEMENU: MenuHandle;
FILEMENU : MenuHandle;
EDITMENU : MenuHandle;
MOUSEREGION: RgnHandle;
SCREENREGION : RgnHandle;
MENUHEIGHT : integer;
DRAGRECT : Rect;
GROWRECT : Rect;
SCREENRECT : Rect;
COLUMNS: integer;
ROWS : integer;
WINDOWCOUNT: integer;
DONE : logical;
JEVENT : logical;
MAINEVENT: EventRecord;
(************************************************************)
procedure _datainit; external;
(************************************************************)
{$R-}
{$SC+}
(************************************************************)
procedure panic;
begin
ExitToShell;
end;
(************************************************************)
procedure initmac;
begin
MaxApplZone;
InitGraf(@thePort);
InitFonts;
InitWindows;
InitCursor;
InitMenus;
TEInit;
InitDialogs(@panic);
UnloadSeg(@_datainit);
end;
(************************************************************)
procedure setupmenus;
begin
APPLEMENU := GetMenu(applenum);
AddResMenu(APPLEMENU, DRVR);
InsertMenu(APPLEMENU, 0);
FILEMENU := GetMenu(filenum);
InsertMenu(FILEMENU, 0);
EDITMENU := GetMenu(editnum);
InsertMenu(EDITMENU, 0);
DrawMenuBar;
end;
(************************************************************
initglobals
----------
Heres where I initialize all the global variables.
DRAGRECT is an argument to DragWindow; GROWRECT is an
argument to growthewindow (in the Patches unit);
SCREENRECT is used in zooming (its the portrect of a full-
screen window); and ROWS andCOLUMNS are used to stack the
windows on the screen.
*************************************************************)
procedure initglobals;
var
index : integer;
theshort : shortpointer;
begin
for index := 1 to 10 do
MoreMasters;
if BitTst(Ptr(rom85), 0) then begin
MENUHEIGHT := 20;
JEVENT := false;
end else begin
theshort := shortpointer(mbarheight);
MENUHEIGHT := theshort^;
JEVENT := (NGetTrapAddress($A860, ToolTrap)
<> NGetTrapAddress($A89F, ToolTrap));
end;
with screenBits.bounds do begin
SetRect(DRAGRECT, left + 5, top + MENUHEIGHT + 5,
right - 5, bottom - 25);
SetRect(GROWRECT, 160, 100, right - left - 10,
bottom - top - MENUHEIGHT - 10);
SetRect(SCREENRECT, left + 5, top + MENUHEIGHT + 25,
right - 5, bottom - 5);
COLUMNS := 1 + ((right - left - 330) div hoffset);
ROWS := 1 + ((bottom - top - MENUHEIGHT - 230) div voffset);
WINDOWCOUNT := 0;
end;
DONE := false;
end;
(************************************************************
clickapplemenu
--------------
This may not be new to you but it is to me! Instead of
using an alert for the About... box, Im using a picture.
First I open a new GrafPort, then draw the picture in its
center. Note that I must re-draw the windows after the user
dismisses the screen, using PaintBehind.
*************************************************************)
procedure clickapplemenu(theitem : integer);
var
itemname : Str255;
savedport: GrafPtr;
dummy : integer;
newport: GrafPort;
thepicture : PicHandle;
therect: Rect;
begin
if theitem > 3 then begin
GetItem(APPLEMENU, theitem, itemname);
GetPort(savedport);
dummy := OpenDeskAcc(itemname);
SetPort(savedport);
end else if theitem < 3 then begin
InitCursor;
GetPort(savedport);
OpenPort(@newport);
SetPort(@newport);
thepicture := PicHandle(GetResource(PICT,
1000 + theitem));
with thepicture^^.picFrame do
SetRect(therect, 0, 0, right - left, bottom - top);
with screenBits.bounds, therect.botright do
OffsetRect(therect, (right - left - h) div 2,
(bottom - top - v) div 3);
DrawPicture(thepicture, therect);
repeat until Button;
ClosePort(@newport);
EnableItem(EDITMENU, 0);
DrawMenuBar;
PaintBehind(WindowPeek(FrontWindow),
RgnHandle(longpointer(grayrgn)^));
SetPort(savedport);
FlushEvents(everyEvent, 0);
end;
end;
(*************************************************************
placewindow
----------
This routine cost me $40.00 (its the only thing I got out
of Macintosh Revealed).
*************************************************************)
procedure placewindow(thewindow : WindowPtr);
var
left : integer;
top : integer;
begin
left := 5 + hoffset * (WINDOWCOUNT mod COLUMNS);
top := 5 + MENUHEIGHT
+ voffset * (1 + (WINDOWCOUNT mod ROWS));
MoveWindow(thewindow, left, top, true);
end;
(************************************************************)
procedure wsize(thewindow : whandle);
var
thewidth : integer;
theheight: integer;
begin
HLock(Handle(thewindow));
with thewindow^^ do begin
thewidth := window^.portRect.right;
theheight := window^.portRect.bottom;
HideControl(hscroll);
HideControl(vscroll);
MoveControl(vscroll, thewidth - 15, -1);
SizeControl(vscroll, 16, theheight - 13);
MoveControl(hscroll, 15, theheight - 15);
SizeControl(hscroll, thewidth - 29, 16);
disprect := window^.portRect;
InsetRect(disprect, 10, 10);
OffsetRect(disprect, -8, -8);
ShowControl(hscroll);
ShowControl(vscroll);
end;
HUnlock(Handle(thewindow));
end;
(************************************************************)
procedure donew;
label
100;
var
thehandle: whandle;
thewindow: WindowPtr;
begin
thehandle := whandle(NewHandle(sizeof(wrecord)));
if thehandle = nil then
goto 100;
HLock(Handle(thehandle));
with thehandle^^ do begin
window := GetNewWindow(windownum, nil, WindowPtr(-1));
if window = nil then begin
DisposHandle(Handle(thehandle));
goto 100;
end;
SetWRefCon(window, long(thehandle));
zoomrect := SCREENRECT;
hscroll := GetNewControl(scrollnum, window);
if hscroll = nil then begin
DisposeWindow(window);
DisposHandle(Handle(thehandle));
goto 100;
end;
vscroll := GetNewControl(scrollnum, window);
if vscroll = nil then begin
DisposeControl(hscroll);
DisposeWindow(window);
DisposHandle(Handle(thehandle));
goto 100;
end;
placewindow(window);
wsize(thehandle);
ShowWindow(window);
WINDOWCOUNT := WINDOWCOUNT + 1;
end;
HUnlock(Handle(thehandle));
100: end;
(************************************************************)
procedure doclose(thepeek : WindowPeek);
var
thehandle: whandle;
begin
if thepeek^.windowkind < 0 then
CloseDeskAcc(thepeek^.windowkind)
else begin
thehandle := whandle(thepeek^.refCon);
DisposeControl(thehandle^^.hscroll);
DisposeControl(thehandle^^.vscroll);
DisposeWindow(WindowPtr(thepeek));
DisposHandle(Handle(thehandle));
WINDOWCOUNT := WINDOWCOUNT - 1;
end;
end;
(************************************************************)
procedure clickfilemenu(itemchoice : integer);
var
dummy : logical;
begin
case itemchoice of
newitem: donew;
closeitem: doclose(WindowPeek(FrontWindow));
quititem : DONE := true;
end;
end;
(************************************************************)
procedure checkmenu(thewindow : WindowPeek);
begin
DisableItem(EDITMENU, 0);
if thewindow = nil then
DisableItem(FILEMENU, closeitem)
else begin
if thewindow^.windowkind <> userKind then
EnableItem(EDITMENU, 0);
EnableItem(FILEMENU, closeitem);
end;
end;
(************************************************************)
procedure clickinmenu;
var
choice : long;
begin
checkmenu(WindowPeek(FrontWindow));
choice := MenuSelect(MAINEVENT.where);
case HiWord(choice) of
applenum : clickapplemenu(LoWord(choice));
filenum: clickfilemenu(LoWord(choice));
editnum: if not SystemEdit(LoWord(choice) - 1) then;
end;
HiliteMenu(0);
end;
(**********************************************************
clickingrow
----------
This is just like the usual grow routine, except that Im
calling the Patches routines growthewindow and
sizethewindow. These behave like GrowWindow and
SizeWindow, but in the four-cornered context.
*************************************************************)
procedure clickingrow(thewindow : WindowPtr);
var
newrect: Rect;
begin
if growthewindow(thewindow, MAINEVENT.where,
GROWRECT, newrect) then begin
sizethewindow(thewindow, newrect);
wsize(whandle(GetWRefCon(thewindow)));
end;
end;
(************************************************************)
procedure clickingoaway(thewindow : WindowPtr);
begin
if TrackGoAway(thewindow, MAINEVENT.where) then
doclose(WindowPeek(thewindow));
end;
(*************************************************************
clickinzoom
----------
Custom zooming - this will work on any ROM. trackthebox
performs exactly like TrackBox; I wrote it so I could track
clicks in the zoom box regardless of ROM version. The
actual zooming uses sizethewindow, which I already have
for growing windows.
Each window has a field called zoomrect. If Im zooming
to full screen, I save the old portRect in zoomrect first.
If Im already at full screen and Im zooming back, I use
the save zoomrect as the target portRect. Note, though,
that zoomrect must be in global coordinates.
*************************************************************)
procedure clickinzoom(thewindow : WindowPtr);
var
thehandle: whandle;
therect: Rect;
begin
if trackthebox(thewindow) then begin
thehandle := whandle(GetWRefCon(thewindow));
therect := thewindow^.portRect;
EraseRect(therect);
LocalToGlobal(therect.topleft);
LocalToGlobal(therect.botright);
if EqualRect(therect, SCREENRECT) then
therect := thehandle^^.zoomrect
else begin
thehandle^^.zoomrect := therect;
therect := SCREENRECT;
end;
sizethewindow(thewindow, therect);
wsize(thehandle);
end;
end;
(************************************************************)
procedure aclick;
var
location : integer;
thewindow: WindowPtr;
begin
location := FindWindow(MAINEVENT.where, thewindow);
case location of
inDesk : SysBeep(1);
inMenuBar: clickinmenu;
inSysWindow: SystemClick(MAINEVENT, thewindow);
inContent: SelectWindow(thewindow);
inDrag : DragWindow(thewindow, MAINEVENT.where, DRAGRECT);
inGrow : clickingrow(thewindow);
inGoAway : clickingoaway(thewindow);
inZoomIn : clickinzoom(thewindow);
end;
end;
(************************************************************)
procedure akey;
var
charcode : integer;
choice : long;
begin
if BitAnd(MAINEVENT.modifiers, cmdKey) <> 0 then begin
charcode := BitAnd(MAINEVENT.message, charCodeMask);
checkmenu(WindowPeek(FrontWindow));
choice := MenuKey(chr(charcode));
if choice <> 0 then begin
case HiWord(choice) of
applenum : clickapplemenu(LoWord(choice));
filenum: clickfilemenu(LoWord(choice));
editnum: if not SystemEdit(LoWord(choice) - 1) then;
end;
HiliteMenu(0);
end;
end;
end;
(************************************************************)
procedure anactivate(thewindow : WindowPtr);
begin
SetPort(thewindow);
DrawGrowIcon(thewindow);
end;
(************************************************************)
procedure anupdate(thewindow : WindowPtr);
var
savedport: GrafPtr;
begin
GetPort(savedport);
SetPort(thewindow);
BeginUpdate(thewindow);
ClipRect(thewindow^.portRect);
EraseRect(thewindow^.portRect);
DrawGrowIcon(thewindow);
DrawControls(thewindow);
EndUpdate(thewindow);
SetPort(savedport);
end;
(************************************************************)
procedure mainloop;
var
dummy : logical;
begin
repeat
if JEVENT then
dummy := waitnextevent(everyEvent, MAINEVENT,
GetCaretTime, nil)
else begin
SystemTask;
dummy := GetNextEvent(everyEvent, MAINEVENT);
end;
if dummy then begin
case MAINEVENT.what of
mouseDown: aclick;
keyDown: akey;
autoKey: akey;
activateEvt: anactivate(WindowPtr(MAINEVENT.message));
updateEvt: anupdate(WindowPtr(MAINEVENT.message));
end;
end;
until DONE;
end;
(************************************************************)
procedure shutdown;
var
thelong: longpointer;
thepeek: WindowPeek;
begin
thelong := longpointer(windowlist);
thepeek := WindowPeek(thelong^);
while thepeek <> nil do begin
doclose(thepeek);
thepeek := thepeek^.nextwindow;
end;
end;
(************************************************************)
begin
initmac;
setupmenus;
initglobals;
mainloop;
shutdown;
end.
(************************************************************)
Listing: Patches.p
(************************************************************
Patches.p
ROM replacements for four-cornered windows.
(c) 1988, by Clifford Story & Attic Software
*************************************************************)
unit Patches;
(************************************************************)
interface
(************************************************************)
uses memtypes, quickdraw, osintf, toolintf, Common;
(************************************************************)
function growthewindow(theWindow : WindowPtr; startpoint : Point; sizerect
: Rect; var newportrect : Rect) : logical;
procedure sizethewindow(theWindow : WindowPtr; newrect : Rect);
function trackthebox(theWindow : WindowPtr) : logical;
(************************************************************)
implementation
(************************************************************)
{$R-}
{$SC+}
(*************************************************************
callWDEF
--------
The inline code here is:
movea.l(SP)+,A0
jsr A0
That is, it pops the address argument into register A0,
and then calls the routine at that address.
*************************************************************)
function callWDEF(variation : integer; thewindow : WindowPtr; message
: integer; param : Ptr; address : Ptr) : long; inline $205F, $4E90;
(*************************************************************
growthewindow
------------
This routine is an analog of the Toolbox trap GrowWindow; it
follows mouse with a gray outline of the windows new size.
Im going to draw in Window Manager port, and Im going to
set the clipping to full screen (the low-memory global
grayrgn contains a handle to the region consisting of
everything but the menu bar). Since I dont want to upset
the Window Manager, Ill save the old clip region first, so
I can restore it at the end. The pen mode makes drawing its
own inverse. This routine draws by calling the WDEF with a
wGrow message. All this is in the Window Manager section
of Inside Mac; Im just approaching it from the other side.
The mouse is down in one corner of the window. The
diagonally opposite window is fixed for this operation; I
call it the pivot. The mouse is probably not on the
corner exactly; I use offset to correct the mouse
position. And this corrected position will be corrected
further to bring it within limitrect if it strays outside.
From here on, its simple. Draw the first outline; then, so
long as the mouse stays down, repeatedly erase it (by re-
drawing) and draw the new outline. When the mouse is
released, erase the outline and return the new portRect.
*************************************************************)
function growthewindow(thewindow : WindowPtr; startpoint : Point; sizerect
: Rect; var newportrect : Rect) : logical;
var
savedport: GrafPtr;
drawport : GrafPtr;
savedclip: RgnHandle;
thepointer : longpointer;
WDEF : Handle;
newrect: Rect;
west : logical;
north : logical;
pivot : Point;
offset : Point;
limitrect: Rect;
menuheight : integer;
theshort : shortpointer;
dummy : long;
oldrect: Rect;
newpoint : Point;
begin
GetPort(savedport);
GetWMgrPort(drawport);
SetPort(drawport);
savedclip := NewRgn;
GetClip(savedclip);
thepointer := longpointer(grayrgn);
SetClip(RgnHandle(thepointer^));
PenMode(notPatXor);
PenPat(gray);
WDEF := WindowPeek(thewindow)^.windowdefproc;
HLock(WDEF);
newrect := thewindow^.portRect;
with thewindow^.portBits.bounds do
OffsetRect(newrect, - left, - top);
with newrect do begin
if startpoint.v <= ((top + bottom) div 2) then begin
pivot.v := bottom;
offset.v := top - startpoint.v;
limitrect.top := bottom - sizerect.bottom;
limitrect.bottom := bottom - sizerect.top;
end else begin
pivot.v := top;
offset.v := bottom - startpoint.v;
limitrect.top := top + sizerect.top;
limitrect.bottom := top + sizerect.bottom;
end;
if startpoint.h <= ((left + right) div 2) then begin
pivot.h := right;
offset.h := left - startpoint.h;
limitrect.left := right - sizerect.right;
limitrect.right := right - sizerect.left;
end else begin
pivot.h := left;
offset.h := right - startpoint.h;
limitrect.left := left + sizerect.left;
limitrect.right := left + sizerect.right;
end;
end;
if BitTst(Ptr(rom85), 0) then
menuheight := 38
else begin
theshort := shortpointer(mbarheight);
menuheight := theshort^ + 18;
end;
if limitrect.top < menuheight then
limitrect.top := menuheight;
newpoint := startpoint;
AddPt(offset, newpoint);
newpoint := Point(PinRect(limitrect, newpoint));
Pt2Rect(pivot, newpoint, newrect);
dummy := callWDEF(0, thewindow, wGrow, @newrect, WDEF^);
oldrect := newrect;
while StillDown do begin
GetMouse(newpoint);
AddPt(offset, newpoint);
newpoint := Point(PinRect(limitrect, newpoint));
Pt2Rect(pivot, newpoint, newrect);
if not EqualRect(newrect, oldrect) then begin
dummy := callWDEF(0, thewindow, wGrow, @oldrect, WDEF^);
dummy := callWDEF(0, thewindow, wGrow, @newrect, WDEF^);
oldrect := newrect;
end;
end;
dummy := callWDEF(0, thewindow, wGrow, @oldrect, WDEF^);
HUnlock(WDEF);
PenNormal;
SetClip(savedclip);
DisposeRgn(savedclip);
SetPort(thewindow);
oldrect := thewindow^.portRect;
LocalToGlobal(oldrect.topleft);
LocalToGlobal(oldrect.botright);
if EqualRect(oldrect, newrect) then
growthewindow := false
else begin
newportrect := newrect;
growthewindow := true;
end;
SetPort(savedport);
end;
(************************************************************
sizethewindow
------------
This routine is an analog of the Toolbox trap SizeWindow.
It just precedes SizeWindow with MovePortTo, which moves the
window without updating the screen. After this, I update
the Window Manager ports clipping, so it will draw the
window correctly.
*************************************************************)
procedure sizethewindow(thewindow : WindowPtr; newrect : Rect);
var
drawport : GrafPtr;
begin
EraseRect(thewindow^.portRect);
with newrect do begin
MovePortTo(left, top);
SizeWindow(thewindow, right - left, bottom - top, false);
end;
InvalRect(thewindow^.portRect);
GetWMgrPort(drawport);
SetPort(drawport);
SetClip(WindowPeek(thewindow)^.strucrgn);
SetPort(thewindow);
ClipAbove(WindowPeek(thewindow));
end;
(************************************************************
trackthebox
----------
This routine is a duplicate of TrackBox; I would use
TrackBox but it isnt available in the old ROM.
The idea is to highlight the zoom box, and then track the
mouse while the button remains down. The zoom box should be
highlighted when the mouse is in it, and unhighlighted when
it is not. When the button is finally released, the routine
returns true if the mouse is in the zoom box, and false if
it is not.
************************************************************)
function trackthebox(thewindow : WindowPtr) : logical;
var
highlight: logical;
savedport: GrafPtr;
drawport : GrafPtr;
thepointer : longpointer;
WDEF : Handle;
thepoint : Point;
thepart: long;
begin
GetPort(savedport);
GetWMgrPort(drawport);
SetPort(drawport);
WDEF := WindowPeek(thewindow)^.windowdefproc;
HLock(WDEF);
thepart := callWDEF(0, thewindow,
wDraw, Ptr(wInZoomIn), WDEF^);
highlight := true;
while StillDown do begin
GetMouse(thepoint);
thepart := callWDEF(0, thewindow,
wHit, Ptr(thepoint), WDEF^);
if not highlight and (thepart = wInZoomIn) then begin
thepart := callWDEF(0, thewindow,
wDraw, Ptr(wInZoomIn), WDEF^);
highlight := true;
end else if highlight and (thepart <> wInZoomIn) then begin
thepart := callWDEF(0, thewindow,
wDraw, Ptr(wInZoomIn), WDEF^);
highlight := false;
end;
end;
if highlight then
thepart := callWDEF(0, thewindow,
wDraw, Ptr(wInZoomIn), WDEF^);
HUnlock(WDEF);
SetPort(savedport);
trackthebox := highlight;
end;
(************************************************************)
end.
(************************************************************)
Listing: WDEF.p
(************************************************************
WDEF.p
WDEF for four-cornered window.
(c) 1988, by Clifford Story & Attic Software
*************************************************************)
unit WDEF;
(************************************************************)
interface
(************************************************************)
uses memtypes, quickdraw, osintf, toolintf, Common;
(************************************************************)
function windowdef(variation : integer; thewindow : WindowPeek;
message : integer; param : long) : long;
(************************************************************)
implementation
(************************************************************)
{$R-}
{$SC+}
(************************************************************
datahandle
----------
This is horribly inefficient; each window saves the data for
each BitMap in its datahandle. So each window duplicates
this information (which must also be in the code, or where
would it come from?). Ive got an assembler version of this
WDEF that eliminates all this duplicate data; you could do
it in Pascal by moving the StuffHexs out of the init
routine and into the draw routine.
*************************************************************)
type
rectrecord = record
dragrect : Rect;
closerect: Rect;
zoomrect : Rect;
NWmap : BitMap;
NWdata : array [1..28] of integer;
NEmap : BitMap;
NEdata : array [1..28] of integer;
SWmap : BitMap;
SWdata : array [1..8] of integer;
SEmap : BitMap;
SEdata : array [1..8] of integer;
erasedata: array [1..8] of integer;
closemap : BitMap;
closedata: array [1..9] of integer;
zoommap: BitMap;
zoomdata : array [1..9] of integer;
end;
rectpointer= ^rectrecord;
recthandle = ^rectpointer;
QDrecord = record
randseed : long;
screenbits : bitmap;
arrow : cursor;
dkgray : pattern;
ltgray : pattern;
gray : pattern;
black : pattern;
white : pattern;
theport: grafptr;
end;
QDpointer= ^QDrecord;
(************************************************************)
procedure wdodraw(thewindow : WindowPeek; param : long); forward;
function wdohit(thewindow : WindowPeek; thepoint : Point) : long; forward;
procedure wdocalc(thewindow : WindowPeek); forward;
procedure wdonew(thewindow : WindowPeek); forward;
procedure wdodispose(thewindow : WindowPeek); forward;
procedure wdogrow(therect : rectpointer); forward;
procedure wdoicon(thewindow : WindowPtr); forward;
(************************************************************)
function windowdef(variation : integer; thewindow : WindowPeek; message
: integer; param : long) : long;
begin
windowdef := 0;
case message of
wDraw : wdodraw(thewindow, param);
wHit : windowdef := wdohit(thewindow, Point(param));
wCalcRgns: wdocalc(thewindow);
wNew : wdonew(thewindow);
wDispose : wdodispose(thewindow);
wGrow : wdogrow(rectpointer(param));
wDrawGIcon : wdoicon(WindowPtr(thewindow));
end;
end;
(************************************************************
QDglobals
--------
A WDEF cant use globals, hence cannot reference the
Quickdraw globals directly. This routine returns a pointer
to the Quickdraw globals, which the WDEF can use instead.
*************************************************************)
function QDglobals : QDpointer;
var
thepointer : longpointer;
begin
thepointer := longpointer(currenta5);
thepointer := longpointer(thepointer^);
QDglobals := QDpointer(long(thepointer^)
- sizeof(QDrecord) + sizeof(grafptr));
end;
(************************************************************
wdodraw
------
This routine draws the window. There are two special cases:
if the low word of the param argument is wInGoAway, then
this is a call for close box highlighting; if it is
wInZoomIn, then this is a call for zoom box highlighting.
I draw the various parts of the window in order. First, I
recalculate the various regions. Then I draw the windows
outline and shadow. Next is the title bar: outline the
title bar, then erase its interior. Draw the title
(truncated, if necessary, by clipping), then corners with
CopyBits, and finally the horizontal lines between corners
and the title. Last, draw the lower corners. Note that the
corner brackets are drawn only if the window is highlighted.
*************************************************************)
procedure wdodraw(thewindow : WindowPeek; param : long);
var
therect: Rect;
width : integer;
limitrect: Rect;
savedclip: RgnHandle;
height : integer;
index : integer;
begin
with thewindow^, QDglobals^.thePort^ do begin
if visible then begin
HLock(dataHandle);
with recthandle(dataHandle)^^ do begin
if LoWord(param) = wInGoAway then begin
closemap.baseAddr := @closedata;
CopyBits(closemap, portBits, closemap.bounds,
closemap.bounds, srcXor, nil);
end else if LoWord(param) = wInZoomIn then begin
zoommap.baseAddr := @zoomdata;
CopyBits(zoommap, portBits, zoommap.bounds,
zoommap.bounds, srcXor, nil);
end else if param = 0 then begin
wdocalc(thewindow);
FrameRgn(strucrgn);
therect := strucrgn^^.rgnBBox;
with therect do begin
MoveTo(left, bottom - 2);
LineTo(right - 2, bottom - 2);
LineTo(right - 2, top);
end;
therect := dragrect;
InsetRect(therect, 1, 1);
EraseRect(therect);
FrameRect(dragrect);
with dragrect do
width := (right + left - titlewidth) div 2;
if width < NWmap.bounds.right then
width := NWmap.bounds.right + 3;
limitrect.left := NWmap.bounds.right;
limitrect.top := NWmap.bounds.top - 2;
limitrect.right := NEmap.bounds.left - 3;
limitrect.bottom := NWmap.bounds.bottom + 2;
savedclip := NewRgn;
GetClip(savedclip);
ClipRect(limitrect);
SectRgn(savedclip, clipRgn, clipRgn);
MoveTo(width, dragrect.bottom - 5);
DrawString(titlehandle^^);
SetClip(savedclip);
DisposeRgn(savedclip);
if hilited then begin
NWmap.baseAddr := @NWdata;
CopyBits(NWmap, portBits, NWmap.bounds,
NWmap.bounds, srcCopy, nil);
NEmap.baseAddr := @NEdata;
CopyBits(NEmap, portBits, NEmap.bounds,
NEmap.bounds, srcCopy, nil);
if (width - 7) > NWmap.bounds.right then begin
height := closerect.top;
for index := 1 to 6 do begin
MoveTo(NWmap.bounds.right, height);
LineTo(width - 7, height);
Move(titlewidth + 13, 0);
LineTo(NEmap.bounds.left - 1, height);
height := height + 2;
end;
end;
end;
if hilited then begin
SEmap.baseAddr := @SEdata;
SWmap.baseAddr := @SWdata;
end else begin
SWmap.baseAddr := @erasedata;
SEmap.baseAddr := @erasedata;
end;
CopyBits(SWmap, portBits, SWmap.bounds,
SWmap.bounds, srcCopy, nil);
CopyBits(SEmap, portBits, SEmap.bounds,
SEmap.bounds, srcCopy, nil);
end;
end;
HUnlock(dataHandle);
end;
end;
end;
(************************************************************
wdohit
------
This routine hit-tests a point, and returns window part that
the point lies in. The first section tests for the grow
brackets; if the point is near the top, and also near the
left edge, then its in top-left bracket, ect. Note that
unhighlighted windows dont have grow brackets. The rest is
just testing for specific rectangles.
************************************************************)
function wdohit(thewindow : WindowPeek; thepoint : Point) : long;
label
100, 200;
var
therect: Rect;
begin
wdocalc(thewindow);
with thewindow^ do begin
HLock(dataHandle);
with recthandle(dataHandle)^^ do begin
wdohit := wNoHit;
if hilited then begin
therect := strucrgn^^.rgnBBox;
if (thepoint.v > (therect.top + 8))
and (thepoint.v < (therect.bottom - 8)) then
goto 100;
if (thepoint.h > (therect.left + 8))
and (thepoint.h < (therect.right - 8)) then
goto 100;
wdohit := wInGrow;
goto 200;
end;
100: if PtInRect(thepoint, closerect) and hilited and goAwayFlag then
wdohit := wInGoAway
else if PtInRect(thepoint, zoomrect) and hilited then
wdohit := wInZoomIn
else if PtInRect(thepoint, contrgn^^.rgnBBox) then
wdohit := wInContent
else if PtInRect(thepoint, dragrect) then
wdohit := wInDrag;
end;
HUnlock(dataHandle);
end;
200: end;
(************************************************************
wdocalc
------
This routine calculates all regions and rectangles in the
window. Note these are all in local coordinates, and that
I assume that windows portBits.bounds.topleft is the point
(0, 0).
*************************************************************)
procedure wdocalc(thewindow : WindowPeek);
var
therect: Rect;
begin
with thewindow^ do begin
therect := port.portRect;
with port.portBits.bounds do
OffsetRect(therect, - left, - top);
OpenRgn;
MoveTo(therect.left + 1, therect.top);
LineTo(therect.right - 1, therect.top);
LineTo(therect.right - 1, therect.bottom - 9);
LineTo(therect.right - 9, therect.bottom - 9);
LineTo(therect.right - 9, therect.bottom - 1);
LineTo(therect.left + 9, therect.bottom - 1);
LineTo(therect.left + 9, therect.bottom - 9);
LineTo(therect.left + 1, therect.bottom - 9);
LineTo(therect.left + 1, therect.top);
CloseRgn(contrgn);
with recthandle(dataHandle)^^, therect do begin
SetRect(dragrect, left, top - 19, right, top);
SetRect(closerect, left + 12, top - 15, left + 23, top - 4);
SetRect(zoomrect, right - 23, top - 15, right - 12, top - 4);
SetRect(NWmap.bounds, left + 1, top - 18, left + 33, top - 4);
SetRect(NEmap.bounds, right - 33, top - 18, right - 1, top - 4);
SetRect(SWmap.bounds, left + 1, bottom - 9, left + 9, bottom - 1);
SetRect(SEmap.bounds, right - 9, bottom - 9, right - 1, bottom - 1);
SetRect(closemap.bounds, left + 13, top - 14, left + 22, top - 5);
SetRect(zoommap.bounds, right - 22, top - 14, right - 13, top - 5);
end;
therect.top := therect.top - 19;
OpenRgn;
MoveTo(therect.left, therect.top);
LineTo(therect.right, therect.top);
LineTo(therect.right, therect.top + 1);
LineTo(therect.right + 1, therect.top + 1);
LineTo(therect.right + 1, therect.bottom + 1);
LineTo(therect.left + 1, therect.bottom + 1);
LineTo(therect.left + 1, therect.bottom);
LineTo(therect.left, therect.bottom);
LineTo(therect.left, therect.top);
CloseRgn(strucrgn);
end;
end;
(************************************************************
wdonew
------
This routine is called by GetNewWindow, so WDEF can set up
its private data, which is just what I do here. All those
BitMaps were carefully calculated with screen shots and fat
bits, and at a severe cost to my eyesight!
*************************************************************)
procedure wdonew(thewindow : WindowPeek);
begin
with thewindow^ do begin
dataHandle := NewHandle(sizeof(rectrecord));
HLock(dataHandle);
with recthandle(dataHandle)^^ do begin
with NWmap do begin
baseAddr := @NWdata;
if goAwayFlag then
StuffHex(baseAddr, 0100000001000000010000001F5FFDFF1010040017 D005FF10100400F7D005FF001004007FD005FF001004007FD005FF001004007FDFFDFF)
else
StuffHex(baseAddr, 01000000010000000100000 01F7FFFFF1000000017FFFFFF10000000F7FFFFFF000000007FFFFFFF000000007F
FFFFFF000000007FFFFFFF);
rowBytes := 4;
end;
with NEmap do begin
baseAddr := @NEdata;
StuffHex(baseAddr, 000000800000008000000080FFBFF AF800208808FFA08BE800208808FFA08BEF00208800FFBF8BFE00200800FFA
00BFE00200800FFBFFBFE);
rowBytes := 4;
end;
with SWmap do begin
baseAddr := @SWdata;
StuffHex(baseAddr, F0001000100010001F00010001000100);
rowBytes := 2;
end;
with SEmap do begin
baseAddr := @SEdata;
StuffHex(baseAddr, 0F00080008000800F800800080008000);
rowBytes := 2;
end;
StuffHex(@erasedata, 00000000000000000000000000000000);
with closemap do begin
baseAddr := @closedata;
StuffHex(baseAddr, 080049002A000000E38000002A0049000800);
rowBytes := 2;
end;
with zoommap do begin
baseAddr := @zoomdata;
StuffHex(baseAddr, 0C004D002E000400E780FC002A0049000800);
rowBytes := 2;
end;
end;
HUnlock(dataHandle);
end;
wdocalc(thewindow);
end;
(************************************************************
wdodispose
----------
This routine is called by DisposeWindow so the WDEF can
clean up its private data.
*************************************************************)
procedure wdodispose(thewindow : WindowPeek);
begin
DisposHandle(thewindow^.dataHandle);
end;
(************************************************************
wdogrow
------
This routine draws a gray facsimile of the window, using the
rectangle it is passed as the portRect. It is called by
GrowWindow (in this program, by growthewindow).
*************************************************************)
procedure wdogrow(therect : rectpointer);
begin
with therect^ do begin
MoveTo(dragrect.left, dragrect.top - 18);
LineTo(dragrect.right, dragrect.top - 18);
LineTo(dragrect.right, dragrect.bottom);
LineTo(dragrect.left, dragrect.bottom);
LineTo(dragrect.left, dragrect.top - 18);
MoveTo(dragrect.left, dragrect.top);
LineTo(dragrect.right, dragrect.top);
end;
end;
(**************************************************************
wdoicon
------
This routine is supposed to draw the grow icon. This window
doesnt have a grow icon, so it only draws the outline for
scroll bars.
*************************************************************)
procedure wdoicon(thewindow : WindowPtr);
var
savedport: GrafPtr;
begin
GetPort(savedport);
SetPort(thewindow);
with thewindow^.portRect do begin
MoveTo(left, bottom - 15);
LineTo(right, bottom - 15);
MoveTo(right - 15, top);
LineTo(right - 15, bottom);
end;
SetPort(savedport);
end;
(************************************************************)
end.
(************************************************************)
Listing: Corners.R
/***********************************************************
Corners.r
Resources for four-cornered window.
(c) 1988, by Clifford Story & Attic Software
*************************************************************/
#include types.r
/************************************************************
Menu resources
*************************************************************/
resource MENU (1001, preload) {
1001,
textMenuProc,
0x7FFFFFFB,
enabled,
apple,
{ /* array: 3 elements */
/* [1] */
About Corners..., 1, , , plain,
/* [2] */
About Attic Software..., noicon, , , plain,
/* [3] */
-, noIcon, , , plain
}
};
resource MENU (1002, preload) {
1002,
textMenuProc,
0x7FFFFFF9,
enabled,
File,
{ /* array: 4 elements */
/* [1] */
New, noIcon, N, , plain,
/* [2] */
Close, noIcon, K, , plain,
/* [3] */
-, noIcon, , , plain,
/* [4] */
Quit, noIcon, Q, , plain
}
};
resource MENU (1003, preload) {
1003,
textMenuProc,
0x7FFFFFFD,
enabled,
Edit,
{ /* array: 6 elements */
/* [1] */
Undo, noIcon, Z, , plain,
/* [2] */
-, noIcon, , , plain,
/* [3] */
Cut, noIcon, X, , plain,
/* [4] */
Copy, noIcon, C, , plain,
/* [5] */
Paste, noIcon, V, , plain,
/* [6] */
Clear, noIcon, , , plain,
}
};
/************************************************************
Picture resources
*************************************************************/
resource PICT (1001, About, purgeable) {
1081,
{7, 7, 308, 499},
$1101 A000 82A0 008C 0100 0A00 0700 0701"
$3401 F30A 0000 0000 0000 0000 0B00 1B00"
$1B44 0009 0009 0132 01F1 0700 0200 0248"
$A100 9600 0606 0000 0002 03A1 009A 0008"
$FFFD 0000 00D4 0000 A000 9803 0003 0D00"
$0A28 012A 0026 22A9 2031 3938 3820 6279"
$2043 6C69 6666 6F72 6420 5374 6F72 7920"
$616E 6420 4174 7469 6329 AC22 2053 6F66"
$7477 6172 652C 2050 2E4F 2E20 426F 7820"
$3231 392C 2047 6F6C 6574 612C 2043 29A6"
$1161 6C69 666F 726E 6961 2020 2039 3331"
$3136 A000 99A0 0097 A100 9600 0606 0000"
$0002 03A1 009A 0008 FFFA 0000 0027 0000"
$A000 9804 050D 0012 2800 2D00 E007 436F
$726E 6572 73A0 0099 A000 97A1 0096 0006"
$0500 0000 0203 A100 9A00 0800 4400 0000"
$DA00 00A0 0098 0400 0D00 0C28 0057 001E
$2254 6869 7320 7072 6F67 7261 6D20 6465"
$6D6F 6E73 7472 6174 6573 2061 6E20 696E
$7465 7229 E022 6573 7469 6E67 2065 7874"
$656E 7469 6F6E 206F 6620 7468 6520 4D61"
$6369 6E74 6F73 680D A000 99A1 009A 0008"
$0034 0000 00DA 0000 A000 9828 0067 001E
$2269 6E74 6572 6661 6365 3A20 2077 696E
$646F 7773 2074 6861 7420 6361 6E20 6265"
$2072 6529 D622 2D73 697A 6564 2066 726F
$6D20 616E 7920 636F 726E 6572 2028 696E
$7374 6561 6420 6F66 29D7 010D A000 99A1"
$009A 0008 0024 0000 00DA 0000 A000 9828"
$0077 001E 226F 6E6C 7920 6672 6F6D 2074"
$6865 206C 6F77 6572 2072 6967 6874 292E
$2020 4561 6368 2029 CF22 636F 726E 6572"
$2068 6173 2061 20D2 6772 6F77 2062 7261"
$636B 6574 D320 7768 6963 680D A000 99A1"
$009A 0008 0014 0000 00DA 0000 A000 9828"
$0087 001E 2279 6F75 2063 616E 2064 7261"
$6720 6A75 7374 206C 696B 6520 7468 6520"
$7573 7561 6C20 6729 CF0A 726F 7720 6963"
$6F6E 2E0D A000 99A1 009A 0008 0004 0000"
$00DA 0000 A000 9828 0097 001E 010D A000"
$99A1 009A 0008 FFF4 0000 00DA 0000 A000"
$982A 1022 5769 6E64 6F77 7320 7769 7468"
$2074 6869 7320 6665 6174 7572 6520 776F
$756C 6420 7072 29E1 1B6F 6261 626C 7920"
$6265 206D 6F73 7420 7573 6566 756C 2069"
$6E20 610D A000 99A1 009A 0008 FFE4 0000"
$00DA 0000 A000 9828 00B7 001E 2267 7261"
$7068 6963 7320 7072 6F67 7261 6D2C 206C
$6573 7320 7573 6566 756C 2069 6E20 6129"
$D420 2074 6578 7420 7072 6F67 7261 6D2E
$2020 5468 6973 2070 6172 7469 6375 6C61"
$720D A000 99A1 009A 0008 FFD4 0000 00DA
$0000 A000 9828 00C7 001E 2270 726F 6772"
$616D 2069 7320 6F66 206E 6F20 7573 6520"
$6174 2061 6C6C 3B20 6974 2773 2029 C622"
$6A75 7374 2061 2074 6561 7365 7220 666F
$7220 7468 6520 436F 726E 6572 7320 6172"
$7469 29D0 0463 6C65 0DA0 0099 A100 9A00"
$08FF C400 0000 DA00 00A0 0098 2800 D700"
$1E22 696E 2074 6865 2046 6562 7275 6172"
$7920 3139 3839 2069 7373 7565 206F 6620"
$4D61 6320 29D7 1F54 7574 6F72 2C20 7768"
$6963 6820 696E 636C 7564 6573 2074 6865"
$2066 756C 6C0D A000 99A1 009A 0008 FFB4"
$0000 00DA 0000 A000 9828 00E7 001E 1350"
$6173 6361 6C20 736F 7572 6365 2063 6F64"
$652E A000 99A0 0097 A000 8DA0 0083 FF
};
resource PICT (1002, Attic, purgeable) {
1125,
{7, 7, 306, 497},
$1101 A000 82A0 008C 0100 0A00 0700 0701"
$3201 F10A 0000 0000 0000 0000 0B00 1B00"
$1B44 0009 0009 0130 01EF 0700 0200 0248"
$A100 9600 0606 0000 0002 03A1 009A 0008"
$FFFA 0000 004B 0000 A000 9803 0003 0405"
$0D00 122B BA2B 0E41 7474 6963 2053 6F66"
$7477 6172 65A0 0099 A000 97A1 0096 0006"
$0500 0000 0203 A100 9A00 0800 5C00 0000"
$E600 00A0 0098 0400 0D00 0C28 004D 001D
$2241 7474 6963 2053 6F66 7477 6172 6520"
$6973 2061 2073 6D61 6C6C 204D 6163 696E
$746F 7329 DC22 6820 7072 6F67 7261 6D6D
$696E 6720 636F 6D70 616E 792E 2069 6E20"
$6275 7369 6E65 7373 29E2 010D A000 99A1"
$009A 0008 004C 0000 00E6 0000 A000 9828"
$005D 001D 2273 696E 6365 2031 3938 362E
$2020 5765 2064 6F20 6120 7661 7269 6574"
$7920 6F66 2077 6F29 D722 726B 3B20 D249"
$6465 616C 696E 6572 D32C 2061 2073 6861"
$7265 7761 7265 206F 7574 6C69 29D1 056E
$6572 2C0D A000 99A1 009A 0008 003C 0000"
$00E6 0000 A000 9828 006D 001D 2269 7320"
$6F75 7220 6265 7374 2D6B 6E6F 776E 2070"
$726F 6475 6374 2E20 2057 6520 616C 7329"
$D81B 6F20 646F 2063 6F6E 7472 6163 7420"
$7072 6F67 7261 6D6D 696E 672E 0DA0 0099"
$A100 9A00 0800 2C00 0000 E600 00A0 0098"
$2800 7D00 1D01 0DA0 0099 A100 9A00 0800"
$1C00 0000 E600 00A0 0098 2A10 1E57 6520"
$6361 6E20 6265 2072 6561 6368 6564 2062"
$7920 6D61 696C 2061 743A 0DA0 0099 A100"
$9A00 0800 0C00 0000 E600 00A0 0098 2A10"
$010D A000 99A1 009A 0008 FFFC 0000 00E6"
$0000 A000 982A 1022 2020 2020 2020 2020"
$2020 2020 2020 2020 2020 2020 2020 2020"
$2020 2020 2020 2041 7474 2991 0C69 6320"
$536F 6674 7761 7265 0DA0 0099 A100 9A00"
$08FF EC00 0000 E600 00A0 0098 2800 BD00"
$1D22 2020 2020 2020 2020 2020 2020 2020"
$2020 2020 2020 2020 2020 2020 2020 2020"
$2050 2E4F 298F 0A2E 2042 6F78 2032 3139"
$0DA0 0099 A100 9A00 08FF DC00 0000 E600"
$00A0 0098 2800 CD00 1D22 2020 2020 2020"
$2020 2020 2020 2020 2020 2020 2020 2020"
$2020 2020 2020 2020 2047 6F6C 2990 1865"
$7461 2C20 4361 6C69 666F 726E 6961 2020"
$2039 3331 3136 0DA0 0099 A100 9A00 08FF
$CC00 0000 E600 00A0 0098 2800 DD00 1D01"
$0DA0 0099 A100 9A00 08FF BC00 0000 E600"
$00A0 0098 2A10 2257 6520 616C 736F 206F
$7065 7261 7465 2061 2062 756C 6C65 7469"
$6E20 626F 6172 6420 7329 D422 7973 7465"
$6D20 6174 2028 3830 3529 2036 3833 2D30"
$3332 322C 2062 6574 7765 656E 2074 29E6"
$0368 650D A000 99A1 009A 0008 FFAC 0000"
$00E6 0000 A000 9828 00FD 001D 2268 6F75"
$7273 206F 6620 363A 3030 2050 4D20 616E
$6420 323A 3030 2041 4D2C 2050 6163 6929"
$D822 6669 6320 7469 6D65 2C20 7365 7665"
$6E20 6461 7973 2061 2077 6565 6B2E 2020"
$506C 6561 29D3 0373 650D A000 99A1 009A
$0008 FF9C 0000 00E6 0000 A000 9828 010D
$001D 1566 6565 6C20 6672 6565 2074 6F20"
$6361 6C6C 2069 6E21 A000 99A0 0097 A100"
$9600 0606 0000 0002 03A1 009A 0008 FFFD
$0000 006D 0000 A000 980D 000A 2B73 1722"
$A920 3139 3838 2062 7920 436C 6966 666F
$7264 2053 746F 7279 2061 6E64 2041 7474"
$6963 29AC 0920 536F 6674 7761 7265 A000"
$99A0 0097 A000 8DA0 0083 FF
};
/************************************************************ Window
resource
*************************************************************/
resource WIND (1001, purgeable, preload) {
{0, 0, 200, 320},
800,
invisible,
goaway,
0x0,
untitled
};
/************************************************************ Scroll
bar resource
*************************************************************/
resource CNTL (1001, purgeable, preload) {
{0, 0, 16, 50},
1,
invisible,
1,
1,
scrollBarProc,
0,
};
/************************************************************
Bundle resources
*************************************************************/
resource BNDL (1001, Corners) {
CORN,
0,
{ /* array TypeArray: 2 elements */
/* [1] */
ICN#,
{ /* array IDArray: 1 elements */
/* [1] */
0, 1001,
},
/* [2] */
FREF,
{ /* array IDArray: 1 elements */
/* [1] */
0, 1001,
}
}
};
/************************************************************
File reference resource
************************************************************/
resource FREF (1001, CORN APPL, purgeable) {
APPL,
0,
};
/************************************************************
Icon list resource
************************************************************/
resource ICN# (1001, APPL Icon, purgeable) {
{ /* array: 2 elements */
/* [1] */
$0000 0000 7FFF FFFE 4040 0202 4040 0202"
$4040 0202 47C0 03E2 4400 0022 4400 0022"
$4400 0022 7C00 003E 4000 0002 4000 0002"
$4000 0002 4000 0002 4000 0002 4000 0002"
$4000 0002 4000 0002 4000 0002 4000 0002"
$4000 0002 4000 0002 7C00 003E 4400 0022"
$4400 0022 4400 0022 47C0 03E2 4040 0202"
$4040 0202 4040 0202 7FFF FFFE,
/* [2] */
$FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF
$FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF
$FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF
$FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF
$FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF
$FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF
$FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF
$FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF
}
};
/************************************************************
Icon resource
************************************************************/
resource ICON (257, purgeable) {
$0000 0000 7FFF FFFE 4040 0202 4040 0202"
$4040 0202 47C0 03E2 4400 0022 4400 0022"
$4400 0022 7C00 003E 4000 0002 4000 0002"
$4000 0002 4000 0002 4000 0002 4000 0002"
$4000 0002 4000 0002 4000 0002 4000 0002"
$4000 0002 4000 0002 7C00 003E 4400 0022"
$4400 0022 4400 0022 47C0 03E2 4040 0202"
$4040 0202 4040 0202 7FFF FFFE,
};
/************************************************************
Finder resource
************************************************************/
data CORN (0, purgeable) {
$50A9 2031 3938 382C 2062 7920 436C 6966"
/* P© 1988, by Clif */
$666F 7264 2053 746F 7279 2026 2041 7474"
/* ford Story & Att */
$6963 2053 6F66 7477 6172 650D 502E 4F2E
/* ic Software¬P.O. */
$2042 6F78 2032 3139 0D47 6F6C 6574 612C
/* Box 219¬Goleta, */
$2043 616C 6966 6F72 6E69 6120 3933 3131"
/* California 9311 */
$36" /* 6 */
};
/************************************************************
Multifinder resource
************************************************************/
resource SIZE (-1) {
saveScreen,
acceptSuspendResumeEvents,
enableOptionSwitch,
cannotBackground,
MultiFinderAware,
98304,
98304
};
/***********************************************************/
Listing: Corners.make
#************************************************************
#Corners.make
#(c) 1988, by Clifford Story & Attic Software
#************************************************************
#************************************************************
#compile resources
#************************************************************
Corners Corners.make Corners.r
Rez Corners.r -append -o Corners
#************************************************************
#compile common declarations
#************************************************************
Common.p.o Corners.make Common.p
Pascal Common.p
#************************************************************
#compile and link WDEF
#************************************************************
WDEF.p.o Corners.make WDEF.p Common.p.o
Pascal WDEF.p
Corners Corners.make WDEF.p.o
Link -m WINDOWDEF -w -t APPL -c CORN
-rt WDEF=50 -sn Main=Four Corners
WDEF.p.o
{Libraries}Interface.o
{Libraries}Runtime.o
{PLibraries}PasLib.o
{PLibraries}SANELib.o
-o Corners
#************************************************************
#compile ROM replacements
#************************************************************
Patches.p.o Corners.make Patches.p Common.p.o
Pascal Patches.p
#************************************************************
#compile and link Corners
#************************************************************
Corners.p.o Corners.make Corners.p Patches.p.o
Pascal Corners.p
Corners Corners.make Corners.p.o
Link -w -t APPL -c CORN
Corners.p.o
Patches.p.o
{Libraries}Interface.o
{Libraries}Runtime.o
{PLibraries}PasLib.o
{PLibraries}SANELib.o
-o Corners
#************************************************************