TweetFollow Us on Twitter

Windows Holes
Volume Number:3
Issue Number:10
Column Tag:Pascal Procedures

Blasting Holes in Windows

By Greg Marriott, MacHax™ Group, Bryan, Texas

How To Build A Laser Cannon: A Home S.D.I. Project

Bit O’ History

I wish I came up with the idea to blast holes in windows, but I didn’t. The credit goes to Andrew Donoho and Darin Adler. Andrew is the author of MacSpin, a 3-d data analysis tool. MacSpin allows a user to rotate a “cloud” of data points around any of three axes in real time. Because of its highly interactive nature, Andrew likes to refer to it as a thinking man’s video game. He and Darin got together and decided that MacSpin was missing a feature essential to successful video games: laser cannons. They envisioned a user holding down command-shift-option-capsLock and being rewarded by laser turrents appearing in the corners of the data window. Add in some crosshairs with range and elevation readouts, and the user could blast away! They figured laser cannons would be especially useful in MacSpin, where unwanted data points could be annihilated, thus saving a pet theory from bothersome reality.

Andrew continued to joke about actually implementing laser cannons. That’s how my partner, Scott Boyd, heard about it. Scott was working closely with Andrew on enhancements for MacSpin when the subject of laser cannons came up. Scott knows a good idea when he hears one (most of the time), so he immediately urged Andrew to stop joking and do it. More pressing concerns kept them both busy for a while, but the idea wouldn’t die.

Laser Cannons Are Born

I learned about laser cannons in a phone conversation with Scott. I know a good idea when I hear one, too (I hope...). They were busy. I wasn’t. By the time Scott came home from Austin a couple of days later, I had the first incarnation of Blast finished. It was an application that brought up a window, and made holes wherever the cursor was when the mouse button was pressed. The holes were plain and round, and it ran silently. The holes weren’t even centered under the cursor. But gridlines drawn in the window showed that the holes were “not there.” That is, holes had been cut out of the structure of the window. Wow laser cannons.

Fig. 1 Blasting holes in Full Paint's windows! (note how the cursor changes over a hole to the arrow, proof that it is not in the window!)

“Useless Interface” Concerns

Scott and I talked about what the holes should look like. After some discussion, he drew some sample holes in MacDraw. After a while, he had something we both liked. I took the coordinates of the vertices around the hole, and put in some code to make a region (instead of just using circles). While I was at it, I started centering the hole under the cursor. So far, so good.

Sound came next. Poking holes in things isn’t very much fun if you don’t get some sort of aural feedback. We discussed all sorts of options, from simple beeps to elaborate crashing noises. I chose the easy route and used the Sound Driver to make some square-wave sound.

Making sound on the Mac is pretty easy if you’re willing to settle for single voice tones. Each tone is described by a trio of values known as a “triplet.” These numbers describe the pitch, volume, and duration of the tones you want to play. I decided to use twenty triplets. The last triplet has zero for all three values, to tell the Sound Driver to stop making noise. For the other nineteen, I chose a starting value, then decreased the pitch and volume of each succeeding tone. This gives the impression of something moving into the distance, like a train’s whistle as it heads away from you.

Now We’re Getting Somewhere

Blast didn’t change much after I added sound. The biggest change was in “packaging.” I wanted Blast to be available from anywhere, so I decided to make it into an FKEY. But as an FKEY, Blast had to stop counting on having access to global variables and resources. QuickDraw globals such as screenBits and thePort may not be available while an FKEY is running. And, counting on certain resources being installed along with the FKEY is a sure way to see everybody’s favorite bomb box. So, Blast became a procedure in a UNIT. The procedure has everything in it Blast needs to do its dirty work. [The version presented here is compatible with both MPW Pascal and LS Pascal. The unit can be either installed as an FKEY or you can call the unit from a program. In the code listing, a USES statement is presented for both MPW and LS Pascal. Since LS Pascal requires code resources to have a MAIN entry point, a procedure with the name MAIN was added to the unit, which calls BlastIt. This MAIN can be removed for MPW. -Ed]

Gory Details

The first thing I do in Blast is allocate a non-relocatable block for the sound buffer, and fill it with triplets. Then I go about putting up the crosshair cursor. I want to be polite and give the user their original cursor back when Blast is done, so I have to know what it is. But there isn’t a call to get the current cursor. Apple seems to feel that the cursor should be “write-only.” I have to dip into low memory and suck the cursor out the hard way. I suppose this is “against the rules,” but I refuse to sit back and hope the application running is smart enough to update its cursor when Blast is through. I set up the crosshair cursor and do a SetCursor call. Remember what I said about no resources? The crosshair cursor is hard-coded into Blast and the way I set it up is by using StuffHex to load up a cursor variable. It looks kind of gnarly, but it helps make Blast self-contained.

Once the cursor is up (so the user gets some immediate feedback), I pre-fabricate the hole. To do this I open a region, and draw the outline of the hole. OpenRegion hides the QuickDraw pen, so the user doesn’t get to see any drawing happen. Then I close the region and move it to the origin, ( 0, 0 ). This makes the size calculations simple, since the top and left coordinates are both zero. I want to know how big the hole is in order to “add in” a round part (sort of like a bullet hole). I make another region shaped like a circle, and use UnionRgn to add it to the jagged part. After the composite hole is prepared, Blast is almost ready to go. First, though, I set the current port to be the window manager port (the whole screen). This is so the coordinates of the holes line up with the windows’ regions out on the desktop.

The Heart Of The Matter

The main loop is pretty straightforward. Wait for a mouse click. If the click is in the content region of any window, go to work. Initiate some asynchrounous sound by calling StartSound. Move the hole to center it under the mouse. Subtract the hole (via DiffRgn) from the content region and structure region of the window. Presto! Laser cannons. After blasting a window, all the windows underneath the blasted one need to be notified that they have newly visible areas. I use the low-level Window Manager call CalcVisBehind to do this. It recalculates the visible regions of all windows under the given window that intersect a certain region (the hole region). PaintBehind is called to paint newly visible areas, including the desktop. The new system paints windows with their background patterns, instead of always painting white like the old system.

If the user clicks anywhere but a content region, Blast exits. It throws away the hole region and the sound buffer, then restores the cursor and the old port. However, the windows retain their missing holes so you can drag a window around and see the windows behind through the holes. You can even scroll the window and watch the contents move around the hole! Only when you cause the window manager to reconstruct the window such as growing or zooming the window, do the holes go away. See figure 1.

FKEY, What’s An FKEY?

Now for a few words about FKEYs. The Mac deals with FKEYs behind the scenes by intercepting key-down events when GetNextEvent is called. If an FKEY resource with the ID number of the key that was hit is found, the system loads it in and executes it. When the FKEY is done, it passes control back to the system, which then flushes the event and pretends it never happened.

Blast can be called up from within any program that calls GetNextEvent. As a matter of fact, Blast can be called recursively from within itself, since it calls GetNextEvent. This presents no real problem, since Blast carries its own local variables around. I guess the only limit is how much stack space you have, since each activation uses up several bytes of the stack.

The Recipe for MPW

Making “non-applications” is relatively simple in MPW, as long as you pay attention to a few technical details. I made Blast part of a Pascal UNIT so the compiler wouldn’t try to create a main entry point. If it was a PROGRAM, the compiler would stick in a whole bunch of global variable initialization code and try to identify an entry point. FKEYs don’t have global variables (traditionally accessed relative to register A5), so any extra code provided by the compiler is decidedly unwelcome! [Note that for LS Pascal, a main entry point is required! But the DA PasLib file is used instead of the regular PasLib so that none of the initialization for a program is done. By clicking on the code resource option, everything gets built correctly for you. See figures 2,3 and 4. -Ed]

Once the compiler is through chewing on it, the resulting object file (the .p.o file) is passed through the linker. The linker puts in any glue code needed by functions called by Blast. Glue code is most commonly used to interface between Pascal, with its stack-based calling convention, and some parts of the Mac ROM that are register-based. The glue takes parameters off the stack and puts them in registers before calling the ROM routines. Then it takes any result from a register and puts it on the stack before returning to the main program. Another kind of glue is used for range checking by the compiler. The compiler calls glue routines to check the length of strings and such when range checking is turned on.

After the glue is taken care of, the linker expects to be told where the entry point is. The -m option on the linker let me point to the proper procedure in the Blast UNIT. The linker makes sure that the very first instruction in the resulting program jumps to the entry point. An FKEY resource is just like a CODE resource without any jump table information. With the -rt option I told the linker to create FKEY resources instead of CODE resources (the default). I also told the linker to rename the main code segment from Main to BlastKey with the -sn option. This provides a reminder when viewing the resource in ResEdit. I use ResEdit to install the FKEY in the system file. FKEY Installer and FKEY Manager should work just as well.

Adding Blast to Hypercard

Everyone I’ve talked to about WildCard (now known as HyperCard, but I think that name is really dumb) is impressed by it. One of the neatest features is the ability to compile your own commands and add them to WildCard. I recently got ahold of some sketchy documentation about these XCMD resources and decided to make Blast into a WildCard command. The only difference between an FKEY and a XCMD is that XCMDs take a single argument on the stack. WildCard passes a pointer to a block full of information to the XCMD upon activation. Inside that block of information are all sorts of goodies, like handles to command-line arguments, a place for a result code, and several fields to allow the XCMD to communicate directly with WildCard. I wasn’t really interested in all that parameter stuff (yet!), so I ignored it for the moment. All I had to do to make Blast WildCard compatible was to add a formal parameter to the procedure in the UNIT. I just changed its declaration from PROCEDURE BlastIt; to PROCEDURE BlastIt( aParam : Ptr );. Then I changed the link statement to produce XCMD resources instead of FKEY resources. Voilá, a brand new WildCard command. By the way, the name of the resource is important here, because that’s how WildCard knows which XCMD is for which command.

Up On The Soap Box

I don’t know who made up some of the “rules,” but they’re not going to be too happy with Blast. I managed to break quite a few of them along the way. The first infraction is sneaking into low memory to get the current cursor. Using any low memory globals is frowned upon. Look at all the trouble Think got into when they used BasicGlobs. For those that don’t know, BasicGlobs was to be used by MacBasic, which never made it to market. Think’s Lightspeed C generated code that used it for a scratch area. Apple started to use it in System 4.1, blowing away a whole bunch of programs. Think has corrected the problem, but they blame Apple for changing their minds about using BasicGlobs. The way I see it, anybody who uses low memory areas without express written approval from Apple deserves what they get. Apple has stated many times that low memory is off limits. In fact, the area we know as low memory is going to disappear in future architectures. But since I’m only reading (and not writing) low memory, I’ll just get trash if they ever move the cursor storage area.

The next infraction is a biggy. Blast directly modifies the fields of a windowRecord, namely the strucRgn and contRgn. Apple is really touchy about windowRecords, especially since the invention of Juggler (now known as MultiFinder, but I think that name is really dumb, too). Juggler does all sorts of neat things with windows and window lists to manage multiple applications. Blast isn’t directly affected by this, but Juggler proves that Apple is serious about changing window handling without notice. When Apple gives us windowing hardware, programs like Blast will be next to impossible (but I’m gonna try it anyway! ).

The next one is more a matter of style, but could cause problems. I just assume that Blast will have plenty of memory to make the sound buffer and the hole regions. I wouldn’t recommend using Blast when you’ve got a bunch of unsaved data and can’t afford to crash with an out of memory error.

Credits, etc...

Thanks to Andrew and Darin for having the idea, and to Scott for planting the seed in my head. Speaking of seeds, TECHNOSTUD (a.k.a. Steve Knouse) helped out by showing Blast to anyone he could drag over to a Macintosh for two minutes. Steve is sort of like a reverse Johnny Appleseed. He goes around sowing MacHax™ programs on Apples everywhere. Thanks for all your support, Steve. And thanks to Dave Smith, who put me on a panel at the Boston MacWorld Expo. That’s where Blast made its public debut. To all the attendees of that panel, here is source code, only two months late.

I can be reached at any of the following:

3420D Sandra St.

Bryan, TX 77801

(409) 846-4102

AppleLink: D0635

MCIMail: Greg Marriott

BITNet: max@tamlsr

Fig. 2 LS Pascal Project Definition

UNIT BlastStuff;

{MPW and LS Pascal Version}

INTERFACE

{ For MPW, use the following USES statement}
 USES  {$LOAD fkeyblast.dump}
      MemTypes, QuickDraw, OSIntf, ToolIntf;

{ For LS Pascal, use the following USES statement}
 USES
 ROM85;

 PROCEDURE BlastIt;
 PROCEDURE Main; {not needed for MPW}

IMPLEMENTATION

PROCEDURE BlastIt;
 CONST
 buffSize = 122; 
 { sound takes 2, 20 triplets = 120 bytes }
 VAR
 holeRgn, circleRgn : RgnHandle;
 theEvent : EventRecord;
 stopIt : Boolean;
 whichWindow : WindowPtr;
 thisWindow : WindowPeek;
 i, dur, cnt, minSize:Integer; 
 pictWidth, thePart : Integer;
 blastPict : Pichandle;
 anotherRect, circleRect, tempRect : Rect;
 mouseSpot, holeSize, middlePoint : Point;
 wPort, oldPort, tempPort : GrafPtr;
 DeskPattern : ^Pattern;
 crossHairs, oldCursor : Cursor;
 TheCurs : ^Cursor;
 squareWavePtr : SWSynthPtr;
 amp : integer;

 BEGIN

    { let’s set up sounds... }
 squareWavePtr := SWSynthPtr(NewPtr(buffSize));
 squareWavePtr^.mode := swMode; { squarewave mode }
 cnt := 400;
 amp := 150;

    { 19 triplets, with decreasing pitch and volume }
 FOR i := 0 TO 18 DO
 WITH squareWavePtr^.triplets[i] DO
 BEGIN
 count := cnt;
 amplitude := amp;
 duration := 1;
 cnt := cnt + 60;
 amp := amp - 8;
 END;

 WITH squareWavePtr^.triplets[19] DO
 BEGIN
 count := 0;     { quit }
 amplitude := 0; { making }
 duration := 0;  { sounds }
 END;

{ let’s put up our cursor, saving the old one first...}
{ there is no ‘GetCursor’ call to complement }
{ ‘SetCursor’,}
{  so we have to dip into low memory and steal it }
 TheCurs := pointer($844);
 oldCursor := TheCurs^;

{ we need to put data into our cursor variable so we}
{ can do a ‘SetCursor’ call.  stuffing the data }
{ directly into low memory doesn’t work, because the }
{ cursor on the screen wouldn’t change until mouse }
{ was moved }
 StuffHex(ptr(@crossHairs), ’71C7408140810000');
 StuffHex(ptr(longint(@crossHairs) + 8), ‘049002A041C17777’);
 StuffHex(ptr(longint(@crossHairs) + 16), ’41C102A004900000');
 StuffHex(ptr(longint(@crossHairs) + 24), ‘4081408171C70000’);
 StuffHex(ptr(longint(@crossHairs) + 32), ’01C0208210840808');
 StuffHex(ptr(longint(@crossHairs) + 40), ’07F007F047F177F7');
 StuffHex(ptr(longint(@crossHairs) + 48), ’47F107F007F00808');
 StuffHex(ptr(longint(@crossHairs) + 56), ‘1084208201C00000’);
 StuffHex(ptr(longint(@crossHairs) + 64), ‘00070008’);
 SetCursor(crossHairs);

    { make the jaggy hole }
 holeRgn := NewRgn;
 OpenRgn;
 MoveTo(250, 180);
 LineTo(260, 226);
 LineTo(230, 252);
 LineTo(260, 242);
 LineTo(232, 278);
 LineTo(270, 242);
 LineTo(286, 304); 
 { basic hole design by Scott Boyd }
 LineTo(278, 234);
 LineTo(306, 242);
 LineTo(278, 244);
 LineTo(314, 196);
 LineTo(270, 216);
 LineTo(250, 180);
 CloseRgn(holeRgn);

{ “home” the region, prepare to add circle to }
{ the middle of the hole }
 WITH holeRgn^^.rgnBBox DO
 OffsetRgn(holeRgn, -left, -top);
 { calculate size ofhole and where the middle is }
 WITH holeRgn^^.rgnBBox DO
 BEGIN
 holeSize.h := right - left;
 holeSize.v := bottom - top;
 middlePoint.h := (right - left) DIV 2;
 middlePoint.v := (bottom - top) DIV 2;
 END;
    { figure out what size to make the circle }
 IF holeSize.h > holeSize.v THEN
 minSize := holeSize.h
 ELSE
 minSize := holeSize.v;

{ we’ll make the circle 40% of the small dimension;}
{ minSize will be the radius of the circle }
 minSize := minSize DIV 5;
 WITH middlePoint DO
 SetRect(circleRect, h - minSize, v - minSize, h + minSize, v + minSize);

    { make the circle }
 circleRgn := NewRgn;
 OpenRgn;
 FrameOval(circleRect);
 CloseRgn(circleRgn);
    { add the circle to the hole }
 UnionRgn(holeRgn, circleRgn, holeRgn);
    { we don’t need this any more... }
 DisposeRgn(circleRgn);
    { make the window manager port the current port }
 GetPort(oldPort);
 GetWMgrPort(wPort);
 SetPort(wPort);

{ ok, setup’s all finished... here’s the “main loop” }
stopIt := FALSE;
REPEAT
{ accept only mouseDown events }
IF GetNextEvent(mDownMask, theEvent) THEN
 BEGIN
 { figure out where they clicked }
 thePart := FindWindow(theEvent.where, whichWindow);
 { respond only if click on content area of window }
 IF (thePart = inContent) THEN
 BEGIN
 { Make some asynchrounous noise }
 StartSound(Ptr(squareWavePtr), buffSize, NIL);
 mouseSpot := theEvent.where;
 { position hole centered over the mouse spot }
 WITH holeRgn^^.rgnBBox DO
 OffsetRgn(holeRgn, -left, -top);
 OffsetRgn(holeRgn, mouseSpot.h - holeSize.h DIV 2, mouseSpot.v - holeSize.v 
DIV 2);
 ThisWindow := WindowPeek(whichWindow);
 { blast a hole in the structure region }
 DiffRgn(ThisWindow^.contRgn, holeRgn, ThisWindow^.contRgn);
 { blast a hole in the content region }
 DiffRgn(ThisWindow^.strucRgn, holeRgn, ThisWindow^.strucRgn);

 { calculate and paint new visible regions  }
 CalcVisBehind(WindowPeek(whichWindow), holeRgn);
 PaintBehind(windowPeek(whichWindow), holeRgn);

 {since ‘PaintBehind’ messes with the port.. }
 SetPort(wPort);
 END {IF ( thePart = inContent )... }
 ELSE
 { didn’t click in a window? }
 stopIt := TRUE;
 END; {IF GetNextEvent...}
UNTIL stopIt;
  { clean up the hole }
 DisposeRgn(holeRgn);
  {  fix the port  }
 SetPort(oldPort);
  { put the old cursor back }
 SetCursor(oldCursor);
  { get rid of the sound buffer }
 DisposPtr(Ptr(squareWavePtr));
END; {BlastIt}

 PROCEDURE Main; {Not needed for MPW}
 BEGIN
 BlastIt;
 END;

END.

Fig. 3 Creating a Code Resource in LS Pascal

Listing 2: MPW Make file for Blast

Fig. 4 Installing an FKEY in the System File

UNIT BlastStuff;

{MPW and LS Pascal Version}

INTERFACE

{ For MPW, use the following USES statement}
 USES  {$LOAD fkeyblast.dump}
      MemTypes, QuickDraw, OSIntf, ToolIntf;

{ For LS Pascal, use the following USES statement}
 USES
 ROM85;

 PROCEDURE BlastIt;
 PROCEDURE Main; {not needed for MPW}

IMPLEMENTATION

PROCEDURE BlastIt;
 CONST
 buffSize = 122; 
 { sound takes 2, 20 triplets = 120 bytes }
 VAR
 holeRgn, circleRgn : RgnHandle;
 theEvent : EventRecord;
 stopIt : Boolean;
 whichWindow : WindowPtr;
 thisWindow : WindowPeek;
 i, dur, cnt, minSize:Integer; 
 pictWidth, thePart : Integer;
 blastPict : Pichandle;
 anotherRect, circleRect, tempRect : Rect;
 mouseSpot, holeSize, middlePoint : Point;
 wPort, oldPort, tempPort : GrafPtr;
 DeskPattern : ^Pattern;
 crossHairs, oldCursor : Cursor;
 TheCurs : ^Cursor;
 squareWavePtr : SWSynthPtr;
 amp : integer;

 BEGIN

    { let’s set up sounds... }
 squareWavePtr := SWSynthPtr(NewPtr(buffSize));
 squareWavePtr^.mode := swMode; { squarewave mode }
 cnt := 400;
 amp := 150;

    { 19 triplets, with decreasing pitch and volume }
 FOR i := 0 TO 18 DO
 WITH squareWavePtr^.triplets[i] DO
 BEGIN
 count := cnt;
 amplitude := amp;
 duration := 1;
 cnt := cnt + 60;
 amp := amp - 8;
 END;

 WITH squareWavePtr^.triplets[19] DO
 BEGIN
 count := 0;     { quit }
 amplitude := 0; { making }
 duration := 0;  { sounds }
 END;

{ let’s put up our cursor, saving the old one first...}
{ there is no ‘GetCursor’ call to complement }
{ ‘SetCursor’,}
{  so we have to dip into low memory and steal it }
 TheCurs := pointer($844);
 oldCursor := TheCurs^;

{ we need to put data into our cursor variable so we}
{ can do a ‘SetCursor’ call.  stuffing the data }
{ directly into low memory doesn’t work, because the }
{ cursor on the screen wouldn’t change until mouse }
{ was moved }
 StuffHex(ptr(@crossHairs), ’71C7408140810000');
 StuffHex(ptr(longint(@crossHairs) + 8), ‘049002A041C17777’);
 StuffHex(ptr(longint(@crossHairs) + 16), ’41C102A004900000');
 StuffHex(ptr(longint(@crossHairs) + 24), ‘4081408171C70000’);
 StuffHex(ptr(longint(@crossHairs) + 32), ’01C0208210840808');
 StuffHex(ptr(longint(@crossHairs) + 40), ’07F007F047F177F7');
 StuffHex(ptr(longint(@crossHairs) + 48), ’47F107F007F00808');
 StuffHex(ptr(longint(@crossHairs) + 56), ‘1084208201C00000’);
 StuffHex(ptr(longint(@crossHairs) + 64), ‘00070008’);
 SetCursor(crossHairs);

    { make the jaggy hole }
 holeRgn := NewRgn;
 OpenRgn;
 MoveTo(250, 180);
 LineTo(260, 226);
 LineTo(230, 252);
 LineTo(260, 242);
 LineTo(232, 278);
 LineTo(270, 242);
 LineTo(286, 304); 
 { basic hole design by Scott Boyd }
 LineTo(278, 234);
 LineTo(306, 242);
 LineTo(278, 244);
 LineTo(314, 196);
 LineTo(270, 216);
 LineTo(250, 180);
 CloseRgn(holeRgn);

{ “home” the region, prepare to add circle to }
{ the middle of the hole }
 WITH holeRgn^^.rgnBBox DO
 OffsetRgn(holeRgn, -left, -top);
 { calculate size ofhole and where the middle is }
 WITH holeRgn^^.rgnBBox DO
 BEGIN
 holeSize.h := right - left;
 holeSize.v := bottom - top;
 middlePoint.h := (right - left) DIV 2;
 middlePoint.v := (bottom - top) DIV 2;
 END;
    { figure out what size to make the circle }
 IF holeSize.h > holeSize.v THEN
 minSize := holeSize.h
 ELSE
 minSize := holeSize.v;

{ we’ll make the circle 40% of the small dimension;}
{ minSize will be the radius of the circle }
 minSize := minSize DIV 5;
 WITH middlePoint DO
 SetRect(circleRect, h - minSize, v - minSize, h + minSize, v + minSize);

    { make the circle }
 circleRgn := NewRgn;
 OpenRgn;
 FrameOval(circleRect);
 CloseRgn(circleRgn);
    { add the circle to the hole }
 UnionRgn(holeRgn, circleRgn, holeRgn);
    { we don’t need this any more... }
 DisposeRgn(circleRgn);
    { make the window manager port the current port }
 GetPort(oldPort);
 GetWMgrPort(wPort);
 SetPort(wPort);

{ ok, setup’s all finished... here’s the “main loop” }
stopIt := FALSE;
REPEAT
{ accept only mouseDown events }
IF GetNextEvent(mDownMask, theEvent) THEN
 BEGIN
 { figure out where they clicked }
 thePart := FindWindow(theEvent.where, whichWindow);
 { respond only if click on content area of window }
 IF (thePart = inContent) THEN
 BEGIN
 { Make some asynchrounous noise }
 StartSound(Ptr(squareWavePtr), buffSize, NIL);
 mouseSpot := theEvent.where;
 { position hole centered over the mouse spot }
 WITH holeRgn^^.rgnBBox DO
 OffsetRgn(holeRgn, -left, -top);
 OffsetRgn(holeRgn, mouseSpot.h - holeSize.h DIV 2, mouseSpot.v - holeSize.v 
DIV 2);
 ThisWindow := WindowPeek(whichWindow);
 { blast a hole in the structure region }
 DiffRgn(ThisWindow^.contRgn, holeRgn, ThisWindow^.contRgn);
 { blast a hole in the content region }
 DiffRgn(ThisWindow^.strucRgn, holeRgn, ThisWindow^.strucRgn);

 { calculate and paint new visible regions  }
 CalcVisBehind(WindowPeek(whichWindow), holeRgn);
 PaintBehind(windowPeek(whichWindow), holeRgn);

 {since ‘PaintBehind’ messes with the port.. }
 SetPort(wPort);
 END {IF ( thePart = inContent )... }
 ELSE
 { didn’t click in a window? }
 stopIt := TRUE;
 END; {IF GetNextEvent...}
UNTIL stopIt;
  { clean up the hole }
 DisposeRgn(holeRgn);
  {  fix the port  }
 SetPort(oldPort);
  { put the old cursor back }
 SetCursor(oldCursor);
  { get rid of the sound buffer }
 DisposPtr(Ptr(squareWavePtr));
END; {BlastIt}

 PROCEDURE Main; {Not needed for MPW}
 BEGIN
 BlastIt;
 END;

END.
 
AAPL
$500.72
Apple Inc.
+2.04
MSFT
$34.67
Microsoft Corpora
+0.18
GOOG
$894.72
Google Inc.
+12.71

MacTech Search:
Community Search:

Software Updates via MacUpdate

Apple HP Printer Drivers 2.16.1 - For OS...
Apple HP Printer Drivers includes the latest HP printing and scanning software for Mac OS X 10.6, 10.7 and 10.8. For information about supported printer models, see this page.Version 2.16.1: This... Read more
Yep 3.5.1 - Organize and manage all your...
Yep is a document organization and management tool. Like iTunes for music or iPhoto for photos, Yep lets you search and view your documents in a comfortable interface, while offering the ability to... Read more
Apple Canon Laser Printer Drivers 2.11 -...
Apple Canon Laser Printer Drivers is the latest Canon Laser printing and scanning software for Mac OS X 10.6, 10.7 and 10.8. For information about supported printer models, see this page.Version 2.11... Read more
Apple Java for Mac OS X 10.6 Update 17 -...
Apple Java for Mac OS X 10.6 delivers improved security, reliability, and compatibility by updating Java SE 6.Version Update 17: Java for Mac OS X 10.6 Update 17 delivers improved security,... Read more
Arq 3.3 - Online backup (requires Amazon...
Arq is online backup for the Mac using Amazon S3 and Amazon Glacier. It backs-up and faithfully restores all the special metadata of Mac files that other products don't, including resource forks,... Read more
Apple Java 2013-005 - For OS X 10.7 and...
Apple Java for OS X 2013-005 delivers improved security, reliability, and compatibility by updating Java SE 6 to 1.6.0_65. On systems that have not already installed Java for OS X 2012-006, this... Read more
DEVONthink Pro 2.7 - Knowledge base, inf...
Save 10% with our exclusive coupon code: MACUPDATE10 DEVONthink Pro is your essential assistant for today's world, where almost everything is digital. From shopping receipts to important research... Read more
VirtualBox 4.3.0 - x86 virtualization so...
VirtualBox is a family of powerful x86 virtualization products for enterprise as well as home use. Not only is VirtualBox an extremely feature rich, high performance product for enterprise customers... Read more
Merlin 2.9.2 - Project management softwa...
Merlin is the only native network-based collaborative Project Management solution for Mac OS X. This version offers many features propelling Merlin to the top of Mac OS X professional project... Read more
Eye Candy 7.1.0.1191 - 30 professional P...
Eye Candy renders realistic effects that are difficult or impossible to achieve in Photoshop alone, such as Fire, Chrome, and the new Lightning. Effects like Animal Fur, Smoke, and Reptile Skin are... Read more

Sorcery! Enhances the Gameplay in Latest...
Sorcery! | Read more »
PROVERBidioms Paints English Sayings in...
PROVERBidioms Paints English Sayings in a Picture for Users to Find Posted by Andrew Stevens on October 16th, 2013 [ permalink ] | Read more »
OmniFocus 2 for iPhone Review
OmniFocus 2 for iPhone Review By Carter Dotson on October 16th, 2013 Our Rating: :: OMNIPOTENTiPhone App - Designed for the iPhone, compatible with the iPad OmniFocus 2 for iPhone is a task management app for people who absolutely... | Read more »
Ingress – Google’s Augmented-Reality Gam...
Ingress – Google’s Augmented-Reality Game to Make its Way to iOS Next Year Posted by Andrew Stevens on October 16th, 2013 [ permalink ] | Read more »
CSR Classics is Full of Ridiculously Pre...
CSR Classics is Full of Ridiculously Pretty Classic Automobiles Posted by Rob Rich on October 16th, 2013 [ permalink ] | Read more »
Costume Quest Review
Costume Quest Review By Blake Grundman on October 16th, 2013 Our Rating: :: SLIGHTLY SOURUniversal App - Designed for iPhone and iPad This bite sized snack lacks the staying power to appeal beyond the haunting season.   | Read more »
Artomaton – The AI Painter is an Artific...
Artomaton – The AI Painter is an Artificial Artistic Intelligence That Paints From Photos You’ve Taken Posted by Andrew Stevens on October 16th, 2013 [ | Read more »
Hills of Glory 3D Review
Hills of Glory 3D Review By Carter Dotson on October 16th, 2013 Our Rating: :: BREACHED DEFENSEUniversal App - Designed for iPhone and iPad Hills of Glory 3D is the most aggravating kind of game: one with good ideas but sloppy... | Read more »
FitStar: Tony Gonzalez Adds New 7 Minute...
FitStar: Tony Gonzalez Adds New 7 Minute Workout Program for Those Who Are in a Hurry Posted by Andrew Stevens on October 16th, 2013 [ permalink ] | Read more »
PUMATRAC Review
PUMATRAC Review By Angela LaFollette on October 16th, 2013 Our Rating: :: INSIGHTFULiPhone App - Designed for the iPhone, compatible with the iPad PUMATRAC not only provides runners with stats, it also motivates them with insights... | Read more »

Price Scanner via MacPrices.net

Updated MacBook Price Trackers
We’ve updated our MacBook Price Trackers with the latest information on prices, bundles, and availability on MacBook Airs, MacBook Pros, and the MacBook Pros with Retina Displays from Apple’s... Read more
13-inch Retina MacBook Pros on sale for up to...
B&H Photo has the 13″ 2.5GHz Retina MacBook Pro on sale for $1399 including free shipping. Their price is $100 off MSRP. They have the 13″ 2.6GHz Retina MacBook Pro on sale for $1580 which is $... Read more
AppleCare Protection Plans on sale for up to...
B&H Photo has 3-Year AppleCare Warranties on sale for up to $105 off MSRP including free shipping plus NY sales tax only: - Mac Laptops 15″ and Above: $244 $105 off MSRP - Mac Laptops 13″ and... Read more
Apple’s 64-bit A7 Processor: One Step Closer...
PC Pro’s Darien Graham-Smith reported that Canonical founder and Ubuntu Linux creator Mark Shuttleworth believes Apple intends to follow Ubuntu’s lead and merge its desktop and mobile operating... Read more
MacBook Pro First, Followed By iPad At The En...
French site Info MacG’s Florian Innocente says he has received availability dates and order of arrival for the next MacBook Pro and the iPad from the same contact who had warned hom of the arrival of... Read more
Chart: iPad Value Decline From NextWorth
With every announcement of a new Apple device, serial upgraders begin selling off their previous models – driving down the resale value. So, with the Oct. 22 Apple announcement date approaching,... Read more
SOASTA Survey: What App Do You Check First in...
SOASTA Inc., the leader in cloud and mobile testing announced the results of its recent survey showing which mobile apps are popular with smartphone owners in major American markets. SOASTA’s survey... Read more
Apple, Samsung Reportedly Both Developing 12-...
Digitimes’ Aaron Lee and Joseph Tsai report that Apple and Samsung Electronics are said to both be planning to release 12-inch tablets, and that Apple is currently cooperating with Quanta Computer on... Read more
Apple’s 2011 MacBook Pro Lineup Suffering Fro...
Appleinsider’s Shane Cole says that owners of early-2011 15-inch and 17-inch MacBook Pros are reporting issues with those models’ discrete AMD graphics processors, which in some cases results in the... Read more
Global Notebook Shipments To Grow Less Than 3...
Digitimes Research’s Joanne Chien reports that Taiwan’s notebook shipments grew only 2.5% sequentially, and dropped 8.6% year-over-year in the third quarter despite the fact that notebook ODMs have... Read more

Jobs Board

Senior Mac / *Apple* Systems Engineer - 318...
318 Inc, a top provider of Apple solutions is seeking a new Senior Apple Systems Engineer to be based out of our Santa Monica, California location. We are a Read more
*Apple* Retail - Manager - Apple Inc. (Unite...
Job Summary Keeping an Apple Store thriving requires a diverse set of leadership skills, and as a Manager, you’re a master of them all. In the store’s fast-paced, Read more
*Apple* Solutions Consultant - Apple (United...
**Job Summary** Apple Solutions Consultant (ASC) - Retail Representatives Apple Solutions Consultants are trained by Apple on selling Apple -branded products Read more
Associate *Apple* Solutions Consultant - Ap...
**Job Summary** The Associate ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The Associate ASC's role is to 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
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.