TweetFollow Us on Twitter

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 you’ve 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.

That’s 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; here’s 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.

WDEF’s have been pretty well covered in MacTutor; I refer you to the Window Manager chapter of Inside Macintosh, and to Melton and Ritter’s 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 hasn’t 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, I’d 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!). There’s 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 ROM’s 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 doesn’t 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 window’s new size and location. What could be easier than just returning the last rectangle?

Now we’re 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, you’ll 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
 ---------- 
 Here’s 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 (it’s 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, I’m 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 (it’s 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 I’m
 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 I’m zooming
 to full screen, I save the old portRect in zoomrect first.  
 If I’m already at full screen and I’m 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 window’s new size.
 
 I’m going to draw in Window Manager port, and I’m 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 don’t want to upset 
 the Window Manager, I’ll 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; I’m 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, it’s 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 port’s 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 isn’t 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?).  I’ve got an assembler version of this 
 WDEF that eliminates all this duplicate data; you could do 
 it in Pascal by moving the StuffHex’s 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 can’t 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 window’s
 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 it’s in top-left bracket, ect.  Note that
 unhighlighted windows don’t 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 window’s 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
 doesn’t 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
#************************************************************

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Latest Forum Discussions

See All

Challenge those pesky wyverns to a dance...
After recently having you do battle against your foes by wildly flailing Hello Kitty and friends at them, GungHo Online has whipped out another surprising collaboration for Puzzle & Dragons. It is now time to beat your opponents by cha-cha... | Read more »
Pack a magnifying glass and practice you...
Somehow it has already been a year since Torchlight: Infinite launched, and XD Games is celebrating by blending in what sounds like a truly fantastic new update. Fans of Cthulhu rejoice, as Whispering Mist brings some horror elements, and tests... | Read more »
Summon your guild and prepare for war in...
Netmarble is making some pretty big moves with their latest update for Seven Knights Idle Adventure, with a bunch of interesting additions. Two new heroes enter the battle, there are events and bosses abound, and perhaps most interesting, a huge... | Read more »
Make the passage of time your plaything...
While some of us are still waiting for a chance to get our hands on Ash Prime - yes, don’t remind me I could currently buy him this month I’m barely hanging on - Digital Extremes has announced its next anticipated Prime Form for Warframe. Starting... | Read more »
If you can find it and fit through the d...
The holy trinity of amazing company names have come together, to release their equally amazing and adorable mobile game, Hamster Inn. Published by HyperBeard Games, and co-developed by Mum Not Proud and Little Sasquatch Studios, it's time to... | Read more »
Amikin Survival opens for pre-orders on...
Join me on the wonderful trip down the inspiration rabbit hole; much as Palworld seemingly “borrowed” many aspects from the hit Pokemon franchise, it is time for the heavily armed animal survival to also spawn some illegitimate children as Helio... | Read more »
PUBG Mobile teams up with global phenome...
Since launching in 2019, SpyxFamily has exploded to damn near catastrophic popularity, so it was only a matter of time before a mobile game snapped up a collaboration. Enter PUBG Mobile. Until May 12th, players will be able to collect a host of... | Read more »
Embark into the frozen tundra of certain...
Chucklefish, developers of hit action-adventure sandbox game Starbound and owner of one of the cutest logos in gaming, has released their roguelike deck-builder Wildfrost. Created alongside developers Gaziter and Deadpan Games, Wildfrost will... | Read more »
MoreFun Studios has announced Season 4,...
Tension has escalated in the ever-volatile world of Arena Breakout, as your old pal Randall Fisher and bosses Fred and Perrero continue to lob insults and explosives at each other, bringing us to a new phase of warfare. Season 4, Into The Fog of... | Read more »
Top Mobile Game Discounts
Every day, we pick out a curated list of the best mobile discounts on the App Store and post them here. This list won't be comprehensive, but it every game on it is recommended. Feel free to check out the coverage we did on them in the links below... | Read more »

Price Scanner via MacPrices.net

Free iPhone 15 plus Unlimited service for $60...
Boost Infinite, part of MVNO Boost Mobile using AT&T and T-Mobile’s networks, is offering a free 128GB iPhone 15 for $60 per month including their Unlimited service plan (30GB of premium data).... Read more
$300 off any new iPhone with service at Red P...
Red Pocket Mobile has new Apple iPhones on sale for $300 off MSRP when you switch and open up a new line of service. Red Pocket Mobile is a nationwide MVNO using all the major wireless carrier... Read more
Clearance 13-inch M1 MacBook Airs available a...
Apple has clearance 13″ M1 MacBook Airs, Certified Refurbished, available for $759 for 8-Core CPU/7-Core GPU/256GB models and $929 for 8-Core CPU/8-Core GPU/512GB models. Apple’s one-year warranty is... Read more
Updated Apple MacBook Price Trackers
Our Apple award-winning MacBook Price Trackers are continually updated with the latest information on prices, bundles, and availability for 16″ and 14″ MacBook Pros along with 13″ and 15″ MacBook... Read more
Every model of Apple’s 13-inch M3 MacBook Air...
Best Buy has Apple 13″ MacBook Airs with M3 CPUs in stock and on sale today for $100 off MSRP. Prices start at $999. Their prices are the lowest currently available for new 13″ M3 MacBook Airs among... Read more
Sunday Sale: Apple iPad Magic Keyboards for 1...
Walmart has Apple Magic Keyboards for 12.9″ iPad Pros, in Black, on sale for $150 off MSRP on their online store. Sale price for online orders only, in-store price may vary. Order online and choose... Read more
Apple Watch Ultra 2 now available at Apple fo...
Apple has, for the first time, begun offering Certified Refurbished Apple Watch Ultra 2 models in their online store for $679, or $120 off MSRP. Each Watch includes Apple’s standard one-year warranty... Read more
AT&T has the iPhone 14 on sale for only $...
AT&T has the 128GB Apple iPhone 14 available for only $5.99 per month for new and existing customers when you activate unlimited service and use AT&T’s 36 month installment plan. The fine... Read more
Amazon is offering a $100 discount on every M...
Amazon is offering a $100 instant discount on each configuration of Apple’s new 13″ M3 MacBook Air, in Midnight, this weekend. These are the lowest prices currently available for new 13″ M3 MacBook... Read more
You can save $300-$480 on a 14-inch M3 Pro/Ma...
Apple has 14″ M3 Pro and M3 Max MacBook Pros in stock today and available, Certified Refurbished, starting at $1699 and ranging up to $480 off MSRP. Each model features a new outer case, shipping is... Read more

Jobs Board

Omnichannel Associate - *Apple* Blossom Mal...
Omnichannel Associate - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Read more
Operations Associate - *Apple* Blossom Mall...
Operations Associate - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Read more
Cashier - *Apple* Blossom Mall - JCPenney (...
Cashier - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Blossom Mall Read more
IT Systems Engineer ( *Apple* Platforms) - S...
IT Systems Engineer ( Apple Platforms) at SpaceX Hawthorne, CA SpaceX was founded under the belief that a future where humanity is out exploring the stars is Read more
*Apple* Systems Administrator - JAMF - Activ...
…**Public Trust/Other Required:** None **Job Family:** Systems Administration **Skills:** Apple Platforms,Computer Servers,Jamf Pro **Experience:** 3 + years of Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.