home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / pcmagazi / 1992 / 03 / addit.asm < prev    next >
Assembly Source File  |  1991-11-13  |  78KB  |  2,195 lines

  1.             page    66,132
  2. ;============================================================================
  3. ; ADDIT.COM adds a series of numbers captured from the display.
  4. ;
  5. ;       Usage: ADDIT [/B][/U]
  6. ;
  7. ;              B = Use Video BIOS calls
  8. ;              U = Uninstall
  9. ;
  10. ; Revision History:
  11. ;
  12. ;       Version 1.0     Initial Release
  13. ;
  14. ;============================================================================
  15. POPTIME         equ     9                       ;Allow 1/2 second to popup
  16.  
  17. STACKSIZE       equ     512                     ;TSR stack
  18. MSGBOX_BUFFSIZE equ     1 * 132 * 2             ;Screen save buff for title
  19. HELPBOX_BUFFSIZE equ    5 * 132 * 2             ;Screen save buff for help
  20.  
  21. MSGBOX_BUFFER   equ     offset end_of_resident
  22. ATTR_BUFFER     equ     MSGBOX_BUFFER + MSGBOX_BUFFSIZE
  23.  
  24. ;----------------------------------------------------------------------------
  25. ; BIOS Data segment
  26. ;----------------------------------------------------------------------------
  27. bios_data       segment at 40h
  28.             org     17h
  29. shift_state     db      ?                       ;State of keyboard shift keys
  30.         org    1Ah
  31. keybuff_head    dw    ?            ;Start ptr for keyboard buff
  32. keybuff_tail    dw    ?             ;End ptr for keyboard buff
  33.  
  34.             org     4Eh
  35. video_buffoff   dw      ?                       ;Offset of video buffer
  36.             org     63h
  37. video_ioregs    dw      ?                       ;I/O addr of video controller
  38.         org    80h
  39. keybuff_start    dw    ?            ;Start ptr for keyboard buff
  40. keybuff_end    dw    ?             ;End ptr for keyboard buff
  41. video_rows      db      ?                       ;Number of rows on the screen
  42. bios_data       ends
  43.  
  44. ;----------------------------------------------------------------------------
  45. ; ADDIT Code and Data segments
  46. ;----------------------------------------------------------------------------
  47.             code    segment
  48.             assume  cs:code
  49.  
  50.             org     2ch
  51. env_segment     dw      ?                       ;Word containing the segment
  52.                                             ;  of the program's env. block.
  53.             org     80h
  54. command_tail    db      ?                       ;Offset of the command tail.
  55.  
  56.             org     100h
  57. prog:           jmp     initialize
  58. ;---------------------------------------------------------------------------            pushf
  59. ; Resident Data
  60. ;---------------------------------------------------------------------------            pushf
  61. program         db      13,10
  62. program1    db    "ADDIT 1.0 "
  63. copyright       db      "(c) 1992 Douglas Boling"
  64. program2    db    10,13
  65.             db      "First published in PC Magazine, Feburary 11, 1992"
  66.             db      13,10,"$",1Ah
  67.  
  68. def_marked_bw   db      70h                     ;Default marked attr B/W
  69. def_text_bw     db      70h                     ;Default text attr B/W
  70. def_number_bw   db      79h                     ;Default number attr B/W
  71. def_neg_bw      db      7Fh                     ;Default neg number attr B/W
  72. bw_segment    dw    0B000h            ;Segment of B/W video memory
  73.  
  74. def_marked_clr  db      70h                     ;Default marked attr Color
  75. def_text_clr    db      71h                     ;Default text attr Color
  76. def_number_clr  db      7Eh                     ;Default number attr Color
  77. def_neg_clr     db      74h                     ;Default neg number attr Color
  78. clr_segment    dw    0B800h            ;Segment of color video memory
  79.  
  80. attr_buffsize    dw    1024            ;Size of attribute buffer
  81. helpbox_buff      dw    0               ;Pointer to helpbox buffer
  82. res_stack    dw    0            ;Stack ptr when resident
  83.  
  84. indos_ptr       dd      -1                      ;Pointer to INDOS flag
  85. criterr_ptr     dd      -1                      ;Pointer to DOS crit err flag
  86.  
  87. int08h          dd      -1                      ;Int 2f vector (Timer)
  88. int09h          dd      -1                      ;Int 09 vector (Keyboard HW)
  89. int10h          dd      -1                      ;Int 10 vector (Video BIOS)
  90. int13h          dd      -1                      ;Int 13 vector (Disk BIOS)
  91. int16h          dd      -1                      ;Int 16 vector (Keyboard)
  92. int28h          dd      -1                      ;Int 28 vector (DOS Idle)
  93. int2Fh          dd      -1                      ;Int 2F vector (DOS Multiplex)
  94.  
  95. int08_active    db      0                       ;Interrupt active flag
  96. int09_active    db      0                       ;Interrupt active flag
  97. int10_active    db      0                       ;Interrupt active flag
  98. int13_active    db      0                       ;Interrupt active flag
  99. int16_active    db      0                       ;Interrupt active flag
  100. int28_active    db      0                       ;Interrupt active flag
  101. int2F_active    db      0                       ;Interrupt active flag
  102. main_active     db      0                       ;TSR active flag
  103.  
  104. saved_ss        dw      0
  105. saved_sp        dw      0
  106.  
  107. hotshift        db      0ah                     ;Shift condition for popup
  108. popflag         db      0                       ;Go active counter
  109.  
  110. keycodes        db      3bh,4eh,0dh,51h,49h,4fh,47h,48h,50h,74h,73h,4bh,4dh
  111. keycodes_end    =       $
  112.  
  113. keyjmp_table    dw      offset cursor_rt        ;Index into key routines are
  114.             dw      offset cursor_lt        ;  inverse of order of
  115.             dw      offset cursor_clt       ;  keycode array.
  116.             dw      offset cursor_crt
  117.             dw      offset cursor_dn 
  118.             dw      offset cursor_up
  119.             dw      offset cursor_home    ;Home
  120.             dw      offset cursor_end    ;End
  121.             dw      offset cursor_top    ;Page Up
  122.             dw      offset cursor_bottom    ;Page Down
  123.             dw      offset addmarked    ;=/+ key
  124.             dw      offset addmarked    ;keypad +
  125.             dw      offset showhelp        ;F1
  126.  
  127. addmarked_tbl    dw    offset add_digit    ;Digit after digit
  128.         dw    offset setdec        ;Period after digit
  129.         dw    offset chkcomma        ;Comma after digit
  130.         dw    offset setneg        ;Dash after digit
  131.         dw    offset termnumber    ;Char after digit
  132.         dw    offset add_digit    ;Digit after char
  133.         dw    offset setdec        ;Period after char
  134.         dw    offset termnumber    ;Comma after char
  135.         dw    offset setneg1        ;Dash after char
  136.         dw    offset termnumber    ;Char after char
  137.  
  138. summsg          db      "Sum:",0
  139. pastemsg    db    "Number too long to paste",0
  140. helptag         db      "F1 for Help",0
  141. no_help        db    0            ;Blocks help msg
  142. ;                        1234567891123456789212345678931234567894
  143. helpmsg1        db      " <Cursor> keys delete box/move cursor   "
  144.             db      " <Shift><Cursor> keys size box",0
  145. helpmsg2        db      " <Home>   Move to start of line         "
  146.             db      " <End>    Move to end of line",0
  147. helpmsg3        db      " <Pg Up>  Move to top of screen         "
  148.             db      " <Pg Dn>  Move to bot of screen",0
  149. helpmsg4        db      " <+>      Add numbers found in box      "
  150.             db      " <P>      Paste sum into application",0
  151. helpmsg5        db      " <Esc>    Exit the program",0
  152.  
  153. overflowmsg     db      "Overflow",0
  154. ;
  155. ;Screen variables
  156. ;
  157. BIOSFlag    db    0            ;1 = Use Vid BIOS calls
  158. video_ptr    label    dword
  159. video_offset    dw    0            ;Offset of video memory
  160. video_seg    dw    0            ;Segment of video memory
  161.  
  162. marked_attr     db      0                       ;Screen attr for marked area
  163. text_attr       db      0                       ;Attribute for msg box text
  164. number_attr     db      0                       ;Attribute to mark numbers
  165. negative_attr   db      0                       ;Attribute to mark neg numbers
  166.  
  167. cursor_pos      dw      0                       ;Cursor position at popup
  168. cursor_type     dw      0                       ;Cursor shape at popup
  169.  
  170. screen_page     db      0                       ;Active video page
  171. screen_size     label   word
  172. screen_cx       db      0                       ;Screen columns
  173. screen_cy       db      0                       ;Screen rows
  174.  
  175. marked_pos1     label   word
  176. marked_x1       db      0                       ;Marked area starting column
  177. marked_y1       db      0                       ;marked area starting row
  178. marked_pos2     label   word
  179. marked_x2       db      0                       ;Marked area ending column
  180. marked_y2       db      0                       ;marked area ending row
  181.  
  182. oldmarked_pos1  label   word
  183. oldmarked_x1    db      0                       ;Marked area starting row
  184. oldmarked_y1    db      0                       ;marked area starting column
  185. oldmarked_pos2  label   word
  186. oldmarked_x2    db      0                       ;Marked area columns
  187. oldmarked_y2    db      0                       ;marked area rows
  188.     
  189. boxactive       db      0                       ;Flag for message box
  190. ;
  191. ;Variables used in the addition routines.
  192. ;
  193. base            dw      10                      ;base 10
  194. sum_num         dw      3 dup (0)
  195. sum_exp         db      0
  196. sum_sign        db      0
  197.  
  198. curr_num        dw      3 dup (0)
  199. curr_exp        db      0
  200. curr_sign       db      0
  201.  
  202. sum_overflow    db      0
  203. decimal_flag    db      0
  204. curr_num_active db      0
  205. last_char    db    0
  206.  
  207. ;============================================================================
  208. ; VIDEOINT processes BIOS video services interrupt (Int 10h)
  209. ;============================================================================
  210. videoint        proc    far
  211.             assume  cs:code,ds:nothing,es:nothing
  212.             inc     cs:int10_active
  213.             pushf
  214.             call    cs:[int10h]             ;Call old int
  215.             dec     cs:int10_active
  216.             iret                            ;Return
  217. videoint        endp
  218.  
  219. ;============================================================================
  220. ; DISKINT processes BIOS disk services interrupt (Int 13h)
  221. ;============================================================================
  222. diskint         proc    far
  223.             assume  cs:code,ds:nothing,es:nothing
  224.             inc     cs:int13_active
  225.             pushf
  226.             call    cs:[int13h]             ;Call old int
  227.             pushf
  228.             dec     cs:int13_active
  229.             popf
  230.             ret     2                       ;Return preserving flags
  231. diskint         endp
  232.  
  233. ;============================================================================
  234. ; BIOSKEYINT processes keyboard services interrupt (Int 16h)
  235. ;============================================================================
  236. bioskeyint      proc    far
  237.             assume  cs:code,ds:nothing,es:nothing
  238.             inc     cs:int16_active
  239.             pushf
  240.             call    cs:[int16h]             ;Call old int
  241.             pushf
  242.             dec     cs:int16_active
  243.             popf
  244.             ret     2                       ;Return preserving flags
  245. bioskeyint      endp
  246.  
  247. ;============================================================================
  248. ; TIMERINT processes timer interrupt (Int 08h)
  249. ;============================================================================
  250. timerint        proc    far
  251.             assume  cs:code,ds:nothing,es:nothing
  252.             pushf
  253.             call    cs:[int08h]             ;Call old int 8
  254.  
  255.  
  256.         push    ds
  257.         push    cs
  258.         pop    ds
  259.         assume    ds:code
  260.     
  261.             cmp     int08_active,0          ;See if we are in this
  262.             jne     timerint_exit           ;  routine already
  263.  
  264.             cmp     popflag,0               ;See if we need to try to
  265.             jne     timer_check             ;  pop up
  266. timerint_exit:
  267.         pop    ds
  268.             iret                            ;Return
  269. timer_check:
  270.             push    ax
  271.             inc     int08_active            ;Set int active flag
  272.  
  273.             call    check_system            ;See if system OK to pop up
  274.             or      ax,ax
  275.             jne     timerint_dec
  276.             call    main                    ;Call the TSR
  277.             mov     popflag,1
  278. timerint_dec:
  279.             dec     popflag
  280.             dec     int08_active            ;Clear int active flag
  281.             pop     ax
  282.             jmp     short timerint_exit
  283. timerint        endp
  284.  
  285. ;============================================================================
  286. ; KEYINT processes keyboard interrupts (Int 09h)
  287. ;============================================================================
  288. keyint          proc    far
  289.             assume  cs:code,ds:nothing,es:nothing
  290.             pushf
  291.             call    cs:[int09h]             ;Call old int 9
  292.  
  293.             push    ax
  294.             push    ds
  295.             mov     ax,40h
  296.             mov     ds,ax                   ;Set ES to bios data segment
  297.             assume  ds:bios_data
  298.             mov     al,ds:[shift_state]
  299.             and     al,0fh                  ;Mask lock bits
  300.             cmp     al,cs:[hotshift]
  301.             pop     ds
  302.             pop     ax
  303.             je      keyint_hotkey
  304. keyint_exit:
  305.             iret                            ;Return
  306. keyint_hotkey:
  307.             mov     cs:popflag,POPTIME      ;Set timer to pop up
  308.             jmp     short keyint_exit
  309. keyint          endp
  310.  
  311. ;============================================================================
  312. ; IDLEINT processes DOS Idle interrupt (Int 28h)
  313. ;============================================================================
  314. idleint         proc    far
  315.             assume  cs:code,ds:nothing,es:nothing
  316.             pushf
  317.             call    cs:[int28h]             ;Call old int
  318.  
  319.         push    ds
  320.         push    cs
  321.         pop    ds
  322.         assume    ds:code
  323.             cmp     int28_active,0          ;See if we are in this
  324.             jne     idleint_exit            ;  routine already
  325.             cmp     popflag,0               ;See if we need to try to
  326.             jne     idle_check              ;  pop up
  327. idleint_exit:
  328.         pop    ds
  329.             iret                            ;Return
  330. idle_check:
  331.             push    ax
  332.             inc     int28_active            ;Set int active flag
  333.             call    check_system            ;See if OK to pop up.  Ignore
  334.             or      al,al                   ;  INDOS since in idle.
  335.             jne     idleint_exit1
  336.             mov     popflag,0               ;Clear popup flag
  337.             call    main                    ;Call the TSR
  338. idleint_exit1:
  339.             dec     int28_active            ;Clear int active flag
  340.             pop     ax
  341.             jmp     short idleint_exit
  342. idleint         endp
  343.  
  344. ;---------------------------------------------------------------------------            pushf
  345. ; Check System Determines if the system is in a state compatible with TSRs
  346. ; Exit: AL - ORed flags for DOS Idle OK
  347. ;       AH - State of INDOS flag
  348. ;---------------------------------------------------------------------------            pushf
  349. check_system    proc    near
  350.             assume  cs:code,ds:code,es:nothing
  351.             push    bx
  352.             push    ds
  353.             xor     ax,ax
  354.             or      al,int10_active         ;Check BIOS video int
  355.             or      al,int13_active         ;Check BIOS disk int
  356.             or      al,int16_active         ;Check BIOS keyboard int
  357.             lds     bx,criterr_ptr          ;Check DOS critical error
  358.             or      al,byte ptr ds:[bx]     ;  flag.
  359.             lds     bx,indos_ptr            ;Check INDOS flag
  360.             mov     ah,byte ptr ds:[bx]
  361. check_sys_exit:
  362.             pop     ds
  363.             pop     bx
  364.             ret
  365. check_system    endp
  366.  
  367. ;============================================================================
  368. ; MAIN this is the main body of the TSR
  369. ;============================================================================
  370. main            proc    near
  371.             assume  cs:code,ds:code,es:nothing
  372.             cmp     main_active,0           ;See if already active
  373.             jne     main_exit
  374.             cli
  375.             inc     main_active
  376.             mov     [saved_sp],sp           ;Save old stack pointer
  377.             mov     [saved_ss],ss
  378.  
  379.             mov     ax,cs                   ;Set ss:sp to internal stack
  380.             mov     ss,ax
  381.             mov     sp,res_stack
  382.             sti                ;Enable interrupts
  383.             cld                ;Set string direction UP
  384.  
  385.             push    bx
  386.             push    cx
  387.             push    dx
  388.             push    di
  389.             push    si
  390.             push    bp
  391.             push    es
  392.     
  393.             mov     ah,0fh                  ;Get display mode
  394.             int     10h
  395.             cmp     al,7
  396.             je      main_1                  ;Pop up only if in text mode.
  397.             cmp     al,4
  398.             jb      main_1
  399. main_exit1:
  400.             pop     es
  401.             pop     bp
  402.             pop     si
  403.             pop     di
  404.             pop     dx
  405.             pop     cx
  406.             pop     bx
  407.     
  408.             cli
  409.             mov     ss,[saved_ss]           ;Restore old stack
  410.             mov     sp,[saved_sp]
  411.             dec     main_active
  412. main_exit:
  413.             ret
  414. main_1:
  415.         mov    byte ptr no_help,0    ;Enable help message
  416.             cmp     ah,80
  417.             jb      main_exit1
  418.             mov     screen_page,bh          ;Save active video page
  419.             mov     screen_cx,ah            ;Save screen columns
  420.  
  421.             mov     ah,3                    ;Get cursor position
  422.             int     10h
  423.             mov     cursor_pos,dx           ;Save cursor information
  424.             mov     cursor_type,cx
  425.         cmp    dh,0            ;If on top line, move down 1
  426.         jne    main_11            ;  to miss banner.
  427.         inc    dh
  428. main_11:
  429.         mov    marked_pos1,dx        ;Save initial cursor position
  430.             mov     ax,40h
  431.             mov     es,ax                   ;Set ES to bios data segment
  432.             assume  es:bios_data
  433.             mov     ah,12h                  ;Determine if CGA by checking
  434.             mov     bl,10h                  ;  for EGA compatibility
  435.             int     10h
  436.             mov     al,24                   ;CGA, only 25 rows on screen
  437.             cmp     bl,10h
  438.             je      main_2
  439.  
  440.             mov     al,es:video_rows        ;Get number of rows on screen
  441. main_2:
  442.             mov     screen_cy,al        ;Save screen rows
  443.         mov    ax,es:video_buffoff    ;Copy ptr to video memory
  444.         mov    video_offset,ax
  445.  
  446.             mov     ax,marked_pos1        ;Copy starting pos to ending
  447.             mov     marked_pos2,ax        ;  pos to zero block.
  448.             mov     oldmarked_pos1,ax
  449.             mov     oldmarked_pos2,ax
  450.     
  451.             test    es:video_ioregs,40h     ;See if color or monochrome
  452.             jne     main_colorvid
  453.  
  454.         mov    si,offset def_marked_bw    ;Point to B/W parameters
  455.             jmp     short main_3
  456. main_colorvid:
  457.         mov    si,offset def_marked_clr ;Point to color parameters    
  458. main_3:
  459.             push    ds
  460.             pop     es
  461.             assume  es:code
  462.  
  463.         mov    di,offset marked_attr    ;Copy default attributes 
  464.         movsw
  465.         movsw
  466.         lodsw                ;Get Video buffer segment
  467.         mov    video_seg,ax
  468.  
  469.             mov     ah,1            ;Hide the cursor by changing
  470.             mov     cx,200h                 ;  the size of the cursor
  471.             int     10h
  472.  
  473.         call    init_attrlist        ;Initialize attr save list
  474.         jc    main_end1
  475.  
  476.             mov     dx,marked_pos1          ;Mark initial cursor where
  477.             call    getchar                 ;  the old cursor was
  478.             mov     ah,marked_attr        ;Mark cursor position on
  479.             call    putchar            ;  screen.
  480. main_loop:
  481.             cmp     boxactive,1             ;If box active, don't reprint
  482.             je      main_4                  ;  the box.
  483.  
  484.         mov    al,marked_y2        ;If cursor on top line, don't
  485.         or    al,marked_y2        ;  print the title box.
  486.         je    main_4
  487.             call    msgbox                  ;Draw title box
  488. main_4:
  489.         call    getkey            ;Wait for a key
  490.             cmp     al,27                   ;If ESC, end.
  491.             je      main_end
  492.             cmp     ah,25                   ;If 'p' paste and exit
  493.             je      main_paste
  494.             mov     al,ah            ;Copy scan code
  495. main_6:
  496.             mov     di,offset keycodes
  497.             mov     cx,offset keycodes_end - offset keycodes
  498.             repne   scasb
  499.             jne     main_loop
  500.             shl     cx,1            ;Convert key num into jump
  501.             mov     bx,cx            ;  table index.
  502.         mov    ax,marked_pos2        ;Preload parameters into regs
  503.         mov    cx,screen_size        ;  to save code
  504.             call    [keyjmp_table+bx]    ;Call key routine
  505.             jmp     short main_loop
  506. main_paste:
  507.         call    paste            ;Paste to keyboard buffer
  508. main_end:
  509.             call    clearmarked             ;Restore attributes
  510.             call    clearbox                ;Delete title box
  511. main_end1:
  512.             mov     ah,1                    ;Set cursor type
  513.             mov     cx,cursor_type
  514.             mov     bh,screen_page
  515.             int     10h
  516.             mov     ah,2                    ;Set cursor position
  517.             mov     dx,cursor_pos
  518.             int     10h
  519.             jmp     main_exit1
  520. main            endp
  521.  
  522. ;-----------------------------------------------------------------------------
  523. ; CURSOR KEYS Handles the actions of the cursor keys as the user uses them
  524. ;             to mark the selected area.
  525. ; Entry: AL - marked_x2
  526. ;        AH - marked_y2
  527. ;        CL - screen_cx
  528. ;        CH - screen_cy
  529. ;-----------------------------------------------------------------------------
  530. cursor_keys     proc    near
  531.  
  532. ; CURSOR HOME  Moves the cursor to the left most column
  533. cursor_home:
  534.             xor     al,al            ;Zero current column
  535.             jmp     short cursor_1
  536. ; CURSOR END  Moves the cursor to the right most column
  537. cursor_end:
  538.             mov     al,cl            ;Set Cur column to screen cols
  539.             dec     al
  540.             jmp     short cursor_1
  541. ; CURSOR TOP  Moves the cursor to the top row
  542. cursor_top:
  543.             mov     ah,1                    ;Move to line 1 to avoid
  544.             jmp     short cursor_1          ;  title erase
  545. ; CURSOR END  Moves the cursor to the bottom row
  546. cursor_bottom:
  547.             mov     ah,ch            ;Set Cur Row to screen rows
  548.             jmp     short cursor_1
  549. ; CURSOR UP  Moves the marked orgin up one row
  550. cursor_up:
  551.             or      ah,ah
  552.             je      cursor_1
  553.             dec     ah
  554.             jmp     short cursor_1
  555. ; CURSOR DN  Moves the marked orgin down one row
  556. cursor_dn:
  557.             cmp     ah,ch
  558.             je      cursor_1
  559.             inc     ah
  560.             jmp     short cursor_1
  561. ; CURSOR CLT  Moves the marked orgin left 8 columns
  562. cursor_clt:
  563.         sub    al,8
  564.         jae    cursor_1
  565.             xor     al,al
  566.             jmp     short cursor_1
  567. ; CURSOR CRT  Moves the marked orgin right 8 columns
  568. cursor_crt:
  569.         add    al,8
  570.         dec    cl
  571.         cmp    al,cl
  572.         jb    cursor_1
  573.             mov     al,cl
  574.             jmp     short cursor_1
  575. ; CURSOR LT  Moves the marked orgin left one col
  576. cursor_lt:
  577.             or      al,al
  578.             je      cursor_1
  579.             dec     al
  580.             jmp     short cursor_1
  581. ; CURSOR RT  Moves the marked orgin right one col
  582. cursor_rt:
  583.         dec    cl
  584.             cmp     al,cl
  585.             jae     cursor_1
  586.             inc     al
  587. cursor_1:
  588.         mov    marked_pos2,ax        ;Save new position
  589.         push    ax
  590.             mov     ah,2                    ;Get shift state
  591.             int     16h
  592.             and     al,3
  593.         pop    ax
  594.             je      cursor_11
  595.             mov     si,offset sum_num       ;If changing the size of the
  596.             call    clear_number        ;  box, clear the sum.
  597.         inc    boxactive
  598.             jmp     short cursor_2
  599. cursor_11:
  600.             mov     marked_pos1,ax          ;Not shifted, set points equal
  601. cursor_2:
  602.             or      ah,ah                   ;If cursor on top line, clear
  603.             jne     cursor_3                ;  title box so user can see
  604.             call    clearbox                ;  what is on top line.
  605. cursor_3:
  606.             call    drawmarked
  607.             ret
  608. cursor_keys     endp
  609.  
  610. ;-----------------------------------------------------------------------------
  611. ; PASTE  Clears the keyboard buffer, then copys the sum into the buffer.
  612. ; Entry: SI - Points to ASCIIZ string to paste into keyboard buffer.
  613. ;-----------------------------------------------------------------------------
  614. paste        proc    near
  615.         push    es
  616.             mov     di,offset command_tail  ;Point buffer
  617.         mov    si,offset sum_num
  618.         push    di
  619.             call    hex2asc            ;Convert sum to ASCII
  620.         pop    si
  621.         inc    si            ;Move past attribute
  622.         mov    cx,di            ;Compute length of number
  623.         sub    cx,si
  624.  
  625.         cmp    sum_overflow,0
  626.         jne    paste_exit
  627.         mov    ax,bios_data
  628.         mov    es,ax
  629.         assume    es:bios_data
  630.         cli                ;No interrupts
  631.         mov    di,es:[keybuff_start]    ;Get ptr to buffer offset
  632.         mov    bx,es:[keybuff_end]    ;Get ptr to end of buffer
  633.         push    bx
  634.         sub    bx,di
  635.         shr    bx,1
  636.         cmp    cx,bx
  637.         pop    bx
  638.         ja    paste_overflow
  639.         sub    bx,2
  640.         mov    es:[keybuff_head],di    ;Clear buffer by setting
  641.         mov    es:[keybuff_tail],di    ;  pointers equal.
  642. paste_1:
  643.         lodsb                ;Get character
  644.         or    al,al            ;See if end of string
  645.         je    paste_done
  646. paste_2:
  647.         call    getscan            ;Get scan code for char
  648.         stosw                ;Stuff in keyboard buffer
  649.         cmp    di,bx            ;See if buffer full
  650.         jb    paste_1            ;No, continue
  651.         mov    es:[keybuff_tail],di
  652. paste_overflow:
  653.         sti
  654.         mov    si,offset pastemsg    ;If number longer than the
  655.         mov    dx,39            ;  keyboard buffer print
  656.         mov     ah,negative_attr    ;  message to warn user.
  657.         call    writestr1
  658.         call    getkey
  659. paste_done:
  660.         mov    es:[keybuff_tail],di    
  661.         sti
  662. paste_exit:
  663.         pop    es
  664.         ret
  665. paste        endp
  666.  
  667. ;-----------------------------------------------------------------------------
  668. ; GETSCAN  Returns the keyboard scan code for a limit set of ASCII characters
  669. ; Entry: AL - ASCII character
  670. ; Exit:  AH - Scan code
  671. ;-----------------------------------------------------------------------------
  672. xlate_keys    db    27,"1234567890-,."
  673. xlate_keys_end    =    $
  674. xlate_scan    db    52,51,12,11,10,9,8,7,6,5,4,3,2,1 ;Rev of ASCII table
  675. getscan        proc    near
  676.         push    di
  677.         push    es
  678.         mov    cx,cs
  679.         mov    es,cx
  680.         mov    cx,offset xlate_keys_end - offset xlate_keys
  681.         mov    di,offset xlate_keys
  682.         repne    scasb
  683.         mov    di,cx
  684.         mov    ah,[xlate_scan+di]
  685.         pop    es
  686.         pop    di
  687.         ret
  688. getscan        endp
  689.  
  690. ;-----------------------------------------------------------------------------
  691. ; DRAWMARKED  Displays the marked area by changing the screen attributes
  692. ;             inside the marked area.
  693. ;-----------------------------------------------------------------------------
  694. drawmarked      proc    near
  695.             push    es
  696.  
  697.             mov     ax,marked_pos1
  698.             mov     dx,marked_pos2
  699.             cmp     dx,oldmarked_pos2
  700.             jne     drawmarked_1
  701.  
  702.             cmp     ax,oldmarked_pos1
  703.             je      drawmarked_exit
  704. drawmarked_1:
  705.             mov     bx,offset marked_pos1
  706.             mov     cx,4
  707. drawmarked_2:
  708.             call    find_min                ;AX = upper left corner
  709.             call    find_max                ;DX = lower right corner
  710.             add     bx,2
  711.             loop    drawmarked_2
  712. drawmarked_7:
  713.             sub     dx,ax                   ;Compute size of area
  714.  
  715.             xor     cx,cx
  716.             mov     cl,dl                   ;Copy column count
  717.             mov     si,cx
  718.             inc     si
  719.             mov     cl,dh                   ;Copy row count
  720.             inc     cx
  721.             mov     dx,ax                   ;Copy starting row, column
  722. drawmarked_8:
  723.             push    cx                      ;Save row count
  724.             push    dx                      ;Save cursor position
  725.             mov     cx,si                   ;Get column count
  726. drawmarked_9:
  727.             mov     bx,offset marked_pos1
  728.             call    chk_inwin
  729.             mov     ah,al                   ;Save in marked area flag
  730.     
  731.             mov     bx,offset oldmarked_pos1
  732.             call    chk_inwin
  733.  
  734.             cmp     ah,al                   ;See if in or out of both
  735.             je      drawmarked_11           ;  areas. If so, no change.
  736.  
  737.             push    ax                      ;Save in-window flags
  738.             call    getchar
  739.             pop     bx
  740.             or      bh,bh                   ;See if in marked area
  741.             je      drawmarked_10
  742.  
  743.             mov     ah,marked_attr        ;Mark character
  744.             call    putchar
  745.  
  746.             jmp     short drawmarked_11
  747. drawmarked_10:
  748.         call    get_attr        ;Get saved screen attribute
  749.             call    putchar            ;Restore attribute
  750. drawmarked_11:
  751.             inc     dl
  752.             loop    drawmarked_9
  753.  
  754.             pop     dx
  755.             pop     cx
  756.             inc     dh
  757.             loop    drawmarked_8
  758.  
  759.             mov     ax,marked_pos1          ;Update old pointers
  760.             mov     oldmarked_pos1,ax
  761.             mov     ax,marked_pos2
  762.             mov     oldmarked_pos2,ax
  763. drawmarked_exit:
  764.             pop     es
  765.             ret
  766. drawmarked      endp
  767.  
  768. ;-----------------------------------------------------------------------------
  769. ; CLEARMARKED  Restores the marked area to its original screen attributes
  770. ;-----------------------------------------------------------------------------
  771. clearmarked     proc    near
  772.             assume  ds:code
  773.             mov     bx,offset marked_pos1
  774.             call    compute_box
  775.             sub     ax,dx
  776.             xor     cx,cx
  777.             mov     cl,al
  778.             mov     si,cx                   ;Save column count
  779.             inc     si
  780.             mov     cl,ah
  781.             inc     cx
  782. clearmarked_3:
  783.             push    cx
  784.             push    dx
  785.             mov     cx,si
  786. clearmarked_4:
  787.             call    getchar
  788.         call    get_attr        ;Get saved screen attribute
  789.             call    putchar
  790.             inc     dl
  791.             loop    clearmarked_4
  792.  
  793.             pop     dx
  794.             pop     cx
  795.             inc     dh
  796.             loop    clearmarked_3
  797. clearmarked_exit:
  798.             ret
  799. clearmarked     endp
  800.  
  801. ;-----------------------------------------------------------------------------
  802. ; ADDMARKED  Finds numbers in marked area, marks them, then sums them.
  803. ;-----------------------------------------------------------------------------
  804. addmarked       proc    near
  805.             assume  ds:code
  806.  
  807.             mov     si,offset sum_num       ;Zero sum
  808.             call    clear_number
  809.             mov     di,si
  810.             mov     si,offset curr_num      ;Zero current number
  811.             call    clear_number
  812.  
  813.             xor     al,al
  814.             mov     decimal_flag,al         ;Zero other flags
  815.             mov     sum_overflow,al
  816.             mov     curr_sign,al
  817.             mov     curr_num_active,al
  818.  
  819.             mov     bx,offset marked_pos1   ;Compute dim of marked box
  820.             call    compute_box
  821.             sub     ax,dx                   ;Compute size of box
  822.             xor     cx,cx
  823.             mov     cl,al
  824.             inc     cx
  825.             mov     bp,cx                   ;BP = column count
  826.             mov     cl,ah
  827.             inc     cx                      ;CX = row count
  828. addmarked_loop1:
  829.             push    cx
  830.             push    dx
  831.             mov     cx,bp                   ;Get column count
  832. addmarked_loop2:
  833.             push    cx
  834.             call    getchar                 ;Read char from screen
  835.             call    isnum                   ;See if character is a number
  836.         mov    bl,ch
  837.         mov    bh,ch
  838.         xchg    last_char,bh        ;Change routine called 
  839.         or    bh,bh            ;  depending on if the 
  840.         je    addmarked_3        ;  pervious char was a digit.
  841.         add    bl,5
  842. addmarked_3:
  843.         xor    bh,bh
  844.         shl    bx,1
  845.         push    ax
  846.         call    [addmarked_tbl+bx]
  847.         pop    ax
  848.             cmp     curr_num_active,0       ;See if we need to mark the
  849.         je    addmarked_4        ;  character
  850.         call    marknum
  851. addmarked_4:
  852.             pop     cx
  853.             inc     dl                      ;Inc Column
  854.             loop    addmarked_loop2
  855.  
  856.             call    termnumber        ;Number ends at boundry
  857.             pop     dx
  858.             pop     cx
  859.             inc     dh                      ;Inc Row
  860.             loop    addmarked_loop1
  861.             inc     boxactive               ;Force box to be redrawn
  862. addmarked_exit:
  863.             ret
  864. addmarked       endp
  865.  
  866. ;-----------------------------------------------------------------------------
  867. ; ADDDIGIT Adds digit to current number
  868. ; Entry:  SI - Pointer to current number
  869. ;         DI - Pointer to sum number
  870. ;-----------------------------------------------------------------------------
  871. add_digit    proc    near
  872.             mov     bl,decimal_flag         ;If sign or fraction flags set
  873.             add     bl,curr_sign            ;  back up to mark the leading
  874.             je      add_digit_1        ;  characters
  875.             call    markprev                ;Mark preceding char
  876. add_digit_1:
  877.             inc     curr_num_active         ;Digit found
  878.             mov     bx,base
  879.             call    mul_number              ;Multiply number by BASE
  880.             jo      add_digit_3
  881.  
  882.             cmp     decimal_flag,0          ;If in fraction, inc exponent
  883.             je      add_digit_2
  884.             inc     curr_exp
  885. add_digit_2:
  886.             add     [si],cx                 ;Add new digit to number
  887.             adc     word ptr [si+2],0
  888.             adc     word ptr [si+4],0
  889.             jno     short add_digit_exit
  890. add_digit_3:
  891.             inc     sum_overflow            ;Set overflow flag
  892. add_digit_exit:
  893.         ret
  894. add_digit    endp
  895.  
  896. ;-----------------------------------------------------------------------------
  897. ; SETDEC Process decimal point after character
  898. ; Entry:  SI - Pointer to current number
  899. ;         DI - Pointer to sum number
  900. ;-----------------------------------------------------------------------------
  901. setdec        proc    near
  902.         cmp    decimal_flag,0        ;If decimal flag already found
  903.         je    setdec_1        ;  the period terminates the
  904.         call    termnumber            ;  current number.
  905.         jmp    short setdec_exit
  906. setdec_1:
  907.         mov    decimal_flag,1        ;  current number.
  908. setdec_exit:
  909.         ret
  910. setdec        endp
  911.  
  912. ;-----------------------------------------------------------------------------
  913. ; CHKCOMMA Process commas
  914. ; Entry:  SI - Pointer to current number
  915. ;         DI - Pointer to sum number
  916. ;-----------------------------------------------------------------------------
  917. chkcomma    proc    near
  918.         cmp    decimal_flag,0        ;If decimal flag already found
  919.         je    chkcomma_exit        ;  the comma terminates the
  920.         call    termnumber            ;  current number.
  921. chkcomma_exit:
  922.         ret
  923. chkcomma    endp
  924.  
  925. ;-----------------------------------------------------------------------------
  926. ; SETNEG Process dash after character
  927. ;-----------------------------------------------------------------------------
  928. setneg        proc    near
  929.         call    termnumber        ;If num active, terminate it
  930. setneg1:
  931.             mov     curr_sign,1             ;Set sign bit.
  932.         ret
  933. setneg        endp
  934.  
  935. ;-----------------------------------------------------------------------------
  936. ; TERMNUMBER Process character after character
  937. ; Entry:  SI - Pointer to current number
  938. ;         DI - Pointer to sum number
  939. ;-----------------------------------------------------------------------------
  940. termnumber    proc    near
  941.             cmp     curr_num_active,0       ;See if a number is active
  942.             je      termnum_clear
  943.  
  944.             push    di                      ;Save original pointers
  945.             push    si
  946.             mov     al,[di+6]               ;Get destination exponent
  947.             sub     al,[si+6]               ;Compare to source exponent
  948.             je      termnum_2               ;If equal power, skip shift.
  949.             ja      termnum_1               ;If dest exp less, shift
  950.             xchg    si,di                   ;  destination instead of
  951.             neg     al                      ;  the source.
  952. termnum_1:
  953.             add     [si+6],al               ;Change exponent
  954.             xor     ah,ah
  955.             mov     cx,ax
  956.             mov     bx,base
  957. termnum_11:
  958.             call    mul_number              ;Mul number by the base
  959.             jo      termnum_2               ;  raised to the power of the
  960.             loop    termnum_11              ;  of the exponent.
  961. termnum_2:
  962.             pop     si                      ;Restore original pointers
  963.             pop     di
  964.             jo      termnum_overflow
  965.  
  966.         call    add_number        ;Add numbers together
  967.             jno     termnum_3
  968. termnum_overflow:
  969.             inc     sum_overflow        ;Set overflow flag
  970. termnum_3:
  971.             call    clear_number            ;Zero current number
  972. termnum_clear:
  973.             xor    al,al            
  974.             mov     curr_num_active,al      ;Terminate number
  975.             mov     decimal_flag,al         ;Zero fraction flag
  976.             mov     curr_sign,al            ;Clear sign
  977. termnum_exit:
  978.             ret
  979. termnumber    endp
  980.  
  981. ;-----------------------------------------------------------------------------
  982. ; ISNUM - Determines if a character is a number, a break character, or a
  983. ;         character to be ignored
  984. ; Entry:  AL - character
  985. ; Exit:   CL - Number, if character is a number
  986. ;         CH - 0 if number, 1 if decimal point, 2 if comma, 3 if a dash,
  987. ;              4 if anything else.
  988. ;-----------------------------------------------------------------------------
  989. isnum           proc    near
  990.             mov     ch,3                    ;Use AH as char type flag
  991.             mov     cl,al
  992.             cmp     cl,'-'                  ;Is char a dash?
  993.             je      isnum_1
  994.             dec     ch
  995.             cmp     cl,','                  ;Is char a comma?
  996.             je      isnum_1
  997.             dec     ch
  998.             cmp     cl,'.'                  ;Is char a decimal point?
  999.             je      isnum_1
  1000.             dec     ch
  1001.             sub     cl,'0'                  ;Convert char to number
  1002.             jb      isnum_no
  1003.             cmp     cl,9
  1004.             ja      isnum_no
  1005. isnum_1:
  1006.             clc
  1007. isnum_exit:
  1008.             ret
  1009. isnum_no:
  1010.             mov    ch,4
  1011.             jmp     short isnum_exit
  1012. isnum           endp
  1013.  
  1014. ;-----------------------------------------------------------------------------
  1015. ; MARKNUM - Sets the attribute of a number on the screen
  1016. ; Entry:    AL - character on screen
  1017. ;        DH,DL - Current row/column
  1018. ;-----------------------------------------------------------------------------
  1019. marknum         proc    near
  1020.             mov     ah,number_attr          ;Change attribute to indicate
  1021.             cmp     curr_sign,0             ;  that a number has been
  1022.             je      marknum_1               ;  found.
  1023.             mov     ah,negative_attr
  1024. marknum_1:
  1025.             call    putchar                 ;Write attribute
  1026.             ret
  1027. marknum         endp
  1028.  
  1029. ;-----------------------------------------------------------------------------
  1030. ; MARKPREV - Sets the attribute of the character before the current char
  1031. ; Entry:     BL - Number of prev characters to mark
  1032. ;         DH,DL - Current row/column
  1033. ;-----------------------------------------------------------------------------
  1034. markprev        proc    near
  1035.             dec     dl                      ;Back up and read prev char
  1036.             dec     bl                      ;Recursively call markprev
  1037.             je      markprev_1              ;  to mark the proper number
  1038.             call    markprev                ;  of characters.
  1039. markprev_1:
  1040.             push    ax
  1041.             call    getchar
  1042.             call    marknum                 ;Mark char
  1043.             inc     dl                      ;Go back to original char
  1044.             pop     ax
  1045.             ret
  1046. markprev        endp
  1047.  
  1048. ;-----------------------------------------------------------------------------
  1049. ; MULNUMBER - Multiplys a number pointed to by SI by the number in BX
  1050. ; Entry:  SI pointer to number
  1051. ;         BX number
  1052. ; Exit:   OF - set if overflow
  1053. ;-----------------------------------------------------------------------------
  1054. mul_number      proc    near
  1055.             push    ax
  1056.         push    dx
  1057.             mov     ax,[si+4]
  1058.             imul    bx                      ;Mul upper word
  1059.             jo      mulnum_exit
  1060.             mov     [si+4],ax
  1061.  
  1062.             mov     ax,[si+2]
  1063.             mul     bx                      ;Mul mid word
  1064.             add     [si+4],dx
  1065.             jo      mulnum_overflow
  1066.             mov     [si+2],ax
  1067.  
  1068.             mov     ax,[si]
  1069.             mul     bx                      ;Mul lower word
  1070.             add     [si+2],dx
  1071.             adc     word ptr [si+4],0
  1072.             jo      mulnum_overflow
  1073.             mov     [si],ax
  1074.             clc
  1075. mulnum_exit:
  1076.         pop    dx
  1077.             pop     ax
  1078.             ret
  1079. mulnum_overflow:
  1080.             stc
  1081.             jmp     short mulnum_exit
  1082. mul_number      endp
  1083.  
  1084. ;-----------------------------------------------------------------------------
  1085. ; ADDNUMBER - Adds two numbers pointed to by SI and DI
  1086. ; Entry:  SI pointer to first number
  1087. ;         DI pointer to second number
  1088. ; Exit:   OF - set if overflow
  1089. ;-----------------------------------------------------------------------------
  1090. add_number      proc    near
  1091.             cmp     curr_sign,0             ;If the source is negitive,
  1092.             je      addnum_1                ;  2's compliment the number.
  1093.             call    neg_number
  1094. addnum_1:
  1095.         push    si
  1096.             lodsw                ;Get low source word
  1097.             add     [di],ax                 ;Add to dest low word
  1098.             lodsw                ;Get mid source word
  1099.         adc    [di+2],ax
  1100.             lodsw                ;Get high source word
  1101.             adc     [di+4],ax               ;Add to dest high word
  1102.         pop    si
  1103.         ret
  1104. add_number      endp
  1105.  
  1106. ;-----------------------------------------------------------------------------
  1107. ; NEGNUMBER - Performs a two'w compliment on the number
  1108. ; Entry:  SI pointer to number structure
  1109. ;-----------------------------------------------------------------------------
  1110. neg_number    proc    near
  1111.             not     word ptr [si]           ;2's compliment the number
  1112.             not     word ptr [si+2]
  1113.             not     word ptr [si+4]
  1114.             xor     ax,ax
  1115.             stc
  1116.             adc     word ptr [si],ax
  1117.             adc     word ptr [si+2],ax
  1118.             adc     word ptr [si+4],ax
  1119.         ret
  1120. neg_number    endp
  1121.  
  1122. ;-----------------------------------------------------------------------------
  1123. ; CLRNUMBER - Clears the a number
  1124. ; Entry:  SI pointer to number structure
  1125. ;-----------------------------------------------------------------------------
  1126. clear_number    proc    near
  1127.         push    ax
  1128.         push    di
  1129.         mov    di,si
  1130.             xor     ax,ax
  1131.         stosw                ;Clear low word
  1132.         stosw                ;Clear mid word
  1133.         stosw                ;Clear high word
  1134.         stosw                ;Clear flags
  1135.         pop    di
  1136.         pop    ax
  1137.         ret
  1138. clear_number    endp
  1139.  
  1140. ;-----------------------------------------------------------------------------
  1141. ; GET ATTR  Gets a saved attribute in the attribute buffer for a given 
  1142. ;           cursor location.
  1143. ; Entry:  DX - Row, Column of character
  1144. ; Exit:   AH - Attribute
  1145. ;-----------------------------------------------------------------------------
  1146. get_attr    proc    near
  1147.         push    cx
  1148.         push    dx
  1149.         push    si
  1150.         push    ax
  1151.         call    compute_offset        ;Get count into buffer
  1152.         mov    si,ATTR_BUFFER
  1153.         xor    ax,ax
  1154.         mov    dx,ax
  1155. get_attr_1:
  1156.         lodsb                ;Get count byte
  1157.         inc    si
  1158.         or    al,al
  1159.         je    get_attr_exit
  1160.         sub    cx,ax
  1161.         jae    get_attr_1
  1162.         mov    dh,[si-1]        ;Get attribute
  1163. get_attr_exit:
  1164.         pop    ax
  1165.         mov    ah,dh            ;Copy attribute
  1166.         pop    si
  1167.         pop    dx
  1168.         pop    cx
  1169.         ret
  1170. get_attr    endp
  1171.  
  1172. ;-----------------------------------------------------------------------------
  1173. ; INIT ATTRLIST  Initializes the attribute list
  1174. ;-----------------------------------------------------------------------------
  1175. init_attrlist    proc    near
  1176.             assume  ds:code
  1177.         mov    bx,screen_size        ;Get size of screen
  1178.         inc    bh
  1179.         inc    bh
  1180.         xor    ax,ax
  1181.         mov    dx,ax            ;Start at top left corner
  1182.         mov    cx,ax
  1183.         xchg    bh,cl            ;CX-Col count, BX-Row cnt
  1184.         mov    si,bx
  1185.         mov    di,ATTR_BUFFER        ;Get pointer to buffer
  1186.         call    getchar
  1187.         mov    bh,ah
  1188.         mov    bl,0
  1189. init_attrlist_1:
  1190.         push    cx
  1191.         push    dx
  1192.         mov    cx,si            ;Get number of columns
  1193. init_attrlist_2:
  1194.         call    getchar         ;Read attribute
  1195.         cmp    bh,ah            ;Compare attributes
  1196.         jne    init_attrlist_newblk    ;If different write block
  1197.         inc    bl            ;Incriment count
  1198.         cmp    bl,-1            ;If count full, write block
  1199.         je    init_attrlist_newblk
  1200.         mov    bh,ah            ;Copy attribute value
  1201. init_attrlist_3:
  1202.         inc    dl            ;Next column
  1203.         loop    init_attrlist_2
  1204.         pop    dx
  1205.         pop    cx
  1206.         inc    dh            ;Next row
  1207.         loop    init_attrlist_1
  1208.         clc
  1209. init_attrlist_exit:
  1210.             ret
  1211. init_attrlist_newblk:
  1212.         mov    ds:[di],bx        ;Write old block to list
  1213.         inc    di            ;Update ptr
  1214.         inc    di
  1215.         mov    bl,1            ;New count
  1216.         mov    bh,ah            ;Copy new attribute 
  1217.         cmp    di,helpbox_buff
  1218.         jb    init_attrlist_3        ;If list runs into the help
  1219.         inc    no_help            ;  buffer, disable help
  1220.         push    ax
  1221.         mov    ax,helpbox_buff        ;If past helpbox buffer, exit
  1222.         add    ax,HELPBOX_BUFFSIZE
  1223.         cmp    di,ax
  1224.         pop    ax
  1225.         jb    init_attrlist_3        ;If list past help box
  1226.         stc                        ;  buffer, exit prog.
  1227.         jmp    short init_attrlist_exit
  1228. init_attrlist    endp
  1229.  
  1230. ;-----------------------------------------------------------------------------
  1231. ; COMPUTE OFFSET  Computes the offset into the attribute buffer for a
  1232. ;                 given cursor location.
  1233. ; Entry:  DX - Row, Column of character
  1234. ; Exit:   CX - Offset in buffer.
  1235. ;-----------------------------------------------------------------------------
  1236. compute_offset  proc    near
  1237.             push    ax
  1238.         push    dx
  1239.             mov     al,dh                   ;Copy column
  1240.             mul     screen_cx               ;Mul by width of screen
  1241.             xor     dh,dh
  1242.             add     ax,dx                   ;Add row
  1243.         xchg    cx,ax
  1244.         pop    dx
  1245.             pop     ax
  1246.             ret
  1247. compute_offset  endp
  1248.  
  1249. ;-----------------------------------------------------------------------------
  1250. ; CHK INWIN  Determines if a character is inside the bounds of an area
  1251. ; Entry:  BX - Pointer to bounding rectangle
  1252. ;           x1  db  point 1 column
  1253. ;           y1  db  point 1 row
  1254. ;           x2  db  point 2 column
  1255. ;           y2  db  point 2 row
  1256. ;         DX - Row, Column of character
  1257. ; Exit:   AL - <> 0 if inside area
  1258. ;-----------------------------------------------------------------------------
  1259. chk_inwin       proc    near
  1260.             push    bx
  1261.             push    cx
  1262.  
  1263.             push    ax                      ;Save AX
  1264.             push    dx                      ;Save current cursor pos
  1265.             call    compute_box             ;DX = UL corner, AX = LR corner
  1266.             pop     bx
  1267.             xchg    bx,dx                   ;DX = cur cursor, BX=UL corner
  1268.             mov     cx,ax                   ;CX = LR corner
  1269.             pop     ax                      ;Restore AX
  1270.  
  1271.             mov     al,0                    ;Clear inbox flag
  1272.  
  1273.             cmp     dl,bl                   ;See if above starting row
  1274.             jb      chk_inwin_exit
  1275.             cmp     dh,bh                   ;See if left of starting col
  1276.             jb      chk_inwin_exit
  1277.  
  1278.             cmp     dl,cl                   ;See if below ending row
  1279.             ja      chk_inwin_exit
  1280.             cmp     dh,ch                   ;See if right of ending col
  1281.             ja      chk_inwin_exit
  1282.             inc     al
  1283. chk_inwin_exit:
  1284.             pop     cx
  1285.             pop     bx
  1286.             ret
  1287. chk_inwin       endp
  1288.  
  1289. ;-----------------------------------------------------------------------------
  1290. ; FIND MIN  Computes the smaller of two screen coordinates.
  1291. ; Entry:  AX - Row, Column of 1st coordinate
  1292. ;         BX - Pointer to 2nd coordinate
  1293. ; Exit:   AX - Result coordinate.
  1294. ;-----------------------------------------------------------------------------
  1295. find_min        proc    near
  1296.             cmp     al,[bx]
  1297.             jbe     find_min_1
  1298.             mov     al,[bx]
  1299. find_min_1:
  1300.             cmp     ah,[bx+1]
  1301.             jbe     find_min_2
  1302.             mov     ah,[bx+1]
  1303. find_min_2:
  1304.             ret
  1305. find_min        endp
  1306.  
  1307. ;-----------------------------------------------------------------------------
  1308. ; FIND MAX  Computes the larger of two screen coordinates.
  1309. ; Entry:  DX - Row, Column of 1st coordinate
  1310. ;         BX - Pointer to 2nd coordinate
  1311. ; Exit:   AX - Result coordinate.
  1312. ;-----------------------------------------------------------------------------
  1313. find_max        proc    near
  1314.             cmp     dl,[bx]
  1315.             jae     find_max_1
  1316.             mov     dl,[bx]
  1317. find_max_1:
  1318.             cmp     dh,[bx+1]
  1319.             jae     find_max_2
  1320.             mov     dh,[bx+1]
  1321. find_max_2:
  1322.             ret
  1323. find_max        endp
  1324.  
  1325. ;-----------------------------------------------------------------------------
  1326. ; COMPUTE BOX  Puts the starting row/column in DX and the SI and CX
  1327. ; Entry:  BX - Pointer to coordinates
  1328. ; Exit:   AX - Ending row/column
  1329. ;         DX - Starting row/column
  1330. ;-----------------------------------------------------------------------------
  1331. compute_box     proc    near
  1332.             mov     ax,[bx]
  1333.             mov     dx,[bx+2]
  1334.  
  1335.             cmp     al,dl
  1336.             ja      compute_box_1
  1337.             xchg    al,dl
  1338. compute_box_1:
  1339.             cmp     ah,dh
  1340.             ja      compute_box_2
  1341.             xchg    ah,dh
  1342. compute_box_2:
  1343.             ret
  1344. compute_box     endp
  1345.  
  1346. ;-----------------------------------------------------------------------------
  1347. ; SHOWHELP  Displays a help screen on the first three lines of the display
  1348. ;-----------------------------------------------------------------------------
  1349. showhelp        proc    near
  1350.         cmp    byte ptr no_help,0    ;See if help msg disabled.
  1351.         jne    showhelp_exit
  1352.             mov     dh,1                    ;Box at top of screen
  1353.             mov     cx,5
  1354.             mov     di,helpbox_buff
  1355. showhelp_1:
  1356.             push    cx
  1357.             call    saveline
  1358.             inc     dh
  1359.             pop     cx
  1360.             loop    showhelp_1
  1361.  
  1362.             mov     dh,1
  1363.             mov     si,offset helpmsg1      ;Write help text line
  1364.             call    writeline
  1365.             inc     dh                      ;Move to next line
  1366.             mov     si,offset helpmsg2
  1367.             call    writeline
  1368.             inc     dh                      ;Move to next line
  1369.             mov     si,offset helpmsg3
  1370.             call    writeline
  1371.             inc     dh                      ;Move to next line
  1372.             mov     si,offset helpmsg4
  1373.             call    writeline
  1374.             inc     dh                      ;Move to next line
  1375.             mov     si,offset helpmsg5
  1376.             call    writeline
  1377.  
  1378.         call    getkey            ;Wait for a key
  1379.             mov     dh,1                    ;Box at top of screen
  1380.             mov     cx,5
  1381.             mov     si,helpbox_buff
  1382. showhelp_2:
  1383.             push    cx
  1384.             call    restoreline
  1385.             inc     dh
  1386.             pop     cx
  1387.             loop    showhelp_2
  1388. showhelp_exit:
  1389.             ret
  1390. showhelp        endp
  1391.  
  1392. ;-----------------------------------------------------------------------------
  1393. ; MSGBOX  displays a message in a text window on the top line of the
  1394. ;         screen.  The current data on the screen is saved.
  1395. ;
  1396. ; Entry:  DS:SI - Pointer to string to display.
  1397. ;-----------------------------------------------------------------------------
  1398. msgbox          proc    near
  1399.             mov     dh,0                    ;Box at top of screen
  1400.         mov    al,boxactive
  1401.             cmp     al,2                 ;Display sum only
  1402.             je      msgbox_1
  1403.             or      al,al                  ;If box already displayed,
  1404.             jne     msgbox_1                ;  don't save screen data.
  1405.             mov     di,MSGBOX_BUFFER
  1406.             call    saveline
  1407. msgbox_1:
  1408.         mov    si,offset program1
  1409.         mov    cx,offset program2 - offset program1
  1410.         xor    dx,dx
  1411. msgbox_11:
  1412.         lodsb
  1413.         call    writechar
  1414.         loop    msgbox_11
  1415.         push    dx
  1416. msgbox_12:
  1417.             mov     al,' '                  ;Pad line with spaces
  1418.             call    writechar
  1419.             cmp     dl,screen_cx
  1420.             jb      msgbox_12
  1421.         pop    dx
  1422.  
  1423.         add    dl,6
  1424.         mov    si,offset summsg
  1425.         call    writestr
  1426.         mov    dl,screen_cx
  1427.         sub    dl,12
  1428.         mov    si,offset helptag
  1429.         call    writestr
  1430. msgbox_2:
  1431.         mov    ah,text_attr
  1432.         mov    si,offset overflowmsg    ;Assume overflow
  1433.             cmp     sum_overflow,0
  1434.             jne     msgbox_error
  1435.             mov     di,offset command_tail  ;Point to num and print
  1436.         mov    si,offset sum_num
  1437.         push    di
  1438.             call    hex2asc            ;Convert number to ASCII
  1439.         pop    si
  1440.         lodsb                ;Get attribute for number
  1441.         mov    ah,al
  1442. msgbox_error:
  1443.             mov     dl,44
  1444.         call    writestr1        ;Write number or overflow
  1445. msgbox_3:
  1446.             mov     boxactive,1             ;Set box active flag
  1447.             ret
  1448. msgbox          endp
  1449.  
  1450. ;-----------------------------------------------------------------------------
  1451. ; CLEARBOX  removes the title box from the screen.
  1452. ;-----------------------------------------------------------------------------
  1453. clearbox        proc    near
  1454.             cmp     boxactive,0             ;If box already displayed,
  1455.             je      clearbox_2              ;  don't save screen data.
  1456.             mov     si,MSGBOX_BUFFER
  1457.             mov     dh,0                    ;Box at top of screen
  1458.             call    restoreline
  1459.             mov     boxactive,0             ;Clear box displayed flag
  1460. clearbox_2:
  1461.             ret
  1462. clearbox        endp
  1463.  
  1464. ;-----------------------------------------------------------------------------
  1465. ; WRITELINE  Writes a line of help text to the screen.  The line is padded
  1466. ;            with spaces to the right.
  1467. ; Entry: DH - Line on screen to write
  1468. ;        SI - Pointer to ASCIIZ text
  1469. ;-----------------------------------------------------------------------------
  1470. writeline       proc    near
  1471.             push    dx
  1472.             xor     dl,dl                   ;Start at left side of screen
  1473.             call    writestr                ;Write string
  1474. writeline_2:
  1475.             mov     al,' '                  ;Pad line with spaces
  1476.             call    writechar
  1477.             cmp     dl,screen_cx
  1478.             jb      writeline_2
  1479.             pop     dx
  1480.             ret
  1481. writeline       endp
  1482.  
  1483. ;-----------------------------------------------------------------------------
  1484. ; SAVELINE  Saves the contents of a screen line ot a buffer
  1485. ; Entry: DH - Line on screen to save
  1486. ;        DI - Pointer to save buffer
  1487. ;-----------------------------------------------------------------------------
  1488. saveline        proc    near
  1489.             push    dx
  1490.             xor     dl,dl                   ;Start at left side of screen
  1491.             xor     cx,cx
  1492.             mov     cl,screen_cx
  1493. saveline_1:
  1494.             call    getchar                 ;Read character from screen
  1495.             stosw
  1496.             inc     dl                      ;Point to next character
  1497.             loop    saveline_1
  1498.             pop     dx
  1499.             ret
  1500. saveline        endp
  1501.  
  1502. ;-----------------------------------------------------------------------------
  1503. ; RESTORELINE  Restores the screen that was covered by a line of program
  1504. ;              helptext.
  1505. ; Entry: DH - Line on screen to restore
  1506. ;        SI - Pointer to buffer that contains original screen contents
  1507. ;-----------------------------------------------------------------------------
  1508. restoreline     proc    near
  1509.             push    dx
  1510.             xor     dl,dl                   ;Start at left side of screen
  1511.             xor     cx,cx
  1512.             mov     cl,screen_cx
  1513. restoreline_1:
  1514.             lodsw
  1515.             call    writechar1              ;Read character from screen
  1516.             loop    restoreline_1
  1517.             pop     dx
  1518.             ret
  1519. restoreline     endp
  1520.  
  1521. ;-----------------------------------------------------------------------------
  1522. ; WRITESTR  Writes a string to the screen.
  1523. ; Entry: DH,DL - Row/Column to write the string
  1524. ;        SI - Pointer to ASCIIZ text
  1525. ;-----------------------------------------------------------------------------
  1526. writestr        proc    near
  1527.             mov     ah,text_attr            
  1528. writestr1:
  1529.             lodsb                           ;Read text from string, then
  1530.             or      al,al                   ;  call putchar to write to
  1531.             je      writestr_1        ;  the screen.
  1532.             call    writechar1
  1533.             jmp     short writestr1
  1534. writestr_1:
  1535.             ret
  1536. writestr        endp
  1537.  
  1538. ;-----------------------------------------------------------------------------
  1539. ; WRITECHAR  Writes a character to the screen
  1540. ; Entry: AL - Character
  1541. ;        DX - Row, Column 
  1542. ;-----------------------------------------------------------------------------
  1543. writechar       proc    near
  1544.             mov     ah,text_attr
  1545. writechar1:
  1546.             call    putchar
  1547.             inc     dl
  1548.             ret
  1549. writechar       endp
  1550.  
  1551. ;-----------------------------------------------------------------------------
  1552. ; HEX2ASC converts number in DX AX to ASCII
  1553. ; Entry:  SI - Pointer to number
  1554. ;         DI - Pointer to buffer to store ASCII number
  1555. ;-----------------------------------------------------------------------------
  1556. hex2asc         proc near
  1557.             assume  ds:code,es:nothing
  1558.             push    bx
  1559.             push    cx
  1560.             push    si
  1561.             push    bp
  1562.         push    [si]            ;Save current number
  1563.         push    [si+2]
  1564.         push    [si+4]
  1565.  
  1566.         mov    al,number_attr        ;Save proper attribute
  1567.         stosb    
  1568.             test    byte ptr [si+5],80h     ;See if negative
  1569.             je      hex_1
  1570.         call    neg_number        ;Negate number
  1571.         dec    di
  1572.             mov     al,negative_attr        ;Change attribute to indicate
  1573.             mov     ah,'-'                  ;  negative number, then
  1574.             stosw               ;  print - sign.
  1575. hex_1:
  1576.             xor     cx,cx                   ;Clear digit counter
  1577. hex_loop1:
  1578.             xor     bx,bx                   ;BX used for zero test
  1579.             mov     ax,[si+4]               ;Get high word
  1580.             xor     dx,dx                   ;Clear high word
  1581.             div     base                    ;Divide by base
  1582.             mov     [si+4],ax
  1583.             or      bx,ax                   ;OR quotient for zero test
  1584.             mov     ax,[si+2]               ;Get mid word
  1585.             div     base                    ;Divide by base
  1586.             mov     [si+2],ax
  1587.             or      bx,ax                   ;OR quotient for zero test
  1588.             mov     ax,[si]                 ;Get low word
  1589.             div     base                    ;Divide by base
  1590.             mov     [si],ax
  1591.             or      bx,ax                   ;OR quotient for zero test
  1592.  
  1593.             add     dl,30h                  ;Convert to ascii
  1594.             push    dx                      ;Save digit on stack
  1595.             inc     cx                      ;Inc digit count
  1596.             or      bx,bx
  1597.             jne     hex_loop1               ;If number <> 0, continue.
  1598.  
  1599.             mov     bl,"0"                  ;Set leading zero flag
  1600.             mov     bh,3                    ;Get comma spacing constant
  1601.  
  1602.             mov     bp,cx                   ;Copy digit count
  1603.             xor     ax,ax
  1604.             mov     al,[si+6]               ;Subtract exponent to get
  1605.             sub     bp,ax                   ;  num of non-fraction digits
  1606.             jmp     short hex_2             ;Don't lead with a comma
  1607. hex_loop2:
  1608.             xor     ax,ax
  1609.             or      ax,bp                   ;Get number non-fract digits
  1610.             js      hex_4                   ;If count neg, inside fract
  1611.             div     bh                      ;If digit count a multiple
  1612.             or      al,al                   ;  of 3 insert comma.
  1613.             je      hex_2
  1614.             or      ah,ah
  1615.             jne     hex_2
  1616.             mov     al,','
  1617.             jmp     short hex_3
  1618. hex_2:
  1619.             or      bp,bp                   ;If position count zero
  1620.             jne     hex_4                   ;  insert decimal point.
  1621.             mov     al,'.'
  1622. hex_3:
  1623.         stosb                ;Copy char to buffer
  1624. hex_4:
  1625.             pop     ax                      ;Get digit off stack
  1626.             or      bl,al                   ;Don't print leading zeros.
  1627.             cmp     bl,"0"                  ;The first non zero will
  1628.             je      hex_5                   ;  change bl to non-zero.
  1629.         stosb
  1630. hex_5:
  1631.             dec     bp                      ;Dec current digit count
  1632.             loop    hex_loop2
  1633.             cmp     bl,"0"                  ;If number zero, write last
  1634.             jne     hex_exit                ;  zero.
  1635.             mov     al,bl
  1636.         stosb
  1637. hex_exit:
  1638.         xor    al,al            ;Terminate with 0
  1639.         stosb
  1640.         pop    [si+4]            ;Restore number
  1641.         pop    [si+2]
  1642.         pop    [si]
  1643.             pop     bp
  1644.             pop     si
  1645.             pop     cx
  1646.             pop     bx
  1647.             ret
  1648. hex2asc         endp
  1649.  
  1650. ;-----------------------------------------------------------------------------
  1651. ; GETCHAR  Reads a character and its attribute from the screen
  1652. ; Entry:  DH - Row of character to read
  1653. ;         DL - Column of character to read
  1654. ; Exit:   AL - Character
  1655. ;         AH - Attribute
  1656. ;-----------------------------------------------------------------------------
  1657. getchar         proc    near
  1658.             push    bx
  1659.         cmp    BIOSFlag,0
  1660.         jne    getchar_bios
  1661.         push    cx
  1662.         push    si
  1663.         push    ds
  1664.         call    compute_offset        ;Get offset into buffer
  1665.         shl    cx,1            ;Double for char and attr
  1666.         lds    si,video_ptr        ;Get ptr to video memory
  1667.         add    si,cx            ;Double since char and attr
  1668.         lodsw                ;Read char/attribute
  1669.         pop    ds
  1670.         pop    si
  1671.         pop    cx
  1672.         jmp    short getchar_exit
  1673. getchar_bios:
  1674.             mov     ah,2                    ;Set cursor
  1675.             mov     bh,screen_page
  1676.             int     10h
  1677.             mov     ah,8                    ;Read character/attr
  1678.             int     10h
  1679. getchar_exit:
  1680.             pop     bx
  1681.             ret
  1682. getchar         endp
  1683.  
  1684. ;-----------------------------------------------------------------------------
  1685. ; PUTCHAR  Writes a character and its attribute to the screen
  1686. ; Entry:  AL - Character to write
  1687. ;         AH - Attribute to write
  1688. ;         DH - Row of character to write
  1689. ;         DL - Column of character to write
  1690. ;-----------------------------------------------------------------------------
  1691. putchar         proc    near
  1692.             push    bx
  1693.             push    cx
  1694.             push    ax
  1695.         cmp    BIOSFlag,0
  1696.         jne    putchar_bios
  1697.         push    di
  1698.         push    es
  1699.         call    compute_offset        ;Get offset into buffer
  1700.         shl    cx,1             ;Double since char and attr
  1701.         les    di,video_ptr
  1702.         add    di,cx                  ;Add to start of buffer
  1703.         stosw                ;Read char/attribute
  1704.         pop    es
  1705.         pop    di
  1706.         jmp    short putchar_exit
  1707. putchar_bios:
  1708.             mov     ah,2                    ;Set cursor
  1709.             mov     bh,screen_page
  1710.             int     10h
  1711.             pop     ax
  1712.         push    ax
  1713.             mov     bl,ah                   ;Copy attribute
  1714.             mov     ah,9                    ;Read character/attr
  1715.             mov     cx,1
  1716.             int     10h
  1717. putchar_exit:
  1718.         pop    ax
  1719.             pop     cx
  1720.             pop     bx
  1721.             ret
  1722. putchar         endp
  1723.  
  1724. ;-----------------------------------------------------------------------------
  1725. ; GETKEY  Waits for a key from the keyboard.
  1726. ; Exit:   AX - Scan code, ASCII char from keyboard.
  1727. ;-----------------------------------------------------------------------------
  1728. getkey          proc    near
  1729.             mov     ah,1                    ;Check for key
  1730.             int     16h
  1731.             jnz     getkey_exit
  1732.             int     28h                     ;Call DOS Idle
  1733.         mov    ax,1680h        ;Release Timeslice
  1734.         int    2fh
  1735.             jmp     short getkey
  1736. getkey_exit:
  1737.             xor     ax,ax                   ;Get key
  1738.             int     16h
  1739.         ret
  1740. getkey          endp
  1741.             even                            ;Align stack on word boundry
  1742. end_of_resident =       $
  1743.  
  1744. ;----------------------------------------------------------------------------
  1745. ; Non-resident data.
  1746. ;----------------------------------------------------------------------------
  1747. alrdy_installed db      0                       ;Installed flag
  1748. installed_seg   dw      0                       ;Segment of installed code
  1749. dos_version     dw      0                       ;DOS version
  1750.  
  1751. patchcode    db    "AlLs"
  1752. ShiftCodes    db    "Rs","Ls","Al","Ct"    ;These codes are used by
  1753. ShiftText    db    "Ctrl",0        ;  PATCH.COM for indicating
  1754.         db    "Alt",0            ;  Hot Shift combinations.  
  1755.         db    "Left-Shift",0
  1756.         db    "Right-Shift",0
  1757.  
  1758. infomsg2        db      "ADDIT uninstalled$"
  1759.  
  1760. errmsg0         db      "Need DOS 3.0 or greater$"
  1761. errmsg1         db      "ADDIT not installed$"
  1762. errmsg2         db      "Usage: ADDIT [/B][/U]",13,10
  1763.             db      "/B = Use Video BIOS",13,10
  1764.             db      "/U = Uninstall",13,10,"$"
  1765. errmsg3         db      "Can",39,"t uninstall$"
  1766. errmsg4         db      "ADDIT already installed$"
  1767. errmsg5         db      "Can not find Critical error flag$"
  1768. endmsg          db      13,10,"$"
  1769.  
  1770. infomsg1        db      "ADDIT installed",13,10,10
  1771.             db      "Hot key is "
  1772. infomsg1a    db    "$"
  1773.  
  1774. ;----------------------------------------------------------------------------
  1775. ; Initialization routine.
  1776. ;----------------------------------------------------------------------------
  1777. initialize      proc    near
  1778.             assume  cs:code,ds:code,es:code
  1779.             cld
  1780.             mov     dx,offset program       ;Print copyright message
  1781.             call    printmsgcr
  1782.  
  1783.             mov     ah,30h                  ;Get DOS version
  1784.             int     21h
  1785.             xchg    al,ah                   ;Swap major, minor numbers
  1786.             mov     dx,offset errmsg0       ;Bad DOS version
  1787.             cmp     ah,3                    ;Run if DOS 3.0 or greater.
  1788.             jb      disp_error
  1789.             mov     dos_version,ax          ;Save version number
  1790.  
  1791.             mov     ax,offset end_of_code+512       ;Set stack ptr
  1792.             mov     sp,ax
  1793.             add     ax,15
  1794.             mov     cl,4                    ;Convert offset to segment size
  1795.             shr     ax,cl
  1796.             mov     ah,4ah                  ;Reduce memory allocation
  1797.             int     21h
  1798.  
  1799.             call    find_installed        ;See if already installed
  1800.             jc      init_1
  1801.             inc     alrdy_installed        ;Yes, set flag
  1802.             mov     installed_seg,es        ;Save seg of installed code
  1803. init_1:
  1804.             push    ds
  1805.             pop     es
  1806.             mov     dx,offset errmsg4       ;Default message
  1807.             mov     di,80h            ;Parse command line
  1808.             xor     cx,cx
  1809.             or      cl,[di]                 ;Get length of cmd line
  1810.             je      init_exit
  1811. init_2:
  1812.             mov     al,'/'
  1813.             repne   scasb                   ;Find command line switches
  1814.             jne     init_exit
  1815.             mov     al,[di]                 ;Get comamnd line switch
  1816.             or      al,20h
  1817.             cmp     al,'b'                  ;See if Video BIOS parameter
  1818.             jne     init_3
  1819.             inc    BIOSFlag
  1820.             jmp     short init_2
  1821. init_3:
  1822.             cmp     al,'u'                  ;See if uninstall
  1823.             je    init_4
  1824.             mov     dx,offset errmsg2       ;Print useage statement
  1825. ;
  1826. ;Display error message.
  1827. ;
  1828.             assume  ds:nothing
  1829. disp_error:
  1830.             push    cs
  1831.             pop     ds
  1832.             assume  ds:code
  1833.             call    printmsgcr              ;print string
  1834.  
  1835.             mov     ax,4c01h                ;Terminate with RC = 1
  1836.             int     21h
  1837. init_4:
  1838.             call    remove                  ;Remove installed copy
  1839.             jc    disp_error
  1840.         jmp    short exit
  1841. init_exit:
  1842.             cmp     alrdy_installed,0
  1843.             jne     disp_error
  1844.             call    install
  1845.             jc      disp_error
  1846. exit:
  1847.             mov     ax,4C00h                ;Terminate with RC = 0
  1848.             int     21h
  1849. initialize      endp
  1850.  
  1851. ;-----------------------------------------------------------------------------
  1852. ; INSTALL Installs the program
  1853. ;-----------------------------------------------------------------------------
  1854.             assume  cs:code,ds:code,es:code
  1855. install         proc    near
  1856.             mov     ah,34h                  ;Get ptr to INDOS flag
  1857.             int     21h
  1858.             mov     word ptr indos_ptr,bx
  1859.             mov     word ptr indos_ptr[2],es
  1860.             call    findCEF                 ;Get ptr to crit error flag
  1861.             jc      install_error
  1862.             mov     word ptr criterr_ptr,bx
  1863.             mov     word ptr criterr_ptr[2],es
  1864.             mov     al,08h                  ;Get/set the timer interrupt
  1865.             mov     dx,offset timerint
  1866.             mov     di,offset int08h
  1867.             call    set_interrupt
  1868.             mov     al,09h                  ;Get/set the keyboard int
  1869.             mov     dx,offset keyint
  1870.             mov     di,offset int09h
  1871.             call    set_interrupt
  1872.             mov     al,10h                  ;Get/set the video interrupt
  1873.             mov     dx,offset videoint
  1874.             mov     di,offset int10h
  1875.             call    set_interrupt
  1876.             mov     al,13h                  ;Get/set the disk interrupt
  1877.             mov     dx,offset diskint
  1878.             mov     di,offset int13h
  1879.             call    set_interrupt
  1880.             mov     al,16h                  ;Get/set the BIOS keyboard 
  1881.             mov     dx,offset bioskeyint    ;  services int
  1882.             mov     di,offset int16h
  1883.             call    set_interrupt
  1884.             mov     al,28h                  ;Get/set the DOS idle int
  1885.             mov     dx,offset idleint
  1886.             mov     di,offset int28h
  1887.             call    set_interrupt
  1888.  
  1889.         push    cs
  1890.         push    cs
  1891.         pop    ds
  1892.         assume    ds:code
  1893.         pop    es
  1894.         assume    es:code
  1895.         call    setshiftmsg        ;Set proper install text
  1896.             mov     dx,offset infomsg1      ;Print program installed msg
  1897.             call    printmsgcr
  1898.  
  1899.         mov    dx,ATTR_BUFFER        ;Set pointers for resident
  1900.         add    dx,attr_buffsize    ;  code.
  1901.         mov    helpbox_buff,dx
  1902.         add    dx,HELPBOX_BUFFSIZE + 512
  1903.         mov    res_stack,dx
  1904.             add     dx,15
  1905.             mov     cl,4
  1906.             shr     dx,cl
  1907.             mov     ax,3100h                ;Terminate and stay resident
  1908.             int     21h
  1909. install_error:
  1910.             ret
  1911. install         endp
  1912.  
  1913. ;-----------------------------------------------------------------------------
  1914. ; REMOVE uninstalls the installed program from memory.
  1915. ;-----------------------------------------------------------------------------
  1916. remove          proc    near
  1917.             assume  ds:code,es:code
  1918.             push    ds
  1919.             push    es
  1920.  
  1921.             mov     dx,offset errmsg1       ;Not installed message
  1922.             cmp     alrdy_installed,0
  1923.             je      remove_error1
  1924.  
  1925.             mov     ds,installed_seg        ;Point DS to installed code
  1926.             assume  ds:nothing
  1927.  
  1928.             mov     al,8                    ;Restore int 8 (Timer)
  1929.             mov     dx,offset timerint
  1930.             mov     di,offset int08h
  1931.             call    restore_int
  1932.             jc      remove_error
  1933.             mov     al,9                    ;Restore int 9 (keyboard)
  1934.             mov     dx,offset keyint
  1935.             mov     di,offset int09h
  1936.             call    restore_int
  1937.             jc      remove_error
  1938.             mov     al,10h                  ;Restore int 10h (BIOS Video)
  1939.             mov     dx,offset videoint
  1940.             mov     di,offset int10h
  1941.             call    restore_int
  1942.             jc      remove_error
  1943.             mov     al,13h                  ;Restore int 13h (BIOS disk)
  1944.             mov     dx,offset diskint
  1945.             mov     di,offset int13h
  1946.             call    restore_int
  1947.             jc      remove_error
  1948.             mov     al,16h                  ;Restore int 16h (BIOS key)
  1949.             mov     dx,offset bioskeyint
  1950.             mov     di,offset int16h
  1951.             call    restore_int
  1952.             jc      remove_error
  1953.             mov     al,28h                  ;Restore int 28h (DOS Idle)
  1954.             mov     dx,offset idleint
  1955.             mov     di,offset int28h
  1956.             call    restore_int
  1957.             jc      remove_error
  1958.             mov     es,ds:[2ch]             ;Get installed env seg
  1959.             mov     ah,49h
  1960.             int     21h                     ;Free installed env segment
  1961.             push    ds
  1962.             pop     es
  1963.             mov     ah,49h                  ;Free installed program segment
  1964.             int     21h
  1965.             mov     ax,cs
  1966.             mov     ds,ax
  1967.             mov     es,ax
  1968.             mov     dx,offset infomsg2      ;Print program removed msg
  1969.             call    printmsgcr
  1970.             clc
  1971. remove_exit:
  1972.             pop     ds
  1973.             pop     es
  1974.             ret
  1975. remove_error:
  1976.             mov     dx,offset errmsg3       ;Can't uninstall msg
  1977. remove_error1:
  1978.             stc
  1979.             jmp     short remove_exit
  1980. remove          endp
  1981.  
  1982. ;-----------------------------------------------------------------------------
  1983. ; SETINTERRUPT Get and sets an interrupt
  1984. ; Entry: AL - Interrupt number
  1985. ;        DX - Pointer to new interrupt routine
  1986. ;        DI - Pointer to storage location for old interrupt vector
  1987. ;-----------------------------------------------------------------------------
  1988.             assume  cs:code,ds:code,es:nothing
  1989. set_interrupt   proc    near
  1990.             push    es
  1991.             push    ax
  1992.             mov     ah,35h                  ;DOS get interrupt
  1993.             int     21h
  1994.             pop     ax
  1995.             mov     word ptr [di],bx        ;Save old vector
  1996.             mov     word ptr [di+2],es
  1997.             mov     ah,25h                  ;DOS set interrupt
  1998.             int     21h
  1999.             pop     es
  2000.             ret
  2001. set_interrupt   endp
  2002.  
  2003. ;-----------------------------------------------------------------------------
  2004. ; RESTOREINT Checks to see if an interrupt vector has been changed, if not
  2005. ;            the interrupt vector is restored with its original value
  2006. ; Entry:    AL - Interrupt number
  2007. ;        DS:DX - Pointer to current interrupt routine
  2008. ;        DS:DI - Pointer to old interrupt vector
  2009. ;-----------------------------------------------------------------------------
  2010.             assume  cs:code,ds:nothing
  2011. restore_int     proc    near
  2012.             push    es
  2013.             push    ax
  2014.             mov     ah,35h                  ;DOS get interrupt
  2015.             int     21h
  2016.             pop     ax                      ;Get back interrupt number
  2017.             cmp     dx,bx                   ;Compare routine offset
  2018.             jne     restoreint_error
  2019.             mov     bx,es                   ;Get current vector segment
  2020.             mov     cx,ds                   ;Get installed segment
  2021.             cmp     cx,bx                   ;Compare routine segment
  2022.             jne     restoreint_error
  2023.             push    ds
  2024.             lds     dx,ds:[di]              ;Get old vector
  2025.             mov     ah,25h                  ;DOS set interrupt
  2026.             int     21h
  2027.             clc
  2028.             pop     ds
  2029. restoreint_exit:
  2030.             pop     es
  2031.             ret
  2032. restoreint_error:
  2033.             stc
  2034.             jmp     short restoreint_exit
  2035. restore_int     endp
  2036.  
  2037. ;-----------------------------------------------------------------------------
  2038. ; FINDCEF  Finds the DOS ErrorMode (Critical error) flag
  2039. ; Exit:   ES:BX - Segment,offset of ErrorMode flag
  2040. ;         CF - Clear if flag found
  2041. ;-----------------------------------------------------------------------------
  2042. findCEF         proc    near
  2043.         mov    ah,34h            ;Get InDOS address
  2044.         int    21h
  2045.         dec    bx        
  2046.         cmp    dos_version,30ah    ;If DOS 3.1 or later, ErrorMode
  2047.         jnc    findCEF_exit        ;  sits before InDOS.
  2048.  
  2049.             mov     ax,3e80h                ;CMP opcode
  2050.         mov     si,028cdh               ;Int 28 Opcode
  2051.         mov     dl,75h                  ;JNE Opcode
  2052.             mov     cx,-1                   ;max search length
  2053.             mov     di,bx                   ;start at INDOS address
  2054. findCEF_1:
  2055.         repne   scasb                   ;do the search
  2056.             jcxz    findCEF_notfound        ;branch if search failed
  2057.         cmp     es:[di],ah              ;Check other half of CMP opcode
  2058.         jne     findCEF_1
  2059.         cmp     byte ptr es:[di+4],dl   ;Check for JNE
  2060.         jne     findCEF_1
  2061.         cmp     word ptr es:[di+6],si   ; Check for Int 28h call
  2062.         jne     findCEF_1               ;Resume loop if not found
  2063.         inc     di
  2064.         mov     bx,es:[di]              ;Get offset of ErrorMode flag
  2065.         clc
  2066. findCEF_exit:
  2067.         ret
  2068. findCEF_notfound:
  2069.         stc
  2070.         mov    dx,offset errmsg5    ;Can't find Critical Error flg
  2071.         jmp     short findCEF_exit
  2072. findCEF        endp
  2073.  
  2074. ;-----------------------------------------------------------------------------
  2075. ; FIND INSTALLED Find the installed code by scanning the memory control blocks.
  2076. ; Exit:   AX - Segment of installed code if found.
  2077. ;         CF - Clear if installed code found
  2078. ;-----------------------------------------------------------------------------
  2079. find_installed  proc    near
  2080.             assume  ds:code,es:code
  2081.             mov     word ptr prog,0
  2082.             mov     bx,0A000h               ;Start at upper mem blk start
  2083.             mov     ax,cs                   ;keep CS value in AX
  2084. find_installed_1:
  2085.             inc     bx                      ;increment search segment value
  2086.             mov     es,bx
  2087.             assume  es:nothing
  2088.             cmp     ax,bx                   ;not installed if current
  2089.             je      find_installed_2        ;  segment is found.
  2090.             call    cmpheader
  2091.             jne     find_installed_1        ;loop back if not found
  2092.  
  2093.             clc
  2094. find_installed_exit:
  2095.             ret
  2096. find_installed_2:
  2097.             stc
  2098.             jmp     short find_installed_exit
  2099. find_installed  endp
  2100.  
  2101. ;-----------------------------------------------------------------------------
  2102. ; CMPHEADER compares the first 16 bytes of this file with the segment
  2103. ;           pointed to by ES.
  2104. ; Entry:  DS - code segment
  2105. ;         ES - pointer to segment to compare
  2106. ; Exit:   ZF - 0 = segments match.
  2107. ;-----------------------------------------------------------------------------
  2108. cmpheader       proc    near
  2109.             assume  ds:code,es:nothing
  2110.             mov     si,offset prog          ;Search this segment for ASCII
  2111.             mov     di,si                   ;  fingerprint.
  2112.             mov     cx,16
  2113.             repe    cmpsb
  2114.             ret
  2115. cmpheader       endp
  2116.  
  2117. ;-----------------------------------------------------------------------------
  2118. ; SETSHIFTMSG Sets the proper hot shift text from the code set by PATCH.COM
  2119. ;-----------------------------------------------------------------------------
  2120. setshiftmsg     proc    near
  2121.             assume  ds:code,es:code
  2122.         mov    si,offset infomsg1a
  2123.         mov    ax,word ptr patchcode
  2124.         call    setshiftmsg1
  2125.         mov    ax,word ptr [patchcode+2]
  2126.         call    setshiftmsg1
  2127.         mov    byte ptr [si],'$'
  2128.         ret
  2129. setshiftmsg     endp
  2130.  
  2131. setshiftmsg1    proc    near
  2132.         mov    byte ptr [si],'<'
  2133.         inc    si
  2134.         mov    di,offset shiftcodes    ;Scan code list to find
  2135.         mov    cx,4            ;  the proper shift word 
  2136.         repne    scasw            ;  to use in the message
  2137.         jne    setshiftmsg_exit
  2138.         mov    ah,cl
  2139.         mov    di,offset shifttext    ;Find message in list
  2140.         xor    al,al
  2141.         or    ah,ah
  2142.         je    setshiftmsg_2
  2143. setshiftmsg_1:
  2144.         mov    cx,30
  2145.         repne    scasb
  2146.         dec    ah
  2147.         jne    setshiftmsg_1
  2148. setshiftmsg_2:
  2149.         xchg    di,si
  2150. setshiftmsg_3:
  2151.         lodsb                ;Copy shift label to msg
  2152.         stosb
  2153.         or    al,al
  2154.         jne    setshiftmsg_3
  2155.         mov    byte ptr [di-1],'>'    ;Append closing >
  2156.         mov    si,di
  2157. setshiftmsg_exit:        
  2158.         ret
  2159. setshiftmsg1    endp
  2160.  
  2161. ;-----------------------------------------------------------------------------
  2162. ; PRINTMSG prints the message pointed to by DX to the screen.
  2163. ; Entry:  DX - pointer to ASCII message terminated by $
  2164. ;-----------------------------------------------------------------------------
  2165. printmsg        proc    near
  2166.             assume  ds:nothing,es:nothing
  2167.             push    ds
  2168.             push    cs
  2169.             pop     ds
  2170.             assume  ds:code
  2171.             mov     ah,9                    ;Print message
  2172.             int     21h
  2173.             pop     ds
  2174.             ret
  2175. printmsg        endp
  2176.  
  2177. ;-----------------------------------------------------------------------------
  2178. ; PRINTMSGCR calls PRINTMSG, then appends a carriage return to the message.
  2179. ; Entry:  DX - pointer to ASCII message terminated by $
  2180. ;-----------------------------------------------------------------------------
  2181. printmsgcr      proc    near
  2182.             assume  ds:nothing,es:nothing
  2183.             push    dx
  2184.             call    printmsg
  2185.             mov     dx,offset endmsg
  2186.             call    printmsg
  2187.             pop     dx
  2188.             ret
  2189. printmsgcr      endp
  2190.             even
  2191. end_of_code     =       $
  2192. code            ends
  2193.  
  2194. end             prog
  2195.