home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / pascal / library / dos / packer / arc / arctool / timer.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1988-09-29  |  21.0 KB  |  629 lines

  1. {
  2.                        F i l e    I n f o r m a t i o n
  3.  
  4. * DESCRIPTION
  5. Version 1.01. Author Rob Rosenberger. Turbo Pascal 4.0 unit source code
  6. provides 256 independent stop-watch timers. Great for timing the execution
  7. of a routine or an I/O access. Timer #0 specifically times the overall
  8. program, the rest are at your disposal. Fully compatible with other
  9. programs and units since it dosen't use clock ticks.
  10.  
  11. }
  12. {$R-,S+,I+,D+,T-,F-,V+,B-,N-,L+ }
  13.  
  14. UNIT Timer;  {Version 1.01, released to the public domain on 20 June 1988 }
  15.  
  16. {
  17. Created by:          Rob Rosenberger             CompuServe
  18.                       P.O. Box #643              74017,1344
  19.                    O'Fallon, IL  62269
  20.  
  21.  
  22.    This unit takes the hassles off the programmer when it comes to timing
  23. programming routines, disk accesses, etc.  Just place the appropriate routine
  24. calls where you want to start/start the timer, or catch a lap-time.  This
  25. unit does the rest!
  26.    You can use up to 255 different timers at once!  Just supply the number of
  27. the timer you want to use.  Clock #zero is a special timer that starts when
  28. the program begins.  You can tell how long your program has been running just
  29. by using GetLapTime(0)!
  30.    The unit does NOT count clock ticks or anything like that.  It asks DOS for
  31. the current date & time and calculates the elapsed time from that.  It should
  32. be compatible with any program or unit.
  33.    Please send a letter or CompuServe EasyPlex message if you have any ideas
  34. that will make this unit even better.  I'll give you credit for your ideas!
  35.  
  36. Version 1.00: released to the public domain on 24 Feb 88.
  37.  
  38. Version 1.01: released to the public domain on 20 Jun 88
  39.    Altered the returned strings for GetLapTime and RestartTimer so they would
  40. only show the time-lapse portion.  The programmer must attach a description to
  41. the time, i.e. WRITE(OUTPUT,Timer0msg + GetLapTime(0)).
  42.    Added logic to the program to account for a DOS 3.20 bug which doesn't roll
  43. the date when the DOS clock ticks past midnight.  The TIMER unit now accounts
  44. for just such a possibility and, if it comes across it, it will add one day to
  45. the current time.  Note: This means a time-lapse is limited to 24 hours.  Any
  46. multiple-day lapses will be lost because of the DOS 3.20 bug.
  47. }
  48.  
  49. INTERFACE {section}
  50.  
  51. USES DOS;
  52.  
  53.  
  54. PROCEDURE StartTimer (WhichClock : BYTE);
  55.   {Starts the internal clock.  Resets the clock if it was previously set.}
  56.  
  57. FUNCTION  GetLapTime (WhichClock : BYTE) : STRING;
  58.   {Returns a string showing the elapsed time.  The returned string is...
  59.     "xx:xx:xx.xx".  The clock continues to run.}
  60.  
  61. PROCEDURE RestartTimer (WhichClock : BYTE);
  62.   {Restarts the clock if the StopTimer procedure stopped the clock.  It does
  63.     nothing if the clock is still running.}
  64.  
  65. FUNCTION  StopTimer (WhichClock : BYTE) : STRING;
  66.   {Stops the timer without clearing the elapsed time.  Returned string will be
  67.     one of the following...  "xx:xx:xx.xx", or "Can't stop clock #0!".}
  68.  
  69. {----------------------------------------------------------------------------}
  70.  
  71.  
  72.  
  73. IMPLEMENTATION {section}
  74.  
  75. CONST
  76.    NullChar = $00;
  77.    Colon    = ':';
  78.    Period   = '.';
  79.    Space    = ' ';
  80.    Zero     = '0';
  81.  
  82. TYPE
  83.    DateRecord = RECORD
  84.                 Year      : WORD;
  85.                 Month     : WORD;
  86.                 Date      : WORD;
  87.                 DayOfWeek : WORD
  88.                 END;
  89.  
  90.    TimeRecord = RECORD
  91.                 Hour      : WORD;
  92.                 Minute    : WORD;
  93.                 Second    : WORD;
  94.                 Hundredth : WORD
  95.                 END;
  96.  
  97.    ClockRecord = RECORD
  98.                  ClockStartDate : DateRecord;
  99.                  ClockStartTime : TimeRecord;
  100.                  ElapsedTime    : TimeRecord;
  101.                  ClockIsRunning : BOOLEAN;
  102.                  END;
  103.  
  104. VAR
  105.    ClockArray : ARRAY [BYTE] OF ClockRecord;
  106.  
  107.  
  108. {============================================================================}
  109. PROCEDURE AddTogetherTwoTimeRecords(TimeRecordOne : TimeRecord;
  110.                                     TimeRecordTwo : TimeRecord;
  111.                                 VAR ResultRecord  : TimeRecord);
  112.    {This is an internal procedure.}
  113.  
  114.    {This procedure adds two time records and stores the result in the third
  115. record.  It is up to the calling routine to deal with times that go beyond the
  116. 24-hour mark.}
  117.  
  118. BEGIN {AdditionOfTwoTimes}
  119. ResultRecord.Hundredth := (TimeRecordOne.Hundredth + TimeRecordTwo.Hundredth);
  120. ResultRecord.Second    := (TimeRecordOne.Second    + TimeRecordTwo.Second);
  121. ResultRecord.Minute    := (TimeRecordOne.Minute    + TimeRecordTwo.Minute);
  122. ResultRecord.Hour      := (TimeRecordOne.Hour      + TimeRecordTwo.Hour);
  123.  
  124. WHILE (ResultRecord.Hundredth >= 100)
  125.  DO BEGIN
  126.     DEC(ResultRecord.Hundredth,100);
  127.     INC(ResultRecord.Second)
  128.     END;
  129. WHILE (ResultRecord.Second >= 60)
  130.  DO BEGIN
  131.     DEC(ResultRecord.Second,60);
  132.     INC(ResultRecord.Minute)
  133.     END;
  134. WHILE (ResultRecord.Minute >= 60)
  135.  DO BEGIN
  136.     DEC(ResultRecord.Minute,60);
  137.     INC(ResultRecord.Hour)
  138.     END
  139. END; {AdditionOfTwoTimes}
  140. {============================================================================}
  141.  
  142. {============================================================================}
  143. PROCEDURE AddOneDayToDate(VAR TheDateRecord : DateRecord);
  144.    {This is an internal procedure.}
  145.  
  146.    {This procedure adds one day to TheDateRecord.  Results are unpredictable
  147. with an invalid date.}
  148.  
  149. BEGIN {AddOneDayToDate}
  150. WITH TheDateRecord
  151.  DO BEGIN
  152.     INC(Date);
  153.     CASE Month OF
  154.       1, 3, 5, 7, 8, 10, 12 :
  155.         IF (Date > 31)
  156.          THEN
  157.             BEGIN
  158.             DEC(Date,31);
  159.             INC(Month)
  160.             END;
  161.       4, 6, 9, 11 :
  162.         IF (Date > 30)
  163.          THEN
  164.             BEGIN
  165.             DEC(Date,30);
  166.             INC(Month)
  167.             END;
  168.       2 :
  169.         IF (Date > 29)
  170.          THEN
  171.             BEGIN
  172.             DEC(Date,29);
  173.             Month := 3
  174.             END
  175.          ELSE
  176.             IF ((Date > 28) AND NOT (((Year MOD 4) = 0)
  177.              AND (((Year MOD 100) <> 0) OR ((Year MOD 400) = 0))))
  178.              THEN
  179.                 BEGIN
  180.                 DEC(Date,28);
  181.                 Month := 3
  182.                 END
  183.      END; {CASE Month}
  184.     WHILE (Month > 12)
  185.      DO BEGIN
  186.         DEC(Month,12);
  187.         INC(Year)
  188.         END;
  189.     INC(DayOfWeek);
  190.     DayOfWeek := (DayOfWeek MOD 7)
  191.     END {WITH TheDateRec}
  192. END; {AddOneDayToDate}
  193. {============================================================================}
  194.  
  195. {============================================================================}
  196. FUNCTION JulianDate(TheDate : DateRecord) : LONGINT;
  197.    {This is an internal function.}
  198.  
  199.    {This function returns TheDate as a long integer which is the value of the
  200. date as a julian date.  It assumes the date is valid or at least zeroed-out.
  201. The syntax of the julian date is Year*1000 + the day of the year.  Be sure the
  202. year is in the format 19xx, not just xx!
  203.    Julian dates are nice in that you can compare them to see which date comes
  204. first in history.}
  205.  
  206. VAR
  207.    TempLongInt : LONGINT;
  208.  
  209. BEGIN {JulianDate}
  210. TempLongInt := TheDate.Year;
  211. TempLongInt := (TempLongInt * 1000);
  212.    {We do this portion of the logic in two steps because we would get overflow
  213.    if we said "TempLongInt := (DateRecord.Year * 1000)".  See the TP4 manual,
  214.    p. 210 for an in-depth explanation.}
  215.  
  216. CASE TheDate.Month OF
  217.   02 : INC(TempLongInt,31);
  218.   03 : INC(TempLongInt,59);
  219.   04 : INC(TempLongInt,90);
  220.   05 : INC(TempLongInt,120);
  221.   06 : INC(TempLongInt,151);
  222.   07 : INC(TempLongInt,181);
  223.   08 : INC(TempLongInt,212);
  224.   09 : INC(TempLongInt,243);
  225.   10 : INC(TempLongInt,273);
  226.   11 : INC(TempLongInt,304);
  227.   12 : INC(TempLongInt,334)
  228.  END; {CASE DateRecord.Month}
  229. IF (((TheDate.Year MOD 4) = 0) AND (TheDate.Month > 2))
  230.  THEN
  231.     IF (((TheDate.Year MOD 100) <> 0) OR ((TheDate.Year MOD 400) = 0))
  232.      THEN INC(TempLongInt); {add a day for leapyears}
  233.  
  234. TempLongInt := (TempLongInt + TheDate.Date);
  235.  
  236. JulianDate := TempLongInt
  237. END; {JulianDate}
  238. {============================================================================}
  239.  
  240. {============================================================================}
  241. PROCEDURE SubtractOneDayFromDate(VAR TheDateRecord : DateRecord);
  242.    {This is an internal procedure.}
  243.  
  244.    {This procedure subtracts one day to TheDateRecord.  Results are unpredict-
  245. able with an invalid date.}
  246.  
  247. BEGIN {SubtractOneDayFromDate}
  248. WITH TheDateRecord
  249.  DO BEGIN
  250.     IF Date = 1
  251.      THEN
  252.         BEGIN
  253.         IF Month = 1
  254.          THEN
  255.             BEGIN
  256.             DEC(Year);
  257.             Month := 12;
  258.             Date := 31
  259.             END
  260.          ELSE
  261.             BEGIN
  262.             DEC(Month);
  263.             CASE Month OF
  264.               1, 3, 5, 7, 8, 10, 12 :
  265.                 Date := 31;
  266.               4, 6, 9, 11 :
  267.                 Date := 30;
  268.               2 :
  269.                 IF (((Year MOD 4) = 0)
  270.                  AND (((Year MOD 100) <> 0) OR ((Year MOD 400) = 0)))
  271.                  THEN Date := 29
  272.                  ELSE Date := 28
  273.              END {CASE Month}
  274.             END
  275.         END
  276.      ELSE
  277.         DEC(Date);
  278.     IF (DayOfWeek = 0)
  279.      THEN
  280.         DayOfWeek := 6
  281.      ELSE
  282.         DEC(DayOfWeek)
  283.     END {WITH TheDateRec}
  284. END; {SubtractOneDayFromDate}
  285. {============================================================================}
  286.  
  287. {============================================================================}
  288. FUNCTION  ConvertTimeToString(TheTimeRec : TimeRecord) : STRING;
  289.    {This is an internal function.}
  290.  
  291.    {This function creates a time string from TheTimeRec.  It doesn't check to
  292. see if the time is valid.}
  293.  
  294. VAR
  295.    TempString1 : STRING;
  296.    TempString2 : STRING;
  297.    Index       : BYTE;
  298.  
  299. BEGIN {ConvertTimeToString}
  300. STR(TheTimeRec.Hour:2,{VAR} TempString1);
  301. STR(TheTimeRec.Minute:2,{VAR} TempString2);
  302. TempString1 := (TempString1 + Colon + TempString2);
  303. STR(TheTimeRec.Second:2,{VAR} TempString2);
  304. TempString1 := (TempString1 + Colon + TempString2);
  305. STR(TheTimeRec.Hundredth:2,{VAR} TempString2);
  306. TempString1 := (TempString1 + Period + TempString2);
  307.  
  308. FOR Index := 1 TO LENGTH(TempString1)
  309.  DO IF (TempString1[Index] = Space)
  310.      THEN TempString1[Index] := Zero;
  311. ConvertTimeToString := TempString1
  312. END; {ConvertTimeToString}
  313. {============================================================================}
  314.  
  315. {============================================================================}
  316. FUNCTION  DatesAreEqual(DateRecord1 : DateRecord;
  317.                         DateRecord2 : DateRecord) : BOOLEAN;
  318.  
  319.    {This function determines if two date records are identical.  It does not
  320. compare the day of the week.}
  321.  
  322. BEGIN {DatesAreEqual}
  323. IF ((DateRecord1.Date = DateRecord2.Date)
  324.  AND (DateRecord1.Month = DateRecord2.Month)
  325.  AND (DateRecord1.Year = DateRecord2.Year))
  326.  THEN DatesAreEqual := TRUE
  327.  ELSE DatesAreEqual := FALSE
  328. END; {DatesAreEqual}
  329. {============================================================================}
  330.  
  331. {============================================================================}
  332. FUNCTION  JulianTime(TimeRecord : TimeRecord) : LONGINT;
  333.  
  334.    {This function returns the given TimeRecord as a long integer which is the
  335. value of the time as a julian time.  Julian times are nice in that you can
  336. compare them to see which time is earlier in the day.}
  337.  
  338. VAR
  339.    TempLongInt  : LONGINT;
  340.    TempVariable : LONGINT;
  341.  
  342. BEGIN {JulianTime}
  343. TempLongInt  := TimeRecord.Hour;
  344. TempLongInt  := (TempLongInt * 1000000);
  345. TempVariable := TimeRecord.Minute;
  346. TempLongInt  := (TempLongInt
  347.                    + (TempVariable * 10000)
  348.                    + (TimeRecord.Second * 100)
  349.                    + TimeRecord.Hundredth);
  350.   {We do some portions of the logic in two steps because we would get overflow
  351.     if we said "TempLongInt := (TimeRecord.Hour * 1000000)", etc.  See the TP4
  352.     manual, p. 210 for an in-depth explanation.}
  353.  
  354. JulianTime := TempLongInt
  355. END; {JulianTime}
  356. {============================================================================}
  357.  
  358. {============================================================================}
  359. PROCEDURE DetermineLengthBetweenTwoDateTimes(StartDateRecord   : DateRecord;
  360.                                              StartTimeRecord   : TimeRecord;
  361.                                              EndDateRecord     : DateRecord;
  362.                                              EndTimeRecord     : TimeRecord;
  363.                                          VAR ElapsedTimeRecord : TimeRecord);
  364.    {This is an internal procedure.}
  365.  
  366.    {This procedure determines the length of time between two dates/times.  It
  367. assumes the starting date/time comes after the ending date/time.
  368.    This procedure quickly calculates the elapsed time, then begins adding one
  369. day at a time until it determines the date separation.  Lengthy separations
  370. will require quite a few add-one-day repetitions!
  371.    Should the starting date be GREATER THAN the ending date, this procedure
  372. will assume DOS 3.20 is in use and it's date-rollover bug has popped up.  It
  373. will add one day to the ending date as a compromise.}
  374.  
  375. VAR
  376.    JulianEndDate : LONGINT;
  377.  
  378. BEGIN {DetermineLengthBetweenTwoDateTimes}
  379. {Initialize.}
  380. WITH ElapsedTimeRecord
  381.  DO BEGIN
  382.     Hour      := 0;
  383.     Minute    := 0;
  384.     Second    := 0;
  385.     Hundredth := 0
  386.     END;
  387.  
  388. IF ((JulianDate(StartDateRecord) > JulianDate(EndDateRecord))
  389.  OR (DatesAreEqual(StartDateRecord,EndDateRecord)
  390.  AND (JulianTime(StartTimeRecord) > JulianTime(EndTimeRecord))))
  391.  THEN {StartDateRecord comes chronologically after EndDateRecord!}
  392.     AddOneDayToDate({VAR} EndDateRecord);
  393.  
  394. WHILE (EndTimeRecord.Hundredth < StartTimeRecord.Hundredth)
  395.  DO BEGIN
  396.     INC(EndTimeRecord.Hundredth,100);
  397.     IF (EndTimeRecord.Second = 0)
  398.      THEN
  399.         BEGIN
  400.         EndTimeRecord.Second := 59;
  401.         IF (EndTimeRecord.Minute = 0)
  402.          THEN
  403.             BEGIN
  404.             EndTimeRecord.Minute := 59;
  405.             IF (EndTimeRecord.Hour = 0)
  406.              THEN
  407.                 BEGIN
  408.                 EndTimeRecord.Hour := 23;
  409.                 SubtractOneDayFromDate(EndDateRecord)
  410.                 END
  411.              ELSE
  412.                 DEC(EndTimeRecord.Hour)
  413.             END
  414.          ELSE
  415.             DEC(EndTimeRecord.Minute)
  416.         END
  417.      ELSE
  418.         DEC(EndTimeRecord.Second)
  419.     END; {WHILE (EndTimeRecord.Hundreth < StartTimeRecord.Hundredth)}
  420. ElapsedTimeRecord.Hundredth := (EndTimeRecord.Hundredth
  421.                                         - StartTimeRecord.Hundredth);
  422.  
  423. WHILE (EndTimeRecord.Second < StartTimeRecord.Second)
  424.  DO BEGIN
  425.     INC(EndTimeRecord.Second,60);
  426.     IF (EndTimeRecord.Minute = 0)
  427.      THEN
  428.         BEGIN
  429.         EndTimeRecord.Minute := 59;
  430.         IF (EndTimeRecord.Hour = 0)
  431.          THEN
  432.             BEGIN
  433.             EndTimeRecord.Hour := 23;
  434.             SubtractOneDayFromDate(EndDateRecord)
  435.             END
  436.          ELSE
  437.             DEC(EndTimeRecord.Hour)
  438.         END
  439.      ELSE
  440.         DEC(EndTimeRecord.Minute)
  441.     END; {WHILE (EndTimeRecord.Second < StartTimeRecord.Second)}
  442. ElapsedTimeRecord.Second := (EndTimeRecord.Second - StartTimeRecord.Second);
  443.  
  444. WHILE (EndTimeRecord.Minute < StartTimeRecord.Minute)
  445.  DO BEGIN
  446.     INC(EndTimeRecord.Minute,60);
  447.     IF (EndTimeRecord.Hour = 0)
  448.      THEN
  449.         BEGIN
  450.         EndTimeRecord.Hour := 23;
  451.         SubtractOneDayFromDate(EndDateRecord)
  452.         END
  453.      ELSE
  454.         DEC(EndTimeRecord.Hour)
  455.     END; {WHILE (EndTimeRecord.Minute < StartTimeRecord.Minute)}
  456. ElapsedTimeRecord.Minute := (EndTimeRecord.Minute - StartTimeRecord.Minute);
  457.  
  458. WHILE (EndTimeRecord.Hour < StartTimeRecord.Hour)
  459.  DO BEGIN
  460.     INC(EndTimeRecord.Hour,24);
  461.     SubtractOneDayFromDate(EndDateRecord)
  462.     END; {WHILE (EndTimeRecord.Hour < StartTimeRecord.Hour)}
  463. ElapsedTimeRecord.Hour := (EndTimeRecord.Hour - StartTimeRecord.Hour);
  464.  
  465. JulianEndDate := JulianDate(EndDateRecord);
  466. WHILE (JulianDate(StartDateRecord) <> JulianEndDate)
  467.  DO BEGIN
  468.     INC(ElapsedTimeRecord.Hour,24);
  469.     AddOneDayToDate({VAR} StartDateRecord)
  470.     END {WHILE}
  471. END; {DetermineLengthBetweenTwoDateTimes}
  472. {============================================================================}
  473.  
  474. {============================================================================}
  475. PROCEDURE StartTimer (WhichClock : BYTE);
  476.  
  477.   {Starts the internal clock.  Resets the clock if it was previously set.}
  478.  
  479. BEGIN {StartTimer}
  480. IF (WhichClock = 0)
  481.  THEN {can't reset the program-timer clock!}
  482.     EXIT
  483.  ELSE
  484.     WITH ClockArray[WhichClock]
  485.      DO BEGIN
  486.         WITH ClockStartDate
  487.          DO GETDATE({VAR} Year,Month,Date,DayOfWeek);
  488.         WITH ClockStartTime
  489.          DO GETTIME({VAR} Hour,Minute,Second,Hundredth);
  490.         WITH ElapsedTime
  491.          DO BEGIN
  492.             Hour      := 0;
  493.             Minute    := 0;
  494.             Second    := 0;
  495.             Hundredth := 0
  496.             END;
  497.         ClockIsRunning := TRUE
  498.         END
  499. END; {StartTimer}
  500. {============================================================================}
  501.  
  502. {============================================================================}
  503. FUNCTION  GetLapTime (WhichClock : BYTE) : STRING;
  504.  
  505.   {Returns a string showing the elapsed time.  The returned string is...
  506.     "xx:xx:xx.xx".  The clock continues to run.}
  507.  
  508. VAR
  509.    CurrentDate : DateRecord;
  510.    CurrentTime : TimeRecord;
  511.    ElapsedTime : TimeRecord;
  512.    TempString  : STRING[3];
  513.  
  514. BEGIN {GetLapTime}
  515. {Initialize.}
  516. WITH CurrentDate
  517.  DO GETDATE({VAR} Year,Month,Date,DayOfWeek);
  518. WITH CurrentTime
  519.  DO GETTIME({VAR} Hour,Minute,Second,Hundredth);
  520. FILLCHAR(ElapsedTime,SIZEOF(ElapsedTime),NullChar);
  521. STR(WhichClock,{VAR} TempString);
  522.  
  523. {Determine how long it's been since timer was started.}
  524. DetermineLengthBetweenTwoDateTimes(ClockArray[WhichClock].ClockStartDate,
  525.                                    ClockArray[WhichClock].ClockStartTime,
  526.                                    CurrentDate,
  527.                                    CurrentTime,
  528.                              {VAR} ElapsedTime);
  529. {Add that to any lap time that was stored when StopTimer routine was called.}
  530. AddTogetherTwoTimeRecords(ElapsedTime,
  531.                           ClockArray[WhichClock].ElapsedTime,
  532.                     {VAR} ElapsedTime);
  533.  
  534. {Feed information back to the calling routine.}
  535. GetLapTime := ConvertTimeToString(ElapsedTime)
  536. END; {GetLapTime}
  537. {============================================================================}
  538.  
  539. {============================================================================}
  540. PROCEDURE RestartTimer (WhichClock : BYTE);
  541.  
  542.   {Restarts the clock if the StopTimer procedure stopped the clock.  It does
  543.     nothing if the clock is still running.}
  544.  
  545. BEGIN {RestartTimer}
  546. WITH ClockArray[WhichClock]
  547.  DO BEGIN
  548.     WITH ClockStartDate
  549.      DO GETDATE({VAR} Year,Month,Date,DayOfWeek);
  550.     WITH ClockStartTime
  551.      DO GETTIME({VAR} Hour,Minute,Second,Hundredth);
  552.     {Leave the elapsed time alone.}
  553.     ClockIsRunning := TRUE
  554.     END
  555. END; {RestartTimer}
  556.  
  557. {============================================================================}
  558.  
  559.  
  560. {============================================================================}
  561. FUNCTION  StopTimer (WhichClock : BYTE) : STRING;
  562.  
  563.   {Stops the timer without clearing the elapsed time.  Returned string will be
  564.     one of the following...  "xx:xx:xx.xx", or "Can't stop clock #0!".}
  565.  
  566. CONST
  567.    CantStopClockZeroText = 'Can''t stop clock #0!';
  568.  
  569. VAR
  570.    CurrentDate : DateRecord;
  571.    CurrentTime : TimeRecord;
  572.    ElapsedTime : TimeRecord;
  573.    TempString  : STRING[3];
  574.  
  575. BEGIN {StopTimer}
  576. IF ((WhichClock = 0)
  577.  OR (NOT ClockArray[WhichClock].ClockIsRunning))
  578.  THEN {tell programmer we can't stop the overall program timer}
  579.     StopTimer := (CantStopClockZeroText)
  580.  ELSE
  581.     BEGIN
  582.     {Initialize.}
  583.     WITH CurrentDate
  584.      DO GETDATE({VAR} Year,Month,Date,DayOfWeek);
  585.     WITH CurrentTime
  586.      DO GETTIME({VAR} Hour,Minute,Second,Hundredth);
  587.     FILLCHAR(ElapsedTime,SIZEOF(ElapsedTime),NullChar);
  588.     STR(WhichClock,{VAR} TempString);
  589.  
  590.     {Determine how long it's been since timer was started.}
  591.     DetermineLengthBetweenTwoDateTimes(ClockArray[WhichClock].ClockStartDate,
  592.                                        ClockArray[WhichClock].ClockStartTime,
  593.                                        CurrentDate,
  594.                                        CurrentTime,
  595.                                  {VAR} ElapsedTime);
  596.     {Add that to any lap time currently stored.}
  597.     AddTogetherTwoTimeRecords(ElapsedTime,
  598.                               ClockArray[WhichClock].ElapsedTime,
  599.                         {VAR} ClockArray[WhichClock].ElapsedTime);
  600.  
  601.     ClockArray[WhichClock].ClockIsRunning := FALSE;
  602.  
  603.     {Feed information back to the calling routine.}
  604.     StopTimer := ConvertTimeToString(ElapsedTime)
  605.     END
  606. END; {StopTimer}
  607. {============================================================================}
  608.  
  609.  
  610.  
  611.  
  612.  
  613. BEGIN {Timer UNIT}
  614.  
  615. {Zero-out the ClockArray.}
  616. FILLCHAR(ClockArray,SIZEOF(ClockArray),NullChar);
  617.  
  618. {Start the program timer, AKA ClockArray(0).}
  619. WITH ClockArray[0]
  620.  DO BEGIN
  621.     WITH ClockStartDate
  622.      DO GETDATE({VAR} Year,Month,Date,DayOfWeek);
  623.     WITH ClockStartTime
  624.      DO GETTIME({VAR} Hour,Minute,Second,Hundredth);
  625.     ClockIsRunning := TRUE
  626.     END
  627.  
  628. END. {Timer UNIT}
  629.