TweetFollow Us on Twitter

MACINTOSH C

Demonstration Program

Go to Contents
// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
// AppleEvents.c
// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
// 
// This program:
//
// „  Installs handlers for the required Apple events and Appearance Manager Apple 
//    events.
//
// „  Responds to the receipt of required Apple events by displaying descriptive text in
//    a window opened for that purpose, and by opening simulated document windows as
//    appropriate.  These responses result from the user:
//
//    „    Double clicking on the application's icon, or selecting the icon and choosing
//        Open from the Finder's File menu, thus causing the receipt of an Open
//        Application event.
//
//    „    When the application is already open, double clicking on the application's 
//        icon, or selecting the icon and choosing Open from the Finder's File menu, 
//        thus causing the receipt of a Re-open  Application event.
//
//    „    Double clicking on one of the document icons, selecting one or both of the
//        document icons and choosing Open from the Finder's File menu, or dragging one
//        or both of the document icons onto the application's icon, thus causing the
//        receipt of an Open Documents event.
//
//    „    Selecting one or both of the document icons and choosing Print from the
//        Finder's file menu, thus causing the receipt of a Print Documents event and,
//        if the application is not already running, a subsequent Quit Application event.
//
//    „    While the application is running, choosing Shut Down or Restart from the
//        Finder's Special menu, thus causing the receipt of a Quit Application event.   
//
// „  Responds to the receipt of Appearance Manager Apple events by displaying 
//    descriptive text.
//
// The program, which is intended to be run as a built application rather than within
// CodeWarrior, utilises the following resources:
//
// „  'WIND' resources (purgeable, initially visible) for the descriptive text display
//    window and simulated document windows.
//
// „  'MBAR' and 'MENU' resources (preload, non-purgeable).
//
// „  'STR#' resources (purgeable) for displaying error messages using StandardAlert.
//
// „  'ICN#', 'ics#', 'ics4', 'ics8', 'icl4', and 'icl8' resources (that is, an icon
//    family) for the application and for the application's documents. (Purgeable.)
//
// „  'FREF' resources (non-purgeable) for the application and the application's 'TEXT'
//    documents, which link the icons with the file types they represent, and which allow
//    users to launch the application by dragging the document icons to the application
//    icon.  
//
// „  The application's signature resource (non-purgeable), which enables the Finder to
//    identify and start up the application when the user double clicks the application's
//    document icons.  
//
// „  A 'BNDL' resource (non-purgeable), which groups together the application's
//    signature, icon and 'FREF' resources.  
//
// „  A 'hfdr' resource (purgeable), which provides the customised finder icon help 
//    override help balloon for the  application icon. 
//
// „  A 'vers' resource (purgeable), which provides version information via the 
//    information window and the Version column in list view windows.
//
// „  A 'SIZE' resource with the isHighLevelEventAware,  acceptSuspendResumeEvents, and
//    and is32BitCompatible flags set.
//
// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××

// ............................................................................. includes

#include <Appearance.h>
#include <AERegistry.h>
#include <Devices.h>
#include <Dialogs.h>
#include <Gestalt.h>
#include <ToolUtils.h>

// .............................................................................. defines

#define rMenubar              128
#define mApple                128
#define mFile                 129
#define  iQuit                11
#define rDisplayWindow        128
#define rDocWindow            129
#define rErrorStrings         128
#define eInstallHandler       1
#define eGetRequiredParam     2
#define eGetDescriptorRecord  3
#define eMissedRequiredParam  4
#define eCannotOpenFile       5
#define eCannotPrintFile      6
#define eCannotOpenWindow     7
#define eMenus                8  
#define MIN(a,b)              ((a) < (b) ? (a) : (b))

// ..................................................................... global variables

AEEventHandlerUPP  doOpenAppEventUPP;
AEEventHandlerUPP  doReopenAppEventUPP;
AEEventHandlerUPP  doOpenDocsEventUPP;
AEEventHandlerUPP  doPrintDocsEventUPP;
AEEventHandlerUPP  doQuitAppEventUPP;

AEEventHandlerUPP  doAppearanceChangeUPP;
AEEventHandlerUPP  doSysFontChangeUPP;
AEEventHandlerUPP  doSmallSysFontChangeUPP;
AEEventHandlerUPP  doViewsFontChangeUPP;

Boolean    gMacOS85Present     = false;
WindowPtr  gWindowPtr;
Boolean    gDone;
Boolean    gApplicationWasOpen = false;
WindowPtr  gWindowPtrs[10];
SInt16     gNumberOfWindows    = 0;

// .................................................................. function prototypes

void          main                      (void);
void          doInitManagers            (void);
void          doInstallAEHandlers       (void);
void          doEvents                  (EventRecord *);
pascal OSErr  doOpenAppEvent            (AppleEvent *,AppleEvent *,SInt32);
pascal OSErr  doReopenAppEvent          (AppleEvent *,AppleEvent *,SInt32);
pascal OSErr  doOpenDocsEvent           (AppleEvent *,AppleEvent *,SInt32);
pascal OSErr  doPrintDocsEvent          (AppleEvent *,AppleEvent *,SInt32);
pascal OSErr  doQuitAppEvent            (AppleEvent *,AppleEvent *,SInt32);
pascal OSErr  doAppearanceChangeEvent   (AppleEvent *,AppleEvent *,SInt32);
pascal OSErr  doSysFontChangeEvent      (AppleEvent *,AppleEvent *,SInt32);
pascal OSErr  doSmallSysFontChangeEvent (AppleEvent *,AppleEvent *,SInt32);
pascal OSErr  doViewsFontChangeEvent    (AppleEvent *,AppleEvent *,SInt32);
OSErr         doHasGotRequiredParams    (AppleEvent *);
Boolean       doOpenFile                (FSSpec *,SInt32,SInt32);
Boolean       doPrintFile               (FSSpec *,SInt32,SInt32);
void          doPrepareToTerminate      (void);
WindowPtr     doNewWindow               (void);
void          doMenuChoice              (SInt32);
void          doErrorAlert              (SInt16);
void          doDrawText                (Str255);
void          doConcatPStrings          (Str255,Str255);

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× main

void  main(void)
{
  OSErr       osError;
  SInt32      response;
  EventRecord EventStructure;
  Handle      menubarHdl;
  MenuHandle  menuHdl;
  RGBColor    foreColour = { 0xFFFF,0xFFFF,0xFFFF };
  RGBColor    backColour = { 0x4444,0x4444,0x9999 };

  // ................................................................ initialise managers

  doInitManagers();
  
  // ....................................... check whether Mac OS 8.5 or later is present

  osError = Gestalt(gestaltSystemVersion,&response);
  
  if(osError == noErr && response >= 0x00000850)
    gMacOS85Present = true;

  // ......................... create routine descriptors (required Apple event handlers)

  doOpenAppEventUPP    = NewAEEventHandlerProc((ProcPtr) doOpenAppEvent);
  doReopenAppEventUPP  = NewAEEventHandlerProc((ProcPtr) doReopenAppEvent);
  doOpenDocsEventUPP   = NewAEEventHandlerProc((ProcPtr) doOpenDocsEvent);
  doPrintDocsEventUPP  = NewAEEventHandlerProc((ProcPtr) doPrintDocsEvent);
  doQuitAppEventUPP    = NewAEEventHandlerProc((ProcPtr) doQuitAppEvent);

  // ................ create routine descriptor (Appearance Manager Apple event handlers)

  doAppearanceChangeUPP    = NewAEEventHandlerProc((ProcPtr) doAppearanceChangeEvent);
  
  if(gMacOS85Present)
  {
    doSysFontChangeUPP       = NewAEEventHandlerProc((ProcPtr) doSysFontChangeEvent);
    doSmallSysFontChangeUPP  = NewAEEventHandlerProc((ProcPtr) doSmallSysFontChangeEvent);
    doViewsFontChangeUPP     = NewAEEventHandlerProc((ProcPtr) doViewsFontChangeEvent);
  }
  
  // ...................................................................... open a window
  
  if(!(gWindowPtr = GetNewCWindow(rDisplayWindow,NULL,(WindowPtr) -1)))
  {
    doErrorAlert(eCannotOpenWindow);
    ExitToShell();
  }

  SetPort(gWindowPtr);
  TextSize(10);
  TextFace(bold);
  RGBBackColor(&backColour);
  RGBForeColor(&foreColour);
  EraseRect(&gWindowPtr->portRect);

  // .......................................................... set up menu bar and menus
  
  if(!(menubarHdl = GetNewMBar(rMenubar)))
    doErrorAlert(eMenus);
  SetMenuBar(menubarHdl);
  DrawMenuBar();

  if(!(menuHdl = GetMenuHandle(mApple)))
    doErrorAlert(eMenus);
  else
    AppendResMenu(menuHdl,'DRVR');

  // ....................................................... install Apple event handlers

  doInstallAEHandlers();

  // ......................................................................... event loop
  
  gDone = false;

  while(!gDone)
  {
    if(WaitNextEvent(everyEvent,&EventStructure,180,NULL))
      doEvents(&EventStructure);
  }
}

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doInitManagers

void  doInitManagers(void)
{
  MaxApplZone();
  MoreMasters();

  InitGraf(&qd.thePort);
  InitFonts();
  InitWindows();
  InitMenus();
  TEInit();
  InitDialogs(NULL);

  InitCursor();  
  FlushEvents(everyEvent,0);

  RegisterAppearanceClient();
}

// ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doInstallAEHandlers

void  doInstallAEHandlers(void)
{
  OSErr  osErr;

  // .............................................................. required Apple events

  osErr = AEInstallEventHandler(kCoreEventClass,kAEOpenApplication,doOpenAppEventUPP,
                                0L,false);
  if(osErr != noErr)  doErrorAlert(eInstallHandler);

  osErr = AEInstallEventHandler(kCoreEventClass,kAEReopenApplication,doReopenAppEventUPP,
                                0L,false);
  if(osErr != noErr)  doErrorAlert(eInstallHandler);

  osErr = AEInstallEventHandler(kCoreEventClass,kAEOpenDocuments,doOpenDocsEventUPP,
                                0L,false);
  if(osErr != noErr)  doErrorAlert(eInstallHandler);

  osErr = AEInstallEventHandler(kCoreEventClass,kAEPrintDocuments,doPrintDocsEventUPP,
                                0L,false);
  if(osErr != noErr)  doErrorAlert(eInstallHandler);

  osErr = AEInstallEventHandler(kCoreEventClass,kAEQuitApplication,doQuitAppEventUPP,
                                0L,false);
  if(osErr != noErr)  doErrorAlert(eInstallHandler);

  // .................................................... Appearance Manager Apple events

  osErr = AEInstallEventHandler(kAppearanceEventClass,kAEAppearanceChanged,
                                doAppearanceChangeUPP,0L,false);
  if(osErr != noErr)  doErrorAlert(eInstallHandler);

  if(gMacOS85Present)
  {
    osErr = AEInstallEventHandler(kAppearanceEventClass,kAESystemFontChanged,
                                  doSysFontChangeUPP,0L,false);
    if(osErr != noErr)  doErrorAlert(eInstallHandler);

    osErr = AEInstallEventHandler(kAppearanceEventClass,kAESmallSystemFontChanged,
                                  doSmallSysFontChangeUPP,0L,false);
    if(osErr != noErr)  doErrorAlert(eInstallHandler);

    osErr = AEInstallEventHandler(kAppearanceEventClass,kAEViewsFontChanged,
                                  doViewsFontChangeUPP,0L,false);
    if(osErr != noErr)  doErrorAlert(eInstallHandler);
  }
}

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doEvents

void  doEvents(EventRecord *eventStrucPtr)
{
  SInt16     partCode;
  WindowPtr  windowPtr;
  SInt32     menuChoice;
  SInt8      charCode;

  switch(eventStrucPtr->what)
  {
    case kHighLevelEvent:
      AEProcessAppleEvent(eventStrucPtr);
      break;

    case mouseDown:
      partCode = FindWindow(eventStrucPtr->where,&windowPtr);
      switch(partCode)
      {
        case inMenuBar:
          menuChoice = MenuSelect(eventStrucPtr->where);
          doMenuChoice(menuChoice);
          break;

        case inDrag:
          DragWindow(windowPtr,eventStrucPtr->where,&qd.screenBits.bounds);
          break;
      }
      break;

    case keyDown:
    case autoKey:
      charCode = eventStrucPtr->message & charCodeMask;
      if((eventStrucPtr->modifiers & cmdKey) != 0)
        doMenuChoice(MenuEvent(eventStrucPtr));
      break;

    case updateEvt:
      BeginUpdate((WindowPtr)eventStrucPtr->message);
      EndUpdate((WindowPtr)eventStrucPtr->message);
      break;

    case activateEvt:
      if(FrontWindow() == gWindowPtr)
        EraseRect(&gWindowPtr->portRect);
      break;

    case osEvt:
      HiliteMenu(0);
      break;
  }
}
  
// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doOpenAppEvent

pascal OSErr  doOpenAppEvent(AppleEvent *appEvent,AppleEvent *reply,SInt32 handlerRefCon)
{
  OSErr      osErr;
  WindowPtr  windowPtr;

  gApplicationWasOpen = true;

  osErr = doHasGotRequiredParams(appEvent);

  if(osErr == noErr)
  {
    doDrawText("\pReceived an Apple event: OPEN APPLICATION.");
    doDrawText("\p    „ Opening an untitled window in response.");

    windowPtr = doNewWindow();
    SetWTitle(windowPtr,"\pUntitled 1");

    return(noErr);
  }
  else
    return(osErr);
}

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doReopenAppEvent

pascal OSErr  doReopenAppEvent(AppleEvent *appEvent,AppleEvent *reply,
                               SInt32 handlerRefCon)
{
  OSErr      osErr;
  WindowPtr  windowPtr;

  osErr = doHasGotRequiredParams(appEvent);

  if(osErr == noErr)
  {
    doDrawText("\pReceived an Apple event: RE-OPEN APPLICATION.");
    doDrawText("\p    „ I will check whether I have any windows open.");
    doDrawText("\p      If no windows are open, I will open a window.");

    if(!FrontWindow())
    {
      windowPtr = doNewWindow();
      SetWTitle(windowPtr,"\pUntitled 1");
    }

    return(noErr);
  }
  else
    return(osErr);
}

// ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doOpenDocsEvent

pascal OSErr  doOpenDocsEvent(AppleEvent *appEvent,AppleEvent *reply,SInt32 handlerRefcon)
{
  AEDescList  docList;
  OSErr       osErr, ignoreErr;
  SInt32      numberOfItems, index;
  DescType    returnedType;
  FSSpec      fileSpec;
  AEKeyword   keyWord;
  Size        actualSize;
  Boolean     result;

  osErr = AEGetParamDesc(appEvent,keyDirectObject,typeAEList,&docList);

  if(osErr == noErr)
  {
    osErr = doHasGotRequiredParams(appEvent);
    if(osErr == noErr)
    {
      AECountItems(&docList,&numberOfItems);
      if(osErr == noErr)
      {
        for(index=1;index<=numberOfItems;index++)
        {
          osErr = AEGetNthPtr(&docList,index,typeFSS,&keyWord,&returnedType,
                              (Ptr) &fileSpec,sizeof(fileSpec),&actualSize);
          if(osErr == noErr)
          {
            if(!(result = doOpenFile(&fileSpec,index,numberOfItems)))
              doErrorAlert(eCannotOpenFile);
          }
          else
            doErrorAlert(eGetDescriptorRecord);
        }
      }
    }
    else
      doErrorAlert(eMissedRequiredParam);

    ignoreErr = AEDisposeDesc(&docList);
  }
  else
    doErrorAlert(eGetRequiredParam);

  return(osErr);
}

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doPrintDocsEvent

pascal OSErr  doPrintDocsEvent(AppleEvent *appEvent,AppleEvent *reply,SInt32 handlerRefcon)
{
  AEDescList  docList;
  OSErr       osErr, ignoreErr;
  SInt32      numberOfItems, index;
  DescType    returnedType;
  FSSpec      fileSpec;
  AEKeyword   keyWord;
  Size        actualSize;
  Boolean     result;
  
  osErr = AEGetParamDesc(appEvent,keyDirectObject,typeAEList,&docList);

  if(osErr == noErr)
  {
    osErr = doHasGotRequiredParams(appEvent);
    if(osErr == noErr)
    {
      AECountItems(&docList,&numberOfItems);
      if(osErr == noErr)
      {
        for(index=1;index<=numberOfItems;index++)
        {
          osErr = AEGetNthPtr(&docList,index,typeFSS,&keyWord,&returnedType,
                              (Ptr) &fileSpec,sizeof(fileSpec),&actualSize);
          if(osErr == noErr)
          {
            if(!(result = doPrintFile(&fileSpec,index,numberOfItems)))
              doErrorAlert(eCannotPrintFile);
          }
          else
            doErrorAlert(eGetDescriptorRecord);
        }
      }
    }
    else
      doErrorAlert(eMissedRequiredParam);

    ignoreErr = AEDisposeDesc(&docList);
  }
  else
    doErrorAlert(eGetRequiredParam);

  return(osErr);
}

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doQuitAppEvent

pascal OSErr  doQuitAppEvent(AppleEvent *appEvent,AppleEvent *reply,SInt32 handlerRefcon)
{
  OSErr  osErr;

  osErr = doHasGotRequiredParams(appEvent);

  if(osErr == noErr)
  {
    doPrepareToTerminate();
    return(noErr);
  }
  else
    return(osErr);
}

// ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doAppearanceChangeEvent

pascal OSErr  doAppearanceChangeEvent(AppleEvent *appEvent,AppleEvent *reply,
                                      SInt32 handlerRefcon)
{
  OSErr  osErr;

  osErr = doHasGotRequiredParams(appEvent);

  if(osErr == noErr)
  {
    EraseRect(&gWindowPtr->portRect);
    MoveTo(8,160);
    doDrawText("\pReceived an Apple event: APPEARANCE CHANGED.");
    // Action as required by application.
  }
  else
    return(osErr);
}

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doSysFontChangeEvent

pascal OSErr  doSysFontChangeEvent(AppleEvent *appEvent,AppleEvent *reply,
                                   SInt32 handlerRefcon)
{
  OSErr   osErr;
  Str255  fontName, theString = "\p   Current large system font is: ";

  osErr = doHasGotRequiredParams(appEvent);

  if(osErr == noErr)
  {
    doDrawText("\pReceived an Apple event: LARGE SYSTEM FONT CHANGED.");
#if TARGET_CPU_PPC
    GetThemeFont(kThemeSystemFont,smSystemScript,fontName,NULL,NULL);
    doConcatPStrings(theString,fontName);
    doDrawText(theString);
#endif
    // Action as required by application.
  }
  else
    return(osErr);
}

// ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doSmallSysFontChangeEvent

pascal OSErr  doSmallSysFontChangeEvent(AppleEvent *appEvent,AppleEvent *reply,
                                        SInt32 handlerRefcon)
{
  OSErr   osErr;
  Str255  fontName, theString = "\p   Current small system font is: ";
  
  osErr = doHasGotRequiredParams(appEvent);

  if(osErr == noErr)
  {
    doDrawText("\pReceived an Apple event: SMALL SYSTEM FONT CHANGED.");
#if TARGET_CPU_PPC
    GetThemeFont(kThemeSmallSystemFont,smSystemScript,fontName,NULL,NULL);
    doConcatPStrings(theString,fontName);
    doDrawText(theString);
#endif
    // Action as required by application.
  }
  else
    return(osErr);
}

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doViewsFontChangeEvent

pascal OSErr  doViewsFontChangeEvent(AppleEvent *appEvent,AppleEvent *reply,
                                      SInt32 handlerRefcon)
{
  OSErr   osErr;
  Str255  fontName, fontSizeString, theString = "\p   Current views font is: ";
  SInt16  fontSize;

  osErr = doHasGotRequiredParams(appEvent);

  if(osErr == noErr)
  {
    doDrawText("\pReceived an Apple event: VIEWS FONT CHANGED.");
#if TARGET_CPU_PPC
    GetThemeFont(kThemeViewsFont,smSystemScript,fontName,&fontSize,NULL);
    doConcatPStrings(theString,fontName);
    doConcatPStrings(theString,"\p ");
    NumToString((SInt32) fontSize,fontSizeString);
    doConcatPStrings(theString,fontSizeString);
    doConcatPStrings(theString,"\p point");
    doDrawText(theString);
#endif
    // Action as required by application.
  }
  else
    return(osErr);
}

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doHasGotRequiredParams

OSErr  doHasGotRequiredParams(AppleEvent *appEvent)
{
  OSErr     osErr;  
  DescType  returnedType;
  Size      actualSize;

  osErr = AEGetAttributePtr(appEvent,keyMissedKeywordAttr,typeWildCard,&returnedType,
                            NULL,0,&actualSize);

  if(osErr == errAEDescNotFound)
    return(noErr);
  else if(osErr == noErr)
    return(errAEParamMissed);
}

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doOpenFile

Boolean  doOpenFile(FSSpec *fileSpecPtr,SInt32 index,SInt32 numberOfItems)
{
  WindowPtr  windowPtr;

  gApplicationWasOpen = true;

  if(index == 1)
    doDrawText("\pReceived an Apple event: OPEN DOCUMENTS.");

  if(numberOfItems == 1)
  {
    doDrawText("\p    „ The file to open is: ");
    DrawString(fileSpecPtr->name);
    doDrawText("\p    „ Opening titled window in response.");
  }
  else
  {
    if(index == 1)
    {    
      doDrawText("\p    „ The files to open are: ");
      DrawString(fileSpecPtr->name);
    }
    else
    {
      DrawString("\p and ");
      DrawString(fileSpecPtr->name);
      doDrawText("\p    „ Opening titled windows in response.");
    }
  }      

  if(windowPtr = doNewWindow())
  {
    SetWTitle(windowPtr,fileSpecPtr->name);
    return(true);
  }  
  else
    return(false);
}

// ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doPrintFile

Boolean  doPrintFile(FSSpec *fileSpecPtr,SInt32 index,SInt32 numberOfItems)
{
  WindowPtr windowPtr;
  UInt32    finalTicks;

  if(index == 1)
    doDrawText("\pReceived an Apple event: PRINT DOCUMENTS");

  if(numberOfItems == 1)
  {
    doDrawText("\p    „ The file to print is: ");
    DrawString(fileSpecPtr->name);
    windowPtr = doNewWindow();
    SetWTitle(windowPtr,fileSpecPtr->name);
    doDrawText("\p    „ I would present the Print dialog box first and then print");
    doDrawText("\p       the document when the user has made his settings.");
    Delay(60,&finalTicks);
    doDrawText("\p    „ Assume that I am now printing the document.");
    Delay(120,&finalTicks);
  }
  else
  {
    if(index == 1)
    {    
      doDrawText("\p    „ The first file to print is: ");
      DrawString(fileSpecPtr->name);
      doDrawText("\p       I would present the Print dialog box for the first file");
      doDrawText("\p       only and use the user's settings to print both files.");
    }
    else
    {
      Delay(200,&finalTicks);
      doDrawText("\p    „ The second file to print is: ");
      DrawString(fileSpecPtr->name);
      doDrawText("\p       I am using the Print dialog box settings used for the");
      doDrawText("\p       first file.");
    }
    
    windowPtr = doNewWindow();
    SetWTitle(windowPtr,fileSpecPtr->name);
    doDrawText("\p    „ Assume that I am now printing the document.");
  }

  if(numberOfItems == index)
  {
    if(!gApplicationWasOpen)
    {
      doDrawText("\p       Since the application was not already open, I expect to"); 
      doDrawText("\p       receive a QUIT APPLICATION event when I have finished.");
    }
    else
    {
      doDrawText("\p       Since the application was already open, I do NOT expect"); 
      doDrawText("\p       to receive a QUIT APPLICATION event when I have finished.");
    }

    Delay(180,&finalTicks);
    doDrawText("\p    „ Finished print job.");
  }

  DisposeWindow(windowPtr);
  return(true);
}

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doPrepareToTerminate

void  doPrepareToTerminate(void)
{
  UInt32  finalTicks;

  doDrawText("\pReceived an Apple event: QUIT APPLICATION");

  if(gApplicationWasOpen)
  {
    doDrawText("\p    „ I would now ask the user to save any unsaved files before");
    doDrawText("\p       terminating myself in response to the event.");
    doDrawText("\p    „ Click the mouse when ready to terminate.");
    while(!Button()) ;
  }
  else
  {
    doDrawText("\p    „ Terminating myself in response");
    Delay(300,&finalTicks);
  }

  // If the user did not click the Cancel button in a Save dialog box:

  gDone = true;
}

// ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doNewWindow

WindowPtr  doNewWindow(void)
{
  if(!(gWindowPtrs[gNumberOfWindows] = GetNewCWindow(rDocWindow,NULL,(WindowPtr) -1)))
    doErrorAlert(eCannotOpenWindow);

  gNumberOfWindows++;

  return(gWindowPtrs[gNumberOfWindows -1]);
}

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doMenuChoice

void  doMenuChoice(SInt32 menuChoice)
{
  SInt16  menuID, menuItem;
  Str255  itemName;
  SInt16  daDriverRefNum;

  menuID  =HiWord(menuChoice);
  menuItem=LoWord(menuChoice);

  if(menuID == 0)
    return;

  switch(menuID)
  {
    case mApple:
      GetMenuItemText(GetMenuHandle(mApple),menuItem,itemName);
      daDriverRefNum = OpenDeskAcc(itemName);
      break;

    case mFile:
      if(menuItem  == iQuit)
        gDone = true;
      break;
  }

  HiliteMenu(0);
}

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doErrorAlert

void  doErrorAlert(SInt16 errorType)
{
  AlertStdAlertParamRec paramRec;
  Str255                errorString;
  SInt16                itemHit;

  paramRec.movable        = true;
  paramRec.helpButton     = false;
  paramRec.filterProc     = NULL;
  paramRec.defaultText    = (StringPtr) kAlertDefaultOKText;
  paramRec.cancelText     = NULL;
  paramRec.otherText      = NULL;
  paramRec.defaultButton  = kAlertStdAlertOKButton;
  paramRec.cancelButton   = 0;
  paramRec.position       = kWindowDefaultPosition;

  GetIndString(errorString,rErrorStrings,errorType);

  if(errorType < 7)
    StandardAlert(kAlertCautionAlert,errorString,NULL,¶mRec,&itemHit);
  else
  {
    StandardAlert(kAlertStopAlert,errorString,NULL,¶mRec,&itemHit);
    ExitToShell();
  }
}

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doDrawText

void  doDrawText(Str255 eventString)
{
  RgnHandle tempRegion;
  SInt16    a;
  UInt32    finalTicks;
  
  tempRegion = NewRgn();

  for(a=0;a<15;a++)
  {
    ScrollRect(&gWindowPtr->portRect,0,-1,tempRegion);
    Delay(4,&finalTicks);
  }

  DisposeRgn(tempRegion);

  MoveTo(8,160);
  DrawString(eventString);
}

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doConcatPStrings

void  doConcatPStrings(Str255 targetString,Str255 appendString)
{
  SInt16  appendLength;

  appendLength = MIN(appendString[0],255 - targetString[0]);

  if(appendLength > 0)
  {
    BlockMoveData(appendString+1,targetString+targetString[0]+1,(SInt32) appendLength);
    targetString[0] += appendLength;
  }
}

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××

Demonstration Program Comments

The demonstration requires that the user open the window containing the AppleEvents
application in order to access the Apple Events application icon and two document icons.

Using all of the methods available in the Finder (that is, double clicking the icons,
dragging document icons to the application icon, selecting the icons and choosing Open and
Print from the Finder's File menu) the user should launch the application, open the
simulated documents and "print" the documents, noting the descriptive text printed in the
non-document window in response to the receipt of the resulting Apple events.  

When the application is open, the user should double-click the application icon, or select
it and choose Open from the Finder's File menu, noting the receipt of the Re-Open
Application event.

The user should also choose Restart or Shut Down from the Finder's Special menu while the
application is running, also noting the displayed text resulting from receipt of the Quit
Application event.  Opening and printing should be attempted when the application is
already running and when the application is not running.

With regard to the Appearance Manager Apple events, the user should make changes to the 
system font, small system font, and views font in the Fonts tab of the Mac OS 8.5 
Appearance control panel, noting the descriptive text that appears in the non-document 
window.

Although not related to the required Apple events aspects of the program, the following
aspects of the demonstration may also be investigated:

*   The customised finder icon help override help balloon for the application icon.  
    (The 'hfdr' resource refers.)

*   The version information for the application in the Finder's Get Info... window and
    in the window containing the AppleEvents application when list view and show version
    column are selected.  (The 'vers' resource refers.)

#define

Constants are established relating to menu, alert box, error message string, and window
resources, menus IDs and menu item numbers.

Global Variables

The first five global variables will be assigned universal procedure pointers to the
required Apple events handling functions.  The next four global variables will be assigned
universal procedure pointers to the appearance Apple event handling functions.

GMacOS85Present will be assigned true if Mac OS 8.5 or later is present.  gWindowPtr will
be assigned the pointer to the text display window. gDone controls program termination.

gApplicationWasOpen will be used to control the manner of program termination when a Quit
Application event is received, depending on whether the event followed a Print Documents
event or resulted from the user choosing Restart of Shut Down from the Finder's Special
menu.

gWindowPtrs will be assigned pointers to the document windows.  gNumberOfWindows is used
to increment the gWindowPtrs[] array element after each document window is created.

main

The main function initialises the system software managers and then determines 
whether Mac OS 8.5 is present.

The next block calls NewAEEventHandlerProc nine times to create routine descriptors for 
each of the required Apple event and appearance Apple event handling functions.  Note that
the last three calls are made only if Mac OS 8.5 or later is present; this is because the
Mac OS 8.5 Appearance control panel was the first to contain pop-up menus allowing the 
user to change the system, small system, and views fonts.

The next block calls GetNewCWindow to open the text display window, makes that window the
current graphics port, sets the text size for that graphics port to 10pt, sets the text
style to bold, sets the foreground and background colours, and calls EraseRect to draw the
window' content area in the new background colour.

The menus are then set up.  Note that here, and in other areas of the program, an error
will cause the application-defined error-handling function doErrorAlert to be called.

The call to doInstallAEHandlers installs the Apple event handlers.  Finally, the main
event loop is entered.

doInstallAEHandlers

doInstallAEHandlers installs the handlers for the required Apple events and the 
Appearance Manager Apple events in the application's Apple event dispatch table.  Note 
that the last three are only installed if Mac OS 8.5 or later is present.

doEvents

doEvents switches according to the event type received.

The kHighLevelEvent case accommodates the receipt of a high-level event, in which case
AEProcessAppleEvent is called.  (AEProcessAppleEvent looks in the application's Apple
event dispatch table for a match to the event class and event ID contained in,
respectively, the event structure's message and where fields, and calls the appropriate
handler.)

doMouseDown

doMouseDown performs such mouse-down processing as is necessary to support the
demonstration aspects of the program.

doOpenAppEvent

doOpenAppEvent is the handler for the Open Application event.

At the first line, the global variable gApplicationWasOpen, which controls the manner of
program termination when a Quit Application event is received, is set to true.  (This line
is required for demonstration program purposes only.)

The application-defined function doHasGotRequiredParams is then called to check whether
the Apple event contains any required parameters.  If so, the handler returns an error
because, by definition, the Open Application event should not contain any required
parameters.

If noErr is returned by doHasGotRequiredParams, the handler does what the user expects the
application to do when it is opened, that is, it opens an untitled document window (the
call to doNewWindow and the subsequent call to SetWTitle).  The handler then returns
noErr.

The last two lines mean that, if errAEParamMissed is returned by doHasGotRequiredParams,
this is returned by the handler.

The calls to doDrawText simply print some text in the text window for demonstration
program purposes.

doReopenAppEvent

doRepenAppEvent is the handler for the Re-open Documents event.

At the first line, the application-defined function doHasGotRequiredParams is called to
check whether the Apple event contains any required parameters.  If so, the handler
returns an error because, by definition, the Re-open Application event should not contain
any required parameters.

If noErr is returned by dHasGotRequiredParams, and if there are currently no open windows,
the handler opens an untitled document window and returns noErr.

The last two lines mean that, if errAEParamMissed is returned by doHasGotRequiredParams,
this is returned by the handler.

The calls to doDrawText simply print some text in the text window for demonstration
program purposes.

doOpenDocsEvent

doOpenDocsEvent is the handler for the Open Documents event.

At the first line, AEGetParamDesc is called to get the direct parameter (specified in the
keyDirectObject keyword) out of the Apple event.  The constant typeAEList specifies the
descriptor type as a list of descriptor structures.  The descriptor list is received by
the docList variable.

Before proceeding further, the handler checks that it has received all the required
parameters by calling the application-defined function doHasGotRequiredParams (Line 324).

Having retrieved the descriptor list from the Apple event, the handler calls AECountItems
to count the number of descriptors in the list.

Using the returned number as an index, AEGetNthPtr is called to get the data of each
descriptor structure in the list.  In the AEGetNthPtr call, the parameter typeFSS
specifies the desired type of the resulting data, causing the Apple Event Manager to
coerce the data in the descriptor structure to a file system specification structure. 
Note also that keyWord receives the keyword of the specified descriptor structure,
returnedType receives the descriptor type, fileSpec receives a pointer to the file system
specification structure, sizeof(fileSpec) establishes the length, in bytes, of the data
returned, and actualSize receives the actual length, in bytes, of the data for the
descriptor structure.

After extracting the file system specification structure describing the document to open,
the handler calls the application-defined function for opening files (doOpenFile).  (In a
real application, that function would typically be the same as that invoked when the user
chooses Open from the application's File menu.)

If the call to AEGetNthPtr does not return noErr, the application-defined error handling
function (doErrorAlert) is called.  (AEGetNthPtr will return an error code if there was
insufficient room in the heap, the data could not be coerced, the descriptor structure was
not found, the descriptor was of the wrong type or the descriptor structure was not a
valid descriptor structure.)

If the call to doHasGotRequiredParams does not return noErr, the application-defined error
handling function (doErrorAlert) is called.  (doHasGotRequiredParams returns noErr only if
you got all the required parameters.)

Since the handler has no further requirement for the data in the descriptor list,
AEDisposeDesc is called to dispose of the descriptor list.

If the call to AEGetParamDesc does not return noErr the application-defined error handling
function (doErrorAlert) is called.  (AEGetParamDesc will return an error code for much the
same reasons as will AEGetNthPtr.)

doPrintDocsEvent

doPrintDocsEvent is the handler for the Print Documents event.

The code is identical to that for the Open Documents event handler doOpenDocs except that
the application-defined function for printing files (doPrintFile) is called rather than
the function for simply opening files (doOpenFile).

doQuitAppEvent

doQuitAppEvent is the handler for the Quit Application event.

After checking that it has received all the required parameters by calling the
application-defined function doHasGotRequiredParams, the handler calls the
application-defined function doPrepareToTerminate.

doAppearanceChangeEvent, doSysFontChangeEvent, doSmallSysFontChange, and doViewsFontChangeEvent

doAppearanceChangeEvent, doSysFontChangeEvent, doSmallSysFontChange, and 
doViewsFontChangeEvent are the handlers for the Appearance Manager Apple events.

After checking that they have received all the required parameters by calling the
application-defined function doHasGotRequiredParams, the handlers draw some advisory 
text in the non-document window indicating that the event has been received, call the 
Appearance Manager function GetThemeFont to obtain information about the relevant font 
(large system, small system, or views), and draw the font name (and, in the case of the 
views font, the font size).

doHasGotRequiredParams

doHasGotRequiredParams is the application-defined function called by doOpenAppEvent
and doThemeSwitch to confirm that the event passed to it contains no required parameters,
and by the other required Apple event handlers to check that they have received all the
required parameters.

The first parameter in the call to AEGetAttributePtr is a pointer to the Apple event in
question.  The second parameter is the Apple event keyword; in this case the constant
keyMissedKeywordAttr is specified, meaning the first required parameter remaining in the
event.  The third parameter specifies the descriptor type; in this case the constant
typeWildCard is specified, meaning any descriptor type.  The fourth parameter receives the
descriptor type of the returned data.  The fifth parameter is a pointer to the data buffer
which stores the returned data.  The sixth parameter is the maximum length of the data
buffer to be returned.  Since we do not need the data itself, these parameters are set to
NULL and 0 respectively.  The last parameter receives the actual length, in bytes, of the
data buffer for the attribute.

AEGetAttributePtr returns the result code errAEDescNotFound if the specified descriptor
type (typeWildCard, that is, any descriptor type) is not found, meaning that the handler
extracted all the required parameters.  In this event, doHasGotRequiredParams returns
noErr.

If AEGetAttributePtr returns noErr, the handler has not extracted all of the required
parameters, in which case, the handler should return errAEParamMissed and not handle the
event.  Accordingly, errAEParamMissed is returned to the handler (and, in turn, by the
handler) if noErr is returned by AEGetAttributePtr.

doOpenFile

doOpenFile takes the file system specification structure and opens a window with the
filename contained in that structure repeated in the window's title bar (the calls to
doNewWindow and SetWTitle).  The rest of the doOpenFile code simply draws explanatory text
in the text window. 

In a real application, this is the function that would open files as a result of, firstly,
the receipt of the Open Documents event and, secondly, the user choosing Open from the
application's File menu and then choosing a file or files from the resulting Open dialog
box.

doPrintFile

doPrintFile is the function which, in a real application, would take the file system
specification structure passed to it from the Print Documents event handler, extract the
filename and control the printing of that file.  In this demonstration, most of the
doPrintFile code is related to drawing explanatory text in the text window.

If your application can interact with the user, it should open windows for the documents,
display a print Job dialog for the first document, and use the settings entered by the
user for the first document to print all documents.

Note that, if your application was not running when the user selected a document icon and
chose Print from the Finder's File menu, the Finder will send a Quit Application event
following the print operation.

doPrepareToTerminate

doPrepareToTerminate is the function called by the Quit Application event handler. 
In this demonstration, gDone will be set to true, and the program will thus terminate
immediately, if the Quit Application event resulted from the user initiating a print
operation from the Finder when the application was not running.

If the application was running (gApplicationWasOpen contains true) and the Quit
Application event thus arose from the user selecting Restart or Shut Down from the
Finder's File menu, the demonstration waits for a button click before setting gDone to
true.  (In a real application, and where appropriate, this area of the code would invoke
dialog boxes to ascertain whether the user wished to save any changed documents before
closing down.)

Note that, when your application is ready to quit, it must call ExitToShell from the main
event loop, not from the handlers for the Quit Application event.  Your application should
quit only after the handler returns noErr as its function result.

doNewWindow

doNewWindow opens document windows in response to calls from the Open Application and
Open Documents event handlers.

doMenuChoice, doErrorAlert, doDrawText, and doConcatPStrings

doMenuChoice handles menu selections.  gDone is set to true when the user selects
Quit from the application's File menu.  doErrorAlert handles errors, displaying a movable
modal alert box with descriptive text and, where necessary, terminating the program. 
doDrawText draws scrolling explanatory text in the text window as each event is
received.  DoConcatPStrings concatenates two Pascal strings.
 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Latest Forum Discussions

See All

Make the passage of time your plaything...
While some of us are still waiting for a chance to get our hands on Ash Prime - yes, donā€™t remind me I could currently buy him this month Iā€™m barely hanging on - Digital Extremes has announced its next anticipated Prime Form for Warframe. Starting... | Read more »
If you can find it and fit through the d...
The holy trinity of amazing company names have come together, to release their equally amazing and adorable mobile game, Hamster Inn. Published by HyperBeard Games, and co-developed by Mum Not Proud and Little Sasquatch Studios, it's time to... | Read more »
Amikin Survival opens for pre-orders on...
Join me on the wonderful trip down the inspiration rabbit hole; much as Palworld seemingly ā€œborrowedā€ many aspects from the hit Pokemon franchise, it is time for the heavily armed animal survival to also spawn some illegitimate children as Helio... | Read more »
PUBG Mobile teams up with global phenome...
Since launching in 2019, SpyxFamily has exploded to damn near catastrophic popularity, so it was only a matter of time before a mobile game snapped up a collaboration. Enter PUBG Mobile. Until May 12th, players will be able to collect a host of... | Read more »
Embark into the frozen tundra of certain...
Chucklefish, developers of hit action-adventure sandbox game Starbound and owner of one of the cutest logos in gaming, has released their roguelike deck-builder Wildfrost. Created alongside developers Gaziter and Deadpan Games, Wildfrost will... | Read more »
MoreFun Studios has announced Season 4,...
Tension has escalated in the ever-volatile world of Arena Breakout, as your old pal Randall Fisher and bosses Fred and Perrero continue to lob insults and explosives at each other, bringing us to a new phase of warfare. Season 4, Into The Fog of... | Read more »
Top Mobile Game Discounts
Every day, we pick out a curated list of the best mobile discounts on the App Store and post them here. This list won't be comprehensive, but it every game on it is recommended. Feel free to check out the coverage we did on them in the links below... | Read more »
Marvel Future Fight celebrates nine year...
Announced alongside an advertising image I can only assume was aimed squarely at myself with the prominent Deadpool and Odin featured on it, Netmarble has revealed their celebrations for the 9th anniversary of Marvel Future Fight. The Countdown... | Read more »
HoYoFair 2024 prepares to showcase over...
To say Genshin Impact took the world by storm when it was released would be an understatement. However, I think the most surprising part of the launch was just how much further it went than gaming. There have been concerts, art shows, massive... | Read more »
Explore some of BBCs' most iconic s...
Despite your personal opinion on the BBC at a managerial level, it is undeniable that it has overseen some fantastic British shows in the past, and now thanks to a partnership with Roblox, players will be able to interact with some of these... | Read more »

Price Scanner via MacPrices.net

You can save $300-$480 on a 14-inch M3 Pro/Ma...
Apple has 14ā€³ M3 Pro and M3 Max MacBook Pros in stock today and available, Certified Refurbished, starting at $1699 and ranging up to $480 off MSRP. Each model features a new outer case, shipping is... Read more
24-inch M1 iMacs available at Apple starting...
Apple has clearance M1 iMacs available in their Certified Refurbished store starting at $1049 and ranging up to $300 off original MSRP. Each iMac is in like-new condition and comes with Appleā€™s... Read more
Walmart continues to offer $699 13-inch M1 Ma...
Walmart continues to offer new Apple 13ā€³ M1 MacBook Airs (8GB RAM, 256GB SSD) online for $699, $300 off original MSRP, in Space Gray, Silver, and Gold colors. These are new MacBook for sale by... Read more
B&H has 13-inch M2 MacBook Airs with 16GB...
B&H Photo has 13ā€³ MacBook Airs with M2 CPUs, 16GB of memory, and 256GB of storage in stock and on sale for $1099, $100 off Appleā€™s MSRP for this configuration. Free 1-2 day delivery is available... Read more
14-inch M3 MacBook Pro with 16GB of RAM avail...
Apple has the 14ā€³ M3 MacBook Pro with 16GB of RAM and 1TB of storage, Certified Refurbished, available for $300 off MSRP. Each MacBook Pro features a new outer case, shipping is free, and an Apple 1-... Read more
Apple M2 Mac minis on sale for up to $150 off...
Amazon has Appleā€™s M2-powered Mac minis in stock and on sale for $100-$150 off MSRP, each including free delivery: ā€“ Mac mini M2/256GB SSD: $499, save $100 ā€“ Mac mini M2/512GB SSD: $699, save $100 ā€“... Read more
Amazon is offering a $200 discount on 14-inch...
Amazon has 14-inch M3 MacBook Pros in stock and on sale for $200 off MSRP. Shipping is free. Note that Amazonā€™s stock tends to come and go: ā€“ 14ā€³ M3 MacBook Pro (8GB RAM/512GB SSD): $1399.99, $200... Read more
Sunday Sale: 13-inch M3 MacBook Air for $999,...
Several Apple retailers have the new 13ā€³ MacBook Air with an M3 CPU in stock and on sale today for only $999 in Midnight. These are the lowest prices currently available for new 13ā€³ M3 MacBook Airs... Read more
Multiple Apple retailers are offering 13-inch...
Several Apple retailers have 13ā€³ MacBook Airs with M2 CPUs in stock and on sale this weekend starting at only $849 in Space Gray, Silver, Starlight, and Midnight colors. These are the lowest prices... Read more
Roundup of Verizonā€™s April Apple iPhone Promo...
Verizon is offering a number of iPhone deals for the month of April. Switch, and open a new of service, and you can qualify for a free iPhone 15 or heavy monthly discounts on other models: ā€“ 128GB... Read more

Jobs Board

Relationship Banker - *Apple* Valley Financ...
Relationship Banker - Apple Valley Financial Center APPLE VALLEY, Minnesota **Job Description:** At Bank of America, we are guided by a common purpose to help Read more
IN6728 Optometrist- *Apple* Valley, CA- Tar...
Date: Apr 9, 2024 Brand: Target Optical Location: Apple Valley, CA, US, 92308 **Requisition ID:** 824398 At Target Optical, we help people see and look great - and Read more
Medical Assistant - Orthopedics *Apple* Hil...
Medical Assistant - Orthopedics Apple Hill York Location: WellSpan Medical Group, York, PA Schedule: Full Time Sign-On Bonus Eligible Remote/Hybrid Regular Apply Now Read more
*Apple* Systems Administrator - JAMF - Activ...
ā€¦**Public Trust/Other Required:** None **Job Family:** Systems Administration **Skills:** Apple Platforms,Computer Servers,Jamf Pro **Experience:** 3 + years of Read more
Liquor Stock Clerk - S. *Apple* St. - Idaho...
Liquor Stock Clerk - S. Apple St. Boise Posting Begin Date: 2023/10/10 Posting End Date: 2024/10/14 Category: Retail Sub Category: Customer Service Work Type: Part Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.