TweetFollow Us on Twitter

Screen Dump
Volume Number:4
Issue Number:2
Column Tag:Macintosh II

Screen Dump FKEY for Color Picts

By Steven C. Sheets, Chicago, IL

In our first article, we saw how to create a plot in PICT format, complete with the old style Quickdraw color. But, since our program did not include an open command, how can we view the plot in color once it is made? If we try to snapshot the color screen, we get a beep! What we need is a way to snapshot and view our plot without having to turn off the color. Steve Sheets, from Apple’s Chicago technical support office, shows us how to capture the screen on a Mac II with the color enabled.And best of all, the picture is not rotated! Once we capture our plot, we want to view it. Steve again comes to our rescue with a companion viewer DA for color PICTs.

Color Images: Saving and Loading

Since this column has given some examples of how to draw in Color on the Mac //, now would be a good time to describe how to save and load color pictures. While a specific file format can always be defined for an application, it is convenient to be able to read generic file formats, so that various applications can share and port data. When discussing graphics, the two generic file formats have always been MacPaint file format and PICT file format. MacPaint format has always been considered the generic Bitmap method of saving Mac graphics, while PICT format is the associated with object oriented graphics programs (ie. MacDraw).

With the introduction of Color Quickdraw and the Mac //, things have changed slightly. Unfortunately MacPaint file format can not be expanded to cover PixMap graphics (ie. multiple colors per pixel). Nor is there any other PixMap file format that has been widely accepted by developers (though there is a need). On the other hand, PICT file format is nothing but an extension of a Quickdraw Picture Handle. With the introduction of the Mac //, Quickdraw Pictures have been expanded to support color. This article will talk about the new Color Quickdraw Picture format, the PICT file format, and will touch briefly on using the Palette Manager to display a Picture in the Color needed. The example sources, ColorImage DA and ColorImage FKEY, will demonstrate how to save and read PICT file.

Quickdraw Picture Format

A Quickdraw Picture is a data structure that contains a sequence of Quickdraw commands. To create a Picture, a program defines a Picture Frame (ie, a rectangle and data structure) with the OpenPicture function. OpenPicture returns a handle to the Picture data structure being created. At this point, the program can call any Quickdraw command. Instead of being drawn on the current grafport, the command is stored in the Picture for later use. A ClosePicture command needs to be issued to tell Quickdraw to stop saving the commands into the Picture Handle. Once the program has a Picture, it can display it using the DrawPicture call. This will draw the Picture (ie. all the Quickdraw commands saved in the Picture) into a destination rectangle. If the destination rectangle is not the same size as the picture frame, the picture will be expanded or reduced to fit the destination rectangle. The Plotter program in this issue illustrates this traditional use of the Quickdraw picture.

The Picture handle points to a data structure which contains the Picture Size (Integer picSize), the Picture Frame (Rect picFrame) and various Opcodes describing the Quickdraw calls. Always ignore picSize. With the expansion of the Memory Manager so that it can handle sizes beyond 32K, picSize is now ignored by Quickdraw. Instead, the picture is played out until the end. If the Picture size is needed, call GetHandleSize. Generally beyond picSize and picFrame, a program should not read the data structures directly. The internal structures beyond this point are documented in Inside Macintosh, Vol 5 and the various tech notes cited in the Pascal column.

An image stored and drawn as a Picture (using DrawPicture) is much more compressed than the same image drawn using individual Quickdraw commands in the code. Also the program can pass a Picture through the clipboard and Scrapbook to other Applications. Notice while the Picture is considered an Object Graphic type of data structure, one of the commands it stores is CopyBits. A Picture can thus have BitMapped graphics in it.

Version 1 vs Version 2 Format

With the introduction of the Mac //, the Picture Format has been extended. The old Picture format (called Version 1 Format) contains only the non-Color Quickdraw commands. The newer Picture format (called Version 2 Format) contains all the Color Quickdraw commands. On a Mac //, which Format is created with an OpenPicture call depends on the current GrafPort. If an OpenPicture call is made when the current GrafPort is a Color GrafPort, the Picture created is a Version 2 format. If a call is made on a normal GrafPort, a Version 1 Picture is created. Obviously non-Mac // computers can not create a Version 2 Picture. However, due to a patch in System 4.1 and later, an Enhanced Mac 512K, a MacPlus or a Mac SE can display a Version 2 Picture (not in color, of course).

While checking the Opcodes (Quickdraw picture commands) directly is not a good idea, a program can identify which version of Picture it has by checking the first integer past the picSize and picFrame. If this integer is 4353 ($1101), the Picture is Version 1. If the integer is 17 ($0011), the Picture is Version 2.

Just as a Version 1 Picture can have bitmap graphics in it, a Version 2 Picture can have a PixMap in it. Any CopyBits calls made following an OpenPicture, but before a ClosePicture call, will store the data into the Picture. If the source was a PixMap instead of a BitMap, the Picture handle will have both the bit data (compressed format) and a color table (Color Look Up Table or CLUT) describing the colors used in the PixMap.

PICT File Format

Knowing the Picture format, the PICT File Format is simple. A PICT file (ie. one that has the Filetype ‘PICT’) consists of a data fork with a 512 byte header followed by a picture data structure. The header is usually specific to the application that made it (most programs ignore it). After the header, the picture data contains picSize, picFrame and then the variable length Opcodes. As stated above, do not use picSize to determine how much data follows. Instead, check the size of the file with a File I/O call. Subtract 512 and that should be the size of the handle that the data should be read into.

ColorImage FKEY Code

The ColorImage FKEY was designed to save the current screen to file, similar to the Screen Save FKEY (Command-Shift-3). Instead of a MacPaint file being created, a PICT file is created instead. A CopyBits call on the current screen is used when creating the picture handle, which is then saved to the file.

The FKEY will work on any Macintosh. If the Macintosh has Color Quickdraw (ie. Macintosh //), the Color Window Manager GrafPort is temporarily set before creating the picture handle. Thus a version 2 PICT file will be created and any color images on the screen will be saved. On a non-Color Quickdraw Macintosh (ie. Mac SE and before), the normal Window Manager Port is used and a version 1 PICT file is created. If the Caps Lock key is pressed, the entire screen is saved to a file. If the Caps Lock key is not pressed and a front window exists, only the current window is saved to a file. The picture is not saved to a set file name like the Screen Save FKEY, instead the user is prompted for the file name. The image is also not rotated on a Mac II monitor. Thus you won’t need to edit your screen dumps before using them in your documentation, nor will you need to turn off your color interface as is the case with the old style shift-cmd-3.

Remember, if the Screen was a PixMap instead of a Bitmap, the CLUT will be saved into the PICT file along with the compressed bit data. Color PICTs are amazingly packed files.

Palette Manager

Reading a PICT file, however, is only half the job of displaying a color image correctly. If the Picture contained Color Quickdraw commands (for example, a Color Window saved with ColorImage FKEY), the user will want to see the Picture drawn again using the original colors. For this, the Palette Manager needs to be used.

The Palette Manager establishes the color environment of the Mac //. It uses the Color Manager (which controls what colors are used) to select the best colors for a given display. The idea is that each window can have a Color Palette associated with it. These are the Colors that the window wants the screen to be showing, in order to view the window at it’s best. Unless there are to many windows needing to many colors, each window gets it’s Palette. If there are not enough colors, highest priority goes to the top most window. Every time the top most window changes (and it has an associated Palette), the colors may change to give the new window it’s best appearance. The Palette Manager will then issue an update event for all Palette windows so that they can be redrawn to their best appearance in the new colors.

While an Application could use the Color Manager directly and bypass the Palette Manager, this is not recommended. Such programming would fall apart in a color Multiple task environment. Remember, Multifinder is not the only such environment. There are also color DAs like ColorImage.

Thus the DA takes the Picture (if it is Version 2), searches for a CLUT, and tries to create a Color Palette from it. The program does all this by temporarily replacing the low-level quickdraw procs (specifically StdBits) with one that checks for a PixMap, then transfers the RGB colors into a temporary buffer. The low-level routines are replaced and the buffer is converted to a Color Palette. Then the Palette is attached to the window so every time that particular window becomes the top most, the screen colors are set to the Palette. This also causes an update of the window so the Picture can be shown in it’s best colors.

ColorImage DA Code

The ColorImage Desk Accessory contains the complementing code to Color FKEY, and more. The DA creates a window (Color Window if the CPU has Color Quickdraw) to display Pictures in. The user can then select a PICT file and have it read into a Picture handle. Since a user may want to know what colors are being used for a specific Picture, the DA allows the users to switch between looking at the Picture or the current Palette.

Think of two ColorImage DA’s that are loaded into the system. Each opens a Picture with a radically different CLUT (one is a 256 color RGB Picture while the other is a 256 shade Gray Scaled one). When the RGB Picture is clicked on, it becomes the front window. The Palette Manager sets the 256 RGB colors (assuming the Color Video Card has 8 Bits per Pixel). Both pictures are completely redrawn using the current screen colors. Notice the Palette Manager caused the update; the program does not have to keep track. The RGB Picture appears perfect, while the Gray Picture (which can be seen behind the front window) appears as best as it can using the current screen colors. Then the user wants to look at the Gray Picture. He clicks on that window. It becomes front window, and the Palette Manager sets the current screen to 256 shades of gray. The windows are redrawn. The Gray Picture appears perfectly, while the RGB one appears as best it can using these new gray tones.

Last Comments

The ColorImage FKEY and Desk Accessory were created with LightSpeed Pascal (LSP). Macintosh Programming Workshop (MPW) has it’s points. It is an extremely powerful development system perfect for large projects. Being from Apple, MPW is the first development system that has any new Trap Listings or new code interfaces. LSP only recently has released the Mac // libraries and interfaces. MPW is also the best Object Pascal system around. However LSP may be the best environment to develop code segments (ie. DA, FKEYs, Window or Control Panel Definition Procedures) for the Macintosh. Both code examples were tested from inside a test program (a simple program that called the FKEY and a modified version of LSP DAShell). This decreases development time since the various codes could be tested without having to insert the DA or FKEY into the System file. The code could even be stepped through one line at a time, perhaps the best feature of LSP!

This program requires the Palette manager. When LS Pascal version 1.11 was released in September, Think did not include the Palette manager, nor the MultiFinder routines. We are still waiting for both Think and Borland to upgrade their products to MPW version 2.0 interfaces. You can add the Palette manager by taking the MPW 2.0 interface and adding it to your project. Remove the USES MemTypes and replace with USES ColorQuickdraw instead. Then add “Implementation” to the end of the file and your in business.

ColorImage DA could be expanded to check not only the PixMap’s CLUT in a Picture, but could check other Color Quickdraw commands. Since the DA was designed to work with the FKEY, checking the CLUT is all that is needed to function. The program could also check for colors that are in the CLUT, but are NOT present in the PixMap. Such colors are not displayed and need not be in the Palette.

Yet to come a full blown explanation of the Palette Manager and Palette Animation!

{ ColorImage DA / FKEY by Steve Sheets 12/87 }
{ Saves the current Screen to a PICT file.  If Cap Lock }
{is down, saves theentire screen.  If the key is not & a}
{ Window exists, saves the window.}

UNIT UColorImageFKEY;

INTERFACE

 PROCEDURE main;

IMPLEMENTATION

{Returns the Color Window Manager Port.  }
 PROCEDURE CGetWMgrPort (VAR CWPort : GrafPtr);
 INLINE
 $AA48;

{Does this CPU have color Quickdraw? }
 FUNCTION ColorQDExists : boolean;
 CONST
 ROM85Loc = $28E;
 TwoHighMask = $C000;
 TYPE
 WordPtr = ^INTEGER;
 VAR
 Wd : WordPtr;
 BEGIN
 Wd := POINTER(ROM85Loc);
 ColorQDExists := (BitAnd(Wd^, TwoHighMask) = 0);
 END;

{Is Cap Lock key down?  }
 FUNCTION CapLockDown : BOOLEAN;
 VAR
 theMap : KeyMap;
 BEGIN
 GetKeys(theMap);
 CapLockDown := BitTst(@theMap[1], 30);
 END;

{Given a flag saying color Quickdraw exists, returns} 
{the Handle of a Picture and a flag saying if the window } 
{was saved or if the entire screen was.}
 PROCEDURE GetPic (VAR thePic : PicHandle;
 VAR IsWindow : BOOLEAN;
 QDExists : BOOLEAN);
 TYPE
 BitMapPtr = ^BitMap;
 BitMapHdl = ^BitMapPtr;
 VAR
 sorcRect, destRect, mapRect : Rect;
 OldPort, WPort : GrafPtr;
 clip, vis : RgnHandle;
 FWin : WindowPtr;
 PixH : BitMapHdl;
 tempMap : BitMap;
 BEGIN
 GetPort(OldPort);

{ If Color Quickdraw exists, use the Color Window Manager 
{ PixMap. Else use the normal Window Manager BitMap. }
 IF QDExists THEN
 BEGIN
 CGetWMgrPort(WPort);
 PixH := BitMapHdl(WPort^.portBits.baseAddr);
 mapRect := PixH^^.bounds;
 END
 ELSE
 BEGIN
 GetWMgrPort(WPort);
 mapRect := WPort^.portBits.bounds;
 END;

{Chose to save the Window or entire Screen.  }
 FWin := FrontWindow;
 IsWindow := (NOT CapLockDown) AND (FWin <> NIL);
 IF IsWindow THEN
 BEGIN
 SetPort(FWin);
 sorcRect := FWin^.portRect;
 LocalToGlobal(sorcRect.topLeft);
 LocalToGlobal(sorcRect.botRight);
 OffSetRect(sorcRect, mapRect.left, mapRect.top);
 END
 ELSE
 sorcRect := mapRect;
 destRect.left := 0;
 destRect.right := sorcRect.right - sorcRect.left;
 destRect.top := 0;
 destRect.bottom := sorcRect.bottom - sorcRect.top;

{Resize the regions so they do not get in the way. }
 SetPort(WPort);
 vis := WPort^.visRgn;
 clip := WPort^.clipRgn;
 WPort^.visRgn := NewRgn;
 WPort^.clipRgn := NewRgn;
 SetRectRgn(WPort^.visRgn, -30000, -30000, 30000, 30000);
 SetRectRgn(WPort^.clipRgn, -30000, -30000, 30000, 30000);

{Create Picture, copy map to it and close the Picture. }
 thePic := OpenPicture(destRect);
 CopyBits(WPort^.portBits, WPort^.portBits, sorcRect, destRect, srcCopy, 
NIL);
 ClosePicture;

{Reset the Regions and Port.}
 DisposeRgn(WPort^.visRgn);
 DisposeRgn(WPort^.clipRgn);
 WPort^.visRgn := vis;
 WPort^.clipRgn := clip;

 SetPort(OldPort);
 END;

{Pick a PICT file to save the Picture into (with correct title line).
 }
 PROCEDURE PickFile (VAR theReply : SFReply;
 IsWindow : BOOLEAN;
 QDExists : BOOLEAN);
 VAR
 Pt : Point;
 S1, S2 : str255;
 BEGIN
 Pt.v := 60;
 Pt.h := 60;
 IF QDExists THEN
 S1 := ‘Save Color ‘
 ELSE
 S1 := ‘Save ‘;
 IF IsWindow THEN
 S2 := ‘Window PICT:’
 ELSE
 S2 := ‘Screen PICT:’;
 SFPutFile(Pt, CONCAT(S1, S2), ‘’, NIL, theReply);
 END;

{Given a Picture handle and a reference to a file, create a PICT file 
and save the Picture into it. }
 PROCEDURE SaveColorImage (thePic : PicHandle;
 theReply : SFReply);
 TYPE
 BufType = PACKED ARRAY[1..128] OF LongInt;
 VAR
 theErr : OSErr;
 OK : BOOLEAN;
 FileRef : INTEGER;
 BufSize : LongInt;
 Buf : BufType;
 count : integer;
 BEGIN
 OK := FALSE;
 FileRef := 0;
 theErr := FSDelete(theReply.fname, theReply.vRefNum);
 IF (theErr = noErr) OR (theErr = fnfErr) THEN
 BEGIN
 theErr := Create(theReply.fname, theReply.vRefNum, ‘MDRW’, ‘PICT’);
 IF (theErr = noErr) THEN
 BEGIN
 theErr := FSOpen(theReply.fname, theReply.vRefNum, FileRef);
 IF (theErr = noErr) THEN
 BEGIN
 FOR count := 1 TO 128 DO
 Buf[count] := 0;
 BufSize := 512;
 theErr := FSWrite(FileRef, BufSize, @Buf);
 IF (theErr = noErr) THEN
 BEGIN
 BufSize := GetHandleSize(Handle(thePic));
 HLock(Handle(thePic));
 theErr := FSWrite(FileRef, BufSize, Ptr(thePic^));
 HUnLock(Handle(thePic));
 IF (theErr = noErr) THEN
 BEGIN
 theErr := FSClose(FileRef);
 FileRef := 0;
 IF (theErr = noErr) THEN
 BEGIN
 theErr := FlushVol(NIL, theReply.vRefNum);
 OK := TRUE;
 END;
 END;
 END;
 END;
 END;
 END;
 IF NOT OK THEN
 SysBeep(60);
 IF (FileRef <> 0) THEN
 theErr := FSClose(FileRef);
 END;

{Main FKEY routine:  Check if this CPU has Color Quickdraw}
{(used by all routines).  Create the Picture Handle and Pick} 
{ a File.  If successful, savethe Picture into the file and}
{ kill the picture.}
 PROCEDURE main;
 VAR
 thePic : PicHandle;
 theReply : SFReply;
 IsWindow : BOOLEAN;
 QDExist : BOOLEAN;
 BEGIN
 QDExist := ColorQDExists;
 GetPic(thePic, IsWindow, QDExist);
 PickFile(theReply, IsWindow, QDExist);
 IF theReply.good THEN
 SaveColorImage(thePic, theReply);
 KillPicture(thePic);
 END;
END.

{ColorImage DA by Steve Sheets 12/87 }

{Displays a PICT file.  Checks if the PICT has a Color}
{ PixMap. If so, use the Palette Manager to display the PICT} 
{ in the correct colors.  }

UNIT xColorImageDA;

INTERFACE

 USES
 ColorQuickDraw, PaletteMgr, ColorWindowMgr;

 FUNCTION Main (theDCE : DCtlPtr;
 IOPB : ParmBlkPtr;
 driveCall : Integer) : OSErr;

IMPLEMENTATION

 CONST
 DriverOpen = 0;
 DriverPrime = 1;
 DriverControl = 2;
 DriverStatus = 3;
 DriverClose = 4;

 MaxPal = 512;

 dCtlEnable = 10;

 kNum = 16;
 kBox = 20;
 kHst = 30;
 kVst = 40;
 kVoff = 40;

 kAbout = 1;
 kLoadPic = 3;
 kShowPic = 5;
 kShowPal = 6;

 TYPE
 BufType = RECORD
 Counter : integer;
 CLUTnum : longint;
 B : ARRAY[1..MaxPal] OF RGBColor;
 END;
 BufPtr = ^BufType;
 BufHdl = ^BufPtr;

 imageData = RECORD
 imagePic : PicHandle;
 imagePal : PaletteHandle;
 imageID : integer;
 imageWindow : WindowPtr;
 imageMenu : MenuHandle;
 picRect, palRect : Rect;
 ColorFlag, ShowPicFlag : boolean;
 numPal : integer;
 noPicstr, nameStr : str255;
 END;
 imagePtr = ^imageData;
 imageHandle = ^imagePtr;

 MyCSpecArray = ARRAY[0..MaxPal] OF ColorSpec;

 MyCTabHandle = ^MyCTabPtr;
 MyCTabPtr = ^MyColorTable;
 MyColorTable = RECORD
 ctSeed : LONGINT;
 transIndex : INTEGER;
 ctSize : INTEGER;
 ctTable : MyCSpecArray;
 END;

{Resize the window W to the size R.  Updates the entire}
{ window (window must be the current Grafport).    }
 PROCEDURE ReSize (W : WindowPtr;
 R : rect);
 BEGIN
 SizeWindow(W, R.right, R.bottom, false);
 InvalRect(R)
 END;

{Low level Quickdraw Proc.  Instead of drawing a} {Bitmap/Pixmap, grabs 
the Color Lookup Table, and passes}
{the RGB colors into the   buffer (stored in the Window}
{Ref Con). }
 PROCEDURE BitInfo (VAR srcBits : PixMap;
 VAR srcRect, dstRect : Rect;
 mode : integer;
 maskRgn : RgnHandle);
 VAR
 tempW : WindowPtr;
 theBuf : BufHdl;
 tempC : MyCTabHandle;
 n, count : integer;
 BEGIN
 GetPort(tempW);
 theBuf := POINTER(GetWRefCon(tempW));
 { Make sure it is a PixMap.}
 IF (srcBits.rowBytes < 0) THEN
 BEGIN
 tempC := POINTER(srcBits.pmTable);
 { Make sure this is a new CLUT.  }
 IF (tempC^^.ctSeed <> theBuf^^.CLUTnum) THEN
 BEGIN
 { Cycle through all colors, stuffing into Buf.}
 theBuf^^.CLUTnum := tempC^^.ctSeed;
 n := theBuf^^.Counter;
 IF tempC^^.ctSize >= 0 THEN
 FOR count := 0 TO tempC^^.ctSize DO
 BEGIN
 IF n < MaxPal THEN
 BEGIN
 n := n + 1;
 theBuf^^.B[n] := tempC^^.ctTable[count].rgb;
 END;
 END;
 theBuf^^.Counter := n;
 END;
 END;
 END;

{Given a window and a Picture Handle, return a}
{ Palette Handle and Palette number of the colors used} 
{ in the Picture Handle.  }
 FUNCTION GetPal (theW : WindowPtr;
 thePic : PicHandle;
 VAR thePal : PaletteHandle;
 VAR theNum : integer) : boolean;
 TYPE
 myPicHdl = ^myPicPtr;
 myPicPtr = ^myPicData;
 myPicData = RECORD
 P : Picture;
 ID   : integer;
 END;
 VAR
 count : integer;
 theBuf : BufHdl;
 tempPtr : myPicHdl;
 tempProc : CQDProcs;
 oldProc : QDProcsPtr;
 oldRef : longint;
 dummy : boolean;
 tempP : GrafPtr;
 BEGIN
 dummy := false;
 { If this is a Handle, }
 IF thePic <> NIL THEN
 BEGIN
 { And if it is a color Picture. }
 tempPtr := POINTER(thePic);
 IF tempPtr^^.ID = $0011 THEN
 BEGIN
 { Create the Buffer.}
 theBuf := POINTER(NewHandle(SizeOf(BufType)));
 IF (theBuf <> NIL) THEN
 BEGIN
 { Clear Buffers counters.}
 theBuf^^.Counter := 0;
 theBuf^^.CLUTnum := -1;

{Save the old Window RefCon, and stuff the Buffer into the RefCon.
 }
 oldRef := GetWRefCon(theW);
 SetWRefCon(theW, ord4(theBuf));
{Save the old low level QD Procs, create new ones (including BitInfo).
 }
 oldProc := POINTER(theW^.grafProcs);
 SetStdCProcs(tempProc);
 tempProc.bitsProc := @BitInfo;
 theW^.grafProcs := @tempProc;

{Draw the Picture (grabing the CLUT and RGB Colors).  }
 GetPort(tempP);
 SetPort(theW);
 DrawPicture(thePic, thePic^^.picFrame);
 SetPort(tempP);

 theW^.grafProcs := POINTER(oldProc);
 SetWRefCon(theW, oldRef);

{If there were any colors, create a Color Palette.}
 IF theBuf^^.Counter > 0 THEN
 BEGIN
 thePal := NewPalette(theBuf^^.Counter, NIL, pmTolerant, 0);
 IF thePal <> NIL THEN
 BEGIN
 dummy := true;
 theNum := theBuf^^.Counter;
 FOR count := 1 TO theNum DO
 SetEntryColor(thePal, count - 1, theBuf^^.B[count]);
 END;
 END
 ELSE
 thePal := NIL;
 DisposHandle(POINTER(theBuf));
 END;
 END;
 END;
 GetPal := dummy;
 END;

{Given references to a PICT file, read the PICT file into a PICT handle.
 }
 FUNCTION GetPic (theReply : SFReply;
 VAR thePic : PicHandle) : BOOLEAN;
 VAR
 OK : BOOLEAN;
 FileRef : INTEGER;
 BufSize : LongInt;
 theE : OSerr;
 tempPic : PicHandle;
 BEGIN
 OK := FALSE;
 FileRef := 0;
 tempPic := NIL;
 theE := FSOpen(theReply.fname, theReply.vRefNum, FileRef);
 IF (theE = noErr) THEN
 BEGIN
 theE := GetEOF(FileRef, BufSize);
 IF (theE = noErr) THEN
 BEGIN
 BufSize := BufSize - 512;
 theE := SetFPos(FileRef, fsFromStart, 512);
 IF (theE = noErr) THEN
 BEGIN
 tempPic := PicHandle(NewHandle(BufSize));
 theE := MemError;
 IF (theE = noErr) THEN
 BEGIN
 HLock(Handle(tempPic));
 theE := FSRead(FileRef, BufSize, POINTER(tempPic^));
 HUnLock(Handle(tempPic));
 OK := (theE = noErr);
 IF OK THEN
 thePic := tempPic;
 END;
 END;
 END;
 END;
 IF (FileRef <> 0) THEN
 FileRef := FSClose(FileRef);

 IF NOT OK THEN
 BEGIN
 SysBeep(1);
 IF tempPic <> NIL THEN
 DisposHandle(Handle(tempPic));
 END;
 GetPic := OK;
 END;

{Load a PICT into the DA. }
 PROCEDURE LoadPic (theDCE : DCtlPtr);
 VAR
 theImage : ImageHandle;
 tempReply : SFReply;
 P : point;
 theList : SFTypeList;
 S : str255;
 BEGIN
 theImage := ImageHandle(theDCE^.dCtlStorage);
 WITH theImage^^ DO
 BEGIN
 { Select a File.}
 P.h := 60;
 P.v := 60;
 theList[0] := ‘PICT’;
 SFGetFile(P, ‘’, NIL, 1, theList, NIL, tempReply);
 IF tempReply.good THEN
 BEGIN
 {If a files is selected, release the old Picture and Palette (if any).}
 IF imagePic <> NIL THEN
 BEGIN
 DisposHandle(Handle(imagePic));
 imagePic := NIL;
 picRect.bottom := kBox * kNum;
 picRect.right := kBox * kNum;
 END;
 IF imagePal <> NIL THEN
 BEGIN
 DisposePalette(imagePal);
 numPal := 0;
 imagePal := NIL;
 END;
 { Prepare to set Windows name to ‘ColorImage’.}
 S := nameStr;

 { Read the Picture. }
 IF GetPic(tempReply, imagePic) THEN
 BEGIN
 { If PICT read correctly, resize the window & set the Window name to 
‘ColorImage : (filename)’.}
 picRect.bottom := imagePic^^.picFrame.bottom - imagePic^^.picFrame.top;
 picRect.right := imagePic^^.picFrame.right - imagePic^^.picFrame.left;

 S := CONCAT(S, ‘: ‘, tempReply.fname);

 {If this is Color Quickdraw CPU.}
 IF ColorFlag THEN
 BEGIN
 { Get Palette from Picture.}
 IF GetPal(imageWindow, imagePic, imagePal, numpal) THEN
 BEGIN
 { If successful, set the Palette to the Image Window & resize the Pal 
rect. }
 SetPalette(imageWindow, imagePal, true);
 IF numPal > kNum THEN
 palRect.right := palRect.left + (kNum * kBox)
 ELSE
 palRect.right := numPal * kBox;
 palRect.bottom := (((numPal - 1) DIV kNum) + 1) * kBox;
 END;
 END;
 END;

{Set the Menu correctly, set so the Picture is displayed first, resize
 the window, and set the Window Title. }
 IF imagePic <> NIL THEN
 EnableItem(imageMenu, kShowPic)
 ELSE
 DisableItem(imageMenu, kShowPic);
 IF imagePal <> NIL THEN
 EnableItem(imageMenu, kShowPal)
 ELSE
 DisableItem(imageMenu, kShowPal);

 ShowPicFlag := true;
 ReSize(imageWindow, picRect);
 SetWTitle(imageWindow, S);
 END;
 END;
 END;

{Does this CPU have color Quickdraw? }
 FUNCTION ColorQDExists : boolean;
 CONST
 ROM85Loc = $28E;
 TwoHighMask = $C000;
 TYPE
 WordPtr = ^INTEGER;
 VAR
 Wd : WordPtr;
 BEGIN
 Wd := POINTER(ROM85Loc);
 ColorQDExists := (BitAnd(Wd^, TwoHighMask) = 0);
 END;

{Open the DA.  Set the data structures, the Menu,  the window,  etc.
 }
 FUNCTION Open (theDCE : DCtlPtr) : OSErr;
 VAR
 tempPort : Grafptr;
 theImage : ImageHandle;
 tmpRect : Rect;
 insideWindow : WindowPeek;
 BEGIN
 getport(tempPort);
 IF theDCE^.dCtlStorage = NIL THEN
 BEGIN
 theDCE^.dCtlStorage := NewHandle(SizeOf(imageData));
 HLock(theDCE^.dCtlStorage);
 theImage := ImageHandle(theDCE^.dCtlStorage);
 WITH theDCE^, theImage^^ DO
 BEGIN
 imageID := dCtlRefNum;
 IF imageID > 0 THEN
 imageID := -imageID;
 imageID := $C000 + 32 * (-1 - imageID);

 imageMenu := GetMenu(imageID);
 IF dCtlRefNum < 0 THEN
 BEGIN
 imageMenu^^.menuID := imageID;
 theDCE^.dctlMenu := imageID;
 END
 ELSE
 BEGIN
 imageMenu^^.menuID := -imageID;
 theDCE^.dctlMenu := -imageID;
 END;

 imagePic := NIL;
 imagePal := NIL;
 numPal := 0;
 DisableItem(imageMenu, kShowPic);
 DisableItem(imageMenu, kShowPal);
 picRect.top := 0;
 picRect.left := 0;
 picRect.bottom := kBox * kNum;
 picRect.right := kBox * kNum;
 palRect := picRect;
 ShowPicFlag := true;
 ColorFlag := ColorQDExists;
 GetIndString(nameStr, imageID, 1);
 GetIndString(nopicStr, imageID, 2);

 tmpRect := picRect;
 OffSetRect(tmpRect, 0, kVoff);
 IF ColorFlag THEN
 imageWindow := NewCWindow(NIL, tmpRect, nameStr, true, rDocProc, Pointer(-1), 
True, 0)
 ELSE
 imageWindow := NewWindow(NIL, tmpRect, nameStr, true, rDocProc, Pointer(-1), 
True, 0);
 SetPort(imageWindow);
 insideWindow := WindowPeek(imageWindow);
 insideWindow^.windowKind := dCtlRefNum;
 dCtlWindow := Ptr(imageWindow);
 END;
 HUnLock(theDCE^.dCtlStorage);
 END
 ELSE
 BEGIN
 SelectWindow(WindowPtr(theDCE^.dCtlWindow));
 SetPort(WindowPtr(theDCE^.dCtlWindow));
 END;
 SetPort(tempPort);
 Open := noErr;
 END;

{Do nothing Prime routine.}
 FUNCTION Prime (theDCE : DCtlPtr;
 IOPB : ParmBlkPtr) : OSErr;
 BEGIN
 Prime := noErr;
 END;

{Do the Control routine (ie. Events, Menus, etc.).}
 FUNCTION Control (theDCE : DCtlPtr;
 IOPB : ParmBlkPtr) : OSErr;
 CONST
 accEvent = 64;
 accMenu = 67;
 accUndo = 68;
 accCut = 70;
 accCopy = 71;
 accPaste = 72;
 accClear = 73;
 VAR
 theEvent : EventRecord;
 theImage : ImageHandle;
 aWindow : WindowPtr;
 tempRect : Rect;
 tempPort : Grafptr;
 count : integer;
 BEGIN
 getport(tempPort);
 HLock(theDCE^.dCtlStorage);
 theImage := ImageHandle(theDCE^.dCtlStorage);
 WITH theImage^^ DO
 BEGIN
 SetPort(imageWindow);
 CASE IOPB^.csCode OF
 accEvent : 
 BEGIN
 BlockMove(IOPB^.ioMisc, @theEvent, SizeOf(theEvent));
 CASE theEvent.what OF
 {Update event:  Show the Picture or the Palette.}
 updateEvt : 
 BEGIN
 BeginUpdate(WindowPtr(theEvent.message));
 SetPort(WindowPtr(theEvent.message));
 
 IF ShowPicFlag THEN
 BEGIN
 EraseRect(picRect);
 IF imagePic <> NIL THEN
 DrawPicture(imagePic, picRect)
 ELSE
 BEGIN
 MoveTo(kHst, kVst);
 DrawString(noPicStr);
 END;
 END
 ELSE IF ColorFlag THEN
 BEGIN
 EraseRect(palRect);
 IF imagePal <> NIL THEN
 FOR count := 0 TO NumPal - 1 DO
 BEGIN
 PmForeColor(count);
 tempRect.top := (count DIV kNum) * kBox;
 tempRect.left := (count MOD kNum) * kBox;
 tempRect.bottom := tempRect.top + kBox;
 tempRect.right := tempRect.left + kBox;
 PaintRect(tempRect);
 END;
 END;
 EndUpdate(WindowPtr(theEvent.message));
 END;
 { Activate Event:  Add or remove the Menu.  }
 activateEvt : 
 IF BitAND(theEvent.modifiers, activeFlag) <> 0 THEN
 BEGIN
 IF Ord(theEvent.message) = Ord(imageWindow) THEN
 BEGIN
 InsertMenu(imageMenu, 0);
 DrawMenuBar;
 END;
 END
 ELSE IF Ord(theEvent.message) = Ord(imageWindow) THEN         
 {De-activate event}
 BEGIN
 DeleteMenu(imageMenu^^.menuID);
 DrawMenuBar;
 END;
 { Mouse Down:  Drag the window.   }
 mouseDown : 
 IF FindWindow(theEvent.where, awindow) IN [inSysWindow, inContent] THEN
 BEGIN
 SetRect(tempRect, -30000, -30000, 30000, 30000);
 DragWindow(awindow, theEvent.where, tempRect);
 END;
 keyDown, autoKey : 
 SysBeep(1);
 OTHERWISE
 END;
 END;
{Menus:  Do the About Alert, Load a Picture or switch between the Picture 
or Palette. }
 accMenu : 
 CASE IOPB^.CSParam[1] OF
 kAbout : 
 count := Alert(imageID, NIL);
 kLoadPic : 
 LoadPic(theDCE);
 kShowPic : 
 IF NOT ShowPicFlag THEN
 BEGIN
 ShowPicFlag := true;
 ReSize(imageWindow, picRect);
 END;
 kShowPal : 
 IF ShowPicFlag THEN
 BEGIN
 ShowPicFlag := false;
 ReSize(imageWindow, palRect);
 END;
 OTHERWISE
 END;
 accUndo, accCut, accCopy, accPaste, accClear : 
 SysBeep(1);
 OTHERWISE
 END;
 END;
 HUnLock(Handle(theImage));
 SetPort(tempPort);
 Control := noErr;
 END;

{Do nothing Status routine. }
 FUNCTION Status (theDCE : DCtlPtr;
 IOPB : ParmBlkPtr) : OSErr;
 BEGIN
 Status := noErr;
 END;

{Close Routine:  Clear the Menu, Window, Palette, Picture and Data Structure. 
 }
 FUNCTION Close (theDCE : DCtlPtr;
 IOPB : ParmBlkPtr) : OSErr;
 VAR
 theImage : ImageHandle;
 BEGIN
 HLock(theDCE^.dCtlStorage);
 theImage := ImageHandle(theDCE^.dCtlStorage);
 WITH theImage^^ DO
 BEGIN
 DeleteMenu(imageMenu^^.menuID);
 ReleaseResource(Handle(imageMenu));
 DrawMenuBar;
 IF imagePal <> NIL THEN
 DisposePalette(imagePal);
 IF imagePic <> NIL THEN
 DisposHandle(Handle(imagePic));
 DisposeWindow(imageWindow);
 END;
 HUnLock(theDCE^.dCtlStorage);

 IF theDCE^.dCtlRefNum < 0 THEN
 HPurge(Handle(theDCE^.dCtlDriver));

 theDCE^.dCtlWindow := NIL;
 DisposHandle(theDCE^.dCtlStorage);
 theDCE^.dCtlStorage := NIL;
 Close := noErr;
 END;

{DAs main routine. }
 FUNCTION Main;
 BEGIN
 CASE driveCall OF
 DriverOpen : 
 Main := Open(theDCE);
 DriverPrime : 
 Main := Prime(theDCE, IOPB);
 DriverControl : 
 BEGIN
 BitClr(@theDCE^.dCtlFlags, 15 - dCtlEnable);
 Main := Control(theDCE, IOPB);
 BitSet(@theDCE^.dCtlFlags, 15 - dCtlEnable);
 END;
 DriverStatus : 
 Main := Status(theDCE, IOPB);
 DriverClose : 
 Main := Close(theDCE, IOPB);
 END;
 END;

END.

*  ColorImageDA.R
*  Resource Source File 
*by Steve Sheets 12/87
* 
ColorImageDA Rsrc

Type MENU
  ,-16000
ColorImage
  About ColorImage...
  (-
  Load Picture
  (-
  Show Picture
  Show Palette

Type STR#
  ,-16000
2
ColorImage
No Picture Available

Type DITL
  ,-16000
5

button
160 170 180 230
OK

staticText
20 95 39 305
ColorImage 1.1 by Steve Sheets

staticText
40 104 59 296
Designed for MacTutor 12/87

staticText
80 40 119 360
DA - Displays a PICT file.  If 
it contains a Color PixMap, 
displays it in the correct Palette.

staticText
120 40 139 360
FKEY - Saves the current screen 
into a PICT file.

Type ALRT
  ,-16000
60 120 260 520
-16000
5555
 
AAPL
$102.23
Apple Inc.
+2.47
MSFT
$44.61
Microsoft Corpora
+0.53
GOOG
$520.91
Google Inc.
+0.07

MacTech Search:
Community Search:

Software Updates via MacUpdate

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
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
TechTool Pro 7.0.5 - Hard drive and syst...
TechTool Pro is now 7, and this is the most advanced version of the acclaimed Macintosh troubleshooting utility created in its 20-year history. Micromat has redeveloped TechTool Pro 7 to be fully 64... Read more
PDFKey Pro 4.0.2 - Edit and print passwo...
PDFKey Pro can unlock PDF documents protected for printing and copying when you've forgotten your password. It can now also protect your PDF files with a password to prevent unauthorized access and/... Read more
Yasu 2.9.1 - System maintenance app; per...
Yasu was originally created with System Administrators who service large groups of workstations in mind, Yasu (Yet Another System Utility) was made to do a specific group of maintenance tasks... Read more
Hazel 3.3 - Create rules for organizing...
Hazel is your personal housekeeper, organizing and cleaning folders based on rules you define. Hazel can also manage your trash and uninstall your applications. Organize your files using a... Read more
Autopano Giga 3.7 - Stitch multiple imag...
Autopano Giga allows you to stitch 2, 20, or 2,000 images. Version 3.0 integrates impressive new features that will definitely make you adopt Autopano Pro or Autopano Giga: Choose between 9... Read more

Latest Forum Discussions

See All

Inferno 2 Review
Inferno 2 Review By Andrew Fisher on October 21st, 2014 Our Rating: :: TWIN STICK GOODNESSUniversal App - Designed for iPhone and iPad With tight controls and awesome, stark visuals, Inferno 2 is loads of fun.   | Read more »
Clips Review
Clips Review By Jennifer Allen on October 21st, 2014 Our Rating: :: CONVENIENT PASTINGUniversal App - Designed for iPhone and iPad Making copying and pasting more powerful than usual, Clips is a great way to move stuff around.   | Read more »
MonSense Review
MonSense Review By Jennifer Allen on October 21st, 2014 Our Rating: :: ORGANIZED FINANCESiPhone App - Designed for the iPhone, compatible with the iPad Organize your finances with the quick and easy to use, MonSense.   | Read more »
This Week at 148Apps: October 13-17, 201...
Expert App Reviewers   So little time and so very many apps. What’s a poor iPhone/iPad lover to do? Fortunately, 148Apps is here to give you the rundown on the latest and greatest releases. And we even have a tremendous back catalog of reviews; just... | Read more »
Angry Birds Transformers Review
Angry Birds Transformers Review By Jennifer Allen on October 20th, 2014 Our Rating: :: TRANSFORMED BIRDSUniversal App - Designed for iPhone and iPad Transformed in a way you wouldn’t expect, Angry Birds Transformers is a quite... | Read more »
GAMEVIL Announces the Upcoming Launch of...
GAMEVIL Announces the Upcoming Launch of Mark of the Dragon Posted by Jessica Fisher on October 20th, 2014 [ permalink ] Mark of the Dragon, by GAMEVIL, put | Read more »
Interview With the Angry Birds Transform...
Angry Birds Transformers recently transformed and rolled out worldwide. This run-and-gun title is a hit with young Transformers fans, but the ample references to classic Transformers fandom has also earned it a place in the hearts of long-time... | Read more »
Hail to the King: Deathbat Review
Hail to the King: Deathbat Review By Rob Thomas on October 20th, 2014 Our Rating: :: SO FAR AWAYUniversal App - Designed for iPhone and iPad Hail to the King: Deathbat may feel like “Coming Home” for Avenged Sevenfold’s faithful,... | Read more »
Find Free Food on Campus with Ypay
Find Free Food on Campus with Ypay Posted by Jessica Fisher on October 20th, 2014 [ permalink ] iPhone App - Designed for the iPhone, compatible with the iPad | Read more »
Strung Along Review
Strung Along Review By Jordan Minor on October 20th, 2014 Our Rating: :: GOT NO STRINGSUniversal App - Designed for iPhone and iPad A cool gimmick and a great art style keep Strung Along from completely falling apart.   | Read more »

Price Scanner via MacPrices.net

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
Deals on 2011 13-inch MacBook Airs, from $649
Daily Steals has the Mid-2011 13″ 1.7GHz i5 MacBook Air (4GB/128GB) available for $699 with a 90 day warranty. The Mid-2011 13″ 1.7GHz i5 MacBook Air (4GB/128GB SSD) is available for $649 at Other... Read more
2013 15-inch 2.0GHz Retina MacBook Pro availa...
B&H Photo has leftover previous-generation 15″ 2.0GHz Retina MacBook Pros now available for $1599 including free shipping plus NY sales tax only. Their price is $400 off original MSRP. B&H... Read more
Updated iPad Prices
We’ve updated our iPad Air Price Tracker and our iPad mini Price Tracker with the latest information on prices and availability from Apple and other resellers, including the new iPad Air 2 and the... Read more
Apple Pay Available to Millions of Visa Cardh...
Visa Inc. brings secure, convenient payments to iPad Air 2 and iPad mini 3as well as iPhone 6 and 6 Plus. Starting October 20th, eligible Visa cardholders in the U.S. will be able to use Apple Pay,... Read more
Textkraft Pocket – the missing TextEdit for i...
infovole GmbH has announced the release and immediate availability of Textkraft Pocket 1.0, a professional text editor and note taking app for Apple’s iPhone. In March 2014 rumors were all about... Read more
C Spire to offer iPad Air 2 and iPad mini 3,...
C Spire on Friday announced that it will offer iPad Air 2 and iPad mini 3, both with Wi-Fi + Cellular, on its 4G+ LTE network in the coming weeks. C Spire will offer the new iPads with a range of... Read more
Belkin Announces Full Line of Keyboards and C...
Belkin International has unveiled a new lineup of keyboard cases and accessories for Apple’s newest iPads, featuring three QODE keyboards and a collection of thin, lightweight folios for both the... Read more

Jobs Board

*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
Position Opening at *Apple* - Apple (United...
**Job Summary** At the Apple Store, you connect business professionals and entrepreneurs with the tools they need in order to put Apple solutions to work in their Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.