Back to home page

MITgcm

 
 

    


File indexing completed on 2018-03-02 18:44:52 UTC

view on githubraw file Latest commit ec6cf3b0 on 2003-08-26 20:45:25 UTC
ec6cf3b09d Ed H*0001 /* macnapp.c -- macintosh nifty application library
                0002  */
                0003 /* (C) Copyright 1995 by Carnegie Mellon University
                0004  * All Rights Reserved.
                0005  *
                0006  * Permission to use, copy, modify, distribute, and sell this software
                0007  * and its documentation for any purpose is hereby granted without
                0008  * fee, provided that the above copyright notice appear in all copies
                0009  * and that both that copyright notice and this permission notice
                0010  * appear in supporting documentation, and that the name of Carnegie
                0011  * Mellon University not be used in advertising or publicity
                0012  * pertaining to distribution of the software without specific,
                0013  * written prior permission.  Carnegie Mellon University makes no
                0014  * representations about the suitability of this software for any
                0015  * purpose.  It is provided "as is" without express or implied
                0016  * warranty.
                0017  *
                0018  * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
                0019  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
                0020  * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
                0021  * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                0022  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
                0023  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
                0024  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
                0025  * SOFTWARE.
                0026  */
                0027 /* (C) Copyright 1990-1995 by Christopher J. Newman
                0028  * All Rights Reserved.
                0029  *
                0030  * Permission to use, copy, modify, distribute, and sell this software and its
                0031  * documentation for any purpose is hereby granted without fee, provided that
                0032  * the above copyright notice appear in all copies and that both that
                0033  * copyright notice and this permission notice appear in supporting
                0034  * documentation, and that the name of Christopher J. Newman not be used in
                0035  * advertising or publicity pertaining to distribution of the software without
                0036  * specific, written prior permission.  Christopher J. Newman makes no
                0037  * representations about the suitability of this software for any purpose.  It
                0038  * is provided "as is" without express or implied warranty.
                0039  *
                0040  * CHRISTOPHER J. NEWMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
                0041  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT
                0042  * SHALL CHRISTOPHER J. NEWMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR
                0043  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
                0044  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
                0045  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
                0046  * OF THIS SOFTWARE.
                0047  *
                0048  * Author:  Christopher J. Newman
                0049  * Message: This is a nifty program.
                0050  */
                0051 
                0052 #ifndef THINK_C
                0053 #include <Resources.h>
                0054 #include <Dialogs.h>
                0055 #include <Desk.h>
                0056 #include <SegLoad.h>
                0057 #include <OSEvents.h>
                0058 #include <DiskInit.h>
                0059 #include <Traps.h>
                0060 #include <ToolUtils.h>
                0061 #endif
                0062 #include <AppleEvents.h>
                0063 #include "macnapp.h"
                0064 
                0065 /* export globals */
                0066 na_win **NAhead = (na_win**) NULL;      /* head of the window tree */
                0067 na_win **NAtask = (na_win**) NULL;      /* head of the task list */
                0068 na_win **NActask = (na_win**) NULL;     /* next task to be called */
                0069 na_win *NAwin = (na_win*) NULL;         /* the current window */
                0070 na_menup NAmenup = (na_menup) NULL;     /* application menu procedure */
                0071 MenuHandle **NAmenus;                   /* list of menu handles */
                0072 short NAnewitem = 0;                    /* the new item number */
                0073 short NAcloseitem = 0;                  /* the close item number */
                0074 short NAappleitems = 0;                 /* number of user apple menu items */
                0075 short NAhelpitems = 0;                  /* number of user help menu items */
                0076 short NAhelpcount = 0;                  /* number of system help menu items */
                0077 Boolean NAhasedit = false;              /* true if application supports edit menu */
                0078 long NAdelay = 30;                      /* delay (1/60th of a second) between null events */
                0079 SysEnvRec NAsysenv;                     /* set up by Initialize */
                0080 Boolean NAinBack = false;               /* true when app is in the background */
                0081 short NAlastmouse = NA_RELEASE;         /* the last mouse event type */
                0082 long NAmousetime = 0;                   /* the time of the last mouse up */
                0083 Point NAmousept;                        /* the point (local) of last mouse down */
                0084 
                0085 THz NAappzone;                          /* the application heap zone */
                0086 RgnHandle NAfullRgn;                    /* a region containing everything */
                0087 RgnHandle NAnullRgn;                    /* a region containing nothing */
                0088 Cursor NAibeam;                         /* the Ibeam cursor */
                0089 long NAgestaltBits;                     /* flags for gestalt options */
                0090 
                0091 /* private globals */
                0092 static Point    mselpoint;              /* the menu selection point */
                0093 static short    aestatus;               /* if set, close everything */
                0094 
                0095 /* constants for DoDraw procedure */
                0096 #define DO_UPDATE       0x0
                0097 #define DO_RESIZE       0x1
                0098 #define DO_ACTIVATE     0x2
                0099 #define DO_DEACTIVATE   0x4
                0100 
                0101 /* private routines */
                0102 
                0103 static na_win **GetWinH(WindowPtr);
                0104 static void DoDraw(na_win*, short);
                0105 static short DoActivate(WindowPtr, na_win*, Boolean, Point p);
                0106 static short DoMenu(na_win*, BYTE);
                0107 static void AdjustCursor(na_win*, Point, Boolean);
                0108 static short aboutmouse(na_win*, Point, short, short);
                0109 
                0110 /* get the handle to a window
                0111  */
                0112 static na_win **GetWinH(WindowPtr window)
                0113 {
                0114     na_win      **winh;
                0115     
                0116     /* make positively sure that we have a valid handle */
                0117     if (window != (WindowPtr) NULL && !NAisDAWindow(window)) {
                0118 #ifdef DEBUG
                0119         if (PtrZone((Ptr) window) == NAappzone && MemError() == noErr) {
                0120 #endif
                0121             if ((winh = (na_win **) GetWRefCon(window)) != (na_win**) NULL) {
                0122 #ifdef DEBUG
                0123                 if (HandleZone((Handle) winh) == NAappzone && MemError() == noErr) {
                0124                     if ((*winh)->pwin == window) {
                0125 #endif
                0126                         return (winh);
                0127 #ifdef DEBUG
                0128                     } else {
                0129                         NAdebug("Corrupted window structure found.\015");
                0130                         NAdebug("handle: %lx, pwin: %lx, window: %lx\015",
                0131                             (long) winh, (long) (*winh)->pwin, (long) window);
                0132                         Debugger();
                0133                     }
                0134                 } else {
                0135                     NAdebug("Corrupted Handle Zone Found.\015");
                0136                     NAdebug("handle: %lx, error: %ld\015", (long) winh,
                0137                         (long) MemError());
                0138                     Debugger();
                0139                 }       
                0140 #endif
                0141             }
                0142 #ifdef DEBUG
                0143         } else {
                0144             NAdebug("Corrupted Window Pointer Found.\n");
                0145             NAdebug("Pointer: %lx, error: %ld\n", (long) window, (long) MemError());
                0146             Debugger();
                0147         }
                0148 #endif
                0149     }
                0150     return ((na_win**) NULL);
                0151 }
                0152 
                0153 /* handle drawing controls & growbox for update/activate events
                0154  */
                0155 static void DoDraw(na_win *winp, short how)
                0156 {
                0157     WindowPtr window = winp->pwin;
                0158     long flags = winp->flags;
                0159     ControlHandle ctrl;
                0160     Rect tmpRect;
                0161     RgnHandle tmpRgn;
                0162 
                0163     /* hilite or draw controls as appropriate */
                0164     if (flags & NA_HASCONTROLS) {
                0165         if (how & (DO_ACTIVATE | DO_DEACTIVATE)) {
                0166             if (flags & NA_HILITECTRLS) {
                0167                 for (ctrl = ((WindowPeek) window)->controlList; ctrl;
                0168                         ctrl = (*ctrl)->nextControl) {
                0169                     HiliteControl(ctrl, (how & DO_ACTIVATE) ? 0 : 255);
                0170                 }
                0171             }
                0172         } else {
                0173             DrawControls(window);
                0174         }
                0175     }
                0176     
                0177     /* draw the grow box properly -- mask out scroll bar outlines */
                0178     if (flags & NA_GROWBOX) {
                0179         tmpRgn = window->clipRgn;
                0180         tmpRect.left = (tmpRect.right = window->portRect.right) - 15;
                0181         tmpRect.top = (tmpRect.bottom = window->portRect.bottom) - 15;
                0182         RectRgn(window->clipRgn = NewRgn(), &tmpRect);
                0183         DrawGrowIcon(window);
                0184         DisposeRgn(window->clipRgn);
                0185         window->clipRgn = tmpRgn;
                0186     }
                0187     
                0188     /* draw the default button on a dialog */
                0189     if (flags & NA_DEFBUTTON) NAdefaultButton(window);
                0190     
                0191     /* calculate the un-cursor region if the window size changed */
                0192     if (how & DO_RESIZE) NAcalcCursor(winp);
                0193 }
                0194 
                0195 /* handle activate event (either activate or MultiFinder suspend/resume)
                0196  */
                0197 static short DoActivate(WindowPtr window, na_win *winp, Boolean activate, Point p)
                0198 {
                0199     na_win **winh;
                0200     short   status = NA_NOTPROCESSED;
                0201     GrafPtr tmpPort;
                0202 
                0203     /* unlock current front window */
                0204     if (winp != (na_win*) NULL) {
                0205         NAunlockWindow(winp);
                0206         NAwin = (na_win*) NULL;
                0207     }
                0208     
                0209     /* check if there is a new window, and lock it */
                0210     if (window == (WindowPtr) NULL)  return (NA_PROCESSED);
                0211     
                0212     /* for app windows, update the cursor, call the activate proc, and DoDraw */
                0213     if ((NAwin = winp = NAlockWindow(winh = GetWinH(window))) != (na_win*) NULL) {
                0214         GetPort(&tmpPort);
                0215         SetPort(window);
                0216         if (winp->cursorRgn != (RgnHandle) NULL && ((activate && !NAinBack)
                0217                 || winp->flags & NA_CURSORON)) {
                0218             LocalToGlobal(&p);
                0219             AdjustCursor(winp, p, activate);
                0220         }
                0221         if (winp->activep == (na_activep) NULL
                0222                 || (status = (*winp->activep)(winp, activate)) == NA_NOTPROCESSED) {
                0223             DoDraw(winp, activate ? DO_ACTIVATE : DO_DEACTIVATE);
                0224         }
                0225         if (!activate || winp->pwin != FrontWindow()) {
                0226             SetPort(tmpPort);
                0227             NAunlockWindowh(winh, winp);
                0228             NAwin = (na_win*) NULL;
                0229         }
                0230     }
                0231     
                0232     return (status);
                0233 }
                0234 
                0235 /* handle menu selection -- either menu click or menu shortcut
                0236  */
                0237 static short DoMenu(na_win *winp, BYTE key)
                0238 {
                0239     WindowPtr   window = FrontWindow();
                0240     short       status = NA_NOTPROCESSED;
                0241     WORD        menuid, itemno;
                0242     MenuHandle  mnu;
                0243     long        menusel;
                0244     PCstr       mItem[256];
                0245     
                0246     /* enable/disable edit menu as appropriate */
                0247     if (NAhasedit) {
                0248         mnu = NAmenuh(mEdit);
                0249         
                0250         if (NAisDAWindow(window)) {
                0251             EnableItem(mnu, iUndo);
                0252             for (itemno = iCut; itemno <= iClear; itemno++) {
                0253                 EnableItem(mnu, itemno);
                0254             }
                0255         } else {
                0256             DisableItem(mnu, iUndo);
                0257             for (itemno = iCut; itemno <= iClear; itemno++) {
                0258                 DisableItem(mnu, itemno);
                0259             }
                0260         }
                0261     }
                0262     
                0263     /* enable/disable the close menu as appropriate */
                0264     if (NAcloseitem) {
                0265         mnu = NAmenuh(mFile);
                0266         
                0267         if (window != (WindowPtr) NULL && (winp == (na_win*) NULL
                0268                 || winp->pwin != window || winp->flags & NA_CLOSEBOX)) {
                0269             EnableItem(mnu, NAcloseitem);
                0270         } else {
                0271             DisableItem(mnu, NAcloseitem);
                0272         }
                0273     }
                0274     
                0275     /* call menu proc to enable/disable items as appropriate */
                0276     if (winp != (na_win*) NULL && winp->menup != (na_menup) NULL) {
                0277         status = (*winp->menup)(winp, (WORD) 0, (WORD) key);
                0278     }
                0279     if (status == NA_NOTPROCESSED && NAmenup != (na_menup) NULL
                0280         && (winp == (na_win *) NULL || !(winp->flags & NA_MODAL))) {
                0281         status = (*NAmenup)(winp, (WORD) 0, (WORD) key);
                0282     }
                0283     if (status != NA_NOTPROCESSED) return (status);
                0284     
                0285     /* get menu selection */
                0286     menusel = (key == 0) ? MenuSelect(mselpoint) : MenuKey(key);
                0287     itemno = LOWORD(menusel);
                0288     if ((menuid = HIWORD(menusel)) == 0) menuid = 1;
                0289     
                0290     /* check for DA menu items */
                0291     switch (menuid) {
                0292         case mApple:    /* check for a desk accessary selection */
                0293             if (itemno > NAappleitems) {
                0294                 if (itemno - NAappleitems <= NAhelpitems) {
                0295                     itemno -= NAappleitems;
                0296                     menuid = mHelp;
                0297                 } else {
                0298                     GetItem(NAmenuh(mApple), itemno, mItem);
                0299                     OpenDeskAcc(mItem);
                0300                     menuid = 1;
                0301                 }
                0302             }
                0303             break;
                0304         
                0305         case mFile:     /* check for the close menu item for DAs */
                0306             if (itemno == NAcloseitem && NAisDAWindow(window)) {
                0307                 CloseDeskAcc(((WindowPeek) window)->windowKind);
                0308                 menuid = 1;
                0309             }
                0310             break;
                0311     
                0312         case mEdit:     /* check for the edit menu for DAs */
                0313             if (NAhasedit && itemno <= iClear && SystemEdit(itemno - iUndo)) {
                0314                 menuid = 1;
                0315             }
                0316             break;
                0317         
                0318         case mHelp:
                0319             itemno -= NAhelpcount;
                0320             break;
                0321     }
                0322     
                0323     /* call menu proc to handle/disable items */
                0324     if (winp != (na_win*) NULL && winp->menup != (na_menup) NULL) {
                0325         status = (*winp->menup)(winp, menuid, itemno);
                0326     }
                0327     if (status != NA_PROCESSED && NAmenup != (na_menup) NULL) {
                0328         status = (*NAmenup)(winp, menuid, itemno);
                0329     }
                0330     
                0331     /* if close/about item wasn't processed, process it */
                0332     if (status == NA_NOTPROCESSED) {
                0333         if (menuid == mFile && itemno == NAcloseitem) {
                0334             status = NA_REQCLOSE;
                0335         } else if (menuid == mApple && itemno == iAbout) {
                0336             NAwindow(0, NA_DIALOGWINDOW | NA_USERESOURCE | NA_MODAL,
                0337             NULL, NA_ABOUTDLOG, (long *) NULL, 0, NAabout);
                0338         }
                0339     }
                0340     
                0341     /* turn off the menu */
                0342     HiliteMenu(0);
                0343     
                0344     return (status);
                0345 }
                0346 
                0347 /* set the cursor icon appropriately
                0348  */
                0349 static void AdjustCursor(na_win *winp, Point gmouse, Boolean active)
                0350 {
                0351     short   status = NA_NOTPROCESSED;
                0352     
                0353     /* don't change the cursor when in wrong window */
                0354     if (active && FrontWindow() != winp->pwin) return;
                0355     
                0356     /* if the cursor is on */
                0357     if (winp->flags & NA_CURSORON) {
                0358         /* and the point moves outside the cursor region or window is deactivated
                0359          * turn cursor off */
                0360         if (!active || PtInRgn(gmouse, winp->uncrsrRgn)) {
                0361             winp->flags &= ~NA_CURSORON;
                0362             if (winp->cursorp == (na_cursorp*) NULL) {
                0363                 SetCursor(&QD(arrow));
                0364             } else {
                0365                 goto DOCURSORP;
                0366             }
                0367         }
                0368     
                0369     /* if the cursor is off and the point moves into the window, turn cursor on */
                0370     } else if (PtInRgn(gmouse, winp->cursorRgn)) {
                0371         winp->flags |= NA_CURSORON;
                0372         if (winp->cursorp == (na_cursorp) NULL) {
                0373             SetCursor(&NAibeam);
                0374         } else {
                0375         DOCURSORP:
                0376             GlobalToLocal(&gmouse);
                0377             status = (*winp->cursorp)(winp, gmouse);
                0378         }
                0379     }
                0380     
                0381     /* if cursor event was processed, reset the un-cursor region */
                0382     if (status == NA_PROCESSED) NAcalcCursor(winp);
                0383 }
                0384 
                0385 
                0386 /* export routines */
                0387 
                0388 /* save the current window position in a resource file
                0389  */
                0390 void NAsaveWin(na_win *winp)
                0391 {
                0392     Rect        *rptr;
                0393     WindowPtr   window = winp->pwin;
                0394     Handle      wind = GetResource('WIND', winp->resid);
                0395     
                0396     HLock(wind);
                0397     rptr = (Rect *) *wind;
                0398     rptr->right = (rptr->left = -window->portBits.bounds.left)
                0399         + window->portRect.right;
                0400     rptr->bottom = (rptr->top = -window->portBits.bounds.top)
                0401         + window->portRect.bottom;
                0402     ChangedResource(wind);
                0403     HUnlock(wind);
                0404 }
                0405 
                0406 /* calculate the cursor regions for Multi-Finder
                0407  */
                0408 void NAcalcCursor(na_win *winp)
                0409 {
                0410     if (winp->cursorRgn != (RgnHandle) NULL) {
                0411         if (winp->uncrsrRgn == (RgnHandle) NULL)  winp->uncrsrRgn = NewRgn();
                0412         DiffRgn(NAfullRgn, winp->cursorRgn, winp->uncrsrRgn);
                0413     }
                0414 }
                0415 
                0416 /* lock a window context
                0417  */
                0418 na_win *NAlockWindow(na_win **winh)
                0419 {
                0420     if (winh == (na_win**) NULL) return ((na_win*) NULL);
                0421     if (!(*winh)->locks++) {
                0422         MoveHHi((Handle) winh);
                0423         HLock((Handle) winh);
                0424     }
                0425     
                0426     return (*winh);
                0427 }
                0428 
                0429 /* request or force a window to close
                0430  */
                0431 short NAcloseWindow(na_win *winp, short status)
                0432 {
                0433     na_win  **winh, ***whp;
                0434     short childstatus;
                0435     
                0436     if (winp == (na_win*) NULL) return (NA_NOTPROCESSED);
                0437     switch (status) {
                0438         case NA_REQCLOSE:
                0439             /* check if window ready to close */
                0440             status = NA_CLOSED;
                0441             if (winp->closep != (na_closep) NULL) status = (*winp->closep)(winp);
                0442             if (status > NA_CLOSED)     break;
                0443         case NA_CLOSED:
                0444             /* close children */
                0445             childstatus = NAcloseWindows(winp->child, NA_REQCLOSEALL);
                0446             /* clear current window */
                0447             if (winp == NAwin) NAwin = (na_win*) NULL;
                0448             /* reset the cursor */
                0449             if (winp->flags & NA_CURSORON) SetCursor(&QD(arrow));
                0450             /* dispose of any cursor regions */
                0451             if (winp->cursorRgn != (RgnHandle) NULL) DisposeRgn(winp->cursorRgn);
                0452             if (winp->uncrsrRgn != (RgnHandle) NULL) DisposeRgn(winp->uncrsrRgn);
                0453             /* close the window */
                0454             if (winp->pwin != (WindowPtr) NULL) {
                0455                 if (winp->flags & NA_DIALOGWINDOW) {
                0456                     DisposDialog((DialogPtr) winp->pwin);
                0457                 } else {
                0458                     DisposeWindow(winp->pwin);
                0459                 }
                0460             }
                0461             /* remove from window list */
                0462             winh = (na_win**) RecoverHandle((Ptr) winp);
                0463             whp = &NAhead;
                0464             if (winp->parent != (na_win**) NULL) whp = &(*winp->parent)->child;
                0465             while (*whp != (na_win**) NULL) {
                0466                 if (*whp == winh) {
                0467                     *whp = winp->next;
                0468                 } else {
                0469                     whp = &(**whp)->next;
                0470                 }
                0471             }
                0472             /* relink children in list */
                0473             if (childstatus > NA_ALLCLOSED) {
                0474                 *whp = winp->child;
                0475                 do {
                0476                     (**whp)->parent = winp->parent;
                0477                     whp = &(**whp)->next;
                0478                 } while (*whp != (na_win**) NULL);
                0479                 *whp = winp->next;
                0480             }
                0481             /* remove from task list */
                0482             whp = &NAtask;
                0483             while (*whp != (na_win**) NULL && *whp != winh) {
                0484                 whp = &(**whp)->task;
                0485             }
                0486             *whp = winp->task;
                0487             NActask = (na_win**) NULL;
                0488             /* after-close function */
                0489             if (winp->afterp != (na_afterp) NULL) (*winp->afterp)(winp);
                0490             /* destroy window structure */
                0491             DisposHandle((Handle) winh);
                0492             if (status < NA_CLOSED) {
                0493                 if ((status = NAcloseWindows(NAhead, status)) > NA_CLOSED) {
                0494                     status = NA_CLOSED;
                0495                 }
                0496             }
                0497             break;
                0498     }
                0499     
                0500     return (status);            
                0501 }
                0502 
                0503 short NAcloseWindows(na_win **winh, short status)
                0504 {
                0505     na_win  *winp, **lasth;
                0506     short   substatus;
                0507     
                0508     while ((winp = NAlockWindow(winh)) != (na_win*) NULL) {
                0509         lasth = winh;
                0510         winh = winp->next;
                0511         substatus = NAcloseWindow(winp, status + 2);
                0512         if (substatus > NA_CLOSED) {
                0513             NAunlockWindowh(lasth, winp);
                0514             return (NA_NOTPROCESSED);
                0515         }
                0516         if (substatus < NA_CLOSED) return (substatus);
                0517     }
                0518     
                0519     return (NA_ALLCLOSED);
                0520 }
                0521 
                0522 /* remove the window on a mouse-up event
                0523  */
                0524 static short aboutmouse(na_win *winp, Point mousep, short type, short mods)
                0525 #ifdef applec
                0526 #pragma unused (winp, mousep, mods)
                0527 #endif
                0528 {
                0529     return (type & 1 ? NA_REQCLOSE : NA_PROCESSED);
                0530 }
                0531 
                0532 /* a standard about box init procedure
                0533  */
                0534 short NAabout(na_win *winp, long *dptr)
                0535 #ifdef applec
                0536 #pragma unused (dptr)
                0537 #endif
                0538 {
                0539     winp->mousep = aboutmouse;
                0540     
                0541     return (NA_PROCESSED);
                0542 }
                0543 
                0544 /* flash a button in a dialog box for equivalent keypresses
                0545  */
                0546 void NAflashButton(DialogPtr dialog, short item)
                0547 {
                0548     long    scratch;
                0549     short   type;
                0550     Handle  ctrl;
                0551     Rect    box;
                0552     
                0553     GetDItem(dialog, item, &type, &ctrl, &box);
                0554     if (type == ctrlItem + btnCtrl) {
                0555         HiliteControl((ControlHandle) ctrl, 1);
                0556         Delay(5, &scratch);
                0557         HiliteControl((ControlHandle) ctrl, 0);
                0558     }
                0559 }
                0560 
                0561 /* draw the default button
                0562  */
                0563 void NAdefaultButton(DialogPtr dialog)
                0564 {
                0565     Rect tmpRect;
                0566     PenState pnState;
                0567     
                0568     NAgetDRect(dialog, iOk, &tmpRect);
                0569     GetPenState(&pnState);
                0570     PenNormal();
                0571     PenSize(3, 3);
                0572     InsetRect(&tmpRect, -4, -4);
                0573     FrameRoundRect(&tmpRect, 16, 16);
                0574     SetPenState(&pnState);
                0575 }
                0576 
                0577 /* a filter proc which handles Return, Enter, Esc, command-period properly
                0578  */
                0579 pascal Boolean NAfilterProc(DialogPtr dialog, EventRecord *pevent, short *item)
                0580 {
                0581     if (pevent->what == autoKey || pevent->what == keyDown) {
                0582         switch (pevent->message & charCodeMask) {
                0583             case '\r':
                0584             case '\n':
                0585             case 0x03:
                0586                 *item = 1;
                0587                 goto HILITE;
                0588             
                0589             case '.':
                0590                 if (!(pevent->modifiers & cmdKey)) break;
                0591             case '\033':
                0592                 *item = 2;
                0593             HILITE:
                0594                 NAflashButton(dialog, *item);
                0595                 return (true);
                0596         }
                0597     }
                0598     
                0599     return (false);
                0600 }
                0601 
                0602 /* send an event message to all windows
                0603  */
                0604 short NAallWindows(na_win **winh, EventRecord *pevent)
                0605 {
                0606     na_win *winp, **oldwinh;
                0607     short   status = NA_NOTPROCESSED;
                0608     
                0609     while ((winp = NAlockWindow(winh)) != (na_win*) NULL) {
                0610         oldwinh = winh;
                0611         winh = winp->next;
                0612         if (winp->miscp != (na_miscp) NULL) {
                0613             GrafPtr tempPort;
                0614             
                0615             GetPort(&tempPort);
                0616             SetPort(winp->pwin);
                0617             status = (*winp->miscp)(winp, pevent);
                0618             SetPort(tempPort);
                0619         }
                0620         if ((status == NA_CLOSED || status == NA_REQCLOSE)
                0621                 && NAcloseWindow(winp, status) == NA_CLOSED) {
                0622             continue;
                0623         }
                0624         NAunlockWindowh(oldwinh, winp);
                0625         if (status == NA_ALLCLOSED || status == NA_REQCLOSEALL) {
                0626             if (NAcloseWindows(NAhead, status) == NA_ALLCLOSED) {
                0627                 return (NA_ALLCLOSED);
                0628             }
                0629             /* make sure our handle is still valid */
                0630             if (GetHandleSize((Handle) oldwinh) == 0) continue;
                0631         }
                0632         if ((*oldwinh)->child != (na_win**) NULL &&
                0633                 NAallWindows((*oldwinh)->child, pevent) == NA_ALLCLOSED) {
                0634             return (NA_ALLCLOSED);
                0635         }
                0636     }
                0637     
                0638     return (NA_PROCESSED);
                0639 }
                0640 
                0641 /* apple event handler
                0642  */
                0643 pascal OSErr NArequiredAE(AppleEvent *, AppleEvent *, long);
                0644 pascal OSErr NArequiredAE(AppleEvent *event, AppleEvent *reply, long ref)
                0645 {
                0646     na_openp openp = (na_openp) ref;
                0647     OSErr err;
                0648     DescType actualType, eventID;
                0649     Size actualSize;
                0650     AEDescList doclist;
                0651     long count, i;
                0652     short gotdoc;
                0653     FSSpec fspec;
                0654     AEKeyword keywd;
                0655     FInfo finfo;
                0656     
                0657     err = AEGetAttributePtr(event, keyEventIDAttr, typeType, &actualType,
                0658         (Ptr) &eventID, sizeof (eventID), &actualSize);
                0659     if (err == noErr) {
                0660         gotdoc = 0;
                0661         if (eventID == kAEOpenDocuments || eventID == kAEPrintDocuments) {
                0662             err = AEGetParamDesc(event, keyDirectObject, typeAEList, &doclist);
                0663             if (err == noErr) gotdoc = 1;
                0664         }
                0665         if (err == noErr) {
                0666             err = AEGetAttributePtr(event, keyMissedKeywordAttr, typeWildCard,
                0667                 &actualType, NULL, 0, &actualSize);
                0668             if (err == errAEDescNotFound) {
                0669                 err = noErr;
                0670             } else if (err == noErr) {
                0671                 err = errAEEventNotHandled;
                0672             }
                0673         }
                0674         if (err == noErr) switch (eventID) {
                0675             case kAEOpenApplication:
                0676                 if (NAmenup && NAnewitem) {
                0677                     aestatus = (*NAmenup)(NULL, mFile, NAnewitem);
                0678                 }
                0679                 break;
                0680             case kAEOpenDocuments:
                0681             case kAEPrintDocuments:
                0682                 err = AECountItems(&doclist, &count);
                0683                 if (err != noErr) break;
                0684                 for (i = 1; i <= count; ++i) {
                0685                     err = AEGetNthPtr(&doclist, i, typeFSS, &keywd, &actualType,
                0686                         (Ptr) &fspec, sizeof (fspec), &actualSize);
                0687                     if (err != noErr) break;
                0688                     FSpGetFInfo(&fspec, &finfo);
                0689                     if (!openp || (*openp)(eventID == kAEOpenDocuments
                0690                                 ? appOpen : appPrint, &fspec, &finfo) <= 0) {
                0691                         err = errAEEventNotHandled;
                0692                         break;
                0693                     }
                0694                 }
                0695                 break;
                0696             case kAEQuitApplication:
                0697                 aestatus = NA_ALLCLOSED;
                0698                 if (NAhead != NULL) {
                0699                     aestatus = NAcloseWindows(NAhead, NA_REQCLOSEALL);
                0700                     if (aestatus != NA_ALLCLOSED) err = userCanceledErr;
                0701                 }
                0702                 break;
                0703         }
                0704         if (gotdoc) {
                0705             AEDisposeDesc(&doclist);
                0706         }
                0707     }
                0708     
                0709     return (err);
                0710 }
                0711 
                0712 /* handle Dialog window events
                0713  */
                0714 static Boolean DoDialog(na_win *winp, EventRecord *event, Point mouse,
                0715     short item, short *status)
                0716 {
                0717     DialogPtr dialog = NULL;
                0718     ControlHandle ctrlh;
                0719     Boolean result = false;
                0720     
                0721     if (*status == NA_NOTPROCESSED && (item || ((result = IsDialogEvent(event))
                0722         && DialogSelect(event, &dialog, &item))) && winp && winp->ctrlp) {
                0723         if (!dialog) dialog = winp->pwin;
                0724         NAgetDHandle(dialog, item, &ctrlh);
                0725         *status = (*winp->ctrlp)(winp, mouse, item, event->modifiers, ctrlh);
                0726     }
                0727     
                0728     return (result);
                0729 }
                0730 
                0731 /* call the main loop procedure
                0732  */
                0733 void NAmainloop()
                0734 {
                0735     na_win *winp, *wp, **wh;
                0736     Boolean gotEvent;
                0737     EventRecord event;
                0738     Point mouse;
                0739     Point ptemp;
                0740     short status;
                0741     short citem, item;
                0742     short part;
                0743     short delay;
                0744     short mousepix;
                0745     short fastdelay = 0;
                0746     long growInfo;
                0747     long key;
                0748     WindowPtr window;
                0749     GrafPtr tempPort;
                0750     ControlHandle ctrl;
                0751     RgnHandle rgn;
                0752     Rect tmpRect, bRect;
                0753     short prioritycnt;
                0754     
                0755     UnloadSeg((Ptr) NAinit);        /* unload the initialize routine */
                0756     
                0757     do {
                0758         /* check for a window in front */
                0759         if ((winp = NAwin) == (na_win*) NULL
                0760                 && (window = FrontWindow()) != (WindowPtr) NULL
                0761                 && (NAwin = winp = NAlockWindow(GetWinH(window))) != (na_win *) NULL) {
                0762             SetPort(window);
                0763         }
                0764     
                0765         /* get an event */
                0766         rgn = NAfullRgn;
                0767         delay = NAdelay;
                0768         /* if there is an app window in front, use app delay & cursor region */
                0769         if (winp != (na_win*) NULL) {
                0770             delay = winp->delay;
                0771             if (winp->cursorRgn != (RgnHandle) NULL && !NAinBack) {
                0772                 rgn = winp->cursorRgn;
                0773                 if (!(winp->flags & NA_CURSORON)) rgn = winp->uncrsrRgn;
                0774             }
                0775             if (winp->mousepix && !(NAlastmouse & 1)) {
                0776                 rgn = NAnullRgn;
                0777                 delay = 0;
                0778             }
                0779         }
                0780         gotEvent = WaitNextEvent(everyEvent, &event, fastdelay ? 0 : delay, rgn);
                0781         fastdelay = 0;
                0782         status = NA_NOTPROCESSED;
                0783         
                0784         /* get mouse position */
                0785         mouse = event.where;
                0786         GlobalToLocal(&mouse);
                0787         item = 0;
                0788 
                0789         /* handle the event */
                0790         if (gotEvent) switch (event.what) {
                0791             case mouseUp:
                0792                 /* deal with mouse up events to keep track of double/triple clicks */
                0793                 if (NAlastmouse & 1) break;
                0794                 ++NAlastmouse;
                0795                 NAmousetime = TickCount();
                0796                 if (winp == (na_win*) NULL) break;
                0797             DOMOUSEP:
                0798                 if (winp->mousep != (na_mousep) NULL) {
                0799                     status = (*winp->mousep)(winp, mouse, NAlastmouse, event.modifiers);
                0800                 }
                0801                 break;
                0802     
                0803             case mouseDown:
                0804                 part = FindWindow(event.where, &window);
                0805                 /* Rules for clicks when a modal dialog is in front:
                0806                  *  1) let the user command-move other windows
                0807                  *  2) don't let user do anything else with other app windows
                0808                  *  3) if not movable, require click to be in window
                0809                  */
                0810                 if (winp != (na_win*) NULL && winp->flags & NA_MODAL
                0811                     && !(part == inDrag && event.modifiers & cmdKey)
                0812                     && ((!(winp->flags & NA_TITLEBAR)
                0813                             && !PtInRect(mouse, &winp->pwin->portRect))
                0814                         || (window != NULL && window != winp->pwin))) {
                0815                     SysBeep(10);
                0816                     status = NA_PROCESSED;
                0817                     break;
                0818                 }
                0819                 switch (part) {
                0820                     case inMenuBar:
                0821                         /* call an appropriate menu bar handler */
                0822                         mselpoint = event.where;
                0823                         status = DoMenu(winp, 0);
                0824                         break;
                0825                         
                0826                     case inSysWindow:
                0827                         /* System Click in DA */
                0828                         SystemClick(&event, window);
                0829                         break;
                0830     
                0831                     case inContent:
                0832                         /* click a window to front if not in front */
                0833                         if (window != FrontWindow()) {
                0834                             SelectWindow(window);
                0835                             if (winp != (na_win*) NULL) NAunlockWindow(winp);
                0836                             NAwin = (na_win*) NULL;
                0837                             NAlastmouse = NA_RELEASE;
                0838                             break;
                0839                         }
                0840                         
                0841                         /* don't bother processing further if no mouse proc */
                0842                         if (winp == (na_win*) NULL) break;
                0843     
                0844                         /* check for control events */
                0845                         if (winp->ctrlp != (na_ctrlp) NULL && winp->flags & NA_HASCONTROLS) {
                0846                             if ((citem = FindControl(mouse, window, &ctrl)) != 0
                0847                                     && (status = (*winp->ctrlp)(winp, mouse, citem,
                0848                                     event.modifiers, ctrl)) != NA_NOTPROCESSED) {
                0849                                 break;
                0850                             }
                0851                         }
                0852                         
                0853                         /* deal with double clicks */
                0854                         if ((NAlastmouse & 1) && NAlastmouse < NA_RELEASE
                0855                                 && event.when - NAmousetime <= GetDblTime()) {
                0856                             if (++NAlastmouse > NA_DOWNN) NAlastmouse = NA_DOWNN;
                0857                         } else {
                0858                             NAlastmouse = NA_DOWN1;
                0859                         }
                0860                         NAmousept = mouse;
                0861                         
                0862                         /* call the mouse handler */
                0863                         goto DOMOUSEP;
                0864     
                0865                     case inDrag:
                0866                         /* drag the window */
                0867                         tmpRect = QD(screenBits.bounds);
                0868                         InsetRect(&tmpRect, 4, 4);
                0869                         bRect = window->portBits.bounds;
                0870                         DragWindow(window, event.where, &tmpRect);
                0871                         if ((bRect.left != window->portBits.bounds.left
                0872                                 || bRect.top != window->portBits.bounds.top) &&
                0873                                 (wp = NAlockWindow(wh = GetWinH(window))) != NULL) {
                0874                             if (wp->flags & NA_SMARTSIZE) NAsaveWin(wp);
                0875                             if (wp->cursorRgn != (RgnHandle) NULL) {
                0876                                 OffsetRgn(wp->cursorRgn,
                0877                                     bRect.left - window->portBits.bounds.left,
                0878                                     bRect.top - window->portBits.bounds.top);
                0879                                 NAcalcCursor(wp);
                0880                             }
                0881                             NAunlockWindowh(wh, wp);
                0882                         }
                0883                         break;
                0884                     
                0885                     case inGoAway:
                0886                         /* deal with the close window box */
                0887                         if (TrackGoAway(window, event.where)) status = NA_REQCLOSE;
                0888                         break;
                0889     
                0890                     case inGrow:
                0891                         /* grow the window */
                0892                         /* assume there is a valid app window in front */
                0893                         /* calculate min & max grow dimensions */
                0894                         tmpRect = QD(screenBits.bounds);
                0895                         tmpRect.bottom -= tmpRect.top;
                0896                         tmpRect.right -= tmpRect.left;
                0897                         tmpRect.top = winp->minh;
                0898                         tmpRect.left = winp->minw;
                0899                         if (winp->maxh) tmpRect.bottom = winp->maxh;
                0900                         if (winp->maxw) tmpRect.right = winp->maxw;
                0901                         
                0902                         /* check for resize proc */
                0903                         if (winp->resizep != (na_resizep) NULL) {
                0904                             status = (*winp->resizep)(winp, event.where, &tmpRect);
                0905                             if (status == NA_PROCESSED) break;
                0906                             goto RESIZEWINDOW;
                0907                         }
                0908                         
                0909                         /* grow, resize, and update the window */
                0910                         if ((growInfo = GrowWindow(window, event.where, &tmpRect))) {
                0911                             SizeWindow(window, LOWORD(growInfo), HIWORD(growInfo),
                0912                                 false);
                0913                             goto RESIZEWINDOW;
                0914                         }
                0915                         break;
                0916                     
                0917                     case inZoomIn:
                0918                     case inZoomOut:
                0919                         /* assume there is a valid app window in front */
                0920                         /* track, zoom, and update the window */
                0921                         if (TrackBox(window, event.where, part)) {
                0922                             SetPort(window);
                0923                             EraseRect(&window->portRect);
                0924                             ZoomWindow(window, part, true);
                0925                     RESIZEWINDOW:
                0926                             if (winp != (na_win*) NULL) {
                0927                                 if (winp->flags & NA_SMARTSIZE) NAsaveWin(winp);
                0928                                 if (winp->updatep == (na_updatep) NULL ||
                0929                                         (status = (*winp->updatep)(winp, (Boolean) true))
                0930                                         == NA_NOTPROCESSED) {
                0931                                     DoDraw(winp, DO_RESIZE);
                0932                                 }
                0933                             }
                0934                             ValidRect(&window->portRect);
                0935                         }
                0936                         break;
                0937                 }
                0938                 break;
                0939             
                0940             case keyDown:
                0941             case autoKey:
                0942                 /* deal with keyboard events */
                0943                 key = event.message & charCodeMask;
                0944 
                0945                 /* call the window's key handling procedure */
                0946                 if (winp != (na_win *) NULL && winp->keyp != (na_keyp) NULL) {
                0947                     status = (*winp->keyp)(winp, winp->flags & NA_RAWKEY ? event.message : key,
                0948                         event.modifiers);
                0949                 }
                0950 
                0951                 /* translate command-foo to an appropriate menu operation */
                0952                 if (status == NA_NOTPROCESSED &&
                0953                     (event.modifiers & cmdKey) && event.what == keyDown &&
                0954                         (status = DoMenu(winp, key)) != NA_NOTPROCESSED) {
                0955                     break;
                0956                 }
                0957                 
                0958                 /* require an app window for further processing */
                0959                 if (winp == (na_win*) NULL) break;
                0960                 
                0961                 /* if it's an unprocessed event in a dialog window */
                0962                 if (status == NA_NOTPROCESSED && (winp->flags & NA_DIALOGWINDOW)) {
                0963                     if (!NAfilterProc(winp->pwin, &event, &item)
                0964                         && (event.modifiers & cmdKey)) {
                0965                         status = NA_PROCESSED;
                0966                     }
                0967                 }
                0968                 break;
                0969             
                0970             case activateEvt:
                0971                 /* deal with activate windows based on activeFlag */
                0972                 status = DoActivate((WindowPtr) event.message, winp,
                0973                     event.modifiers & activeFlag, mouse);
                0974                 break;
                0975                 
                0976             case updateEvt:
                0977                 /* deal with update events with proper port setting, etc. */
                0978                 window = (WindowPtr) event.message;
                0979                 BeginUpdate(window);
                0980                 if ((wp = NAlockWindow(wh = GetWinH(window))) != (na_win*) NULL) {
                0981                     GetPort(&tempPort);
                0982                     SetPort(window);
                0983                     if (wp->flags & NA_DIALOGWINDOW) {
                0984                         UpdtDialog(window, window->visRgn);
                0985                     }
                0986                     if (wp->updatep == (na_updatep) NULL
                0987                         || (status = (*wp->updatep)(wp, (Boolean) false))
                0988                             == NA_NOTPROCESSED) {
                0989                         DoDraw(wp, DO_UPDATE);
                0990                     }
                0991                     DoDialog(winp, &event, mouse, 0, &status);
                0992                     SetPort(tempPort);
                0993                     NAunlockWindowh(wh, wp);
                0994                 }
                0995                 EndUpdate(window);
                0996                 if (status == NA_NOTPROCESSED) status = NA_PROCESSED;
                0997                 break;
                0998             
                0999             case diskEvt:
                1000                 /* let the user format bad disks */
                1001                 if (HIWORD(event.message) != noErr) {
                1002                     SetPt(&ptemp, 0x0070, 0x0050);
                1003                     (void) DIBadMount(ptemp, event.message);
                1004                 } else {
                1005                     status = NAallWindows(NAhead, &event);
                1006                 }
                1007                 break;
                1008             
                1009             case networkEvt:
                1010             case driverEvt:
                1011             case app1Evt:
                1012             case app2Evt:
                1013             case app3Evt:
                1014                 /* send event to all windows */
                1015                 status = NAallWindows(NAhead, &event);
                1016                 break;
                1017             
                1018             case osEvt:
                1019                 switch ((event.message >> 24) & 0xff) {
                1020                     case suspendResumeMessage:
                1021                         status = DoActivate(FrontWindow(), winp,
                1022                             !(NAinBack = !(event.message & resumeFlag)), mouse);
                1023                         break;
                1024                     
                1025                     case mouseMovedMessage:
                1026                         /* only interesting if a window is in front */
                1027                         if (NAinBack || winp == (na_win*) NULL) break;
                1028                         
                1029                         mousepix = winp->mousepix;
                1030                         
                1031                         /* deal with mouse dragging */
                1032                         if (mousepix && !(NAlastmouse & 1)) {
                1033                             if (NAlastmouse != NA_DRAG) {
                1034                                 InsetRect(&tmpRect, -mousepix, -mousepix);
                1035                                 if (PtInRect(mouse, &tmpRect)) break;
                1036                                 NAlastmouse = NA_DRAG;
                1037                             }
                1038                             goto DOMOUSEP;
                1039                         
                1040                         /* deal with cursor moving in/out of window */
                1041                         } else if (winp->cursorRgn != (RgnHandle) NULL) {
                1042                             AdjustCursor(winp, event.where, true);
                1043                         }
                1044                         break;
                1045                     }
                1046                 break;
                1047             
                1048             case kHighLevelEvent:
                1049                 if (NAgestaltBits & NA_HASAEVENTS) {
                1050                     aestatus = status;
                1051                     (void) AEProcessAppleEvent(&event);
                1052                     status = aestatus;
                1053                 }
                1054                 break;
                1055         }
                1056 
                1057         /* handle dialog events */      
                1058         DoDialog(winp, &event, mouse, item, &status);
                1059 
                1060         /* call the idle procedure of the front window */
                1061         if (winp != (na_win*) NULL && !NAinBack
                1062                 && status >= NA_NOTPROCESSED && winp->idlep != (na_idlep) NULL) {
                1063             status = (*winp->idlep)(winp);
                1064         }
                1065         
                1066         /* deal with window/app close requests and events */
                1067         switch (status) {
                1068             case NA_ALLCLOSED:
                1069             case NA_REQCLOSEALL:
                1070                 status = NAcloseWindows(NAhead, status);
                1071                 break;
                1072                 
                1073             case NA_CLOSED:
                1074             case NA_REQCLOSE:
                1075                 status = NAcloseWindow(winp, status);
                1076                 break;
                1077             
                1078             default:
                1079                 /* call the next task procedure */
                1080                 if (NAtask != (na_win**) NULL) {
                1081                     if (NActask == (na_win**) NULL) {
                1082                         NActask = NAtask;
                1083                         prioritycnt = (*NAtask)->priority;
                1084                     }
                1085                     for (wh = NAtask; wh; wh = (*wh)->task) {
                1086                         if ((wh == NActask || (*wh)->priority == -1)
                1087                             && (wp = NAlockWindow(wh)) != (na_win*) NULL
                1088                             && wp->taskp != (na_taskp) NULL) {
                1089                             GetPort(&tempPort);
                1090                             if (wp->pwin != (WindowPtr) NULL) SetPort(wp->pwin);
                1091                             status = (*wp->taskp)(wp);
                1092                             SetPort(tempPort);
                1093                             if (status == NA_REQCLOSE || status == NA_CLOSED) {
                1094                                 status = NAcloseWindow(wp, status);
                1095                                 break;
                1096                             }
                1097                             if (status == NA_REQCLOSEALL || status == NA_ALLCLOSED) {
                1098                                 status = NAcloseWindows(NAhead, status);
                1099                                 break;
                1100                             }
                1101                             if (status == NA_NOTPROCESSED) fastdelay = 1;
                1102                             NAunlockWindowh(wh, wp);
                1103                         }
                1104                     }
                1105                     if (NActask && prioritycnt-- <= 0
                1106                         && (NActask = (*NActask)->task) != (na_win **) NULL) {
                1107                         prioritycnt = (*NActask)->priority;
                1108                     }
                1109                 }
                1110             case NA_USERINTERACT:
                1111                 break;
                1112         }
                1113     } while (status != NA_ALLCLOSED);
                1114     
                1115     while (NAtask != NULL) NAcloseWindow(NAlockWindow(NAtask), NA_REQCLOSE);
                1116     
                1117     DisposeRgn(NAfullRgn);
                1118     DisposeRgn(NAnullRgn);
                1119     DisposHandle((Handle) NAmenus);
                1120 }
                1121 
                1122 /* position a rectangle based on screen size
                1123  */ 
                1124 Rect *NAscreenrect(short position)
                1125 {
                1126     static short stacktimes = 0;
                1127     static Rect sb;
                1128     short topoffset, leftoffset;
                1129     short width, height;
                1130     short bw;
                1131             
                1132     /* calculate the position to open the window */
                1133     sb = QD(screenBits.bounds);
                1134     InsetRect(&sb, 4, 4);
                1135     sb.top += MBarHeight;
                1136     if (position & NA_TITLEOFFSET) {
                1137         sb.top += 18;
                1138     }
                1139     width = sb.right - sb.left;
                1140     height = sb.bottom - sb.top;
                1141     if (position & 0x03) {
                1142         width = (width * (position & 0x03)) >> 2;
                1143     }
                1144     if (position & 0x0c) {
                1145         height = (height * ((position & 0x0c) >> 2)) >> 2;
                1146     }
                1147     if (position & NA_TOPSCN) {
                1148         sb.bottom = sb.top + height;
                1149     } else if (position & NA_BOTTOMSCN) {
                1150         sb.top = sb.bottom - height;
                1151     } else {
                1152         short bw = (sb.bottom - sb.top - height) >> 1;
                1153         sb.top += bw;
                1154         sb.bottom -= bw;
                1155     }
                1156     if (position & NA_LEFTSCN) {
                1157         sb.right = sb.left + width;
                1158     } else if (position & NA_RIGHTSCN) {
                1159         sb.left = sb.right - width;
                1160     } else {
                1161         bw = (sb.right - sb.left - width) >> 1;
                1162         sb.left += bw;
                1163         sb.right -= bw;
                1164     }
                1165     
                1166     return (&sb);
                1167 }
                1168 
                1169 /* create a new window/dialog/task structure
                1170  */
                1171 short NAwindow(Rect *rpos, long flags, char *title, short res, long *initdata,
                1172     long datasize, na_initp initp)
                1173 {
                1174     GrafPtr tmpPort;
                1175     short procID;
                1176     short status;
                1177     Boolean goAwayFlag, visible;
                1178     na_win **winh, *winp;
                1179     char *newdata, *dcopy;
                1180     WindowPtr behind, prev, window;
                1181     Rect wsize, sb;
                1182     PCstr wtitle[257];
                1183     Handle items;   
                1184     
                1185     /* save previous window */
                1186     prev = FrontWindow();
                1187     
                1188     /* set up flags for the NewWindow call */
                1189     goAwayFlag = (flags & NA_CLOSEBOX);
                1190     visible = (flags & NA_NOTVISIBLE) ? false : true;
                1191     behind = (flags & NA_BEHIND && NAwin != (na_win*) NULL) ? NAwin->pwin : (WindowPtr) -1;
                1192     
                1193     /* decide on the correct procID */
                1194     procID = rDocProc;
                1195     if ((flags & NA_ROUNDBORDER) != NA_ROUNDBORDER) {
                1196         procID = plainDBox;
                1197         if (flags & NA_SHADOWBORDER)    procID = altDBoxProc;
                1198         if (flags & NA_DOUBLEBORDER)    procID = dBoxProc;
                1199         if (flags & NA_TITLEBAR) {
                1200             procID = flags & NA_DOUBLEBORDER ? movableDBoxProc : documentProc;
                1201         }
                1202         if (!(flags & NA_GROWBOX)
                1203             && procID == documentProc)  procID |= noGrowDocProc;
                1204         if (flags & NA_ZOOMBOX)         procID |= zoomDocProc;
                1205     }
                1206     
                1207     /* get the window title to a pacsal string */
                1208     if (title) CtoPCstrcpy(wtitle, title);
                1209         
                1210     /* allocate memory and copy the user data */
                1211     if (!datasize) datasize = sizeof (na_win);
                1212     winh = (na_win**) NewHandleClear((Size) datasize);
                1213     if (winh == (na_win**) NULL) return (NA_NOTPROCESSED);
                1214     MoveHHi((Handle) winh);
                1215     HLock((Handle) winh);
                1216     winp = *winh;
                1217     if (initdata != NULL && flags & NA_COPYDATA) {
                1218         dcopy = (char *) initdata;
                1219         datasize -= sizeof (na_win);
                1220         for (newdata = (char*) winp + sizeof (na_win); datasize > 0; datasize--) {
                1221             *newdata = *dcopy++;
                1222             newdata++;
                1223         }
                1224     }
                1225     
                1226     /* initialize winp parameters */
                1227     winp->locks = 1;
                1228     winp->delay = NAdelay;
                1229     winp->flags = flags;
                1230     winp->minw = 128;
                1231     winp->minh = 64;
                1232     winp->resid = res;
                1233         
                1234     /* install in window tree */
                1235     if (flags & NA_CHILDWINDOW && NAwin != (na_win*) NULL) {
                1236         winp->parent = (na_win**) RecoverHandle((Ptr)NAwin);
                1237         winp->next = NAwin->child;
                1238         NAwin->child = winh;
                1239     } else {
                1240         winp->next = NAhead;
                1241         NAhead = winh;
                1242     }
                1243     
                1244     /* install in task list */
                1245     if (flags & NA_HASTASK) {
                1246         winp->task = NAtask;
                1247         NAtask = winh;
                1248     }
                1249     
                1250     /* open the window appropriately */
                1251     switch (flags & (NA_COLORWINDOW | NA_DIALOGWINDOW)) {
                1252         case NA_DIALOGWINDOW:
                1253         case (NA_DIALOGWINDOW | NA_COLORWINDOW):
                1254             if (flags & NA_USERESOURCE) {
                1255                 window = (WindowPtr) GetNewDialog(res, (Ptr) NULL, behind);
                1256             } else {
                1257                 items = GetResource('DITL', res);
                1258                 DetachResource(items);
                1259                 if (flags & NA_COLORWINDOW) {
                1260                     window = (WindowPtr) NewCDialog((Ptr) NULL, rpos, wtitle,
                1261                         visible, procID, behind, goAwayFlag, (long) winh, items);
                1262                 } else {
                1263                     window = (WindowPtr) NewDialog((Ptr) NULL, rpos, wtitle,
                1264                         visible, procID, behind, goAwayFlag, (long) winh, items);
                1265                 }
                1266             }
                1267             break;
                1268             
                1269         case NA_COLORWINDOW:
                1270             if (flags & NA_USERESOURCE) {
                1271                 window = (WindowPtr) GetNewCWindow(res, (Ptr) NULL, behind);
                1272             } else {
                1273                 window = (WindowPtr) NewCWindow((Ptr) NULL, rpos, wtitle,
                1274                     visible, procID, behind, goAwayFlag, (long) winh);
                1275             }
                1276             break;
                1277         
                1278         default:
                1279             if (flags & NA_USERESOURCE) {
                1280                 window = GetNewWindow(res, (Ptr) NULL, behind);
                1281             } else {
                1282                 window = NewWindow((Ptr) NULL, rpos, wtitle, visible, procID,
                1283                     behind, goAwayFlag, (long) winh);
                1284             }
                1285             break;
                1286     }
                1287     if (title && (flags & NA_USERESOURCE)) SetWTitle(window, wtitle);
                1288     winp->pwin = window;
                1289 
                1290     /* activate the window */
                1291     GetPort(&tmpPort);
                1292     SetPort(window);
                1293 
                1294     /* additional options for windows from resources */
                1295     if (flags & NA_USERESOURCE) {
                1296         SetWRefCon(window, (long) winh);
                1297         
                1298         /* force the size */
                1299         if (flags & NA_FORCESIZE) {
                1300             MoveWindow(window, rpos->left, rpos->top, false);
                1301             SizeWindow(window, rpos->right - rpos->left, rpos->bottom - rpos->top, false);
                1302         }
                1303     }
                1304     
                1305     /* get the screen bounds */
                1306     sb = QD(screenBits.bounds);
                1307     InsetRect(&sb, 4, 4);
                1308     
                1309     /* get window position */   
                1310     wsize = window->portRect;
                1311     LocalToGlobal((Point *)&wsize.top);
                1312     
                1313     /* make sure the window is on the screen */
                1314     if (wsize.top > sb.bottom || wsize.left > sb.right) {
                1315         MoveWindow(window, 60, 60, false);
                1316     }
                1317     
                1318     /* call the init procedure */
                1319     if ((status = (*initp)(winp, initdata)) >= NA_NOTPROCESSED) {
                1320     
                1321         /* draw the window immediately for better look & update has first newsize */
                1322         if (winp->updatep == (na_updatep) NULL
                1323                 || (status = (*winp->updatep)(winp, (Boolean) true))
                1324                 == NA_NOTPROCESSED) {
                1325             DoDraw(winp, FrontWindow() != window ? DO_RESIZE | DO_DEACTIVATE :
                1326                 DO_RESIZE);
                1327         }
                1328         if (flags & NA_DIALOGWINDOW) DrawDialog(window);
                1329         ValidRect(&window->portRect);
                1330     }
                1331 
                1332     /* deal with close requests/events result codes */
                1333     switch (status) {
                1334         case NA_ALLCLOSED:
                1335         case NA_REQCLOSEALL:
                1336             status = NAcloseWindows(NAhead, status);
                1337             break;
                1338 
                1339         case NA_CLOSED:
                1340         case NA_REQCLOSE:
                1341             status = NAcloseWindow(winp, status);
                1342             break;
                1343         
                1344         default:
                1345             NAunlockWindowh(winh, winp);
                1346             break;
                1347     }
                1348     
                1349     /* give a nice return value & clean up the port */
                1350     if (status == NA_NOTPROCESSED)                          status = NA_PROCESSED;
                1351     if (FrontWindow() != window || status != NA_PROCESSED)  SetPort(tmpPort);
                1352     
                1353     return (status);
                1354 }
                1355 
                1356 /* create & add a new task to the task list
                1357  */
                1358 na_win **NAaddtask(na_taskp taskp, long size)
                1359 {
                1360     na_win **task, *winp;
                1361     
                1362     if (!size) size = sizeof (na_win);
                1363     task = (na_win **) NewHandleClear(size);
                1364     if (task) {
                1365         (*task)->taskp = taskp;
                1366         (*task)->task = NAtask;
                1367         NAtask = task;
                1368     }
                1369     
                1370     return (task);
                1371 }