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
#************************************************************

 
AAPL
$102.99
Apple Inc.
+0.52
MSFT
$44.38
Microsoft Corpora
-0.50
GOOG
$532.71
Google Inc.
+6.17

MacTech Search:
Community Search:

Software Updates via MacUpdate

OmniOutliner 4.1.3 - Organize your ideas...
OmniOutliner is a flexible program for creating, collecting, and organizing information. Give your creativity a kick start by using an application that's actually designed to help you think. It's... Read more
BBEdit 11.0 - Powerful text and HTML edi...
BBEdit is the leading professional HTML and text editor for the Mac. Specifically crafted in response to the needs of Web authors and software developers, this award-winning product provides a... Read more
Apple Security Update 2014-005 - For OS...
Apple Security Update is recommended for all users and improves the security of Mac OS X. For information on the security content of this update, please visit this website: http://support.apple.com/... Read more
EyeTV 3.6.6 - Watch and record TV on you...
EyeTV brings a rich TV experience to your Mac. Watch live TV on your Mac. Pause, rewind, and record whenever you want. EyeTV gives you powerful control over what you watch and how you watch it. Put... Read more
RapidWeaver 6.0 - Create template-based...
RapidWeaver is a next-generation Web design application to help you easily create professional-looking Web sites in minutes. No knowledge of complex code is required, RapidWeaver will take care of... Read more
NTFS 12.0.39 - Provides full read and wr...
Paragon NTFS breaks down the barriers between Windows and OS X. Paragon NTFS effectively solves the communication problems between the Mac system and NTFS, providing full read and write access to... Read more
RestoreMeNot 2.0.3 - Disable window rest...
RestoreMeNot provides a simple way to disable the window restoration for individual applications so that you can fine-tune this behavior to suit your needs. Please note that RestoreMeNot is designed... Read more
Command-C 1.1.5 - Clipboard sharing tool...
Command-C is a revolutionary app which makes easy to share your clipboard between iOS and OS X using your local WiFi network, even if the app is not currently opened. Copy anything (text, pictures,... Read more
Macgo Blu-ray Player 2.10.9.1750 - Blu-r...
Macgo Mac Blu-ray Player can bring you the most unforgettable Blu-ray experience on your Mac. Overview Macgo Mac Blu-ray Player can satisfy just about every need you could possibly have in a Blu-ray... Read more
Apple iOS 8.1 - The latest version of Ap...
The latest version of iOS can be downloaded through iTunes. Apple iOS 8 comes with big updates to apps you use every day, like Messages and Photos. A whole new way to share content with your family.... Read more

Latest Forum Discussions

See All

TinType by Hipstamatic (Photography)
TinType by Hipstamatic 1.0 Device: iOS iPhone Category: Photography Price: $.99, Version: 1.0 (iTunes) Description: Create hauntingly beautiful, soul capturing portraits with TinType by Hipstamatic. Inspired by daguerreotypes,... | Read more »
The Latest Update for Heroes of Dragon A...
The Latest Update for Heroes of Dragon Age Introduces Daily PvE Challenges Posted by Ellis Spice on October 22nd, 2014 [ permalink ] | Read more »
A New Trailer has Been Revealed for Epic...
A New Trailer has Been Revealed for Epic of Kings Posted by Jessica Fisher on October 22nd, 2014 [ permalink ] Dead Mage Inc. has released a new, action-packed trailer for the upcoming Epic of Kings. | Read more »
Find the Line Review
Find the Line Review By Campbell Bird on October 22nd, 2014 Our Rating: :: INSLIDE THE LINESUniversal App - Designed for iPhone and iPad Tease out beautiful line drawings in this unique, free-to-play puzzle game.   | Read more »
The Silent Age Episode 2 Review
The Silent Age Episode 2 Review By Jennifer Allen on October 22nd, 2014 Our Rating: :: ROUNDING THINGS OFF NICELYUniversal App - Designed for iPhone and iPad Rounding off a great point and click adventure comes The Silent Age... | Read more »
Craft Your Own Mini-Games with Papercade
Craft Your Own Mini-Games with Papercade Posted by Jessica Fisher on October 22nd, 2014 [ permalink ] iPad Only App - Designed for the iPad Scrapbookers move over, Scrapgaming is the new thing. | Read more »
Reshape Review
Reshape Review By Jennifer Allen on October 22nd, 2014 Our Rating: :: SIMPLE SHAPESUniversal App - Designed for iPhone and iPad Match triangles together to form cubes in this fast-paced and twitchy game.   | Read more »
Miika (Games)
Miika 1.0.0 Device: iOS Universal Category: Games Price: $1.99, Version: 1.0.0 (iTunes) Description: Miika is a beautiful 3D puzzle game based on camera perspectives combined with the use of optical illusions. Miika challenges... | Read more »
Infuse Pro (Photography)
Infuse Pro 3.0 Device: iOS Universal Category: Photography Price: $9.99, Version: 3.0 (iTunes) Description: ** All-new version 3 includes fully licensed and certified DTS® and DTS-HD® audio! ** | Read more »
Swap Heroes (Games)
Swap Heroes 1.0 Device: iOS Universal Category: Games Price: $.99, Version: 1.0 (iTunes) Description: **Half price for a limited time only** Swap Heroes is a casual turn-based strategy adventure. Form a group of heroes and guide them... | Read more »

Price Scanner via MacPrices.net

Save with Best Buy’s College Student Deals
Take an additional $50 off all MacBooks and iMacs at Best Buy Online with their College Students Deals Savings, valid through November 1st. Anyone with a valid .EDU email address can take advantage... Read more
iPad Air 2 & iPad mini 3 Best Tablets Yet...
The new iPads turned out to be pretty much everything I’d been hoping for and more than I’d expected.”More” particularly in terms of a drinking-from-a-firehose choice of models and configurations,... Read more
Drafts 4 Reinvents iOS Productivity App
N Richland Hills, Texas based Agile Tortoise has announced the release of Drafts 4 for iPhone and iPad. Drafts is a quick capture note taking app with flexible output actions. Drafts 4 scales from... Read more
AT&T accepting preorders for new iPads fo...
AT&T Wireless is accepting preorders for the new iPad Air 2 and iPad mini 3, cellular models, for $100 off MSRP with a 2-year service agreement: - 16GB iPad Air 2 WiFi + Cellular: $529.99 - 64GB... Read more
Apple offering refurbished Mac Pros for up to...
The Apple Store is offering Apple Certified Refurbished 2013 Mac Pros for up to $600 off the cost of new models. An Apple one-year warranty is included with each Mac Pro, and shipping is free. The... Read more
Select MacBook Airs $100 off MSRP, free shipp...
B&H Photo has 2014 a couple of MacBook Airs on sale for $100 off MSRP. Shipping is free, and B&H charges NY sales tax only. They also include free copies of Parallels Desktop and LoJack for... Read more
13-inch 2.5GHz MacBook Pro on sale for $100 o...
B&H Photo has the 13″ 2.5GHz MacBook Pro on sale for $999.99 including free shipping plus NY sales tax only. Their price is $100 off MSRP. Read more
Strong iPhone, Mac And App Store Sales Drive...
Apple on Monday announced financial results for its fiscal 2014 fourth quarter ended September 27, 2014. The Company posted quarterly revenue of $42.1 billion and quarterly net profit of $8.5 billion... Read more
Apple Posts How-To For OS X Recovery
OS X 10.7 Lion and later include OS X Recovery. This feature includes all of the tools you need to reinstall OS X, repair your disk, and even restore from a Time Machine backup. OS X Recovery... Read more
Mac OS X Versions (Builds) Supported By Vario...
Apple Support has posted a handy resource explaining which Mac OS X versions (builds) originally shipped with or are available for your computer via retail discs, downloads, or Software Update. Apple... Read more

Jobs Board

Senior Event Manager, *Apple* Retail Market...
…This senior level position is responsible for leading and imagining the Apple Retail Team's global event strategy. Delivering an overarching brand story; in-store, Read more
*Apple* Solutions Consultant (ASC) - Apple (...
**Job Summary** The ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The ASC's role is to grow Apple Read more
Project Manager / Business Analyst, WW *Appl...
…a senior project manager / business analyst to work within our Worldwide Apple Fulfillment Operations and the Business Process Re-engineering team. This role will work Read more
*Apple* Retail - Multiple Positions (US) - A...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
Position Opening at *Apple* - Apple (United...
…customers purchase our products, you're the one who helps them get more out of their new Apple technology. Your day in the Apple Store is filled with a range of Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.