Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
SimpleViewer.c
//-------------------------------------------------------------------------------------------- |
// simple viewer application |
// DEVELOPER SUPPORT May 95 |
// |
// This is a simple viewer application, that illustrates a minimal, but |
// functionally complete viewer application. |
// |
// Nick Thompson, Developer Support, Apple Computer (DEVSUPPORT), |
// ©1995, Apple Computer Inc., All Rights Reserved |
#include <AppleEvents.h> |
#include <menus.h> |
#include <PictUtils.h> |
#include <QDOffScreen.h> |
#include <Errors.h> |
#include "QD3D.h" |
#include "QD3DViewer.h" |
#include "QD3DGestalt.h" |
#include "QD3DViewerGestalt.h" |
//-------------------------------------------------------------------------------------------- |
// |
const int kWindowWidth = 220 ; |
const int kWindowHeight = 150 ; |
//-------------------------------------------------------------------------------------------- |
// |
#define HiWrd(aLong) (((aLong) >> 16) & 0xFFFF) |
#define LoWrd(aLong) ((aLong) & 0xFFFF) |
//-------------------------------------------------------------------------------------------- |
// menu id's |
enum { |
mApple = 128, |
mFile, |
mEdit |
} ; |
//-------------------------------------------------------------------------------------------- |
// command id's, Apple menu |
enum { |
iAbout = 1 |
} ; |
//-------------------------------------------------------------------------------------------- |
// command id's, File menu |
enum { |
iNew = 1, |
iOpen, |
iUnused1, |
iClose, |
iSave, |
iSaveAs, |
iRevert, |
iUnused2, |
iQuit |
} ; |
//-------------------------------------------------------------------------------------------- |
// command id's, Edit menu |
enum { |
iUndo = 1, |
iUnused3, |
iCut, |
iCopy, |
iPaste, |
iClear |
} ; |
//-------------------------------------------------------------------------------------------- |
// static control variables |
static Boolean gQuitFlag = false ; // we ain't quittin yet |
static Point gStaggerPos = {50,50} ; // start opening staggered windows at this point |
static AEAddressDesc gSelfAddress; // A self-addressed address descriptor record |
static ProcessSerialNumber gSelfPSN; // This application's psn |
//-------------------------------------------------------------------------------------------- |
// function prototypes |
Boolean SupportsQuickDraw3D(void) ; |
Boolean SupportsQuickDraw3DViewer(void) ; |
void InitToolbox( void ) ; |
void FailIfErr(OSErr something ) ; |
void MainEventLoop( void ) ; |
void HandleKeyPress( EventRecord *event ) ; |
Boolean HandleEvent( EventRecord *theEvent ) ; |
void HandleMenuCommand( long menuResult ) ; |
void MyAdjustMenus( void ) ; |
OSErr MyDisposeViewerWindow( WindowPtr theWindow ) ; |
CGrafPtr MyCreateViewerWindow( void ) ; |
//-- AppleEvent Related |
Boolean SupportsAEVT(void) ; |
void RegisterMyEvents(void) ; |
pascal OSErr MyAEHandleOAPP( AppleEvent *theAppleEvent, AppleEvent *reply, long refCon) ; |
pascal OSErr MyAEHandleODOC(AppleEvent *theAppleEvent, AppleEvent *reply, long refCon) ; |
pascal OSErr MyAEHandlePDOC(AppleEvent *theAppleEvent,AppleEvent *reply,long refCon) ; |
pascal OSErr MyAEHandleQUIT(AppleEvent *theAppleEvent,AppleEvent *reply,long refCon) ; |
void DoAppOpenCommand( void ) ; |
void MySendQuitApp( void ) ; |
void MySendOpenDoc(FSSpec *myFSSpec) ; |
//-------------------------------------------------------------------------------------------- |
// Constants |
const RGBColor kRGBBlack = { 0x0000, 0x0000, 0x0000 } ; |
const RGBColor kRGBWhite = { 0xFFFF, 0xFFFF, 0xFFFF } ; |
const int kMyAboutDialogID = 128 ; |
const int kMyFatalDialogID = 129 ; |
const int kQD3DAlertID = 27309 ; |
//-------------------------------------------------------------------------------------------- |
// Types |
typedef struct _viewerData { |
TQ3ViewerObject theViewer ; |
FSSpec theFile ; |
Boolean isFileValid ; |
} ViewerData, *ViewerDataPtr, **ViewerDataHandle ; |
//-------------------------------------------------------------------------------------------- |
// |
// |
main() |
{ |
MoreMasters(); MoreMasters() ; MoreMasters() ; |
MaxApplZone() ; // Maximise the heap - the viewer requires at least 32k |
InitToolbox() ; |
// WE DON'T CHECK FOR 68K machine. |
// Instead I use the NotPPC.rsrc resource file. This is a file with a 68k CODE 0 |
// and CODE 1 resource that puts up a dialog that says "this app only runs on a power |
// macintosh computer. |
if( SupportsAEVT() && SupportsQuickDraw3D() && SupportsQuickDraw3DViewer() ) { |
// AppleEvent stuff: |
// Set up the self-addressed descriptor record. |
gSelfPSN.highLongOfPSN = 0; |
gSelfPSN.lowLongOfPSN = kCurrentProcess; //* Use this instead of GetCurrentProcess *// |
FailIfErr(AECreateDesc(typeProcessSerialNumber,(Ptr)&gSelfPSN,sizeof(ProcessSerialNumber),&gSelfAddress)); |
RegisterMyEvents() ; // register the appleevents for this app |
MainEventLoop() ; // Handle events 'til we die |
} |
else { |
Str255 theString ; |
GetIndString(theString,kQD3DAlertID,3); |
ParamText( theString, 0L, 0L, 0L ) ; |
(void)Alert(kQD3DAlertID,nil); |
} |
} |
//--------------------------------------------------------------------- |
Boolean SupportsQuickDraw3D(void) |
{ |
OSErr err; |
long response; |
err = Gestalt(gestaltQD3D,&response); |
if (err!=noErr) |
return false; |
return (response && (response << gestaltQD3DAvailable)); |
} |
//--------------------------------------------------------------------- |
Boolean SupportsQuickDraw3DViewer(void) |
{ |
OSErr err; |
long response; |
err = Gestalt( gestaltQD3DViewer,&response ); |
if (err!=noErr) |
return false; |
return (response && ( response << gestaltQD3DViewerAvailable )); |
} |
//-------------------------------------------------------------------------------------------- |
// |
// |
void FailIfErr( OSErr something ) |
{ |
OSErr myErr ; |
if(( myErr = something) != noErr ) { |
ModalFilterUPP theProc ; |
DialogPtr theDialog ; |
short itemHit ; |
Str255 theError ; |
NumToString(something,theError); |
theDialog = GetNewDialog ( kMyFatalDialogID, nil, (WindowPtr)-1 ); |
// these two lil' snappers are system 7 only |
// so if you use them, check before!! |
// in this app we will only run on Power |
// Macintosh, so we don't check |
GetStdFilterProc( &theProc ) ; |
SetDialogDefaultItem(theDialog, ok) ; |
ParamText( theError, 0L, 0L, 0L ) ; |
// put the dialog up and loop 'til |
// the user hits the OK button |
do { |
ModalDialog ( theProc, &itemHit ); |
} while( itemHit != ok ) ; |
DisposeDialog ( theDialog ); |
ExitToShell() ; |
} |
} |
//-------------------------------------------------------------------------------------------- |
// |
// |
void InitToolbox() |
{ |
Handle menuBar = nil; |
InitGraf((Ptr) &qd.thePort); |
InitFonts(); |
InitWindows(); |
InitMenus(); |
TEInit(); |
InitDialogs((long)nil); |
InitCursor(); |
// initialize application globals |
gQuitFlag = false; |
menuBar = GetNewMBar(128); // Read menus into menu bar, MBAR res id is 128 |
if ( menuBar == nil ) |
ExitToShell(); // if we dont have it then quit - your app |
// needs a dialog here |
SetMenuBar(menuBar); // Install menus |
DisposeHandle(menuBar); |
AppendResMenu(GetMenuHandle(mApple), 'DRVR'); // Add DA names to Apple menu, ID 128 |
MyAdjustMenus() ; |
DrawMenuBar(); |
} |
//-------------------------------------------------------------------------------------------- |
// |
// |
void MainEventLoop() |
{ |
EventRecord event; |
WindowPtr theWindow; |
Boolean wasViewerEvent ; |
GrafPtr savedPort ; |
Point localPt ; |
TQ3ViewerObject theViewer ; |
ViewerDataHandle myData ; |
MyAdjustMenus() ; |
while( !gQuitFlag ) |
{ |
if (WaitNextEvent( everyEvent, &event, 0, nil )) |
{ |
if((theWindow = FrontWindow()) != nil ) { |
myData = (ViewerDataHandle)GetWRefCon(theWindow); |
theViewer = (**myData).theViewer; |
} |
if( theViewer ) { |
GetPort( &savedPort ) ; |
SetPort( (GrafPtr)theWindow ) ; |
GetMouse(&localPt); |
if (!Q3ViewerAdjustCursor(theViewer, &localPt)) |
InitCursor(); |
wasViewerEvent = Q3ViewerEvent ( theViewer, &event ); |
SetPort( savedPort ) ; |
} |
else |
wasViewerEvent = false ; |
// was it a viewer event???? |
if( !wasViewerEvent ) |
HandleEvent( &event ); |
} |
} |
} |
//---------------------------------------------------------------------------------- |
// HandleActivateWindow is called when an event is received that reports that |
// a window is being either activated or deactivated. |
static void HandleActivateWindow(WindowPtr theWindow, short activate) |
{ |
if (theWindow) { |
if (activate) { |
// do whatever else you'd like to do for a activate event |
LoadScrap() ; |
} else { |
// do whatever you'd like to do for a deactivate event |
UnloadScrap() ; |
} |
} |
} |
//-------------------------------------------------------------------------------------------- |
// |
// |
Boolean HandleEvent( EventRecord *theEvent ) |
{ |
short thePart; |
WindowPtr theWindow ; |
Rect screenRect; |
GrafPtr oldPort ; |
Point aPoint = {100, 100}; |
TQ3ViewerObject theViewer ; |
ViewerDataHandle myData ; |
switch (theEvent->what) { |
case mouseDown: |
thePart = FindWindow( theEvent->where, &theWindow ); |
switch( thePart ) { |
case inMenuBar: |
MyAdjustMenus() ; |
HandleMenuCommand(MenuSelect(theEvent->where)); |
break; |
case inDrag: |
screenRect = (**GetGrayRgn()).rgnBBox; |
DragWindow( theWindow, theEvent->where, &screenRect ); |
break ; |
case inContent: |
if (theWindow != FrontWindow()) |
SelectWindow( theWindow ); |
break ; |
case inGoAway: |
if (TrackGoAway( theWindow, theEvent->where )) { |
MyDisposeViewerWindow( theWindow ) ; |
} |
break ; |
default: |
break ; |
} |
break ; |
case updateEvt: |
theWindow = (WindowPtr)theEvent->message; |
myData = (ViewerDataHandle)GetWRefCon( theWindow ) ; |
theViewer = (**myData).theViewer ; |
GetPort(&oldPort ) ; |
SetPort( theWindow ); |
BeginUpdate( theWindow ); |
Q3ViewerDraw( theViewer ) ; |
EndUpdate( theWindow ); |
SetPort( oldPort ) ; |
break ; |
case keyDown: |
case autoKey: |
HandleKeyPress(theEvent); |
break; |
case diskEvt: |
if ( HiWrd(theEvent->message) != noErr ) |
(void) DIBadMount(aPoint, theEvent->message); |
break; |
case osEvt: |
break ; |
case activateEvt: |
if ((theWindow = (WindowPtr) theEvent->message) != nil) { |
HandleActivateWindow(theWindow, (theEvent->modifiers & activeFlag)); |
} |
break; |
case kHighLevelEvent: // Let the Apple Event Manager handle high level event. |
AEProcessAppleEvent(theEvent); |
break; |
} |
return true ; |
} |
//-------------------------------------------------------------------------------------------- |
// |
// |
void HandleKeyPress(EventRecord *event) |
{ |
char key; |
key = event->message & charCodeMask; |
// just check to see if we want to quit... |
if ( event->modifiers & cmdKey ) { /* Command key down? */ |
HandleMenuCommand(MenuKey(key)); |
} |
} |
//-------------------------------------------------------------------------------------------- |
// |
// |
static void HandleAboutApp( void ) |
{ |
ModalFilterUPP theProc ; |
DialogPtr theDialog ; |
short itemHit ; |
theDialog = GetNewDialog ( kMyAboutDialogID, nil, (WindowPtr)-1 ); |
// these two lil' snappers are system 7 only |
// so if you use them, check before!! |
// in this app we will only run on Power |
// Macintosh, so we don't check |
GetStdFilterProc( &theProc ) ; |
SetDialogDefaultItem(theDialog, ok) ; |
// put the dialog up and loop 'til |
// the user hits the OK button |
do { |
ModalDialog ( theProc, &itemHit ); |
} while( itemHit != ok ) ; |
DisposeDialog ( theDialog ); |
} |
//-------------------------------------------------------------------------------------------- |
// |
// |
static OSErr HandleOpenDoc(FSSpec *theFile) |
{ |
OSErr err ; |
short theRef ; |
ViewerDataHandle myData ; |
TQ3ViewerObject theViewer ; |
WindowPtr theWindow ; |
// display the contents |
theWindow = (WindowPtr)MyCreateViewerWindow() ; |
// open the file |
err = FSpOpenDF( theFile, fsRdPerm, &theRef ) ; |
if (err == noErr) |
{ |
myData = (ViewerDataHandle)GetWRefCon( theWindow ) ; |
theViewer = (**myData).theViewer ; |
(**myData).theFile = *theFile ; |
(**myData).isFileValid = true ; |
Q3ViewerUseFile(theViewer, theRef) ; |
err = FSClose(theRef) ; |
} |
// set the window title |
SetWTitle( theWindow, theFile->name ); |
MyAdjustMenus() ; |
return err ; |
} |
//-------------------------------------------------------------------------------------------- |
// |
// |
void HandleMenuCommand(long menuResult) |
{ |
short menuID; |
short menuItem; |
Str255 daName; |
short numTypes = 2 ; |
SFTypeList myTypes = { '3DMF', 'TEXT', 0 } ; |
OSErr err ; |
short theRef ; |
ViewerDataHandle myData ; |
TQ3ViewerObject theViewer ; |
WindowPtr theWindow ; |
GrafPtr savedPort ; |
FSSpec theFile ; |
StandardFileReply theSFReply ; |
menuID = HiWrd(menuResult); |
menuItem = LoWrd(menuResult); |
switch ( menuID ) { |
// |
//-------------------------------------------------------------------------- |
// |
case mApple: |
switch ( menuItem ) { |
case iAbout: |
HandleAboutApp() ; |
break ; |
default: |
GetMenuItemText(GetMenuHandle(mApple), menuItem, daName); |
(void) OpenDeskAcc(daName); |
break; |
} |
break; |
// |
//-------------------------------------------------------------------------- |
// |
case mFile: |
switch ( menuItem ) { |
case iNew: |
// display the contents |
(void)MyCreateViewerWindow() ; |
break ; |
case iOpen: |
// Get the file name to open |
StandardGetFile( nil, numTypes, myTypes, &theSFReply ) ; |
// did the user cancel, if not open the file? |
if(theSFReply.sfGood) |
MySendOpenDoc(&theSFReply.sfFile) ; |
break ; |
case iRevert: |
// we know this can't be called as long as there |
// is an app window open (MyAdjustMenus) so get the refcon |
// from the front window and get the FSSpec from that |
theWindow = FrontWindow() ; |
myData = (ViewerDataHandle)GetWRefCon( theWindow ) ; |
theFile = (**myData).theFile ; |
// open the file and read it back into the viewer |
err = FSpOpenDF( &theFile, fsRdPerm, &theRef ) ; |
if (err == noErr) |
{ |
theViewer = (**myData).theViewer ; |
Q3ViewerUseFile(theViewer, theRef) ; |
err = FSClose(theRef) ; |
} |
GetPort( &savedPort ) ; |
SetPort((GrafPtr)theWindow) ; |
InvalRect( &theWindow->portRect ) ; |
SetPort( savedPort ) ; |
break ; |
case iSave: |
// we know this can't be called as long as there |
// is an app window open (MyAdjustMenus) so get the refcon |
// from the front window and get the FSSpec from that |
theWindow = FrontWindow() ; |
myData = (ViewerDataHandle)GetWRefCon( theWindow ) ; |
theFile = (**myData).theFile ; |
theViewer = (**myData).theViewer ; |
// assumes the original file still exists |
err = FSpOpenDF(&theFile, fsWrPerm, &theRef); |
if (err == noErr) |
{ |
Q3ViewerWriteFile(theViewer, theRef); |
err = FSClose(theRef); |
} |
break ; |
case iSaveAs: |
// we know this can't be called as long as there |
// is an app window open (MyAdjustMenus) so get the refcon |
// from the front window and get the FSSpec from that |
theWindow = FrontWindow() ; |
myData = (ViewerDataHandle)GetWRefCon( theWindow ) ; |
theViewer = (**myData).theViewer ; |
StandardPutFile("\pSave model as:", "\pUntitled", &theSFReply); |
if (theSFReply.sfGood) |
{ |
err = FSpOpenDF(&theSFReply.sfFile, fsWrPerm, &theRef); |
if (err != noErr) |
{ |
err = FSpCreate(&theSFReply.sfFile, '????', '3DMF', theSFReply.sfScript); |
if (err == noErr) |
err = FSpOpenDF(&theSFReply.sfFile, fsCurPerm, &theRef); |
} |
if (err == noErr) |
{ |
Q3ViewerWriteFile(theViewer, theRef); |
err = FSClose(theRef); |
} |
// set up our record of the file location, |
// update the structure |
theWindow = FrontWindow() ; |
myData = (ViewerDataHandle)GetWRefCon( theWindow ) ; |
theViewer = (**myData).theViewer ; |
(**myData).theFile = theSFReply.sfFile ; |
(**myData).isFileValid = true ; |
// reset the window title |
SetWTitle( theWindow, theSFReply.sfFile.name ); |
} |
break; |
case iClose: |
MyDisposeViewerWindow ( FrontWindow() ); |
break ; |
case iQuit: |
MySendQuitApp(); |
break; |
} |
break; |
// |
//-------------------------------------------------------------------------- |
// |
case mEdit: |
// display the contents |
theWindow = FrontWindow() ; |
myData = (ViewerDataHandle)GetWRefCon( theWindow ) ; |
theViewer = (**myData).theViewer ; |
switch(menuItem) |
{ |
case iCut: |
Q3ViewerCut(theViewer); |
break; |
case iCopy: |
Q3ViewerCopy(theViewer); |
break; |
case iPaste: |
Q3ViewerPaste(theViewer); |
break; |
case iClear: |
Q3ViewerClear(theViewer); |
break; |
default: |
break; |
} |
break; |
} |
HiliteMenu(0); // Unhighlight whatever MenuSelect or MenuKey hilited |
} |
//-------------------------------------------------------------------------------------------- |
// |
// |
void MyAdjustMenus( void ) |
{ |
WindowPtr theWindow ; |
ViewerDataHandle myData ; |
MenuHandle theMenu ; |
theWindow = FrontWindow() ; |
if( theWindow != nil ) { |
theMenu = GetMenuHandle ( mFile ) ; |
EnableItem ( theMenu, iClose ); |
EnableItem ( theMenu, iSaveAs ); |
myData = (ViewerDataHandle)GetWRefCon( theWindow ) ; |
if( (**myData).isFileValid) { |
EnableItem ( theMenu, iSave ); |
EnableItem (theMenu, iRevert ); |
} |
else { |
DisableItem ( theMenu, iSave ); |
DisableItem ( theMenu, iRevert ); |
} |
EnableItem ( GetMenuHandle ( mEdit ), 0 ); |
} |
else { |
theMenu = GetMenuHandle ( mFile ) ; |
DisableItem ( theMenu, iClose ); |
DisableItem ( theMenu, iRevert ); |
DisableItem ( theMenu, iSave ); |
DisableItem ( theMenu, iSaveAs ); |
DisableItem ( GetMenuHandle ( mEdit ), 0 ); |
} |
// we don't support undo |
DisableItem ( GetMenuHandle ( mEdit ), iUndo ); |
DrawMenuBar() ; |
} |
//-------------------------------------------------------------------------------------------- |
// |
// |
OSErr MyDisposeViewerWindow( WindowPtr theWindow ) |
{ |
TQ3ViewerObject theViewer ; |
ViewerDataHandle myData ; |
if( theWindow == nil) |
return paramErr ; |
myData = (ViewerDataHandle)GetWRefCon( theWindow ) ; |
theViewer = (**myData).theViewer ; |
DisposeHandle((Handle)myData); |
DisposeWindow(theWindow); |
MyAdjustMenus() ; |
return Q3ViewerDispose(theViewer); |
} |
//-------------------------------------------------------------------------------------------- |
// |
// |
CGrafPtr MyCreateViewerWindow( ) |
{ |
Rect theRect ; |
GrafPtr savedPort ; |
TQ3ViewerObject myViewerObj ; |
WindowPtr theWindow ; |
ViewerDataHandle myData = (ViewerDataHandle)NewHandle(sizeof(ViewerData)) ; |
GetPort( &savedPort ) ; |
// set the new rect up with a stagger for multiple windows |
SetRect( &theRect, |
gStaggerPos.h, |
gStaggerPos.v, |
gStaggerPos.h + kWindowWidth, |
gStaggerPos.v + kWindowHeight ); |
gStaggerPos.h += 16 ; |
gStaggerPos.v += 16 ; // this is not "real staggering code, it don't wrap ; |
theWindow = NewCWindow( nil, |
&theRect, |
"\pUntitled", |
false, |
documentProc, |
(WindowPtr)-1, |
true, |
0L ); |
SetPort( (GrafPtr)theWindow ) ; |
// set up the viewer object here |
myViewerObj = Q3ViewerNew ((CGrafPtr)theWindow, &theWindow->portRect, kQ3ViewerDefault) ; |
//stuff the reference to the viewer in the RefCon field of the Window |
(**myData).theViewer = myViewerObj ; |
(**myData).isFileValid = false ; |
SetWRefCon( theWindow, (long)myData ); |
// make sure it is visible |
ShowWindow( theWindow ) ; |
SetPort( savedPort ) ; |
return (CGrafPtr)theWindow ; |
} |
//----------------------------------------------------------------------- |
// returns true if the platform supports appleevents - we won't run |
// if it doesn't |
Boolean SupportsAEVT(void) |
{ |
OSErr err; |
long response; |
err = Gestalt(gestaltAppleEventsAttr,&response); |
if (err!=noErr) |
return false; |
return (response && (response << gestaltAppleEventsPresent)); |
} |
//----------------------------------------------------------------------- |
// called to register our appleevent handlers |
void RegisterMyEvents(void) |
{ |
OSErr err; |
if (!SupportsAEVT()) |
return; |
err = AEInstallEventHandler(kCoreEventClass,kAEOpenApplication,NewAEEventHandlerProc(MyAEHandleOAPP),0L,false); |
if (err!=noErr) |
return; |
err = AEInstallEventHandler(kCoreEventClass,kAEOpenDocuments,NewAEEventHandlerProc(MyAEHandleODOC),0L,false); |
if (err!=noErr) |
return; |
err = AEInstallEventHandler(kCoreEventClass,kAEPrintDocuments,NewAEEventHandlerProc(MyAEHandlePDOC),0L,false); |
if (err!=noErr) |
return; |
err = AEInstallEventHandler(kCoreEventClass,kAEQuitApplication,NewAEEventHandlerProc(MyAEHandleQUIT),0L,false); |
if (err!=noErr) |
return; |
} |
//----------------------------------------------------------------------- |
// open application event handler for the core event suite, |
// by default we just want a blank new document |
pascal OSErr MyAEHandleOAPP( AppleEvent *theAppleEvent, AppleEvent *reply, long refCon) |
{ |
// we don't actually do anything on open - you could, |
// for example you might want to open a blank untitled |
// window |
OSErr err = noErr ; |
return err; |
} |
//----------------------------------------------------------------------- |
// handler for the open document appleevent handler |
pascal OSErr MyAEHandleODOC(AppleEvent *theAppleEvent, AppleEvent *reply, long refCon) |
{ |
FSSpec myFSS; |
AEDescList docList; |
OSErr err, |
ignoreErr; |
long index, |
itemsInList; |
Size actualSize; |
AEKeyword keywd; |
DescType returnedType; |
err = AEGetParamDesc(theAppleEvent,keyDirectObject,typeAEList,&docList); |
if (err == noErr) { |
// see how many descriptor items are in the list |
// this is the number of documents we want to open |
err = AECountItems(&docList,&itemsInList); |
// now get each descriptor record from the list |
// coerce the returned data to an FSSpec record, and |
// open the asoociated file |
for (index=1; index <= itemsInList && err == noErr; index++) { |
err = AEGetNthPtr( &docList, |
index, |
typeFSS, |
&keywd, |
&returnedType, |
(Ptr)&myFSS, |
sizeof(myFSS), |
&actualSize); |
if (err == noErr) { |
FInfo fndrInfo ; |
// we now have a valid FSSpec to reference the file, we need to know |
// what type the file is to determine which file open function to call |
// we can determine this from the finder info for the file |
err = FSpGetFInfo( &myFSS, &fndrInfo ); |
// if we got that ok, then we switch on the file |
// type (we don't care about the creator type) |
if (err == noErr) { |
switch( fndrInfo.fdType ) { |
case 'TEXT': |
case '3DMF': |
err = HandleOpenDoc(&myFSS); |
break ; |
} |
} |
} |
} |
ignoreErr = AEDisposeDesc(&docList); |
} |
return err ; |
} |
//----------------------------------------------------------------------- |
// handler for the print document event handler |
pascal OSErr MyAEHandlePDOC(AppleEvent *theAppleEvent,AppleEvent *reply,long refCon) |
{ |
FSSpec myFSS; |
AEDescList docList; |
OSErr err; |
long index, |
itemsInList; |
Size actualSize; |
AEKeyword keywd; |
DescType returnedType; |
err = AEGetParamDesc(theAppleEvent,keyDirectObject,typeAEList,&docList); |
if (err == noErr) { |
// see how many descriptor items are in the list |
// this is the number of documents we want to open |
err = AECountItems(&docList,&itemsInList); |
// now get each descriptor record from the list |
// coerce the returned data to an FSSpec record, and |
// open the asoociated file |
for (index=1; index <= itemsInList && err == noErr; index++) { |
err = AEGetNthPtr( &docList, |
index, |
typeFSS, |
&keywd, |
&returnedType, |
(Ptr)&myFSS, |
sizeof(myFSS), |
&actualSize); |
if (err == noErr) { |
// err = HandlePrintDoc( &myFSS ); |
err = errAEEventNotHandled ; // we don't do this yet... |
} |
} |
err = AEDisposeDesc(&docList); |
} |
return err ; |
} |
//----------------------------------------------------------------------- |
// quit appleevent handler |
pascal OSErr MyAEHandleQUIT(AppleEvent *theAppleEvent,AppleEvent *reply,long refCon) |
{ |
OSErr err = noErr ; // used as return value |
WindowPtr theWindow ; |
Boolean quitting = true ; |
// close all windows and signal to Quit |
// attempt to close all documents |
while(( theWindow = FrontWindow()) != nil && quitting ) |
quitting = (MyDisposeViewerWindow( theWindow ) == noErr); |
// if we closed everything up successfully, we can return noErr, otherwise |
// indicate to sender of the 'quit' aevt that we canceled |
if (quitting) { |
gQuitFlag = true; // user didn't cancel |
AEDisposeDesc(&gSelfAddress); // Dispose of my self-addressed descriptor. |
} |
else { |
err = userCanceledErr ; |
} |
return err ; |
} |
//----------------------------------------------------------------------------------// |
// Send a Quit Application Apple Event to myself to terminate this app. |
void MySendQuitApp( void ) |
{ |
AppleEvent myAppleEvent, reply; |
// Create the Apple Event. |
FailIfErr(AECreateAppleEvent( kCoreEventClass, |
kAEQuitApplication, |
&gSelfAddress, |
kAutoGenerateReturnID, |
kAnyTransactionID, |
&myAppleEvent)); |
// Send the Apple Event. |
FailIfErr(AESend( &myAppleEvent, |
&reply, |
kAENoReply+kAENeverInteract, |
kAENormalPriority, |
kAEDefaultTimeout, |
nil, |
nil)); |
AEDisposeDesc(&myAppleEvent); // Dispose of the Apple Event. |
} // MySendQuitApp |
//----------------------------------------------------------------------------------// |
// Send a Open Document Application Apple Event to myself to open a document. |
void MySendOpenDoc(FSSpec *myFSSpec) |
{ |
AppleEvent myAppleEvent; |
AppleEvent defReply; |
AEDescList docList; |
OSErr myErr; |
OSErr ignoreErr; |
myAppleEvent.dataHandle = nil; |
docList.dataHandle = nil; |
defReply.dataHandle = nil; |
// Create empty list and add one file spec |
FailIfErr(AECreateList(nil,0,false, &docList)); |
FailIfErr(AEPutPtr(&docList,1,typeFSS,(Ptr)myFSSpec,sizeof(FSSpec))); |
FailIfErr(AECreateAppleEvent( kCoreEventClass, |
kAEOpenDocuments, |
&gSelfAddress, |
kAutoGenerateReturnID, |
kAnyTransactionID, |
&myAppleEvent)); |
// Put Params into our event and send it |
FailIfErr(AEPutParamDesc( &myAppleEvent, |
keyDirectObject, |
&docList)); |
FailIfErr(AESend( &myAppleEvent, |
&defReply, |
kAENoReply+kAENeverInteract, |
kAENormalPriority, |
kAEDefaultTimeout, |
nil, |
nil)); |
if (myAppleEvent.dataHandle) |
ignoreErr = AEDisposeDesc(&myAppleEvent); |
if (docList.dataHandle) |
ignoreErr = AEDisposeDesc(&docList); |
} // MySendOpenDoc |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14