TweetFollow Us on Twitter

Smart Docs
Volume Number:4
Issue Number:2
Column Tag:C Workshop

Smart Documents

By Joel McNamara, Watercourse Software, Bellevue, WA

Forked Tongue Programming: Data Forks, Resource Juggling, and Stand Alone Documents

Most developers are quick to realize that a Macintosh file, whether application or not, could easily be an advertisement for Double Mint Gum. Yes, it’s two, two, two files in one. As “Inside Macintosh” is quick to point out, “Every file has a resource fork and a data fork (either of which may be empty). The resource fork of an application contains not only the resources used by the application but also the application code itself. The data fork of an application can contain anything an application wants to store there.” Big deal. Even most novices know that when an application creates a document, it places the data into the data fork of a file. Pretty basic stuff, even a bit dull and boring for most MacTutor readers.

But let’s step beyond the obvious for a moment, and concentrate on the quote “can contain anything an application wants to store there.” If we can put anything in there, how about data that only the application could access. No reading in other files, but just operating on the information found within its data fork. Think of it as a stand alone document. Perhaps a word processor that generates a file when double clicked will run itself. Or a chart program that makes files you could modem to a business associate without him needing the creator application. Something a little like “Glue,” where you have the ability to view an application’s output without needing the application. Runtime versions of data bases incorporate these features. Even Microsoft is rumored to be considering a version of “Excel” that will create stand alone spreadsheets.

Pretty neat stuff, but probably too tricky for the average programmer, right? Wrong. The secret lies within effectively using the resource and data forks.

Stand Alone Document Theory

The reasons for developing such stand alone documents are quite obvious; the ability to disseminate information without the need of a “mother” application to access it; being able to address larger audiences with your output since not everyone needs the creator; not needing sophisticated knowledge of an application to use the information found in a document. All of these points and more make it worthwhile to consider incorporating the ability to generate stand alone documents in your applications.

In thinking about such a project, there are several things to consider. The first is the functionality you want the document to have. More than likely you’re not going to want the stand alone file to do everything the original application does. Therefore, you’ll need to include some secondary code that will simply display, scroll, print, or do whatever.

But where does one put the code and resources actually needed to run the document? If there is one set of CODE resources that run the main application and another set that will run the stand alone document, won’t they conflict and cause problems? Two theories can be used in developing stand alone document generators. The first espouses putting all the required resources into a template file. The generator then simply copies the template, gives the copied file a new name, and inserts the desired information into the data fork. This is the technique used in the stand alone text generator “Take A Letter.” The second method is cleaner, eliminating the need for template files. The generator program actually contains the code needed to run a stand alone document, although it may masquerade as another resource. The generator creates a new file, copies in the resources, renames them, fills the data fork, and sets the file’s attributes to be an application.

Stand Alone Document Practice

Enough theory, and on to the practice. What will be demonstrated is how to construct a stand alone document generator that works with MacPaint format documents. Three sources are included here. The first (PaintDisplay.c) is code for a program that loads a Paint file stored in its data fork and then shows the upper left hard corner of the bit mapped image. The second listing (PostCard.c) is for an application called PostCard that builds a stand alone Paint document. (The code from PaintDisplay will be inserted into this document generator.) And finally, PostCard.r is the RMaker file. Although the sources are in Lightspeed C, the techniques should be general enough to apply to a different variation of C or even another language. (Lightspeed info: Both projects (PaintDisplay proj and PostCard proj) should include MacTraps plus their own respective source files and be set to build applications. PostCard’s creator type should be ‘PCRD’.)

The first step is to compile PaintDisplay.c. This source contains a standard algorithm for displaying an image from a MacPaint format file. It initializes everything, opens up its data fork, grabs bytes, puts up a window, displays the left corner of the Paint document, and waits for a mouse click to quit. All in one breath. Don’t try to run it quite yet though. If you do, it will be looking in its own data fork for something that isn’t there yet, and your curiosity will be rewarded with a bomb.

The only real item in the code that needs discussing, is how one goes about accessing the data fork. To quote from the source:

if (GetVol(&thisVolume,&vRef) != noErr)
 ErrorRoutine(FALSE,0);
GetAppParms(&thisProgram,&temp,&thisHandle);
if (FSOpen(thisProgram,vRef,&srcFile) != noErr)
 ErrorRoutine(TRUE,srcFile);

The first step is to determine what volume the application is on with a GetVol() call. Next, use GetAppParms() to return the name of the current application. Now pass the application’s name and the volume reference number to FSOpen(). It will oblige by opening up your application’s data fork.

Resource Rascality

Once you’ve compiled PaintDisplay, the next task is to use RMaker on the PostCard.r file. This file contains the resources for the menus, dialogs, bundles, icons, etc. for the PostCard application. It also has the necessary resources to be used in creating the stand alone document.

An often overlooked feature of RMaker is the ability to copy specific resources from one file to another during the compile stage. By using the “.R” command you could load, let’s say, a font from an existing file into the resource file you’re currently compiling. The format is:

Type FONT = GNRL* the new resource type (FONT)
,8 * the new resource ID
.R * the RMaker directive
Fonts FONT 12  * the file “Fonts” and the resource
 * (FONT 12) to copy into the new resource

RMaker is pretty lax as to letting you get away with things in certain areas. This feature proves beneficial when building program generating applications. As mentioned before, the biggest problem in writing an application that builds another, is where to stick the code that will be spawned off. Obviously you can’t have a program with two CODE 0 resources, at least without the potential for serious problems.

The solution is to build a new resource type of your choosing, and then through RMaker, stuff the CODE into it. For example:

Type FAKE = GNRL * creates a resource type called FAKE...
,0 * with an ID of 0 
.R * tells RMaker to load in something
SuperEdit CODE 0 * else, i.e., the jump table from
 * a file called “SuperEdit”

This is what’s happening in PostCard.r. The previously compiled code from PaintDisplay is being read in, and then assigned a new type and identification. The CODE resource is still the same, but it’s gone into hiding by changing its name. It’s as easy as that. When the resource file is compiled, you’ll have your CODE just sitting there, ready to use, but disguised as something else that won’t conflict with the the program that will be using it to create another application.

Taking a peek with ResEdit at the results. FAKE and DUMY are really code resources, but with their new identities, don’t conflict with code resources found in the application that will use them.

Two words of advice on using RMaker in such a fashion. The first is, RMaker frowns on using a source file with a space in its name. Therefore, “My File” will cause you problems but “MyFile” will not. The second caveat is to be aware of path names. If all of your formats look all right, but RMaker still is complaining, odds are you have an improperly laid out path. Double check it.

You’ll notice in the PostCard.r file, more than just CODE resources are being changed. Remember, all compilers are not created equal. Some will generate just two code segments (for under 32k of code, of course): 0 - the jump table, and 1 - the actual code . Others, Lightspeed C for example, will generate more than two code segments and a variety of other resource types where data is stored. That’s what all the CRELs, DATAs, ZEROs, etc. are all about. When you are transferring and converting code resources, be sure you get everything your particular compiler needs for the application to run. At first put everything in, but after a while try some experimenting. At times you’ll find you don’t need all of the data and support resources.

Resource Moving Without ResEdit

The last step in the process is to compile PostCard.c. The compiled resources from PostCard proj.Rsrc are copied in, and the application is ready to run.

From the Macintosh’s perspective, here’s what happens when the user selects “Make a PostCard...” from the menu:

The SFPut() routine is called to select a name and location for the new file. CreateResFile() is used to create the named file. Finder attributes are then set, and the resource fork of the new file is opened.

Now the fun stuff. The code determines what the resource reference number of the current application is (in this case PostCard). It then makes use of a programmer defined function called ResTransfer().

ResTransfer(sourceRes, sourceID, destRes, destID)
ResType sourceRes, destRes;
intsourceID, destID; 
{
Handle  codeHandle;
 codeHandle = NewHandle(0);
 codeHandle = GetResource(sourceRes,sourceID);
 UseResFile(resRef);
 DetachResource(codeHandle);
 AddResource(codeHandle, destRes, destID, “\p”);
 if (ResError() != noErr) {
   DoMessage(“\pSorry, couldn’t copy the required resource.”);
 myError = 1;
 }
}

ResTransfer() is passed the resource type and ID of the resource to be copied, along with what type of resource and what ID number you want the copy to appear as. GetResource() is used to get a handle to the resource to be copied. UseResFile() is then called with the resource reference file number of the application that will be created. This tells the resource manager to only deal with the resource fork of the new stand alone document.

As per “Inside Macintosh,” the resource to be copied is detached, and then added to the new application with AddResource(). AddResource() is passed the handle to the resource, along with information concerning type and identification. If for some reason it can’t be added, an error handling routine is alerted.

ResTransfer() is called repeatedly for all of the resources needed to be placed in the stand alone document. At first BNDL, FREF, ICN#, etc. are moved in, giving the application its own unique type and icon. Next the FAKE and DUMY resources are copied and then converted back to their original types and IDs.

Once all the resources have been moved and/or changed, UpdateResFile() is used to tell the resource manager the new file needs updating, effectively adding and writing all of the resources. The stand alone document’s resource fork is then closed, and UseResFile() is called to revert the current resource fork back to PostCard.

With the resources in place, SFGet() is called to select the Paint format file to be read in. Its data fork is read and then written to the stand alone document’s data fork. With no errors reported, the stand alone document has now been created and is ready to run!

Final Thoughts

Needless to say, PostCard ain’t very fancy. If one was to do it right, scrolling, desk accessory support, more error handling, perhaps even printing and the ability to save a full MacPaint format document out of it should be included in the PaintDisplay code. Did I just hear the basis for a shareware product?

Also keep in mind that PostCard just demonstrates the idea of stand alone documents. Although application generators like it are useful, stand alone documents would really be best created by say a “WriteNow” or “SuperPaint.” Ideally, the entire process would be incorporated as a function in an actual, full blown program where the user would simply select a menu item to create the stand alone file.

One potential argument to the idea of stand alone documents is more code overhead in the original program. However, with a little thought and planning this can easily be avoided by segmenting the program so the main application and the one to be generated would share some common code. Even if an extra 15 or 20k went into the final product, users would likely justify the size increase because of the benefits.

As you can see, creating stand alone documents isn’t that difficult. The problems with data and resources can easily be overcome, with the end result being things like self running documentation, double clickable desktop presentations, or stand alone spreadsheets. Hopefully in the near future we’ll be seeing more of stand alone documents. But for now, why don’t you give your own a try.

/* 
 * PostCard, version 1.0, Lightspeed C
 * demonstrates using data forks and resource tricks
 * Copyright 1987 by Joel McNamara - All Rights Reserved
 * for MacTutor Magazine
 * initial coding - October 12, 1987
 */
#include“MacTypes.h”
#include“QuickDraw.h”
#include“WindowMgr.h”
#include“EventMgr.h”
#include“MenuMgr.h”
#include“FileMgr.h”
#include“MemoryMgr.h”
#include“ResourceMgr.h”
#include“StdFilePkg.h”
#include“OSUtil.h”
#include“DialogMgr.h”

/* defines... */
#define MessageDLOG255
#define AboutDLOG256
#define HelpDLOG 257
#define AppleMENU1
#define About    1
#define FileMENU 255
#define Quit1
#define CommandMENU256
#define MakeCard 1
#define Help3

/* globals... */
Boolean done;
char    theString[256];
MenuHandleAppleMenuHndl, FileMenuHndl, CommandMenuHndl;
EventRecord theEvent;
DialogPtr theDialog;
int     resRef,dummy,myError;

/* main */
main()
{
 Initialize();
 do{
 MainLoop();
 }while(!done);
} 
/* as always... */
Initialize()
{
 InitGraf(&thePort);
 InitFonts();
 InitWindows();
 InitMenus();
 TEInit();
 InitDialogs(0);
 InitCursor();
 FlushEvents(everyEvent, 0);
 SetUpMenus();
 done = FALSE;
 myError = 0;
}

/* make the menus */
SetUpMenus()
{
 AppleMenuHndl = GetMenu(AppleMENU);
 AddResMenu(AppleMenuHndl, ‘DRVR’);
 InsertMenu(AppleMenuHndl, 0);
 FileMenuHndl = GetMenu(FileMENU);
 InsertMenu(FileMenuHndl, 0);
 CommandMenuHndl = GetMenu(CommandMENU);
 InsertMenu(CommandMenuHndl, 0);
 DrawMenuBar();
}
/* generic dialog displayer */
DoDialog(theDLOG)
inttheDLOG;
{
 theDialog = GetNewDialog(theDLOG, 0, -1);
 DoButton(theDialog);
 ModalDialog(0, &dummy);
 DisposDialog(theDialog);
}
/* message display routine */
DoMessage(theMessage)
Str255  theMessage;
{
 theDialog = GetNewDialog(MessageDLOG, 0, -1);
 ParamText(theMessage, “\p”, “\p”, “\p”);
 DoButton(theDialog);
 ModalDialog(0, &dummy);
 DisposDialog(theDialog); 
}
/* loop until we’re done */
MainLoop()
{
 SystemTask();
 if (GetNextEvent(everyEvent,&theEvent)) {
 switch (theEvent.what) {
 case mouseDown:
 DoMouseDown();  
 break;
 default:
 break;
 }
 }
}
/* if we have a mouse down */
DoMouseDown()
{
WindowPtr whichWindow;
intthePart;
 thePart = FindWindow(theEvent.where,&whichWindow);
 switch(thePart) {
 case inMenuBar:
 DoMenu();
 break;
 case inSysWindow:
 SystemClick(&theEvent, whichWindow);
 break;
 default:
 break;
 }
}

/* if a menu hit then... */
DoMenu()
{
long menuChoice;
 menuChoice = MenuSelect(theEvent.where);
 DoMenuItem(menuChoice);
}
/* which menu was selected? */
DoMenuItem(menuChoice)
long menuChoice;
{
int theMenu,theItem;
 if (menuChoice != 0 ) {
 theItem = menuChoice;
 theMenu = (menuChoice >> 16);
 switch (theMenu) {
 case AppleMENU:
 DoDA(theItem);
 break; 
 case FileMENU:
 done = TRUE;
 break;
 case CommandMENU:
 DoCommands(theItem);
 default:
 break;
 }
 HiliteMenu(0);
 }
}
/* the apple menu was hit */
DoDA(theItem)
int theItem;
{
int accNumber;
 if (theItem == About)
 DoDialog(AboutDLOG);
 else{
 GetItem(AppleMenuHndl,theItem,theString);
 accNumber = OpenDeskAcc(theString);
 }
}
/* the commands menu was hit */
DoCommands(theItem)
int theItem;
{
 switch(theItem) {
 case MakeCard:
 ConvertFile();
 break;
 case Help:
 DoDialog(HelpDLOG);
 break;
 default:
 break;
 }
}
/* make a postcard */
ConvertFile()
{
char*   buffer;
long    theEOF;
intcurrentResRef,refNum,destRef;
Handle  codeHandle;

Point   myPoint;
SFReply paintReply, myReply;
SFTypeListmyTypes;
FInfo   myFInfo;
OSErr   myErr;   
 myTypes[0] = ‘PNTG’;
 myPoint.h = 90;
 myPoint.v = 90;

 /* first we create the application */ 
 DoMessage(“\pFirst name the PostCard you want to create.”);
 SFPutFile(myPoint, “\pEnter PostCard name:”, “\pMy PostCard”, 0,
 &myReply);
 if (myReply.good)
 {
 SetVol(0, myReply.vRefNum);
 CreateResFile(myReply.fName);
 /* make it what we want... */
 myFInfo.fdType = ‘APPL’;
 myFInfo.fdCreator = ‘PDIS’;
 myFInfo.fdFlags = fHasBundle;
 myFInfo.fdLocation.h = 0;
 myFInfo.fdLocation.v = 0;
 SetFInfo(myReply.fName, myReply.vRefNum, &myFInfo);
 /* open its resource fork */
 resRef = OpenResFile(myReply.fName);
 if (resRef != -1)
 {
 /* get PostCard’s resource ref number and then
 start moving the resources */
 currentResRef = CurResFile();
 /* first the obvious ones */
 ResTransfer(‘BNDL’,129, ‘BNDL’,128);
 ResTransfer(‘PDIS’,0,’PDIS’,0);
 ResTransfer(‘FREF’,128,’FREF’,128);
 ResTransfer(‘ICN#’,129,’ICN#’,128);
 /* now grab the FAKEs and make them CODE */
 ResTransfer(‘FAKE’,0,’CODE’,0);
 ResTransfer(‘FAKE’,1,’CODE’,1);
 ResTransfer(‘FAKE’,2,’CODE’,2);
 /* finally get the DUMYs and convert them */
 ResTransfer(‘DUMY’,0,’CREL’,2);
 ResTransfer(‘DUMY’,1,’DATA’,0);
 ResTransfer(‘DUMY’,2,’DREL’,0);
 ResTransfer(‘DUMY’,3,’STRS’,0);
 ResTransfer(‘DUMY’,4,’ZERO’,0);

 /* update the new application, close it, make PostCard
 the current open resource fork */
 UpdateResFile(resRef);
 CloseResFile(resRef);
 UseResFile(currentResRef);
 
 /* see if we have any errors - open the application */
 if ( (FSOpen(myReply.fName, myReply.vRefNum, &destRef) != noErr) || 
(myError == 1) ) {
 DoMessage(“\pSorry a resource error prevented the PostCard from being 
created.”); 
 FSDelete(myReply.fName,myReply.vRefNum);
 myError = 0;    
 }
 else
 { 
 /* here we select the paint file we want to convert */
 DoMessage(“\pNow select the Paint file you want to display.”);
 SFGetFile(myPoint, “\p”, 0, 1, myTypes, 0, &paintReply);
 if (paintReply.good)
 { 
 /* open, read, and write into the document */
if (FSOpen(paintReply.fName, paintReply.vRefNum, &refNum) == noErr)
 {
 if ( GetEOF(refNum, &theEOF) != noErr)
 myError = 1;
 buffer = NewPtr(theEOF);
 if ( FSRead(refNum, &theEOF, buffer) != noErr)
 myError = 1;
 if ( FSWrite(destRef, &theEOF, buffer) != noErr)
 myError = 1;
 myErr = FSClose(refNum);
 myErr = FSClose(destRef);
 if (myError != 1)
 DoMessage(“\pYour PostCard has been created!”);
 } 
 }
 else
 {
 /* get rid of file we’ve created */
 FSDelete(myReply.fName,myReply.vRefNum);    
 }
 }
 
 }
 else
 myError = 1;
 
 if (myError == 1) {
 /* opps, problems - blitz the file */
 DoMessage(“\pSorry an error prevented the PostCard from being created.”); 

 FSDelete(myReply.fName,myReply.vRefNum);
 }
 }
}

/* grab a resource and rename it routine */
ResTransfer(sourceRes, sourceID, destRes, destID)
ResType sourceRes, destRes;
intsourceID, destID; 
{
Handle  codeHandle;
 codeHandle = NewHandle(0);
 
 /* get the source resource */
 codeHandle = GetResource(sourceRes,sourceID);
 /* set the current res file to the stand alone document */
 UseResFile(resRef);
 /* detach the source resource... */
 DetachResource(codeHandle);
 /* and add it to the document */
 AddResource(codeHandle, destRes, destID, “\p”);
 if (ResError() != noErr) {
 DoMessage(“\pSorry, couldn’t copy the required resource.”);
 myError = 1;
 }
}


/* fancy button for the modals */
DoButton(myDialog)
DialogPtr myDialog;
{
short   myType;
Handle  myHandle;
Rect    myBox;
GrafPtr dummyPort;

 GetPort(&dummyPort);
 SetPort(myDialog);
 GetDItem( myDialog, 1, &myType, &myHandle, &myBox );
 InsetRect(&myBox, -4, -4);
 PenSize(3, 3);
 FrameRoundRect(&myBox, 16, 16);
 PenNormal();
 SetPort(dummyPort);
}


/*
 * PaintDisplay.c
 *
 * This program supplies the code needed for the PostCard application
 * to generate a stand alone Paint file.
 *
 * copyright 1987, Joel McNamara - All Rights Reserved
 * for MacTutor Magazine
 *
 * initial coding - October 12, 1987
 *
 */
  
#include<MacTypes.h>
#include<QuickDraw.h>
#include<WindowMgr.h>
#include<EventMgr.h>
#include<MemoryMgr.h>
#include<SegmentLdr.h>

/* setup the world, display the image, and wait for a click */
main()
{
 InitGraf(&thePort);
 InitFonts();
 InitWindows();
 InitMenus();
 TEInit();
 InitDialogs(0L);
 InitCursor();
 FlushEvents(everyEvent,0);
 displayPaint();
 while (!Button());
}

/* the guts of the paint display program */
displayPaint()
{
char    *srcPtr, *dstPtr, *saveDstPtr, *skipPtr;
intsrcFile, scanLine, vRef, temp;
long    srcSize, paintSize;
Str255  thisProgram;
StringPtr thisVolume;
GrafPortaPort;
BitMap  theBitMap;
Rect    myRect;
WindowPtr myWind;
Handle  thisHandle;

 /* we’ll be sloppy with the nonrelocatable pointers and let them all 
get cleaned up upon exiting */
    
 /* the first 512 header bytes to skip */
 srcSize = 512;  
 skipPtr = NewPtr(512);
 if (srcPtr == 0L)
        ErrorRoutine(FALSE,0);
     /* the biggest it can be */  
 srcPtr = NewPtr(51840);
 if (srcPtr == 0L)
        ErrorRoutine(FALSE,0);
 /* see who and where we are... */
 if (GetVol(&thisVolume,&vRef) != noErr)
 ErrorRoutine(FALSE,0);
 GetAppParms(&thisProgram,&temp,&thisHandle);
    /* then open our data fork and read past the header */
    if (FSOpen(thisProgram,vRef,&srcFile) != noErr)
 ErrorRoutine(TRUE,srcFile);
 if (FSRead(srcFile,&srcSize,skipPtr) != noErr)
        ErrorRoutine(TRUE,srcFile);
 /* see how big we really are... */
 if (GetEOF(srcFile,&paintSize) != noErr)
        ErrorRoutine(TRUE,srcFile);
 paintSize -= 512;
 /* now read the rest of the bytes and close */
 if (FSRead(srcFile,&paintSize,srcPtr) != noErr)
        ErrorRoutine(TRUE,srcFile);  
 if (FSClose(srcFile) != noErr)
        ErrorRoutine(TRUE,srcFile);
 /* get a destination pointer... */
 dstPtr = NewPtr(51840);
 if (dstPtr == 0L)
        ErrorRoutine(FALSE,0); 
 saveDstPtr = dstPtr;
 scanLine = 1; 
 /* and start unpacking the compressed Paint data */
 for (scanLine = 1; scanLine <= 720; scanLine++)
 UnpackBits(&srcPtr,&dstPtr,72);
 /* make a window */      
 SetRect(&myRect,12,35,500,325);
   myWind = NewWindow(0L,&myRect,”\p”,TRUE,1,-1L,FALSE,99);

 /* configure our bitmap */
 theBitMap.baseAddr = saveDstPtr;
 theBitMap.rowBytes = 72;  
 theBitMap.bounds.top = 0;
 theBitMap.bounds.left = 0;
 theBitMap.bounds.bottom = 72 * 8;
 theBitMap.bounds.right = 720;
 /* and copy the Paint bits into our window */  
 CopyBits(&theBitMap, &myWind->portBits, &myWind->portRect, &myWind->portRect, 
srcCopy, 0L);    
}


/* simple no frills, beep and quit */
ErrorRoutine( closeFile, fileNum )
Boolean closeFile;
intfileNum; 
{
 SysBeep(5);
 if (closeFile)
 FSClose(fileNum); 
 ExitToShell();
}

* resource file for PostCard.c
* by Joel McNamara
* for MacTutor Magazine
* October 12, 1987

Development:MacTutor:PostCard proj.Rsrc
* you’ll probably want to change the pathname

* the bundles, first for PostCard then PaintDisplay
Type BNDL
,128
PCRD 0
ICN#
0 128
FREF
0 128

* this BNDL will be renumbered by the application
,129
PDIS 0
ICN#
0 128
FREF
0 128

* we’ll use the same FREF for both
Type FREF
,128
APPL 0

* PostCard file type
Type PCRD = STR 
,0
PostCard Version 1.0 - 12 Oct 87

* PaintDISplay file type
Type PDIS = STR 
,0
PaintDisplay Version 1.0 - 12 Oct 87

* der menu
Type MENU
,1
\14
About PostCard...
(-

,255
File
Quit

,256
Commands
Make a PostCard...
(-
Help...

* the dialog items
Type DITL
,255 (4)
2

button
48 272 66 349
OK

staticText Disabled
6 11 43 350
^0

,256 (4)
5
button
171 86 190 178
OK

staticText Disabled
2 86 20 177
PostCard 1.0

staticText Disabled
24 13 87 263
PostCard creates an application and then places a Paint file into the 
data fork, thus creating a stand alone viewer.

staticText Disabled
124 24 158 241
Copyright 1987, Joel McNamara\0D         All Rights Reserved

staticText Disabled
100 50 118 208
for MacTutor Magazine

,257 (4)
4
button
166 295 184 406
OK

staticText Disabled
3 4 38 423
PostCard takes a MacPaint document and turns it into a stand alone application 
that displays the upper left corner.

staticText Disabled
42 4 91 423
When the Paint document is selected a new file is created with CODE resources 
(FAKE and DUMY - stored within the PostCard application) copied and renamed 
into the new file.


staticText Disabled
95 4 161 423
These resources drive the new application by reading its own data fork 
(copied in from the Paint file) and then displaying the bit mapped image.


* the dialogs
Type DLOG
,255 (4)
message
60 68 136 438
Visible NoGoAway
1
0
255

,256 (4)
about
52 122 252 394
Visible NoGoAway
1
0
256

,257 (4)
help
46 48 242 474
Visible NoGoAway
1
0
257


* here’s the trickery - we create new resources of type FAKE, and read
* the CODE resources from PaintDisplay into them.
Type FAKE = GNRL
,0
.R
Development:MacTutor:PaintDisplay CODE 0
* you’ll need to specify a different pathname above

,1
.R
Development:MacTutor:PaintDisplay CODE 1
* you’ll need to specify a different pathname above

,2
.R
Development:MacTutor:PaintDisplay CODE 2
* you’ll need to specify a different pathname above


* now get the rest of the resources we need (as required by Lightspeed 
C) -
* creating dummy resources named DUMY.
Type DUMY = GNRL
,0
.R
Development:MacTutor:PaintDisplay CREL 2
* you’ll need to specify a different pathname above

,1
.R
Development:MacTutor:PaintDisplay DATA 0
* you’ll need to specify a different pathname above

,2
.R
Development:MacTutor:PaintDisplay DREL 0
* you’ll need to specify a different pathname above

,3
.R
Development:MacTutor:PaintDisplay STRS 0
* you’ll need to specify a different pathname above

,4
.R
Development:MacTutor:PaintDisplay ZERO 0
* you’ll need to specify a different pathname above

* now the application icon
Type ICN# = GNRL
,128
.H
00000000
00000000 
1FFFF800
20003C00 
20007C00
27FFFC00 
2401FC00
2553FC00 
2402F400
2545E400 
2409C400
25428400 
24010400
25420400 
24003F00
25084080 
24108040
23F13020 
2039C814
201E7F8F 
20023007
261F0007 
26008007
20006007 
3FFFFFE7
2000021F 
1FFFFC07
00000000 
00000000
00000000 
00000000
00000000
* next the mask
00000000
00000000 
1FFFF800
3FFFFC00 
3FFFFC00
3FFFFC00 
3FFFFC00
3FFFFC00 
3FFFFC00
3FFFFC00 
3FFFFC00
3FFFFC00 
3FFFFC00
3FFFFC00 
3FFFFF00
3FFFFF80 
3FFFFFC0
3FFFFFE0 
3FFFFFF4
3FFFFFFF 
3FFFFFFF
3FFFFFFF 
3FFFFFFF
3FFFFFFF 
3FFFFFFF
3FFFFE1F 
1FFFFC07
00000000 
00000000
00000000 
00000000
00000000 

* now the stand alone file’s icon
,129
00000000
00000000 
00000000
00000000 
00000000
00000000 
00000000
00000000 
00000000
FFFFFFFF 
81D00001
81D000FD 
81F000AD
811000D5 
811000AD
811000D5 
811000FD
81100001 
80E00001
81F00001 
81F00001
81F80001 
81F80001
81E85FFF 
81F80BFF
80D03FFF 
80F0FFFF
80703FFF 
8019FFFF
80000001 
FFFFFFFF
00000000
* next the mask
00000000
00000000 
00000000
00000000 
00000000
00000000 
00000000
00000000 
00000000
FFFFFFFF 
FFFFFFFF
FFFFFFFF 
FFFFFFFF
FFFFFFFF 
FFFFFFFF
FFFFFFFF 
FFFFFFFF
FFFFFFFF 
FFFFFFFF
FFFFFFFF 
FFFFFFFF
FFFFFFFF 
FFFFFFFF
FFFFFFFF 
FFFFFFFF
FFFFFFFF 
FFFFFFFF
FFFFFFFF 
FFFFFFFF
FFFFFFFF 
FFFFFFFF
00000000 
 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Logic Pro X 10.1.1 - Music creation and...
Apple Logic Pro X is the most advanced version of Logic ever. Sophisticated new tools for professional songwriting, editing, and mixing are built around a modern interface that's designed to get... Read more
VLC Media Player 2.2.0 - Popular multime...
VLC Media Player is a highly portable multimedia player for various audio and video formats (MPEG-1, MPEG-2, MPEG-4, DivX, MP3, OGG, ...) as well as DVDs, VCDs, and various streaming protocols. It... Read more
Sound Studio 4.7.8 - Robust audio record...
Sound Studio lets you easily record and professionally edit audio on your Mac. Easily rip vinyls and digitize cassette tapes, or record lectures and voice memos. Prepare for live shows with live... Read more
LibreOffice 4.4.1.2 - Free, open-source...
LibreOffice is an office suite (word processor, spreadsheet, presentations, drawing tool) compatible with other major office suites. The Document Foundation is coordinating development and... Read more
Freeway Pro 7.0.3 - Drag-and-drop Web de...
Freeway Pro lets you build websites with speed and precision... without writing a line of code! With its user-oriented drag-and-drop interface, Freeway Pro helps you piece together the website of... Read more
Cloud 3.3.0 - File sharing from your men...
Cloud is simple file sharing for the Mac. Drag a file from your Mac to the CloudApp icon in the menubar and we take care of the rest. A link to the file will automatically be copied to your clipboard... Read more
Cyberduck 4.6.5 - FTP and SFTP browser....
Cyberduck is a robust FTP/FTP-TLS/SFTP browser for the Mac whose lack of visual clutter and cleverly intuitive features make it easy to use. Support for external editors and system technologies such... Read more
Firefox 36.0 - Fast, safe Web browser. (...
Firefox for Mac offers a fast, safe Web browsing experience. Browse quickly, securely, and effortlessly. With its industry-leading features, Firefox is the choice of Web development professionals and... Read more
Thunderbird 31.5.0 - Email client from M...
As of July 2012, Thunderbird has transitioned to a new governance model, with new features being developed by the broader free software and open source community, and security fixes and improvements... Read more
VOX 2.4 - Music player that supports man...
VoxIt just sounds better! The beauty is in its simplicity, yet behind the minimal exterior lies a powerful music player with a ton of features & support for all audio formats you should ever need... Read more

Get The Whole Story – Lone Wolf Complete...
Get The Whole Story – Lone Wolf Complete is Now Available and On Sale Posted by Jessica Fisher on February 27th, 2015 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Who Wore it Best? The Counting Dead vs....
Like it or not, the “clicker” genre, popularized by cute distractions like Candy Box and Cookie Clicker, seems like it’s here to stay. So Who Wore it Best? takes a look at two recent examples: The Counting Dead and AdVenture Capitalist. | Read more »
Card Crawl, the Mini Deck Building Game,...
Card Crawl, the Mini Deck Building Game, is Coming Soon Posted by Jessica Fisher on February 27th, 2015 [ permalink ] Tinytouchtales and Mexer have announced their new game, | Read more »
Witness an all new puzzle mechanic in Bl...
Well, BlastBall MAX is not one of those games and is bucking trends such as timers, elements of randomness, and tacked-on mechanics in favor of pure puzzle gameplay. When you first boot up the game you’ll see a grid made up of squares that are each... | Read more »
This Princess Has a Dragon and She isn’t...
This Princess Has a Dragon and She isn’t Afraid to Useit. | Read more »
Mecha Showdown Review
Mecha Showdown Review By Lee Hamlet on February 27th, 2015 Our Rating: :: IN A SPINUniversal App - Designed for iPhone and iPad Mecha Showdown replaces traditional buttons with a slot machine mechanic in this robot fighting game,... | Read more »
Reliance Games and Dreamworks Unveil Rea...
Reliance Games and Dreamworks Unveil Real Steel Champions Posted by Ellis Spice on February 27th, 2015 [ permalink ] Reliance Games and Dreamworks have announced that a third game in | Read more »
Sum Idea Review
Sum Idea Review By Jennifer Allen on February 27th, 2015 Our Rating: :: TAXING NUMBERSUniversal App - Designed for iPhone and iPad Sum Idea is a fairly charming but taxing puzzle game.   | Read more »
A New Badland Update Brings Daydream Lev...
A New Badland Update Brings Daydream Levels to Co-Op Posted by Ellis Spice on February 27th, 2015 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Slashing Demons Review
Slashing Demons Review By Lee Hamlet on February 27th, 2015 Our Rating: :: IT'S A LONG WAY TO THE TOPUniversal App - Designed for iPhone and iPad Slashing Demons lacks the depth or scope to take it beyond the point of being just... | Read more »

Price Scanner via MacPrices.net

Apple CEO Tim Cook to Deliver 2015 George Was...
Apple CEO Tim Cook will deliver the George Washington University’s Commencement address to GWU grads on May 17, at which time he will also be awarded an honorary doctorate of public service from the... Read more
Apple restocks refurbished Mac minis for up t...
The Apple Store has restocked Apple Certified Refurbished 2014 Mac minis, with models available starting at $419. Apple’s one-year warranty is included with each mini, and shipping is free: - 1.4GHz... Read more
Save up to $50 on iPad Air 2s, NY tax only, f...
 B&H Photo has iPad Air 2s on sale for $50 off MSRP including free shipping plus NY sales tax only: - 16GB iPad Air 2 WiFi: $469.99 $30 off - 64GB iPad Air 2 WiFi: $549 $50 off - 128GB iPad Air 2... Read more
16GB iPad Air 2 on sale for $447, save $52
Walmart has the 16GB iPad Air 2 WiFi on sale for $446.99 on their online store for a limited time. Choose free shipping or free local store pickup (if available). Sale price for online orders only,... Read more
iMacs on sale for up to $205 off MSRP
B&H Photo has 21″ and 27″ iMacs on sale for up to $205 off MSRP including free shipping plus NY sales tax only: - 21″ 1.4GHz iMac: $1029 $70 off - 21″ 2.7GHz iMac: $1199 $100 off - 21″ 2.9GHz... Read more
Apple Takes 89 Percent Share of Global Smartp...
According to the latest research from Strategy Analytics, global smartphone operating profit reached US$21 billion in Q4 2014. The Android operating system captured a record-low 11 percent global... Read more
New Travel Health App “My Travel Health” iOS...
Rochester, Minnesota based Travel Health and Wellness LLC has announced that its new iOS app help safeguard the user’s health when traveling abroad — “My Travel Health” is now available on the Apple... Read more
Sale! MacBook Airs for up to $115 off MSRP
B&H Photo has MacBook Airs on sale for up to $100 off MSRP. Shipping is free, and B&H charges NY sales tax only: - 11″ 128GB MacBook Air: $799 100 off MSRP - 11″ 256GB MacBook Air: $999 $100... Read more
15-inch 2.0GHz Retina MacBook Pro (refurbishe...
The Apple Store has Apple Certified Refurbished previous-generation 15″ 2.0GHz Retina MacBook Pros available for $1489 including free shipping plus Apple’s standard one-year warranty. Their price is... Read more
Wither The iPad mini? End Of The Road Imminen...
AppleDailyReport’s Dennis Sellers predicts that the iPad mini is going to be left to wither on the vine, as it were, and then just allowed to fade away — a casualty of the IPhone 6 Plus and other... Read more

Jobs Board

Sr. Technical Services Consultant, *Apple*...
**Job Summary** Apple Professional Services (APS) has an opening for a senior technical position that contributes to Apple 's efforts for strategic and transactional Read more
Event Director, *Apple* Retail Marketing -...
…This senior level position is responsible for leading and imagining the Apple Retail Team's global engagement strategy and team. Delivering an overarching brand Read more
*Apple* Pay - Site Reliability Engineer - Ap...
**Job Summary** Imagine what you could do here. At Apple , great ideas have a way of becoming great products, services, and customer experiences very quickly. Bring Read more
*Apple* Solutions Consultant - Retail Sales...
**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
*Apple* Solutions Consultant - Retail Sales...
**Job Summary** As an Apple Solutions Consultant (ASC) you are the link between our customers and our products. Your role is to drive the Apple business in a retail Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.