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