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

Whitethorn Games combines two completely...
If you have ever gone fishing then you know that it is a lesson in patience, sitting around waiting for a bite that may never come. Well, that's because you have been doing it wrong, since as Whitehorn Games now demonstrates in new release Skate... | Read more »
Call of Duty Warzone is a Waiting Simula...
It's always fun when a splashy multiplayer game comes to mobile because they are few and far between, so I was excited to see the notification about Call of Duty: Warzone Mobile (finally) launching last week and wanted to try it out. As someone who... | Read more »
Albion Online introduces some massive ne...
Sandbox Interactive has announced an upcoming update to its flagship MMORPG Albion Online, containing massive updates to its existing guild Vs guild systems. Someone clearly rewatched the Helms Deep battle in Lord of the Rings and spent the next... | Read more »
Chucklefish announces launch date of the...
Chucklefish, the indie London-based team we probably all know from developing Terraria or their stint publishing Stardew Valley, has revealed the mobile release date for roguelike deck-builder Wildfrost. Developed by Gaziter and Deadpan Games, the... | Read more »
Netmarble opens pre-registration for act...
It has been close to three years since Netmarble announced they would be adapting the smash series Solo Leveling into a video game, and at last, they have announced the opening of pre-orders for Solo Leveling: Arise. [Read more] | Read more »
PUBG Mobile celebrates sixth anniversary...
For the past six years, PUBG Mobile has been one of the most popular shooters you can play in the palm of your hand, and Krafton is celebrating this milestone and many years of ups by teaming up with hit music man JVKE to create a special song for... | Read more »
ASTRA: Knights of Veda refuse to pump th...
In perhaps the most recent example of being incredibly eager, ASTRA: Knights of Veda has dropped its second collaboration with South Korean boyband Seventeen, named so as it consists of exactly thirteen members and a video collaboration with Lee... | Read more »
Collect all your cats and caterpillars a...
If you are growing tired of trying to build a town with your phone by using it as a tiny, ineffectual shover then fear no longer, as Independent Arts Software has announced the upcoming release of Construction Simulator 4, from the critically... | Read more »
Backbone complete its lineup of 2nd Gene...
With all the ports of big AAA games that have been coming to mobile, it is becoming more convenient than ever to own a good controller, and to help with this Backbone has announced the completion of their 2nd generation product lineup with their... | Read more »
Zenless Zone Zero opens entries for its...
miHoYo, aka HoYoverse, has become such a big name in mobile gaming that it's hard to believe that arguably their flagship title, Genshin Impact, is only three and a half years old. Now, they continue the road to the next title in their world, with... | Read more »

Price Scanner via MacPrices.net

B&H has Apple’s 13-inch M2 MacBook Airs o...
B&H Photo has 13″ MacBook Airs with M2 CPUs and 256GB of storage in stock and on sale for up to $150 off Apple’s new MSRP, starting at only $849. Free 1-2 day delivery is available to most US... Read more
M2 Mac minis on sale for $100-$200 off MSRP,...
B&H Photo has Apple’s M2-powered Mac minis back in stock and on sale today for $100-$200 off MSRP. Free 1-2 day shipping is available for most US addresses: – Mac mini M2/256GB SSD: $499, save $... Read more
Mac Studios with M2 Max and M2 Ultra CPUs on...
B&H Photo has standard-configuration Mac Studios with Apple’s M2 Max & Ultra CPUs in stock today and on Easter sale for $200 off MSRP. Their prices are the lowest available for these models... Read more
Deal Alert! B&H Photo has Apple’s 14-inch...
B&H Photo has new Gray and Black 14″ M3, M3 Pro, and M3 Max MacBook Pros on sale for $200-$300 off MSRP, starting at only $1399. B&H offers free 1-2 day delivery to most US addresses: – 14″ 8... Read more
Department Of Justice Sets Sights On Apple In...
NEWS – The ball has finally dropped on the big Apple. The ball (metaphorically speaking) — an antitrust lawsuit filed in the U.S. on March 21 by the Department of Justice (DOJ) — came down following... Read more
New 13-inch M3 MacBook Air on sale for $999,...
Amazon has Apple’s new 13″ M3 MacBook Air on sale for $100 off MSRP for the first time, now just $999 shipped. Shipping is free: – 13″ MacBook Air (8GB RAM/256GB SSD/Space Gray): $999 $100 off MSRP... Read more
Amazon has Apple’s 9th-generation WiFi iPads...
Amazon has Apple’s 9th generation 10.2″ WiFi iPads on sale for $80-$100 off MSRP, starting only $249. Their prices are the lowest available for new iPads anywhere: – 10″ 64GB WiFi iPad (Space Gray or... Read more
Discounted 14-inch M3 MacBook Pros with 16GB...
Apple retailer Expercom has 14″ MacBook Pros with M3 CPUs and 16GB of standard memory discounted by up to $120 off Apple’s MSRP: – 14″ M3 MacBook Pro (16GB RAM/256GB SSD): $1691.06 $108 off MSRP – 14... Read more
Clearance 15-inch M2 MacBook Airs on sale for...
B&H Photo has Apple’s 15″ MacBook Airs with M2 CPUs (8GB RAM/256GB SSD) in stock today and on clearance sale for $999 in all four colors. Free 1-2 delivery is available to most US addresses.... Read more
Clearance 13-inch M1 MacBook Airs drop to onl...
B&H has Apple’s base 13″ M1 MacBook Air (Space Gray, Silver, & Gold) in stock and on clearance sale today for $300 off MSRP, only $699. Free 1-2 day shipping is available to most addresses in... Read more

Jobs Board

Medical Assistant - Surgical Oncology- *Apple...
Medical Assistant - Surgical Oncology- Apple Hill Location: WellSpan Medical Group, York, PA Schedule: Full Time Sign-On Bonus Eligible Remote/Hybrid Regular Apply Read more
Omnichannel Associate - *Apple* Blossom Mal...
Omnichannel Associate - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Read more
Cashier - *Apple* Blossom Mall - JCPenney (...
Cashier - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Blossom Mall Read more
Operations Associate - *Apple* Blossom Mall...
Operations Associate - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Read more
Business Analyst | *Apple* Pay - Banco Popu...
Business Analyst | Apple PayApply now " Apply now + Apply Now + Start applying with LinkedIn Start + Please wait Date:Mar 19, 2024 Location: San Juan-Cupey, PR Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.