home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / mac / progrmng / trnsdspl.sit / EventLog.c.bin / EventLog.c
Encoding:
C/C++ Source or Header  |  1989-02-18  |  15.9 KB  |  851 lines  |  [TEXT/KAHL]

  1. /*
  2.     EventLog - TransDisplay event-logging demonstration program
  3.  
  4.     The project should include EventLog.c (this file), TransDisplay.c
  5.     (or a project made from TransDisplay.c), TransSkel.c (or a project
  6.     made from TransSkel.c), and MacTraps.
  7.     
  8.     08 Nov 86 Paul DuBois
  9.     28 Dec 86 Removed window zooming constants, since LightspeedC
  10.               v. 2.01 now supports them directly.
  11.     01 Feb 89 Modified for TransSkel 2.0.  2-byte and 4-byte integer
  12.               types are typedef'ed to Integer and Longint to ease porting.
  13. */
  14.  
  15.  
  16. # include    <EventMgr.h>
  17. # include    <MenuMgr.h>
  18. # include    <ControlMgr.h>
  19. # include    <FontMgr.h>
  20. # include    "TransDisplay.h"
  21.  
  22.  
  23. typedef    int        Integer;    /* compiler 2-byte integer type */
  24. typedef    long    Longint;    /* compiler 4-byte integer type */
  25.  
  26.  
  27. # define    maxButton    14
  28.  
  29.  
  30. # define    helpTextRes        1000    /* help text resource number */
  31. # define    aboutAlrtRes    1000    /* About... alert resource number */
  32.  
  33.  
  34. typedef enum                    /* Menu resource numbers */
  35. {
  36.     fileMenuRes = 1000,
  37.     editMenuRes,
  38.     logMenuRes
  39. };
  40.  
  41.  
  42. typedef enum                    /* Window resource numbers */
  43. {
  44.     logWindRes = 1000,
  45.     helpWindRes,
  46.     selectWindRes
  47. };
  48.  
  49.  
  50. typedef enum            /* File menu item numbers */
  51. {
  52.     showLog = 1,    /* make windows visible/bring to front */
  53.     showHelp,
  54.     showSelect,
  55.     /* --- */
  56.     quit = 5
  57. };
  58.  
  59.  
  60. typedef enum                /* Edit menu item numbers */
  61. {
  62.     undo = 1,
  63.     /* --- */
  64.     cut = 3,
  65.     copy,
  66.     paste,
  67.     clear
  68. };
  69.  
  70.  
  71. typedef enum                /* Log menu item numbers */
  72. {
  73.     logEvents = 1,        /* whether events are logged */
  74.     excludeLWind,
  75.     /* --- */
  76.     flushLog = 4,        /* flush log output */
  77.     /* --- */
  78.     wrapStyle = 6,        /* word wrap or not */
  79.     /* --- */
  80.     leftJust = 8,        /* justification */
  81.     centerJust,
  82.     rightJust,
  83.     /* --- */
  84.     small = 12,            /* text size */
  85.     medium,
  86.     large,
  87.     /* --- */
  88.     top = 16,            /* scroll home */
  89.     bottom                /* scroll to bottom */
  90. };
  91.  
  92.  
  93. typedef struct CtrlInfo
  94. {
  95.     Point            loc;        /* upper left of control */
  96.     Str255            title;        /* control title */
  97.     Boolean            *flagAddr;    /* associated boolean */
  98.     ControlHandle    ctrl;        /* associated control */
  99.     struct CtrlInfo    *subInfo;    /* subsidiary control */
  100.  
  101. } CtrlInfo;
  102.  
  103.  
  104. WindowPtr    selectWind;            /* event selection window */
  105. WindowPtr    helpWind;            /* help text window */
  106. WindowPtr    logWind;            /* log output window */
  107. MenuHandle    fileMenu;
  108. MenuHandle    editMenu;
  109. MenuHandle    logMenu;
  110. Boolean        reportEvents;        /* report events or not */
  111. Boolean        excludeLog;            /* exclude log window events or not */
  112. Integer        logFont;
  113. Integer        logSize;
  114. Integer        logWrap;
  115. Integer        logJust;
  116.  
  117.  
  118. Boolean                            /* event type selection flags */
  119.         rMouseDown = true,
  120.             rMouseMods = false,
  121.             rMouseWind = true,
  122.             rMouseLoc = false,
  123.             rMousePart = true,
  124.             rMouseSys = false,
  125.         rMouseUp = false,
  126.         rKeyDown = true,
  127.             rKDMods = false,
  128.         rAutoKey = true,
  129.             rAKMods = false,
  130.         rUpdate = true,
  131.         rActivate = true,
  132.         rDisk = true;
  133.  
  134.  
  135. /*
  136.     Control information.  The last field is used to tell which controls
  137.     are "owned" by another.  When the owner is unchecked, all the owned
  138.     controls go dim.
  139. */
  140.  
  141. CtrlInfo    ctrlInfo [maxButton] =
  142. {
  143.     { { 5, 10}, "\pMouse Down", &rMouseDown, nil, nil },
  144.     { { 25, 30}, "\pModifiers", &rMouseMods, nil, &ctrlInfo[0] },
  145.     { { 45, 30}, "\pWindow", &rMouseWind, nil, &ctrlInfo[0] },
  146.     { { 65, 30}, "\pLocation", &rMouseLoc, nil, &ctrlInfo[0] },
  147.     { { 85, 30}, "\pPart Code", &rMousePart, nil, &ctrlInfo[0] },
  148.     { { 105, 30}, "\pSystem Clicks", &rMouseSys, nil, &ctrlInfo[0] },
  149.     { { 125, 10}, "\pMouse Up", &rMouseUp, nil, nil },
  150.     { { 5, 160}, "\pKey Down", &rKeyDown, nil, nil },
  151.     { { 25, 180}, "\pModifiers", &rKDMods, nil, &ctrlInfo[7] },
  152.     { { 45, 160}, "\pAutoKey", &rAutoKey, nil, nil },
  153.     { { 65, 180}, "\pModifiers", &rAKMods, nil, &ctrlInfo[9] },
  154.     { { 85, 160}, "\pUpdate", &rUpdate, nil, nil },
  155.     { { 105, 160}, "\pActivate", &rActivate, nil, nil },
  156.     { { 125, 160}, "\pDisk", &rDisk, nil, nil }
  157. };
  158.  
  159. /*    Window that was in front last time checked    */
  160.  
  161. WindowPtr    lastFront = nil;
  162.  
  163.  
  164. /*
  165.     Print information about a window.  If it's a window with a title,
  166.     print the title.  Print whether it's a desk accessory window.
  167. */
  168.  
  169. WindowInfo (theWind)
  170. WindowPeek    theWind;
  171. {
  172. Str255    title;
  173.  
  174.     GetWTitle (theWind, title);
  175.     if (title[0] != 0)            /* window has title */
  176.     {
  177.         DisplayChar (' ');
  178.         DisplayString (title);
  179.     }
  180.  
  181.     if (theWind->windowKind < 0)
  182.         DisplayString ("\p (DA)");
  183. }
  184.  
  185.  
  186. Modifiers (mods)
  187. Integer    mods;
  188. {
  189.     DisplayString ("\p mods (0x");
  190.     DisplayHexInt (mods);
  191.     DisplayChar (')');
  192. }
  193.  
  194.  
  195. MouseLoc (thePt, thePort)
  196. Point    thePt;
  197. GrafPtr    thePort;
  198. {
  199. GrafPtr    savePort;
  200.  
  201.     GetPort (&savePort);
  202.     SetPort (thePort);
  203.     GlobalToLocal (&thePt);
  204.     SetPort (savePort);
  205.     if (rMouseLoc)
  206.     {
  207.         DisplayString ("\p loc (");
  208.         DisplayInt (thePt.h);
  209.         DisplayString ("\p, ");
  210.         DisplayInt (thePt.v);
  211.         DisplayChar (')');
  212.     }
  213. }
  214.  
  215.  
  216. /*
  217.     Mouse click.  Get the window that the click occurred in, and the
  218.     part of the window.
  219.  
  220.     Make sure to get all the part codes!  (incl. zoom box stuff)
  221. */
  222.  
  223. ReportMouse (theEvent)
  224. EventRecord    *theEvent;
  225. {
  226. Point    evtPt;
  227. Integer    evtPart;
  228. GrafPtr    evtPort;
  229.  
  230.     evtPt = theEvent->where;
  231.     evtPart = FindWindow (evtPt, &evtPort);
  232.     if (excludeLog && evtPort == logWind)
  233.         return;
  234.     DisplayString ("\pMouse click");
  235.  
  236.     switch (evtPart)
  237.     {
  238.  
  239. /*
  240.     Click in a desk accessory window.
  241. */
  242.         case inSysWindow:
  243.             if (rMouseSys)
  244.             {
  245.                 if (rMousePart)
  246.                     DisplayString ("\p in system window:");
  247.                 if (rMouseWind)
  248.                     WindowInfo (evtPort);
  249.                 MouseLoc (evtPt, evtPort);
  250.             }
  251.             break;
  252.  
  253. /*
  254.     Click in desk top.
  255. */
  256.         case inDesk:
  257.             if (rMousePart)
  258.                 DisplayString ("\p in desktop");
  259.             break;
  260.  
  261. /*
  262.     Click in menu bar.
  263. */
  264.         case inMenuBar:
  265.             if (rMousePart)
  266.                 DisplayString ("\p in menu bar");
  267.             break;
  268.  
  269. /*
  270.     Click in grow box.
  271. */
  272.         case inGrow:
  273.             if (rMousePart)
  274.                 DisplayString ("\p in grow region:");
  275.             if (rMouseWind)
  276.                 WindowInfo (evtPort);
  277.             MouseLoc (evtPt, evtPort);
  278.             break;
  279.  
  280. /*
  281.     Click in title bar.
  282. */
  283.         case inDrag:
  284.             if (rMousePart)
  285.                 DisplayString ("\p in drag region:");
  286.             if (rMouseWind)
  287.                 WindowInfo (evtPort);
  288.             break;
  289.  
  290. /*
  291.     Click in close box.
  292. */
  293.         case inGoAway:
  294.             if (rMousePart)
  295.                 DisplayString ("\p in close box:");
  296.             if (rMouseWind)
  297.                 WindowInfo (evtPort);
  298.             break;
  299.  
  300. /*
  301.     Click in zoom-in box.
  302. */
  303.         case inZoomIn:
  304.             if (rMousePart)
  305.                 DisplayString ("\p in zoom-in box:");
  306.             if (rMouseWind)
  307.                 WindowInfo (evtPort);
  308.             break;
  309.  
  310. /*
  311.     Click in zoom-out box.
  312. */
  313.         case inZoomOut:
  314.             if (rMousePart)
  315.                 DisplayString ("\p in zoom-out box:");
  316.             if (rMouseWind)
  317.                 WindowInfo (evtPort);
  318.             break;
  319.  
  320. /*
  321.     Click in content region.
  322.  
  323.     (some day - check if in control, and if so, print control information)
  324. */
  325.         case inContent:
  326.             if (rMousePart)
  327.                 DisplayString ("\p in content region:");
  328.             if (rMouseWind)
  329.                 WindowInfo (evtPort);
  330.             MouseLoc (evtPt, evtPort);
  331.             break;
  332.  
  333.     }
  334.     if (rMouseMods)
  335.         Modifiers (theEvent->modifiers);
  336.     DisplayLn ();
  337. }
  338.  
  339.  
  340. ReportKey (what, c, mods, modFlag)
  341. Integer    what;
  342. char    c;
  343. Integer    mods;
  344. Boolean    modFlag;
  345. {
  346.     if (what == keyDown)
  347.         DisplayString ("\pKey down: char '");
  348.     else
  349.         DisplayString ("\pAutokey: char '");
  350.     DisplayChar (c);
  351.     DisplayString ("\p' ");
  352.     if (modFlag)
  353.         Modifiers (mods);
  354.     DisplayLn ();
  355. }
  356.  
  357.  
  358. ReportActivate (theWind, mods)
  359. WindowPtr    theWind;
  360. Integer        mods;
  361. {
  362.     if ((mods & activeFlag) != 0)
  363.         DisplayString ("\pActivate:");
  364.     else
  365.         DisplayString ("\pDeactivate:");
  366.     WindowInfo (theWind);
  367.     DisplayLn ();
  368. }
  369.  
  370.  
  371. ReportUpdate (theWind)
  372. WindowPtr    theWind;
  373. {
  374.     DisplayString ("\pUpdate:");
  375.     WindowInfo (theWind);
  376.     DisplayLn ();
  377. }
  378.  
  379.  
  380. /*
  381.     General event logger
  382. */
  383.  
  384. LogEvent (theEvt)
  385. EventRecord    *theEvt;
  386.  
  387. {
  388. register EventRecord    *theEvent;
  389. Point                    evtPt;
  390. GrafPtr                    tmpPort;
  391. register Integer        evtPart;
  392. register char            evtChar;
  393. register Integer        evtMods;
  394. Rect                    r;
  395.  
  396.     if (reportEvents == false)
  397.         return (false);            /* don't do anything */
  398.     theEvent = theEvt;
  399.     evtPt = theEvent->where;
  400.     switch (theEvent->what)
  401.     {
  402.  
  403. /*
  404.     Mouse click.
  405. */
  406.         case mouseDown:
  407.             if (rMouseDown)
  408.                 ReportMouse (theEvent);
  409.             break;
  410.  
  411.         case mouseUp:
  412.             if (rMouseUp)
  413.                 DisplayString ("\pMouse up\r");
  414.             break;
  415.  
  416. /*
  417.     Key event.
  418. */
  419.         case keyDown:
  420.             if (excludeLog && FrontWindow () == logWind)
  421.                 break;
  422.             if (rKeyDown)
  423.             {
  424.                 evtChar = theEvent->message & charCodeMask;
  425.                 evtMods = theEvent->modifiers;
  426.                 ReportKey (keyDown, evtChar, evtMods, rKDMods);
  427.             }
  428.             break;
  429.  
  430.         case autoKey:
  431.             if (excludeLog && FrontWindow () == logWind)
  432.                 break;
  433.             if (rKeyDown)
  434.             {
  435.                 evtChar = theEvent->message & charCodeMask;
  436.                 evtMods = theEvent->modifiers;
  437.                 ReportKey (autoKey, evtChar, evtMods, rAKMods);
  438.             }
  439.             break;
  440.  
  441. /*
  442.     Update a window.  If it's an update for the log window, invalidate
  443.     it, because the message is written and will cause a scroll BEFORE
  444.     the window actually gets updated.  This means that part of what
  445.     needs redrawing will be scrolled out of the update region and won't
  446.     be redrawn properly.  Invalidating the entire port is wasteful but
  447.     makes sure the whole window can be drawn properly.
  448. */
  449.         case updateEvt:
  450.             if ((WindowPtr) theEvent->message == logWind)
  451.             {
  452.                 GetPort (&tmpPort);
  453.                 SetPort (logWind);
  454.                 InvalRect (&logWind->portRect);
  455.                 SetPort (tmpPort);
  456.             }
  457.             if (excludeLog && (WindowPtr) theEvent->message == logWind)
  458.                 break;
  459.             if (rUpdate)
  460.                 ReportUpdate (theEvent->message);
  461.             break;
  462.  
  463. /*
  464.     Activate or deactivate a window.
  465. */
  466.         case activateEvt:
  467.             if (excludeLog && (WindowPtr) theEvent->message == logWind)
  468.                 break;
  469.             if (rActivate)
  470.                 ReportActivate (theEvent->message, theEvent->modifiers);
  471.             break;
  472.  
  473. /*
  474.     handle inserts of uninitialized disks
  475. */
  476.         case diskEvt:
  477.             if (rDisk)
  478.             {
  479.                 DisplayString ("\pDisk insertion");
  480.                 if (HiWord (theEvent->message) != noErr)
  481.                 {
  482.                     DisplayString ("\p (needs initializing)");
  483.                 }
  484.                 DisplayLn ();
  485.             }
  486.             break;
  487.  
  488.     }
  489.     return (false);        /* never tell TransSkel the event was handled */
  490. }
  491.  
  492.  
  493. /*
  494.     Background procedure.  Check front window, reset edit menu if window
  495.     changes from an application window to a non-application window.
  496.     Disable the Edit menu whenever an application window is active,
  497.     enable it otherwise.
  498.     Also called whenever it is known that the active window has changed.
  499. */
  500.  
  501. CheckFront ()
  502. {
  503. WindowPtr    curWind;
  504. Integer        theKind;
  505. Boolean        lastIsApp = false,
  506.             curIsApp = false;
  507.  
  508.     curWind = FrontWindow ();
  509.     if (IsDWindow (lastFront) || lastFront == selectWind)
  510.         lastIsApp = true;
  511.     if (IsDWindow (curWind) || curWind == selectWind)
  512.         curIsApp = true;
  513.     if (lastFront != curWind)
  514.     {
  515.         if (IsDWindow (lastFront) || lastFront == selectWind)
  516.             lastIsApp = true;
  517.         if (IsDWindow (curWind) || curWind == selectWind)
  518.             curIsApp = true;
  519.         if (lastIsApp != curIsApp)
  520.         {
  521.             theKind = 0;
  522.             if (curWind != nil)
  523.                 theKind = ((WindowPeek) curWind)->windowKind;
  524.             if (curWind == nil || theKind < 0)    /* no window or DA in front */
  525.                 EnableItem (editMenu, 0);
  526.             else
  527.                 DisableItem (editMenu, 0);
  528.             DrawMenuBar ();
  529.         }
  530.         lastFront = curWind;
  531.     }
  532. }
  533.  
  534.  
  535. /* ------------------------------------------------------------ */
  536. /*            Event Selection Window Handler Routines                */
  537. /* ------------------------------------------------------------ */
  538.  
  539.  
  540. /*
  541.     Activate event procedure for both display windows and the checkbox
  542.     window.
  543. */
  544.  
  545. Activate (active)
  546. Boolean    active;
  547. {
  548.     CheckFront ();
  549. }
  550.  
  551. /*
  552.     Update window.  This is easy, just draw the controls.
  553. */
  554.  
  555. Update (resized)
  556. Boolean    resized;            /* ignored */
  557. {
  558.     DrawControls (selectWind);
  559. }
  560.  
  561.  
  562. /*
  563.     Handle hits in check boxes of selection window:
  564.     Toggle check box, sync the associated flag, and enable or disable
  565.     any subsidiary check boxes accordingly.  (Subsidiaries have
  566.     information in the control structure that points back to the owner
  567.     check box.)
  568.  
  569. */
  570.  
  571. Mouse (thePt, t, mods)
  572. Point    thePt;
  573. Longint    t;
  574. Integer    mods;
  575. {
  576. ControlHandle    ctl;
  577. CtrlInfo        *ci;
  578. Boolean            val;
  579. Integer            i;
  580.  
  581.     if (FindControl (thePt, selectWind, &ctl))
  582.     {
  583.         if (TrackControl (ctl, thePt, nil))
  584.         {
  585.             ci = (CtrlInfo *) GetCRefCon (ctl);
  586.             val = !GetCtlValue (ctl);
  587.             *(ci->flagAddr) = val;
  588.             SetCtlValue (ctl, val);
  589.         
  590.             /* enable/disable any subsidiaries */
  591.         
  592.             for (i = 0; i < maxButton; ++i)
  593.             {
  594.                 if (ctrlInfo[i].subInfo->ctrl == ci->ctrl)
  595.                     HiliteControl (ctrlInfo[i].ctrl, val ? 0 : 255);
  596.             }
  597.         }
  598.     }
  599. }
  600.  
  601.  
  602. /*
  603.     File menu handler
  604. */
  605.  
  606. DoFileMenu (item)
  607. Integer    item;
  608. {
  609.     switch (item)
  610.     {
  611.         case showHelp:
  612.             SelectWindow (helpWind);
  613.             ShowWindow (helpWind);
  614.             break;
  615.         
  616.         case showSelect:
  617.             SelectWindow (selectWind);
  618.             ShowWindow (selectWind);
  619.             break;
  620.         
  621.         case showLog:
  622.             SelectWindow (logWind);
  623.             ShowWindow (logWind);
  624.             break;
  625.         
  626.         case quit:
  627.             SkelWhoa ();
  628.             break;
  629.  
  630.     }
  631. }
  632.  
  633. /*
  634.     Put the right check marks in the Log menu
  635. */
  636.  
  637. SetLogMenu ()
  638. {
  639.     CheckItem (logMenu, logEvents, reportEvents);
  640.     CheckItem (logMenu, excludeLWind, excludeLog);
  641.     CheckItem (logMenu, wrapStyle, logWrap >= 0);
  642.     CheckItem (logMenu, leftJust, logJust == teJustLeft);
  643.     CheckItem (logMenu, centerJust, logJust == teJustCenter);
  644.     CheckItem (logMenu, rightJust, logJust == teJustRight);
  645.     CheckItem (logMenu, small, logSize == 9);
  646.     CheckItem (logMenu, medium, logSize == 12);
  647.     CheckItem (logMenu, large, logSize == 24);
  648. }
  649.  
  650.  
  651. /*
  652.     Set display style of log window
  653. */
  654.  
  655. SetStyle ()
  656. {
  657.     SetDWindowStyle (logWind, logFont, logSize, logWrap, logJust);
  658.     SetLogMenu ();
  659. }
  660.  
  661.  
  662. /*
  663.     Log menu handler
  664. */
  665.  
  666. DoLogMenu (item)
  667. Integer    item;
  668. {
  669.     switch (item)
  670.     {
  671.         case logEvents:
  672.             reportEvents = !reportEvents;
  673.             SetLogMenu ();
  674.             break;
  675.  
  676.         case excludeLWind:
  677.             excludeLog = !excludeLog;
  678.             SetLogMenu ();
  679.             break;
  680.  
  681.         case flushLog:
  682.             FlushDWindow (logWind, 32767L);
  683.             break;
  684.         
  685.         case wrapStyle:
  686.             logWrap = (logWrap >= 0 ? -1 : 0);
  687.             SetStyle ();
  688.             break;
  689.  
  690.         case leftJust:
  691.             logJust = teJustLeft;
  692.             SetStyle ();
  693.             break;
  694.  
  695.         case centerJust:
  696.             logJust = teJustCenter;
  697.             SetStyle ();
  698.             break;
  699.  
  700.         case rightJust:
  701.             logJust = teJustRight;
  702.             SetStyle ();
  703.             break;
  704.  
  705.         case small:
  706.             logFont = monaco;
  707.             logSize = 9;
  708.             SetStyle ();
  709.             break;
  710.  
  711.         case medium:
  712.             logFont = systemFont;
  713.             logSize = 12;
  714.             SetStyle ();
  715.             break;
  716.  
  717.         case large:
  718.             logFont = geneva;
  719.             logSize = 24;
  720.             SetStyle ();
  721.             break;
  722.  
  723.         case top:
  724.             SetDWindowPos (logWind, 0);
  725.             break;
  726.  
  727.         case bottom:
  728.             SetDWindowPos (logWind, 32767);
  729.             break;
  730.     }
  731. }
  732.  
  733.  
  734. /*
  735.     Handle selection of Aboutâ•” item from Apple menu
  736. */
  737.  
  738. DoAbout ()
  739. {
  740.     (void) Alert (aboutAlrtRes, nil);
  741. }
  742.  
  743.  
  744. /*
  745.     Dispose of event selection window (and controls)
  746. */
  747.  
  748. WClobber ()
  749. {
  750.     DisposeWindow (selectWind);
  751. }
  752.  
  753.  
  754.  
  755. /*
  756.     Create controls
  757. */
  758.  
  759. MakeControls (theWind)
  760. WindowPtr    theWind;
  761. {
  762. Integer        i;
  763. CtrlInfo    *ci;
  764. Rect        r;
  765.  
  766.     for (i = 0; i < maxButton; ++i)
  767.     {
  768.         ci = &ctrlInfo[i];
  769.         SetRect (&r, ci->loc.h, ci->loc.v,
  770.                     ci->loc.h + StringWidth (ci->title) + 30,
  771.                     ci->loc.v + 20);
  772.         ci->ctrl = NewControl (theWind, &r, ci->title, true,
  773.                             *(ci->flagAddr), 0, 1,
  774.                             checkBoxProc, ci);
  775.     }
  776.     ValidRect (&theWind->portRect);
  777. }
  778.  
  779.  
  780. main ()
  781. {
  782. Handle    h;
  783.  
  784.     SkelInit (6, nil);
  785.     SkelApple ("\pAbout EventLogâ•”", DoAbout);
  786.  
  787.     fileMenu = GetMenu (fileMenuRes);
  788.     (void) SkelMenu (fileMenu, DoFileMenu, nil, false);
  789.  
  790.     editMenu = GetMenu (editMenuRes);
  791.     DisableItem (editMenu, 0);
  792.     (void) SkelMenu (editMenu, nil, nil, false);
  793.  
  794.     logMenu = GetMenu (logMenuRes);
  795.     (void) SkelMenu (logMenu, DoLogMenu, nil, true);
  796.  
  797. /*
  798.     Create windows and install handlers.
  799. */
  800.  
  801.     SetDWindowNotify (nil, Activate);
  802.  
  803.     helpWind = GetNewDWindow (helpWindRes, -1L);
  804.     SetDWindowStyle (helpWind, 0, 0, 0, teJustLeft);
  805.  
  806.     h = GetResource ('TEXT', helpTextRes);    /* read help text */
  807.     HLock (h);                        /* lock it and write to window */
  808.     DisplayText (*h, GetHandleSize (h));
  809.     HUnlock (h);
  810.     ReleaseResource (h);            /* done with it, so goodbye */
  811.     SetDWindowPos (helpWind, 0);    /* scroll back to top */
  812.     ShowWindow (helpWind);
  813.  
  814.     logWind = GetNewDWindow (logWindRes, -1L);
  815.  
  816.     SkelEventHook (LogEvent);
  817.     reportEvents = true;
  818.     excludeLog = false;
  819.  
  820.     logFont = monaco;
  821.     logSize = 9;
  822.     logWrap = 0;
  823.     logJust = teJustLeft;
  824.     SetStyle ();
  825.     ShowWindow (logWind);
  826.  
  827.     selectWind = GetNewWindow (selectWindRes, nil, -1L);
  828.  
  829.     (void) SkelWindow (selectWind,    /* the window */
  830.                 Mouse,        /* mouse click handler */
  831.                 nil,        /* key clicks are ignored */
  832.                 Update,        /* window updating procedure */
  833.                 Activate,    /* window activate/deactivate procedure */
  834.                 nil,        /* hide window */
  835.                 WClobber,    /* window disposal procedure */
  836.                 nil,        /* idle proc */
  837.                 true);        /* irrelevant */
  838.  
  839.     MakeControls (selectWind);
  840.  
  841. /*
  842.     Process events until user quits,
  843.     then clean up and exit
  844. */
  845.  
  846.     CheckFront ();
  847.     SkelBackground (CheckFront);
  848.     SkelMain ();
  849.     SkelClobber ();
  850. }
  851.