home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 15 / CDACTUAL15.iso / cdactual / program / asm / MSKERMIT.ZIP / MSYIBM.ASM < prev   
Encoding:
Assembly Source File  |  1985-01-03  |  29.9 KB  |  1,150 lines

  1.  
  2.     title term
  3.  
  4.     public    term, gss        ; entry points
  5.     include msdefs.h
  6.  
  7. ; some character definitions
  8.  
  9. chesc    equ    27
  10. bel    equ    7
  11.  
  12. print_out equ    05h            ; dos function to print to printer
  13. pbout    equ    02h            ; dos function to print a character
  14. prscan    equ    72h            ; print-screen scan code...
  15. upscan    equ    49h            ; up page
  16. dnscan    equ    51h            ; down page
  17. ctlup    equ    84h            ; ctl-up page
  18. ctldn    equ    76h            ; ctl-down page
  19. homscn    equ    47h            ; home screen
  20. endscn    equ    4fh            ; end of screen
  21. screen    equ    10h            ; bios screen call
  22. kb    equ    16h            ; keyboard interrupt
  23. alt_shift equ    8H            ; alt shift key down
  24. ctl_shift equ    4H            ; ctl key down
  25. left_shift equ    2H            ; left shift key down
  26. right_shift equ 1H            ; right shift key down
  27.  
  28. timer    equ    40h            ; timer port
  29. bel_prt equ    61h            ; speaker control
  30.  
  31. crt_status equ    3dah            ; crt status port
  32. disp_enb   equ    8            ; display enable bit
  33.  
  34. uparr    equ    48h            ; scan codes for arrow keys
  35. dnarr    equ    50h
  36. lftarr    equ    4bh
  37. rgtarr    equ    4dh
  38.  
  39.  
  40. modfrm    struc                ; format of mode line
  41.     db    'Esc chr: '
  42. m_echr    db    2 dup (?)
  43.     db    ', Port: '
  44. m_prt    db    1 dup (?)
  45.     db    ', Speed: '
  46. m_baud    db    4 dup (?)
  47.     db    ', Parity: '
  48. m_par    db    4 dup (?)
  49.     db    ', Echo: '
  50. m_echo    db    3 dup (?)
  51.     db    ', Type '
  52. m_hlp    db    2 dup (?)
  53.     db    '? for Help'
  54. modfrm    ends
  55.  
  56. datas    segment public 'datas'
  57. waste    db    100h dup (?)        ;*** need this junk because assembler
  58.                     ;*** generates non-relocatable offsets
  59.                     ;*** for things like
  60.                     ;*** "sub di,offset foo"
  61.                     ;*** if offset foo < 100H
  62. ; stuff for screen routines
  63. flags    db    ?            ; status flags...
  64. flags1    db    0            ; internal flags.
  65. prtscr    equ    80h            ; print screen pressed
  66. lnwrap    equ    40h            ; line wrap enabled.
  67. inited    equ    08h            ; been here before...
  68. cursor    dw    ?
  69. esc_ch    db    ?
  70. argadr    dw    ?            ; address of arg blk
  71. ckeys    db    0,prscan,dnscan,upscan,endscn,homscn,ctlup,ctldn
  72.     db    uparr,dnarr,lftarr,rgtarr
  73. lckeys    equ    $-ckeys
  74. ; ckacts must parallel ckeys above...
  75. ckacts    dw    trnbrk,trnprs,upwpg,dnwpg,endwnd,homwnd,dnwind,upwind
  76.     dw    trnupw,trndnw,trnlfw,trnrgw
  77.  
  78. uptrn    db    esc,'A'
  79. dntrn    db    esc,'B'
  80. rgtrn    db    esc,'C'
  81. lftrn    db    esc,'D'
  82.  
  83. spctab    db    chesc,cr,lf,bs,tab,bel
  84. lspctab equ    $-spctab
  85. spcjmp    dw    outesc,outcr,outlf,outbs,outtab,outbel    ; must match spctab
  86. esctab    db    'YABCDEFGHIJKLM'
  87.     db    'NOZ@[pq<vw'
  88. lesctab equ    $-esctab
  89. ; escjmp must parallel esctab above
  90. escjmp    dw    movcur,curup,curdwn,currt,outbs,clrscr,outign,outign,curhom
  91.     dw    revind,clreow,clreol,inslin,dellin,delchr,noins
  92.     dw    vtident,entins,doansi
  93.     dw    invvid,nrmvid,outign,dowrap,nowrap
  94. vtidstr db    chesc,'/K'
  95. lvtidst equ    $-vtidstr
  96. coord    dw    ?
  97. insmod    db    ?
  98. wcoord    dw    ?
  99. ttstate dw    outtt0
  100. curattr db    ?            ; current attribute
  101. ansarg    db    ?            ; ansi argument value
  102. igncnt    db    ?            ; # of chars to ignore
  103. beldiv    dw    2dch            ; 550 hz?
  104. crt_mode db    ?
  105. crt_cols db    ?
  106. crt_lins db    ?
  107. low_rgt dw    ?            ; lower right corner of window
  108. ; key redefinitions
  109. ktrntab dw    ?            ; address of translation table
  110. krpltab dw    ?            ; address of replacement table
  111. tmptab    db    0eh,3bh         ; scan code for bs, f1
  112. ktlen    dw    ?
  113. modbuf    modfrm    <>            ; mode line buffer
  114. ; routine to call for captured output
  115. captrtn dw    ?
  116. ; some static data for mode line
  117. unkbaud db    'Unk '                  ; must be 4 chars...
  118. baudn    db    '45.5'
  119.     db    '  50'
  120.     db    '  75'
  121.     db    ' 110'
  122.     db    ' 135'
  123.     db    ' 150'
  124.     db    ' 300'
  125.     db    ' 600'
  126.     db    '1200'
  127.     db    '1800'
  128.     db    '2000'
  129.     db    '2400'
  130.     db    '4800'
  131.     db    '9600'
  132. baudnsiz  equ    14            ; # of baud rates known (tbl size / 4)
  133. parnams db    'Even'
  134.     db    'Mark'
  135.     db    'None'
  136.     db    'Odd '                  ; must be 4 chars
  137.     db    'Spc '
  138. offmsg    db    'Off'
  139. onmsg    db    'On '
  140. lclmsg    db    'Lcl'
  141. remmsg    db    'Rem'
  142. ; storage for multi-window stuff
  143. swidth    equ    80
  144. slen    equ    24
  145. npgs    equ    5            ; # of pages on each side
  146. bsize    equ    swidth*slen*npgs*2
  147. scrsav    dw    swidth*slen dup (0700H) ; a blank screen
  148.  
  149. ; circular buffer.  To work properly, the buffer size should be an exact
  150. ; multiple of swidth*2
  151. cbuf    struc
  152. pp    dw    ?            ; place ptr in buffer
  153. bend    dw    ?            ; end of buffer
  154. orig    dw    ?            ; buffer origin
  155. lcnt    dw    0            ; # of lines in buffer.
  156. cbuf    ends
  157.  
  158. topbuf    db    bsize dup (?)
  159. botbuf    db    bsize dup (?)        ; top and bottom windows
  160. tlbuf    db    swidth*2 dup (?)
  161. blbuf    db    swidth*2 dup (?)
  162. twnd    cbuf    <topbuf,topbuf+bsize-1,topbuf,0>
  163. bwnd    cbuf    <botbuf,botbuf+bsize-1,botbuf,0>
  164. portno    db    ?
  165. prton    db    'Printer: on'
  166. prtnlen equ    $-prton
  167. prtoff    db    'Printer: off'
  168. prtflen equ    $-prtoff
  169. datas    ends
  170.  
  171. code    segment public            ; code segment
  172.     extrn    prtchr:near,outchr:near,sendbr:near
  173.     assume    cs:code,ds:datas,es:datas
  174.  
  175. scrini    proc    near            ; init screen stuff
  176.     mov    ah,15            ; read video state...
  177.     int    screen
  178.     mov    crt_mode,al        ; save crt mode
  179.     cmp    ah,crt_cols        ; is real # of cols < passed?
  180.     jge    scrin1            ; no
  181.     mov    crt_cols,ah        ; yes, save # of cols
  182. scrin1: mov    dl,crt_cols        ; # of cols again
  183.     mov    dh,crt_lins        ; and # of rows
  184.     dec    dl
  185.     dec    dh
  186.     mov    low_rgt,dx        ; save away window address
  187.     mov    insmod,0        ; not in insert mode
  188.     mov    dx,cursor        ; assume old cursor
  189.     test    flags1,inited        ; have we been here before?
  190.     jnz    scrin4            ; yes, use old cursor
  191.     mov    curattr,07        ; else set nice screen attribute
  192.     mov    ttstate,offset outtt0    ; normal screen state
  193.     mov    ah,3            ; figure out where cursor is
  194.     xor    bh,bh            ; page 0
  195.     int    screen            ; read cursor position
  196.     cmp    dh,crt_lins        ; past logical end of screen?
  197.     jb    scrin2            ; no, keep going
  198.     mov    dh,byte ptr low_rgt+1    ; yes, just use lower right corner
  199. scrin2: cmp    dl,crt_cols        ; maybe past right margin
  200.     jb    scrin3            ; no, use the way it is
  201.     mov    dl,byte ptr low_rgt
  202. scrin3: mov    cursor,dx        ; init cursor
  203. scrin4: mov    ah,2
  204.     xor    bh,bh
  205.     int    screen            ; set cursor in case it moved
  206.     ret
  207. scrini    endp
  208.  
  209. argini    proc    near            ; read passed arguments
  210.     mov    bx,argadr        ; base of argument block
  211.     mov    al,[bx].flgs        ; get flags
  212.     and    al,capt+emheath+havtt+trnctl+lclecho+modoff
  213.     mov    flags,al        ; mask for allowable and save
  214.     and    flags1,not (prtscr)    ; these are allowable
  215.                     ; (others remain).
  216.     mov    al,[bx].prt
  217.     cmp    al,portno        ; using same port?
  218.     je    argin1            ; yes, go on
  219.     and    flags1,not inited    ; else re-init stuff
  220. argin1: mov    portno,al        ; update port number
  221.     mov    al,[bx].cols
  222.     mov    crt_cols,al
  223.     mov    al,[bx].rows
  224.     mov    crt_lins,al        ; init # of rows and cols
  225.     mov    ax,[bx].captr
  226.     mov    captrtn,ax        ; buffer capture routine
  227.     mov    ax,[bx].belld
  228.     mov    beldiv,ax        ; bell divisor
  229.     mov    ax,[bx].klen
  230.     mov    ktlen,ax        ; length of key redef tbl
  231.     mov    ax,[bx].ktab
  232.     mov    ktrntab,ax        ; save key translation table
  233.     mov    ax,[bx].krpl
  234.     mov    krpltab,ax
  235.     mov    al,[bx].escc
  236.     mov    esc_ch,al
  237.     ret                ; that's it
  238. argini    endp
  239.  
  240. modlin    proc    near            ; turn on mode line
  241.     mov    al,esc_ch
  242.     mov    modbuf.m_echr,' '       ; first char is initial space
  243.     mov    modbuf.m_hlp,' '        ; goes here too.
  244.     cmp    al,32            ; printable?
  245.     jnb    modl1            ; yes, keep going
  246.     add    al,40h            ; made printable
  247.     mov    modbuf.m_echr,'^'       ; note control char
  248.     mov    modbuf.m_hlp,'^'
  249. modl1:    mov    modbuf.m_echr+1,al    ; fill in character
  250.     mov    modbuf.m_hlp+1,al
  251.     mov    bx,argadr        ; get argument block
  252.     mov    al,[bx].baudb        ; get baud bits
  253.     mov    si,offset unkbaud    ; assume unknown baud
  254.     cmp    al,baudnsiz        ; too big?
  255.     jnb    modl2            ; yes, use default
  256.     mov    cl,2            ; each is 4 bytes long
  257.     shl    al,cl
  258.     mov    ah,0
  259.     add    ax,offset baudn
  260.     mov    si,ax
  261. modl2:    mov    cx,size m_baud        ; length of baud space
  262.     mov    di,offset modbuf.m_baud
  263.     rep    movsb            ; copy in baud rate
  264.     mov    al,[bx].parity        ; get parity code
  265.     mov    cl,2            ; each is 4 bytes long...
  266.     shl    al,cl
  267.     mov    ah,0
  268.     add    ax,offset parnams    ; names of parity settings
  269.     mov    si,ax
  270.     mov    cx,4            ; each is 4 long
  271.     mov    di,offset modbuf.m_par
  272.     rep    movsb
  273.     mov    si,offset lclmsg    ; assume remote echoing
  274.     test    flags,lclecho        ; echoing?
  275.     jz    modl4            ; no, keep going
  276.     mov    si,offset remmsg
  277. modl4:    mov    cx,3            ; size of on/off
  278.     mov    di,offset modbuf.m_echo
  279.     rep    movsb
  280.     mov    al,'1'
  281.     cmp    portno,1        ; port 1?
  282.     je    modl5            ; yes, keep going
  283.     mov    al,'2'
  284. modl5:    mov    modbuf.m_prt,al     ; fill in port number
  285.     mov    cx,size modfrm        ; this is size of mode line
  286.     mov    si,offset modbuf    ; mode line image
  287. ; alternate entry to write an alternate mode line
  288. modwrt: push    cx
  289.     push    si            ; save mode line and size
  290.     mov    dx,24 * 100h        ; 25th line for mode line
  291.     push    word ptr curattr    ; save current attributes
  292.     mov    curattr,70h        ; want inverse video
  293.     call    clreol            ; clear to end of line...
  294.     pop    word ptr curattr    ; restore attributes
  295.     mov    dx,24 * 100h
  296.     mov    bh,0
  297.     mov    ah,2            ; set cursor position
  298.     int    screen
  299.     pop    si
  300.     pop    cx            ; restore these
  301. modl6:    lodsb                ; get a byte
  302.     mov    ah,14            ; write to terminal
  303.     mov    bh,0            ; page 0
  304.     int    screen
  305.     loop    modl6            ; write out entire mode line
  306.     mov    dx,cursor
  307.     mov    ah,2
  308.     mov    bh,0
  309.     int    screen            ; put cursor back where it belongs
  310.     ret                ; and return
  311. modlin    endp
  312.  
  313. clrmod    proc    near            ; clear mode line
  314.     mov    ax,600h         ; blank window
  315.     mov    cx,24 * 100h        ; beginning of window
  316.     mov    dx,24 * 100h + 79    ; end of window
  317.     mov    bh,07            ; nice attribute
  318.     int    screen            ; clear mode line
  319.     ret                ; and return
  320. clrmod    endp
  321.  
  322. term    proc    near            ; terminal emulator entry point
  323.  
  324.     mov    argadr,ax        ; save argument ptr
  325.     push    es            ; save caller's extra segment address
  326.     mov    ax,seg datas
  327.     mov    es,ax
  328.  
  329.     call    argini            ; init options from arg address
  330.  
  331.     call    scrini            ; init screen stuff
  332.  
  333.     test    flags1,inited        ; have we run yet?
  334.     jz    term1            ; no, forget this part
  335.     call    restscr         ; restore screen
  336. term1:    or    flags1,inited        ; remember we've run already.
  337.  
  338.     call    clrmod            ; empty mode line
  339.     test    flags,modoff        ; is mode line disabled?
  340.     jnz    lp            ; yes, skip it
  341.     call    modlin            ; turn on mode line
  342.  
  343. lp:    call    portchr         ; char at port?
  344.      jnc    chkinp            ; no, keep going
  345.     call    outtty            ; print on terminal
  346.  
  347. chkinp: mov    ah,1
  348.     int    kb
  349.     jz    lp            ; nothing available...
  350.     xor    ah,ah
  351.     int    kb            ; get the char from the buffer
  352.     push    ax            ; save character temporarily
  353.     call    gss            ; get shift state into al
  354.     mov    bl,al            ; save shift state
  355.     pop    ax
  356.  
  357.     cmp    al,esc_ch        ; escape character?
  358.     je    quit            ; yes, stop here
  359.  
  360.     call    trnout            ; translate if nec., output to prt
  361.     jmp    chkinp            ; and keep going
  362.  
  363. quit:    call    clrmod            ; erase mode line
  364.     call    savescr         ; save screen
  365.  
  366.     mov    al,flags
  367.     mov    bx,argadr
  368.     mov    [bx].flgs,al        ; update flags in arg block
  369.     pop    es            ; restore segment register
  370.     ret                ; and return to caller
  371.  
  372. term    endp
  373.  
  374. ; get shift state into al.  We only care about shift, ctl, and alt keys.
  375. ; right shift is collapsed into left shift.
  376. gss    proc    near
  377.     mov    ah,2
  378.     int    kb            ; get current shift state
  379.     mov    bl,al            ; copy for a moment
  380.     and    bl,right_shift        ; mask out all but right shift
  381.     shl    bl,1            ; move right shift to left shift pos
  382.     or    al,bl            ; collapse shift bits
  383.     and    al,(left_shift + alt_shift + ctl_shift)
  384.     ret
  385. gss    endp
  386.  
  387. ; save the screen so we can restore it
  388. ; maybe save cursor also.
  389. savescr proc    near
  390.     push    ds
  391.     mov    si,0
  392.     mov    di,offset scrsav    ; place to put screen
  393.     mov    cx,80*24        ; # of words on screen
  394.     call    scrseg
  395.     push    ax            ; save screen segment
  396.     call    scrwait         ; wait for screen to be ready
  397.     pop    ds            ; address screen
  398.     rep    movsw            ; save the screen
  399.     pop    ds            ; restore this
  400.     ret                ; and return
  401. savescr endp
  402.  
  403. ; restore screen from scrsav buffer
  404. restscr proc    near
  405.     push    es
  406.     mov    si,offset scrsav    ; source
  407.     mov    di,0
  408.     mov    cx,80*24
  409.     call    scrseg
  410.     mov    es,ax
  411.     call    scrwait
  412.     rep    movsw            ; restore it
  413.     pop    es
  414.     ret
  415. restscr endp
  416.  
  417. ; send the character in al out to the serial port
  418. ; handle echoing also...
  419. outprt    proc    near
  420.     test    flags,lclecho        ; echoing?
  421.     jz    outpr1            ; no, forget it
  422.     push    ax            ; save char
  423.     call    outtty            ; print it
  424.     pop    ax            ; restore
  425. outpr1: mov    ah,al            ; this is where outchr expects it
  426.     call    outchr            ; output to the port
  427.      nop
  428.      nop
  429.      nop                ; skip returns...
  430.     ret
  431. outprt    endp
  432.  
  433. ; returns with carry on if a character is available
  434.  
  435. portchr proc    near
  436.     call    prtchr            ; character at port?
  437.      jmp    short portc1        ; yes, go handle
  438.     nop                ; skip return is stupid...
  439.     clc                ; no carry -> no character
  440.     ret                ; and return...
  441. portc1: and    al,7fh            ; we don't worry about parity here
  442.     stc                ; have a character
  443.     ret                ; and return
  444. portchr endp
  445.  
  446.  
  447. ; translate the scan code in ah according to the translate table
  448. ; given in ktrntab/krpltab, output to port.  If no translation,
  449. ; use ascii char in al. (should probably include shift state
  450. ; somewhere).  Shift state is in bl.
  451. trnout    proc    near
  452.     cmp    ah,4eh            ;*** plus key thing?
  453.     je    trnmod            ; yes, go toggle mode line
  454. trnou1: test    flags,havtt        ; translate table given?
  455.     jz    trnou3            ; no, just output character
  456.     push    ax            ; save original value
  457.     mov    al,ah            ; put scan code into ah
  458.     mov    ah,bl            ; shift state into top half.
  459.     mov    di,ktrntab        ; pick up translate tbl
  460.     mov    cx,ktlen        ; length of tbl
  461.     repne    scasw            ; look for our key
  462.     pop    ax            ; recover character
  463.     jne    trnou3            ; not found, forget it
  464.     sub    di,ktrntab        ; get index into tbl
  465.     sub    di,2            ; (minus 2 for pre-increment)
  466.     mov    bx,krpltab        ; get replacement table
  467.     mov    si,[bx][di]        ; and addr of replacement
  468.     mov    cl,[si]         ; get first byte (length)
  469.     xor    ch,ch            ; clear high-order byte
  470.     inc    si            ; point to translation string
  471. trnou2: lodsb                ; get a byte
  472.     push    si
  473.     push    cx            ; save important registers
  474.     call    outprt            ; s
  475.     pop    cx
  476.     pop    si
  477.     loop    trnou2
  478.     ret
  479. trnou3:    cmp    al,0
  480.     jnz    trnou4
  481.     mov    al,ah
  482.     mov    cx,lckeys        ; length of table
  483.     mov    di,offset ckeys     ; table address
  484.     repne    scasb
  485.     mov    al,0            ; ascii code was 0...
  486.     jne    trnou4            ; not found, keep going
  487.     sub    di,offset ckeys+1    ; get table offset
  488.     shl    di,1            ; shift for word offset
  489.     jmp    ckacts[di]        ; jump to appropriate routine
  490. trnou4: call    outprt            ; just output single char
  491.     ret                ; and return
  492.  
  493. trnmod: test    flags,modoff        ; mode line already off?
  494.     jnz    trnm1            ; yes, go turn on
  495.     call    clrmod            ; no, clear mode line here
  496.     or    flags,modoff        ; turn on flag
  497.     ret                ; and return
  498. trnm1:    call    modlin            ; turn on mode line
  499.     and    flags,not modoff    ; clear flag
  500.     ret                ; and return
  501.  
  502. trnbrk: mov    ah,dconio
  503.     mov    dl,0ffH
  504.     int    dos            ; read the bogus ^C DOS gets.
  505.     call    sendbr
  506.     ret
  507. trnprs: xor    flags1,prtscr        ; flip the flag
  508.     and    flags,not modoff    ; turn on mode line
  509.     mov    si,offset prton
  510.     mov    cx,prtnlen
  511.     test    flags1,prtscr        ; did it go on?
  512.     jnz    trnpr1            ; yes, say so
  513.     mov    si,offset prtoff
  514.     mov    cx,prtflen
  515. trnpr1: call    modwrt            ; write into mode line
  516.     ret                ; and return
  517.  
  518. ; common entry for arrow keys
  519. trnarr: mov    cx,2            ; length is always 2
  520.     jmp    trnou2            ; go send definition
  521.  
  522. trnupw: mov    si,offset uptrn
  523.     jmp    trnarr
  524.  
  525. trndnw: mov    si,offset dntrn
  526.     jmp    trnarr
  527.  
  528. trnlfw: mov    si,offset lftrn
  529.     jmp    trnarr
  530.  
  531. trnrgw: mov    si,offset rgtrn
  532.     jmp    trnarr
  533.  
  534. trnout    endp
  535.  
  536. ; move viewing window up (screen moves down).
  537. ; alternate entry upwin2 doesn't beep if invalid.
  538. upwind    proc    near
  539.     mov    ax,offset tlbuf ; place to put line temporarily
  540.     mov    bx,offset twnd ; where to get lines from
  541.     call    getcirc     ; try to get a line
  542.     jnc    upwin3        ; have a line, go show it
  543.     call    outbel        ; else ring bel
  544.     ret            ; and return
  545. upwin2: mov    ax,offset tlbuf
  546.     mov    bx,offset twnd
  547.     call    getcirc
  548.     jnc    upwin3
  549.     ret            ; this just rets if no line avail.
  550. upwin3: mov    ax,offset blbuf ; place for bottom line
  551.     call    getbot        ; fetch bottom line
  552.     mov    ax,offset blbuf
  553.     mov    bx,offset bwnd
  554.     call    putcirc     ; save in circular buffer
  555.     mov    ax,701h     ; scroll down one line
  556.     xor    cx,cx        ; from top
  557.     mov    dx,low_rgt    ; to bottom
  558.     mov    bh,curattr
  559.     int    screen        ; scroll it down
  560.     mov    di,0        ; offset for destination
  561.     mov    si,offset tlbuf ; where to get line from
  562.     mov    cx,swidth    ; length of line
  563.     push    es
  564.     call    scrseg
  565.     push    ax
  566.     call    scrwait
  567.     pop    es
  568.     rep    movsw        ; copy the line in
  569.     pop    es        ; restore this
  570.     ret            ; and return
  571. upwind    endp
  572.  
  573.  
  574. ; move viewing window down a line (screen scrolls up)
  575. ; entry dwin2 does same w/out checking to see if scroll is legal
  576. dnwind    proc    near
  577.     mov    ax,offset blbuf ; place to put line temporarily
  578.     mov    bx,offset bwnd ; where to get lines from
  579.     call    getcirc     ; try to get a line
  580.     jnc    dnwin3        ; have a line, go show it
  581.     call    outbel        ; else ring bel
  582.     ret            ; and return
  583. dnwin2: mov    ax,offset blbuf
  584.     mov    bx,offset bwnd
  585.     call    getcirc
  586.     jnc    dnwin3
  587.     ret            ; this just rets if no line avail.
  588. dnwin3: call    scrprep     ; save top line
  589.     mov    ax,601h     ; scroll up one line
  590.     xor    cx,cx        ; from top
  591.     mov    dx,low_rgt    ; to bottom
  592.     mov    bh,curattr
  593.     int    screen        ; scroll it down
  594.     mov    dx,low_rgt
  595.     mov    dl,0        ; get addr of last line
  596.     call    scrloc
  597.     mov    di,ax        ; this is offset in dest
  598.     mov    si,offset blbuf ; where to get line from
  599.     mov    cx,swidth    ; length of line
  600.     push    es
  601.     call    scrseg
  602.     push    ax
  603.     call    scrwait
  604.     pop    es
  605.     rep    movsw        ; copy the line in
  606.     pop    es        ; restore this
  607.     ret            ; and return
  608. dnwind    endp
  609.  
  610. ; move viewing window down as much as possible...
  611. endwnd    proc    near
  612.     mov    cx,1000         ; large number of lines
  613.     jmp    dnwp1            ; and enter dwnpg
  614. endwnd    endp
  615.  
  616. ; scroll viewing window down (contents move up) crt_lins times...
  617. dnwpg    proc    near
  618.     mov    cl,crt_lins
  619.     mov    ch,0
  620. dnwp1:    push    cx            ; save this
  621.     call    dnwin2
  622.     pop    cx
  623.     loop    dnwp1
  624.     ret                ; and return
  625. dnwpg    endp
  626.  
  627. ; home viewing window
  628. homwnd    proc    near
  629.     mov    cx,1000         ; large # of lines
  630.     jmp    upwp1            ; join upwpg
  631. homwnd    endp
  632.  
  633. ; scroll viewing window up (screen moves down) a page
  634. upwpg    proc    near
  635.     mov    cl,crt_lins
  636.     mov    ch,0
  637. upwp1:    push    cx
  638.     call    upwin2
  639.     pop    cx
  640.     loop    upwp1
  641.     ret                ; and return
  642. upwpg    endp
  643.  
  644. ; get the bottom line into the buffer pointed to by ax.
  645. getbot    proc    near
  646.     push    ds
  647.     mov    di,ax            ; save dest
  648.     mov    cx,swidth
  649.     mov    dx,low_rgt
  650.     mov    dl,0
  651.     call    scrloc
  652.     mov    si,ax
  653.     call    scrseg
  654.     push    ax
  655.     call    scrwait
  656.     pop    ds
  657.     rep    movsw
  658.     pop    ds
  659.     ret
  660. getbot    endp
  661.  
  662. ; put a line into the circular buffer.    Pass the buffer structure
  663. ; in bx, the pointer to the line in ax.
  664. putcirc proc    near
  665.     push    si
  666.     push    di
  667.     push    cx
  668.     push    dx
  669.     mov    di,[bx].pp        ; pick up buffer ptr
  670.     add    di,2*swidth        ; increment to next avail slot
  671.     cmp    di,[bx].bend        ; past end?
  672.     jb    putci1            ; no, leave alone
  673.     mov    di,[bx].orig        ; else start at beginning
  674. putci1: mov    [bx].pp,di        ; update ptr
  675.     mov    si,ax            ; this is source
  676.     mov    cx,swidth
  677.     rep    movsw            ; copy into buffer
  678.     cmp    [bx].lcnt,npgs*slen    ; can we increment it?
  679.     jae    putci2            ; no, keep going
  680.     inc    [bx].lcnt        ; else count this line
  681. putci2: pop    dx
  682.     pop    cx
  683.     pop    di
  684.     pop    si            ; restore registers
  685.     ret
  686. putcirc endp
  687.  
  688. ; get a line from the circular buffer, removing it from the buffer.
  689. ; returns with carry on if the buffer is empty.
  690. ; pass the buffer structure in bx, the buffer to copy the line into
  691. ; in ax.
  692. getcirc proc    near
  693.     push    si
  694.     push    di
  695.     push    cx
  696.     push    dx
  697.     cmp    [bx].lcnt,0        ; any lines in buffer?
  698.     jne    getci1            ; yes, ok to take one out.
  699.     stc                ; else set carry
  700.     jmp    short getcir3        ; and return
  701. getci1: mov    si,[bx].pp        ; this is source
  702.     mov    di,ax            ; this is dest
  703.     mov    cx,swidth        ; # of chars to copy
  704.     rep    movsw
  705.     mov    si,[bx].pp        ; get ptr again
  706.     sub    si,2*swidth        ; move back
  707.     cmp    si,[bx].orig        ; compare to origin
  708.     jae    getcir2         ; still in range, continue
  709.     mov    si,[bx].bend        ; else use end of buffer
  710.     sub    si,2*swidth-1        ; minus length of a piece
  711. getcir2:mov    [bx].pp,si        ; update ptr
  712.     dec    [bx].lcnt        ; decrement # of lines in buffer
  713.     clc                ; make sure no carry
  714. getcir3:pop    dx
  715.     pop    cx
  716.     pop    di
  717.     pop    si
  718.     ret
  719. getcirc endp
  720.  
  721. ; call before scrolling to save top line...
  722. scrprep proc    near
  723.     push    ds
  724.     mov    si,0            ; offset of top line
  725.     mov    cx,swidth        ; length of line
  726.     mov    di,offset tlbuf     ; place to put line temporarily
  727.     call    scrseg
  728.     push    ax
  729.     call    scrwait
  730.     pop    ds
  731.     rep    movsw            ; copy the line
  732.     pop    ds            ; restore this
  733.     mov    ax,offset tlbuf
  734.     mov    bx,offset twnd        ; this is where it goes
  735.     call    putcirc         ; put into buffer
  736.     ret                ; and return
  737. scrprep endp
  738.  
  739.  
  740. ; put the character in al to the screen
  741. outtty    proc    near
  742.     test    flags,capt        ; capturing output?
  743.     jz    outnoc            ; no, forget this part
  744.     push    ax            ; save char
  745.     call    captrtn         ; give it captured character
  746.     pop    ax            ; restore character and keep going
  747.  
  748. outnoc: test    flags1,prtscr        ; should we be printing?
  749.     jz    outnop            ; no, keep going
  750.     push    ax
  751.     mov    ah,print_out
  752.     mov    dl,al            ; put character here for dos...
  753.     int    dos
  754.     pop    ax
  755.  
  756. outnop: test    flags,emheath        ; emulating heath?
  757.     jnz    outnop1         ; yup, go do something smart
  758.     mov    dl,al
  759.     mov    ah,pbout
  760.     int    dos            ; else let dos print char
  761.     ret                ; and return
  762.  
  763. outnop1:mov    dx,cursor        ; these may need cursor...
  764.     jmp    ttstate         ; jump according to current state
  765.  
  766. outtt0:
  767.     cmp    al,32            ; special character?
  768.     jb    outtt1            ; yes, handle specially...
  769.  
  770.     cmp    insmod,0        ; in insert mode?
  771.     je    outnrm            ; no, output normal
  772.     push    ax            ; save character
  773.     call    inschr            ; insert a character
  774.     pop    ax
  775. outnrm: xor    bh,bh            ; current page
  776.     mov    cx,1            ; only one char
  777.     mov    bl,curattr        ; with current attribute
  778.     mov    ah,9
  779.     int    screen            ; put onto screen
  780.     mov    dx,cursor        ; get cursor pos
  781. currt:    inc    dl            ; bump col
  782.     cmp    dl,crt_cols        ; see if in range
  783.     jb    setcur            ; in range, go set cursor
  784.     test    flags1,lnwrap        ; in wrap mode?
  785.     jz    outign            ; no, just return w/out updating cursor
  786.     xor    dl,dl
  787.     inc    dh            ; handle wrap
  788. setcur: cmp    dh,crt_lins
  789.     jb    setc1            ; not off end, keep going
  790.     push    dx            ; save row/col
  791.     call    scrprep         ; save top line in window buf
  792.     mov    ax,0601h        ; scroll up one line
  793.     xor    cx,cx            ; from 0,0
  794.     mov    dx,low_rgt        ; to 24,80
  795.     mov    bh,curattr        ; nice attribute
  796.     int    screen            ; do the scroll
  797.     pop    dx
  798.     mov    dh,crt_lins        ; go to bottom line again...
  799.     dec    dh
  800. setc1:    xor    bh,bh            ; page is 0
  801.     mov    cursor,dx        ; save cursor pos
  802.     mov    ah,2
  803.     int    screen            ; set cursor
  804. outign: ret                ; and return
  805. ; special character (in al)
  806. outtt1: mov    di,offset spctab    ; special char table
  807.     mov    cx,lspctab        ; length of tbl
  808.     repne    scasb            ; look for char in tbl
  809.     jz    outtt2            ; found, go do something with it
  810.     test    flags,trnctl        ; are we allowed to print carets?
  811.     jz    outign            ; no, just ignore it.
  812.     push    ax            ; save char
  813.     mov    al,'^'
  814.     call    outtty            ; print caret
  815.     pop    ax
  816.     add    al,'A'-1                ; make printable
  817.     jmp    outtty            ; print, then return
  818.  
  819. outtt2: mov    dx,cursor        ; might need cursor pos
  820.     sub    di,offset spctab+1    ; get index of char
  821.     shl    di,1            ; double for word offset
  822.     jmp    spcjmp[di]        ; and go handle
  823.  
  824. ; special char routines.  cursor is in dx, char in al
  825.  
  826. outlf:    inc    dh            ; bump row
  827.     jmp    setcur
  828.  
  829. outcr:    xor    dl,dl            ; set col to 0
  830.     jmp    setcur
  831.  
  832. outbs:    or    dl,dl
  833.     jle    setcur            ; col 0, can't back up
  834.     dec    dl            ; back up col
  835.     jmp    setcur            ; and use if reasonable
  836.  
  837. outtab: mov    dl,byte ptr cursor    ; get initial column
  838. outta1: mov    dh,dl            ; save column ptr
  839.     push    dx
  840.     mov    al,' '                  ; output a space
  841.     call    outtty            ; convenient, huh?
  842.     pop    dx
  843.     mov    dl,byte ptr cursor
  844.     cmp    dh,dl            ; is it moving?
  845.     je    outta2            ; no, forget this
  846.     test    dl,7            ; is it a multiple of 8?
  847.     jnz    outta1            ; no, keep going
  848. outta2: ret                ; else return
  849.  
  850. ; stolen from bios
  851. outbel: mov    al,10110110b        ; timer initialization
  852.     out    timer+3,al
  853.     mov    ax,beldiv        ; bel divisor
  854.     out    timer+2,al
  855.     mov    al,ah
  856.     out    timer+2,al        ; output divisor
  857.     in    al,bel_prt
  858.     mov    ah,al            ; remember original value
  859.     or    al,3            ; turn speaker on
  860.     out    bel_prt,al
  861.     mov    cx,8888h
  862. outbe1: loop    outbe1            ; wait a while
  863.     mov    al,ah
  864.     out    bel_prt,al        ; turn bell off
  865.     ret                ; and return
  866.  
  867. outesc: mov    ttstate,offset escseq    ; expect escape sequence.
  868.     ret                ; and return
  869.  
  870. ; escape-char handling routines
  871. escseq: mov    ttstate,offset outtt0    ; put state back to normal
  872.     mov    di,offset esctab    ; escape char tbl
  873.     mov    cx,lesctab        ; length of tbl
  874.     repne    scasb            ; look for it in tbl
  875.     jz    escsq1            ; found, go use it
  876.     jmp    outtty            ; not there, just print it
  877. escsq1: sub    di,offset esctab+1    ; get offset into tbl
  878.     shl    di,1            ; convert to word offset
  879.     jmp    escjmp[di]        ; and go dispatch on it
  880.  
  881. ; escape dispatch routines
  882. revind: cmp    dh,0
  883.     jle    revin1
  884.     dec    dh            ; back up a row
  885.     jmp    setcur            ; and go set cursor
  886. revin1: push    dx            ; save cursor pos
  887.     mov    ax,701h         ; scroll down one line
  888.     xor    cx,cx            ; from top
  889.     mov    dx,low_rgt        ; to bottom
  890.     mov    bh,curattr
  891.     int    screen            ; scroll it down
  892.     pop    dx            ; restore cursor.
  893.     mov    dh,0            ; set row back to 0
  894.     jmp    setcur
  895.  
  896. curup:    cmp    dh,0            ; w/in range?
  897.     jle    curu1            ; no, skip this
  898.     dec    dh            ; else back up
  899. curu1:    jmp    setcur            ; and go set position
  900.  
  901. curdwn: inc    dh
  902.     jmp    setcur            ; increment row (setcur can scroll!)
  903.  
  904. ; currt is above
  905.  
  906. clrscr: call    curhom            ; go home cursor
  907.     jmp    clreow            ; then clear to end of window
  908.  
  909. curhom: xor    dx,dx            ; move to 0,0
  910.     jmp    setcur
  911.  
  912. clreow: cmp    dl,0            ; at beginning of line?
  913.     jz    clrw1            ; yes, skip this part...
  914.     push    dx            ; remember cursor pos
  915.     call    clreol            ; clear to end of this line
  916.     pop    dx
  917.     inc    dh            ; bump row
  918.     xor    dl,dl            ; start from col 0
  919. clrw1:    cmp    dh,crt_lins        ; last line on screen
  920.     jnb    clrw2            ; if not in range, forget it
  921.     mov    ax,700h         ; clear whole window
  922.     mov    cx,dx            ; this is beginning
  923.     mov    dx,low_rgt
  924. ;    mov    dx,174fh        ; this is lower right corner
  925.     mov    bh,curattr        ; default attribute
  926.     int    screen            ; go clear it
  927. clrw2:    ret                ; and return
  928.  
  929. clreol: push    es
  930.     mov    cl,crt_cols        ; last col + 1
  931.     sub    cl,dl            ; this is # of chars to move
  932.     xor    ch,ch
  933.     jcxz    clrl1
  934.     call    scrloc            ; compute screen location (to ax)
  935.     mov    di,ax
  936.     call    scrseg
  937.     mov    es,ax            ; address screen segment
  938.     call    scrwait         ; wait for retrace
  939.     mov    ah,curattr        ; current attribute
  940.     mov    al,' '                  ; fill char
  941.     rep    stosw            ; fill line with spaces
  942. clrl1:    pop    es
  943.     ret                ; and return
  944.  
  945. inslin: mov    al,1            ; scroll one line
  946. ; alternate entry if inserting more then one line
  947. inslin1:mov    ch,dh            ; start at current row
  948.     xor    cl,cl            ; column 0
  949.     mov    dx,low_rgt
  950. ;    mov    dx,174fh        ; to bottom of screen
  951.     mov    ah,7h            ; scroll down.
  952.     mov    bh,curattr        ; attribute
  953.     int    screen
  954.     ret
  955.  
  956. dellin: mov    al,1            ; scroll 1 line
  957. ; alternate entry if deleting more than one line
  958. dellin1:mov    ch,dh            ; start at current row
  959.     xor    cl,cl            ; column 0
  960.     mov    dx,low_rgt
  961. ;    mov    dx,174fh        ; to bottom of screen
  962.     mov    ah,6h            ; scroll up.
  963.     mov    bh,curattr        ; attribute
  964.     int    screen
  965.     ret
  966.  
  967. delchr: push    ds
  968.     push    es
  969.     pushf            ; these may get changed...
  970.     mov    cl,crt_cols
  971.     dec    cl
  972.     sub    cl,dl        ; from what we're fiddling)
  973.     xor    ch,ch
  974.     jcxz    delch1        ; none to move, forget it
  975.     call    scrloc        ; compute location
  976.     mov    di,ax
  977.     mov    si,ax
  978.     add    si,2        ; source is next position over
  979.     call    scrseg        ; pick up screen segment
  980.     push    ax        ; put screen segment onto stack
  981.     mov    es,ax        ; and in destination segment
  982.     call    scrwait     ; wait for retrace
  983.     pop    ds        ; address screen segment
  984.     rep    movsw        ; delete it
  985.     mov    byte ptr [di],' ' ; kill char at end of line
  986. delch1: popf
  987.     pop    es
  988.     pop    ds
  989.     ret
  990.  
  991. inschr: push    ds
  992.     push    es        ; save these as well
  993.     pushf            ; might as well save flags...
  994.     mov    dx,cursor    ; this is place to do it
  995.     mov    cl,crt_cols
  996.     dec    cl
  997. ;    mov    cl,79        ; this is last col to move, +1 for length
  998.     sub    cl,dl        ; compute distance to end
  999.     xor    ch,ch        ; clear top half of offset
  1000.     jcxz    insch1        ; nothing to move...
  1001.     mov    dl,crt_cols
  1002.     sub    dl,2        ; last col to move
  1003. ;    mov    dl,78        ; this is address of last col to move
  1004.     call    scrloc        ; compute pos
  1005.     mov    si,ax
  1006.     mov    di,ax
  1007.     add    di,2        ; destination is one byte over...
  1008.     std            ; remember to move us backwards
  1009.     call    scrseg        ; find screen segment
  1010.     mov    es,ax
  1011.     push    ax        ; save screen seg on stack
  1012.     call    scrwait     ; w
  1013.     pop    ds
  1014.     rep    movsw        ; move each char and attribute
  1015. insch1: popf
  1016.     pop    es
  1017.     pop    ds
  1018.     ret            ; and return
  1019.  
  1020. noins:    mov    insmod,0        ; turn off insert mode
  1021.     ret                ; and return
  1022.  
  1023. movcur: mov    wcoord,2        ; want two coordinates...
  1024.     mov    ttstate,offset getcoord
  1025.     ret                ; and return
  1026.  
  1027. vtident: mov    si,offset vtidstr
  1028.     mov    cx,lvtidst
  1029. vtid1:    lodsb                ; get a byte from the string
  1030.     push    si            ; have to save from outprt
  1031.     push    cx
  1032.     call    outprt            ; send to serial port
  1033.     pop    cx
  1034.     pop    si
  1035.     loop    vtid1            ; go thru all chars
  1036.     ret                ; and return
  1037.  
  1038. entins: mov    insmod,0ffh        ; enter insert mode...
  1039.     ret                ; and return
  1040.  
  1041. doansi: mov    ansarg,0        ; ansi argument is 0 (default)
  1042.     mov    ttstate,offset getaarg    ; state is get ansi argument
  1043.     ret
  1044.  
  1045. getaarg:cmp    al,'0'
  1046.     jb    getaa1            ; in range for digit?
  1047.     cmp    al,'9'
  1048.     ja    getaa1
  1049.     sub    al,'0'                  ; convert to binary
  1050.     mov    dl,al            ; tuck away
  1051.     mov    al,ansarg
  1052.     mov    dh,10
  1053.     mul    dh            ; shift sum
  1054.     add    al,dl            ; add in this digit (what about ovfl?)
  1055.     mov    ansarg,al
  1056.     ret                ; and return
  1057.  
  1058. getaa1: cmp    al,'?'                  ; the dreaded question mark?
  1059.     jne    getaa2
  1060.     mov    ttstate,offset ignn    ; we ignore these...
  1061.     mov    igncnt,2        ; this is how many chars come after him
  1062.     ret
  1063.  
  1064. getaa2: mov    ttstate,offset outtt0    ; reset state
  1065.     mov    dx,cursor        ; this needs cursor position
  1066.     mov    bl,ansarg
  1067.     xchg    al,bl            ; put argument in nice place
  1068.     cmp    bl,'L'                  ; insert line?
  1069.     jne    getaa3
  1070.     jmp    inslin1         ; and go do it
  1071.  
  1072. getaa3: cmp    bl,'M'                  ; maybe delete line?
  1073.     jne    getaa4
  1074.     jmp    dellin1
  1075.  
  1076. getaa4: ret                ; ignore.
  1077.  
  1078. invvid: mov    curattr,70h        ; attribute for inverse video
  1079.     ret
  1080.  
  1081. nrmvid: mov    curattr,07h        ; attribute for normal video
  1082.     ret
  1083.  
  1084. dowrap: or    flags1,lnwrap        ; turn on wrap mode
  1085.     ret                ; and return
  1086.  
  1087. nowrap: and    flags1,not lnwrap    ; turn off wrap mode
  1088.     ret                ; and return
  1089.  
  1090. ; get a coordinate.
  1091. getcoord:
  1092.     sub    al,32            ; coordinates offset by 32
  1093.     mov    si,wcoord
  1094.     dec    si
  1095.     mov    byte ptr coord[si],al    ; fill in appropriate coordinate
  1096.     mov    wcoord,si        ; update flag
  1097.     jnz    getco1            ; more needed, can't do anything yet
  1098.     mov    ttstate,offset outtt0    ; reset state
  1099.     mov    dx,coord        ; get coordinates
  1100.     jmp    setcur            ; and go jump there
  1101. getco1: ret
  1102.  
  1103. ; ignore following igncnt characters
  1104. ignn:    dec    igncnt            ; decrement count
  1105.     jnz    ignn1
  1106.     mov    ttstate,offset outtt0    ; put state back to normal if done
  1107. ignn1:    ret
  1108.  
  1109. outtty    endp
  1110.  
  1111. ; computes screen location to ax, given row and col in dx.
  1112. ; trashes ax,bx
  1113. scrloc    proc    near
  1114.     mov    al,dh        ; get row
  1115.     mov    bl,crt_cols    ;** row size
  1116.     mul    bl        ; multiply by row size
  1117.     xor    dh,dh        ; clear col
  1118.     add    ax,dx        ; this is current position
  1119.     sal    ax,1        ; double for attributes
  1120.     ret
  1121. scrloc    endp
  1122.  
  1123. ; puts current screen segment in ax
  1124. scrseg    proc    near
  1125.     mov    ax,0b000h        ; assume bw for now
  1126.     cmp    crt_mode,7        ; 7 is bw (***)
  1127.     je    scrse1
  1128.     mov    ax,0b800h        ; color card
  1129. scrse1: ret
  1130. scrseg    endp
  1131.  
  1132. ; wait for retrace so can write to screen memory
  1133. scrwait proc    near
  1134.     cmp    crt_mode,7        ; bw mode?
  1135.     je    scrwa3            ; yes, no waiting
  1136.     push    dx
  1137.     mov    dx,crt_status
  1138. scrwa1: in    al,dx
  1139.     test    al,disp_enb        ; display enable?
  1140.     jnz    scrwa1            ; yes, keep waiting
  1141. scrwa2: in    al,dx
  1142.     test    al,disp_enb        ; now wait for it to go off
  1143.     jz    scrwa2            ; so can have whole cycle
  1144.     pop    dx
  1145. scrwa3: ret
  1146. scrwait endp
  1147.  
  1148. code    ends 
  1149.     end
  1150.