![](/file/12652/www.mactech.com.tar/www.mactech.com/sites/all/themes/custom_front/images/you_are_here_red.gif)
![](/file/12652/www.mactech.com.tar/www.mactech.com/sites/default/files/beta-site.gif)
|
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 #************************************************************
![](/file/12652/www.mactech.com.tar/www.mactech.com/sites/all/themes/custom_front/img/search_text.gif)
- SPREAD THE WORD:
- Slashdot
- Digg
- Del.icio.us
- Newsvine