home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Utilities / Time Till / main.c next >
Encoding:
C/C++ Source or Header  |  1994-03-22  |  19.5 KB  |  790 lines  |  [TEXT/KAHL]

  1. /***************************************************************************************************
  2.     main.c
  3.  
  4.         Source code for the 'Time Till' application.
  5.  
  6.         This simple application displays a small window showing the date/time remaining
  7.         until a specfied target date/time.
  8.  
  9.         This is hardly a perfect example of how a Mac application should be built.
  10.  
  11.         Pardon the sloppy code - this was just slapped together to make it work.
  12.  
  13.         Almost no error checking is done, so beware.
  14.  
  15.         If you build a more spiffy version of this application, consider sending
  16.         me a copy. It's not required. I'm just curious what others might do with
  17.         this code.
  18.  
  19.         Mark W. DeNyse
  20.         March, 1994
  21.  
  22.         CIS:         74776,755
  23.         AOL:         markdenyse
  24.         Internet: markd@shiva.com
  25.  
  26. ****************************************************************************************************/
  27.  
  28. // Assume a #include "MacHeaders" in your project prefix
  29. #include <Traps.h>
  30. #include <Packages.h>
  31.  
  32. /***************************************************************************************************
  33.                                                     Constants
  34. ****************************************************************************************************/
  35. enum {
  36.     kAppleMenuID                = 1,
  37.         kAboutItem                = 1,
  38.  
  39.     kFileMenuID                    = 2,
  40.         kSetTargetDateItem    = 1,
  41.         kQuitItem                = 3
  42. } MenuConstants;
  43.  
  44. enum {
  45.     kSleepTime                    = 1,
  46.  
  47.     kWindowID                    = 128,
  48.     kHandCursID                    = 128,
  49.     kGrabbedHandlCursID        = 129,
  50.  
  51.     kSignature                    = '????',
  52.     kDateTimeFileType            = '•MWD'
  53. } MiscConstants;
  54.  
  55. enum {
  56.     kStrID                        = kWindowID,
  57.  
  58.     kTimeUntilIndex            = 1,
  59.     kUpTimeIndex,
  60.     kOneDayUpTimeIndex,
  61.     kManyDaysUpTimeIndex,
  62.     kAlreadyPastIndex,
  63.     kDateTimeFileNameIndex
  64. } StringConstants;
  65.  
  66. enum {
  67.     kSetTargetID                = kWindowID,
  68.  
  69.     kOKButton                    = 1,
  70.     kCancelButton,
  71.     kTargetDate,
  72.     kTargetTime
  73. } GetDateTimeConstants;
  74.  
  75. #define kOneMinute        ((unsigned long)60)
  76. #define kOneHour            ((unsigned long)3600)
  77. #define kHoursInADay        ((unsigned long)24)
  78. #define kOneDay            (kOneHour * kHoursInADay)
  79.  
  80.  
  81.  
  82. #define    HiShort(longNum)    (short)(((longNum) >> 16) & 0xFFFF)
  83. #define    LoShort(longNum)    (short)((longNum) & 0xFFFF)
  84.  
  85. /***************************************************************************************************
  86.                                                     Global variables
  87. ****************************************************************************************************/
  88. static short                gVRefNum;
  89. static Boolean                gHasWNE;
  90. static WindowPtr            gWindow;
  91. static RgnHandle            gSleepRgn;
  92. static long                    gLastDateTime;
  93. static long                    gTargetDate;
  94. static NumberParts        gPartsTable;
  95. static DateCacheRecord    gDateCache;
  96.  
  97.  
  98. /***************************************************************************************************
  99.                                                     Function Prototypes
  100. ****************************************************************************************************/
  101. void                main(void);
  102.  
  103. static void        Initialize(void);
  104.  
  105. static Boolean    TrapAvailable(short theTrap);
  106. static void        CopyPString(ConstStr255Param srcString, Str255 destString);
  107. static void        InsertStrAt(Str255 theStr, Str255 insertStr, short index);
  108. static void        MakeTimeString(long timePart, Str255 theStr);
  109. static void        MakeRelativeTimeString(unsigned long theTime, Str255 timeStr);
  110. static void        SetMemory(register Ptr thePtr, register long dataSize, register char initValue);
  111.  
  112. static Boolean    GetTargetDate(long *targetDate);
  113. static void        ReadFile(long *targetDate);
  114. static void        WriteFile(long targetDate);
  115.  
  116. static void        DoIdle(Boolean fullRedraw);
  117. static Boolean    DoCommand(long theCommand);
  118. static Boolean    ProcessEvent(void);
  119.  
  120.  
  121. /***************************************************************************************************
  122.     TrapAvailable
  123.  
  124.         Return true if the specified trap exists. Snarfed from the TCL sources.
  125.  
  126.         -> theTrap        The trap to test for.
  127.  
  128.         returns:            true if the specified trap exists, else false.
  129.  
  130. ****************************************************************************************************/
  131. static Boolean TrapAvailable(short theTrap)
  132. {
  133.     TrapType tType;
  134.     short    numToolBoxTraps;
  135.  
  136.                 
  137.     tType = (theTrap & 0x800) > 0 ? ToolTrap : OSTrap;
  138.     
  139.     if (NGetTrapAddress(_InitGraf, ToolTrap) == NGetTrapAddress(0xAA6E, ToolTrap))
  140.         numToolBoxTraps = 0x200;
  141.     else
  142.         numToolBoxTraps = 0x400;
  143.     
  144.     if (tType == ToolTrap)
  145.     {
  146.         theTrap &= 0x7FF;
  147.         if (theTrap >= numToolBoxTraps)
  148.             theTrap = _Unimplemented;
  149.     }
  150.  
  151.     return(NGetTrapAddress(theTrap, tType) != NGetTrapAddress(_Unimplemented, ToolTrap));
  152. }
  153.  
  154.  
  155. /***************************************************************************************************
  156.     CopyPString
  157.  
  158.         Copy a Pascal string. Snarfed from the TCL sources.
  159.  
  160.         -> srcString            The string to copy
  161.         <- destString            Where to put the copy
  162.  
  163. ****************************************************************************************************/
  164. static void CopyPString(ConstStr255Param srcString, Str255 destString)
  165. {
  166.     BlockMove(srcString, destString, srcString[0] + 1L);
  167.     return;
  168. }
  169.  
  170.  
  171. /***************************************************************************************************
  172.     InsertStrAt
  173.  
  174.         Given a string containing a '%n' token (where n is 1-9), insert a string replacing
  175.         the '%n' token.
  176.  
  177.         Example:
  178.             CopyPString("\pThe color of the ball is %1.", string1);
  179.             CopyPString("\pred", string2);
  180.             InsertStrAt(string1, string2, 1);
  181.  
  182.             result: string1 = "\pThe color of the ball is red."
  183.  
  184.  
  185.         <-> theStr            The string to insert insertStr into
  186.          -> insertStr        The string to insert into theStr
  187.          -> index            The '%n' index in theStr to insert insertStr into.
  188.  
  189. ****************************************************************************************************/
  190. static void InsertStrAt(Str255 theStr, Str255 insertStr, short index)
  191. {
  192.     short                i;
  193.     Str255            newStr;
  194.     StringHandle    theStrHdl;
  195.     char                tokenChar;
  196.  
  197.  
  198.     CopyPString(theStr, newStr);
  199.  
  200.     for (i = 1; i < theStr[0]; i++)
  201.         if ((theStr[i] == '%') && (theStr[i + 1] == ('0' + index)))
  202.         {
  203.             BlockMove((Ptr)theStr + 1,        (Ptr)newStr + 1,                       i - 1);
  204.             BlockMove((Ptr)insertStr + 1,  (Ptr)newStr + i,                       (long)insertStr[0]);
  205.             BlockMove((Ptr)theStr + i + 2, (Ptr)newStr + i + insertStr[0], theStr[0] - i - 1);
  206.  
  207.             newStr[0] = theStr[0] + insertStr[0] - 2;
  208.             break;
  209.         }
  210.  
  211.     CopyPString(newStr, theStr);
  212.  
  213.     return;
  214. }
  215.  
  216.  
  217. /***************************************************************************************************
  218.     MakeTimeString
  219.  
  220.         Given a number, convert it to a string, adding a leading zero if necessary.
  221.  
  222.         -> timePart            The value to convert
  223.         <- theStr            The string form of timePart
  224.  
  225. ****************************************************************************************************/
  226. static void MakeTimeString(long timePart, Str255 theStr)
  227. {
  228.     theStr[0] = 0;
  229.     NumToString(timePart, theStr);
  230.     if (theStr[0] == 1)                                            // Need a leading zero?
  231.     {
  232.         theStr[2] = theStr[1];
  233.         theStr[1] = '0';
  234.         theStr[0] = 2;
  235.     }
  236.     return;
  237. }
  238.  
  239.  
  240. /***************************************************************************************************
  241.     MakeRelativeTimeString
  242.  
  243.         Create a string that represents the relative time of theTime, expressed as:
  244.                         nn Days hh:mm:ss
  245.             -or-        hh:mm:ss
  246.  
  247.         The “nn Days” portion of the string is only outputted if the time is greater
  248.         than one day.
  249.  
  250.         -> theTime        An unsigned long expressing time in seconds
  251.         <- timeStr        Str255 expressing theTime
  252.  
  253. ****************************************************************************************************/
  254. static void MakeRelativeTimeString(unsigned long theTime, Str255 timeStr)
  255. {
  256.     Str255            aStr;
  257.     Str255            bStr;
  258.     unsigned long    days;
  259.     unsigned long    hours;
  260.     unsigned long    minutes;
  261.     unsigned long    seconds;
  262.  
  263.  
  264.     timeStr[0] = 0;
  265.  
  266.     days        = 0L;
  267.     hours        = 0L;
  268.     minutes    = 0L;
  269.     seconds    = 0L;
  270.  
  271.     // Calculate the days, hours, minutes and seconds.
  272.     if (theTime >= kOneDay)                                        // Only do days if caller wants it
  273.     {
  274.         days = theTime / kOneDay;                                // Calculate days up
  275.         theTime -= (days * kOneDay);                            // Leave remainder
  276.     }
  277.  
  278.     if (theTime >= kOneHour)                                    // Any hours?
  279.     {
  280.         hours = theTime / kOneHour;                            // Calculate hours up
  281.         theTime -= (hours * kOneHour);                        // Leave remainder
  282.     }
  283.  
  284.     if (theTime >= kOneMinute)                                    // Any minutes?
  285.     {
  286.         minutes = theTime / kOneMinute;
  287.         theTime -= (minutes * kOneMinute);
  288.     }
  289.  
  290.     seconds = theTime;                                            // Seconds are what's left
  291.  
  292.     GetIndString(timeStr, kStrID, kUpTimeIndex);            // Get the hh:mm:ss string
  293.  
  294.     MakeTimeString(hours, bStr);
  295.     InsertStrAt(timeStr, bStr, 1);                            // Insert the hours
  296.     MakeTimeString(minutes, bStr);
  297.     InsertStrAt(timeStr, bStr, 2);                            // Insert the minutes
  298.     MakeTimeString(seconds, bStr);
  299.     InsertStrAt(timeStr, bStr, 3);                            // Insert the seconds
  300.  
  301.     if (days != 0)
  302.     {
  303.         GetIndString(aStr, kStrID, (days == 1) ? kOneDayUpTimeIndex : kManyDaysUpTimeIndex);
  304.         InsertStrAt(aStr, timeStr, 1);                        // Insert hh:mm:ss into days string
  305.         if (days > 1)
  306.         {
  307.             NumToString(days, bStr);
  308.             InsertStrAt(aStr, bStr, 2);                        // Insert the number of days
  309.         }
  310.         CopyPString(aStr, timeStr);                            // Now copy into timeStr
  311.     }
  312.  
  313.     return;
  314. }
  315.  
  316.  
  317. /***************************************************************************************************
  318.     SetMemory
  319.  
  320.         Set a bunch of bytes to the same value.
  321.  
  322.         -> thePtr            The address of the memory to set
  323.         -> dataSize            The number of bytes to set
  324.         -> initValue        The value to initialize each byte to
  325.  
  326. ****************************************************************************************************/
  327. static void SetMemory(register Ptr thePtr, register long dataSize, register char initValue)
  328. {
  329.     register short    index;
  330.  
  331.  
  332.     for (index = 0; index < dataSize; index++)
  333.         thePtr[index] = initValue;
  334.     return;
  335. }
  336.  
  337.  
  338. /***************************************************************************************************
  339.     GetTargetDate
  340.  
  341.         Display a modal dialog that prompts the user to enter a date and time.
  342.         The formats of the date/time can be entered by the user in any form that
  343.         the String2Date/String2Time can decipher. shortDate form is used for the
  344.         date field as the default format. 
  345.  
  346.         <-> targetDate        On input, the date/time to display in the dialog.
  347.                                 On output, the date/time the user entered if the user
  348.                                 pressed the OK button.
  349.  
  350.         returns:                true if the user clicked the OK button, else false.
  351.  
  352. ****************************************************************************************************/
  353. static Boolean GetTargetDate(long *targetDate)
  354. {
  355.     DialogPtr            theDialog;
  356.     GrafPtr                savePort;
  357.     short                    itemHit;
  358.     short                    kind;
  359.     Handle                h;
  360.     Rect                    r;
  361.     Str255                theStr;
  362.     String2DateStatus    theStatus;
  363.     long                    lengthUsed;
  364.     LongDateRec            dateTime;
  365.  
  366.  
  367.     GetPort(&savePort);
  368.     theDialog = GetNewDialog(kSetTargetID, nil, (WindowPtr)-1);
  369.     // Should check for an error here…
  370.     SetPort(theDialog);
  371.  
  372.     GetDItem(theDialog, OK, &kind, &h, &r);
  373.     PenSize(3, 3);
  374.     InsetRect(&r, -4, -4);
  375.     FrameRoundRect(&r, 16, 16);
  376.     PenSize(1, 1);
  377.  
  378.     IUDateString((unsigned long)*targetDate, shortDate, theStr);
  379.     GetDItem(theDialog, kTargetDate, &kind, &h, &r);
  380.     SetIText(h, theStr);
  381.     SelIText(theDialog, kTargetDate, 0, 9999);
  382.  
  383.     IUTimeString((unsigned long)*targetDate, shortDate, theStr);
  384.     GetDItem(theDialog, kTargetTime, &kind, &h, &r);
  385.     SetIText(h, theStr);
  386.  
  387.     do {
  388.         ModalDialog(nil, &itemHit);
  389.     } while ((itemHit != OK) && (itemHit != cancel));
  390.  
  391.     if (itemHit == OK)
  392.     {
  393.         SetMemory((Ptr)&dateTime, sizeof(dateTime), 0);
  394.  
  395.         GetDItem(theDialog, kTargetDate, &kind, &h, &r);
  396.         GetIText(h, theStr);
  397.         theStatus = String2Date((Ptr)&(theStr[1]), Length(theStr), &gDateCache, &lengthUsed, &dateTime);
  398.         if (theStatus >= 0)
  399.             Date2Secs(&dateTime.od.oldDate, (unsigned long *)targetDate);
  400.  
  401.         GetDItem(theDialog, kTargetTime, &kind, &h, &r);
  402.         GetIText(h, theStr);
  403.         theStatus = String2Time((Ptr)&(theStr[1]), Length(theStr), &gDateCache, &lengthUsed, &dateTime);
  404.         if (theStatus >= 0)
  405.             Date2Secs(&dateTime.od.oldDate, (unsigned long *)targetDate);
  406.     }
  407.  
  408.     DisposDialog(theDialog);
  409.     SetPort(savePort);
  410.  
  411.     return(itemHit == OK);
  412. }
  413.  
  414.  
  415. /***************************************************************************************************
  416.     ReadFile
  417.  
  418.         Read the file containing the saved 'time till' date. If the file doesn't exist,
  419.         return 0.
  420.  
  421.         <- targetDate        The date/time read from the file. If the file does not exist
  422.                                 or could not be opened, 0 is returned.
  423.  
  424. ****************************************************************************************************/
  425. static void ReadFile(long *targetDate)
  426. {
  427.     OSErr    theErr;
  428.     Str63 fileName;
  429.     short    fRefNum;
  430.     long    numBytes;
  431.  
  432.  
  433.     *targetDate = 0;
  434.  
  435.     GetIndString(fileName, kStrID, kDateTimeFileNameIndex);
  436.     theErr = FSOpen(fileName, gVRefNum, &fRefNum);
  437.     if (theErr == noErr)
  438.     {
  439.         numBytes = sizeof(long);
  440.         theErr = FSRead(fRefNum, &numBytes, (Ptr)targetDate);
  441.         theErr = FSClose(fRefNum);
  442.     }
  443.  
  444.     return;
  445. }
  446.  
  447.  
  448. /***************************************************************************************************
  449.     WriteFile
  450.  
  451.         Save the 'time till' date in a file. If the file does not exist, create it.
  452.  
  453.         -> targetDate        The date/time to write to the file.
  454.  
  455. ****************************************************************************************************/
  456. static void WriteFile(long targetDate)
  457. {
  458.     OSErr    theErr;
  459.     Str63 fileName;
  460.     short    fRefNum;
  461.     long    numBytes;
  462.  
  463.  
  464.     GetIndString(fileName, kStrID, kDateTimeFileNameIndex);                        // Get the file name
  465.  
  466.     theErr = FSOpen(fileName, gVRefNum, &fRefNum);                                    // Try to open it
  467.     if (theErr == fnfErr)                                                                    // Doesn't exist?
  468.     {
  469.         theErr = Create(fileName, gVRefNum, kDateTimeFileType, kSignature);    // Create it
  470.         if (theErr == noErr)
  471.             theErr = FSOpen(fileName, gVRefNum, &fRefNum);                            // Now open it
  472.     }
  473.  
  474.     if (theErr == noErr)
  475.     {
  476.         numBytes = sizeof(long);
  477.         theErr = FSWrite(fRefNum, &numBytes, (Ptr)&targetDate);                    // Write the data
  478.         theErr = FSClose(fRefNum);                                                            // Close the file
  479.     }
  480.  
  481.     return;
  482. }
  483.  
  484.  
  485. /***************************************************************************************************
  486.     DoIdle
  487.  
  488.         We've got a slice of free time, so update the date/time remaining.
  489.  
  490.         -> fullRedraw        If true, all parts of the window will be redrawn. If false,
  491.                                 only remaining date/time string is redrawn.
  492.  
  493. ****************************************************************************************************/
  494. static void DoIdle(Boolean fullRedraw)
  495. {
  496.     Str255        theStr;
  497.     Str32            theStr1;
  498.     long            theDateTime;
  499.     Point            mousePt;
  500.     short            thePart;
  501.     WindowPtr    macWindow;
  502.  
  503.  
  504.     SetPort(gWindow);
  505.  
  506.     GetMouse(&mousePt);                                                        // Set the cursor
  507.     LocalToGlobal(&mousePt);
  508.     thePart = FindWindow(mousePt, &macWindow);
  509.     if (thePart == inContent)
  510.         SetCursor(*GetCursor(kHandCursID));
  511.     else
  512.         InitCursor();
  513.  
  514.     if (fullRedraw)                                                            // Redraw everything?
  515.     {
  516.         MoveTo(5, 14);
  517.         GetIndString(theStr, kStrID, kTimeUntilIndex);
  518.         IUDateString(gTargetDate, shortDate, theStr1);
  519.         InsertStrAt(theStr, theStr1, 1);
  520.         IUTimeString(gTargetDate, false, theStr1);
  521.         InsertStrAt(theStr, theStr1, 2);
  522.         DrawString(theStr);
  523.     }
  524.  
  525.     GetDateTime((unsigned long *)&theDateTime);
  526.     if ((unsigned long)theDateTime > (unsigned long)gLastDateTime)
  527.     {
  528.         gLastDateTime = theDateTime;
  529.  
  530.         if (theDateTime > gTargetDate)
  531.             GetIndString(theStr, kStrID, kAlreadyPastIndex);
  532.         else
  533.             MakeRelativeTimeString(gTargetDate - theDateTime, theStr);
  534.  
  535.         MoveTo(5, 28);
  536.         DrawString(theStr);
  537.     }
  538.  
  539.     return;
  540. }
  541.  
  542.  
  543. /***************************************************************************************************
  544.     DoCommand
  545.  
  546.         Handle a menu command.
  547.  
  548.         -> theCommand        The result from MenuSelect or MenuKey
  549.  
  550.         returns:                true if the application should quit, else false.
  551.  
  552. ****************************************************************************************************/
  553. static Boolean DoCommand(long theCommand)
  554. {
  555.     short        theMenu;
  556.     short        itemNum;
  557.     Str255    theDA;
  558.     Boolean    running;
  559.  
  560.  
  561.     running = true;
  562.     theMenu = HiShort(theCommand);
  563.     itemNum = LoShort(theCommand);
  564.  
  565.     switch (theMenu)
  566.     {
  567.         case kAppleMenuID:
  568.         {
  569.             if (itemNum == kAboutItem)
  570.                 Alert(256, nil);
  571.             else
  572.             {
  573.                 GetItem(GetMHandle(kAppleMenuID), itemNum, theDA);
  574.                 OpenDeskAcc(theDA);
  575.             }
  576.             break;
  577.         }
  578.         case kFileMenuID:
  579.         {
  580.             if (itemNum == kSetTargetDateItem)
  581.             {
  582.                 if (GetTargetDate(&gTargetDate))
  583.                 {
  584.                     SetPort(gWindow);
  585.                     InvalRect(&thePort->portRect);
  586.                     WriteFile(gTargetDate);
  587.                 }
  588.             }
  589.             else if (itemNum == kQuitItem)
  590.                 running = false;
  591.             break;
  592.         }
  593.         default:
  594.         {
  595.             break;
  596.         }
  597.     }
  598.     HiliteMenu(0);
  599.  
  600.     return(running);
  601. }
  602.  
  603.  
  604. /***************************************************************************************************
  605.     ProcessEvent
  606.  
  607.         Process an event.
  608.  
  609.         returns:            true if the application should quit, else false.
  610.  
  611. ****************************************************************************************************/
  612. static Boolean ProcessEvent(void)
  613. {
  614.     Boolean        eventResult;
  615.     EventRecord    macEvent;
  616.     Boolean        running;
  617.  
  618.  
  619.     running = true;
  620.     if (gHasWNE)
  621.         eventResult = WaitNextEvent(everyEvent, &macEvent, kSleepTime, gSleepRgn);
  622.     else
  623.     {
  624.         SystemTask();
  625.         eventResult = GetNextEvent(everyEvent, &macEvent);
  626.     }
  627.  
  628.     if (!eventResult)
  629.         DoIdle(false);
  630.     else
  631.     {
  632.         switch (macEvent.what)
  633.         {
  634.             case mouseDown:
  635.             {
  636.                 short            thePart;
  637.                 WindowPtr    macWindow;
  638.                 Rect            dragRect;
  639.                 RgnHandle    grayRgn;
  640.  
  641.  
  642.                 InitCursor();
  643.                 thePart = FindWindow(macEvent.where, &macWindow);
  644.                 switch (thePart)
  645.                 {
  646.                     case inMenuBar:
  647.                     {
  648.                         running = DoCommand(MenuSelect(macEvent.where));
  649.                         break;
  650.                     }
  651.                     case inSysWindow:
  652.                     {
  653.                         SystemClick(&macEvent, macWindow);
  654.                         break;
  655.                     }
  656.                     case inContent:
  657.                     case inDrag:
  658.                     {
  659.                         grayRgn = GetGrayRgn();
  660.                         dragRect = (**grayRgn).rgnBBox;
  661.                         InsetRect(&dragRect, 2, 2);
  662.                         SetCursor(*GetCursor(kGrabbedHandlCursID));
  663.                             DragWindow(macWindow, macEvent.where, &dragRect);
  664.                         SetCursor(*GetCursor(kHandCursID));
  665.                         break;
  666.                     }
  667.                     default:
  668.                     {
  669.                         break;
  670.                     }
  671.                 }
  672.                 break;
  673.             }
  674.  
  675.             case keyDown:
  676.             {
  677.                 InitCursor();
  678.                 if (macEvent.modifiers & cmdKey)
  679.                     running = DoCommand(MenuKey(macEvent.message & charCodeMask));
  680.                 break;
  681.             }
  682.  
  683.             case updateEvt:
  684.             {
  685.                 BeginUpdate((WindowPtr)macEvent.message);
  686.                     ClipRect(&thePort->portRect);
  687.                     EraseRect(&thePort->portRect);
  688.                     DoIdle(true);
  689.                 EndUpdate((WindowPtr)macEvent.message);
  690.                 break;
  691.             }
  692.  
  693.             default:
  694.             {
  695.                 break;
  696.             }
  697.         }
  698.     }
  699.  
  700.     return(running);
  701. }
  702.  
  703.  
  704.  
  705. /***************************************************************************************************
  706.     Initialize
  707.  
  708.         Initialize the toolbox and application.
  709.  
  710. ****************************************************************************************************/
  711. static void Initialize(void)
  712. {
  713.     MenuHandle    theMenu;
  714.     short            index;
  715.     SysEnvRec    theWorld;
  716.     Rect            theRect;
  717.     Ptr            p;
  718.     Itl4Handle    itl4;
  719.  
  720.  
  721.     InitGraf(&thePort);
  722.     InitFonts();
  723.     InitWindows();
  724.     InitMenus();
  725.     TEInit();
  726.     InitDialogs(nil);
  727.     InitCursor();
  728.     MaxApplZone();
  729.     FlushEvents(everyEvent - diskMask, 0);
  730.  
  731.     GetVol(nil, &gVRefNum);
  732.  
  733.     gHasWNE            = false;
  734.     gWindow            = nil;
  735.     gLastDateTime    = 0;
  736.  
  737.     ReadFile(&gTargetDate);
  738.  
  739.     gSleepRgn = NewRgn();
  740.     SetRect(&theRect, 1, 1, 3, 3);
  741.     RectRgn(gSleepRgn, &theRect);
  742.  
  743.     SysEnvirons(1, &theWorld);
  744.     if ((theWorld.machineType >= 0) && TrapAvailable(_WaitNextEvent))
  745.         gHasWNE = true;
  746.  
  747.     for (index = kAppleMenuID; index <= kFileMenuID; index++)
  748.     {
  749.         theMenu = GetMenu(index);
  750.         InsertMenu(theMenu, 0);
  751.     }
  752.     AddResMenu(GetMHandle(kAppleMenuID), 'DRVR');
  753.     DrawMenuBar();
  754.  
  755.     gWindow = GetNewWindow(kWindowID, nil, (WindowPtr)(-1));
  756.     SetPort(gWindow);
  757.     TextFont(applFont);
  758.     TextSize(9);
  759.     TextMode(srcCopy);
  760.  
  761.     itl4 = (Itl4Handle)IUGetIntl(4);
  762.     if (itl4 != nil)
  763.     {
  764.         p = (Ptr)(*itl4);
  765.         BlockMove((Ptr)(p + (**itl4).defPartsOffset), (Ptr)&gPartsTable, sizeof(NumberParts));
  766.     }
  767.  
  768.     InitDateCache(&gDateCache);
  769.  
  770.     return;
  771. }
  772.  
  773.  
  774. /***************************************************************************************************
  775.     main
  776.  
  777. ****************************************************************************************************/
  778. void main(void)
  779. {
  780.     Boolean    running;
  781.  
  782.  
  783.     Initialize();
  784.  
  785.     running = true;
  786.     do {
  787.         running = ProcessEvent();
  788.     } while (running);
  789. }
  790.