*******************************************************************************
*
* fakeModalDialog and other supporting access routines and such.
* Version 3.0
*
* Copyright (c)
* Apple Computer, Inc.  1989-1990
* All Rights Reserved.
*
* Written by Eric Soldan.
*
* Developer Technical Support Apple II Sample Code
*
* The purpose of this code is to handle dialogs in a variety of ways
* that are more robust than what the toolbox offers.  It also supports
* the new movable/modeless dialog types described in the latest human
* interface guidelines.
*
*******************************************************************************
*
* Here is some C sample code that uses fakeModalDialog.  This code is
* for an about box.  What is different about this about box is that
* you can use menus while the about box is on the screen.  This means
* that you can use desk accessories while the about box is active.
* It also means that you can quit the application at this time.
* You can also close the about box with the close menu option.
*
* This sample uses the modal mode with menus for the about box.  Since
* menus are available, there is more support (code) necessary from the
* application.  The application has to detect that the user chose
* close from the menu and take appropriate action, for example.
*
* First, a little about fakeModalDialog:
*
* fakeModalDialog returns a long as a result.
* If the result is NULL:
*     Nothing happened.  Unlike ModalDialog, control is returned to
*     the application during null events.  This is so the application
*     can do stuff like switch cursors, or other idle tasks.
* If bit 31 of the result is true:
*     The user chose a menu item.  Bits 0-15 are the menu item ID.
*                                  Bits 16-30 are the menu ID.
* If bit 31 of the result is false:
*     The user clicked on a control.  Bits 0-30 are the control ID.

* Now, the sample code fragment:

*   #define aboutBoxID 0x1001L
*
*   void    doAboutBox()
*   {
*       WindowPtr       wptr, keepPort;
*       unsigned long   id;
*       unsigned int    item;
*       keepPort = GetPort();   /* Preserve the current port. */
*
*       wptr = NewWindow2(NULL, NULL, NULL, NULL, 2, aboutBoxID, rWindParam1);
*           /* Open the about box from a resource. */
*
*       if (!_toolErr) {            /* If the window opened successfully... */
*           aboutWindow = wptr;     /* Set the aboutWindow global variable. */
*                                   /* This tells other routines what state */
*                                   /* we are in.                           */
*
*           for (;;) {      /* Loop, due to NULL events being returned. */
*
*               id = fakeModalDialog(
*                   &event,         /* Pointer to extended event record.   */
*                   NULL,           /* Use default update procedure.       */
*                   NULL,           /* There will be no event mods.        */
*                   NULL,           /* Do standard beep.                   */
*                   fmdMenuSelect+  /* Allow pullDowns.                    */
*                   fmdMenuKey+     /* Allow menu keys.                    */
*                   fmdDeskAcc+     /* Allow desk accessories.             */
*                   fmdUpdateAll    /* Update all windows, not just about. */
*               );
*
*               item = id;          /* Get lo-word from result. */
*
*               if (id & 0x80000000L) {             /* If menu command...    */
*                   if (item == 255) {              /* If close command then */
*                       HiliteMenu(0, FileMenuID);  /* turn menu inv. off.   */
*                       break;                      /* Go close about box.   */
*                   }
*                   doMenuCommand(id);      /* Do other menus (like quit).   */
*                   if (quitFlag) break;    /* User did do a quit from menu. */
*               }
*               else {                          /* ...else handle controls. */
*                   if (item == 1) break;       /* User clicked OK button.  */
*               }
*           }
*
*           SetPort(keepPort);      /* Put port back before closing about. */
*           CloseWindow(wptr);      /* Close aboutBox.                     */
*           aboutWindow = NULL;     /* Let others know it is closed.       */
*           appSetMenus();          /* Update the menus to reflect a new.  */
*       }                           /* top window.                         */
*   }

* An interesting point here is the call to appSetMenus.  This is a routine
* in the application that is responsible for putting the menus in the
* correct state.  fakeModalDialog automatically calls this routine (if told
* to) whenever an activate event occurs that it gets a chance to see.
* fakeModalDialog may not see the activate event  only if a desk accessory
* is open, just behind the about box.  When the about box is closed, the
* desk accessory gets the activate event.  fakeModalDialog never got an
* activate event, so it didn't know to call the menu update routine.  This
* situation can only occur when a desk accessory is just behind the window
* to be closed.  As a safe rule, whenever a window is closed, the menu
* update routine should be called by the application.  (Something like this
* should be done anyway.)

* To tell fakeModalDialog to automatically call a menu update routine when
* it gets an activate event, make a call to fmdSetMenuProc.  For an application
* menu update routine called appSetMenus, you would tell fakeModalDialog
* about it by the following:
*     fmdSetMenuProc(appSetMenus);
* To turn off menu updating again, do this:
*     fmdSetMenuProc(NULL);

* fmdEditMenu figures the state of cut, copy, paste, and clear in
* the edit menu based on the state of controls in the window.
* It looks up the target control (either lineEdit or textEdit) and
* then sets the states appropriately.  For lineEdit, if anything
* is selected, then cut, copy and clear are available.  If there is
* anything in the scrap, then paste is also available.  TextEdit 
* works the same way, unless the textEdit control is a read-only
* control.  In that case, cut, paste, and clear are not available.
* If there is no lineEdit or textEdit control, then the state of
* these menu items is left alone.  The application needs to take care
* of them in that case.  (It is possible that there are custom
* controls for the application that can use these menu items, and
* there is no way for fakeModalDialog to know about them.  Therefore
* the correct thing to do is to do nothing.)

* fmdFindCursorCtl is used to find which control is at a certain point.
* The toolbox call FindControl can't be used for this because textEdit
* controls become active when called with a point in them.  That is not
* the desired effect of fmdFindCursorCtl.  If you just want to know what
* control you are over and have nothing affected, then use this entry
* point.  It is used by fakeModalDialog to determine whether or not to
* display an i-beam cursor.  If the i-beam bit is set and the user moves
* the mouse over a lineEdit or textEdit control, then the cursor changes
* to an i-beam.  Note that the scrollbars for a textEdit control are
* considered a separate control.  This is so that the cursor stays
* an arrow when over the scrollbars.

* Back to fakeModalDialog:

* Some sample calls (in C) would look like:
*   ctlID = fakeModalDialog(&event, NULL, NULL, NULL, 0);
*   ctlID = fakeModalDialog(&event, updateProc, NULL, -1L, 0);
*   ctlID = fakeModalDialog(&event, updateProc, eventHook, beepProc, flags);
*
* The parameters are:
*
* event:          A pointer to an extended (for 5.0) event record.
* updateProc:     Pointer to function to update the window.  Pass a NULL for
*                 default.  (The default entry point is called fmdStdDrawProc.)
* eventHook:      Pointer to function that is called after the GetNextEvent
*                 call and before any processing occurs on that event.  This
*                 is more useful than a filter.  You can simply change the
*                 event by changing the event record.  For example:  Let's say
*                 that you want to be able to cancel a modal dialog by pressing
*                 either openApple-period or ESC.  The problem is that,
*                 although you can have two key equivalents for a
*                 super-control, theway that modifiers are determined is the
*                 same for both keys.  This means that you can't have
*                 openApple-period and ESC asyour two key equivalents.  With
*                 this event hook, you can lookat the event, and if it is the
*                 openApple-period, you can simply change the event record so
*                 that it is an ESC with no openApple modifier.  Then when you
*                 return to fakeModalDialog, it will handle the event as if the
*                 user simply typed an ESC.  By using this technique, you can
*                 have as many modifiers as you want.  If you wish to filter
*                 out an event, you would simply changethe event type to a
*                 NULL event.
* beepProc:       Pointer to custom beep function.  fakeModalDialog calls this
*                 if there is any mouseDown outside the window, just like
*                 ModalDialog.If you wish it to beep like ModalDialog, pass a
*                 NULL.  If you wish it to do nothing, pass a -1.
*                 If you wish a custom beep function, pass it a pointer to
*                 that function.
* flags, bit 0:   Cut/Copy/Paste for lineEdit items would normally involve
*                 the scrap.  When this bit is true, the scrap is not involved
*                 when using lineEdit items.  This may be useful to protect a
*                 large scrap for an application from being hit with something
*                 trivial.
*        bit 1:   If true, allow menu pullDowns for movable/modal dialogs.
*                 If they are allowed, then the return value is the menu
*                 item ID (low-word) and the menu ID (hi-word).  To
*                 distinguish from ctlID's, thehi-bit (bit 31) is set.  This
*                 means that if you are allowing menu selections, you can't have
*                 any menu ID's with a hi-bit-on ID.  It also means that you
*                 can't have controls with bit 31 on either.
*        bit 2:   If true, allow menu keys.  Return values work the same as for
*                 pullDowns.
*        bit 3:   If true, use i-beam cursor for lineEdit & textEdit ctls.
*                 Otherwise, use an arrow cursor everywhere.
*        bit 4:   If true, automatically handle desk accessories.  This means
*                 that bit 1 must be true to have fakeModalDialog open the DA.
*                 If the DA is already open, the user can click on it, and it
*                 will become active, even if bit 1 is false.
*        bit 14:  If true, update all windows.  The toolbox call ModalDialog
*                 does not update other windows.  This takes away a lot of the
*                 point of movable/modal dialogs.  The whole point is so that
*                 you can see what is behind it.  When you move the dialog, if
*                 the windows in back didn't update, then there would be no
*                 point in moving the window.  If you want, you can set this
*                 bit false, and it will update only the front-most
*                 application window.
*        bit 15:  This is the bit that determines whether or not a dialog is
*                 movable.  If it is true, then the dialog is movable.  To be
*                 moved, however, it has to have a title bar (the drag region)
*                 and it has to have the fMove bit set.  Without these also,
*                 the window still won't be able to be moved.
*                 
* ctlID:          Control that was hit, or menu that was chosen.
*                 bit 31 off, it is a control ID.
*                 bit 31 on, it is a menu ID (hi-word), menu item ID (lo-word).
*
* There is one more thing to worry about, and that is the border of the window.
* The window manager doesn't allow you have an alert frame and a title at the
* same time.  If you set both of these bits in the wFrameBits field, then the
* alert border is drawn wrong.  It would be ideal for fakeModalDialog if this
* restriction didn't exist.  Then the window attributes all could be chosen via
* the window frame bits in a resource.  Unfortunately, this isn't the case.  To
* manage this restriction, the default update procedure, under certain
* conditions, draws the alert frame itself.  If fAlert is set, then the alert
* border isn't drawn by the default update procedure.  The update procedure
* doesn't have to draw it, since it is automatically drawn by the window
* manager.  If fAlert is set, then the dialog doesn't have a title bar, due to
* the window manager restriction.  If fAlert isn't set, then the default update
* procedure draws the alert border.  The alert border is drawn as part of the
* content of the window.  Due to this, the coordinates you use for the content
* of the window have to be a little different, to make space for the border.
* The upper-left-hand corner of the window is really 10,4, (4,4 for 320 mode)
* instead of 0,0.  So far, we have discussed how the alert border gets drawn,
* either by the window manager, or by the default update procedure for
* fakeModalDialog.  It is possible that you don't want an alert border at all.
* If you don't, then fAlert should be off, and you should turn on fFlex.  fFlex
* was used because it should be able to be set from a resource, and all other
* bits would have an adverse effect.  Dialogs don't have grow boxes and zoom
* boxes, so fFlex is meaningless for dialogs (until now).
