home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / UTILITY / SCREEN / WAS062.ZIP / WAS062.ASM < prev    next >
Encoding:
Assembly Source File  |  1990-10-14  |  117.1 KB  |  2,877 lines

  1. ; WAS.ASM version 0.62
  2.  
  3. comment &
  4.  
  5.  In the code that follows, when a reference is made to an absolute offset it
  6.  means an offset to a byte relative to the zero location that is the first byte
  7.  of the first EMS page allocated by WAS for the scroll back buffer.  So the
  8.  absolute offset of the first byte of the second EMS page is 16384, for the
  9.  first byte of the third page 32768, etc.  These offsets are stored in double
  10.  word locations with the suffix -lo terminating the least significant word of
  11.  the pointer and the suffix -hi terminating the most significant word of the
  12.  pointer.  The routine resolve converts these absolute offsets to pg:ofs form,
  13.  where pg is the EMS page of the byte pointed to by the absolute offset and ofs
  14.  is its offset within that page.  The unresolve routine does the reverse and
  15.  converts pg:ofs values back to absolute offsets.  The suffixes -pg and -ofs
  16.  are used to denote pg:ofs double word pointers.
  17.  
  18. &
  19.  
  20. ver             equ     "0.62"          ; version number for copyright notice
  21. version         equ     "062"           ; version number for summary message
  22. ofs             equ     offset          ; abbreviations
  23. wp              equ     word ptr
  24. bpt             equ     byte ptr
  25. debug           =       1               ; = 1 sets int 3, = 0 sets buzz
  26. cursizhi        =       0ah             ; index to high scan line of cursor
  27. cursizlo        =       0bh             ; index to low scan line of cursor
  28. speaker         =       61h             ; address of speaker port
  29. kbdhead         =       1ah             ; address of head pointer of kbd buffer
  30. kbdtail         =       1ch             ; address of tail pointer of kbd buffer
  31. cursorpos       =       50h             ; base address of ROM BIOS cursor pos
  32. linsiz          =       160             ; size of screen line with attributes
  33. maxlines        =       101             ; max number of screen lines supported
  34. minlines        =       25              ; min number of screen lines supported
  35. k16             =       16384           ; 16k
  36. k32             =       32768           ; 32k
  37. lastcol         =       79              ; last column of display
  38. pwr2div         =       5               ; power of 2 divisor for interval proc
  39. alt             =       8               ; Alt key bit in kbd status byte
  40. ltshift         =       2               ; Left Shift bit in kbd status byte
  41. rtshift         =       1               ; Right Shift bit in kbd status byte
  42. slock           =       10h             ; Scroll Lock bit in kbd status byte
  43. cr              =       13              ; carriage return
  44. lf              =       10              ; line feed
  45. no              =       8f4eh           ; 'N' with blinking bold attribute
  46. yes             =       8f59h           ; 'Y' with blinking bold attribute
  47. sumbg           =       7               ; command summary background attribute
  48.  
  49. biosdata        segment at 40h          ; useful ROM BIOS data locations
  50.                 org     17h
  51. kbdstat         db      ?
  52.                 org     49h
  53. videomode       db      ?
  54.                 org     4eh
  55. videofs         dw      ?
  56.                 org     63h
  57. crtport         dw      ?
  58.                 org     80h
  59. kbdstart        dw      ?
  60. kbdend          dw      ?
  61.                 org     84h
  62. numrows         db      ?
  63.                 org     85h
  64. charhigh        dw      ?
  65. biosdata        ends
  66.  
  67. jmps            macro   loc
  68.                 jmp     short loc
  69.                 endm
  70.  
  71. code            segment
  72.                 assume  cs:code
  73.                 org     2ch
  74. env             dw      ?
  75.                 org     100h
  76. entry:          jmp     start
  77.                 db      253 dup(0)
  78. thestack:
  79.  
  80. countlo         dw      ?
  81. counthi         dw      ?
  82. dummy           db      0
  83.  
  84. interval        proc    near            ; Routine to count interval between
  85.                 mov     ax,countlo      ; successive clicks of speaker for
  86.                 mov     dx,counthi      ; error buzz.  The two count variables
  87.                 inc     dx              ; are initialized with a temporary
  88. dec_count:      cmp     dummy,1         ; int 8 routine at initialization time.
  89.                 je      dec_count
  90.                 dec     ax
  91.                 jnz     dec_count
  92.                 dec     dx
  93.                 jnz     dec_count
  94.                 ret
  95. interval        endp
  96.  
  97. buzz            proc    near            ; Causes the speaker to buzz by turning
  98.                 push    ax              ; it on and off to produce a tone with
  99.                 push    cx              ; a frequency dependent upon the size
  100.                 push    dx              ; of the pause due to the call to proc
  101.                 mov     cx,50           ; interval.  The duration of the call
  102. nextclick:      in      al,speaker      ; to interval is independent of CPU
  103.                 jmp     $+2
  104.                 xor     al,2            ; speed.
  105.                 out     speaker,al
  106.                 jmp     $+2
  107.                 call    interval
  108.                 loop    nextclick
  109.                 pop     dx
  110.                 pop     cx
  111.                 pop     ax
  112.                 ret
  113. buzz            endp
  114.  
  115. ; The lastpage variable is used to bypass calls to the EMM for logical pages
  116. ; that have already been mapped to physical page 0 (the most frequently mapped
  117. ; physical page).
  118.  
  119. lastpage        dw      ?
  120. handle          dw      ?               ; handle returned by the EMM
  121.  
  122. ems             proc    near            ; Implements call to the expanded
  123.                 cmp     ax,4400h        ; memory manager.
  124.                 jne     doems
  125.                 cmp     bx,lastpage
  126.                 mov     lastpage,bx
  127.                 jne     doems
  128.                 ret
  129. doems:          push    dx
  130.                 push    bx
  131.                 push    ax
  132.                 mov     dx,handle
  133.                 int     67h
  134.                 or      ah,ah
  135.                 jz      emsout
  136.  
  137. if              debug                   ; If a resident debugger is installed
  138.                 mov     dx,ax           ; (e.g., Periscope) the debug constant
  139.                 pop     ax              ; can be set to 1 and this code will
  140.                 mov     al,dh           ; be executed if an EMS error occurs.
  141.                 pop     bx              ; The function causing the error is
  142.                 pop     dx              ; retained in ah while the error code
  143.                 int     3               ; is shown in al.  Both bx and dx
  144.                 ret                     ; remain unchanged.
  145. else
  146.                 call    buzz            ; Otherwise you get a buzz.
  147. endif
  148.  
  149. emsout:         pop     ax
  150.                 pop     bx
  151.                 pop     dx
  152.                 ret
  153. ems             endp
  154.  
  155. regen           dw      ?
  156. pfseg           dw      ?
  157.  
  158. scr2ems         proc    near            ; destroys cx and es
  159.                 push    ds              ; Copies screen (video regen buffer)
  160.                 mov     ds,regen        ; memory to EMS memory.
  161.                 mov     es,pfseg
  162.                 rep     movsw
  163.                 pop     ds
  164.                 ret
  165. scr2ems         endp
  166.  
  167. ems2scr         proc    near            ; destroys cx and es
  168.                 push    ds              ; Copies EMS memory to screen (video
  169.                 mov     ds,pfseg        ; regen buffer) memory.
  170.                 mov     es,regen
  171.                 rep     movsw
  172.                 pop     ds
  173.                 ret
  174. ems2scr         endp
  175.  
  176. savcntx         proc    near            ; destroys ax
  177.                 mov     ah,47h          ; save ems context
  178.                 call    ems
  179.                 mov     lastpage,-1     ; Setting lastpage to 0ffffh assures
  180.                 ret                     ; that the first mapping request will
  181. savcntx         endp                    ; go through.
  182.  
  183. rstcntx         proc    near            ; destroys ax
  184.                 mov     ah,48h          ; restore ems context
  185.                 call    ems
  186.                 ret
  187. rstcntx         endp
  188.  
  189. ; These variables are set by calls to the setvideo procedure.
  190.  
  191. scrnsiz         dw      ?               ; number of bytes in video regen buffer
  192. numlines        dw      ?               ; number of lines on screen
  193. pointsize       db      ?               ; size of character height
  194.  
  195. ; It has been found better to address the hardware when turning the cursor on
  196. ; and off since this eliminates the necessity for use of ROM BIOS functions for
  197. ; cursor control.  Calling int 10h routines at the arbitrary code locations at
  198. ; which WAS can halt the machine can result in system crashes at least for some
  199. ; types of BIOS ROMs.
  200.  
  201.                 assume  ds:biosdata
  202.  
  203. curon           proc    near            ; destroys ax, bx, dx and ds
  204.                 mov     dx,crtport      ; address CRT controller port
  205.                 mov     bl,pointsize    ; restored cursor size depends on
  206.                 mov     bh,bl           ; character height
  207.                 sub     bl,2            ; devote 3 scan lines to cursor
  208.                 sub     bh,4
  209.                 cmp     pointsize,8
  210.                 jne     setcur
  211.                 inc     bl              ; special provision for 8 x 8 character
  212.                 inc     bh              ; box
  213. setcur:         mov     al,cursizhi
  214.                 cli
  215.                 out     dx,al
  216.                 jmp     $+2                ; pause for I/O catch up
  217.                 inc     dx
  218.                 mov     al,bh
  219.                 out     dx,al
  220.                 jmp     $+2
  221.                 dec     dx
  222.                 mov     al,cursizlo
  223.                 out     dx,al
  224.                 jmp     $+2
  225.                 inc     dx
  226.                 mov     al,bl
  227.                 out     dx,al
  228.                 jmp     $+2
  229.                 sti
  230.                 ret
  231. curon           endp
  232.  
  233. curoff          proc    near            ; destroys ax, bx, dx and ds
  234.                 mov     dx,crtport
  235.                 mov     al,cursizhi
  236.                 cli
  237.                 out     dx,al
  238.                 jmp     $+2
  239.                 inc     dx
  240.                 mov     al,31
  241.                 out     dx,al
  242.                 jmp     $+2
  243.                 dec     dx
  244.                 mov     al,cursizlo
  245.                 out     dx,al
  246.                 jmp     $+2
  247.                 inc     dx
  248.                 sub     al,al
  249.                 out     dx,al
  250.                 jmp     $+2
  251.                 sti
  252.                 ret
  253. curoff          endp
  254.  
  255. lastpg          dw      ?               ; Stores page number of highest page.
  256. lastofs         dw      ?               ; This is offset of byte just beyond
  257.                                         ; the last location in the scroll
  258.                                         ; buffer.  This combination of lastpg:
  259.                                         ; lastofs is the result of applying the
  260.                                         ; resolve routine on the absolute
  261.                                         ; pointer stored in endofslo:endofshi.
  262.  
  263. scrsavsiz       dw      60 * 160 + 1    ; size of buffer to save current screen
  264. scrsavofs       dw      16384 - 60*160+1; offset of current screen save buf
  265.  
  266.                 assume  ds:code
  267.  
  268. savscr          proc    near            ; save current screen to EMS memory
  269.                 call    savcntx
  270.                 mov     ax,4400h        ; access page to store screen
  271.                 mov     bx,lastpg       ; screen is stored at end of last EMS
  272.                 call    ems             ; page
  273.                 sub     si,si
  274.                 mov     di,scrsavofs    ; location determined by 'l' switch
  275.                 mov     cx,scrnsiz      ; setvideo sets scrnsiz
  276.                 shr     cx,1
  277.                 call    scr2ems         ; store current screen
  278.                 ret
  279. savscr          endp
  280.  
  281. rstscr          proc    near            ; restore current screen from EMS
  282.                 mov     ax,4400h        ; access page of stored screen
  283.                 mov     bx,lastpg
  284.                 call    ems
  285.                 mov     si,scrsavofs
  286.                 sub     di,di
  287.                 mov     cx,scrnsiz
  288.                 shr     cx,1
  289.                 call    ems2scr         ; restore current screen
  290.                 call    rstcntx         ; restore EMS context before leaving
  291.                 ret
  292. rstscr          endp
  293.  
  294. headlo          dw      0               ; Scroll back buffer is implemented as
  295. headhi          dw      0               ; circular buffer with a head and tail
  296. taillo          dw      0               ; pointer.  The values are stored here
  297. tailhi          dw      0               ; as absolute offsets that are resolved
  298. toplo           dw      ?               ; into page and offset by resolve proc.
  299. tophi           dw      ?               ; The top pointer points to the line
  300.                                         ; saved in EMS that is currently shown
  301.                                         ; at the top of the screen.
  302.  
  303. settop          proc    near            ; destroys ax
  304.                 mov     ax,taillo       ; Routine sets the top pointer from
  305.                 mov     toplo,ax        ; the tail pointer.
  306.                 mov     ax,tailhi
  307.                 mov     tophi,ax
  308.                 ret
  309. settop          endp
  310.  
  311. resolve         proc    near            ; Converts absolute offsets within the
  312.                 push    ax              ; EMS scroll back buffer into page, and
  313.                 rcl     ax,1            ; offset within page of corresponding
  314.                 rcl     dx,1            ; EMS page.
  315.                 rcl     ax,1
  316.                 rcl     dx,1
  317.                 pop     ax
  318.                 and     ax,3fffh
  319.                 ret
  320. resolve         endp
  321.  
  322. unresolve       proc    near            ; Converts EMS page and page offsets
  323.                 push    bx              ; back into absolute offsets within the
  324.                 sub     bx,bx           ; EMS scroll back buffer.
  325.                 rcr     dx,1
  326.                 rcr     bx,1
  327.                 rcr     dx,1
  328.                 rcr     bx,1
  329.                 or      ax,bx
  330.                 pop     bx
  331.                 ret
  332. unresolve       endp
  333.  
  334. frmbuf          proc    near            ; Sets up appropriate EMS scroll back
  335.                 jcxz    fbout           ; buffer pages into physical pages 0
  336.                 call    resolve         ; and 1, then copies the number of
  337.                 mov     si,ax           ; bytes in cx to video memory.
  338.                 mov     ax,4400h
  339.                 mov     bx,dx
  340.                 call    ems
  341.                 mov     bx,k16
  342.                 sub     bx,cx
  343.                 cmp     si,bx
  344.                 jbe     fbshow
  345.                 inc     dx
  346.                 mov     ax,4401h
  347.                 mov     bx,dx
  348.                 call    ems
  349. fbshow:         shr     cx,1
  350.                 call    ems2scr
  351. fbout:          ret
  352. frmbuf          endp
  353.  
  354. siz2cx          proc    near            ; number of bytes in bx lines to cx
  355.                 mov     ax,linsiz
  356.                 mul     bx
  357.                 mov     cx,ax
  358.                 ret
  359. siz2cx          endp
  360.  
  361. frmsav          proc    near            ; lines from saved screen to video mem
  362.                 mov     ax,4400h        ; access page of stored screen
  363.                 mov     bx,lastpg
  364.                 call    ems
  365.                 mov     si,scrsavofs
  366.                 shr     cx,1
  367.                 call    ems2scr
  368.                 ret
  369. frmsav          endp
  370.  
  371. endofslo        dw      ?               ; This is an absolute offset to the byte
  372. endofshi        dw      ?               ; just beyond the last location in the
  373.                                         ; EMS scroll buffer.
  374.  
  375. showattop       proc    near            ; Display a full screen of lines from
  376.                 mov     cx,numlines     ; scroll back buffer and/or saved
  377.                 mov     bp,cx           ; current screen.
  378.                 sub     bx,bx           ; dx:ax contain top pointer at entry
  379.                 sub     di,di
  380.                 push    ax
  381.                 push    dx
  382. sat1:           cmp     dx,tailhi
  383.                 jne     satcmpend
  384.                 cmp     ax,taillo
  385.                 je      sattail1
  386. satcmpend:      cmp     dx,endofshi
  387.                 jne     nextline
  388.                 cmp     ax,endofslo
  389.                 je      satwrap
  390. nextline:       add     ax,linsiz
  391.                 adc     dx,0
  392.                 inc     bx
  393.                 loop    sat1
  394.                 mov     cx,scrnsiz
  395.                 pop     dx
  396.                 pop     ax
  397.                 call    frmbuf
  398.                 ret
  399. sattail1:       call    siz2cx
  400.                 pop     dx
  401.                 pop     ax
  402.                 mov     bx,scrnsiz
  403.                 sub     bx,cx
  404.                 push    bx
  405.                 call    frmbuf
  406.                 pop     cx
  407.                 call    frmsav
  408.                 ret
  409. satwrap:        sub     bp,bx
  410.                 call    siz2cx
  411.                 pop     dx
  412.                 pop     ax
  413.                 call    frmbuf
  414.                 sub     ax,ax
  415.                 sub     dx,dx
  416.                 mov     cx,bp
  417.                 sub     bx,bx
  418. sat2:           cmp     dx,tailhi
  419.                 jne     satbumptr
  420.                 cmp     ax,taillo
  421.                 je      sattail2
  422. satbumptr:      add     ax,linsiz
  423.                 adc     dx,0
  424.                 inc     bx
  425.                 loop    sat2
  426.                 call    siz2cx
  427.                 sub     ax,ax
  428.                 sub     dx,dx
  429.                 call    frmbuf
  430.                 ret
  431. sattail2:       or      bx,bx
  432.                 jz      satdosav
  433.                 sub     bp,bx
  434.                 call    siz2cx
  435.                 sub     ax,ax
  436.                 sub     dx,dx
  437.                 call    frmbuf
  438. satdosav:       mov     bx,bp
  439.                 call    siz2cx
  440.                 call    frmsav
  441.                 ret
  442. showattop       endp
  443.  
  444. margin          dw      0               ; left column of marked area
  445. lnwdth          dw      80              ; number of characters in a marked line
  446. monochrome      db      0               ; marking is different for monochrome
  447.  
  448. markline        proc    near            ; Marks or unmarks a line of text.
  449.                 push    ds              ; A "line" can be one character wide.
  450.                 mov     cx,lnwdth       ; Such is the case when borders are
  451.                 push    si              ; moved one character column left or
  452.                 push    di              ; right.
  453.                 add     si,margin
  454.                 add     di,margin
  455.                 mov     es,pfseg
  456.                 mov     ds,pfseg
  457. markchar:       lodsw
  458.                 cmp     cs:monochrome,1 ; Attributes are set to reverse video
  459.                 jne     color           ; (70h) attribute or plain (07h) for
  460.                 cmp     ah,70h          ; monochrome monitors.  This is the
  461.                 mov     ah,7            ; only way to insure reverse video
  462.                 je      stochr          ; marking of lines, since ANSI.SYS (or
  463.                 mov     ah,70h          ; other like console drivers) can alter
  464.                 jmps    stochr          ; attributes in ways that prevent
  465. color:          xor     ah,77h          ; marking to be visible if the xoring
  466. stochr:         stosw                   ; that works so well for color were
  467.                 loop    markchar        ; also used for monochrome.
  468.                 pop     di
  469.                 pop     si
  470.                 add     si,linsiz
  471.                 add     di,linsiz
  472.                 pop     ds
  473.                 ret
  474. markline        endp
  475.  
  476. markalin        proc    near            ; Sets up the EMS pages for the marking
  477.                 mov     ax,4400h        ; carried out by markline proc.
  478.                 mov     bx,dx
  479.                 call    ems
  480.                 mov     ax,si
  481.                 add     ax,linsiz
  482.                 cmp     ax,k16
  483.                 jbe     mrklin
  484.                 mov     ax,4401h
  485.                 inc     dx
  486.                 mov     bx,dx
  487.                 call    ems
  488. mrklin:         call    markline
  489.                 ret
  490. markalin        endp
  491.  
  492. backandmark     proc    near            ; This routine backs up linsiz bytes
  493.                 cmp     dx,lastpg       ; within the EMS scroll back buffer
  494.                 jne     bambackup       ; and marks a line.  Used to move a
  495.                 cmp     ax,scrsavofs    ; marked line (or set of lines) up in
  496.                 jne     bambackup       ; the scroll back buffer.
  497. bamatend:       mov     ax,taillo
  498.                 mov     dx,tailhi
  499.                 call    resolve
  500. bambackup:      mov     bx,ax
  501.                 or      bx,dx
  502.                 jnz     bambackit
  503.                 mov     ax,lastofs
  504.                 mov     dx,lastpg
  505. bambackit:      sub     ax,linsiz
  506.                 jns     bammarkit
  507.                 add     ax,k16
  508.                 dec     dx
  509. bammarkit:      mov     si,ax
  510.                 mov     di,ax
  511.                 push    ax
  512.                 push    dx
  513.                 call    markalin
  514.                 pop     dx
  515.                 pop     ax
  516. bamout:         ret
  517. backandmark     endp
  518.  
  519. mark1ofs        dw      0               ; Mark1 points to the first highlighted
  520. mark1pg         dw      0               ; line in any series.  Mark2 points to
  521. mark2ofs        dw      0               ; the next location after the last
  522. mark2pg         dw      0               ; highlighted line.
  523.  
  524. linup           proc    near            ; Displays one more line from the scroll
  525.                 push    ds              ; back buffer on the top line of the
  526.                 mov     ax,40h          ; screen, unless a shift key is pressed,
  527.                 mov     ds,ax           ; then a marked area within the scroll
  528.                                         ; buffer will be moved up one line
  529.                 assume  ds:biosdata
  530.  
  531.                 test    kbdstat,ltshift or rtshift
  532.                 pop     ds
  533.  
  534.                 assume  ds:code
  535.  
  536.                 jnz     movhlup?
  537.                 mov     ax,toplo
  538.                 mov     dx,tophi
  539.                 cmp     dx,headhi
  540.                 jne     canlu
  541.                 cmp     ax,headlo
  542.                 jne     canlu
  543.                 ret
  544. canlu:          sub     ax,linsiz
  545.                 sbb     dx,0
  546.                 jns     lustotop
  547.                 add     ax,endofslo
  548.                 adc     dx,endofshi
  549. lustotop:       mov     toplo,ax
  550.                 mov     tophi,dx
  551.                 call    showattop
  552.                 ret
  553. movhlup?:       mov     ax,mark1ofs
  554.                 mov     dx,mark1pg
  555.                 cmp     dx,mark2pg
  556.                 jne     athead?
  557.                 cmp     ax,mark2ofs
  558.                 jne     athead?
  559.                 ret
  560. athead?:        mov     bx,ax
  561.                 mov     cx,dx
  562.                 mov     ax,headlo
  563.                 mov     dx,headhi
  564.                 cmp     dx,tailhi
  565.                 jne     maybehead
  566.                 cmp     ax,taillo
  567.                 jne     maybehead
  568.                 jmps    topoflast?
  569. maybehead:      call    resolve
  570.                 cmp     dx,cx
  571.                 jne     movhlup
  572.                 cmp     ax,bx
  573.                 jne     movhlup
  574.                 ret
  575. topoflast?:     cmp     cx,lastpg
  576.                 jne     movhlup
  577.                 cmp     bx,scrsavofs
  578.                 jne     movhlup
  579.                 ret
  580. movhlup:        mov     ax,bx
  581.                 mov     dx,cx
  582.                 call    backandmark
  583. stomark1:       mov     mark1ofs,ax
  584.                 mov     mark1pg,dx
  585.                 mov     ax,mark2ofs
  586.                 mov     dx,mark2pg
  587.                 call    backandmark
  588.                 mov     mark2ofs,ax
  589.                 mov     mark2pg,dx
  590.                 mov     ax,toplo
  591.                 mov     dx,tophi
  592.                 call    showattop
  593.                 ret
  594. linup           endp
  595.  
  596. mabmark         proc    near            ; Mark-And-Bump Mark.  Routine sets up
  597.                 mov     si,ax           ; and does the line marking without
  598.                 mov     di,ax           ; disturbing dx:ax line pointer.
  599.                 push    ax
  600.                 push    dx
  601.                 call    markalin
  602.                 pop     dx
  603.                 pop     ax
  604.                 ret
  605. mabmark         endp
  606.  
  607. bumpdxax        proc    near            ; Whenever there's a need in the code
  608.                 add     ax,linsiz       ; below to move the dx:ax pointer (with
  609.                 cmp     ax,k16          ; a pg:ofs value) to the next scroll
  610.                 jb      lastpg?         ; buffer/current screen line, this
  611.                 sub     ax,k16          ; routine is called.
  612.                 inc     dx
  613. lastpg?:        cmp     dx,lastpg
  614.                 jne     bdaout
  615.                 cmp     ax,lastofs
  616.                 jne     bdaout
  617.                 sub     ax,ax
  618.                 sub     dx,dx
  619. bdaout:         ret
  620. bumpdxax        endp
  621.  
  622. markandbump     proc    near            ; When routine is entered dx:ax points
  623.                 mov     bx,ax           ; to mark2.  The proc marks EMS scroll
  624.                 mov     cx,dx           ; buffer at mark2, then bumps dx:ax
  625.                 mov     ax,taillo       ; before returning.
  626.                 mov     dx,tailhi
  627.                 call    resolve
  628.                 xchg    ax,bx
  629.                 xchg    dx,cx
  630.                 cmp     dx,cx
  631.                 jne     mabbump
  632.                 cmp     ax,bx
  633.                 jne     mabbump
  634.                 mov     ax,scrsavofs
  635.                 mov     dx,lastpg
  636.                 call    mabmark
  637.                 add     ax,linsiz
  638.                 ret
  639. mabbump:        call    mabmark
  640.                 call    bumpdxax
  641.                 ret
  642. markandbump     endp
  643.  
  644. lastsavofs      dw      ?               ; Actually the offset of the first byte
  645.                                         ; beyond the last location for saving
  646.                                         ; the current screen.  Set by the
  647.                                         ; setvideo procedure.
  648.  
  649. lindn           proc    near            ; Scrolls screen up by one line and
  650.                 push    ds              ; places a line from the EMS scroll
  651.                 mov     ax,40h          ; buffer or the current screen on the
  652.                 mov     ds,ax           ; bottom line of the screen.  If either
  653.                                         ; shift key is pressed it moves any
  654.                 assume  ds:biosdata     ; marked region down a line.
  655.  
  656.                 test    kbdstat,ltshift or rtshift
  657.                 pop     ds
  658.  
  659.                 assume  ds:code
  660.  
  661.                 jnz     movhldn?
  662.                 mov     ax,toplo
  663.                 mov     dx,tophi
  664.                 cmp     dx,tailhi
  665.                 jne     canld
  666.                 cmp     ax,taillo
  667.                 jne     canld
  668.                 ret
  669. canld:          add     ax,linsiz
  670.                 adc     dx,0
  671.                 cmp     dx,endofshi
  672.                 jne     ldstotop
  673.                 cmp     ax,endofslo
  674.                 jne     ldstotop
  675.                 sub     ax,ax
  676.                 sub     dx,dx
  677. ldstotop:       mov     toplo,ax
  678.                 mov     tophi,dx
  679.                 call    showattop
  680.                 ret
  681. movhldn?:       mov     ax,mark2ofs
  682.                 mov     dx,mark2pg
  683.                 cmp     dx,lastpg
  684.                 jne     movhldn
  685.                 cmp     ax,lastsavofs   ; Here's the reason that 1 is
  686.                 jne     movhldn         ; added to 60 * 160 for the
  687.                 ret                     ; size of screen saving area.
  688. movhldn:        call    markandbump
  689.                 mov     mark2ofs,ax
  690.                 mov     mark2pg,dx
  691.                 mov     ax,mark1ofs
  692.                 mov     dx,mark1pg
  693.                 call    markandbump
  694.                 mov     mark1ofs,ax
  695.                 mov     mark1pg,dx
  696.                 mov     ax,toplo
  697.                 mov     dx,tophi
  698.                 call    showattop
  699.                 ret
  700. lindn           endp
  701.  
  702. scrup           proc    near            ; implements the PgUp key command
  703.                 mov     ax,toplo
  704.                 mov     dx,tophi
  705.                 cmp     dx,headhi
  706.                 jne     cansu
  707.                 cmp     ax,headlo
  708.                 jne     cansu
  709.                 ret
  710. cansu:          mov     cx,numlines
  711. sublinsiz:      sub     ax,linsiz
  712.                 sbb     dx,0
  713.                 jns     cmphead
  714.                 mov     ax,endofslo
  715.                 mov     dx,endofshi
  716.                 jmps    sublinsiz
  717. cmphead:        cmp     dx,headhi
  718.                 jne     subnext
  719.                 cmp     ax,headlo
  720.                 je      rtout
  721. subnext:        loop    sublinsiz
  722. rtout:          mov     toplo,ax
  723.                 mov     tophi,dx
  724.                 call    showattop
  725.                 ret
  726. scrup           endp
  727.  
  728. scrdn           proc    near            ; implements the PgDn key command
  729.                 mov     ax,toplo
  730.                 mov     dx,tophi
  731.                 cmp     dx,tailhi
  732.                 jne     cansd
  733.                 cmp     ax,taillo
  734.                 jne     cansd
  735.                 ret
  736. cansd:          mov     cx,numlines
  737. addlinsiz:      add     ax,linsiz
  738.                 adc     dx,0
  739.                 cmp     dx,endofshi
  740.                 jne     comptail
  741.                 cmp     ax,endofslo
  742.                 jne     comptail
  743.                 sub     ax,ax
  744.                 sub     dx,dx
  745. comptail:       cmp     dx,tailhi
  746.                 jne     addnext
  747.                 cmp     ax,taillo
  748.                 je      atout
  749. addnext:        loop    addlinsiz
  750. atout:          mov     toplo,ax
  751.                 mov     tophi,dx
  752.                 call    showattop
  753.                 ret
  754. scrdn           endp
  755.  
  756. hmscr           proc    near            ; implements the Home key command
  757.                 mov     ax,headlo
  758.                 mov     dx,headhi
  759.                 mov     toplo,ax
  760.                 mov     tophi,dx
  761.                 call    showattop
  762.                 ret
  763. hmscr           endp
  764.  
  765. enscr           proc    near            ; implements the End key command
  766.                 mov     ax,taillo
  767.                 mov     dx,tailhi
  768.                 mov     toplo,ax
  769.                 mov     tophi,dx
  770.                 call    showattop
  771.                 ret
  772. enscr           endp
  773.  
  774. insrt           proc    near            ; implements the Insert key command
  775.                 mov     ax,toplo
  776.                 mov     dx,tophi
  777.                 cmp     dx,tailhi
  778.                 jne     insout
  779.                 cmp     ax,taillo
  780.                 je      canins
  781. insout:         ret
  782. canins:         call    rstcntx         ; Must restore EMS context now since
  783.                 mov     ax,600h         ; the sav2ems routine does a savcntx/
  784.                 sub     cx,cx           ; rstcntx method.
  785.                 mov     dx,numlines
  786.                 dec     dx
  787.                 mov     dh,dl
  788.                 mov     dl,lastcol
  789.                 call    sav2ems
  790.                 call    savcntx
  791.                 call    settop
  792.                 ret
  793. insrt           endp
  794.  
  795. cmp2tail        proc    near            ; Is the dx:ax pointer equal to the
  796.                 cmp     dx,tailhi       ; tail pointer?  Zero flag set iff so.
  797.                 jne     c2tout
  798.                 cmp     ax,taillo
  799. c2tout:         ret
  800. cmp2tail        endp
  801.  
  802. firstmark       proc    near            ; This routine does all the initiation
  803.                 mov     cx,numlines     ; of pointers to mark the first screen
  804.                 shr     cx,1            ; line in any series and marks that
  805.                 mov     ax,toplo        ; first line.
  806.                 mov     dx,tophi
  807. chkcrntscr:     call    cmp2tail        ; If the dx:ax pointer is equal to the
  808.                 je      incrntscr       ; tail pointer, then we are viewing the
  809.                 add     ax,linsiz       ; current screen.
  810.                 adc     dx,0
  811.                 cmp     dx,endofshi
  812.                 jne     tochkcrnt
  813.                 cmp     ax,endofslo
  814.                 jne     tochkcrnt
  815.                 sub     ax,ax
  816.                 sub     dx,dx
  817. tochkcrnt:      loop    chkcrntscr
  818.                 call    cmp2tail
  819.                 je      incrntscr
  820.                 jmps    inscrlbak       ; if not, we're going to mark a line
  821. incrntscr:      mov     ax,linsiz       ; in the scroll buffer.
  822.                 mul     cx
  823.                 add     ax,scrsavofs
  824.                 mov     dx,lastpg
  825.                 jmps    lodmrkpg
  826. inscrlbak:      call    resolve
  827. lodmrkpg:       mov     si,ax
  828.                 mov     di,ax
  829.                 mov     mark1ofs,ax
  830.                 mov     mark1pg,dx
  831.                 mov     bx,dx
  832.                 add     ax,linsiz
  833.                 cmp     ax,k16
  834.                 jb      stomark2
  835.                 sub     ax,k16
  836.                 inc     dx
  837. stomark2:       mov     mark2ofs,ax
  838.                 mov     mark2pg,dx
  839.                 mov     dx,bx
  840.                 call    markalin
  841.                 mov     ax,toplo
  842.                 mov     dx,tophi
  843.                 call    showattop
  844.                 ret
  845. firstmark       endp
  846.  
  847. ; When a marked area is set in a region of the scroll buffer and the user moves
  848. ; the displayed region closer to the current screen so that the marks are out
  849. ; of sight and above the lines currently displayed, pressing the keypad plus
  850. ; will cause all lines in the scroll buffer from the end of the marked region
  851. ; to the top line of the present display to be marked.  Mark2top is the routine
  852. ; that does that.  In several places of the code for WAS the algorithm used
  853. ; to trace the chain of locations in the circular scroll buffer is to move one
  854. ; line at a time through the buffer.  When a pointer reaches the end of the
  855. ; scroll buffer it is wrapped back to the beginning (location 0).  This method
  856. ; while much more time consuming than a method that did pointer arithmetic and
  857. ; comparisons is lean on code size and very much easier to debug.
  858.  
  859. mark2top        proc    near
  860.                 push    ax
  861.                 push    dx
  862.                 cmp     dx,lastpg
  863.                 jne     lodtop
  864.                 cmp     ax,scrsavofs
  865.                 jb      lodtop
  866. m2tout:         pop     dx
  867.                 pop     ax
  868.                 ret
  869. lodtop:         mov     bp,tophi
  870.                 mov     bx,toplo
  871.                 call    unresolve
  872.                 mov     si,ax           ; Di:si will be the running pointer
  873.                 mov     di,dx           ; to count the lines to mark.
  874.                 sub     cx,cx           ; Initialize count.
  875.                 mov     dx,tailhi
  876.                 mov     ax,taillo
  877. topnow?:        cmp     di,bp
  878.                 jne     tailnow?
  879.                 cmp     si,bx
  880.                 jne     tailnow?
  881.                 jcxz    m2tout
  882.                 pop     dx
  883.                 pop     ax
  884. marknxt:        mov     si,ax
  885.                 mov     di,ax
  886.                 push    ax
  887.                 push    dx
  888.                 push    cx
  889.                 call    markalin
  890.                 pop     cx
  891.                 pop     dx
  892.                 pop     ax
  893.                 call    bumpdxax
  894.                 loop    marknxt
  895.                 ret
  896. tailnow?:       cmp     di,dx
  897.                 jne     ptrandcnt
  898.                 cmp     si,ax
  899.                 jne     ptrandcnt
  900.                 pop     dx
  901.                 pop     ax
  902.                 ret
  903. ptrandcnt:      add     si,linsiz
  904.                 adc     di,0
  905.                 cmp     di,endofshi
  906.                 jne     bumpcnt
  907.                 cmp     si,endofslo
  908.                 jne     bumpcnt
  909.                 sub     si,si
  910.                 sub     di,di
  911. bumpcnt:        inc     cx
  912.                 jmps    topnow?
  913. mark2top        endp
  914.  
  915. setmk           proc    near            ; The routine that sets a marked line
  916.                 mov     ax,mark1ofs     ; when the keypad plus key is pressed.
  917.                 mov     dx,mark1pg
  918.                 cmp     dx,mark2pg
  919.                 jne     notfirst
  920.                 cmp     ax,mark2ofs
  921.                 jne     notfirst
  922.                 call    firstmark
  923.                 ret
  924. notfirst:       mov     ax,mark2ofs
  925.                 mov     dx,mark2pg
  926.                 cmp     dx,lastpg
  927.                 jne     maybemark
  928.                 cmp     ax,lastsavofs
  929.                 jne     maybemark
  930.                 ret
  931. maybemark:      call    mark2top
  932.                 push    ax
  933.                 push    dx
  934.                 mov     ax,taillo
  935.                 mov     dx,tailhi
  936.                 call    resolve
  937.                 mov     bx,ax
  938.                 mov     cx,dx
  939.                 pop     dx
  940.                 pop     ax
  941.                 cmp     dx,cx
  942.                 jne     setupmark
  943.                 cmp     ax,bx
  944.                 jne     setupmark
  945.                 mov     ax,scrsavofs
  946.                 mov     dx,lastpg
  947. setupmark:      mov     si,ax
  948.                 mov     di,ax
  949.                 push    ax
  950.                 push    dx
  951.                 call    markalin
  952.                 pop     dx
  953.                 pop     ax
  954.                 call    bumpdxax
  955.                 mov     mark2ofs,ax
  956.                 mov     mark2pg,dx
  957.                 mov     ax,toplo
  958.                 mov     dx,tophi
  959.                 call    showattop
  960.                 ret
  961. setmk           endp
  962.  
  963. rstmk           proc    near            ; This routine resets a marked line
  964.                 mov     ax,mark2ofs     ; when the keypad minus key is pressed.
  965.                 mov     dx,mark2pg
  966.                 cmp     dx,mark1pg
  967.                 jne     resetmark
  968.                 cmp     ax,mark1ofs
  969.                 jne     resetmark
  970.                 ret
  971. resetmark:      sub     ax,linsiz
  972.                 jns     chklastpage
  973.                 add     ax,k16
  974.                 dec     dx
  975.                 jns     rmmark
  976.                 mov     ax,lastofs
  977.                 sub     ax,linsiz
  978.                 mov     dx,lastpg
  979.                 jmps    rmmark
  980. chklastpage:    cmp     dx,lastpg
  981.                 jne     rmmark
  982.                 mov     bx,scrsavofs
  983.                 sub     bx,linsiz
  984.                 cmp     ax,bx
  985.                 jne     rmmark
  986.                 mov     ax,taillo
  987.                 mov     dx,tailhi
  988.                 call    resolve
  989.                 jmps    resetmark
  990. rmmark:         mov     mark2ofs,ax
  991.                 mov     mark2pg,dx
  992.                 mov     si,ax
  993.                 mov     di,ax
  994.                 call    markalin
  995.                 mov     ax,toplo
  996.                 mov     dx,tophi
  997.                 call    showattop
  998.                 ret
  999. rstmk           endp
  1000.  
  1001. stuff?          db      ?
  1002. keysleft        db      ?
  1003. crflag          db      ?
  1004. stuff1ofs       dw      ?
  1005. stuff1pg        dw      ?
  1006. stuff2ofs       dw      ?
  1007. stuff2pg        dw      ?
  1008.  
  1009. setstuff        proc    near            ; This one is called when lines are
  1010.                 mov     stuff?,1        ; marked and WAS is leaving the hold
  1011.                 mov     keysleft,0      ; state.  It initializes variables used
  1012.                 mov     crflag,0        ; in the operation to feed the keyboard
  1013.                 mov     stuff1ofs,ax    ; buffer with the marked text.
  1014.                 mov     stuff1pg,dx
  1015.                 mov     stuff2ofs,bx
  1016.                 mov     stuff2pg,cx
  1017.                 ret
  1018. setstuff        endp
  1019.  
  1020. markarea        proc    near            ; Marks (or unmarkes) the area from
  1021. mamark:         push    ax              ; mark 1 to mark2.  This routine is
  1022.                 push    bx              ; called to mark (unmark) borders of
  1023.                 push    cx              ; the marked region or unmark all marked
  1024.                 push    dx              ; text before WAS leaves the hold state.
  1025.                 push    si
  1026.                 push    di
  1027.                 mov     si,ax
  1028.                 mov     di,ax
  1029.                 call    markalin
  1030.                 pop     di
  1031.                 pop     si
  1032.                 pop     dx
  1033.                 pop     cx
  1034.                 pop     bx
  1035.                 pop     ax
  1036.                 call    bumpdxax
  1037.                 cmp     dx,cx
  1038.                 jne     maattail?
  1039.                 cmp     ax,bx
  1040.                 jne     maattail?
  1041.                 ret
  1042. maattail?:      cmp     dx,di
  1043.                 jne     mamark
  1044.                 cmp     ax,si
  1045.                 jne     mamark
  1046.                 mov     ax,scrsavofs
  1047.                 mov     dx,lastpg
  1048.                 jmps    mamark
  1049. markarea        endp
  1050.  
  1051. markdata        proc    near            ; This sets up registers to point to
  1052.                 mov     ax,taillo       ; the locations necessary prior to a
  1053.                 mov     dx,tailhi       ; call to markarea.
  1054.                 call    resolve
  1055.                 mov     si,ax
  1056.                 mov     di,dx
  1057.                 mov     ax,mark1ofs
  1058.                 mov     dx,mark1pg
  1059.                 mov     bx,mark2ofs
  1060.                 mov     cx,mark2pg
  1061.                 cmp     dx,cx
  1062.                 jne     mdout
  1063.                 cmp     ax,bx
  1064. mdout:          ret
  1065. markdata        endp
  1066.  
  1067. chkstat         proc    near            ; Routine sets the zero flag based upon
  1068.                 push    ds              ; the setting of bits in the keyboard
  1069.                 mov     bx,40h          ; status byte common to the al register.
  1070.                 mov     ds,bx
  1071.  
  1072.                 assume  ds:biosdata
  1073.  
  1074.                 and     al,kbdstat
  1075.                 pop     ds
  1076.  
  1077.                 assume  ds:code
  1078.  
  1079.                 ret
  1080. chkstat         endp
  1081.  
  1082. ltshift?        proc    near            ; Sets zero flag based upon status of
  1083.                 mov     al,ltshift      ; the left shift key state.
  1084.                 call    chkstat
  1085.                 ret
  1086. ltshift?        endp
  1087.  
  1088. rtshift?        proc    near            ; Sets zero flag based upon status of
  1089.                 mov     al,rtshift      ; the right shift key state.
  1090.                 call    chkstat
  1091.                 ret
  1092. rtshift?        endp
  1093.  
  1094. markborder      proc    near            ; Marks/unmarks marked area borders
  1095.                 call    markdata        ; determined by the parameters of
  1096.                 call    markarea        ; lnwdth and margin placed upon the
  1097.                 pop     ax              ; stack by the calling routine.
  1098.                 pop     lnwdth
  1099.                 pop     margin
  1100.                 push    ax
  1101.                 mov     ax,toplo
  1102.                 mov     dx,tophi
  1103.                 call    showattop
  1104.                 ret
  1105. markborder      endp
  1106.  
  1107. movlt           proc    near            ; moves the border of a marked area to
  1108.                 mov     ax,mark1ofs     ; the left
  1109.                 mov     dx,mark1pg
  1110.                 cmp     ax,mark2ofs
  1111.                 jne     doleft
  1112.                 cmp     dx,mark2pg
  1113.                 jne     doleft
  1114.                 ret
  1115. doleft:         call    ltshift?
  1116.                 jnz     lt_at_lt
  1117.                 call    rtshift?
  1118.                 jnz     lt_at_rt
  1119.                 ret
  1120. lt_at_lt:       cmp     margin,0
  1121.                 jne     lt_fm_lt
  1122.                 ret
  1123. lt_fm_lt:       sub     margin,2
  1124.                 inc     lnwdth
  1125.                 push    margin
  1126.                 push    lnwdth
  1127.                 mov     lnwdth,1
  1128.                 call    markborder
  1129.                 ret
  1130. lt_at_rt:       cmp     lnwdth,1
  1131.                 jne     lt_fm_rt
  1132.                 ret
  1133. lt_fm_rt:       dec     lnwdth
  1134.                 push    margin
  1135.                 push    lnwdth
  1136.                 mov     ax,lnwdth
  1137.                 add     margin,ax
  1138.                 add     margin,ax
  1139.                 mov     lnwdth,1
  1140.                 call    markborder
  1141.                 ret
  1142. movlt           endp
  1143.  
  1144. movrt           proc    near            ; moves the border of a marked area to
  1145.                 mov     ax,mark1ofs     ; the right
  1146.                 mov     dx,mark1pg
  1147.                 cmp     ax,mark2ofs
  1148.                 jne     doright
  1149.                 cmp     dx,mark2pg
  1150.                 jne     doright
  1151.                 ret
  1152. doright:        call    ltshift?
  1153.                 jnz     rt_at_lt
  1154.                 call    rtshift?
  1155.                 jnz     rt_at_rt
  1156.                 ret
  1157. rt_at_lt:       cmp     lnwdth,1
  1158.                 jne     rt_fm_lt
  1159.                 ret
  1160. rt_fm_lt:       dec     lnwdth
  1161.                 add     margin,2
  1162.                 push    margin
  1163.                 push    lnwdth
  1164.                 sub     margin,2
  1165.                 mov     lnwdth,1
  1166.                 call    markborder
  1167.                 ret
  1168. rt_at_rt:       mov     ax,lnwdth
  1169.                 add     ax,ax
  1170.                 add     ax,margin
  1171.                 cmp     ax,linsiz
  1172.                 jne     rt_fm_rt
  1173.                 ret
  1174. rt_fm_rt:       inc     lnwdth
  1175.                 push    margin
  1176.                 push    lnwdth
  1177.                 mov     ax,lnwdth
  1178.                 dec     ax
  1179.                 add     margin,ax
  1180.                 add     margin,ax
  1181.                 mov     lnwdth,1
  1182.                 call    markborder
  1183.                 ret
  1184. movrt           endp
  1185.  
  1186. saving          db      1
  1187.  
  1188. setsv           proc    near            ; Toggles scroll buffer saving.  Called
  1189.                 xor     saving,1        ; when the delete key is pressed.
  1190.                 ret
  1191. setsv           endp
  1192.  
  1193. ; The following routines prior to delmk support that procedure which is the one
  1194. ; which is called when the delete key is pressed.  The pg0 referred to below is
  1195. ; the page that at any given time contains the source of the bytes to move to
  1196. ; the destination page, pg1.  Bytes are moved from pg0 to pg1.  Each pg? cycles
  1197. ; through those necessary to copy all lines below the marked area to the
  1198. ; location that starts the marked area.  The number of bytes moved on each pass
  1199. ; is the minimum of 16k, the number of bytes remaining to be copied, the number
  1200. ; of bytes left on the source page (pg0) and the number of bytes remaining on
  1201. ; the destination page (pg1) from its current offset to the 16k boundary.  The
  1202. ; source logical page is mapped to physical page 0 and the destination logical
  1203. ; page is mapped to physical page 1 except when the source and destination
  1204. ; logical pages coincide.  Then the destination page is not mapped by the EMS
  1205. ; mapping function; instead it shares physical page 0 with the source page.
  1206. ; This is done in case the EM manager does not support aliasing (as some EMS
  1207. ; emulators don't).
  1208.  
  1209. delpg0          dw      ?
  1210. delpg1          dw      ?
  1211.  
  1212. endpg           proc    near            ; Sets dx to the offset of the byte just
  1213.                 cmp     ax,cs:lastpg    ; beyond the last byte of the EMS page
  1214.                 je      pglast          ; (contained in ax) devoted to the
  1215.                 mov     dx,k16          ; scroll buffer.
  1216.                 ret
  1217. pglast:         mov     dx,cs:lastofs
  1218.                 ret
  1219. endpg           endp
  1220.  
  1221. setpg0          proc    near            ; map the source page
  1222.                 mov     ax,4400h
  1223.                 mov     bx,cs:delpg0
  1224.                 call    ems
  1225.                 ret
  1226. setpg0          endp
  1227.  
  1228. setpg1          proc    near            ; map the destination page
  1229.                 mov     ax,cs:delpg0
  1230.                 cmp     ax,cs:delpg1
  1231.                 je      pg1set
  1232.                 mov     ax,4401h
  1233.                 mov     bx,cs:delpg1
  1234.                 call    ems
  1235. pg1set:         ret
  1236. setpg1          endp
  1237.  
  1238. setdelpg0       proc    near            ; Sets pg0 from variable delpg0.  The
  1239.                 mov     ax,cs:delpg0    ; routine returns the number of bytes
  1240.                 call    endpg           ; remaining to be copied from the source
  1241.                 cmp     si,dx           ; page in ax.
  1242.                 jne     pg0same
  1243.                 mov     ax,cs:lastpg
  1244.                 cmp     ax,cs:delpg0
  1245.                 je      sdp0zero
  1246.                 inc     cs:delpg0
  1247.                 jmps    sdp0set
  1248. sdp0zero:       mov     cs:delpg0,0
  1249. sdp0set:        call    setpg0
  1250.                 sub     si,si
  1251.                 mov     ax,ds:delpg0
  1252.                 call    endpg
  1253.                 mov     ax,dx
  1254.                 ret
  1255. pg0same:        mov     ax,dx
  1256.                 sub     ax,si
  1257.                 ret
  1258. setdelpg0       endp
  1259.  
  1260. getpgofs        proc    near            ; Returns in bx the offset within the
  1261.                 mov     ax,cs:delpg0    ; page frame segment where pg1, the
  1262.                 cmp     ax,cs:delpg1    ; destination page, will be mapped.
  1263.                 je      zerofs
  1264.                 mov     bx,k16
  1265.                 ret
  1266. zerofs:         sub     bx,bx
  1267.                 ret
  1268. getpgofs        endp
  1269.  
  1270. setdelpg1       proc    near            ; Sets a new destination page if the
  1271.                 call    setpg1          ; destination bytes of the current page
  1272.                 call    getpgofs        ; have been filled with bytes from the
  1273.                 mov     ax,cs:delpg1    ; source page(s).  The di offset is set
  1274.                 call    endpg           ; to physical page 0 if destination and
  1275.                 cmp     di,dx           ; source pages share the same logical
  1276.                 jne     pg1same         ; page number, otherwise physical page
  1277.                 mov     ax,cs:lastpg    ; 1 is used as the mapping for the
  1278.                 cmp     ax,cs:delpg1    ; distination page.  The number of bytes
  1279.                 je      sdp1zero        ; remaining to be filled to the end of
  1280.                 inc     cs:delpg1       ; the destination page is returned in
  1281.                 jmps    sdp1set         ; ax.
  1282. sdp1zero:       mov     cs:delpg1,0
  1283. sdp1set:        call    setpg1
  1284.                 call    getpgofs
  1285.                 mov     di,bx
  1286.                 mov     ax,cs:delpg1
  1287.                 call    endpg
  1288.                 mov     ax,dx
  1289.                 ret
  1290. pg1same:        mov     ax,dx
  1291.                 sub     ax,di
  1292.                 add     di,bx
  1293.                 ret
  1294. setdelpg1       endp
  1295.  
  1296. ; Num2delhi:num2dello stores the number of bytes in the lines to be deleted
  1297. ; from the scroll buffer.  Used by setloc routine.
  1298.  
  1299. num2dello       dw      ?
  1300. num2delhi       dw      ?
  1301.  
  1302. num2del         proc    near            ; Computes number of bytes to delete
  1303.                 push    ax              ; placing the result in the double word
  1304.                 push    dx              ; num2delhi:num2dello.
  1305.                 mov     ax,mark1ofs
  1306.                 mov     dx,mark1pg
  1307.                 mov     num2delhi,0
  1308.                 mov     num2dello,0
  1309. n2dnxt:         call    bumpdxax
  1310.                 add     num2dello,linsiz
  1311.                 adc     num2delhi,0
  1312.                 cmp     dx,mark2pg
  1313.                 jne     n2dnxt
  1314.                 cmp     ax,mark2ofs
  1315.                 jne     n2dnxt
  1316.                 pop     dx
  1317.                 pop     ax
  1318.                 ret
  1319. num2del         endp
  1320.  
  1321. bumptr          proc    near            ; Called by the routine setloc below
  1322.                 add     si,linsiz       ; to increment the running pointer kept
  1323.                 adc     di,0            ; in di:si.
  1324.                 cmp     di,endofshi
  1325.                 jne     bumptrout
  1326.                 cmp     si,endofslo
  1327.                 jne     bumptrout
  1328.                 sub     si,si
  1329.                 sub     di,di
  1330. bumptrout:      ret
  1331. bumptr          endp
  1332.  
  1333. ; The location pointer (lochi:loclo) is a temporary pointer that is set to one
  1334. ; of the two pointers tophi:toplo or savhi:savlo so that the same routine,
  1335. ; setloc, can serve to manipulate either one.  The adjusted location pointer is
  1336. ; then stored back to the pointer from which it came.
  1337.  
  1338. loclo           dw      ?
  1339. lochi           dw      ?
  1340.  
  1341. ; The double word num2mov is used by delmk to contain the number of bytes to be
  1342. ; moved (resulting in deletion of lines) within the scroll buffer.
  1343.  
  1344. num2movlo       dw      ?
  1345. num2movhi       dw      ?
  1346.  
  1347. ; Setloc adjusts the loc pointer to a new value that accounts for the deletion
  1348. ; of lines within the scroll buffer caused by delmk.  Di:si is used to point
  1349. ; to successive lines in the scroll buffer.  Starting at the head of the scroll
  1350. ; buffer, it is incremented to point to another scroll buffer line for every
  1351. ; pass through each of the two loops in the routine.  If the loc pointer is
  1352. ; encountered first before either mark1 or mark2, then the routine returns
  1353. ; leaving the loc pointer unchanged.  Should mark1 be encountered first the
  1354. ; routine jumps to the second loop.  Now if the loc pointer is encountered
  1355. ; before mark2, then it is set to mark1.  Otherwise mark2 is encountered and
  1356. ; the loc pointer is moved closer to the head by the number of bytes being
  1357. ; deleted.
  1358.  
  1359. setloc          proc    near
  1360.                 mov     ax,mark1ofs
  1361.                 mov     dx,mark1pg
  1362.                 call    unresolve
  1363.                 mov     si,headlo
  1364.                 mov     di,headhi
  1365.                 jmps    cmploc1
  1366. bump1:          call    bumptr
  1367. cmploc1:        cmp     di,lochi
  1368.                 jne     cmpmk1
  1369.                 cmp     si,loclo
  1370.                 jne     cmpmk1
  1371.                 ret
  1372. cmpmk1:         cmp     di,dx
  1373.                 jne     bump1
  1374.                 cmp     si,ax
  1375.                 jne     bump1
  1376.                 mov     ax,mark2ofs
  1377.                 mov     dx,mark2pg
  1378.                 call    unresolve
  1379.                 jmps    cmploc2
  1380. cmpmk2:         cmp     di,dx
  1381.                 jne     bump2
  1382.                 cmp     si,ax
  1383.                 jne     bump2
  1384.                 mov     ax,num2dello
  1385.                 mov     dx,num2delhi
  1386.                 sub     loclo,ax
  1387.                 sbb     lochi,dx
  1388.                 jns     dmstout
  1389.                 mov     ax,endofslo
  1390.                 mov     dx,endofshi
  1391.                 add     loclo,ax
  1392.                 adc     lochi,dx
  1393. dmstout:        ret
  1394. bump2:          call    bumptr
  1395. cmploc2:        cmp     di,lochi
  1396.                 jne     cmpmk2
  1397.                 cmp     si,loclo
  1398.                 jne     cmpmk2
  1399.                 mov     ax,mark1ofs
  1400.                 mov     dx,mark1pg
  1401.                 call    unresolve
  1402.                 mov     loclo,ax
  1403.                 mov     lochi,dx
  1404.                 ret
  1405. setloc          endp
  1406.  
  1407. ; The sav pointer is used to save the location of the top pointer when the
  1408. ; command is given to save the current location within the scroll buffer for
  1409. ; later recall.  0ffffh in the high word of the sav pointer indicates it is
  1410. ; uninitialized.  It is (possibly) altered within the delmk routine due to the
  1411. ; deletion of lines in exactly the same manner that the top pointer can be
  1412. ; redefined by the removal of scroll buffer lines.
  1413.  
  1414. savlo           dw      ?
  1415. savhi           dw      -1
  1416.  
  1417. ; Bufwrap is set to 1 when the buffer tail wraps to the head pointer.  After
  1418. ; that the head points one line further ahead of the tail in the scroll buffer.
  1419. ; If delmk is used to delete every line from the scroll buffer, bufwrap must be
  1420. ; reset to zero so that the savscr2ems routine will properly manage head and
  1421. ; tail pointers.
  1422.  
  1423. bufwrap         db      0
  1424.  
  1425. delmk           proc    near            ; The procedure that implements the
  1426.                 mov     ax,mark2ofs     ; deletion of marked text lines when the
  1427.                 mov     dx,mark2pg      ; delete key is pressed.
  1428.                 cmp     mark1ofs,ax
  1429.                 jne     onlast?
  1430.                 cmp     mark1pg,dx
  1431.                 jne     onlast?
  1432.                 ret
  1433. onlast?:        cmp     dx,lastpg
  1434.                 jne     dodelete
  1435.                 cmp     ax,scrsavofs
  1436.                 jb      dodelete
  1437.                 je      mk22tail
  1438.                 ret                     ; Return if a location in the current
  1439.                                         ; screen is marked.
  1440. mk22tail:       mov     ax,taillo       ; If mark2 is pointing to the first line
  1441.                 mov     dx,tailhi       ; of the current screen (meaning that
  1442.                 call    resolve         ; the last line marked was the line
  1443.                 mov     mark2ofs,ax     ; before the tail pointer), then mark2
  1444.                 mov     mark2pg,dx      ; is set to the tail.  This makes it
  1445. dodelete:       call    num2del         ; possible to trace up to the tail when
  1446.                 call    unresolve       ; bumping a buffer pointer one line at
  1447.                 mov     bx,taillo       ; a time.
  1448.                 mov     cx,tailhi
  1449.                 mov     num2movlo,0
  1450.                 mov     num2movhi,0
  1451. tailyet?:       cmp     dx,cx           ; Count the number of bytes from mark2
  1452.                 jne     dmnxtlin        ; (represented as absolute offset in
  1453.                 cmp     ax,bx           ; dx:ax at the start of this section of
  1454.                 jne     dmnxtlin        ; code) to the tail (in cx:bx).  The
  1455.                 jmps    newtail         ; count is accumulated in num2movhi:
  1456. dmnxtlin:       add     ax,linsiz       ; num2movlo.
  1457.                 adc     dx,0
  1458.                 cmp     dx,endofshi
  1459.                 jne     bump2mov
  1460.                 cmp     ax,endofslo
  1461.                 jne     bump2mov
  1462.                 sub     ax,ax
  1463.                 sub     dx,dx
  1464. bump2mov:       add     num2movlo,linsiz
  1465.                 adc     num2movhi,0
  1466.                 jmps    tailyet?
  1467. newtail:        mov     ax,mark1ofs     ; The new tail will be num2mov bytes
  1468.                 mov     dx,mark1pg      ; from the mark1 offset.
  1469.                 call    unresolve
  1470.                 add     ax,num2movlo
  1471.                 adc     dx,num2movhi
  1472.                 cmp     dx,endofshi
  1473.                 jb      storetail
  1474.                 ja      wraptail
  1475.                 cmp     ax,endofslo
  1476.                 jb      storetail
  1477. wraptail:       sub     ax,endofslo
  1478.                 sbb     dx,endofshi
  1479. storetail:      mov     taillo,ax
  1480.                 mov     tailhi,dx
  1481.                 mov     ax,toplo        ; See about setting a new top pointer
  1482.                 mov     loclo,ax        ; caused by the deletion of lines.
  1483.                 mov     ax,tophi
  1484.                 mov     lochi,ax
  1485.                 call    setloc
  1486.                 mov     ax,loclo
  1487.                 mov     toplo,ax
  1488.                 mov     ax,lochi
  1489.                 mov     tophi,ax
  1490.                 cmp     savhi,-1        ; Has the save pointer been set?
  1491.                 je      chk2mov         ; No, check the number to move.
  1492.                 mov     ax,savlo        ; See about setting a new sav pointer
  1493.                 mov     loclo,ax        ; caused by the deletion of lines.
  1494.                 mov     ax,savhi
  1495.                 mov     lochi,ax
  1496.                 call    setloc
  1497.                 mov     ax,loclo
  1498.                 mov     savlo,ax
  1499.                 mov     ax,lochi
  1500.                 mov     savhi,ax
  1501. chk2mov:        mov     ax,num2movlo
  1502.                 or      ax,num2movhi
  1503.                 jz      markisgone      ; None to move.
  1504. setdelptrs:     mov     si,mark2ofs
  1505.                 push    mark2pg
  1506.                 pop     delpg0
  1507.                 call    setpg0
  1508.                 mov     di,mark1ofs
  1509.                 push    mark1pg
  1510.                 pop     delpg1
  1511.                 call    setpg1
  1512.                 mov     es,pfseg
  1513.                 push    ds
  1514.                 mov     ds,pfseg
  1515.                 jmps    delfrst
  1516. delnxt:         call    getpgofs
  1517.                 sub     di,bx
  1518. delfrst:        mov     cx,k16          ; The number to move for each pass
  1519.                 cmp     cs:num2movhi,0  ; through the loop is the minimum of
  1520.                 jne     setdelpgs       ; 16k, the number of remaining bytes to
  1521.                 cmp     cs:num2movlo,cx ; move, the number of bytes in the
  1522.                 ja      setdelpgs       ; source page from si to the end of the
  1523.                 mov     cx,cs:num2movlo ; source page (returned in ax by the
  1524. setdelpgs:      call    setdelpg0       ; call to setdelpg0), and the number of
  1525.                 cmp     ax,cx           ; bytes in the destination page from di
  1526.                 ja      dodelpg1        ; to the end of that page (returned in
  1527.                 mov     cx,ax           ; ax by the call to setdelpg1).
  1528. dodelpg1:       call    setdelpg1
  1529.                 cmp     ax,cx
  1530.                 ja      delwords
  1531.                 mov     cx,ax
  1532. delwords:       push    cx
  1533.                 shr     cx,1
  1534.                 rep     movsw
  1535.                 pop     cx
  1536.                 sub     cs:num2movlo,cx
  1537.                 sbb     cs:num2movhi,0
  1538.                 mov     ax,cs:num2movlo
  1539.                 or      ax,cs:num2movhi
  1540.                 jz      showmkgone
  1541.                 jmps    delnxt
  1542. showmkgone:     pop     ds
  1543. markisgone:     mov     ax,headlo
  1544.                 mov     dx,headhi
  1545.                 cmp     dx,tailhi
  1546.                 jne     resetmks
  1547.                 cmp     ax,taillo
  1548.                 jne     resetmks
  1549.                 mov     bufwrap,0       ; Reinitialize bufwrap when all lines
  1550. resetmks:       sub     ax,ax           ; are deleted from the scroll buffer.
  1551.                 mov     mark1ofs,ax     ; Reset mark1 and mark2, then update
  1552.                 mov     mark1pg,ax      ; the screen from the top pointer down.
  1553.                 mov     mark2ofs,ax
  1554.                 mov     mark2pg,ax
  1555.                 mov     ax,toplo
  1556.                 mov     dx,tophi
  1557.                 call    showattop
  1558.                 ret
  1559. delmk           endp
  1560.  
  1561. ; The savadj? flag is set to 1 if the head pointer encounters the sav pointer.
  1562. ; It serves to insure that the sav pointer tracks the head pointer if ever the
  1563. ; original sav location is pushed out of the scroll buffer.
  1564.  
  1565. savadj?         db      ?
  1566.  
  1567. ; savpo = save position, rstpo = restore position
  1568.  
  1569. savpo           proc    near
  1570.                 mov     ax,toplo
  1571.                 mov     savlo,ax
  1572.                 mov     ax,tophi
  1573.                 mov     savhi,ax
  1574.                 mov     savadj?,0
  1575.                 ret
  1576. savpo           endp
  1577.  
  1578. rstpo           proc    near
  1579.                 cmp     savhi,-1        ; Can't restore to an uninitialized
  1580.                 je      rpout           ; location.
  1581.                 mov     ax,savlo
  1582.                 mov     toplo,ax
  1583.                 mov     dx,savhi
  1584.                 mov     tophi,dx
  1585.                 call    showattop
  1586. rpout:          ret
  1587. rstpo           endp
  1588.  
  1589. ;; note:  specify which registers are allowed to be used in command routines
  1590. ;;        without being saved
  1591.  
  1592. esc_enable      db      0               ; The "e" command line switch sets this
  1593.                                         ;   to 1 to enable the ESCape command
  1594.  
  1595. escap           proc    near
  1596.                 cmp     esc_enable,1    ; Command line switch set?
  1597.                 jne     escap_out       ; No, ESCape command not allowed
  1598.                 mov     pause,0         ; Yup, we're getting out
  1599.                 push    ds
  1600.                 mov     ax,40h
  1601.                 mov     ds,ax
  1602.  
  1603.                 assume  ds:biosdata
  1604.  
  1605.                 and     kbdstat,not slock       ; reset Scroll Lock bit
  1606.                 pop     ds
  1607.  
  1608.                 assume  ds:code
  1609.  
  1610. escap_out:      ret
  1611. escap           endp
  1612.  
  1613. freemarks       proc    near            ; This routine is called to unmark all
  1614.                 call    markdata        ; marked lines before WAS leaves the
  1615.                 jnz     freeum          ; hold state.
  1616.                 ret
  1617. freeum:         call    setstuff        ; If an area is marked set the stuff1
  1618.                 call    markarea        ; and stuff2 pointers so that the area
  1619.                 sub     ax,ax           ; marked will be feed to the keyboard
  1620.                 mov     mark1ofs,ax     ; buffer.
  1621.                 mov     mark1pg,ax
  1622.                 mov     mark2ofs,ax
  1623.                 mov     mark2pg,ax
  1624.                 ret
  1625. freemarks       endp
  1626.  
  1627. chkmode         proc    near            ; Check the video mode and return with
  1628.                 push    bx              ; the zero flag set iff it is a text
  1629.                 push    ds              ; mode.
  1630.                 mov     bx,40h
  1631.                 mov     ds,bx
  1632.  
  1633.                 assume  ds:biosdata
  1634.  
  1635.                 cmp     videomode,2
  1636.                 je      cmout
  1637.                 cmp     videomode,3
  1638.                 je      cmout
  1639.                 cmp     videomode,7
  1640.                 je      cmout
  1641. cmout:          pop     ds
  1642.                 pop     bx
  1643.                 ret
  1644. chkmode         endp
  1645.  
  1646.                 assume  ds:nothing
  1647.  
  1648. staton          db      0
  1649. saveword        dw      ?
  1650. stat0           dw      no
  1651. stat1           dw      yes
  1652.  
  1653. setstat         proc    near            ; Destroys ax, si, di and es
  1654.                 cmp     staton,0        ; Show the status of scroll saving in
  1655.                 je      showstat        ; the upper left corner of the screen.
  1656.                 ret
  1657. showstat:       push    ds
  1658.                 push    cs
  1659.                 pop     ds
  1660.  
  1661.                 assume  ds:code
  1662.  
  1663.                 mov     es,regen
  1664.                 sub     di,di
  1665.                 mov     si,ofs saveword
  1666.                 mov     ax,es:[di]
  1667.                 mov     [si],ax
  1668.                 mov     si,ofs stat1
  1669.                 cmp     saving,1
  1670.                 je      putstat
  1671.                 mov     si,ofs stat0
  1672. putstat:        lodsw
  1673.                 stosw
  1674.                 mov     staton,1
  1675.                 pop     ds
  1676.  
  1677.                 assume  ds:nothing
  1678.  
  1679.                 ret
  1680. setstat         endp
  1681.  
  1682. rststat         proc    near            ; destroys ax, si, di and es
  1683.                 cmp     staton,1        ; Remove the status indicator from the
  1684.                 je      killstat        ; upper left corner of the screen by
  1685.                 ret                     ; replacing it with the character and
  1686. killstat:       push    ds              ; attribute originally displayed there.
  1687.                 push    cs
  1688.                 pop     ds
  1689.  
  1690.                 assume  ds:code
  1691.  
  1692.                 mov     es,regen
  1693.                 sub     di,di
  1694.                 mov     si,ofs saveword
  1695.                 lodsw
  1696.                 stosw
  1697.                 mov     staton,0
  1698.                 pop     ds
  1699.  
  1700.                 assume  ds:nothing
  1701.  
  1702.                 ret
  1703. rststat         endp
  1704.  
  1705. ; The keytbl is a table of words that represent the byte pairs placed in the
  1706. ; keyboard buffer by int 9 when a key is pressed.  This table is scanned for a
  1707. ; value matching a key found in the keyboard buffer by the code below.  If a
  1708. ; match is found, then it serves--after adjustment--as an offset into cmdtbl,
  1709. ; a call table containing the addresses of routines that implement the command
  1710. ; corresponding to the keypress.  Thus the command keypresses represented by
  1711. ; the word values in keytbl correspond one-for-one to the routines with their
  1712. ; addresses in cmdtbl.  This makes it extremely easy to add commands to the
  1713. ; existing list.
  1714.  
  1715. keytbl          dw      4800h, 5000h, 4900h, 5100h, 4700h, 4f00h, 5200h, 4e2bh
  1716.                 dw      4838h, 5032h, 4a2dh, 4b00h, 4b34h, 4d00h, 4d36h, 0e08h
  1717.                 dw      5300h, 1c0dh, 000dh, 372ah, 092ah, 011bh
  1718. cmdtbl          dw      linup, lindn, scrup, scrdn, hmscr, enscr, insrt, setmk
  1719.                 dw      linup, lindn, rstmk, movlt, movlt, movrt, movrt, setsv
  1720.                 dw      delmk, savpo, savpo, rstpo, rstpo, escap
  1721. keytblsiz       =       cmdtbl - keytbl
  1722.  
  1723. pause           db      0
  1724. inhold          db      0
  1725. textmode        db      ?
  1726.  
  1727. ; The hold routine is where execution is sent by either of the WAS interrupt
  1728. ; traps for int 8 or int 10h.  Hold waits in a loop looking for keypresses that
  1729. ; express commands and then executes them, but it eats the keypresses that have
  1730. ; no associated command.  The cursor is turned off each time through the loop
  1731. ; in case a pop up TSR has left the cursor on before returning control to WAS.
  1732.  
  1733. ;click           proc   near
  1734. ;                in     al,61h          ; get current value of speaker bit
  1735. ;                jmp    $+2
  1736. ;                xor    al,2            ; toggle bit
  1737. ;                out    61h,al          ; move speaker
  1738. ;                jmp    $+2
  1739. ;                ret
  1740. ;click           endp
  1741.  
  1742. hold            proc    near            ; destroys bx and ds
  1743.                 mov     inhold,1
  1744.                 push    ax
  1745.                 push    cx
  1746.                 mov     ax,ss
  1747.                 mov     bx,sp
  1748.                 mov     cx,cs
  1749.                 mov     ss,cx
  1750.                 mov     sp,ofs thestack
  1751.                 sti
  1752.                 push    ax
  1753.                 push    bx
  1754.                 push    dx
  1755.                 push    si
  1756.                 push    di
  1757.                 push    bp
  1758.                 push    es
  1759.                 push    cs
  1760.                 pop     ds
  1761.                 mov     stuff?,0
  1762.                 mov     textmode,0
  1763.                 call    setvideo
  1764.                 call    chkmode
  1765.                 jne     stay
  1766.                 mov     textmode,1
  1767.                 cld
  1768.                 call    savscr          ; Save user's current screen.
  1769.                 call    settop          ; Set the top pointer to buffer tail.
  1770.                 mov     bx,40h
  1771.                 mov     ds,bx
  1772. stay:           mov     ax,40h
  1773.                 mov     ds,ax
  1774.  
  1775.                 assume  ds:biosdata
  1776.  
  1777.                 cmp     textmode,1
  1778.                 jne     key?
  1779.                 call    curoff
  1780.                 test    kbdstat,alt
  1781.                 jz      blnkstat
  1782.                 call    setstat
  1783.                 jmps    key?
  1784. blnkstat:       call    rststat
  1785. key?:           cli
  1786.                 mov     bx,kbdhead      ; Read keypresses from the keyboard
  1787.                 mov     ax,[bx]         ; buffer; eat them if they are not
  1788.                 cmp     ax,2[bx]        ; commands to WAS.
  1789.                 jne     holdchr
  1790.                 sti
  1791.                 cmp     pause,0
  1792.                 jne     stay
  1793.                 jmps    exithold
  1794. holdchr:        mov     bx,2[bx]        ; Found a keypress.  Place it in ax and
  1795.                 sub     bx,2            ; remove it from the keyboard buffer.
  1796.                 cmp     bx,kbdstart
  1797.                 jae     getkey
  1798.                 mov     bx,kbdend
  1799.                 sub     bx,2
  1800. getkey:         mov     ax,[bx]
  1801.                 push    bx
  1802.                 mov     bx,kbdtail
  1803.                 pop     [bx]
  1804.                 sti
  1805.                 cmp     textmode,1
  1806.                 jne     stay
  1807.                 cmp     al,0e0h
  1808.                 jne     specascii?      ; A special ASCII keypress?
  1809.                 sub     al,al
  1810. specascii?:     cmp     ah,0e0h
  1811.                 jne     chkkey
  1812.                 sub     ah,ah
  1813. chkkey:         mov     di,ofs keytbl
  1814.                 mov     cx,keytblsiz/2
  1815.                 push    cs
  1816.                 pop     es
  1817.                 repne   scasw           ; Is the keypress a recognized command?
  1818.                 je      docommand       ; Yes, call the corresponding routine.
  1819.                 jmps    stay
  1820. docommand:      mov     si,di
  1821.                 add     si,keytblsiz-2
  1822.                 push    cs
  1823.                 pop     ds
  1824. ;               call    click
  1825.                 call    [si]
  1826.                 jmps    stay
  1827. exithold:       cmp     textmode,1
  1828.                 jne     holdout
  1829.                 call    curon
  1830.                 push    cs
  1831.                 pop     ds
  1832.                 call    freemarks
  1833.                 call    rstscr
  1834. holdout:        pop     es
  1835.                 pop     bp
  1836.                 pop     di
  1837.                 pop     si
  1838.                 pop     dx
  1839.                 pop     bx
  1840.                 pop     ax
  1841.                 cli
  1842.                 mov     ss,ax
  1843.                 mov     sp,bx
  1844.                 pop     cx
  1845.                 pop     ax
  1846.  
  1847.                 assume  ds:nothing
  1848.  
  1849.                 mov     inhold,0
  1850.                 ret
  1851. hold            endp
  1852.  
  1853. ascscn: ; The scan codes for the corresponding ASCII codes; accessed using the
  1854.         ; ASCII code as an index into the table (via xlat).  This table is used
  1855.         ; to generate the appropriate keypress to stuff into the keyboard buffer
  1856.         ; whenever the keyboard buffer is feed with text from the scroll buffer.
  1857.  
  1858. db  0,  0,  0,  0,  0,  0,  0,  0, 14, 15,  0,  0,  0, 28,  0,  0,  0,  0,  0
  1859. db  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0, 57,  2, 40,  4,  5,  6
  1860. db  8, 40, 10, 11,  9, 13, 51, 12, 52, 53, 11,  2,  3,  4,  5,  6,  7,  8,  9
  1861. db 10, 39, 39, 51, 13, 52, 53,  3, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37
  1862. db 38, 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 26, 43, 27,  7
  1863. db 12, 41, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, 50, 49, 24, 25, 16
  1864. db 19, 31, 20, 22, 47, 17, 45, 21, 44, 26, 43, 27, 41
  1865.  
  1866. getpage         proc    near            ; Map an EMS page.
  1867.                 mov     ax,4400h
  1868.                 mov     bx,dx
  1869.                 call    ems
  1870.                 ret
  1871. getpage         endp
  1872.  
  1873. nextsi          dw      ?
  1874.  
  1875. ; The keysleft variable is initialized to 0 by the setstuff routine as is the
  1876. ; crflag variable.
  1877.  
  1878. lodkey          proc    near            ; Returns a keypress from marked text.
  1879.                 cmp     keysleft,0      ; The keysleft variable contains the
  1880.                 jne     akey            ; number of text characters remaining
  1881.                 push    cx              ; to be read from a line of formerly
  1882.                 push    si              ; marked text.  When lodkey is called
  1883. flag0?:         cmp     crflag,0        ; and keysleft is zero, then a new line
  1884.                 jne     flag1?          ; is checked for characters and their
  1885.                 mov     bx,si           ; number is placed in keysleft.  This
  1886.                 add     bx,linsiz       ; number is the number of characters on
  1887.                 mov     nextsi,bx       ; the line between the column offset in
  1888.                 jmps    prepline        ; the variable margin for a number of
  1889. flag1?:         cmp     crflag,1        ; characters in the variable lnwdth
  1890.                 jne     flag2?          ; minus any trailing spaces.  Crflag
  1891. nxtlin:         mov     crflag,2        ; controls execution through the code.
  1892.                 pop     si              ; Initially it is 0 so it causes nextsi
  1893.                 mov     si,nextsi       ; to be initialized.  Nextsi is the
  1894.                 cmp     si,k16          ; offset of the next line in the area
  1895.                 jb      nextsiok        ; formerly marked.  Then the code jumps
  1896.                 sub     si,k16          ; to prepline where keysleft is set and
  1897.                 inc     dx              ; crflag is set to 1.  The next time
  1898.                 call    getpage         ; lodkey is called and keysleft is 0
  1899. nextsiok:       mov     bx,si           ; crflag being 1 causes the return of
  1900.                 add     bx,linsiz       ; a carriage return keypress.  Crflag
  1901.                 mov     nextsi,bx       ; is set to 2.  When keysleft is zero
  1902.                 pop     cx              ; and crflag is 2, then si is set to
  1903.                 stc                     ; the address of the next line, crlf is
  1904.                 ret                     ; set to 1, and the routine returns
  1905. flag2?:         cmp     crflag,2        ; with the carry flag set since no
  1906.                 jne     prepline        ; keypress is returned.  Subsequent
  1907.                 mov     al,cr           ; calls to lodkey start the process all
  1908.                 inc     crflag          ; over again only no initialization
  1909.                 pop     si              ; since crflag is never 0 again unless
  1910.                 pop     cx              ; the process starts over from the
  1911.                 ret                     ; beginning.
  1912. akey:           lodsw
  1913.                 dec     keysleft
  1914.                 ret
  1915. prepline:       add     si,margin
  1916.                 cmp     si,k16 - 160
  1917.                 jbe     countspaces
  1918.                 mov     bx,dx
  1919.                 inc     bx
  1920.                 mov     ax,4401h
  1921.                 call    ems
  1922. countspaces:    mov     cx,lnwdth
  1923.                 push    cx
  1924.                 sub     bx,bx
  1925. space?:         lodsw
  1926.                 cmp     al,' '
  1927.                 je      bumpbx
  1928.                 sub     bx,bx
  1929.                 loop    space?
  1930.                 jmps    setline
  1931. bumpbx:         inc     bx
  1932.                 loop    space?
  1933. setline:        pop     cx
  1934.                 sub     cx,bx
  1935.                 jcxz    nxtlin
  1936.                 mov     keysleft,cl
  1937.                 mov     crflag,1
  1938.                 pop     si
  1939.                 add     si,margin
  1940.                 pop     cx
  1941.                 jmps    akey
  1942. lodkey          endp
  1943.  
  1944. getstfkey       proc    near            ; Make a keypress to be stuffed into
  1945. gskfirst:       cmp     si,stuff2ofs    ; the keyboard buffer by translating
  1946.                 jne     gskanother      ; text in the formerly marked area into
  1947.                 cmp     dx,stuff2pg     ; keypress data.
  1948.                 jne     gskanother
  1949.                 stc
  1950.                 mov     stuff?,0
  1951.                 ret
  1952. gskanother:     cmp     si,k16
  1953.                 jne     gskkey
  1954.                 inc     dx
  1955.                 sub     si,si
  1956.                 sub     nextsi,k16
  1957.                 call    getpage
  1958. gskkey:         call    lodkey          ; Get a keypress from EMS memory that
  1959.                 jc      gskfirst        ; was formerly marked text.
  1960.                 cmp     al,127          ; If the ASCII code is 127 or over,
  1961.                 jb      ascii
  1962.                 sub     ah,ah           ; then the main byte is zero.
  1963.                 jmps    gskout
  1964. ascii:          mov     ah,al           ; Otherwise, we use the ascscn table to
  1965.                 push    ds              ; determine the scan code value of the
  1966.                 push    cs              ; corresponding ASCII character.
  1967.                 pop     ds
  1968.                 mov     bx,ofs ascscn
  1969.                 xlat
  1970.                 xchg    al,ah
  1971.                 pop     ds
  1972. gskout:         clc
  1973.                 ret
  1974. getstfkey       endp
  1975.  
  1976.                 assume  ds:biosdata, es:biosdata
  1977.  
  1978. stuffit?        proc    near            ; destroys ax, bx, ds and es
  1979.                 mov     pause,1         ; Stuffit? is called by the replacement
  1980.                 push    dx              ; int 8 routine at every clock tick
  1981.                 push    si              ; that occurs whenever the scroll lock
  1982.                 mov     si,stuff1ofs    ; state is not active.  If there is
  1983.                 mov     dx,stuff1pg     ; text remaining to be stuffed into the
  1984.                 mov     bx,kbdhead      ; keyboard buffer, then the stuff?
  1985.                 mov     ax,[bx]         ; variable is 1 else 0.  That decides
  1986.                 cmp     ax,2[bx]        ; the calling of stuffit? by the int 8
  1987.                 je      stuffit?ok      ; routine.  Stuffit? will not stuff
  1988. stuffit?out:    pop     si              ; keypresses into the keyboard buffer
  1989.                 pop     dx              ; unless it is empty.
  1990.                 mov     pause,0
  1991.                 ret
  1992. stuffit?ok:     sti
  1993.                 push    cx
  1994.                 push    di
  1995.                 call    savcntx         ; Save the EMS context.
  1996.                 call    getpage
  1997.                 mov     di,kbdstart
  1998.                 mov     ds,pfseg
  1999.                 cld
  2000.                 mov     cx,15           ; Stuff up to 15 keypresses.
  2001. nxtstf:         call    getstfkey       ; Getstfkey returns with the carry set
  2002.                 jc      stuffit?done    ; if there are no more keypresses to
  2003.                 stosw                   ; stuff.
  2004.                 loop    nxtstf
  2005. stuffit?done:   mov     stuff1ofs,si
  2006.                 mov     stuff1pg,dx
  2007.                 mov     bx,kbdhead
  2008.                 push    es
  2009.                 pop     ds
  2010.                 cli
  2011.                 push    kbdstart        ; Update keyboard buffer head and tail.
  2012.                 pop     [bx]
  2013.                 mov     2[bx],di
  2014.                 sti
  2015.                 call    rstcntx         ; Restore the EMS context.
  2016.                 pop     di
  2017.                 pop     cx
  2018.                 jmps    stuffit?out
  2019. stuffit?        endp
  2020.  
  2021. chk8259         proc    near            ; Check the 8259A interrupt controller
  2022.                 push    ax              ; for in service interrupts.
  2023.                 mov     al,0bh
  2024.                 cli
  2025.                 out     20h,al
  2026.                 jmp     $+2
  2027.                 in      al,20h
  2028.                 jmp     $+2
  2029.                 sti
  2030.                 or      al,al
  2031.                 pop     ax
  2032.                 ret
  2033. chk8259         endp
  2034.  
  2035. slock2bl        proc    near            ; Return in bl the state of the Scroll
  2036.                 mov     bx,40h          ; Lock bit in the keyboard status byte.
  2037.                 mov     ds,bx           ; (Also sets up the ds register for
  2038.                                         ; addressing BIOS data variables.  Used
  2039.                 assume  ds:biosdata     ; even later in stuffit? routine.)
  2040.  
  2041.                 mov     bl,slock
  2042.                 and     bl,kbdstat
  2043.                 ret
  2044. slock2bl        endp
  2045.  
  2046. ; The int 8 vector as WAS saw it before installing it's own int 8 handler.
  2047.  
  2048. old8            label   dword
  2049. old8lo          dw      ?
  2050. old8hi          dw      ?
  2051.  
  2052. ; The enabled? flag helps to implement the '+' and '-' switches.
  2053.  
  2054. enabled?        db      1               ; We're active by default.
  2055.  
  2056. ; The in10 flag is set to 1 by the trapped int 10h routine so that the spliced
  2057. ; in int 8 routine does not call hold while int 10h is executing.  If hold was
  2058. ; allowed to be called while int 10h was in progress, then there would be times
  2059. ; that a halt would be called when int 10h was in the process of scrolling the
  2060. ; screen and occationally a line would appear twice on the screen and yet not
  2061. ; really be there--an illusion.  (Say a text file was being displayed using the
  2062. ; DOS TYPE command.  A text line might appear twice on the display whereas, in
  2063. ; fact, the line does not appear twice in the file being TYPEd.)
  2064.  
  2065. in10            db      0
  2066.  
  2067. new8            proc    far
  2068.                 pushf                   ; Call the former int 8 routine
  2069.                 call    old8
  2070.                 cmp     enabled?,1      ; Are we active?
  2071.                 je      our8            ; Yes, do our thing.
  2072.                 iret                    ; No, bye.
  2073. our8:           push    bx
  2074.                 push    ds
  2075.                 call    slock2bl        ; (sets ds to biosdata)
  2076.                                         ; If scroll lock state is not on
  2077.                 jz      chkstuff        ; check for keyboard buffer stuffing.
  2078.                 cmp     pause,0         ; Scroll lock is active and we're not
  2079.                 je      hold?           ; holding, can we?
  2080.                 jmps    new8out         ; We're holding get out.
  2081. hold?:          cmp     in10,0          ; Refuse to hold while in int 10h.
  2082.                 jne     new8out
  2083.                 call    chk8259
  2084.                 jnz     new8out         ; Or when there's a pending interrupt.
  2085.                 mov     pause,bl
  2086.                 call    hold            ; Let's go into holding mode.
  2087. new8out:        pop     ds
  2088.                 pop     bx
  2089.                 iret
  2090. chkstuff:       mov     pause,0
  2091.                 cmp     stuff?,1
  2092.                 jne     new8out
  2093.                 cmp     inhold,0        ; Perform some reasonable checks, then
  2094.                 jne     new8out         ; stuff the keyboard buffer with 15
  2095.                 call    chk8259         ; keypresses at a time.
  2096.                 jnz     new8out
  2097.                 push    ax
  2098.                 push    es
  2099.                 push    ds
  2100.                 pop     es              ; put es to BIOS data area also
  2101.                 call    stuffit?
  2102.                 pop     es
  2103.                 pop     ax
  2104.                 jmps    new8out
  2105. new8            endp
  2106.  
  2107. savsiz          dw      ?               ; Number of screen bytes to save.
  2108.  
  2109. ; The following code up to the end of resident code all applies to the spliced
  2110. ; in int 10h routine below.
  2111.  
  2112.                 assume  ds:code
  2113.  
  2114. ; If the head pointer surpasses the sav pointer when it (head ptr) is updated
  2115. ; by savscr2ems, then the sav pointer must be set to the new head pointer.  The
  2116. ; lasthead pointer and the chksavptr routine work together to do this.
  2117.  
  2118. lastheadlo      dw      ?
  2119. lastheadhi      dw      ?
  2120.  
  2121. chksavptr       proc    near
  2122.                 cmp     savhi,-1        ; Has a sav location been stored yet?
  2123.                 jne     savpassed?      ; Yes, has sav been passed by head?
  2124.                 ret
  2125. savpassed?:     cmp     savadj?,1
  2126.                 jne     chksav          ; Not before, maybe now?
  2127. setsav2head:    mov     ax,headlo
  2128.                 mov     savlo,ax
  2129.                 mov     ax,headhi
  2130.                 mov     savhi,ax
  2131.                 ret
  2132. chksav:         mov     ax,lastheadlo
  2133.                 mov     dx,lastheadhi
  2134. cmp2head:       cmp     dx,headhi
  2135.                 jne     cmp2sav
  2136.                 cmp     ax,headlo
  2137.                 jne     cmp2sav
  2138.                 ret
  2139. cmp2sav:        cmp     dx,savhi
  2140.                 jne     cspbump
  2141.                 cmp     ax,savlo
  2142.                 jne     cspbump
  2143.                 mov     savadj?,1
  2144.                 jmps    setsav2head
  2145. cspbump:        add     ax,linsiz
  2146.                 adc     dx,0
  2147.                 cmp     dx,endofshi
  2148.                 jne     cmp2head
  2149.                 cmp     ax,endofslo
  2150.                 jne     cmp2head
  2151.                 sub     ax,ax
  2152.                 sub     dx,dx
  2153.                 jmps    cmp2head
  2154. chksavptr       endp
  2155.  
  2156. savscr2ems      proc    near            ; Transfer savsiz bytes from the screen
  2157.                 mov     ax,taillo       ; to the EMS scroll buffer.
  2158.                 mov     dx,tailhi
  2159.                 call    resolve
  2160.                 mov     di,ax
  2161.                 cmp     dx,lastpg
  2162.                 jne     savem
  2163.                 mov     bx,ax           ; If the tail is in the last page and
  2164.                 add     bx,savsiz       ; savsiz is more than would fit within
  2165.                 cmp     bx,lastofs      ; that portion of the last page devoted
  2166.                 jbe     savem           ; to the scroll buffer, then the number
  2167.                 mov     bx,lastofs      ; of bytes to be saved is broken into
  2168.                 sub     bx,ax           ; two pieces.  The first piece is saved
  2169.                 mov     ax,savsiz       ; to EMS by a call to savem.  The second
  2170.                 sub     ax,bx           ; piece is saved by falling through the
  2171.                 push    ax              ; code after savem.
  2172.                 mov     savsiz,bx
  2173.                 call    savem
  2174.                 pop     savsiz
  2175. savem:          mov     ax,4400h        ; access page(s) to store screen
  2176.                 mov     bx,dx
  2177.                 call    ems
  2178.                 mov     bx,di
  2179.                 add     bx,savsiz
  2180.                 cmp     bx,k16
  2181.                 jbe     dosave
  2182.                 mov     ax,4401h        ; If the savsiz plus the offset of the
  2183.                 inc     dx              ; resolved tail goes beyond the first
  2184.                 mov     bx,dx           ; physical page, then the second
  2185.                 call    ems             ; physical page has the next logical
  2186. dosave:         mov     cx,savsiz       ; page mapped to it.
  2187.                 add     taillo,cx
  2188.                 adc     tailhi,0
  2189.                 shr     cx,1
  2190.                 call    scr2ems
  2191.                 mov     ax,headlo
  2192.                 mov     lastheadlo,ax
  2193.                 mov     ax,headhi
  2194.                 mov     lastheadhi,ax
  2195.                 mov     ax,taillo
  2196.                 mov     bx,tailhi
  2197.                 cmp     bx,endofshi
  2198.                 jne     chkwrap
  2199.                 cmp     ax,endofslo
  2200.                 jne     chkwrap
  2201.                 sub     dx,dx           ; Whenever the tail wraps to zero the
  2202.                 sub     di,di           ; head is set to one line beyond
  2203.                 mov     taillo,dx       ; location 0.
  2204.                 mov     tailhi,dx
  2205.                 mov     headlo,linsiz
  2206.                 mov     headhi,dx
  2207.                 mov     bufwrap,1
  2208.                 jmps    ss2eout
  2209. chkwrap:        cmp     bufwrap,1
  2210.                 jne     ss2eout
  2211.                 add     ax,linsiz       ; After the tail wraps back to the
  2212.                 adc     bx,0            ; beginning of the scroll buffer, the
  2213.                 mov     headlo,ax       ; head is maintained one line above
  2214.                 mov     headhi,bx       ; the tail.
  2215.                 cmp     bx,endofshi
  2216.                 jne     ss2eout
  2217.                 cmp     ax,endofslo
  2218.                 jne     ss2eout
  2219.                 sub     ax,ax
  2220.                 mov     headlo,ax
  2221.                 mov     headhi,ax
  2222. ss2eout:        call    chksavptr
  2223.                 ret     
  2224. savscr2ems      endp
  2225.  
  2226. sav2ems         proc    near            ; destroys ax, bx, cx, dx, and ds
  2227.                 call    chkmode         ; Save only when text modes in effect.
  2228.                 je      modeok
  2229.                 ret
  2230. modeok:         push    ds
  2231.                 push    ax
  2232.                 mov     ax,40h
  2233.                 mov     ds,ax
  2234.                 pop     ax
  2235.  
  2236.                 assume  ds:biosdata
  2237.  
  2238.                 cmp     videofs,0       ; Save only from first video page
  2239.                 pop     ds
  2240.  
  2241.                 assume  ds:code
  2242.  
  2243.                 je      cansav
  2244.                 ret
  2245. cansav:         push    es              ; For the purpose of this screen saving
  2246.                 push    si              ; routine all commands that scroll
  2247.                 push    di              ; lines off the top of the screen have
  2248.                 pushf                   ; been converted to scroll commands.
  2249.                 push    ax
  2250.                 call    savcntx         ; Save the EMS context.
  2251.                 pop     ax
  2252.                 cld
  2253.                 or      ah,ah
  2254.                 jz      modeset         ; A mode set is converted to a scroll.
  2255. s2ein:          cmp     dl,lastcol      ; Save only full width scrolls.
  2256.                 jb      s2eout
  2257.                 or      cl,cl           ; ditto
  2258.                 jnz     s2eout
  2259.                 sub     bh,bh
  2260.                 mov     bl,dh
  2261.                 sub     bl,ch
  2262.                 inc     bl              ; Now bx has number of rows to save.
  2263.                 or      al,al
  2264.                 jz      setsavparams
  2265.                 mov     bl,al           ; Unless al contains a row count.
  2266. setsavparams:   mov     ax,bx
  2267.                 mov     bx,linsiz
  2268.                 mul     bx
  2269.                 mov     savsiz,ax       ; Store bytes to save to EMS,
  2270.                 mov     al,ch
  2271.                 sub     ah,ah
  2272.                 mul     bx
  2273.                 mov     si,ax           ; and offset of those bytes to si.
  2274.                 call    savscr2ems
  2275. s2eout:         call    rstcntx         ; Restore ems context.
  2276.                 popf
  2277.                 pop     di
  2278.                 pop     si
  2279.                 pop     es
  2280.                 ret
  2281. modeset:        push    ds
  2282.                 mov     ax,40h
  2283.                 mov     ds,ax
  2284.  
  2285.                 assume  ds:biosdata
  2286.  
  2287.                 mov     ax,600h
  2288.                 sub     cx,cx
  2289.                 mov     dh,numrows
  2290.                 mov     dl,lastcol
  2291. restoreds:      pop     ds
  2292.                 jmps    s2ein
  2293. sav2ems         endp
  2294.  
  2295. evga            db      0
  2296.  
  2297. setvideo        proc    near            ; This item gets and saves in variables
  2298.                 push    ax              ; a number of valuable video parameters.
  2299.                 push    bx              ; The pointsize (character height) is
  2300.                 push    cx              ; obtained because it is needed when
  2301.                 push    dx              ; properly restoring the cursor.  Regen
  2302.                 push    ds              ; is set as the location of the current
  2303.                 mov     ax,40h          ; screen buffer which can be other than
  2304.                 mov     ds,ax           ; page 0.  Scrolled off lines are not
  2305.                                         ; saved from any page but page 0, but
  2306.                 assume  ds:biosdata     ; they can be viewed while any video
  2307.                                         ; page is current.
  2308.                 mov     al,24
  2309.                 cmp     evga,1
  2310.                 jne     svrows
  2311.                 mov     al,numrows
  2312. svrows:         sub     ah,ah
  2313.                 inc     ax
  2314.                 mov     numlines,ax
  2315.                 mov     bx,linsiz
  2316.                 mul     bx
  2317.                 mov     scrnsiz,ax
  2318.                 add     ax,scrsavofs
  2319.                 mov     lastsavofs,ax
  2320.                 mov     monochrome,0
  2321.                 mov     ax,0b800h
  2322.                 mov     bl,8
  2323.                 cmp     crtport,3d4h
  2324.                 je      setregen
  2325.                 mov     monochrome,1
  2326.                 mov     ax,0b000h
  2327.                 mov     bl,14
  2328. setregen:       mov     regen,ax
  2329.                 mov     pointsize,bl
  2330.                 mov     ax,videofs
  2331.                 mov     cl,4
  2332.                 shr     ax,cl
  2333.                 add     regen,ax
  2334.                 cmp     evga,1
  2335.                 jne     svout
  2336.                 cmp     crtport,3b4h
  2337.                 je      svout
  2338.                 mov     ax,charhigh
  2339.                 mov     pointsize,al
  2340. svout:          pop     ds
  2341.                 pop     dx
  2342.                 pop     cx
  2343.                 pop     bx
  2344.                 pop     ax
  2345.                 ret
  2346. setvideo        endp
  2347.  
  2348.                 assume  ds:nothing
  2349.  
  2350. old10           label   dword
  2351. old10lo         dw      ?
  2352. old10hi         dw      ?
  2353. double          db      0               ; Byte is set to 1 if d (double) switch
  2354.                                         ;   is specified on the command line.
  2355.                                         ;   (See documentation for details.)
  2356.  
  2357. new10           proc    far
  2358.                 cmp     ax,7b1eh        ; This tidbit tells the caller (if ax
  2359.                 jnz     do10            ; and bx are right on entry) that this
  2360.                 cmp     bx,3d8fh        ; routine (and therefore WAS) has been
  2361.                 jnz     do10            ; loaded.  It's how WAS detects for a
  2362.                 xchg    ax,bx           ; prior load of itself.
  2363.                 push    cs              ; Tell caller where we are by setting
  2364.                 pop     es              ; es to the cs of resident code.
  2365.                 iret
  2366. do10:           cmp     enabled?,1      ; Are we active?
  2367.                 je      our10           ; Yes, do our thing.
  2368.                 jmp     old10           ; No, pass it on.
  2369. our10:          mov     in10,1          ; WAS will not call hold from within
  2370.                 push    ax              ; this code because of this flag.
  2371.                 push    bx
  2372.                 push    cx
  2373.                 push    dx
  2374.                 push    ds
  2375.                 or      ah,ah           ; Save screen if mode set.
  2376.                 jz      savit
  2377.                 cmp     ah,6            ; Save if scrolling.
  2378.                 je      savit
  2379.                 cmp     ah,0eh          ; The TTY scrolling gets special
  2380.                 je      tty             ; handling.
  2381. call10:         pop     ds
  2382.                 pop     dx
  2383.                 pop     cx
  2384.                 pop     bx
  2385.                 pop     ax
  2386.                 pushf
  2387.                 call    old10
  2388.                 call    setvideo        ; Any changes in video parameters are
  2389.                 push    bx              ; now updated.
  2390.                 push    ds
  2391.                 call    slock2bl        ; If the scroll lock state is not zero,
  2392.                 jz      new10out        ; then maybe we can call hold.
  2393.                 call    chk8259         ; Check 8259A for in service interrupts.
  2394.                 jnz     new10out
  2395.                 cmp     inhold,0        ; In hold state already?  (Could be.  A
  2396.                 jne     new10out        ; pop-up routine may do an int 10h.)
  2397.                 mov     pause,bl        ; All's well so set pause and call hold.
  2398.                 call    hold
  2399. new10out:       pop     ds
  2400.                 pop     bx
  2401.                 mov     in10,0
  2402.                 iret
  2403. savit:          push    cs
  2404.                 pop     ds
  2405.                 cmp     saving,1
  2406.                 jne     tocall10
  2407.                 call    sav2ems
  2408. tocall10:       jmps    call10
  2409. tty:            cmp     al,7            ; Not concerned about BELL,
  2410.                 je      call10
  2411.                 cmp     al,8            ; BACKSPACE
  2412.                 je      call10
  2413.                 cmp     al,13           ; or RETURN
  2414.                 je      call10
  2415.                 mov     cx,40h
  2416.                 mov    ds,cx
  2417.  
  2418.                 assume  ds:biosdata
  2419.  
  2420.                 mov     bl,bh           ; The code (in sav2ems) does not allow
  2421.                 sub     bh,bh           ; the saving of scrolled lines from
  2422.                 shl     bx,1            ; video pages other than page 0, but
  2423.                 mov     cx,cursorpos[bx]; the code here is going to try in case
  2424.                 cmp     al,lf           ; other video pages are enabled at some
  2425.                 jne     lastcol?        ; later date (say by a command line
  2426.                 cmp     ch,numrows      ; switch).
  2427.                 jne     call10
  2428.                 cmp     double,1        ; is the double switch set?
  2429.                 je      call10          ; yes, no scroll for tty line feed
  2430. savalin:        mov     ax,601h         ; Interpret it as a scroll function.
  2431.                 sub     cx,cx
  2432.                 mov     dx,lastcol
  2433.                 jmps    savit
  2434. lastcol?:       cmp     cl,lastcol      ; If cursor is in the last column, then
  2435.                 je      savalin         ; the screen will scroll when the
  2436.                 jmps    call10          ; character is written.
  2437. new10           endp
  2438.  
  2439. ; resident code ends here
  2440.  
  2441. instmsg         db      cr,lf, 'WAS is already installed.  Only +, -, or v switches are valid now.', cr,lf, '$'
  2442. noemmmsg        db      cr,lf, "Cannot find Expanded Memory Manager.", cr,lf,'$'
  2443. nobufmsg        db      cr,lf, 'No buffer specified or invalid specification.', cr,lf,'$'
  2444. notenuf         db      cr,lf, "Not enough EMS memory for size of buffer specified.", cr,lf,'$'
  2445. badsavmsg       db      cr,lf, "Invalid maximum lines per screen specified.",cr,lf,'$'
  2446. installed       db      cr,lf, "WAS v",ver," Copyright 1990 by Charles Lazo III", cr,lf,'$'
  2447.  
  2448.                 assume  ds:code
  2449.  
  2450. new             db      1               ; If new = 1 then WAS.COM is freshly
  2451.                                         ; assembled, i.e., the coded summary
  2452.                                         ; file has not yet been annexed to
  2453.                                         ; WAS.COM.
  2454. sumfile         db      "W-DOC",version,".SUM", 0
  2455. nosumfile       db      cr,lf,"File W-DOC",version,".SUM cannot be opened.",cr,lf,'$'
  2456. sumhandle       dw      ?               ; file handle of coded summary file
  2457. sumsize         dw      ?               ; size of coded summay file
  2458. wasfile         db      "WAS.COM", 0
  2459. nowasfile       db      cr,lf,"The file WAS.COM cannot be opened.",cr,lf,'$'
  2460.  
  2461. getswitch       proc    near            ; A routine to detect the presence of
  2462.                 mov     bx,80h          ; a switch character on the command
  2463.                 mov     cl,[bx]         ; line.  Al contains the lowercase
  2464.                 or      cl,cl           ; character or symbol to be looked for.
  2465.                 jz      nocmd           ; If lowercase not found it then looks
  2466.                 push    es              ; for the capital as well.  If the
  2467.                 push    cs              ; switch is found, the routine returns
  2468.                 pop     es              ; with the zero flag set and di points
  2469.                 sub     ch,ch           ; to the first character after the
  2470.                 mov     di,82h          ; switch.
  2471.                 repne   scasb
  2472.                 je      gsout
  2473.                 mov     cl,[bx]
  2474.                 sub     ch,ch
  2475.                 mov     di,82h
  2476.                 cmp     al,'a'
  2477.                 jb      gsout           ; It's not a lowercase character.
  2478.                 cmp     al,'z'
  2479.                 ja      gsout           ; ditto.
  2480.                 and     al,0dfh         ; Convert to uppercase.
  2481.                 repne   scasb
  2482. gsout:          pop     es
  2483.                 ret
  2484. nocmd:          or      bx,bx
  2485.                 ret
  2486. getswitch       endp
  2487.  
  2488. deci2bin        proc    near            ; Convert ASCII decimal number at ds:di
  2489.                 mov     si,di           ; to binary value in bx
  2490.                 mov     cx,10
  2491.                 sub     ah,ah
  2492.                 sub     bx,bx
  2493. digit:          lodsb
  2494.                 cmp     al,'0'
  2495.                 jb      d2bout
  2496.                 cmp     al,'9'
  2497.                 ja      d2bout
  2498.                 sub     al,'0'
  2499.                 xchg    ax,bx
  2500.                 mul     cx
  2501.                 jo      d2bout
  2502.                 xchg    ax,bx
  2503.                 add     bx,ax
  2504.                 jc      d2bout
  2505.                 jmps    digit
  2506. d2bout:         ret
  2507. deci2bin        endp
  2508.  
  2509. start_stop      db      0
  2510.  
  2511. temp8           proc    far
  2512.                 inc     start_stop
  2513.                 jmp     old8
  2514. temp8           endp
  2515.  
  2516. ; Execution starts here after jump from entry point.
  2517.  
  2518. start:          push    es              ; The little int 8 splice in routine
  2519.                 mov     ax,3508h        ; above allows the determination of a
  2520.                 int     21h             ; double word count value that will
  2521.                 mov     old8hi,es       ; allow timing intervals to be the same
  2522.                 mov     old8lo,bx       ; no matter the speed of the CPU this
  2523.                                         ; program is run on.  The count is for
  2524.                 mov     dx,ofs temp8    ; the duration of one clock tick or
  2525.                 mov     ax,2508h        ; about 1/18 of a second.  This count
  2526.                 int     21h             ; is divided by a power of 2 constant,
  2527.                                         ; pwr2div.  The resulting count is used
  2528.                 sub     ax,ax           ; in the procedure called interval at
  2529.                 sub     dx,dx           ; the top of this file.
  2530. next_test:      cmp     start_stop,1
  2531.                 je      do_count
  2532.                 jmps    next_test
  2533.  
  2534. do_count:       cmp     start_stop,2
  2535.                 je      divdown
  2536.                 inc     ax
  2537.                 jnz     do_count
  2538.                 inc     dx
  2539.                 jnz     do_count
  2540.  
  2541. divdown:        mov     cx,pwr2div
  2542. divagain:       shr     dx,1
  2543.                 rcr     ax,1
  2544.                 loop    divagain
  2545.                 mov     countlo,ax
  2546.                 mov     counthi,dx
  2547.                 mov     start_stop,0    ; Don't want WAS.COM updated (when the
  2548.                                         ; summary file is annexed) without this
  2549.                                         ; set to zero.
  2550.                 push    ds
  2551.                 mov     ax,2508h        ; Now the former int 8 is replaced in
  2552.                 lds     dx,old8         ; case we have to exit due to an error.
  2553.                 int     21h
  2554.                 pop     ds
  2555.                 pop     es
  2556.  
  2557.                 cmp     new,1           ; The new flag will be set to 1 if WAS
  2558.                 je      test_s          ; .COM is freshly assembled.  It then
  2559.                 jmp     chkinst         ; needs to annex the command summary
  2560. test_s:         mov     al,'s'          ; file.  See the description of the
  2561.                 call    getswitch       ; process in the summary message at the
  2562.                 je      opensum         ; bottom of this source file.
  2563.                 jmp     showsummary
  2564. opensum:        mov     ax,3d00h        ; First open the command summary file.
  2565.                 mov     dx,ofs sumfile  ; The summary file is coded by packing
  2566.                 int     21h             ; spaces to reduce its size to about
  2567.                 jnc     findsumsize     ; a third of its uncompressed size.
  2568.                 mov     ah,9            ; If it can't be opened, say so and
  2569.                 mov     dx,ofs nosumfile
  2570.                 mov     al,1            ; exit with error code 1.
  2571.                 jmp     errexit
  2572. findsumsize:    mov     sumhandle,ax
  2573.                 mov     bx,ax
  2574.                 mov     ax,4202h        ; Find size of file using set file
  2575.                 sub     cx,cx           ; pointer call.
  2576.                 sub     dx,dx
  2577.                 int     21h
  2578.                 mov     sumsize,ax      ; Preserve size of coded summary file
  2579.                 mov     ax,4200h        ; Now we must set the file pointer back
  2580.                 mov     bx,sumhandle    ; to the beginning of the file.
  2581.                 sub     cx,cx
  2582.                 sub     dx,dx
  2583.                 int     21h
  2584.                 mov     ah,3fh          ; Then we read it into the memory now
  2585.                 mov     bx,sumhandle    ; containing the description of what is
  2586.                 mov     cx,sumsize      ; necessary to do all this.
  2587.                 mov     dx,ofs summary
  2588.                 int     21h
  2589.                 mov     ax,3d01h        ; Now open WAS.COM for writing.
  2590.                 mov     dx,ofs wasfile
  2591.                 int     21h
  2592.                 jnc     rewritewas
  2593.                 mov     ah,9            ; Say so and exit if can't find it in
  2594.                 mov     dx,ofs nowasfile; the current directory.
  2595.                 mov     al,2            ; exit with error code 3.
  2596.                 jmp     errexit
  2597. rewritewas:     mov     new,0           ; After rewrite WAS.COM is no longer
  2598.                 mov     bx,ax           ; "new".
  2599.                 mov     ah,40h
  2600.                 mov     dx,100h         ; Code saved starts after the PSP.
  2601.                 mov     cx,ofs summary
  2602.                 sub     cx,dx
  2603.                 add     cx,sumsize
  2604.                 int     21h             ; Write coded summary to WAS.COM.
  2605. coolexit:       mov     ax,4c00h        ; No problems, return code = 0.
  2606.                 int     21h
  2607. showsummary:    mov     ah,9            ; Show user how to use 's' switch.
  2608.                 mov     dx,ofs summary
  2609.                 int     21h
  2610.                 jmps    coolexit
  2611.  
  2612. chkinst:        mov     ax,7b1eh        ; Is WAS presently installed?
  2613.                 mov     bx,3d8fh
  2614.                 int     10h
  2615.                 sub     bx,ax
  2616.                 sub     bx,ax
  2617.                 jnz     install         ; no, go for install
  2618.  
  2619.                 assume  es:code
  2620.  
  2621.                 mov     al,'+'          ; Check for either '+' or
  2622.                 call    getswitch
  2623.                 jne     chkminus
  2624.                 mov     es:enabled?,1
  2625.                 jmps    coolexit
  2626.  
  2627. chkminus:       mov     al,'-'          ; minus or
  2628.                 call    getswitch
  2629.                 jne     chkversion
  2630.                 mov     es:enabled?,0
  2631.                 jmps    coolexit
  2632.  
  2633. chkversion:     mov     al,'v'          ; version switches.
  2634.                 call    getswitch
  2635.                 jne     present
  2636.                 mov     ah,9
  2637.                 mov     dx,ofs installed; Show version message
  2638.                 int     21h
  2639.                 jmps    coolexit
  2640.  
  2641.                 assume  es:nothing
  2642.  
  2643. present:        mov     dx,ofs instmsg  ; WAS is already installed and no '+'
  2644.                 mov     al,3            ; or '-' or 'v' switch found.
  2645.                 jmps    errexit         ; So exit with error message.
  2646.  
  2647. noemm:          mov     dx,ofs noemmmsg ; Message and exit if no EMM manager is
  2648.                 mov     al,4            ; installed.
  2649.                 jmps    errexit
  2650.  
  2651. badsavsiz:      mov     dx,ofs badsavmsg; Message and exit of screen lines to
  2652.                 mov     al,5            ; save is too large.
  2653.                 jmps    errexit
  2654.  
  2655. nobuf:          mov     dx,ofs nobufmsg ; Message and exit if no scroll back
  2656.                 mov     al,6            ; buffer has been specified, or if
  2657.                 jmps    errexit         ; invalid specification has been made.
  2658.  
  2659. errexit:        mov     ah,9            ; Send message at ds:dx, then exit with
  2660.                 push    ax              ; error code in al.
  2661.                 int     21h
  2662.                 call    buzz
  2663.                 pop     ax
  2664.                 mov     ah,4ch
  2665.                 int     21h
  2666.  
  2667. emmsig          db      'EMMXXXX0'      ; signature of expanded memory manager
  2668.  
  2669. install:        mov     ax,3567h        ; check for presence of EMM
  2670.                 push    es
  2671.                 int     21h
  2672.                 mov     di,10
  2673.                 mov     si,ofs emmsig
  2674.                 mov     cx,4
  2675.                 rep     cmpsw
  2676.                 pop     es
  2677.                 jne     noemm           ; error exit if not there
  2678.  
  2679.                 mov     al,'l'
  2680.                 call    getswitch
  2681.                 jne     getmem          ; no 'l' switch, check 'b' switch
  2682.                 call    deci2bin
  2683.                 jo      badsavsiz       ; invalid screen save size
  2684.                 cmp     bx,minlines
  2685.                 jb      badsavsiz       ; not less than minimum screen lines
  2686.                 cmp     bx,maxlines     ; musn't be over maximum screen lines
  2687.                 ja      badsavsiz
  2688.                 mov     ax,linsiz
  2689.                 mul     bx
  2690.                 inc     ax
  2691.                 mov     scrsavsiz,ax
  2692.                 mov     bx,k16
  2693.                 sub     bx,ax
  2694.                 mov     scrsavofs,bx
  2695.  
  2696. getmem:         mov     al,'b'          ; Find the 'b' switch.
  2697.                 call    getswitch
  2698.                 jne     nobuf           ; If can't say so and exit.
  2699.                 call    deci2bin        ; convert decimal size to binary in bx
  2700.                 jo      nobuf           ; bad if overflow
  2701.                 or      bx,bx           ; Error if zero.
  2702.                 jz      nobuf
  2703.                 mov     ax,bx
  2704.                 dec     ax              ; Otherwize, the number of pages less
  2705.                 mov     lastpg,ax       ; one is the last logical page.
  2706.                 mov     ah,43h          ; Ask for this many EMS pages.
  2707.                 int     67h
  2708.                 or      ah,ah           ; Error?
  2709.                 jz      gotmem
  2710.                 mov     dx,ofs notenuf  ; Yes, say there's not enough and exit.
  2711.                 mov     al,7
  2712.                 jmps    errexit
  2713.  
  2714. gotmem:         mov     handle,dx
  2715.                 mov     ax,lastpg       ; Do calculations to set lastofs.
  2716.                 mov     cx,k16 mod linsiz
  2717.                 mul     cx
  2718.                 add     ax,scrsavofs
  2719.                 mov     bx,linsiz
  2720.                 div     bx
  2721.                 mov     cx,scrsavofs
  2722.                 mov     lastofs,cx
  2723.                 sub     lastofs,dx
  2724.  
  2725.                 mov     cx,ax
  2726.                 mov     ax,k16 / linsiz
  2727.                 mul     lastpg
  2728.                 add     ax,cx
  2729.                 mul     bx
  2730.                 mov     endofslo,ax     ; Could just as easily have called the
  2731.                 mov     endofshi,dx     ; unresolve routine on lastpg:lastofs
  2732.  
  2733.                 mov     ah,41h          ; Store away the page frame segment.
  2734.                 int     67h
  2735.                 mov     pfseg,bx
  2736.  
  2737.                 mov     al,'n'
  2738.                 call    getswitch       ; Is the 'n' switch present?
  2739.                 je      testevga        ; Yes, don't place command summary into
  2740.                 mov     cx,lastpg       ; the scroll buffer.
  2741.                 inc     cx
  2742.                 cmp     cx,4            ; Map however many pages necessary to
  2743.                 jbe     ofsbase         ; read in entire command summary.
  2744.                 mov     cx,4
  2745. ofsbase:        mov     dx,cx
  2746.                 mov     lastpage,-1     ; Set this value to something other
  2747. mapnext:        mov     bx,dx           ; than zero so that a page will be read
  2748.                 sub     bx,cx           ; into physical page zero.  (See ems
  2749.                 mov     al,bl           ; procedure for details on the use of
  2750.                 mov     ah,44h          ; lastpage variable.)
  2751.                 call    ems
  2752.                 loop    mapnext
  2753.                 mov     es,pfseg
  2754.                 sub     di,di
  2755.                 mov     si,ofs summary
  2756.                 mov     cx,sumsize      ; number of coded bytes to process
  2757.                 jmps    nxtsumbyte      ; begin command summary decoding
  2758.  
  2759. lastattr        db      sumbg           ; The last attribute used for a decoded
  2760.                                         ; character.  It is the attribute used
  2761.                                         ; for decoded single spaces.
  2762.  
  2763. nxtsumbyte:     lodsb                   ; Get a coded, command summary byte.
  2764.                 test    al,80h          ; Is it a coded series of spaces?
  2765.                 jz      getattr         ; No, got character, now get attribute.
  2766.                 push    cx
  2767.                 mov     cl,al           ; Calculate number of spaces to store.
  2768.                 and     cl,7fh
  2769.                 sub     ch,ch
  2770.                 mov     al,' '          ; Store spaces.
  2771.                 cmp     cx,2            ; And if it's more than two spaces...
  2772.                 jbe     setsumattr
  2773.                 mov     lastattr,sumbg  ; use sumbg (summary background) attr.
  2774. setsumattr:     mov     ah,lastattr     ; else last character attribute is used
  2775.                 rep     stosw
  2776.                 pop     cx
  2777.                 loop    nxtsumbyte
  2778.                 jmps    dotailo
  2779. getattr:        mov     ah,al           ; character to ah
  2780.                 lodsb                   ; attribute to al
  2781.                 dec     cx              ; adjust count
  2782.                 xchg    ah,al           ; character al, attribute ah
  2783.                 mov     lastattr,ah     ; save attribute
  2784.                 stosw
  2785.                 loop    nxtsumbyte
  2786. dotailo:        cmp     endofslo,di
  2787.                 jae     setailo
  2788.                 mov     di,endofslo
  2789. setailo:        mov     taillo,di
  2790.  
  2791. testevga:       mov     ah,12h          ; Test for presence of EGA or VGA.
  2792.                 mov     bx,1010h        ; If present, then number of rows and
  2793.                 int     10h             ; character height will be found in the
  2794.                 cmp     bh,1            ; BIOS data area, otherwise they are
  2795.                 ja      initvideo       ; already known depending upon MDA or
  2796.                 mov     evga,1          ; CGA.
  2797.  
  2798. initvideo:      call    setvideo        ; Be sure video parameters are set
  2799.                                         ; properly from the beginning.
  2800.  
  2801.                 mov     al,'-'          ; Are we to be disabled from the getgo?
  2802.                 call    getswitch
  2803.                 jne     double?         ; No, see if double switch is set.
  2804.                 mov     enabled?,0      ; Yes, reset active flag.
  2805.  
  2806. double?:        mov     al,'d'          ; Is the d switch set?
  2807.                 call    getswitch       ; (see documentation)
  2808.                 jne     esc_enable?     ; No, see if ESCape enable switch set.
  2809.                 mov     double,1        ; Yes, set double flag.
  2810.  
  2811. esc_enable?:    mov     al,'e'          ; Is the e switch set?
  2812.                 call    getswitch       ; (ESCape key to release Scroll Lock?)
  2813.                 jne     goodbyenv       ; No, carry on.
  2814.                 mov     esc_enable,1    ; Yes, ESCape key can cancel hold.
  2815.  
  2816. goodbyenv:      mov     es,env          ; Release memory of environment.
  2817.                 mov     ah,49h
  2818.                 int     21h
  2819.  
  2820.                 mov     ax,2508h        ; Set up new int 8,
  2821.                 mov     dx,ofs new8
  2822.                 int     21h
  2823.  
  2824.                 mov     ax,3510h
  2825.                 int     21h
  2826.                 mov     old10lo,bx
  2827.                 mov     old10hi,es
  2828.  
  2829.                 mov     ax,2510h        ; and int 10h routines
  2830.                 mov     dx,ofs new10
  2831.                 int     21h
  2832.  
  2833.                 assume  ds:biosdata
  2834.  
  2835.                 push    ds              ; An older PC (with BIOS date before
  2836.                 mov     ax,40h          ; the first XT BIOS) will not have
  2837.                 mov     ds,ax           ; the locations kbdstart (40:80) and
  2838.                 mov     bx,kbdhead      ; kbdend (40:82) initialized to the
  2839.                 cmp     wp[bx],3eh      ; start and end respectively of the
  2840.                 ja      back2cs         ; keyboard buffer.  So we do that
  2841.                 mov     kbdstart,1eh    ; initialization here if necessary
  2842.                 mov     kbdend,3eh      ; because kbdstart and kbdend will be
  2843. back2cs:        pop     ds              ; used later in our code.
  2844.  
  2845.                 assume  ds:code
  2846.  
  2847.                 mov     dx,ofs installed; Display copyright message and TSR.
  2848.                 mov     ah,9
  2849.                 int     21h
  2850.  
  2851.                 mov     dx,ofs instmsg + 15
  2852.                 mov     cl,4
  2853.                 shr     dx,cl
  2854.                 mov     ax,3100h
  2855.                 int     21h
  2856.  
  2857. summary:        db      cr,lf
  2858. db " When WAS.COM has been newly assembled, linked, and exe2bined as is the case",cr,lf
  2859. db " now (otherwise this message would not be displayed), you must run WAS with",cr,lf
  2860. db " the 's' switch to force it to incorporate the W-DOC",version,".SUM file into WAS.COM",cr,lf
  2861. db " so that this file (W-DOC",version,".SUM) can be available as a part of WAS to be put",cr,lf
  2862. db " into the scroll back buffer as a command summary.  The command summary is put",cr,lf
  2863. db " into the scroll back buffer by default.  That action is disabled by use of",cr,lf
  2864. db " the 'n' (No summary) switch.  (The file, W-DOC",version,".SUM, is a coded version of",cr,lf
  2865. db " file SUMMARY.",version," [coded by packing spaces] which is in turn a file containing",cr,lf
  2866. db " command summary information in a format that reflects its use, i.e., a video",cr,lf
  2867. db " memory image.  It includes text characters as well as character attributes.",cr,lf
  2868. db " The program SPCPAK.EXE can be used to transform an edited version of the",cr,lf
  2869. db " SUMMARY.",version," file into an updated W-DOC",version,".SUM file.)  Now that you have a",cr,lf
  2870. db " newly assembled copy of WAS.COM enter this command at the prompt (Be sure",cr,lf
  2871. db " that you are running WAS.COM together in the same directory as the coded",cr,lf
  2872. db " summary file, W-DOC",version,".SUM.):",cr,lf,lf
  2873. db "                                       WAS s",cr,lf,'$'
  2874.  
  2875. code            ends
  2876.                 end     entry
  2877.