TweetFollow Us on Twitter

MACINTOSH C CARBON

Demonstration Program AppleEvents

Goto Contents

// *******************************************************************************************
// AppleEvents.c                                                           CLASSIC EVENT MODEL
// *******************************************************************************************
// 
// This program:
//
// o  Installs handlers for the required Apple events, Appearance Manager Apple events, and,
//    on Mac OS X only, the Show Preferences Apple event.
//
// o  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:
//
//    o   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.
//
//    o   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.
//
//    o   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.
//
//    o   On Mac OS 8/9, 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.
//
//    o   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.   
//
// o  Responds to the receipt of Appearance Manager Apple events (Mac OS 8/9) and the Show 
//    Preferences Apple event (Mac OS X) by displaying descriptive text.
//
// The program, which is intended to be run as a built application rather than within
// CodeWarrior, utilises the following resources:
//
// o  A 'plst' resource containing an information property list which provides information
//    to the Mac OS X Finder.
//
// o  An 'icns' resource containing application and document icons for Mac OS X.
//
// o  'WIND' resources (purgeable, initially visible) for the descriptive text display window
//     and simulated document windows.
//
// o  'MBAR' and 'MENU' resources (preload, non-purgeable).
//
// o  'STR#' resources (purgeable) for displaying error messages using StandardAlert.
//
// o  For Mac OS 8/9:
//
//    o   'ICN#', 'ics#', 'ics4', 'ics8', 'icl4', and 'icl8' resources (that is, an icon 
//        family) for the application and for the application's documents. (Purgeable.)
//
//    o   '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.
//
//    o   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.  
//
//    o   A 'BNDL' resource (non-purgeable), which groups together the application's
//        signature, icon and 'FREF' resources.  
//
//    o   A 'hfdr' resource (purgeable), which provides the customised finder icon help 
//        override help balloon for the  application icon. 
//
//    o   A 'vers' resource (purgeable), which provides version information via the Show Info
//        window and the Version column in list view windows.
//
// o  A 'SIZE' resource with the acceptSuspendResumeEvents, canBackground, 
//    doesActivateOnFGSwitch, and isHighLevelEventAware flags set.
//
// *******************************************************************************************

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

#include <Carbon.h>

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

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

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

WindowRef gWindowRef;
Boolean   gRunningOnX = false;
Boolean   gDone;
Boolean   gApplicationWasOpen = false;

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

void      main                           (void);
void      doPreliminaries                (void);
void      doInstallAEHandlers            (void);
void      doInstallAnAEHandler           (AEEventClass,AEEventID,void *);
void      doEvents                       (EventRecord *);
OSErr     openAppEventHandler            (AppleEvent *,AppleEvent *,SInt32);
OSErr     reopenAppEventHandler          (AppleEvent *,AppleEvent *,SInt32);
OSErr     openDocsEventHandler           (AppleEvent *,AppleEvent *,SInt32);
OSErr     printDocsEventHandler          (AppleEvent *,AppleEvent *,SInt32);
OSErr     quitAppEventHandler            (AppleEvent *,AppleEvent *,SInt32);
OSErr     sysFontChangeEventHandler      (AppleEvent *,AppleEvent *,SInt32);
OSErr     smallSysFontChangeEventHandler (AppleEvent *,AppleEvent *,SInt32);
OSErr     viewsFontChangeEventHandler    (AppleEvent *,AppleEvent *,SInt32);
OSErr     showPreferencesEventHandler    (AppleEvent *,AppleEvent *,SInt32);
OSErr     doHasGotRequiredParams         (AppleEvent *);
Boolean   doOpenFile                     (FSSpec *,SInt32,SInt32);
Boolean   doPrintFile                    (FSSpec *,SInt32,SInt32);
void      doPrepareToTerminate           (void);
WindowRef doNewWindow                    (void);
void      doMenuChoice                   (SInt32);
void      doErrorAlert                   (SInt16);
void      doDrawText                     (Str255);
void      doConcatPStrings               (Str255,Str255);

// ************************************************************************************** main

void  main(void)
{
  Rect          portRect;
  RGBColor      foreColour = { 0xFFFF,0xFFFF,0xFFFF };
  RGBColor      backColour = { 0x4444,0x4444,0x9999 };
  MenuBarHandle menubarHdl;
  SInt32        response;
  MenuRef       menuRef;
  EventRecord   eventStructure;
  
  // ........................................................................ do preliminaries

  doPreliminaries();

  // ............................................................... set up menu bar and menus

  menubarHdl = GetNewMBar(rMenubar);
  if(menubarHdl == NULL)
    doErrorAlert(eMenus);
  SetMenuBar(menubarHdl);
  DrawMenuBar();

  Gestalt(gestaltMenuMgrAttr,&response);
  if(response & gestaltMenuMgrAquaLayoutMask)
  {
    menuRef = GetMenuRef(mFile);
    if(menuRef != NULL)
    {
      DeleteMenuItem(menuRef,iQuit);
      DeleteMenuItem(menuRef,iQuit - 1);
      DisableMenuItem(menuRef,0);
    }

    gRunningOnX = true;

    EnableMenuCommand(NULL,kAEShowPreferences);
  }

  // ........................................................................... open a window

  if(!(gWindowRef = GetNewCWindow(rDisplayWindow,NULL,(WindowRef) -1)))
  {
    doErrorAlert(eCannotOpenWindow);
    ExitToShell();
  }

  SetPortWindowPort(gWindowRef);
  TextSize(10);
  TextFace(bold);
  RGBBackColor(&backColour);
  RGBForeColor(&foreColour);
  GetWindowPortBounds(gWindowRef,&portRect);
  EraseRect(&portRect);

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

  doInstallAEHandlers();

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

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

// *************************************************************************** doPreliminaries

void  doPreliminaries(void)
{
  MoreMasterPointers(64);
  InitCursor();
  FlushEvents(everyEvent,0);
}

// *********************************************************************** doInstallAEHandlers

void  doInstallAEHandlers(void)
{
  // ................................................................... required Apple events

  doInstallAnAEHandler(kCoreEventClass,kAEOpenApplication,openAppEventHandler);
  doInstallAnAEHandler(kCoreEventClass,kAEReopenApplication,reopenAppEventHandler);
  doInstallAnAEHandler(kCoreEventClass,kAEOpenDocuments,openDocsEventHandler);
  doInstallAnAEHandler(kCoreEventClass,kAEPrintDocuments,printDocsEventHandler);
  doInstallAnAEHandler(kCoreEventClass,kAEQuitApplication,quitAppEventHandler);

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

  doInstallAnAEHandler(kAppearanceEventClass,kAESystemFontChanged,sysFontChangeEventHandler);
  doInstallAnAEHandler(kAppearanceEventClass,kAESmallSystemFontChanged,
                       smallSysFontChangeEventHandler);
  doInstallAnAEHandler(kAppearanceEventClass,kAEViewsFontChanged,viewsFontChangeEventHandler);

  // ............................................................ Show Preferences Apple event

  if(gRunningOnX)
    doInstallAnAEHandler(kCoreEventClass,kAEShowPreferences,showPreferencesEventHandler);
}

// ********************************************************************** doInstallAnAEHandler

void  doInstallAnAEHandler(AEEventClass eventClass,AEEventID eventID,void *theHandler)
{
  OSErr  osError;

  osError = AEInstallEventHandler(eventClass,eventID,
                                  NewAEEventHandlerUPP((AEEventHandlerProcPtr) theHandler),
                                  0L,false);
  if(osError != noErr)
    doErrorAlert(eInstallHandler);
}

// ********************************************************************************** doEvents

void  doEvents(EventRecord *eventStrucPtr)
{
  WindowPartCode partCode;
  WindowRef      windowRef;
  SInt32         menuChoice;

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

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

        case inDrag:
          DragWindow(windowRef,eventStrucPtr->where,NULL);
          break;

        case inContent:
          if(windowRef != FrontWindow())
            SelectWindow(windowRef);
          break;
          
        case inGoAway:
          DisposeWindow(windowRef);
          break;
      }
      break;

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

    case updateEvt:
      BeginUpdate((WindowRef)eventStrucPtr->message);
      EndUpdate((WindowRef)eventStrucPtr->message);
      break;
  }
}
  
// *********************************************************************** openAppEventHandler

OSErr  openAppEventHandler(AppleEvent *appEvent,AppleEvent *reply,SInt32 handlerRefCon)
{
  OSErr     osError;
  WindowRef windowRef;

  gApplicationWasOpen = true;

  osError = doHasGotRequiredParams(appEvent);

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

    windowRef = doNewWindow();
    SetWTitle(windowRef,"\puntitled");
  }

  return osError;
}

// ********************************************************************* reopenAppEventHandler

OSErr  reopenAppEventHandler(AppleEvent *appEvent,AppleEvent *reply,SInt32 handlerRefCon)
{
  OSErr     osError;
  WindowRef windowRef;

  osError = doHasGotRequiredParams(appEvent);

  if(osError == noErr)
  {
    doDrawText("\pReceived an Apple event: RE-OPEN APPLICATION.");
    doDrawText("\p    o I will check whether I have any windows open.");

    windowRef = GetWindowList();

    if((windowRef = GetNextWindow(windowRef)) == NULL)
    {
      doDrawText("\p      No windows are open, so I will open a window.");

      windowRef = doNewWindow();
      SetWTitle(windowRef,"\puntitled 1");
    }
    else
      doDrawText("\p      A window is open, so I won't open another.");
  }

  return osError;
}

// ********************************************************************** openDocsEventHandler

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

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

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

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

  return osError;
}

// ********************************************************************* printDocsEventHandler

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

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

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

  return osError;
}

// *********************************************************************** quitAppEventHandler

OSErr  quitAppEventHandler(AppleEvent *appEvent,AppleEvent *reply,SInt32 handlerRefcon)
{
  OSErr osError;

  osError = doHasGotRequiredParams(appEvent);

  if(osError == noErr)
    doPrepareToTerminate();

  return osError;
}

// ***************************************************************** sysFontChangeEventHandler

OSErr  sysFontChangeEventHandler(AppleEvent *appEvent,AppleEvent *reply,
                                 SInt32 handlerRefcon)
{
  OSErr  osError;
  Rect   portRect;
  Str255 fontName, theString = "\p   Current large system font is: ";

  osError = doHasGotRequiredParams(appEvent);

  if(osError == noErr)
  {
    GetWindowPortBounds(gWindowRef,&portRect);
    EraseRect(&portRect);
    doDrawText("\pReceived an Apple event: LARGE SYSTEM FONT CHANGED.");
    GetThemeFont(kThemeSystemFont,smSystemScript,fontName,NULL,NULL);
    doConcatPStrings(theString,fontName);
    doDrawText(theString);
    // Action as required by application.
  }

  return osError;
}

// ************************************************************ smallSysFontChangeEventHandler

OSErr  smallSysFontChangeEventHandler(AppleEvent *appEvent,AppleEvent *reply,
                                      SInt32 handlerRefcon)
{
  OSErr  osError;
  Rect   portRect;
  Str255 fontName, theString = "\p   Current small system font is: ";
  
  osError = doHasGotRequiredParams(appEvent);

  if(osError == noErr)
  {
    GetWindowPortBounds(gWindowRef,&portRect);
    EraseRect(&portRect);
    doDrawText("\pReceived an Apple event: SMALL SYSTEM FONT CHANGED.");
    GetThemeFont(kThemeSmallSystemFont,smSystemScript,fontName,NULL,NULL);
    doConcatPStrings(theString,fontName);
    doDrawText(theString);
    // Action as required by application.
  }

  return osError;
}

// *************************************************************** viewsFontChangeEventHandler

OSErr  viewsFontChangeEventHandler(AppleEvent *appEvent,AppleEvent *reply,
                                   SInt32 handlerRefcon)
{
  OSErr  osError;
  Rect   portRect;
  Str255 fontName, fontSizeString, theString = "\p   Current views font is: ";
  SInt16 fontSize;

  osError = doHasGotRequiredParams(appEvent);

  if(osError == noErr)
  {
    GetWindowPortBounds(gWindowRef,&portRect);
    EraseRect(&portRect);
    doDrawText("\pReceived an Apple event: VIEWS FONT CHANGED.");
    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);
    // Action as required by application.
  }

  return osError;
}

// *************************************************************** showPreferencesEventHandler

OSErr  showPreferencesEventHandler(AppleEvent *appEvent,AppleEvent *reply,
                                   SInt32 handlerRefcon)
{
  OSErr osError;
  Rect  portRect;

  osError = doHasGotRequiredParams(appEvent);

  if(osError == noErr)
  {
    GetWindowPortBounds(gWindowRef,&portRect);
    EraseRect(&portRect);
    doDrawText("\pReceived an Apple event: SHOW PREFERENCES.");
    doDrawText("\p    o I would present a Preferences... dialog now.");
  }

  return osError;
}

// ******************************************************************** doHasGotRequiredParams

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

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

  if(osError == errAEDescNotFound)
    osError = noErr;
  else if(osError == noErr)
    osError = errAEParamMissed;

  return osError;
}

// ******************************************************************************** doOpenFile

Boolean  doOpenFile(FSSpec *fileSpecPtr,SInt32 index,SInt32 numberOfItems)
{
  WindowRef windowRef;

  gApplicationWasOpen = true;

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

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

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

// ******************************************************************************* doPrintFile

Boolean  doPrintFile(FSSpec *fileSpecPtr,SInt32 index,SInt32 numberOfItems)
{
  WindowRef windowRef;
  UInt32    finalTicks;

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

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

    windowRef = doNewWindow();
    SetWTitle(windowRef,fileSpecPtr->name);
    doDrawText("\p    o 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    o Finished print job.");
  }
  else
    Delay(180, &finalTicks);

  DisposeWindow(windowRef);
  return true;
}

// ********************************************************************** doPrepareToTerminate

void  doPrepareToTerminate(void)
{
  UInt32 finalTicks;

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

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

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

  gDone = true;
}

// ******************************************************************************* doNewWindow

WindowRef  doNewWindow(void)
{
  WindowRef windowRef;

  if(!(windowRef = GetNewCWindow(rDocWindow,NULL,(WindowRef) -1)))
    doErrorAlert(eCannotOpenWindow);

  return windowRef;
}

// ****************************************************************************** doMenuChoice

void  doMenuChoice(SInt32 menuChoice)
{
  MenuID        menuID;
  MenuItemIndex menuItem;
  
  menuID   = HiWord(menuChoice);
  menuItem = LoWord(menuChoice);

  if(menuID == 0)
    return;

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

  HiliteMenu(0);
}

// ****************************************************************************** doErrorAlert

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

  GetIndString(errorString,rErrorStrings,errorType);

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

// ******************************************************************************** doDrawText

void  doDrawText(Str255 eventString)
{
  RgnHandle tempRegion;
  SInt16    a;
  Rect      portRect;
  UInt32    finalTicks;

  tempRegion = NewRgn();
  GetWindowPortBounds(gWindowRef,&portRect);

  for(a=0;a<15;a++)
  {
    ScrollRect(&portRect,0,-1,tempRegion);
    QDFlushPortBuffer(GetWindowPort(gWindowRef),NULL);

    Delay(4,&finalTicks);
  }

  DisposeRgn(tempRegion);

  MoveTo(8,160);
  DrawString(eventString);
  QDFlushPortBuffer(GetWindowPort(gWindowRef),NULL);
}

// ************************************************************************** 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 AppleEvents Comments

The demonstration requires that the user open the windows containing the AppleEvents
application icon and the two document file icons AppleEvents Document A and AppleEvents
Document B.

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 (on Mac OS
8/9 only) Print from the Finder's File menu, choosing the application from the Apple menu), the
user should launch the application, open the simulated documents and (on Mac OS 8/9 only)
"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 running, the user should double-click the application icon, choose the
application from the Mac OS 8/9 Apple menu, or click the application icon and choose Open from
the Finder's File menu, noting the receipt of the Re-open Application event.  This should be
done when one or more "document" windows are open and when no "document windows are open.

The user should also choose Restart or Shut Down while the application is running, also noting
the displayed text resulting from receipt of the Quit Application event.  (On Mac OS X, the
Quit Application event is also received when Quit is chosen from the Application menu.)

On Mac OS 8/9, opening and printing should be attempted (from the Finder's File menu) when the
application is already running and when the application is not running.

On Mac OS X, the user should choose Show Preferences from the Application menu.

Note that, in this demonstration, it is possible to "open" each "document" more than once, that
is, it is possible to have several "Document A" and/or "Document B" windows open at once. (A
real application, of course, would permit only one "Document A" and/or one "Document B" window
to be open at any one time.)  The reason for this is that, in this demonstration, files are not
actually opened; accordingly, it is not possible to check whether the relevant file is already
open or not.

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 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:

o On Mac OS 8/9, the customised finder icon help override help balloon for the application
  icon.  (The 'hfdr' resource refers.)

o The version information for the application in the Finder's Get Info (Mac OS 8/9) and Show
  Info (Mac OS X) window and in the window containing the AppleEvents application when list 
  view is selected.

'plst' Resource

The following is the information property list in the application's 'plst' resource:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
<plist version="0.9">
<dict>
  <key>CFBundleInfoDictionaryVersion</key>
  <string>6.0</string>
  <key>CFBundleName</key>
  <string>AppleEvents</string>
  <key>CFBundlePackageType</key>
  <string>APPL</string>
  <key>CFBundleSignature</key>
  <string>KJBB</string>
  <key>CFBundleIconFile</key>
  <string>128</string>
  <key>CFBundleIdentifier</key>
  <string>com.Windmill Software.AppleEvents</string>
  <key>LSPrefersCarbon</key>
  <string>Yes</string>
  <key>CFBundleLongVersionString</key> 
  <string>Version 1.0.0 June 2001</string>
  <key>CFBundleShortVersionString</key> 
  <string>1.0.0</string>
  <key>CFBundleDevelopmentRegion</key>
  <string>English</string>
  <key>NSAppleScriptEnabled</key>
  <string>No</string>
  <key>CFBundleDocumentTypes</key>
  <array>
    <dict>
      <key>CFBundleTypeIconFile</key>
      <string>129</string>
      <key>CFBundleTypeName</key>
      <string>AppleEvents Document</string>
      <key>CFBundleTypeOSTypes</key>
      <array>
        <string>TEXT</string>
      </array>
      <key>CFBundleTypeRole</key>
      <string>Viewer</string>
    </dict>
  </array>
</dict>
</plist>

Global Variables

gRunningOnX will be set to true if the program is running on Mac OS X.

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
(on Mac OS 8/9) or resulted from the user choosing Restart of Shut Down from the Finder's
Special menu.

main

In the menus setting up block, if the program is running on Mac OS X, the Preferences item in
the Mac OS X Application menu is enabled.

The call to doInstallAEHandlers installs the Apple event handlers.

doInstallAEHandlers and doInstallAnAEHandler

doInstallAEHandlers, supported by doInstallAnAEHandler, installs the handlers for the required
Apple events, the Appearance Manager Apple events, and (if the program is running on Mac OS X)
the Show Preferences Apple event in the application's Apple event dispatch table.

In doInstallAnAEHandler, false is passed in AEInstallEventHandler's isSysHandler parameter. 
false causes the handler to be installed in the application's Apple event dispatch table.  true
causes handlers to be installed in the system's Apple event dispatch table.  (The system Apple
event dispatch table is a table in the system heap containing handlers that are available to
all applications and processes running on the same computer.)

doEvents

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.)

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 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.

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 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 doHasGotRequiredParams, and if there are currently no open windows, the
handler opens an untitled document window and returns noErr.

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 function doHasGotRequiredParams.

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 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 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 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 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
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 function
doHasGotRequiredParams, the handler calls the function doPrepareToTerminate.
doSysFontChangeEvent, doSmallSysFontChange, and doViewsFontChangeEvent
doSysFontChangeEvent, doSmallSysFontChange, and doViewsFontChangeEvent are the handlers for the
appearance Apple events.

The function doHasGotRequiredParams is called to check whether the Apple event contains any
required parameters.  If so, the handler returns an error because, by definition, these events
should not contain any required parameters.

The handlers then 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).

showPreferencesEventHandler

showPreferencesEventHandler is the handler for the Show Preferences Apple event.  It simply
draws some advosory text in the window to prove that the event was received.

doHasGotRequiredParams

doHasGotRequiredParams is the function called by doOpenAppEvent, doReopenAppEvent,
doSysFontChangeEvent, doSmallSysFontChange, and doViewsFontChangeEvent 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 Navigation
Services Open dialog.

doPrintFile

doPrintFile is applicable to Mac OS 8/9 only.  It 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 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 Mac OS
8/9 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 alerts to ascertain whether the user
wished to save 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.
 
AAPL
$96.12
Apple Inc.
-2.03
MSFT
$43.52
Microsoft Corpora
-0.06
GOOG
$575.28
Google Inc.
-12.14

MacTech Search:
Community Search:

Software Updates via MacUpdate

Ember 1.8 - Versatile digital scrapbook....
Ember (formerly LittleSnapper) is your digital scrapbook of things that inspire you: websites, photos, apps or other things. Just drag in images that you want to keep, organize them into relevant... Read more
OmniPlan 2.3.6 - Robust project manageme...
With OmniPlan, you can create logical, manageable project plans with Gantt charts, schedules, summaries, milestones, and critical paths. Break down the tasks needed to make your project a success,... Read more
Command-C 1.1.1 - Clipboard sharing tool...
Command-C is a revolutionary app which makes easy to share your clipboard between iOS and OS X using your local WiFi network, even if the app is not currently opened. Copy anything (text, pictures,... Read more
Knock 1.1.7 - Unlock your Mac by knockin...
Knock is a faster, safer way to sign in. You keep your iPhone with you all the time. Now you can use it as a password. You never have to open the app -- just knock on your phone twice, even when it's... Read more
Mellel 3.3.6 - Powerful word processor w...
Mellel is the leading word processor for OS X and has been widely considered the industry standard since its inception. Mellel focuses on writers and scholars for technical writing and multilingual... Read more
LibreOffice 4.3.0.4 - Free Open Source o...
LibreOffice is an office suite (word processor, spreadsheet, presentations, drawing tool) compatible with other major office suites. The Document Foundation is coordinating development and... Read more
Freeway Pro 7.0 - Drag-and-drop Web desi...
Freeway Pro lets you build websites with speed and precision... without writing a line of code! With it's user-oriented drag-and-drop interface, Freeway Pro helps you piece together the website of... Read more
Drive Genius 3.2.4 - Powerful system uti...
Drive Genius is an OS X utility designed to provide unsurpassed storage management. Featuring an easy-to-use interface, Drive Genius is packed with powerful tools such as a drive optimizer, a... Read more
Vitamin-R 2.15 - Personal productivity t...
Vitamin-R creates the optimal conditions for your brain to work at its best by structuring your work into short bursts of distraction-free, highly focused activity alternating with opportunities for... Read more
Toast Titanium 12.0 - The ultimate media...
Toast Titanium goes way beyond the very basic burning in the Mac OS and iLife software, and sets the standard for burning CDs, DVDs, and now Blu-ray discs on the Mac. Create superior sounding audio... Read more

Latest Forum Discussions

See All

Puzzle Roo Review
Puzzle Roo Review By Jennifer Allen on July 31st, 2014 Our Rating: :: PUZZLE-BASED TWISTUniversal App - Designed for iPhone and iPad A different take on the usual block dropping puzzle game, Puzzle Roo is quite pleasant.   | Read more »
Super Crossfire Re-Release Super Crossfi...
Super Crossfire Re-Release Super Crossfighter Coming Soon, Other Radiangames Titles Go 50% Off Posted by Ellis Spice on July 31st, 2014 [ | Read more »
Hexiled Review
Hexiled Review By Rob Thomas on July 31st, 2014 Our Rating: :: HEX SELLSUniversal App - Designed for iPhone and iPad In space, no one can hear you… spell? Hexiled is a neat concept for a word scramble puzzle, but it doesn’t go too... | Read more »
Despicable Me: Minion Rush is One Year O...
Despicable Me: Minion Rush is One Year Old, Gets its Biggest Update Yet Posted by Jennifer Allen on July 31st, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Plants vs. Zombies 2 Enters the Second H...
Plants vs. Zombies 2 Enters the Second Half of the Dark Ages Posted by Ellis Spice on July 31st, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Why Does It Spin? (Games)
Why Does It Spin? 1.0 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0 (iTunes) Description: THERE'S ONLY ONE RULE: DON'T TOUCH THE WALLS! Do you think you're able to follow this simple rule even if you would have to... | Read more »
Ice Wings Plus (Games)
Ice Wings Plus 1.0 Device: iOS Universal Category: Games Price: $1.99, Version: 1.0 (iTunes) Description: THE GREAT ENDLESS RUNNER OF COMBAT JETS IS BACK !! With more than 680.000 downloads in the App Store, Ice Wings: Skies of Steel... | Read more »
Murl the Squirrel (Games)
Murl the Squirrel 1.0 Device: iOS Universal Category: Games Price: $.99, Version: 1.0 (iTunes) Description: Meet Murl. He is teased by a group of flying squirrels because he can't fly. Determined to show them he's can fly, he meets... | Read more »
Celleste (Games)
Celleste 0.1 Device: iOS Universal Category: Games Price: $2.99, Version: 0.1 (iTunes) Description: Lots of cute action with amazing 3D graphics and a new type of gameplay! Take control over the forces of the universe to help a group... | Read more »
Super Heavy Sword (Games)
Super Heavy Sword 0.0.1 Device: iOS Universal Category: Games Price: $.99, Version: 0.0.1 (iTunes) Description: Get Ready to Get HEAVY! Monster Robot Studios presents SUPER Heavy Sword! The sequel to the smash hit HEAVY sword which... | Read more »

Price Scanner via MacPrices.net

Save up to $130 on an iPad mini with Apple re...
The Apple Store has Certified Refurbished 2nd generation iPad minis with Retina Displays available for up to $130 off the cost of new models, starting at $339. Apple’s one-year warranty is included... Read more
iPad Cannibalization Threat “Overblown”
Seeking Alpha’s Kevin Greenhalgh observes that while many commentators think Apple’s forthcoming 5.5-inch panel iPhone 6 will cannibalize iPad sales, in his estimation, these concerns are being... Read more
Primate Labs Releases July 2014 MacBook Pro P...
Primate Labs’ John Poole has posted Geekbench 3 results for most of the new MacBook Pro models that Apple released on Tuesday. Poole observes that overall performance improvements for the new MacBook... Read more
Apple Re-Releases Bugfixed MacBook Air EFI Fi...
Apple has posted a bugfixed version EFI Firmware Update 2.9 a for MacBook Air (Mid 2011) models. The update addresses an issue where systems may take longer to wake from sleep than expected, and... Read more
Save $50 on the 2.5GHz Mac mini, plus free sh...
B&H Photo has the 2.5GHz Mac mini on sale for $549.99 including free shipping. That’s $50 off MSRP, and B&H will also include a free copy of Parallels Desktop software. NY sales tax only. Read more
Save up to $140 on an iPad Air with Apple ref...
Apple is offering Certified Refurbished iPad Airs for up to $140 off MSRP. Apple’s one-year warranty is included with each model, and shipping is free. Stock tends to come and go with some of these... Read more
$250 price drop on leftover 15-inch Retina Ma...
B&H Photo has dropped prices on 2013 15″ Retina MacBook Pros by $250 off original MSRP. Shipping is free, and B&H charges NY sales tax only: - 15″ 2.3GHz Retina MacBook Pro: $2249, $250 off... Read more
More iPad Upgrade Musings – The ‘Book Mystiqu...
Much discussed recently, what with Apple reporting iPad sales shrinkage over two consecutive quarters, is that it had apparently been widely assumed that tablet users would follow a two-year hardware... Read more
13-inch 2.5GHz MacBook Pro on sale for $999,...
Best Buy has the 13″ 2.5GHz MacBook Pro available for $999.99 on their online store. Choose free shipping or free instant local store pickup (if available). Their price is $100 off MSRP. Price is... Read more
Save up to $300 on an iMac with Apple refurbi...
The Apple Store has Apple Certified Refurbished iMacs available for up to $300 off the cost of new models. Apple’s one-year warranty is standard, and shipping is free. These are the best prices on... Read more

Jobs Board

Sr. Product Leader, *Apple* Store Apps - Ap...
**Job Summary** Imagine what you could do here. At Apple , great ideas have a way of becoming great products, services, and customer experiences very quickly. Bring Read more
Sr Software Lead Engineer, *Apple* Online S...
Sr Software Lead Engineer, Apple Online Store Publishing Systems Keywords: Company: Apple Job Code: E3PCAK8MgYYkw Location (City or ZIP): Santa Clara Status: Full Read more
Sr Software Lead Engineer, *Apple* Online S...
Sr Software Lead Engineer, Apple Online Store Publishing Systems Keywords: Company: Apple Job Code: E3PCAK8MgYYkw Location (City or ZIP): Santa Clara Status: Full Read more
*Apple* Solutions Consultant (ASC) - Apple (...
**Job Summary** The ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The ASC's role is to grow Apple Read more
Sr. Product Leader, *Apple* Store Apps - Ap...
**Job Summary** Imagine what you could do here. At Apple , great ideas have a way of becoming great products, services, and customer experiences very quickly. Bring Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.