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