home *** CD-ROM | disk | FTP | other *** search
/ Computer Select (Limited Edition) / Computer Select.iso / pcmag / v11n01 / trackr.asm < prev    next >
Encoding:
Assembly Source File  |  1992-01-06  |  79.4 KB  |  2,562 lines

  1. ;============================================================================
  2. ; TRACKR.COM keeps logs of time spent on individual tasks
  3. ;  
  4. ; Revision History:
  5. ;
  6. ;       Version 1.0     Initial Release
  7. ;               1.1     1/7/92  Bug fixes
  8. ;
  9. ;============================================================================
  10.  
  11. Code        segment byte public 'code'
  12.             assume cs:code
  13.             assume ds:code
  14.  
  15. org 100h
  16. LGo:        jmp     Init
  17.  
  18.  
  19. Drive       db      79 dup (0)          ;full pathname of .LOG files
  20. NameOff     dw      offset Drive        ;offset where filename goes onto path
  21. TaskOff     dw      0                   ;offset of current task in TaskList 
  22. SrchName    db      '*'
  23. Extension   db      '.LOG',0
  24. ScanCode    db      13h                 ;Hot key scan code (R)
  25. ShiftState  db      4                   ;hot key shift state (Ctrl)
  26. Space       db      ' '
  27. HAt         db      1Fh                 ;hi-lite screen attribute
  28. NAt         db      31h                 ;normal screen attribute
  29.  
  30. Vec09       dd      0                   ;original BIOS interupt address
  31. Vec13       dd      0
  32. Vec08       dd      0
  33. Vec28       dd      0
  34.  
  35. OrgCursor   dw      0                   ;cursor location when popped up
  36. VidPage     db      0                   ;video page during pop-up
  37. Up?         db      0                   ;1 if Tracker is popped up
  38. MsgUp?      db      0                   ;1 if Reminder msg is up
  39. Minutes     dw      0                   ;# of minutes task has been active
  40. Min_Ticks   dw      0444h               ;ticks in a minute
  41. Display?    db      1                   ;1 if reminder is to be displayed
  42. WaitTicks   dw      444h                ;interval between reminders (ticks)
  43. Rem_Ticks   dw      0                   ;interval between reminders (ticks)
  44. MsgTicks    db      5Ah                 ;clock ticks reminder stays up
  45. Timer?      db      0                   ;1 if timer is activated
  46. Resume      db      'Resume'
  47. Msg         db      ' hh:mm  '
  48. FileName    db      14 dup (0)
  49.             db      0Dh,0Ah,'$'
  50. PauseMsg    db      ' Timer on Pause '
  51. ScrnMsg     db      '   :            '
  52. Tick        dw      0
  53. OurPSP      dw      0                   ;Trackr's PSP segment
  54. ParentPSP   dw      0                   ;parent program's PSP segment
  55. OrgVidSeg   dw      0B000h              ;video segment
  56. VidSeg      dw      0                   ;OrgVidSeg adjusted for screen offset
  57. Pausing?    db      0                   ;1 if pausing
  58. Message     db      'TrackerPro'
  59. Pause       db      'PAUSE'
  60. DayTot      dw      0                   ;day total of time
  61. Total       dw      0                   ;grand total of time
  62. DayTotMsg   db      '*           Day Total:    :'
  63.             db      '              ',0Dh,0Ah,0Dh,0Ah
  64. TotalMsg    db      '========== Task Total:    :              ',0Dh,0Ah
  65. VidMode     db      0                   ;video mode
  66. StrSize     db      0                   ;size of string inputted
  67. TopPage     db      0                   ;first task of current display
  68. NumTasks    db      0                   ;# of tasks
  69. NumClients  db      0                   ;# of Clients
  70. Update?     db      0                   ;1 if updating
  71.  
  72. ThisFile    db      'TRACKR.COM',0
  73. Menu        db      'P',1,'ause',2
  74.             db      'L',1,'og off',2
  75.             db      'S',1,'witch',2
  76. Menu2       db      'C',1,'reate new task',2
  77.             db      'U',1,'pdate task log'
  78. MenuEnd     db      3
  79.             db      'L',1,'og in new task',3
  80. SelectTask  db      '   Task #:',0
  81. InpClient   db      ' Client #:',0
  82.  
  83. TaskMsg     db      'Tasks ─'
  84. Status   db   ' Active task:              Elapsed time:         '
  85.  
  86. Screen   db   ' Active task:              Elapsed time:         '
  87.          db   '┌ Tasks ──────────────────┬ Press: ─────────────┐'
  88.          db   '│ 0 NEW        5          │                     │'
  89.          db   '│ 1            6          │                     │'
  90.          db   '│ 2            7          │                     │'
  91.          db   '│ 3            8          │                     │'
  92.          db   '│ 4            9          │                     │'
  93.          db   '└────────────── Press Escape to Exit ───────────┘'
  94. ;       Note: "Screen" is also used to store screen characters overwritten by
  95. ;             Trackr when it pops up
  96.  
  97. Attributes  db      398 dup (0)         ;stores overwritten screen attributes
  98. DTA         db      49 dup (0)          ;disk transfer area
  99. DiskOp?     db      0                   ;1 if disk ops in progress
  100. DBOff       dw      0                   ;DOS busy byte offset
  101. DBSeg       dw      0                   ;DOS busy byte segment
  102. Request?    db      0                   ;1=request to pop-up
  103. TryCnt      db      5Bh                 ;clock ticks to try to pop-up
  104. NameMsg     db      'Task name:',0
  105. DupNameMsg  db      'Task already exists.  Press any key.',0
  106. InvNameMsg  db      'Invalid file name.  Press any key.',0
  107. TooManyMsg  db      'Ignoring extra clients. Press any key.',0
  108. StackPtr    dw      0
  109. HoldSP      dw      0
  110. ClientFH    dw      0FFFh               ;CLIENT.DAT file handle
  111. LogFH       dw      0FFFh               ;log file handle
  112. TempFH      dw      0FFFh               ;temp file's file handle
  113. HoldFH      dw      0                   ;temporarily holds file handle
  114. Flag        db      0                   ;procedure flag
  115. Client?     db      0                   ;procedure flag
  116. Client      db      21 dup (0)  ;first 21 bytes of Client info
  117. Rate        dw      0                   ;billing rate
  118. Units       dw      0                   ;billing increments
  119. CTopPage    db      0                   ;first client of current display
  120. ClientFN    db      'CLIENT.DAT',0
  121. TempFN      db      'TEMP',0
  122. BytesRead   dw      0                   ;# of bytes read
  123. EndRec      dw      0                   ;signal end of record
  124. EoF         db      0                   ;signals end of file
  125. Date        db      8 dup (0)
  126. Today       db      '  /  /  ',0
  127. LogIn       dw      0                   ;time logged in
  128. LogOut      dw      0                   ;time logged out
  129. LogOff?     db      0                   ;1 if logging out
  130. CListPtr    dw      0
  131. ClientArray dw      30 dup (0)          ;30 clients
  132. TaskList    db      650 dup (0)         ;50 entries 13 bytes each
  133. RecOff      dw      0                   ;file offset of desired record
  134.             db      '  '
  135. Comments    db      30 dup (0)
  136. CommentMsg  db      ' Comment: ',0
  137. FirstRec?   db      0
  138. Temp        dw      0
  139. EndStr      dw      0                   ;sets max lenght of input string
  140. Cursor      dw      0                   ;current cursor location
  141. ErrInfo     dw      3 dup (0)           ;extended error info of parent
  142.         
  143. ;============================================================================
  144. ; Int08 processes BIOS timer interrupt (Int 08h)
  145. ;============================================================================
  146. Int08       proc          
  147.                           
  148.             pushf
  149.             call    cs:Vec08            ;call original interupt
  150.  
  151.             sti
  152.             cmp     cs:Timer?,1
  153.             je      A1                  
  154.             cmp     cs:Pausing?,1
  155.             je      A1
  156. A0:         cmp     cs:Request?,1
  157.             jne     A05
  158.             jmp     Readyet?            ;okay to pop-up yet?
  159.  
  160. A05:        iret
  161.  
  162. A1:         dec     cs:Min_Ticks        ;count down ticks per minute
  163.             jnz     A11                 
  164.             inc     cs:Minutes          ;another minute has passed
  165.             mov     cs:Min_Ticks,0444h  ;reset counter
  166.  
  167. A11:        cmp     cs:MsgUp?,1         
  168.             jne     A12
  169.  
  170. ;reminder message is up
  171.             dec     cs:MsgTicks
  172.             jz      DisTimer             ;if up for 5 secs then remove
  173.             jmp     A0
  174.  
  175. ;reminder message not up    
  176. A12:        dec     cs:Rem_Ticks
  177.             jnz     A0                  
  178.  
  179. ;time to display reminder
  180.             push    cs:WaitTicks
  181.             pop     cs:Rem_Ticks   
  182.     
  183. ;displays or removes reminder
  184. DisTimer:   cmp     cs:Up?,1            ;is TRACKR popped up?
  185.             je      A0
  186.             cmp     cs:Display?,1       ;don't want to re-enter
  187.             jne     A0
  188.  
  189.             mov     cs:Display?,0       ;make sure we don't re-enter
  190.             push    ax
  191.             push    bx
  192.             push    cx
  193.             push    dx
  194.             push    si
  195.             push    di
  196.             push    ds
  197.             push    es
  198.  
  199.             push    cs
  200.             pop     ds                                 
  201.     
  202. A15:        mov     ax,40h
  203.             mov     es,ax
  204.             mov     al,es:49h           ;bios mode
  205.             cmp     al,7
  206.             je      A2
  207.             cmp     al,3
  208.             ja      RetInt              ;if not text mode return
  209.  
  210. A2:         call    AdjVidSeg
  211.             mov     es,VidSeg
  212.             mov     di,32h              ;offset into screen of stuff to grab
  213.             mov     cx,36h              ;number of words to grab
  214.             mov     si,offset Buffer
  215.             cld     
  216.             cmp     MsgUp?,1
  217.             jne     A3
  218.  
  219. ;restore background
  220.             mov     cx,5
  221.             repe    cmpsw               ;are previous 5 characters same
  222.             jne     Bally               ;nope? then don't restore original
  223.             mov     cx,31h
  224.             rep     movsw
  225.             jmp     Bally
  226.  
  227. ;save background
  228. A3:         xchg    si,di
  229.             push    es
  230.             pop     ds
  231.             push    cs
  232.             pop     es
  233.  
  234.             rep     movsw               ;save screen
  235.             push    cs
  236.             pop     ds
  237.  
  238. ;display reminder message
  239.             mov     di,3Dh
  240.             mov     si,offset Attributes
  241.             mov     cx,31h
  242.             call    DisStr          
  243.             mov     MsgTicks,5Ah
  244.             call    DisStatus           ;display reminder
  245.  
  246. Bally:      xor     MsgUp?,1
  247.  
  248. RetInt:     pop     es
  249.             pop     ds
  250.             pop     di
  251.             pop     si
  252.             pop     dx
  253.             pop     cx
  254.             pop     bx
  255.             pop     ax
  256.  
  257.             mov     cs:Display?,1
  258.             cmp     cs:Request?,1
  259.             jne     RY0        
  260.     
  261. ;checks to see if it's safe to pop-up
  262. Readyet?:   dec     cs:TryCnt           ;how many times have we tried?
  263.             jnz     RY1
  264.  
  265.             mov     cs:Request?,0       ;if tried for 5 secs then give up
  266. RY0:        iret
  267.  
  268. RY1:        push    ax
  269.     
  270. ;check DOS busy byte
  271.             push    es
  272.             push    si
  273.             mov     es,cs:DBseg
  274.             mov     si,cs:DBoff
  275.             cmp     byte ptr es:[si],0  ;DOS busy byte
  276.             pop     si
  277.             pop     es
  278.  
  279.             jne      T1                 ;can't pop-up if DOS is busy
  280.  
  281. ;DOS not busy
  282.             cmp     cs:Diskop?,0
  283.             je      T2
  284.  
  285. ;unable to accomodate request (DOS busy or disk ops in progress)
  286. T1:         pop     ax
  287.             iret
  288.  
  289. ;DOS not busy and no disk ops, let's do it
  290. T2:         pop     ax
  291.             jmp     MainStuff  
  292.  
  293. Int08       endp
  294.  
  295. ;============================================================================
  296. ; Int09 processes BIOS keyboard interrupt (Int 09h)
  297. ;============================================================================
  298.  
  299. Int09       proc
  300.  
  301.             sti
  302.             push    ax
  303.             push    es
  304.  
  305.             mov     ax,40h
  306.             mov     es,ax
  307.             mov     al,es:17h
  308.             and     al,0Fh
  309.             cmp     al,cs:ShiftState    ;check shift state
  310.             je      R1
  311.  
  312. R0:         pop     es                  ;chain to original interupt
  313.             pop     ax
  314.             cli
  315.             jmp     cs:Vec09
  316.  
  317. R1:         in      al,60h
  318.             cmp     al,cs:ScanCode      ;check scan code
  319.             jne     R0
  320.  
  321. ;hot key has been pressed, ask to pop-up
  322.             cmp     cs:Up?,1
  323.             je      R0
  324.             mov     cs:Request?,1
  325.             mov     cs:TryCnt,5Bh
  326.  
  327.             cli
  328.             mov     al,20h              ;reset interupts
  329.             out     20h,al
  330.             sti
  331.  
  332.             pop     es
  333.             pop     ax
  334.             iret
  335.  
  336. Int09       endp
  337.  
  338. ;============================================================================
  339. ; Int28 processes undocumented DOS interrupt "keyboard busy loop" (Int 28h)
  340. ;============================================================================
  341.  
  342. Int28       proc    
  343.             pushf
  344.             call    cs:Vec28
  345.             sti
  346.             cmp     cs:Request?,1
  347.             je      I28b
  348. I28a:       iret
  349. I28b:       cmp     cs:Diskop?,1
  350.             je      I28a
  351.  
  352. ;no disk ops, and in Int28, let's do it
  353.             jmp     MainStuff
  354. Int28       endp
  355.  
  356. ;============================================================================
  357. ; Int13 processes BIOS disk services interrupt (Int 13h)
  358. ;============================================================================
  359.  
  360. Int13       proc    
  361. ;won't let you pop-up during BIOS disk operations
  362.             sti
  363.             mov     cs:Diskop?,1
  364.             pushf                           
  365.             call    cs:Vec13            ;call original interupt
  366.             mov     cs:Diskop?,0
  367.             retf    2
  368. Int13       endp
  369.  
  370. ;============================================================================
  371. ; Start logs in a new task
  372. ;============================================================================
  373.  
  374. Start       proc
  375.             call    GetTime         ;get log-in time
  376.             mov     LogIn,ax
  377.             mov     Timer?,1        ;we're on, ignore further requests
  378.             mov     Pausing?,0      ;we're not pausing
  379.             mov     ax,WaitTicks    ;set up Rem_Ticks
  380.             mov     Rem_Ticks,ax
  381.             ret
  382. Start       endp
  383.  
  384. ;============================================================================
  385. ; GetTime returns with seconds since midnight in AX
  386. ;============================================================================
  387.  
  388. GetTime     proc   
  389.             push    es
  390.             mov     ax,40h
  391.             mov     es,ax
  392.             mov     ax,es:6Ch
  393.             mov     dx,es:6Eh
  394.             mov     bx,0444h
  395.             div     bx                  ;ax=minutes since midnight
  396.             pop     es
  397.             ret
  398. GetTime     endp
  399.  
  400. ;============================================================================
  401. ; Stop logs-off
  402. ;============================================================================
  403.  
  404. Stop        proc 
  405.             call    GetTime
  406.             mov     LogOut,ax           ;get log-out time
  407.             mov     Timer?,0            ;we're off
  408.             mov     Minutes,0           ;reset elapsed time
  409.             ret
  410. Stop        endp
  411.  
  412. ;============================================================================
  413. ; Encode puts time in HHH:MM format
  414. ; Entry:  AX = minutes 
  415. ;         DI = offset HHH:MM string goes
  416. ;============================================================================
  417.  
  418. Encode      proc
  419.             mov     cx,3030h
  420.             mov     bx,3Ch
  421.             xor     dx,dx
  422.             div     bx
  423.             xchg    dx,ax               ;put minutes in ax
  424.             aam
  425.             xchg    ah,al
  426.             or      ax,cx
  427.             mov     [di+4],ax           ;minutes
  428.  
  429.             mov     ax,dx               ;put hours in ax
  430.             mov     bl,64h
  431.             div     bl                  ;divide by 100
  432.             mov     bl,al
  433.             mov     al,ah
  434.             aam
  435.             xchg    ah,al
  436.             or      ax,cx
  437.             mov     [di+1],ax           ;hours mod 100
  438.             cmp     bl,0
  439.             je      E1
  440.             mov     al,bl
  441.             aam
  442.             or      ax,cx
  443.             mov     [di],al             ;hundreds of hours value
  444. E1:         mov     byte ptr [di+3],':' ;stick in colon
  445.             ret
  446. Encode      endp
  447.  
  448. ;============================================================================
  449. ; Decode takes time value in HH:MM and returns AX=minutes
  450. ; Entry:  SI = offset of HH:MM value
  451. ; Exit:   AX = minutes
  452. ;============================================================================
  453.  
  454. Decode      proc
  455.             cmp     byte ptr [si],' '
  456.             jne     DD1
  457.             mov     byte ptr [si],'0'
  458. DD1:        mov     ax,[si]
  459.             xor     ax,3030h
  460.             xchg    ah,al
  461.             aad
  462.             mov     bl,3Ch
  463.             mul     bl
  464.             mov     dx,ax
  465.             mov     ax,[si+3]
  466.             xor     ax,3030h
  467.             xchg    ah,al
  468.             aad
  469.             add     ax,dx
  470.             ret
  471. Decode      endp
  472.  
  473. ;============================================================================
  474. ; MainStuff prepares for popping up by saving registers, cursor location, 
  475. ; extended error information, getting and setting the PSP, getting the video 
  476. ; segment and offsets, saving the background, and displaying Trackr's main 
  477. ; screen.
  478. ;============================================================================ 
  479.  
  480. MainStuff   proc
  481.             mov     cs:Request?,0
  482.             mov     cs:Up?,1
  483.             push    ax
  484.             push    bx
  485.             push    cx
  486.             push    dx
  487.             push    si
  488.             push    di
  489.             push    ds
  490.             push    es
  491.  
  492.             mov     ax,cs
  493.             mov     ds,ax
  494.             mov     es,ax
  495.     
  496.             mov     ah,51h
  497.             int     21h                 ;get parent PSP
  498.             mov     ParentPSP,bx
  499.  
  500.             mov     ah,50h
  501.             mov     bx,OurPSP
  502.             int     21h                 ;set our PSP
  503.     
  504.             mov     ah,59h
  505.             int     21h                 ;get extended error information
  506.             mov     ErrInfo,ax
  507.             mov     ErrInfo[2],bx
  508.             mov     ErrInfo[4],cx
  509.         
  510.             call    AdjVidSeg           ;get video segment
  511.  
  512.             cmp     MsgUp?,1
  513.             jne     MS1
  514.  
  515. ;remove reminder if currently displayed
  516.             push    es
  517.             mov     es,VidSeg
  518.             mov     di,3Ch
  519.             mov     cx,31h
  520.             mov     si,offset Buffer
  521.             cld
  522.             rep     movsw
  523.             mov     MsgUp?,0
  524.             pop     es
  525.  
  526. MS1:        mov     ah,0Fh
  527.             int     10h
  528.             mov     VidPage,bh
  529.             mov     ah,3
  530.             int     10h
  531.             mov     OrgCursor,dx    ;save cursor position
  532.     
  533.             mov     ax,sp
  534.             mov     StackPtr,ax     ;save stack ptr
  535.  
  536.             call    SwapScreen      ;save background and display Trackr
  537.  
  538.             call    MakeDate
  539.             cmp     NumTasks,0
  540.             jne     Main
  541.  
  542. ;if no tasks then jump to Create Task
  543.             jmp     M51             
  544.  
  545. ;============================================================================
  546. ; Main procedure
  547. ;============================================================================
  548.  
  549. Main        proc
  550.             mov     Client?,0
  551.             mov     Update?,0
  552.  
  553. ;display Menus
  554.             mov     ah,2
  555.             mov     bh,VidPage
  556.             mov     dx,1900h
  557.             int     10h                 ;move cursor off screen
  558.  
  559.             mov     si,offset TaskMsg
  560.             mov     cx,7
  561.             mov     di,0E0h
  562.             call    DisStr              ;display TaskMsg
  563.  
  564.             mov     si,offset Menu
  565.             mov     MenuEnd,3
  566.             cmp     TaskOff,0
  567.             jne     Mt
  568.             mov     si,offset Menu2
  569.             dec     MenuEnd
  570.  
  571. Mt:         call    DisMenu             ;display appropriate Menu
  572.             cmp     Pausing?,1
  573.             jne     Mu
  574.             mov     di,01B4h
  575.             mov     si,offset Resume
  576.             mov     cx,6
  577.             call    DisStr              ;display Pausing message
  578.  
  579. Mu:         call    DisStatus           ;display task status
  580.             call    DisList             ;display list of tasks
  581.                                         ;fall thru to GetKey
  582. Main        endp
  583. MainStuff   endp
  584.  
  585. ;============================================================================
  586. ; GetKey gets menu keystrokes and directs efforts as appropriate
  587. ;============================================================================
  588.  
  589. GetKey      proc
  590. M0:         xor     ah,ah
  591.             int     16h
  592.             cmp     ah,1
  593.             jne     M2
  594.             jmp     Returnn             ;Escape? then exit
  595.  
  596. M2:         cmp     ah,49h              ;PgUp
  597.             je      M3
  598.             cmp     ah,51h              ;PgDn
  599.             jne     M4 
  600. M3:         call    Chk_PgUp
  601.             jmp     M0
  602.     
  603. M4:         cmp     Update?,1
  604.             jne     M41
  605.             jmp     M9                  ;if Updating then jmp M9
  606.  
  607. M41:        cmp     ah,26h              ;Log-Off
  608.             jne     M5
  609.             cmp     TaskOff,0
  610.             je      M8
  611.     
  612.             call    LogOff
  613.             mov     TaskOff,0
  614.             jmp     Returnn
  615.  
  616. M5:         cmp     ah,2Eh              ;Create new task?
  617.             jne     M6
  618.             cmp     Pausing?,1
  619.             je      M51
  620.             cmp     TaskOff,0
  621.             je      M51
  622.             call    LogOff              ;if logged on then log-off first
  623. M51:        call    NewTask
  624.             jmp     M36
  625.  
  626. M6:         cmp     ah,19h              ;Pause?
  627.             jne     M7
  628.             cmp     TaskOff,0
  629.             je      M8
  630.             call    LogOff
  631.             mov     Pausing?,1
  632.             jmp     Returnn
  633.  
  634. M7:         cmp     ah,13h              ;Resume?
  635.             jne     M8
  636.             cmp     Pausing?,1
  637.             jne     M0
  638.             call    Start               ;log back on
  639.             jmp     Returnn
  640.  
  641. M8:         cmp     ah,16h              ;Update?
  642.             jne     M9
  643.             mov     Update?,1
  644.             push    TaskOff             ;save TaskOff
  645.             call    Update
  646.             pop     TaskOff             ;restore TaskOff
  647.             mov     Update?,0
  648.             jmp     Returnn
  649.  
  650. M9:         cmp     ah,1Fh              ;Switch
  651.             je      M10
  652.             cmp     ah,26h              ;Log-on
  653.             je      M10
  654.             jmp     M0
  655.  
  656. M10:        mov     si,offset SelectTask 
  657.             mov     Client?,0
  658.             call    GetNumber           ;returns task # in al
  659.  
  660. ;number has been pressed
  661.             mov     bl,0Dh
  662.             mul     bl
  663.             add     ax,offset TaskList  ;offset of task name
  664.  
  665.             push    ax
  666.             cmp     Pausing?,1
  667.             je      M35a
  668.             cmp     TaskOff,0
  669.             je      M35a
  670.             call    LogOff              ;if logged on then log-off (switch)
  671.  
  672. ;log on to task whose # was pressed
  673. M35a:       pop     ax
  674.             mov     TaskOff,ax
  675.  
  676. M36:        call    GetComment          ;get comment
  677.  
  678.             call    Start               ;log-on
  679.             jmp     Returnn             ;exit
  680.  
  681. GetKey      endp
  682.  
  683. ;============================================================================
  684. ; GetNumber returns with client (if Client?=1) or task number in AL
  685. ; Entry: SI = offset of prompt message 
  686. ;        Client? = 1 if getting client number else 0
  687. ; Exit:  AL = client or task number
  688. ;============================================================================
  689.  
  690. GetNumber   proc    
  691.     
  692. GN0:        push    si
  693.             mov     ax,2                ;limit input to 2 characters
  694.             call    GetInput
  695.             pop     si
  696.  
  697.             mov     al,Buffer           ;convert to binary number
  698.             sub     al,'0'
  699.             cmp     al,9
  700.             ja      GN0
  701.             cmp     StrSize,1
  702.             je      GN1
  703.             mov     bl,0Ah
  704.             mul     bl
  705.             mov     bl,Buffer+1
  706.             sub     bl,'0'
  707.             cmp     bl,9
  708.             ja      GN0
  709.     
  710.             add     al,bl
  711.  
  712. GN1:        mov     cl,NumTasks
  713.             cmp     Client?,0
  714.             je      GN2
  715.             mov     cl,NumClients
  716. GN2:        cmp     al,cl
  717.             jae     GN0         ;check to see if number is out of limits
  718.             mov     Client?,0
  719.             ret
  720. GetNumber   endp
  721.  
  722. ;============================================================================
  723. ; Returnn exits Trackr and restores everything as it was before popping up
  724. ;============================================================================
  725.  
  726. Returnn     proc   
  727.             push    cs
  728.             pop     ds
  729.  
  730.             call    CloseFiles          ;close any open files
  731.  
  732.             mov     bx,ParentPSP
  733.             mov     ah,50h
  734.             int     21h                 ;restore parent PSP
  735.     
  736.             call    SwapScreen
  737.  
  738.             mov     ax,5D0Ah
  739.             mov     dx,offset ErrInfo
  740.             int     21h                 ;restore extended error info
  741.  
  742.             mov     ah,2
  743.             mov     dx,OrgCursor
  744.             mov     bh,VidPage
  745.             int     10h                 ;restore cursor
  746.  
  747.             mov     ax,StackPtr
  748.             mov     sp,ax               ;restore stackptr
  749.  
  750.             pop     es
  751.             pop     ds
  752.             pop     di
  753.             pop     si
  754.             pop     dx
  755.             pop     cx
  756.             pop     bx
  757.             pop     ax
  758.             mov     cs:Up?,0
  759.             iret
  760. Returnn     endp
  761.  
  762. ;============================================================================
  763. ; CloseFiles closes any open files
  764. ;============================================================================
  765.  
  766. CloseFiles  proc
  767.             mov     cx,3
  768.             mov     si,offset ClientFH
  769. Ret1:       mov     bx,[si]
  770.             cmp     bx,0FFFh
  771.             je      Ret2
  772.             mov     word ptr [si],0FFFh
  773.             mov     ah,3Eh
  774.             int     21h
  775. Ret2:       inc     si
  776.             inc     si
  777.             loop    Ret1
  778.             ret
  779. CloseFiles  endp
  780.  
  781. ;============================================================================
  782. ; DisStatus displays task name and elapsed time (or pausing message)
  783. ;============================================================================
  784.  
  785. DisStatus   proc
  786.             mov     al,' '
  787.             mov     di,offset Status+14
  788.             push    di
  789.             mov     cx,8
  790.             rep     stosb               ;clear task name
  791.             add     di,18
  792.             mov     cx,5
  793.             rep     stosb               ;clear elapsed time
  794.             pop     di
  795.  
  796.             mov     si,TaskOff
  797.             cmp     si,0
  798.             je      ST3
  799.  
  800. ;insert task name
  801. ST0:        mov     al,[si]
  802.             cmp     al,'.'
  803.             je      ST1
  804.             mov     [di],al
  805.             inc     si
  806.             inc     di
  807.             jmp     ST0
  808.  
  809. ST1:        mov     di,offset Status+40
  810.             cmp     Pausing?,1
  811.             jne     ST2
  812.             inc     di
  813.             mov     si,offset Pause
  814.             mov     cx,5
  815.             rep     movsb       ;insert "Pausing" if appropriate
  816.             jmp     ST3
  817.  
  818. ST2:        mov     ax,Minutes
  819.             call    Encode              ;convert elapsed time into ASCII
  820.  
  821. ST3:        mov     si,offset Status
  822.             mov     cx,31h
  823.             mov     di,3Ch
  824.             jmp     DisStr              ;display status message
  825. DisStatus   endp
  826.  
  827. ;============================================================================
  828. ; DisList displays the list of tasks
  829. ;============================================================================
  830.  
  831. DisList     proc 
  832.  
  833. DLz:        call    ClrList
  834.  
  835.             mov     di,180h
  836.             mov     al,TopPage
  837.             mov     bl,0Dh
  838.             mul     bl
  839.             add     ax,offset TaskList
  840.             mov     si,ax               ;first task name on page
  841.  
  842.             mov     dl,TopPage
  843.             mov     cl,NumTasks
  844.             sub     cl,dl
  845.             cmp     cl,0Ah
  846.             jbe     DL1
  847.             mov     cx,0Ah
  848.  
  849. DL1:        push    si
  850.             push    di
  851.             mov     al,dl
  852.             aam
  853.             xor     ax,'00'
  854.             mov     es:[di],ah
  855.             mov     es:[di+2],al
  856.             inc     dl
  857.             add     di,6
  858.  
  859. DL2:        mov     al,[si]
  860.             cmp     al,'.'
  861.             je      DL3
  862.             mov     es:[di],al
  863.             inc     si
  864.             inc     di
  865.             inc     di
  866.             jmp     DL2
  867.  
  868. DL3:        pop     di
  869.             pop     si
  870.             add     si,0Dh
  871.             add     di,0A0h 
  872.             cmp     di,04A0h
  873.             jb      DL4
  874.             mov     di,019Ah
  875. DL4:        loop    DL1
  876.             push    ds
  877.             pop     es
  878.             ret
  879. DisList     endp
  880.  
  881. ;============================================================================
  882. ; ClrList clears the screen where the task list goes
  883. ;============================================================================
  884.  
  885. ClrList     proc  
  886.             mov     ah,NAt
  887.             mov     al,' '
  888.             mov     es,VidSeg
  889.             mov     di,180h
  890.             mov     cx,5
  891. DL0:        push    cx
  892.             push    di
  893.             mov     cx,18h
  894.             rep     stosw
  895.             pop     di
  896.             add     di,0A0h
  897.             pop     cx
  898.             loop    DL0
  899.             ret
  900. ClrList     endp
  901.  
  902. ;============================================================================
  903. ; MakeDate gets date and converts to DD/MM/YR format in "Today" variable
  904. ;============================================================================
  905.  
  906. MakeDate    proc   
  907.             mov     ah,2Ah
  908.             int     21h                 ;dh=month,dl=day,cx=yr
  909.             mov     al,dh
  910.             aam
  911.             xchg    al,ah
  912.             add     ax,3030h
  913.             mov     word ptr Today,ax
  914.             mov     al,dl
  915.             aam
  916.             xchg    al,ah
  917.             add     ax,3030h
  918.             mov     word ptr Today[3],ax
  919.             sub     cx,076Ch
  920. D1:         cmp     cx,64h
  921.             jae     D1
  922.             mov     al,cl
  923.             aam
  924.             xchg    al,ah
  925.             add     ax,3030h
  926.             mov     word ptr Today[6],ax
  927.             ret
  928. MakeDate    endp
  929.  
  930. ;============================================================================
  931. ; LogOff logs off the current task and updates the task file
  932. ;============================================================================
  933.  
  934. LogOff      proc
  935.             call    Stop                ;get log-off time
  936.             cmp     Pausing?,1
  937.             jne     LO1
  938.             mov     Pausing?,0
  939.             ret
  940. LO1:        mov     LogOff?,1
  941.             jmp     FixLog              ;update task file
  942. LogOff      endp
  943.  
  944. ;============================================================================
  945. ; SwapScreen moves data in the "Screen" and "Attributes" buffers back onto 
  946. ;            the screen and vice versa. 
  947. ;============================================================================ 
  948.  
  949. SwapScreen  proc
  950. ;swaps screen to "Screen" buffer
  951.             mov     es,VidSeg
  952.             mov     di,3Ch
  953.             mov     si,offset Screen
  954.             mov     cx,8
  955.  
  956. SW1:        push    cx
  957.             push    di
  958.  
  959.             mov     cx,31h
  960. SW2:        mov     ax,es:[di]
  961.             mov     bl,[si]
  962.             mov     bh,[si+188h]
  963.             mov     es:[di],bx
  964.             mov     [si],al
  965.             mov     [si+188h],ah
  966.             inc     si
  967.             inc     di
  968.             inc     di
  969.             loop    SW2
  970.  
  971.             pop     di
  972.             pop     cx
  973.             add     di,0A0h
  974.             loop    SW1
  975.  
  976.             push    ds
  977.             pop     es
  978.             ret
  979. SwapScreen  endp
  980.  
  981. ;============================================================================
  982. ; AdjVidSeg adjusts VidSeg for offset into the screen (pages)
  983. ;============================================================================
  984.  
  985. AdjVidSeg   proc
  986.             push    es
  987.             mov     ax,40h
  988.             mov     es,ax
  989.             mov     ax,es:4Eh           ;screen offset
  990.             mov     cl,4
  991.             shr     ax,cl               ;divided by 16
  992.             add     ax,OrgVidSeg
  993.             mov     VidSeg,ax           ;add to original video segment
  994.             pop     es
  995.             ret
  996. AdjVidSeg   endp
  997.  
  998. ;============================================================================
  999. ; Update gets task number and then updates the task file to incorporate 
  1000. ;        additions or changes 
  1001. ;============================================================================ 
  1002.  
  1003. Update      proc
  1004.             mov     HoldSP,sp
  1005.             mov     si,offset SelectTask
  1006.             mov     Client?,0
  1007.             call    GetNumber           ;returns with task number in al
  1008.             mov     bl,0Dh
  1009.             mul     bl
  1010.             add     ax,offset TaskList
  1011.             mov     TaskOff,ax
  1012.             call    FixLog              ;fix the task file
  1013.             mov     sp,HoldSP
  1014.             ret
  1015. Update      endp
  1016.  
  1017. ;============================================================================
  1018. ; LoadLog opens the task file with LogFH=file handle
  1019. ;         moves to first data location
  1020. ;         gets Units and Rate info
  1021. ;============================================================================
  1022.  
  1023. LoadLog     proc
  1024.             mov     di,NameOff
  1025.             mov     si,TaskOff
  1026.             mov     cx,0Dh
  1027.             rep     movsb
  1028.  
  1029.             mov     ax,3D02h
  1030.             mov     dx,offset Drive
  1031.             int     21h                 ;open file
  1032.             jnc     S1
  1033.  
  1034. S0:         push    cs                  ;unable to open file
  1035.             pop     ds
  1036.             jmp     TaskErr
  1037.  
  1038. S1:         mov     LogFH,ax            ;file handle
  1039.             mov     bx,ax               
  1040.             mov     LogFH,ax
  1041.             mov     al,2
  1042.             mov     RecOff,0
  1043. ;fall through to GetHeader
  1044. LoadLog     endp
  1045.  
  1046. ;============================================================================
  1047. ; GetHeader loads in Units and Rate information and returns with file at start 
  1048. ;           of next entry and AX=offset into file of next entry
  1049. ; Entry: AL = 0 if task, 1 if making Client array, 2 if making new task
  1050. ;        BX = file handle (LogFH or ClientFH)
  1051. ; Exit:  AX = file offset of next entry
  1052. ;============================================================================
  1053.  
  1054. GetHeader   proc
  1055.             mov     Flag,al
  1056.             mov     HoldFH,bx
  1057.             mov     EoF,0
  1058.  
  1059. H1:         mov     dx,RecOff           
  1060.             xor     cx,cx
  1061.             mov     ax,4200h     
  1062.             int     21h                 ;mov to file ptr to RecOff
  1063.  
  1064. ;read 10 more than scanning to account for unit message length overrun
  1065.             mov     ah,3Fh
  1066.             mov     cx,50h  
  1067.             mov     dx,offset Buffer
  1068.             int     21h                 ;read
  1069.  
  1070.             mov     cx,ax               ;bytes read
  1071.             cmp     Flag,1
  1072.             jne     H2
  1073.  
  1074. ;making client array
  1075.             push    di
  1076.             push    cx
  1077.             mov     si,dx        
  1078.  
  1079. ;go past tabs, spaces, linefeeds and carraige returns
  1080. H14:        mov     al,[si]     
  1081.             cmp     al,7            
  1082.             je      H15
  1083.             cmp     al,' '
  1084.             je      H15
  1085.             cmp     al,0Ah
  1086.             je      H15
  1087.             cmp     al,0Dh
  1088.             jne     H16
  1089. H15:        inc     si
  1090.             jmp     H14
  1091.             
  1092. H16:        mov     di,offset Client
  1093.             mov     cx,15h
  1094.             rep     movsb               ;move in client name
  1095.             pop     cx
  1096.             pop     di
  1097.             mov     Flag,0
  1098.  
  1099. H2:         cmp     cx,50h              ;bytes read
  1100.             je      H3
  1101.             mov     EoF,1       ;set EoF if bytes read less than requested
  1102.  
  1103. H3:         mov     di,dx
  1104.             mov     cx,46h
  1105. H31:        mov     al,'\'
  1106.             repne   scasb               ;look for start of rate info
  1107.  
  1108.             cmp     cx,0
  1109.             je      H34
  1110.  
  1111. ;check to see if '\' is first character in line
  1112.             cmp     di,offset Buffer+1
  1113.             je      H4
  1114.             push    di
  1115.             dec     di
  1116. H32:        dec     di
  1117.             mov     al,[di]
  1118.             cmp     al,' '
  1119.             je      H32
  1120.             cmp     al,0Ah
  1121.             je      H33
  1122.             cmp     al,0Dh
  1123.             je      H33
  1124.  
  1125.             pop     di                  ;'\' isn't first character in line 
  1126.             jmp     H31                 ;so keep looking
  1127.  
  1128. H33:        pop     di          
  1129.             jmp     H4
  1130.  
  1131. ;haven't found '\' yet
  1132. H34:        cmp     EoF,1
  1133.             je      H4                  ;if end of file then goto H4
  1134.  
  1135.             add     RecOff,46h          ;else read in more and try again
  1136.             cmp     Flag,2
  1137.             je      H34a
  1138.             jmp     H1
  1139.  
  1140. H34a:       mov     bx,TempFH           ;if making new task then write info to 
  1141.                                         ;TEMP file first
  1142.             mov     ah,40h
  1143.             mov     cx,46h
  1144.             int     21h                 ;write info to TEMP file
  1145.             jnc     H35
  1146.             jmp     TaskErr
  1147.  
  1148. H35:        mov     bx,HoldFH           ;restore original file handle
  1149.             jmp     H1                  ;go read in more and continue search
  1150.  
  1151. H4:         call    GetVal
  1152.             mov     Rate,ax             ;get Rate Value
  1153.             call    GetVal
  1154.             mov     Units,ax            ;get Units value (billing increment)
  1155.  
  1156. S3:         mov     al,[di]             ;go past end of line
  1157.             cmp     al,0Dh
  1158.             je      S4
  1159.             cmp     al,0Ah
  1160.             jne     S5
  1161. S4:         inc     di
  1162.             jmp     S3
  1163.  
  1164. S5:         sub     di,offset Buffer
  1165.             cmp     Flag,2
  1166.             jne     S6
  1167.  
  1168.             mov     cx,di               ;if creating new task then write info 
  1169.                                         ;to TEMP file
  1170.             mov     bx,TempFH
  1171.             mov     ah,40h
  1172.             int     21h    
  1173.             jnc     S6
  1174.             jmp     TaskErr
  1175.  
  1176. S6:         mov     dx,di               ;change RecOff to next record's offset
  1177.             add     dx,RecOff
  1178.             mov     RecOff,dx
  1179.             xor     cx,cx
  1180.             mov     ax,4200h
  1181.             mov     bx,HoldFH
  1182.             int     21h                 ;move file pos to next record
  1183.             ret
  1184. GetHeader   endp
  1185.  
  1186. ;============================================================================
  1187. ; GetVal takes ASCII # pointed to by DI and returns a binary number in AX 
  1188. ;        and DI pointing to the next ASCII # or carraige return.  Used for 
  1189. ;        decoding task files or CLIENT.DAT.
  1190. ; Entry:  DI = offset of ASCII number
  1191. ; Exit:   AX = binary number 
  1192. ;         DI = offset of next ASCII # or CR
  1193. ;============================================================================ 
  1194.  
  1195. GetVal      proc
  1196.             xor     ax,ax
  1197.             mov     cx,ax
  1198.             mov     bl,0Ah
  1199.  
  1200. G1:         mov     cl,[di]
  1201.             cmp     cl,0Dh
  1202.             je      G2
  1203.             cmp     cl,'\'
  1204.             je      G2
  1205.             sub     cl,'0'
  1206.             cmp     cl,9
  1207.             ja      G15
  1208.             mul     bl
  1209.             add     ax,cx
  1210. G15:        inc     di
  1211.             jmp     G1
  1212. G2:         inc     di
  1213.             ret
  1214. GetVal      endp
  1215.  
  1216. ;============================================================================
  1217. ; NewTask 
  1218. ;============================================================================
  1219.                      
  1220. NewTask     proc
  1221.             mov     si,offset SelectTask-1
  1222.             call    DisMenu             ;display "Select task" menu
  1223.             call    GetClients          ;get clients from CLIENT.DAT
  1224.             mov     CTopPage,0
  1225. NT0:        call    DisClients          ;display client list
  1226.  
  1227.             mov     si,offset InpClient
  1228.             mov     Client?,1
  1229.             call    GetNumber           ;get client #
  1230.     
  1231.             call    MovPtr              ;move file ptr to client
  1232.  
  1233. ;create new task file
  1234. NT8a:       mov     si,offset NameMsg
  1235.             mov     ax,8
  1236.             call    GetInput            ;get task file name
  1237.             mov     si,offset Buffer
  1238.             mov     di,NameOff
  1239.     
  1240. NT9:        mov     al,[si]
  1241.             cmp     al,0Dh
  1242.             je      NT11
  1243.             cmp     al,' '              ;no spaces allowed
  1244.             je      NT11c
  1245.             cmp     al,'.'              ;ignore extension
  1246.             je      NT11
  1247.  
  1248.             cmp     al,'a'
  1249.             jb      NT10
  1250.             cmp     al,'z'
  1251.             ja      NT10
  1252.             sub     al,20h              ;change to upper case
  1253. NT10:       mov     [di],al
  1254.             inc     si
  1255.             inc     di
  1256.             jmp     NT9
  1257.  
  1258. NT11:       mov     si,offset Extension
  1259.             mov     cx,5
  1260.             rep     movsb               ;add .LOG extension
  1261.  
  1262.             mov     dx,offset Drive
  1263.             mov     ax,3D02h
  1264.             int     21h                 ;check for duplicate file
  1265.             jc      NT11b
  1266.  
  1267.             mov     bx,ax
  1268.             mov     ah,3Eh
  1269.             int     21h                 ;file already exists so close file
  1270.  
  1271.             mov     si,offset DupNameMsg
  1272. NT11a:      call    DisErrMsg
  1273.             jmp     NT8a
  1274.     
  1275. ;create new file
  1276. NT11b:      mov     ah,3Ch
  1277.             xor     cx,cx
  1278.             mov     dx,offset Drive
  1279.             int     21h                 ;create new task file
  1280.             jnc     NT12
  1281.  
  1282. NT11c:      mov     si,offset InvNameMsg
  1283.             jmp     NT11a               ;invalid file name, try again
  1284.     
  1285. NT12:       mov     TempFH,ax           ;file handle of task file
  1286.  
  1287.             mov     si,NameOff
  1288.             call    PutTask             ;add task name to task list
  1289.  
  1290.             mov     bx,ClientFH
  1291.             mov     al,2    ;flag
  1292.             call    GetHeader           ;get info from CLIENT.DAT and create 
  1293.                                         ;task file
  1294.             mov     bx,ClientFH
  1295.             mov     ClientFH,0FFFh
  1296.             mov     ah,3Eh              ;close CLIENT.DAT
  1297.             int     21h                                          
  1298.  
  1299.             mov     bx,TempFH
  1300.             mov     TempFH,0FFFh
  1301.             mov     ah,3Eh              ;close TEMP file
  1302.             int     21h
  1303.             ret
  1304. NewTask     endp
  1305.  
  1306. ;============================================================================
  1307. ; DisClients displays the list of clients starting with CTopPage as the first 
  1308. ;            client
  1309. ;============================================================================
  1310.  
  1311. DisClients  proc
  1312.             call    ClrList             ;clear the screen
  1313.             push    ds
  1314.             pop     es
  1315.             mov     al,CTopPage
  1316.             mov     Flag,al
  1317.             mov     di,186h
  1318.             mov     cx,5
  1319.  
  1320. NT1:        mov     al,5
  1321.             sub     al,cl
  1322.             add     al,CTopPage
  1323.             cmp     al,NumClients
  1324.             jb      NT13
  1325.             ret
  1326.  
  1327. NT13:       push    cx
  1328.             push    di         
  1329.  
  1330.             mov     bx,ClientFH
  1331.             call    MovPtr
  1332.             mov     dx,offset Client
  1333.             mov     cx,15h
  1334.             mov     ah,3Fh
  1335.             int     21h         ;read in first 21 bytes of client data
  1336.  
  1337.             pop     di
  1338.             push    di
  1339.  
  1340.             mov     es,VidSeg
  1341.             mov     al,Flag
  1342.             aam
  1343.             or      ax,'00'
  1344.             mov     es:[di-6],ah
  1345.             mov     es:[di-4],al        ;display client number
  1346.             inc     Flag
  1347.             mov     cx,15h
  1348.             mov     si,offset Client
  1349.  
  1350. NT15:       mov     al,[si]
  1351.             cmp     al,0Ah
  1352.             je      NT2
  1353.             cmp     al,0Dh
  1354.             je      NT2
  1355.             cmp     al,7
  1356.             je      NT2
  1357.             cmp     al,' '
  1358.             jne     NT3
  1359. NT2:        inc     si
  1360.             dec     cx
  1361.             jmp     NT15
  1362.  
  1363. NT3:        call    DisStr              ;display 15 bytes of client info
  1364.             pop     di
  1365.             add     di,0A0h
  1366.  
  1367.             pop     cx
  1368.             loop    NT1
  1369.             ret
  1370. DisClients  endp
  1371.    
  1372. ;============================================================================
  1373. ; MovPtr takes client number in AL and returns with file ptr at client's 
  1374. ;        record
  1375. ; Entry:   AL = # of client
  1376. ;============================================================================
  1377.     
  1378. MovPtr      proc
  1379.             xor     ah,ah
  1380.             shl     ax,1
  1381.             add     ax,offset ClientArray
  1382.             mov     di,ax
  1383.             mov     dx,[di]
  1384.             mov     RecOff,dx
  1385.             xor     cx,cx
  1386.             mov     ax,4200h
  1387.             mov     bx,ClientFH
  1388.             int     21h     ;move file ptr to first entry
  1389.             ret
  1390. MovPtr      endp
  1391.  
  1392. ;============================================================================
  1393. ; FixLog updates task log pointed to by TaskOff 
  1394. ;
  1395. ; Entry:  TaskOff pointing to desired task
  1396. ;============================================================================
  1397.  
  1398. FixLog      proc
  1399.             mov     DayTot,0
  1400.             mov     di,NameOff
  1401.             mov     si,offset TempFN
  1402.             mov     cx,5
  1403.             rep     movsb               ;make full pathname for TEMP
  1404.             mov     dx,offset Drive
  1405.             mov     ah,3Ch
  1406.             xor     cx,cx
  1407.             int     21h                 ;create TEMP file
  1408.             jnc     FL1
  1409.             jmp     TaskErr
  1410.  
  1411. FL1:        mov     bx,ax               ;file handle
  1412.             mov     TempFH,ax
  1413.  
  1414.             mov     Flag,2
  1415.             call    LoadLog             
  1416.  
  1417.             cmp     LogOff?,1
  1418.             jne     FL4
  1419.  
  1420. ;if logging off add new entry to file
  1421.             mov     di,offset Buffer+2
  1422.             mov     al,' '
  1423.             mov     cx,50h
  1424.  
  1425.             push    di
  1426.             rep     stosb
  1427.             pop     di
  1428.  
  1429.             mov     si,offset Today
  1430.             mov     cx,8
  1431.             rep     movsb               ;mov in today's date
  1432.  
  1433.             mov     ax,LogIn
  1434.             mov     di,offset Buffer+11
  1435.             call    Encode              ;add log in time
  1436.  
  1437.             mov     ax,LogOut
  1438.             mov     di,offset Buffer+18
  1439.             call    Encode              ;add log out time
  1440.  
  1441.             mov     di,offset Buffer+31
  1442.             mov     si,offset Comments-2
  1443. FL2:        mov     al,[si]             ;add comments
  1444.             cmp     al,0Dh
  1445.             je      FL3  
  1446.             mov     [di],al
  1447.             inc     di
  1448.             inc     si
  1449.             jmp     FL2
  1450.  
  1451. FL3:        mov     ax,0A0Dh
  1452.             mov     [di],ax
  1453.             mov     word ptr Buffer,ax  ;add carraige return, line feed
  1454.             sub     di,offset Buffer-4
  1455.  
  1456.             xor     cx,cx
  1457.             mov     dx,cx
  1458.             mov     ax,4202h
  1459.             mov     bx,LogFH
  1460.             int     21h                 ;move to end of task file
  1461.  
  1462.             mov     dx,offset Buffer
  1463.             mov     cx,di
  1464.             mov     ah,40h
  1465.             int     21h                 ;write entry
  1466.             jnc     FL35
  1467.             jmp     TaskErr
  1468.  
  1469. FL35:       mov     ax,4200h
  1470.             mov     dx,RecOff
  1471.             xor     cx,cx
  1472.             int     21h                 ;return to first record
  1473.             mov     LogOff?,0
  1474.             mov     EoF,0
  1475.  
  1476. FL4:        mov     FirstRec?,1
  1477.                      
  1478. FL5:        mov     bx,LogFH
  1479.             mov     cx,50h
  1480.             mov     ah,3Fh
  1481.             mov     dx,offset Buffer
  1482.             int     21h                 ;read in 80 bytes from task file
  1483.  
  1484.             cmp     ax,0                ;ax=bytes read
  1485.             jne     FL6
  1486.             jmp     FL22
  1487.  
  1488. FL6:        mov     BytesRead,ax
  1489.             mov     cx,ax
  1490.             add     ax,offset Buffer
  1491.             mov     EndRec,ax
  1492.  
  1493. ;search for 13 then go until not 10 or 13, this is next record
  1494.             mov     di,offset buffer
  1495.             mov     al,0Dh
  1496.             repne   scasb
  1497.             cmp     cx,0
  1498.             jne     FL7
  1499.             mov     EoF,1
  1500.  
  1501. FL7:        mov     al,[di]
  1502.             cmp     al,0Dh
  1503.             je      FL8
  1504.             cmp     al,0Ah
  1505.             jne     FL9
  1506. FL8:        inc     di
  1507.             cmp     di,EndRec
  1508.             jb      FL7
  1509.  
  1510. FL9:        sub     di,offset Buffer
  1511.             mov     dx,di
  1512.             add     dx,RecOff
  1513.             mov     RecOff,dx           ;RecOff points to next record
  1514.             xor     cx,cx
  1515.             mov     ax,4200h
  1516.             int     21h                 ;mov source file to next record
  1517.  
  1518.             cmp     di,20h
  1519.             jae     FL10
  1520.  
  1521.             dec     di
  1522.             dec     di
  1523.             mov     cx,1Eh
  1524.             sub     cx,di
  1525.             mov     al,' '
  1526.             add     di,offset Buffer
  1527.             rep     stosb
  1528.             mov     word ptr [di],0A0Dh
  1529.  
  1530. FL10:       cmp     Buffer+0Ch,':'
  1531.             jne     FL11
  1532.             cmp     Buffer+13h,':'
  1533.             je      FL12
  1534. FL11:       jmp     FL21
  1535.  
  1536. FL12:       cmp     FirstRec?,1
  1537.             jne     FL13
  1538.             mov     FirstRec?,0
  1539.             jmp     FL16
  1540.  
  1541. FL13:       cmp     Buffer,' '          ;no date
  1542.             jne     FL14
  1543.             jmp     FL18
  1544.  
  1545. FL14:       mov     di,offset Buffer
  1546.             mov     si,offset Date
  1547.             mov     cx,8
  1548.             repe    cmpsb               ;compare entry date with last entry
  1549.             jz      FL17
  1550.  
  1551. ;new date
  1552.             call    DayTally
  1553.  
  1554. FL16:       mov     si,offset Buffer
  1555.             mov     di,offset Date
  1556.             mov     cx,8
  1557.             rep     movsb
  1558.             jmp     FL18
  1559.  
  1560. ;dates are same
  1561. FL17:       mov     al,' '
  1562.             mov     cx,8
  1563.             mov     di,offset Buffer
  1564.             rep     stosb
  1565.  
  1566. FL18:       mov     si,offset Buffer+0Ah
  1567.             call    Decode
  1568.             push    ax                  ;log in time
  1569.             mov     si,offset Buffer+11h
  1570.             call    Decode              ;log off time
  1571.             pop     bx
  1572.             sub     ax,bx               ;elapsed minutes
  1573.             cmp     ax,0
  1574.             jne     FL19
  1575.             inc     ax
  1576. FL19:       jg      FL191
  1577.             add     ax,05A0h            ;minutes in 24 hours
  1578. FL191:      mov     bx,Units
  1579.             cmp     bx,1
  1580.             je      FL20
  1581.             xor     dx,dx
  1582.             div     bx                  
  1583.             inc     ax
  1584.             mul     bx                  ;elapsed time in billing increments
  1585. FL20:       add     DayTot,ax           ;add to day total
  1586.             add     Total,ax            ;add to grand total
  1587.             mov     di,offset Buffer+17h
  1588.             call    Encode              ;encode and add to log entry string
  1589.             mov     dx,offset Buffer
  1590.             call    WrtEntry            ;write log entry string
  1591.  
  1592. FL21:       cmp     EoF,1
  1593.             je      FL22
  1594.             jmp     FL5
  1595.  
  1596. ;construct and display summary
  1597. FL22:       call    DayTally
  1598.             mov     ax,Total
  1599.             mov     di,offset TotalMsg+23
  1600.             call    Encode
  1601.             cmp     Rate,0
  1602.             jne     FL23
  1603.             mov     di,offset TotalMsg+31
  1604.             mov     al,' '
  1605.             mov     cx,10
  1606.             rep     stosb
  1607.             jmp     FL24
  1608.  
  1609. FL23:       mov     ax,Total
  1610.             mov     di,offset TotalMsg+40
  1611.             call    EncBucks
  1612.  
  1613. FL24:       mov     dx,offset TotalMsg
  1614.             call    WrtEntry
  1615.             mov     Total,0
  1616.  
  1617.             mov     bx,TempFH
  1618.             mov     TempFH,0FFFh
  1619.             mov     ah,3Eh
  1620.             int     21h                 ;close TEMP file
  1621.  
  1622.             mov     bx,LogFH
  1623.             mov     LogFH,0FFFh
  1624.             mov     ah,3Eh
  1625.             int     21h                 ;close .LOG file
  1626.  
  1627.             mov     di,NameOff
  1628.             mov     si,TaskOff
  1629.             mov     cx,0Dh
  1630.             rep     movsb               ;make complete pathname for task file
  1631.  
  1632.             mov     si,offset Drive     ;contains task's complete pathname
  1633.             mov     di,offset Buffer
  1634.             mov     cx,50h
  1635.             rep     movsb               ;move task name to buffer
  1636.  
  1637.             mov     di,NameOff
  1638.             mov     si,offset TempFN
  1639.             mov     cx,5
  1640.             rep     movsb               ;make full pathname for TEMP
  1641.  
  1642.             mov     dx,offset Buffer
  1643.             mov     ah,41h
  1644.             int     21h                 ;delete original task file
  1645.             jnc     FL25
  1646.             jmp     TaskErr
  1647.  
  1648. FL25:       mov     di,offset Buffer
  1649.             mov     dx,offset Drive
  1650.             mov     ah,56h
  1651.             int     21h                 ;rename TEMP to task file
  1652.             ret
  1653. FixLog      endp
  1654.  
  1655. ;============================================================================
  1656. ; DayTally makes the daily total entry for the task log
  1657. ;============================================================================
  1658.  
  1659. DayTally    proc 
  1660.             mov     ax,DayTot
  1661.             cmp     ax,0
  1662.             jne     DT1
  1663.             ret
  1664. DT1:        mov     di,offset DayTotMsg+23
  1665.             call    Encode
  1666.             mov     di,offset DayTotMsg+31
  1667.             mov     al,' '
  1668.             mov     cx,10
  1669.             rep     stosb
  1670.             cmp     Rate,0
  1671.             je      DT4
  1672.  
  1673. DT2:        mov     ax,DayTot
  1674.             mov     di,offset DayTotMsg+40
  1675.             call    EncBucks
  1676.  
  1677. DT4:        mov     DayTot,0
  1678.             mov     dx,offset DayTotMsg
  1679.             mov     cx,2Dh
  1680.             jmp     WriteEntry
  1681. DayTally    endp
  1682.  
  1683. ;============================================================================
  1684. ; WrtEntry takes a log entry pointed to by DX and writes it to the file whose 
  1685. ;          file handle is in TempFH
  1686. ; Entry:  DX - pointing to log entry string
  1687. ;         TempFH - holding file handle
  1688. ;============================================================================
  1689.  
  1690. WrtEntry    proc
  1691.             mov     di,dx
  1692.             mov     al,0Ah
  1693.             mov     cx,50h
  1694.             repne   scasb
  1695.  
  1696.             sub     di,dx
  1697.             mov     cx,di
  1698. WriteEntry  proc
  1699.             mov     bx,TempFH
  1700.             mov     ah,40h
  1701.             int     21h
  1702.             jc      Err
  1703.             ret
  1704. Err:        jmp     TaskErr
  1705. WriteEntry  endp
  1706. WrtEntry    endp
  1707.  
  1708. ;============================================================================
  1709. ; EncBucks displays flush right at DI, minutes (in AX) times Rate
  1710. ; Entry:   AX = minutes
  1711. ;          DI = where rightmost character goes
  1712. ;============================================================================
  1713.  
  1714. EncBucks    proc
  1715.             mov     bx,di
  1716.             mov     cx,8
  1717.             sub     bx,cx
  1718. EB00:       mov     byte ptr [bx],' '
  1719.             inc     bx
  1720.             loop    EB00                ;clear display area
  1721.     
  1722.             mov     bx,Rate
  1723.             mul     bx                  ;hourly rate times minutes
  1724.             mov     bx,3Ch              
  1725.             div     bx                  ;divided by 60
  1726.             mov     cx,ax               ;dollars
  1727.             mov     ax,dx               ;remainder
  1728.             mov     bl,64h
  1729.             mul     bl                  ;multiplied by 100
  1730.             mov     bl,3Ch
  1731.             div     bl                  ;and divided by 60, al=cents
  1732.             aam
  1733.             xchg    ah,al
  1734.             add     ax,3030h
  1735.             dec     di
  1736.             mov     [di],ax             ;display cents
  1737.             dec     di
  1738.             mov     byte ptr [di],'.'
  1739.             mov     ax,cx               ;ax = dollars
  1740.  
  1741. EB2:        dec     di
  1742.             cmp     ax,0
  1743.             je      EB3
  1744.             xor     dx,dx
  1745.             mov     bx,0Ah
  1746.             div     bx
  1747.             add     dl,'0'
  1748.             mov     [di],dl             ;display dollars
  1749.             jmp     EB2
  1750.  
  1751. EB3:        dec     di
  1752.             mov     byte ptr [di],'$'
  1753.             ret
  1754. EncBucks    endp
  1755.  
  1756. NeedDATAmsg db      ' Unable to open CLIENT.DAT.',0        
  1757. WriteErrMsg db      ' Unable to create, open, or modify .LOG file. ',0
  1758.  
  1759. ;============================================================================
  1760. ; TaskErr handles errors with the task (.LOG) file
  1761. ;============================================================================
  1762.     
  1763. TaskErr     proc
  1764.             mov     TaskOff,0
  1765.             mov     si,offset WriteErrMsg
  1766. TaskErr     endp
  1767.  
  1768. ;============================================================================
  1769. ; DisErr displays the error message in SI, waits for keypress and return to 
  1770. ;        the "Main" procedure
  1771. ;============================================================================
  1772.  
  1773. DisErr      proc
  1774.             call    ClrLine
  1775.             mov     di,3Ch
  1776.             call    DisStrZ
  1777.             xor     ah,ah
  1778.             int     16h
  1779. Abort:      push    cs
  1780.             pop     ds
  1781.  
  1782.             call    CloseFiles
  1783.     
  1784. AB0:        mov     ax,StackPtr
  1785.             mov     sp,ax
  1786.             cmp     NumTasks,0
  1787.             jne     AB1
  1788.             jmp     Returnn
  1789. AB1:        jmp     Main
  1790. DisErr      endp
  1791.  
  1792. ;============================================================================
  1793. ; DisErrMsg displays the Error message pointed at by SI and waits for keypress
  1794. ;============================================================================
  1795.  
  1796. DisErrMsg   proc
  1797.             call    ClrLine
  1798.             mov     di,3Eh
  1799.             call    DisStrZ
  1800.             xor     ah,ah
  1801.             int     16h
  1802.             ret
  1803. DisErrMsg   endp
  1804.  
  1805. ;============================================================================
  1806. ; Chk_PgUp chks for PgUp and PgDn while at a menu and acts accordingly
  1807. ;============================================================================
  1808.  
  1809. Chk_PgUp    proc
  1810. GI1:        cmp     ah,49h              
  1811.             jne     GI3
  1812. ;PgUp
  1813.             cmp     Client?,1
  1814.             jne     GI2
  1815.             cmp     CTopPage,0
  1816.             jne     GI1b
  1817. GI1a:       ret
  1818. GI1b:       sub     CTopPage,5
  1819.             jmp     GI4 
  1820.  
  1821. GI2:        cmp     TopPage,0
  1822.             je      GI1a
  1823.             sub     TopPage,0Ah
  1824.             jmp     GI6
  1825.  
  1826. ;PgDn
  1827. GI3:        cmp     Client?,1
  1828.             jne     GI5
  1829.             mov     al,NumClients
  1830.             sub     al,CTopPage
  1831.             cmp     al,5
  1832.             jbe     GI1a
  1833.             add     CTopPage,5
  1834. GI4:        push    di
  1835.             call    DisClients
  1836.             pop     di
  1837.             ret
  1838.     
  1839. GI5:        mov     al,NumTasks
  1840.             sub     al,TopPage
  1841.             cmp     al,0Ah
  1842.             jbe     GI6
  1843.             add     TopPage,0Ah
  1844. GI6:        push    di
  1845.             call    DisList
  1846.             pop     di
  1847.             ret
  1848.  
  1849. Chk_PgUp    endp
  1850.  
  1851. ;============================================================================
  1852. ; GetInput displays prompt message and then gets keyboard input which it puts 
  1853. ;          in "Buffer"
  1854. ; Entry:  SI = pointer to prompt message
  1855. ;         AX = max length of input 
  1856. ; Exit:   Buffer - holds keyboard input string
  1857. ;============================================================================
  1858.  
  1859. GetInput    proc
  1860.  
  1861.             add     ax,offset Buffer
  1862.             mov     EndStr,ax
  1863.  
  1864.             call    ClrLine             ;clear the input area on screen
  1865.  
  1866.             mov     di,3Ch
  1867.             call    DisStrZ             ;display prompt
  1868.             mov     di,offset Buffer
  1869.  
  1870.             mov     Cursor,28h
  1871.             jmp     J1
  1872.  
  1873. ;get input
  1874. J0:         xor     ah,ah
  1875.             int     16h
  1876.             cmp     ah,1                ;escape?
  1877.             jne     J02
  1878.             jmp     Abort
  1879.  
  1880. J02:        cmp     ah,49h              ;PgUp?
  1881.             je      J03
  1882.             cmp     ah,51h              ;PgDn?
  1883.             jne     J05
  1884. J03:        call    Chk_PgUp   
  1885.             jmp     J0
  1886.  
  1887. J05:        cmp     ah,0Eh              ;BS
  1888.             je      J2
  1889.             cmp     al,0Dh              ;return
  1890.             je      J9
  1891.             cmp     al,80h              ;no values >127
  1892.             jae     J0
  1893.  
  1894.             cmp     di,EndStr
  1895.             jae     J0
  1896.             
  1897.             mov     ah,0Ah
  1898.             mov     cx,1
  1899.             int     10h                 ;display value
  1900.             mov     [di],al
  1901.             inc     di        
  1902.     
  1903. J1:         inc     Cursor
  1904.             mov     ah,2
  1905.             xor     bh,bh
  1906.             mov     dx,Cursor
  1907.             int     10h                 ;advance cursor
  1908.             jmp     J0
  1909.  
  1910. ;backspace
  1911. J2:         cmp     Cursor,29h
  1912.             jne     J3
  1913.             jmp     J0
  1914. J3:         dec     Cursor
  1915.             dec     di
  1916.             mov     byte ptr [di],0
  1917.             mov     ah,2
  1918.             mov     dx,Cursor
  1919.             int     10h
  1920.             mov     al,' '
  1921.             mov     ah,0Ah
  1922.             mov     cx,1
  1923.             int     10h
  1924.             jmp     J0
  1925.  
  1926. J9:         mov     ah,2
  1927.             mov     dx,2000h
  1928.             mov     bh,VidPage
  1929.             int     10h
  1930.  
  1931.             mov     byte ptr [di],0Dh   ;add carraige return
  1932.             mov     ax,di
  1933.             sub     ax,offset Buffer
  1934.             mov     StrSize,al
  1935.  
  1936.             push    ds
  1937.             pop     es
  1938.  
  1939.             ret
  1940. GetInput    endp
  1941.  
  1942. ;============================================================================
  1943. ; ClrLine clears top line of Trackr's screen
  1944. ;============================================================================
  1945.  
  1946. ClrLine     proc
  1947.             mov     di,3Ch
  1948.             mov     cx,31h
  1949.             mov     ax,word ptr Space
  1950.             mov     es,VidSeg
  1951.             rep     stosw               ;clear line
  1952.             push    ds
  1953.             pop     es
  1954.             ret
  1955. ClrLine     endp
  1956.  
  1957. ;============================================================================
  1958. ; DisStrZ displays ASCIIZ string
  1959. ; Entry:  SI = offset of string
  1960. ;         DI = offset of destination
  1961. ;============================================================================
  1962.  
  1963. DisStrZ     proc
  1964.             mov     cx,255      ;fall through to DisStr
  1965.  
  1966. ;============================================================================
  1967. ; DisStr displays string
  1968. ; Entry:  SI = offset of string
  1969. ;         CX = string length
  1970. ;         DI = destination offset
  1971. ;============================================================================
  1972.  
  1973. DisStr      proc
  1974. ;enter with di pointing to destination, cx=str len, si point to str
  1975.             mov     es,VidSeg
  1976. DS1:        mov     al,[si]
  1977.             cmp     al,0
  1978.             je      DS3
  1979.             cmp     al,0Dh
  1980.             jne     DS2
  1981.             mov     al,' '
  1982.             dec     si
  1983. DS2:        mov     es:[di],al
  1984.             inc     si
  1985.             inc     di
  1986.             inc     di
  1987.             loop    DS1
  1988.             push    ds
  1989.             pop     es
  1990. DS3:        ret
  1991. DisStr      endp
  1992. DisStrZ     endp
  1993.  
  1994. ;============================================================================
  1995. ; DisMenu displays the menu options
  1996. ; Entry:  SI = offset of Menu string
  1997. ;============================================================================
  1998.  
  1999. DisMenu     proc
  2000. ;clear the screen
  2001.             mov     ah,NAt
  2002.             mov     al,' '
  2003.             mov     di,01B4h
  2004.             push    di
  2005.             mov     es,VidSeg
  2006.             mov     cx,5
  2007. DMx:        push    cx
  2008.             push    di
  2009.             mov     cx,13h
  2010.             rep     stosw
  2011.             pop     di
  2012.             pop     cx
  2013.             add     di,0A0h
  2014.             loop    DMx
  2015.  
  2016.             pop     di
  2017.             push    di
  2018.  
  2019. DM0:        mov     al,[si]             ;menu string
  2020.             cmp     al,3
  2021.             jne     DM1
  2022.             pop     di                  ;if al=3 then return
  2023.             push    ds
  2024.             pop     es
  2025.             ret
  2026.  
  2027. DM1:        cmp     al,1                ;if al=1 then hi-lite last value
  2028.             jne     DM2
  2029.             mov     al,HAt
  2030.             mov     es:[di-1],al
  2031.             inc     si
  2032.             jmp     DM0
  2033.  
  2034. DM2:        cmp     al,2                ;if al=2 then go to next line
  2035.             jne     DM3
  2036.             inc     si
  2037.             mov     al,[si]
  2038.             pop     di
  2039.             add     di,0A0h
  2040.             push    di
  2041. DM3:        mov     es:[di],al          ;else display character
  2042.             inc     si
  2043.             inc     di
  2044.             inc     di
  2045.             jmp     DM0
  2046. DisMenu     endp
  2047.  
  2048. ;============================================================================
  2049. ; GetComment gets log on comments for task entry
  2050. ;============================================================================
  2051.  
  2052. GetComment  proc
  2053.             mov     si,offset CommentMsg
  2054.             mov     ax,1Eh
  2055.             call    GetInput
  2056.             mov     cl,StrSize
  2057.             mov     ch,0
  2058.             inc     cx
  2059.             mov     si,offset Buffer
  2060.             mov     di,offset Comments
  2061.             rep     movsb
  2062.             mov     byte ptr [di],0
  2063.             jmp     DisStatus
  2064. GetComment  endp                                   
  2065.  
  2066. ;============================================================================
  2067. ; PutTask inserts task information into task list in alphebetical order
  2068. ; Entry:  SI = offset of task name
  2069. ; Exit:   TaskOff pointing to desired task
  2070. ;         task list in alphabetical order
  2071. ;============================================================================
  2072.  
  2073. PutTask     proc
  2074. ;enter with si pointing to task name
  2075. ;returns with TaskOff and task list in alpha order
  2076.  
  2077.             mov     Temp,si
  2078.             mov     di,offset TaskList-0Dh
  2079.             mov     cl,NumTasks
  2080.             cmp     cl,32h
  2081.             jb      PT1
  2082.             dec     cl
  2083.             mov     NumTasks,cl                 ;ignore tasks if more than 50
  2084. PT1:        xor     ch,ch
  2085.             inc     cx
  2086.  
  2087. CR11:       add     di,0Dh
  2088.             push    di
  2089.             push    cx
  2090.             mov     cx,0Dh
  2091.             mov     si,Temp
  2092.             cmp     word ptr [di],0
  2093.             je      CR11a
  2094.             repe    cmpsb
  2095. CR11a:      pop     cx
  2096.             pop     di
  2097.             jbe     CR12
  2098.             loop    CR11                ;doesn't go here, keep trying
  2099.             
  2100. CR12:       mov     ax,di   
  2101.             mov     di,offset TaskList+289h
  2102.             cmp     ax,di
  2103.             jae     CR13
  2104.             mov     si,di
  2105.             sub     si,0Dh
  2106.             mov     cx,si
  2107.             sub     cx,ax
  2108.             inc     cx
  2109.  
  2110.             std
  2111.             rep     movsb               ;make room for new entry by moving 
  2112.                                         ;other tasks up
  2113.             cld
  2114. CR13:       mov     di,ax
  2115.             mov     TaskOff,di
  2116.             mov     si,Temp
  2117.             mov     cx,0Dh
  2118.             rep     movsb               ;move in new task
  2119.             inc     NumTasks
  2120.             ret
  2121. PutTask     endp
  2122.  
  2123. ;============================================================================
  2124. ; GetClients makes Client array from CLIENT.DAT file
  2125. ;============================================================================
  2126.  
  2127. GetClients  proc
  2128.             xor     ax,ax
  2129.             mov     RecOff,ax
  2130.             mov     NumClients,0
  2131.             mov     di,offset ClientArray
  2132.             mov     cx,1Eh
  2133.             rep     stosw               ;zero out ClientArray
  2134.  
  2135. ;make Client Array
  2136.             mov     di,NameOff
  2137.             mov     si,offset ClientFN
  2138.             mov     cx,11
  2139.             push    es
  2140.             push    ds
  2141.             pop     es
  2142.             rep     movsb               ;make full pathname for CLIENT.DAT
  2143.             pop     es
  2144.  
  2145.             mov     ax,3D00h
  2146.             mov     dx,offset Drive
  2147.             int     21h                 ;open CLIENT.DAT
  2148.             jnc     K31
  2149.  
  2150.             mov     si,offset NeedDATAmsg
  2151.             jmp     DisErr              ;if no CLIENT.DAT file then abort
  2152.     
  2153. K31:        mov     bx,ax               ;file handle
  2154.             mov     ClientFH,ax
  2155.             mov     di,offset ClientArray+2
  2156. K4:         push    di
  2157.             mov     al,1
  2158.             mov     bx,ClientFH
  2159.             call    GetHeader           ;get client info
  2160.             inc     NumClients
  2161.             pop     di
  2162.  
  2163.             cmp     NumClients,30
  2164.             jb      K5
  2165.  
  2166.             mov     si,offset TooManyMsg
  2167.             jmp     DisErrMsg           ;more than 30 clients
  2168.     
  2169. K5:         mov     ax,RecOff
  2170.             mov     [di],ax             ;store in ClientArray
  2171.             inc     di
  2172.             inc     di
  2173.             cmp     EoF,1               ;End of CLIENT.DAT file?
  2174.             jne     K4
  2175.             ret
  2176. GetClients  endp
  2177.  
  2178. Buffer      db      108 dup (0)
  2179.  
  2180. ;----------------------------------------------------------------------------
  2181. ; Non-TSR portion
  2182. ;----------------------------------------------------------------------------
  2183.  
  2184. CodeSeg     dw      0
  2185. RemovedMsg  db      0Dh,0Ah,'TRACKR is removed.',0Dh,0Ah,'$'
  2186. UnableMsg   db      0Dh,0Ah,'Unable to remove TRACKR.',0Dh,0Ah,'$'
  2187. InHereMsg   db      0Dh,0Ah,'TRACKR is already loaded',0Dh,0Ah,'$'
  2188. Copyright   db      0Ah,'TRACKR 1.0 Copyright (c) 1991 Ziff '
  2189.             db      'Communications Co.',0Dh,0Ah
  2190.             db      'PC Magazine ■ Scott Chaney',0Dh,0Ah,0Ah
  2191. Syntax      db      'Syntax: TRACKR [/#] [/U] [/I D:\PATH]',0Dh,0Ah
  2192.             db      ' /#  = Minutes between reminders '
  2193.             db      '(1-9, 0=disable)',0Dh,0Ah
  2194.             db      ' /U  = Uninstall',0Dh,0Ah
  2195.             db      ' /I  = Sets path for .LOG files',0Dh,0Ah,0Ah
  2196. ActMsg      db      'Activation Hot Key: '
  2197. HKmsg       db      'Ctrl-R          ',0Dh,0Ah,'$'
  2198.  
  2199. Init        proc
  2200.  
  2201.             push    cs
  2202.             pop     es
  2203.  
  2204. B4:         mov     ax,cs
  2205.             mov     ds,ax
  2206.             mov     es,ax
  2207.  
  2208. ;check for DOS 3.0 or greater
  2209.             mov     ah,30h
  2210.             int     21h
  2211.             cmp     al,3
  2212.             jae     B5
  2213.             mov     dx,offset WrongVerMsg
  2214.             jmp     P32b
  2215.     
  2216. ;get our PSP
  2217. B5:         mov     ah,51h
  2218.             int     21h
  2219.             mov     OurPSP,bx
  2220.  
  2221. ;move NAt into attribute array
  2222.             mov     al,HAt
  2223.             mov     cx,31h
  2224.             mov     di,offset Attributes
  2225.             rep     stosb
  2226.             mov     cx,157h
  2227.             mov     al,NAt
  2228.             rep     stosb
  2229.  
  2230. ;check for command line           
  2231. In0:        mov     bx,80h
  2232.             mov     cl,[bx]     ;number of characters in command line
  2233.             cmp     cl,0
  2234.             jne     In2
  2235. In1:        jmp     P4
  2236.  
  2237. In2:        mov     si,81h
  2238.  
  2239. Parse:      mov     al,[si]
  2240.             inc     si
  2241.             cmp     al,0Dh
  2242.             je      In1
  2243.             cmp     al,'/'
  2244.             je      Parse
  2245. P01:        cmp     al,' '
  2246.             je      Parse
  2247.  
  2248.             cmp     al,'?'
  2249.             jne     P012
  2250.  
  2251. ;asking for help: display copyright and exit
  2252.             mov     dx,offset Syntax
  2253.             mov     ah,9
  2254.             mov     ActMsg,'$'
  2255.             int     21h
  2256.             mov     ah,4Ch
  2257.             int     21h
  2258.     
  2259. P012:       cmp     al,'0'
  2260.             jb      P015
  2261.             cmp     al,'9'
  2262.             ja      P015
  2263.  
  2264. ;adjusting reminder interval
  2265.             sub     al,'0'
  2266.             jnz     P013
  2267.             mov     Display?,0
  2268.             jmp     P4                  ;if 0 then no reminders
  2269.  
  2270. P013:       mov     bl,al
  2271.             mov     ax,0444h
  2272.             mul     bx                  ;multiply reminder interval by clock  
  2273.                                         ;ticks per minute
  2274.             mov     WaitTicks,ax
  2275.  
  2276.             jmp     P4
  2277.  
  2278. P015:       or      al,20h
  2279.  
  2280.             cmp     al,'u'              ;uninstall?
  2281.             jne     P3              
  2282.             jmp     UnInstall
  2283.  
  2284. P3:         cmp     al,'i'              ;initialize path for .LOG files?
  2285.             jne     Parse
  2286.             mov     di,offset Drive
  2287.  
  2288. P31:        lodsb
  2289.             cmp     al,' '
  2290.             je      P31
  2291.             cmp     al,0Dh
  2292.             je      P32
  2293.             stosb                       ;store path in "Drive"
  2294.             jmp     P31
  2295.  
  2296. P32:        mov     al,'\'              ;add '\' to end
  2297.             stosb
  2298.             mov     NameOff,di          ;put offset in NameOff
  2299.  
  2300. ;get full pathname of TRACKR.COM
  2301.             mov     ax,cs:2Ch
  2302.             mov     es,ax
  2303.             xor     ax,ax
  2304.             mov     di,ax
  2305.             mov     cx,1024
  2306. GP0:        cmp     word ptr es:[di],ax
  2307.             je      GP1
  2308.             inc     di
  2309.             loop    GP0
  2310.             mov     dx,offset ThisFile
  2311.             jmp     GP2
  2312.     
  2313. GP1:        add     di,4
  2314.             mov     dx,di
  2315.             push    es
  2316.             pop     ds
  2317.  
  2318. GP2:        mov     ax,3D02h
  2319.             int     21h                 ;open TRACKR.COM
  2320.             push    cs
  2321.             pop     ds
  2322.             jnc     P33
  2323.  
  2324. ;can't find TRACKR.COM
  2325. P32a:       mov     dx,offset CantInitMsg
  2326. P32b:       mov     ah,9
  2327.             int     21h
  2328.             mov     ah,4Ch
  2329.             int     21h     ;end
  2330.  
  2331. P33:        mov     bx,ax               ;file handle
  2332.             mov     cx,54h
  2333.             mov     dx,100h
  2334.             mov     ah,40h
  2335.             int     21h                 ;write task and client directory info
  2336.             jc      P32a
  2337.             mov     ah,3Eh
  2338.             int     21h                 ;close file
  2339.  
  2340. P4:         call    Loaded?             ;Trackr loaded already?
  2341.             jne     P45
  2342.  
  2343.             mov     dx,offset InHereMsg ;if so, say so and quit
  2344.             mov     ah,9
  2345.             int     21h
  2346.             mov     ah,4Ch
  2347.             int     21h
  2348.  
  2349. P45:        mov     ah,0Fh              ;get video mode
  2350.             int     10h
  2351.             xor     ah,ah
  2352.             cmp     al,7
  2353.             je      L1
  2354.             mov     al,3
  2355.             mov     OrgVidSeg,0B800h    ;set video segment (0B000 by default)
  2356.  
  2357. L1:         mov     dx,offset DTA
  2358.             mov     ah,1Ah
  2359.             int     21h                 ;set DTA
  2360.  
  2361. ;make task list
  2362.             push    cs
  2363.             pop     es
  2364.  
  2365.             mov     di,NameOff
  2366.             mov     si,offset SrchName
  2367.             mov     cx,6
  2368.             rep     movsb
  2369.  
  2370.             mov     dx,offset Drive 
  2371.             mov     cx,0
  2372.             mov     ah,4Eh
  2373.  
  2374.             int     21h                 ;find first .LOG file
  2375.             jc      K3
  2376.  
  2377. K1:         mov     si,offset DTA+1Eh
  2378.             call    PutTask
  2379.             cmp     NumTasks,32h
  2380.             jb      K2
  2381.             mov     dx,offset Warning
  2382.             mov     ah,9
  2383.             int     21h
  2384.             jmp     K3
  2385.     
  2386. K2:         mov     ah,4Fh
  2387.             int     21h                 ;find next .LOG file
  2388.             jnc     K1
  2389.     
  2390. K3:         mov     TaskOff,0
  2391.  
  2392.             mov     ah,9
  2393.             mov     dx,offset Copyright
  2394.             int     21h                 ;print copyright
  2395.  
  2396. M1:         mov     ax,cs:2Ch
  2397.             mov     es,ax
  2398.             mov     ah,49h
  2399.             int     21h                 ;free environment memory
  2400.  
  2401.             mov     ax,3509h
  2402.             int     21h                 ;get int 09 vector
  2403.             mov     word ptr Vec09,bx
  2404.             mov     word ptr Vec09[2],es
  2405.  
  2406.             mov     ax,3513h
  2407.             int     21h                 ;get int vec 13
  2408.             mov     word ptr Vec13,bx
  2409.             mov     word ptr Vec13[2],es
  2410.  
  2411.             mov     ax,3508h
  2412.             int     21h                 ;get int vec 1C
  2413.             mov     word ptr Vec08,bx
  2414.             mov     word ptr Vec08[2],es
  2415.  
  2416.             mov     ax,3528h
  2417.             int     21h                 ;get int vec 28
  2418.             mov     word ptr Vec28,bx
  2419.             mov     word ptr Vec28[2],es
  2420.  
  2421.             mov     ah,34h
  2422.             int     21h                 ;location of DOS busy byte
  2423.             mov     DBseg,es
  2424.             mov     DBoff,bx
  2425.  
  2426.             mov     dx,offset Int09
  2427.             mov     ax,2509h
  2428.             int     21h                 ;set vector for Int 09
  2429.  
  2430.             mov     dx,offset Int13
  2431.             mov     ax,2513h
  2432.             int     21h                 ;set vector for Int 13
  2433.  
  2434.             mov     dx,offset Int08
  2435.             mov     ax,2508h
  2436.             int     21h                 ;set vector for Int 1C
  2437.  
  2438.             mov     dx,offset Int28
  2439.             mov     ax,2528h
  2440.             int     21h                 ;set vector for Int 28
  2441.  
  2442.             mov     ax,offset CodeSeg
  2443.             mov     cl,4
  2444.             shr     ax,cl
  2445.             inc     ax
  2446.             mov     dx,ax               ;paragraphs to remain resident
  2447.             mov     ax,3100h
  2448.             int     21h                 ;go TSR
  2449. Init        endp
  2450.  
  2451. UnInstall   proc
  2452.             call    Loaded?
  2453.             je      UI1
  2454.             jmp     U2
  2455.  
  2456. UI1:        mov     CodeSeg,es
  2457. ;check to see if anyone else has taken our interupts
  2458.             mov     ax,es
  2459.             xor     si,si
  2460.             mov     ds,si
  2461.             cmp     [si+26h],ax         ;Int 09
  2462.             jne     Unable
  2463.             cmp     [si+4Eh],ax         ;Int 13h 
  2464.             jne     Unable          
  2465.             cmp     [si+22h],ax         ;Int 08h
  2466.             jne     Unable         
  2467.             cmp     [si+0A2h],ax        ;Int 28h
  2468.             je      U1
  2469.     
  2470. Unable:     mov     ah,9
  2471.             mov     dx,offset UnableMsg
  2472.             push    cs
  2473.             pop     ds
  2474.             int     21h
  2475.             mov     ah,4Ch
  2476.             int     21h
  2477.  
  2478. U1:         inc     es:Message+2        ;change message
  2479.  
  2480. ;reset interupts to original values
  2481.             mov     dx,word ptr es:Vec09
  2482.             mov     ax,word ptr es:Vec09[2]
  2483.             mov     ds,ax
  2484.             mov     ax,2509h            ;reset int 09
  2485.             int     21h
  2486.  
  2487.             mov     dx,word ptr es:Vec13
  2488.             mov     ax,word ptr es:Vec13[2]
  2489.             mov     ds,ax
  2490.             mov     ax,2513h            ;reset int 13
  2491.             int     21h
  2492.  
  2493.             mov     dx,word ptr es:Vec08
  2494.             mov     ax,word ptr es:Vec08[2]
  2495.             mov     ds,ax
  2496.             mov     ax,2508h            ;reset int 1C
  2497.             int     21h
  2498.  
  2499.             mov     dx,word ptr es:Vec28
  2500.             mov     ax,word ptr es:Vec28[2]
  2501.             mov     ds,ax
  2502.             mov     ax,2528h            ;reset int 28
  2503.             int     21h
  2504.  
  2505.             mov     ah,49h
  2506.             int     21h                 ;free memory block
  2507.  
  2508.             push    cs
  2509.             pop     ds
  2510.             mov     dx,offset RemovedMsg
  2511.             mov     ah,9
  2512.             int     21h                 ;print message
  2513. U2:         mov     ah,4Ch
  2514.             int     21h                 ;end
  2515.   
  2516. UnInstall   endp
  2517.     
  2518. Loaded?     proc
  2519. ;checks to see if TSR already is loaded.  If it is then zf set upon 
  2520. ;return and es:di points to offset info in TSR
  2521.  
  2522.             mov     bx,offset Message  
  2523.             inc     Message             ;avoid disk cache match
  2524.             mov     ax,cs            
  2525.             mov     dx,0A000h-1
  2526. NextPara:   inc     dx                  ;next paragraph
  2527.             mov     es,dx
  2528.             cmp     dx,ax   
  2529.             je      NotHere             ;If our seg then search is done 
  2530.             mov     si,bx               ;else check for match
  2531.             mov     di,bx              
  2532.             mov     cx,0Ah  
  2533.             rep     cmpsb               ;a match? 
  2534.             jnz     NextPara            ;if no match, keep looking
  2535.             ret
  2536.  
  2537. NotHere:    inc     ax
  2538.             cmp     ax,dx               ;return with not equal
  2539.             ret
  2540.  
  2541. Loaded?     endp
  2542.  
  2543. CantInitMsg db      'Unable to locate TRACKR.COM.  Aborting.$'
  2544. Warning     db      0Dh,0Ah,'WARNING:  Number of tasks exceeds limit'
  2545.             db      ' of 50.  Extras will be ignored.',7,0Dh,0Ah,'$'
  2546. WrongVerMsg db      'Sorry, TRACKR needs DOS 3.0 or greater.',7,'$'
  2547.  
  2548. ;data needed for CONFIG program
  2549. Preface     db      255,'*RsE*',128
  2550. Method      db      1
  2551. Colors      db      2
  2552. ColorOff    dw      offset HAt
  2553. NumKeys     db      1
  2554. NumEtc      db      0
  2555. SSoff       dw      offset ShiftState
  2556. SCoff       dw      offset ScanCode
  2557. DesOff      dw      offset HKmsg
  2558.     
  2559. Code        ends
  2560.             end     LGo
  2561.  
  2562.