home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / mskermit / msxrb1.asm < prev    next >
Assembly Source File  |  2020-01-01  |  80KB  |  2,805 lines

  1.     name    msxrb1
  2. ; File msxrb1.asm
  3.     include    mssdef.h
  4. ;       Copyright (C) 1982,1991, Trustees of Columbia University in the
  5. ;       City of New York.  Permission is granted to any individual or
  6. ;       institution to use, copy, or redistribute this software as long as
  7. ;       it is not sold for profit and this copyright notice is retained.
  8. ; Kermit system dependent module for Rainbow
  9. ; Jeff Damens, July 1984
  10. ;  with additional major changes by Joe Doupnik, 1986, 1987, 1988, 1989, 1991
  11. ; Edit history:
  12. ; 2 March 1991 version 3.10
  13. ; Last edit 1 March 1991
  14. ; 27-AUG-1990 [rhw]
  15. ; 27-AUG-1990    I had added shr cx,1 to divide the CX=swidth by 2
  16. ;        but swidth is a const so I removed the shifts & simply
  17. ;        divided the const by 2.     This saves an shift in many places.
  18. ;        [rhw-5] Robert H. Weiner
  19. ; 25-AUG-1990    Replaced MOVSB with MOVSW for all screen ops
  20. ;        Divide counts by 2 1st for byte to word conversion
  21. ;        Since swidth is always even, this can save alot of cycles:
  22. ;        REP MOVSB -> MOVSW should save 17*132/2=1122 cycles for
  23. ;        swidth char moves since iteration count is cut in half.
  24. ;        [rhw-4] Robert H. Weiner
  25. ; 24-AUG-1990    Added print screen character XLAT table to make all the
  26. ;        VT100 char graphics come out on a normal printer, xlat_tab[]
  27. ;        Added same XLAT code to dumpscr code since that too is
  28. ;        a real mess without it.  Now linedraw boxes look like boxes.
  29. ;        Added SETCHTAB definition that's now required in machine
  30. ;        specific modules
  31. ;        [rhw-3] Robert H. Weiner
  32. ; Present-
  33. ; 01-JUL-1990    MSYIBM.ASM screen rollback routines merged into MSXRB1.ASM
  34. ;        This should speed up rollback screen handling
  35. ;        Sorry, this code left out of this source release since its
  36. ;        presently incomplete.
  37. ;        [rhw-2] Robert H. Weiner
  38. ;    MAY-1990    connect mode hangup (^]-H) fixed (needed delay) RHW/JRD
  39. ;        [rhw-1] Robert H. Weiner (robert%progplus.uucp@uunet.uu.net)
  40. ; 30-Apr-1990    fix baud rate return    [gbs]
  41. ;        convert unprintable characters to "." in print screen
  42. ; 14-Feb-1990    fix VT102 initialization.  gbs
  43. ; 11 Nov Revise for MS Kermit version 3. jrd
  44. ; 11-Nov-1989 reversed print controller/autoprint.
  45. ;        Had it wrong the first time.
  46. ;        Gary B. Stebbins
  47. ; 18-Oct-1989 added minimal print controller support & autoprint
  48. ;        (module needs cleanup in incoming character handling)
  49. ;        (print stuff doesn't handle DECEXT or DECPFF)
  50. ;        (really kludged in...should be rewritten similar to
  51. ;         input character handling for IBM PC)
  52. ;        Gary B. Stebbins
  53. ;  4-Mar-1989 several problems related to modem signal handling fixed.
  54. ;        Gary B. Stebbins, Don Metz
  55. ; 1 July 1988 Version 2.31
  56. ; 10 Jan 1988 Cleanup 8 bit display in outtty. [jrd]
  57. ; 1 Jan 1988 version 2.30
  58.  
  59.     public    serini, serrst, clrbuf, outchr, coms, vts, vtstat, dodel
  60.     public    ctlu, cmblnk, locate, lclini, prtchr, dobaud, clearl
  61.     public    getbaud, beep, pcwait, dumpscr, termtb, shomodem
  62.     public    count, xofsnt, puthlp, putmod, clrmod, poscur, getmodem
  63.     public    sendbr, sendbl, term, machnam, setktab, setkhlp, showkey
  64.     public    ihosts, ihostr, serhng, dtrlow, comptab, baudst
  65.             ; action verb procedures for keyboard translator
  66.     public    prvscr, nxtscr, prtscn
  67.     public    uparrw, dnarrw, rtarr, lfarr, pf1, pf2, pf3, pf4
  68.     public    kp0, kp1, kp2, kp3, kp4, kp5, kp6, kp7, kp8, kp9
  69.     public    kpminus, kpcoma, kpenter, kpdot, chrout, cstatus, cquit
  70.     public    cquery, prvscr, nxtscr, prvlin, nxtlin, trnprs, snull
  71.     public    nxttop, nxtbot, klogon, klogof, cdos, chang
  72.     public    portval, bdtab, setchtab
  73.  
  74. ; rainbow-dependent screen constants
  75.  
  76. scrseg    equ    0ee00H        ; screen segment
  77. latofs    equ    0ef4h        ; ptrs to line beginnings, used by firmware
  78. l1ptr    equ    latofs        ; ptr to first line
  79. llptr    equ    latofs+23*2    ; ptr to last line
  80. csrcol    equ    0f41h        ; current cursor column
  81. csrlin    equ    0f42h        ; current cursor line
  82. curlin    equ    0f43h        ; current line flags
  83. wrpend    equ    2        ; wrap pending
  84. attoffs equ    1000H
  85. rmargin equ    0f57h        ; right margin limit
  86.  
  87. ; rainbow-dependent firmware locations
  88. nvmseg    equ    0ed00h        ; segment containing NVM
  89. xmitbd    equ    0a1h        ; address of xmit baud
  90. rcvbd    equ    0a2h        ;   "      "  receive baud
  91. autwrp    equ    08dH        ; b0 = 1 if auto wrap on (?)
  92. newlmod equ    08eh        ; b0 = 0 lf, = 1 newline (cr/lf)
  93. bdprt    equ    06h        ; baud rate port
  94. vt52mod equ    088h        ; b0 = 1 if in ansi mode
  95. off    equ    0
  96. bufon    equ    1        ; buffer level xon/xoff on-state control flag
  97. usron    equ    2        ; user level xon/xoff on-state control flag
  98.  
  99. mntrgh    equ    bufsiz*3/4    ; High point = 3/4 of buffer full
  100. mntrgl    equ    bufsiz/4    ; Low point = 1/4 buffer full
  101.  
  102. mnstata equ    042H        ; Status/command port A
  103. mnstatb equ    043H        ; Status/command port B
  104. mndata    equ    040H        ; Data port
  105. mndatb    equ    041H
  106. mnctrl    equ    002H        ; Control port
  107. serchn    equ    0A4H        ; interrupt to use
  108. serch1    equ    044H        ; use this too for older rainbows
  109.  
  110. txrdy    EQU    04H        ;Bit for output ready
  111. rxrdy    EQU    01H        ;Bit for input ready
  112.  
  113. fastcon equ    29H        ; fast console handler
  114. firmwr    equ    18H        ; Bios interrupt
  115. kcurfn    equ    8h        ; disable cursor
  116. rcurfn    equ    0ah        ; enable cursor
  117.  
  118. swidth    equ    132        ; screen width
  119. slen    equ    24        ; screen length
  120. npages    equ    10        ; for use with dynamic memory allocation
  121.  
  122. stbrk    equ    15        ; start sending a break
  123. enbrk    equ    16        ; stop sending break
  124.  
  125. ; external variables used:
  126. ; flags - global flags as per flginfo structure defined in pcdefs
  127. ; trans - global transmission parameters, trinfo struct defined in pcdefs
  128. ; portval - pointer to current portinfo structure (currently either port1
  129. ;    or port2)
  130. ; port1, port2 - portinfo structures for the corresponding ports
  131.  
  132. ; global variables defined in this module:
  133. ; xofsnt, xofrcv - tell whether we saw or sent an xoff.
  134.  
  135. ; circular buffer ptr
  136. cbuf    struc
  137. pp    dw    ?            ; place ptr in buffer
  138. bend    dw    ?            ; end of buffer
  139. orig    dw    ?            ; buffer origin
  140. lcnt    dw    0            ; # of lines in buffer
  141. lmax    dw    ?            ; max lines of buffer
  142. cbuf    ends
  143.  
  144. ; answerback structure
  145. ans    struc
  146. anspt    dw    ?            ; current pointer in answerback
  147. ansct    db    ?            ; count of chars in answerback
  148. ansseq    dw    ?            ; pointer to whole answerback
  149. anslen    db    ?            ; original length
  150. ansrtn    dw    ?            ; routine to call
  151. ans    ends
  152.  
  153. ; structure for status information table sttab.
  154. stent    struc
  155. sttyp    dw    ?        ; type (actually routine to call)
  156. msg    dw    ?        ; message to print
  157. val2    dw    ?        ; needed value: another message, or tbl addr
  158. tstcel    dw    ?        ; address of cell to test, in data segment
  159. basval    dw    0        ; base value, if non-zero
  160. stent    ends
  161.  
  162. data    segment public 'data'
  163.     extrn    flags:byte, trans:byte, filtst:byte, dmpname:byte
  164.     extrn    rxtable:byte, kbdflg:byte, repflg:byte, diskio:byte
  165.     extrn    ttyact:byte, denyflg:word, prnhand:word
  166.  
  167. ; [rhw-3] Start Definitions for Print Screen Translation Table
  168. xlat_tab_size    equ    32    ; chars 00 through 31 decimal
  169.     ; 0=null, 1=diamond, 2=blob, 3=HT, 4=FF, 5=CR, 6=LF, 7=degree, 8=+/-
  170.     ; 9=NL, 10=VT, 11=low_rt_corner, 12=up_rt_corner, 13=up_left_corner,
  171.     ; 14=low_left_corner, 15=cross, 16...20=horiz_line_scan1,3,5,7,9
  172.     ; 21=left_t, 22=right_t, 23=bott_t, 24=top_t, 25=vertical, 26=<=
  173.     ; 27=>=, 28=pi, 29=<>, 30=pound, 31=centered_dot
  174.         ;     0 ,  1 ,  2 ,  3 ,  4 ,  5 ,  6 ,  7
  175. xlat_tab    db    ' ', '*', '#', '.', '.', '.', '.', 'o'
  176.         ;     8 ,  9 ,  10,  11,  12,  13,  14,  15
  177.         db    '+', '.', '.', '+', '+', '+', '+', '+'
  178.         ;     16,  17,  18,  19,  20,  21,  22,  23
  179.         db    '_', '_', '-', '-', '-', '+', '+', '+'
  180.         ;     24,  25,  26,  27,  28,  29,  30,  31
  181.         db    '+', '|', '<', '>', 'p', '!', '#', '.'
  182. ; [rhw-3] End Print Screen Translation Table
  183.  
  184. setchtab db    1            ; [rhw-3] Set File Character-Set table
  185.     mkeyw   'VT102',0        ; [rhw-3] hardware default Code Page
  186. ;;    mkeyw   'User-defined',1        ; User loadable table
  187.  
  188.  
  189. setktab db    0
  190. akeyflg db    0        ; non-zero if in alt keypad mode
  191. ckeyflg db    0        ; non-zero if cursor is in applications mode
  192. ourflgs db    0        ; our flags
  193. fpscr    equ    80H        ; flag definitions
  194. vtautop equ    1        ; autoprint enabled
  195. vtcntp    equ    2        ; controller print enabled
  196. fairness dw    0        ; keyboard/port sharing counter
  197. dupflg    db    0        ; full (0) or half (1) duplex on port
  198. argadr    dw    0        ; pointer to arguments from msster
  199. crlf    db    cr,lf,'$'
  200. setkhlp db    0
  201. machnam db    'Rainbow$'
  202. nyimsg    db    cr,lf,'Not yet implemented$'
  203. dmperr    db    cr,lf,'?Cannot access screen-dump file$',cr,lf
  204. hngmsg    db    cr,lf,' The phone should have hungup.',cr,lf,'$'
  205. hnghlp    db    cr,lf,' The modem control lines DTR and RTS for the current'
  206.     db    ' port are forced low (off)'
  207.     db    cr,lf,' to hangup the phone. Normally, Kermit leaves them'
  208.     db    ' high (on) when it exits.'
  209.     db    cr,lf,'$'
  210. msmsg1    db    cr,lf,' Modem is not ready: DSR is off$'
  211. msmsg2    db    cr,lf,' Modem is ready:     DSR is on$'
  212. msmsg3    db    cr,lf,' no Carrier Detect:  CD  is off$'
  213. msmsg4    db    cr,lf,' Carrier Detect:     CD  is on$'
  214. msmsg5    db    cr,lf,' no Clear To Send:   CTS is off$'
  215. msmsg6    db    cr,lf,' Clear To Send:      CTS is on$'
  216. rdbuf    db    swidth dup (?)        ; temp buf
  217. delstr    db    BS,BS,'  ',BS,BS,'$'    ; Delete string
  218. clrlin    db    cr,'$'        ; Clear line (just the cr part)
  219. oldser    dw    ?        ; old serial handler
  220. oldseg    dw    ?        ; segment of above
  221. old1ser dw    ?        ; old serial handler, alternate address
  222. old1seg dw    ?        ; segment of same
  223. portin    db    0        ; Has comm port been initialized
  224. mdstreg db    0        ; Modem line status report for Show Modem
  225. xofsnt    db    0        ; Say if we sent an XOFF
  226. xofrcv    db    0        ; Say if we received an XOFF
  227. parmsk    db    0ffh        ; 7-8 bit parity mask
  228. flowon    db    0        ; flow on char (xon or null)
  229. flowoff db    0        ; flow off char (xoff or null)
  230. mdmhand db    0        ; Modem status register, current
  231. iobuf    db    5 dup (?)    ; buffer for ioctl
  232.  
  233. gopos    db    escape,'['
  234. rowp    db    20 dup (?)
  235. clrseq    db    escape,'[H',escape,'[J$'
  236. ceolseq db    escape,'[K$'
  237. invseq    db    escape,'[7m$'
  238. nrmseq    db    escape,'[0m$'
  239. ivlatt    db    swidth dup (0fH) ; a line's worth of inverse attribute
  240. dumpbuf db    swidth+2 dup (?) ; screen dump work buffer
  241. dumpsep db    FF,cr,lf    ; screen dump image separator
  242. dovt52    db    escape,'[?2l$'    ; set VT52 mode
  243. dovt102 db    escape,'<$'    ; set VT102 mode
  244.  
  245. ourarg    termarg <>
  246. comptab db    2            ; communications port options
  247.     mkeyw    '1',1
  248.     mkeyw    'COM1',1        ; only one option here
  249.  
  250. ontab    db    2
  251.     mkeyw    'off',0
  252.     mkeyw    'on',1
  253.  
  254. vttbl    db    3            ; SET TERM table
  255.     mkeyw    'Roll',10
  256.     mkeyw    'VT102',ttvt100
  257.     mkeyw    'VT52',ttvt52
  258.  
  259. termtb    db    2            ; entries for Status, not Set
  260.     mkeyw    'VT102',ttvt100
  261.     mkeyw    'VT52',ttvt52
  262.  
  263. rolhlp    db    cr,lf,'  Roll (undo screen roll back before writing new'
  264.     db    ' chars, default=off)$'
  265.  
  266. vtrolst db    'Term rollback: $'
  267.  
  268. vtstbl    stent    <srchkw,vtrolst,ontab,vtroll>            ; rollback
  269.     dw    0        ; end of table
  270.  
  271.  
  272.  
  273. ; variables for serial interrupt handler
  274. source    db    bufsiz DUP(?)    ; Buffer for data from port
  275. srcpnt    dw    source        ; Pointer in buffer (DI)
  276. count    dw    0        ; Number of chars in int buffer
  277. telflg    db    0        ; non-zero if we're a terminal. NRU
  278. ivec    dw    tranb        ; transmit empty B
  279.     dw    tranb        ; status change B
  280.     dw    tranb        ; receive b
  281.     dw    tranb        ; special receive b
  282.     dw    stxa        ; transmit empty a
  283.     dw    sstata        ; status change a
  284.     dw    srcva        ; receive a
  285.     dw    srcva        ; special receive a
  286.  
  287. ; baud rate definitions
  288. ; value is programmed into baud rate port
  289. bdtab    db    16            ; Baud rate table
  290.     mkeyw    '50',0
  291.     mkeyw    '75',1
  292.     mkeyw    '110',2
  293.     mkeyw    '134.5',3
  294.     mkeyw    '150',4
  295.     mkeyw    '200',5
  296.     mkeyw    '300',6
  297.     mkeyw    '600',7
  298.     mkeyw    '1200',8
  299.     mkeyw    '1800',9
  300.     mkeyw    '2000',10
  301.     mkeyw    '2400',11
  302.     mkeyw    '3600',12
  303.     mkeyw    '4800',13
  304.     mkeyw    '9600',14
  305.     mkeyw    '19200',15
  306.  
  307. ; multi-screen stuff
  308. twnd    cbuf    <>            ; top screen spill-buffer struct
  309. bwnd    cbuf    <>            ; bottom screen spill buffer struct
  310. topline dw    swidth dup (?)        ; top line screen spill buffer
  311. botline dw    swidth dup (?)        ; bottom line screen spill buffer
  312. rlbuf    dw    swidth dup (?)        ; temp buffer for line scrolling
  313. scrnbuf db    swidth*slen dup (?)    ; save-screen, text
  314. attrbuf db    swidth*slen dup (?)    ; save-screen, attributes
  315. srcseg    dw    0
  316.  
  317. topdwn    db    escape,'[H',escape,'M$' ; go to top, scroll down
  318. botup    db    escape,'[24;0H',escape,'D$' ; go to bottom, scroll up
  319. curinq    db    escape,'[6n$'    ; cursor inquiry
  320. posbuf    db    20 dup (?)    ; place to store cursor position
  321. gtobot    db    escape,'[24;0H$'    ; go to bottom of screen
  322. ourscr    dw    ?
  323. ourattr dw    ?        ; storage for screen and attributes
  324. inited    db    0        ; terminal handler not inited yet
  325. dosmsg    db    '?Must be run in version 2.05 or higher$'
  326. dmphand dw    ?        ; file handle for screen dump
  327. anssq1    db    escape,'[c'
  328. an1len    equ    $-anssq1
  329. anssq2    db    escape,'Z'
  330. an2len    equ    $-anssq2
  331. eakseq    db    escape,'='
  332. eaklen    equ    $-eakseq
  333. dakseq    db    escape,'>'
  334. daklen    equ    $-dakseq
  335. cuapseq db    escape,'[?1h'
  336. cuaplen equ    $-cuapseq
  337. cunapseq db    escape,'[?1l'
  338. cunaplen equ    $-cunapseq
  339. crsseq    db    escape,'c'
  340. crslen    equ    $-crsseq
  341. enqseq    db    escape,'[6n'
  342. enqlen    equ    $-enqseq
  343. apenable db    escape,'[?5i'    ;autoprint enable
  344. apenlen equ    $-apenable
  345. apdisabl db    escape,'[?4i'    ;autoprint disable
  346. apdislen equ    $-apdisabl
  347. pcenable db    escape,'[5i'    ;print controller enable
  348. pcenlen equ    $-pcenable
  349. pcdisabl db    escape,'[4i'    ;print controller disable
  350. pcdislen equ    $-pcdisabl
  351. pscrn0    db    escape,'[i'    ;print screen
  352. psc0len equ    $-pscrn0
  353. pscrn1    db    escape,'[0i'    ;print screen
  354. psc1len equ    $-pscrn1
  355.  
  356. ansbk1    ans    <anssq1,an1len,anssq1,an1len,sndans> ; two answerbacks
  357. ansbk2    ans    <anssq2,an2len,anssq2,an2len,sndans>
  358. ansbk3    ans    <eakseq,eaklen,eakseq,eaklen,enaaky> ; enable alt keypad
  359. ansbk4    ans    <dakseq,daklen,dakseq,daklen,deaaky> ; disable alt keypad
  360. ansbk5    ans    <crsseq,crslen,crsseq,crslen,sndspc> ; crash sequence (!)
  361. ansbk6    ans    <enqseq,enqlen,enqseq,enqlen,ansenq>
  362. ansbk7    ans    <cuapseq,cuaplen,cuapseq,cuaplen,cuapp> ; cursor application
  363. ansbk8    ans    <cunapseq,cunaplen,cunapseq,cunaplen,cunapp>; cursor cursor
  364. ansbk9    ans    <apenable,apenlen,apenable,apenlen,apon>; autoprint enable
  365. ansbk10 ans    <apdisabl,apdislen,apdisabl,apdislen,apoff>;autoprint disable
  366. ansbk11 ans    <pcenable,pcenlen,pcenable,pcenlen,prconon>;print control on
  367. ansbk12 ans    <pcdisabl,pcdislen,pcdisabl,pcdislen,pconoff>;print control off
  368. ansbk13 ans    <pscrn0,psc0len,pscrn0,psc0len,prtscn>    ; print screen
  369. ansbk14 ans    <pscrn1,psc1len,pscrn1,psc1len,prtscn>    ; print screen
  370.  
  371. ansret    db    escape,'[?6c'
  372.     db    10 dup (?)
  373. ansrln    equ    $-ansret
  374. vt52ret db    escape,'/Z'            ; VT52 identification
  375. vt52ln    equ    $-vt52ret
  376. temp    dw    0
  377. vtroll    db    0
  378.  
  379. port1    prtinfo <0FFFH,0,defpar,1,0,defhand,floxon,0>
  380. portval dw    port1            ; Default is to use port 1
  381.  
  382. ;port initialization data for 7201 [ejz]
  383. ;enables Rx,Tx, CTS, DTR, 8 bits, no parity, 1.5 stop bits
  384. prtpar    db    18H,14H,48H,13H,0C1H,15H,0EAH,11H,18H,00H
  385.  
  386. data    ends
  387.  
  388. code    segment public 'code'
  389.     extrn    comnd:near, dopar:near, sleep:near, sbrk:near, isfile:near
  390.     extrn    strlen:near, strcpy:near, msuinit:near, keybd:near
  391.     extrn    statc:near, srchkw:near, pntchr:near, pntflsh:near
  392.  
  393.     assume    cs:code, ds:data, es:nothing
  394.  
  395. ; local initialization routine, called by Kermit initialization.
  396.  
  397. lclini    proc    near
  398.     mov    ah,dosver    ; make sure this is DOS version 2.05 or higher
  399.     int    dos
  400.     xchg    al,ah            ; put major version in ah, minor in al
  401.     cmp    ax,205H            ; is it 2.05?
  402.     jae    lclin1            ; yes, go on
  403.     mov    dx,offset dosmsg
  404.     call    tmsg
  405.     cmp    flags.extflg,1        ; exit now
  406.     ret
  407. lclin1: mov    flags.vtflg,ttvt100    ; default to VT102
  408.     call    setterm            ; set terminal type to VT102
  409.     call    msuinit            ; initialize keyboard translator
  410.     mov    ourscr,offset scrnbuf    ; save-screen text buf address
  411.     mov    ourattr,offset attrbuf    ; save-screen attr buf address
  412.  
  413.     mov    ax,swidth*2*2        ; ask for two lines (1 per buffer)
  414.     call    sbrk            ; allocate mem. Exit Kermit on failure
  415.                     ;if we get here them we have the lines
  416.     mov    bwnd.orig,ax        ; memory segment, bottom window area
  417.     mov    twnd.orig,ax        ; top. same place for both buffers!
  418.     push    es            ; save this register
  419.     mov    es,ax            ; seg pointer to new memory block
  420.     mov    bx,(swidth*slen*npages+7)/8 ; paragraphs wanted for roll back
  421.     add    bx,24000D/16        ; plus paragraphs to run Command.com
  422.     mov    ah,setblk        ; DOS Setblock. Ask for that space
  423.     int    dos            ; bx has # paragraphs available
  424.     sub    bx,24000D/16        ; deduct space for DOS 3.x Command.Com
  425.     cmp    bx,(swidth*4+15)/16    ; any room left for buffers?
  426.     jae    lclyin2            ; some space is available for buffers
  427.     mov    bx,(swidth*4+15)/16    ; else use our sbrk allocation
  428. lclyin2:mov    ah,setblk        ; ask for that many (bx) paragraphs
  429.     int    dos            ; Errors here == DOS deceived us
  430.     pop    es            ; restore reg
  431.     mov    ax,bx            ; bx = # paragraphs allocated by DOS
  432.     mov    cl,3            ; 2**3 = 8
  433.     shl    ax,cl            ; paragraphs to words (char + attrib)
  434.     xor    dx,dx            ; clear extended size
  435.     mov    cx,swidth        ; number of chars per line in buffer
  436.     div    cx            ; ax = number of lines in buffer
  437.     mov    bwnd.lmax,ax        ; max lines per buffer (quotient)
  438.     mov    twnd.lmax,ax        ; max lines per buffer
  439.     add    cx,cx            ; count char and attribute per item
  440.     xor    dx,dx            ; clear extended numerator
  441.     mul    cx            ; ax = effective # bytes per buffer
  442.     dec    ax            ; adjust for counting from zero
  443.     mov    bwnd.bend,ax        ; offset of last byte in buffer
  444.     mov    twnd.bend,ax        ; offset of last byte in buffer
  445.     mov    bwnd.pp,0        ; offset of first byte in buffer
  446.     mov    twnd.pp,0        ; offset of first byte in buffer
  447.     mov    bwnd.lcnt,0        ; number of lines occupied in buffer
  448.     mov    twnd.lcnt,0        ; number of lines occupied in buffer
  449.     or    denyflg,tekxflg        ; deny automatic Tektronix invokation
  450.     ret
  451. lclini    endp
  452.  
  453. ; show the definition of a key.     The terminal argument block (which contains
  454. ; the address and length of the definition tables) is passed in ax.
  455. ; Returns a string to print in AX, length of same in CX.
  456. ; Returns normally.
  457. showkey proc    near
  458.     ret
  459. showkey endp
  460.  
  461.  
  462. ; SHOW MODEM, displays current status of lines DSR, CD, and CTS.
  463. ; Uses byte mdmhand, the modem line status register. [jrd]
  464. shomodem proc    near
  465.     mov    ah,cmeol        ; get a confirm
  466.     call    comnd
  467.     jc    shomd5            ; c = failure
  468.     call    getmodem        ; get modem status
  469.     mov    mdmhand,al
  470.     mov    ah,prstr
  471.     mov    dx,offset msmsg1    ; modem ready msg
  472.     test    mdmhand,20h        ; is DSR asserted?
  473.     jz    shomd1            ; z = no
  474.     mov    dx,offset msmsg2    ; say not asserted
  475. shomd1: int    dos
  476.     mov    dx,offset msmsg3    ; CD asserted msg
  477.     test    mdmhand,80h        ; CD asserted?
  478.     jz    shomd2            ; z = no
  479.     mov    dx,offset msmsg4    ; say not asserted
  480. shomd2: int    dos
  481.     mov    dx,offset msmsg5    ; CTS asserted msg
  482.     test    mdmhand,10h        ; CTS asserted?
  483.     jz    shomd3            ; z = no
  484.     mov    dx,offset msmsg6    ; say not asserted
  485. shomd3: mov    ah,prstr
  486.     int    dos
  487.     clc
  488. shomd5: ret
  489. shomodem endp
  490.  
  491. ; Get modem status and set global byte mdmhand. Preserve all registers.
  492. ; Uses byte mdstreg, the modem line status register, bits as follows:
  493. ; Int Z80, Int 8088, Hwd fail det enable, CD, CTS, DSR, SI/SecCD, RI   [jrd]
  494. getmodem proc    near            ; gets modem status upon request
  495.     push    dx
  496.     mov    al,0            ; assume nothing is on
  497.     mov    dx,mnctrl        ; modem control port (read 02h)
  498.     in    al,dx            ; read modem control port
  499.     not    al            ; invert RB modem bits (0=true) [gbs]
  500.     mov    mdmhand,0        ; clear status byte
  501.     test    al,4            ; DSR asserted?
  502.     jz    getmod1            ; z = no
  503.     or    mdmhand,20h        ; set IBM spec DSR bit
  504. getmod1:test    al,8            ; CTS asserted?
  505.     jz    getmod2            ; z = no
  506.     or    mdmhand,10h        ; set IBM spec CTS bit
  507. getmod2:test    al,10h            ; CD asserted?            [gbs]
  508.     jz    getmod3            ; z = no
  509.     or    mdmhand,80h        ; set IBM spec CD bit        [gbs]
  510. getmod3:mov    al,mdmhand        ; setup return
  511.     mov    ah,0            ; return status in al
  512.     pop    dx
  513.     clc
  514.     ret
  515. getmodem endp
  516.  
  517. ; Clear the input buffer. This throws away all the characters in the
  518. ; serial interrupt buffer.  This is particularly important when
  519. ; talking to servers, since NAKs can accumulate in the buffer.
  520. ; Returns normally.
  521.  
  522. CLRBUF    PROC    NEAR
  523.     cli
  524.     mov    srcpnt,offset source
  525.     mov    count,0
  526.     sti
  527.     ret
  528. CLRBUF    ENDP
  529.  
  530. ; Clear to the end of the current line.     Returns normally.
  531.  
  532. CLEARL    PROC    NEAR
  533.     mov    dx,offset ceolseq    ; clear sequence
  534.     jmp    tmsg
  535. CLEARL    ENDP
  536.  
  537.  
  538. ; Put the char in AH to the serial port, assumimg the port is active.
  539. ; Returns carry clear if success, else carry set.
  540. ; 16 May 1987 Add entry point OUTCH2 for non-flow controlled sending to
  541. ; prevent confusion of flow control logic at top of outchr; used by receiver
  542. ; buffer high/low water mark flow control code. [jrd]
  543. OUTCHR    PROC    NEAR
  544.     cmp    flowoff,0        ; Are we doing flow control
  545.     je    outch2            ; No, just continue
  546.     cmp    ah,flowoff        ; sending xoff?
  547.     jne    outch1            ; ne = no
  548.     mov    xofsnt,usron        ; indicate user level xoff being sent
  549.     jmp    outch1b
  550. outch1:
  551.     and    xofsnt,not usron    ; cancel user level xoff
  552.     cmp    ah,flowon        ; user sending xon?
  553.     jne    outch1b            ; ne = no
  554.     mov    xofsnt,off         ; say an xon has been sent (cancels xoff)
  555. outch1b:cmp    xofrcv,off        ; Are we being held (xoff received)?
  556.     je    outch2            ; e = no - it's OK to go on
  557.     cmp    ttyact,0        ; in Connect mode?
  558.     je    outch1d            ; e = no
  559.     call    beep            ; let user know we are xoff-ed
  560.     mov    xofrcv,off        ; force off XOFF (unblock output)
  561.     jmp    outch2            ;  and send the char anyway
  562. outch1d:cmp    flags.timflg,0        ; is timer off?
  563.     je    outch2            ; e = yes, no timeout period
  564.     push    cx            ; save reg
  565.     mov    ch,trans.rtime        ; receive timeout interval (sec)
  566.     xor    cl,cl            ;  convert to 4 millsec increments
  567.     jcxz    outch1c            ; z = no timeout wanted
  568.  
  569. outch1a:cmp    xofrcv,off        ; Are we being held (xoff received)?
  570.     je    outch1c            ; e = no - it's OK to go on
  571.     push    ax
  572.     mov    ax,4            ; 4 millisec wait loop
  573.     call    pcwait
  574.     pop    ax
  575.     loop    outch1a            ; and try it again
  576.     mov    xofrcv,off        ; timed out, force it off and fall thru
  577. outch1c:pop    cx            ; end of flow control section
  578.              ; OUTCH2 is entry point for sending without flow control
  579. OUTCH2: mov    al,ah            ; Parity routine works on AL
  580.     call    dopar            ; Set parity appropriately
  581.     mov    ah,al            ; Don't overwrite character with status
  582.     cmp    repflg,0        ; doing REPLAY from a file?
  583.     je    outch3            ; e = no
  584.     and    al,7fh            ; strip parity
  585.     cmp    al,'C'-40h        ; Control-C? (to exit playback mode)
  586.     je    outch2a            ; e = yes, return failure
  587.     clc                ; return success, send nothing
  588.     ret
  589. outch2a:stc                ; return failure to exit playback mode
  590.     ret
  591. outch3: push    cx            ; save registers
  592.     push    dx
  593. outch3b:cmp    dupflg,0        ; full duplex?
  594.     je    outch3d            ; e = yes
  595.     mov    al,0f1h        ; enable RTS and DTR Note: bits reversed [gbs]
  596.     out    mnctrl,al        ;[DTR]          compared to documentation
  597.     in    al,mnctrl
  598.     test    al,4            ; ignore CTS if DSR is not asserted
  599.     jz    outch3d            ; z = DSR not asserted
  600.     mov    cx,8000            ; ~10 seconds worth of waiting on CTS
  601. outch3c:in    al,mnctrl
  602.     test    al,8            ; is CTS asserted?
  603.     jnz    outch3d            ; nz = yes
  604.     push    cx
  605.     push    dx
  606.     mov    ax,1            ; wait one millisec
  607.     call    pcwait
  608.     pop    dx
  609.     pop    cx
  610.     loop    outch3c            ; test again
  611.     call    beep            ; half duplex timeout, make non-fatal
  612.     pop    dx
  613.     pop    cx
  614.     clc
  615.     ret
  616.  
  617. outch3d:xor    cx,cx
  618.     mov    dx,mnstata        ; get port status
  619.     in    al,dx
  620.     test    al,txrdy        ; transmitter ready?
  621.     jnz    outch4            ; nz = yes
  622.     jmp    $+2            ; use time, prevent overdriving UART
  623.     loop    outch3b
  624.     jmp    outch5            ; timeout
  625. outch4: mov    al,ah            ; send it out
  626.     mov    dx,mndata        ; use a little time
  627.     jmp    $+2
  628.     out    dx,al
  629.     cmp    dupflg,0        ; full duplex?
  630.     je    outch4a            ; e = yes
  631.     cmp    al,trans.seol        ; End of Line char?
  632.     jne    outch4a            ; ne = no
  633.     mov    al,0f5h            ; disable RTS (4)
  634.     out    mnctrl,al
  635. outch4a:pop    dx            ; exit success
  636.     pop    cx
  637.     clc
  638.     ret
  639. outch5: call    beep
  640.     pop    dx            ; exit failure
  641.     pop    cx
  642.     stc
  643.     ret
  644. OUTCHR    ENDP
  645.  
  646. ; This routine blanks the screen.
  647.  
  648. CMBLNK    PROC    NEAR
  649.     mov    dx,offset clrseq    ; clear screen sequence
  650.     jmp    tmsg
  651. CMBLNK    ENDP
  652.  
  653. ; Locate; homes the cursor.  Returns normally.
  654.  
  655. LOCATE    PROC    NEAR
  656.     xor    dx,dx            ; Go to top left corner of screen
  657.     jmp    poscur
  658. LOCATE    ENDP
  659.  
  660. ; write a line in inverse video at the bottom of the screen...
  661. ; the line is passed in dx, terminated by a $.    Returns normally.
  662. putmod    proc    near
  663.     push    dx        ; preserve message
  664.     mov    dx,24 * 100H    ; line 24
  665.     call    poscur
  666.     mov    dx,offset invseq ; put into inverse video
  667.     call    tmsg
  668.     pop    dx
  669.     call    tmsg        ; print the message
  670.     mov    dx,offset nrmseq ; normal videw
  671.     call    tmsg
  672.     ret            ; and return
  673. putmod    endp
  674.  
  675. ; clear the mode line written by putmod.  Returns normally.
  676. clrmod    proc    near
  677.     mov    dx,24 * 100H
  678.     call    poscur
  679.     jmp    clearl
  680. clrmod    endp
  681.  
  682. ; Put a help message on the screen.  This one uses reverse video...
  683. ; pass the message in ax, terminated by a null.     Returns normally.
  684. puthlp    proc    near
  685.     push    ax
  686.     mov    dx,slen * 100H    ; go to bottom line
  687.     call    poscur
  688.     pop    ax
  689.     push    es
  690.     mov    bx,ds
  691.     mov    es,bx        ; address data segment
  692.     mov    si,ax        ; convenient place for this
  693.     mov    bx,101H        ; current line/position
  694. puthl1: mov    di,offset rdbuf ; this is destination
  695.     xor    cx,cx        ; # of chars in the line
  696.     cld
  697. puthl2: lodsb            ; get a byte
  698.     cmp    al,cr        ; carriage return?
  699.     je    puthl2        ; yes, ignore it
  700.     cmp    al,lf        ; linefeed?
  701.     je    puthl3        ; yes, break the loop
  702.     cmp    al,0
  703.     je    puthl3        ; ditto for null
  704.     dec    cx        ; else count the character
  705.     stosb            ; deposit into the buffer
  706.     jmp    puthl2        ; and keep going
  707. puthl3: add    cx,80        ; this is desired length of the whole
  708.     mov    al,' '
  709.     rep    stosb        ; fill the line
  710.     push    bx
  711.     push    si
  712.     push    es        ; firmware likes to eat this one
  713.     mov    ax,0        ; send chars and attributes
  714.     mov    cx,80        ; this is # of chars to send
  715.     mov    dx,offset ivlatt ; this are attributes to send
  716.     mov    si,offset rdbuf ; the actual message
  717.     mov    di,14H        ; send direct to screen
  718.     mov    bp,ds        ; need data segment as well
  719.     push    ax
  720.     push    cx
  721.     push    dx
  722.     push    di
  723.     mov    di,14H        ; send direct to screen
  724.     int    firmwr
  725.     pop    di
  726.     pop    dx
  727.     pop    cx
  728.     pop    ax
  729.     pop    es
  730.     pop    si
  731.     pop    bx        ; restore everything
  732.     inc    bx        ; next line
  733.     cmp    byte ptr [si-1],0 ; were we ended by a 0 last time?
  734.     jne    puthl1        ; no, keep looping
  735.     pop    es        ; else restore this
  736.     clc
  737.     ret            ; and return
  738. puthlp    endp
  739.  
  740. ; Set the baud rate for the current port, based on the value
  741. ; in the portinfo structure.  Returns normally.
  742.  
  743. BAUDST    PROC    NEAR
  744.     mov    dx,offset bdtab        ; baud rate table, ascii
  745.     xor    bx,bx            ; help is the table itself
  746.     mov    ah,cmkey        ; get keyword
  747.     call    comnd
  748.     jc    baudst1            ; c = failure
  749.     push    bx            ; save result
  750.     mov    ah,cmeol        ; get confirmation
  751.     call    comnd
  752.     pop    bx
  753.     jc    baudst1            ; c = failure
  754.     mov    si,portval
  755.     mov    ax,[si].baud        ; remember original value
  756.     mov    [si].baud,bx        ; set the baud rate
  757.     call    dobaud            ; use common code
  758.     clc
  759. baudst1:ret
  760. BAUDST    ENDP
  761.  
  762. DOBAUD    PROC    NEAR
  763.     push    bx
  764.     push    ds
  765.     pop    es            ; set es to data segment
  766.     cld
  767.     mov    al,bl
  768.     mov    cl,4
  769.     shl    bl,cl            ; shift constant into high nibble
  770.     or    al,bl
  771.     out    bdprt,al        ; write into port
  772.     or    al,0f0h            ; turn on high nibble
  773.     push    es
  774.     mov    bx,nvmseg
  775.     mov    es,bx
  776.     mov    es:[xmitbd],al
  777.     mov    es:[rcvbd],al        ; set baud in nvm
  778.     pop    es
  779.     pop    bx
  780.     ret
  781. DOBAUD    ENDP
  782.  
  783. ; Get the current baud rate from the serial card and set it
  784. ; in the portinfo structure for the current port.  Returns normally.
  785. ; This is used during initialization.
  786.  
  787. GETBAUD PROC    NEAR
  788.     push    ax        ; save some regs
  789.     push    bx
  790.     push    es
  791.     mov    ax,nvmseg
  792.     mov    es,ax
  793.     mov    al,es:[xmitbd]    ; get  xmit baud rate [gbs]
  794.     pop    es
  795.     and    ax,0fh        ; only low nibble is used [gbs]
  796.     mov    bx,portval
  797.     mov    [bx].baud,ax    ; set value
  798.     pop    bx        ; restore regs
  799.     pop    ax
  800.     ret            ; and return
  801. GETBAUD ENDP
  802.  
  803.  
  804. ; Get Char from serial port buffer.
  805. ; skip returns if no character available at port,
  806. ; otherwise returns with char in al, # of chars in buffer in dx.
  807. ; Revised 22 May 1986, and again slightly 2 August 1986 by [jrd]
  808. ; Copied from msxibm.asm [jrd]
  809. PRTCHR    PROC    NEAR
  810.     call    chkxon            ; see if we need to xon
  811.     cmp    repflg,0        ; REPLAY?
  812.     je    prtch0            ; e = no
  813.     jmp    prtch30            ; yes, do replay file reading
  814. prtch0: cmp    count,0            ; any characters available?
  815.     jnz    prtch1            ; nz = yes, get one
  816. prtch0a:xor    dx,dx            ; return count of zero
  817.     stc                ; say no data
  818.     ret
  819. prtch1: push    si            ; save si
  820.     cli        ; interrupts off, to keep srcpnt & count consistent
  821.     mov    si,srcpnt        ; address of next available slot in buffer
  822.     sub    si,count        ; minus number of unread chars in buffer
  823.     cmp    si,offset source    ; located before start of buf?
  824.     jae    prtch2            ; ae = no
  825.     add    si,bufsiz        ; else do arithmetic modulo bufsiz
  826. prtch2: mov    al,byte ptr [si]    ; get a character into al
  827.     dec    count            ; one less unread char now
  828.     sti                ; interrupts back on now
  829.     pop    si
  830.     mov    dx,count        ; return # of chars in buffer
  831.     test    flags.debug,logses    ; debug mode?
  832.     jnz    prtch14            ; nz = yes, pass all chars
  833.     cmp    rxtable+256,0        ; translation turned off?
  834.     jne    prtch14            ; ne = table is on, pass all chars
  835.     cmp    al,0            ; NUL?
  836.     je    prtch13            ; e = yes, ignore it
  837.     cmp    al,DEL            ; DEL char
  838.     jne    prtch14            ; ne = no, pass char
  839. prtch13:xor    dx,dx
  840.     stc                ; no data
  841.     ret
  842. prtch14:clc                ; return char in al
  843.     ret
  844.  
  845. prtch30:push    bx            ; REPLAY, read char from a file
  846.     push    cx
  847.     test    xofsnt,usron        ; user level xoff sent?
  848.     jnz    prtch31            ; nz = yes, suppress reading here
  849.     xor    dx,dx
  850.     mov    ax,100
  851.     mov    bx,1
  852.     jmp    $+2            ; flush lookahead buffer
  853.     div    bx            ; burn some cpu cycles
  854.     jmp    $+2            ; because a 1 ms wait is too long
  855.     div    bx
  856.     jmp    $+2
  857.     div    bx
  858.     mov    ah,readf2
  859.     mov    bx,diskio.handle    ; file handle
  860.     mov    cx,1            ; read one char
  861.     mov    dx,offset rdbuf        ; to this buffer
  862.     int    dos
  863.     jc    prtch31            ; c = read failure
  864.     cmp    ax,cx            ; read the byte?
  865.     jne    prtch31            ; ne = no
  866.     pop    cx
  867.     pop    bx
  868.     mov    al,rdbuf        ; get the char into al
  869.     mov    dx,1            ; external char count
  870.     clc
  871.     ret                ; return it
  872. prtch31:pop    cx
  873.     mov    bx,portval
  874.     mov    [bx].portrdy,0        ; say port is not ready
  875.     pop    bx
  876.     xor    dx,dx
  877.     stc                ; say no char
  878.     ret
  879. PRTCHR    ENDP
  880.  
  881.  
  882. ; IHOSTS - Initialize the host by sending XON. Requires that the port be
  883. ; initialized.
  884. IHOSTS    PROC    NEAR
  885.     push    ax        ; save the registers
  886.     push    cx
  887.     push    dx
  888.     mov    xofrcv,off    ; clear old xoff received flag
  889.     mov    xofsnt,off    ; and old xoff sent flag
  890.     mov    ah,flowon    ; put Go-ahead flow control char in ah
  891.     or    ah,ah        ; doing flow control?
  892.     jz    ihosts1        ; z = no, don't send a null
  893.     call    outchr        ; send it (release Host's output queue)
  894. ihosts1:pop    dx        ; empty buffer. we are done here
  895.     pop    cx
  896.     pop    ax
  897.     ret
  898. IHOSTS    ENDP
  899.  
  900. ; IHOSTR - initialize the remote host for our reception of a file by
  901. ; sending the flow-on character (XON typically) to release any held
  902. ; data. Called by receive-file code just after initializing the serial
  903. ; port.        22 March 1986 [jrd]
  904. ; Modified 26 June 1986 to supress sending a null if no flow control. [jrd]
  905. IHOSTR    PROC    NEAR
  906.     push    ax        ; save regs
  907.     push    cx
  908.     mov    xofrcv,off    ; clear old xoff received flag
  909.     mov    xofsnt,off    ; and old xoff sent flag
  910.     mov    ah,flowon    ; put Go-ahead flow control char in ah
  911.     or    ah,ah        ; doing flow control?
  912.     jz    ihostr1        ; z = no, don't send a null
  913.     call    outchr        ; send it (release Host's output queue)
  914. ihostr1:pop    cx
  915.     pop    ax
  916.     ret
  917. IHOSTR    ENDP
  918.  
  919. ; local routine to see if we have to transmit an xon
  920. chkxon    proc    near
  921.     cmp    flowon,0    ; doing flow control?
  922.     je    chkxo1        ; no, skip all this
  923.     test    xofsnt,usron    ; did user send an xoff?
  924.     jnz    chkxo1        ; nz = yes, don't contradict it here
  925.     test    xofsnt,bufon    ; have we sent a buffer level xoff?
  926.     jz    chkxo1        ; z = no, forget it
  927.     cmp    count,mntrgl    ; below (low water mark) trigger?
  928.     jae    chkxo1        ; no, forget it
  929.     mov    ah,flowon    ; ah gets xon
  930.     and    xofsnt,off    ; remember we've sent the xon
  931.     call    outch2        ; send via non-flow controlled entry point
  932. chkxo1: ret
  933. chkxon    endp
  934.  
  935. ; Send a BREAK out the current serial port.  Returns normally.
  936. SENDBR    PROC    NEAR
  937.     push    cx
  938.     mov    cx,275        ; 275 millisec
  939.     call    sendbw        ; let worker routine do it
  940.     pop    cx
  941.     clc            ; don't exit Connect mode
  942.     ret
  943. ; Send a Log BREAK out the current serial port.
  944. SENDBL: push    cx
  945.     mov    cx,1800        ; 1800 millisec
  946.     call    sendbw        ; let worker routine do it
  947.     pop    cx
  948.     clc            ; don't exit Connect mode
  949.     ret
  950.  
  951. sendbw: push    ax        ; worker routine to send a break [jrd]
  952.     push    bx        ; number of millisec is in cx
  953.     push    dx
  954.     mov    ah,ioctl
  955.     mov    al,3        ; write to control channel
  956.     mov    bx,3        ; aux port handle
  957.     mov    dx,offset iobuf
  958.     mov    iobuf,stbrk        ; start sending a break
  959.     int    dos
  960.     mov    ax,cx        ; # of ms to wait
  961.     call    pcwait        ; hold break for desired interval
  962.     mov    ah,ioctl
  963.     mov    al,3
  964.     mov    bx,3
  965.     mov    dx,offset iobuf
  966.     mov    iobuf,enbrk        ; stop sending the break
  967.     int    dos
  968.     pop    dx
  969.     pop    bx
  970.     pop    ax
  971.     clc
  972.     ret
  973. SENDBR    ENDP
  974.  
  975.  
  976. ; wait for the # of milliseconds in ax
  977. ; thanks to Bernie Eiben for this one.
  978. pcwait    proc    near
  979.     push    cx
  980. pcwai0: mov    cx,240        ; inner loop counter for 1 millisecond
  981. pcwai1: sub    cx,1        ; inner loop takes 20 clock cycles
  982.     jnz    pcwai1
  983.     dec    ax        ; outer loop counter
  984.     jnz    pcwai0        ; wait another millisecond
  985.     pop    cx
  986.     ret
  987. pcwait    endp
  988.  
  989.  
  990. ; Position the cursor according to contents of DX:
  991. ; DH contains row, DL contains column.    Returns normally.
  992.  
  993. POSCUR    PROC    NEAR
  994.     add    dx,101H        ; start at 1,1
  995.     push    es
  996.     push    ax        ; save some regs
  997.     push    bx
  998.     push    di
  999.     push    dx
  1000.     cld
  1001.     mov    ax,ds
  1002.     mov    es,ax        ; address data segment
  1003.     mov    di,offset rowp
  1004.     mov    al,dh        ; row comes first
  1005.     mov    ah,0
  1006.     call    nout
  1007.     mov    al,';'
  1008.     stosb            ; separated by a semicolon
  1009.     pop    dx
  1010.     mov    al,dl
  1011.     mov    ah,0
  1012.     call    nout
  1013.     mov    al,'H'
  1014.     stosb            ; end w/H
  1015.     mov    byte ptr [di],'$' ; and dollar sign
  1016.     mov    dx,offset gopos
  1017.     call    tmsg
  1018.     pop    di        ; restore regs
  1019.     pop    bx
  1020.     pop    ax
  1021.     pop    es
  1022.     ret
  1023. POSCUR    ENDP
  1024.  
  1025. ; Delete a character from the terminal.     This works by printing
  1026. ; backspaces and spaces.  Returns normally.
  1027.  
  1028. DODEL    PROC    NEAR
  1029.     mov    dx,offset delstr    ; Erase weird character
  1030.     jmp    tmsg
  1031. DODEL    ENDP
  1032.  
  1033. ; Move the cursor to the left margin, then clear to end of line.
  1034. ; Returns normally.
  1035.  
  1036. CTLU    PROC    NEAR
  1037.     mov    dx,offset clrlin    ; this just goes to left margin
  1038.     call    tmsg
  1039.     jmp    clearl            ; now clear line
  1040. CTLU    ENDP
  1041.  
  1042. ; set the current port.
  1043.  
  1044. COMS    PROC    NEAR
  1045.     mov    dx,offset nyimsg
  1046.     jmp    tmsg
  1047. COMS    ENDP
  1048.  
  1049. ; Set Terminal command
  1050.  
  1051. VTS    PROC    NEAR            ; SET TERM whatever  [jrd]
  1052.     mov    ah,cmkey        ; parse key word
  1053.     xor    bx,bx            ; use built-in help
  1054.     mov    dx,offset vttbl        ; use this table
  1055.     call    comnd
  1056.     jc    vts0
  1057.     cmp    bx,tttypes        ; ROLL or more?
  1058.     ja    vts4            ; a = yes
  1059.                     ; SET TERM {VT52 | VT102}
  1060.     push    bx
  1061.     mov    ah,cmeol
  1062.     call    comnd            ; get a confirm
  1063.     pop    bx
  1064.     jnc    vts1            ; nc = success
  1065. vts0:    ret
  1066. vts1:    cmp    bl,ttvt100        ; set to VT102?
  1067.     je    vts2            ; e = yes
  1068.     mov    flags.vtflg,ttvt52    ; say VT52
  1069.     jmp    vts3
  1070. vts2:    mov    flags.vtflg,ttvt100    ; say VT102
  1071. vts3:    call    setterm            ; send the message to the console
  1072.     ret
  1073. vts4:    mov    ah,cmkey        ; SET TERM ROLL
  1074.     mov    bx,offset rolhlp    ; help message
  1075.     mov    dx,offset ontab        ; table of answers
  1076.     call    comnd
  1077.     jc    vts6
  1078.     push    bx
  1079.     mov    ah,cmeol
  1080.     call    comnd            ; get a confirm
  1081.     pop    bx
  1082.     jc    vts6
  1083.     mov    vtroll,bl        ; set the flag
  1084. vts6:    ret
  1085. VTS    ENDP
  1086.  
  1087. VTSTAT    PROC    NEAR            ; Status routine for emulation. [jrd]
  1088.     mov    bx,offset vtstbl    ; table of things to show
  1089.     jmp    statc            ; status common code, in mssset
  1090. VTSTAT    ENDP
  1091.  
  1092. ; initialization for using serial port.     This routine performs
  1093. ; any initialization necessary for using the serial port, including
  1094. ; setting up interrupt routines, setting buffer pointers, etc.
  1095. ; Doing this twice in a row should be harmless (this version checks
  1096. ; a flag and returns if initialization has already been done).
  1097. ; SERRST below should restore any interrupt vectors that this changes.
  1098. ; Returns normally.
  1099.  
  1100. SERINI    PROC    NEAR
  1101.     cmp    portin,0        ; Did we initialize port already?
  1102.     jne    serin0            ; ne = yes, so just leave
  1103.     cli                ; Disable interrupts
  1104.     cld                ; Do increments in string operations
  1105.     push    es
  1106.     push    si            ; [ejz] - Save this just in case
  1107.     mov    si,offset prtpar    ; [ejz]
  1108.     mov    dx,mnstata        ; [ejz]
  1109.     push    ds
  1110.     pop    es            ; set es to data segment
  1111.     call    prtset            ; [ejz]
  1112.     xor    ax,ax            ; Address low memory
  1113.     mov    es,ax
  1114.     mov    ax,es:[4*serchn]    ; get old serial handler
  1115.     mov    oldser,ax        ; save
  1116.     mov    ax,es:[4*serchn+2]    ; get segment
  1117.     mov    oldseg,ax        ; save segment as well
  1118.     mov    ax,es:[4*serch1]    ; this is alternate for older rainbows
  1119.     mov    old1ser,ax
  1120.     mov    ax,es:[4*serch1+2]
  1121.     mov    old1seg,ax        ; pretty silly, huh?
  1122.     mov    ax,offset serint    ; point to our routine
  1123.     mov    es:[4*serchn],ax    ; point at our serial routine
  1124.     mov    es:[4*serch1],ax    ; have to set both of these
  1125.     mov    es:[4*serchn+2],cs    ; our segment
  1126.     mov    es:[4*serch1+2],cs
  1127.     pop    si            ; [ejz]
  1128.     pop    es
  1129.     mov    al,0f1h        ; enable RTS and DTR Note: bits reversed [gbs]
  1130.     out    mnctrl,al        ;[DTR]          compared to documentation
  1131.     mov    portin,1        ; Remember port has been initialized
  1132.     sti                ; Allow interrupts
  1133.     push    bx
  1134.     mov    bx,portval        ; get port
  1135.     mov    parmsk,0ffh        ; parity mask, assume parity is None
  1136.     cmp    [bx].parflg,parnon    ; is it None?
  1137.     je    serin1            ; e = yes
  1138.     mov    parmsk,07fh        ; no, pass lower 7 bits as data
  1139. serin1: mov    bx,[bx].flowc        ; get flow control chars
  1140.     mov    flowoff,bl        ; xoff or null
  1141.     mov    flowon,bh        ; xon or null
  1142.     pop    bx
  1143. serin0: clc                ; carry clear for success
  1144.     ret
  1145. SERINI    ENDP
  1146.  
  1147. ; this is used to by serini
  1148. prtset    proc    near
  1149.     cld
  1150.     lodsb            ; get a byte
  1151.     or    al,al
  1152.     jz    prtse1        ; end of table, stop here
  1153.     out    dx,al        ; else send it out
  1154.     jmp    short prtset    ; and keep looping
  1155. prtse1: ret            ; end of routine
  1156. prtset    endp
  1157.  
  1158. ; Reset the serial port.  This is the opposite of serini.  Calling
  1159. ; this twice without intervening calls to serini should be harmless.
  1160. ; Returns normally.
  1161.  
  1162. SERRST    PROC    NEAR
  1163.     cmp    portin,0        ; reset already?
  1164.     je    srst1            ; e = yes, just leave
  1165.     cli                ; disable interrupts
  1166.     push    es            ; preserve this
  1167.     xor    ax,ax
  1168.     mov    es,ax            ; address segment 0
  1169.     mov    ax,oldser
  1170.     mov    es:[4*serchn],ax
  1171.     mov    ax,oldseg
  1172.     mov    es:[4*serchn+2],ax
  1173.     mov    ax,old1ser
  1174.     mov    es:[4*serch1],ax
  1175.     mov    ax,old1seg
  1176.     mov    es:[4*serch1+2],ax    ; restore old handlers
  1177.     mov    portin,0        ; reset flag
  1178.     pop    es
  1179.     sti                ; re-enable interrupts
  1180. srst1:    ret
  1181. SERRST    ENDP
  1182.  
  1183. ; serial port interrupt routine.  This is not accessible outside this
  1184. ; module, handles serial port receiver interrupts.
  1185. ; New code, lifted from msxibm. [jrd]
  1186. serint    PROC  NEAR
  1187.     push    ax
  1188.     push    ds
  1189.     push    bx
  1190.     push    dx
  1191.     mov    ax,seg data
  1192.     mov    ds,ax            ; address data segment
  1193.     mov    dx,mnstatb        ; Asynch status port
  1194.     xor    al,al            ; innocuous value
  1195.     out    dx,al            ; send out to get into a known state
  1196.     mov    al,2            ; now address register 2
  1197.     out    dx,al
  1198.     in    al,dx            ; read interrupt cause
  1199.     cmp    al,7            ; in range?
  1200.     ja    serin7        ; no, just dismiss (what about reset error?)
  1201.     mov    bl,al
  1202.     shl    bl,1            ; double for word index
  1203.     xor    bh,bh
  1204.     call    ivec[bx]        ; call appropriate handler
  1205.     jmp    short serin8
  1206. serin7: mov    dx,mnstata        ; reload port address
  1207.     mov    al,38H
  1208.     out    dx,al        ; tell the port we finished with the interrupt
  1209.     sti                ; turn on interrupts
  1210. serin8: pop    dx
  1211.     pop    bx
  1212.     pop    ds
  1213.     pop    ax
  1214. intret: iret
  1215.  
  1216. ; handler for serial receive, port A
  1217.  
  1218. srcva:    mov dx,mnstata
  1219.     xor    al,al        ; Asynch status port
  1220.     out    dx,al        ; put into known state
  1221.     jmp    $+2
  1222.     in    al,dx
  1223.     test    al,rxrdy    ; Data available?
  1224.     jnz    srcva0a        ; nz = yes
  1225. srcva0: mov    dx,mnstata
  1226.     mov    al,38h        ; tell port we are finished with the interrupt
  1227.     out    dx,al
  1228.     sti            ; turn on interrupts
  1229.     jmp    retint        ;  and exit now (common jump point)
  1230.  
  1231. srcva0a:;;and al,mdmover    ; select overrun bit
  1232. ;;    mov    overrun,al    ; save it for later
  1233.     mov    al,30h        ; clear any errors
  1234.     out    dx,al
  1235.     mov    dx,mndata    ; get modem rx data
  1236.     in    al,dx        ; read the received character into al
  1237.     cmp    flowoff,0    ; flow control active?
  1238.     je    srcva2        ; e = no
  1239.     mov    ah,al        ; ah = working copy. Check null, flow cntl
  1240.     and    ah,parmsk    ; strip parity temporarily, if any
  1241.     cmp    ah,flowoff    ; acting on Xoff?
  1242.     jne    srcva1        ; ne = Nope, go on
  1243.     mov    xofrcv,bufon    ; Set the flag saying XOFF received
  1244.     jmp    srcva0        ;  and exit
  1245. srcva1: cmp    ah,flowon    ; acting on Xon?
  1246.     jne    srcva2        ; ne = no, go on
  1247.     mov    xofrcv,off    ; Clear the XOFF received flag
  1248.     jmp    srcva0        ;  and exit
  1249. srcva2: push    ax        ; save rcvd char around this output cmd
  1250.     mov    dx,mnstata
  1251.     mov    al,38h        ; tell port we are finished with the interrupt
  1252.     out    dx,al
  1253.     pop    ax
  1254.     cli            ; ensure interrupts are off, critical section
  1255. ;;    mov    ah,overrun        ; get overrun flag
  1256. ;;    or    ah,ah        ; overrun?
  1257. ;;    jz    srcva2a        ; z = no
  1258. ;;    mov    ah,al        ; yes, save present char
  1259. ;;    mov    al,bell        ; insert control-G for missing character
  1260. srcva2a:mov    bx,srcpnt    ; address of buffer storage slot
  1261.     mov    byte ptr [bx],al ; store the new char in buffer "source"
  1262.     inc    srcpnt        ; point to next slot
  1263.     inc    bx
  1264.     cmp    bx,offset source + bufsiz ; beyond end of buffer?
  1265.     jb    srcva3        ; b = not past end
  1266.     mov    srcpnt,offset source ; wrap buffer around
  1267. srcva3: cmp    count,bufsiz    ; filled already?
  1268.     jae    srcva4        ; ae = yes
  1269.     inc    count        ; no, add a char
  1270. srcva4:;;or    ah,ah        ; anything in overrun storage?
  1271. ;;    jz    srcva4a        ; z = no
  1272. ;;    mov    al,ah        ; recover any recent char from overrun
  1273. ;;    xor    ah,ah        ; clear overrun storage
  1274. ;;    jmp    srcva2a        ; yes, go store real second char
  1275. srcva4a:sti            ; ok to allow interrupts now, not before
  1276.     cmp    count,mntrgh    ; past the high trigger point?
  1277.     jbe    retint        ; be = no, we're within our limit
  1278.     test    xofsnt,bufon    ; Has an XOFF been sent by buffer control?
  1279.     jnz    retint        ; nz = yes
  1280.     mov    al,flowoff    ; get the flow off char (Xoff or null)
  1281.     or    al,al        ; don't send null chars
  1282.     jz    retint        ; z = null, nothing to send
  1283.     call    dopar        ; Set parity appropriately
  1284.     mov    ah,al        ; Don't overwrite character with status
  1285.     push    cx        ; save reg
  1286.     xor    cx,cx        ; loop counter
  1287. srcva5: mov    dx,mnstata    ; port status register
  1288.     in    al,dx
  1289.     test    al,txrdy    ; Transmitter ready?
  1290.     jnz    srcva6        ; nz = yes
  1291.     push    ax        ; use time, prevent overdriving UART
  1292.     pop    ax
  1293.     loop    srcva5        ; else wait loop, cx times
  1294.     jmp    short srcva7    ; Timeout
  1295. srcva6: mov    al,ah        ; Now send out the flow control char
  1296.     mov    dx,mndata
  1297.     out    dx,al
  1298.     mov    xofsnt,bufon    ; Remember we sent an XOFF at buffer level
  1299. srcva7: pop    cx        ; restore reg
  1300. retint: ret
  1301.  
  1302. ; The interrupt is for the 'B' port - transfer control to
  1303. ; the original handler and hope for the best.
  1304. tranb:    pushf            ; put flags on stack to simulate interrupt
  1305.     call    dword ptr [old1ser] ; call old handler
  1306.     jmp    srccom        ; take common exit
  1307.  
  1308. stxa:    mov    dx,mnstata
  1309.     mov    al,28H        ; reset transmit interrupt
  1310.     out    dx,al
  1311.     jmp    srccom        ; take common exit
  1312.  
  1313. sstata: mov    dx,mnstata
  1314.     mov    al,10H        ; reset status interrupt
  1315.     out    dx,al        ; fall through to common exit srccom below
  1316.  
  1317. srccom: mov    dx,mnstata    ; common exit for above
  1318.     mov    al,38h        ; tell port we are finished with the interrupt
  1319.     out    dx,al
  1320.     sti            ; turn on interrupts
  1321.     ret
  1322.  
  1323. SERINT    ENDP
  1324.  
  1325. DTRLOW    PROC    NEAR        ; Global proc to Hangup the Phone by making
  1326.                 ; DTR and RTS low.
  1327.     mov    ah,cmline        ; allow text, to display help
  1328.     mov    bx,offset rdbuf        ; dummy buffer
  1329.     mov    dx,offset hnghlp    ; help message
  1330.     call    comnd            ; get a confirm
  1331.     jc    dtrlow1
  1332.     call    serhng            ; drop DTR and RTS
  1333.     mov    ah,prstr        ; give a nice message
  1334.     mov    dx,offset hngmsg
  1335.     int    dos
  1336.     clc
  1337. dtrlow1:ret
  1338. DTRLOW    ENDP
  1339.  
  1340. ; Hang up the Phone. Similar to SERRST except it just forces DTR and RTS low
  1341. ; to terminate the connection. 29 March 1986 [jrd]
  1342. ; Calling this twice without intervening calls to serini should be harmless.
  1343. ; Returns normally.
  1344.  
  1345. serhng    proc    near
  1346.     call    serrst        ; reset the port so can be restarted cleanly
  1347.     cli            ; Disable interrupts
  1348.     mov    al,0ffh        ; disable RTS and DTR            [gbs]
  1349.     out    mnctrl,al    ; [DTR]
  1350.     sti            ; Allow interrupts
  1351.     mov    ax,500
  1352.     call    pcwait        ; wait 500ms
  1353.     clc
  1354.     ret
  1355. serhng    endp
  1356.  
  1357. ; Produce a short beep.
  1358. ; Returns normally.
  1359.  
  1360. BEEP    PROC    NEAR
  1361.     mov    dl,bell
  1362.     mov    ah,conout
  1363.     int    dos
  1364.     clc
  1365.     ret
  1366. BEEP    ENDP
  1367.  
  1368. ; put the number in ax into the buffer pointed to by di.  Di is updated
  1369. nout    proc    near
  1370.     mov    dx,0        ; high order is always 0
  1371.     mov    bx,10
  1372.     div    bx        ; divide to get digit
  1373.     push    dx        ; save remainder digit
  1374.     or    ax,ax        ; test quotient
  1375.     jz    nout1        ; zero, no more of number
  1376.     call    nout        ; else call for rest of number
  1377. nout1:    pop    ax        ; get digit back
  1378.     add    al,'0'        ; make printable
  1379.     cld
  1380.     stosb            ; drop it off
  1381.     ret
  1382. nout    endp
  1383.  
  1384.  
  1385. term    proc    near
  1386.     mov    si,ax            ; this is source
  1387.     mov    argadr,ax        ; save here too
  1388.     mov    di,offset ourarg    ; place to store arguments
  1389.     mov    ax,ds
  1390.     mov    es,ax            ; address destination segment
  1391.     mov    cx,size termarg
  1392.     cld
  1393.     rep    movsb            ; copy into our arg blk
  1394.     cmp    inited,0        ; inited yet?
  1395.     jne    term0            ; ne = yes
  1396.     call    cmblnk            ; clear the screen
  1397.     call    locate            ; put cursor at top left corner
  1398.     mov    inited,1        ; say initialized
  1399.     jmp    short term0a
  1400. term0:    call    rstscr            ; restore screen
  1401. term0a:    mov    inited,1        ; remember inited
  1402.     mov    parmsk,0ffh        ; parity mask, assume parity = None
  1403.     cmp    ourarg.parity,parnon    ; is parity None?
  1404.     je    term1            ; e = yes, keep all 8 bits
  1405.     mov    parmsk,07fh        ; else keep lower 7 bits
  1406.  
  1407. term1:    call    portchr              ; get char from port, apply parity mask
  1408.     jnc    short term3        ; nc = char
  1409. term2:    mov    fairness,0        ; say kbd was examined
  1410.     call    keybd            ; call keyboard translator in msu
  1411.     jnc    term1            ; nc = no char or have processed it
  1412.     call    pntflsh            ; flush printer buffer
  1413.     call    savscr            ; save screen
  1414.     mov    dx,offset gtobot    ; go to last line on screen
  1415.     call    tmsg
  1416.     stc
  1417.     ret                ; carry set = quit connect mode
  1418.  
  1419. term3:    call    outtty            ; print on terminal
  1420.     inc    fairness        ; say read port but not kbd, again
  1421.     cmp    fairness,200        ; this many port reads before kbd?
  1422.     jb    term1            ; b = no, read port again
  1423.     call    pntflsh            ; flush printer buffer
  1424.     jmp    short term2        ; yes, let user have a chance too
  1425. term    endp
  1426.  
  1427. ; Get a char from the serial port manager, return it in al
  1428. ; returns with carry clear if a character is available, else carry set
  1429. portchr    proc    near
  1430.     call    prtchr            ; character at port?
  1431.     jnc    portc1            ; nc = yes
  1432. portc0:    stc                ; carry = no character
  1433.     ret
  1434. portc1:    and    al,parmsk        ; apply 8/7 bit parity mask
  1435.     or    al,al            ; catch nulls
  1436.     jz    portc0            ; z = null, ignore it
  1437.     cmp    al,del            ; catch dels
  1438.     je    portc0            ; e = del, ignore it
  1439. portc2:    clc                ; have a character, in AL
  1440.     ret
  1441. portchr    endp
  1442.  
  1443. ; put the character in al to the screen
  1444. outtty    proc    near
  1445.     push    es            ; protect es around fastcon calls
  1446.     test    flags.remflg,d8bit    ; keep 8 bits for displays?
  1447.     jnz    outnp5            ; nz = yes, 8 bits if possible
  1448.     and    al,7fh            ; remove high bit
  1449. outnp5: cmp    rxtable+256,0        ; translation turned off?
  1450.     je    outnp7            ; e = yes, no translation
  1451.     push    bx
  1452.     mov    bx,offset rxtable    ; address of translate table
  1453.     xlatb                ; new char is in al
  1454.     pop    bx
  1455. outnp7: test    ourflgs,fpscr+vtautop+vtcntp ; should we be printing?
  1456.     jz    outnop            ; z = no, keep going
  1457.     call    pntchr            ; queue char for printer
  1458.     jnc    outnop            ; nc = successful print
  1459.     push    ax
  1460.     call    beep            ; else make a noise and
  1461.     call    trnprs            ;  turn off printing
  1462.     pop    ax
  1463.     and    ourflgs,not (fpscr+vtautop+vtcntp) ; turn off printing
  1464.     pop    ax
  1465. outnop: test    ourarg.flgs,capt    ; capturing output?
  1466.     jz    outnoc            ; z = no, forget this part
  1467.     push    ax            ; save char
  1468.     call    ourarg.captr        ; give it captured character
  1469.     pop    ax            ; restore character and keep going
  1470. outnoc:
  1471.     cmp    vtroll,0        ; auto roll back allowed?
  1472.     jz    outnp6            ; z = no, leave screen as is
  1473.     cmp    bwnd.lcnt,0        ; is screen rolled back? [dlk]
  1474.     je    outnp6            ; e = no
  1475.     call    nxtbot            ; restore screen before writing [dlk]
  1476. outnp6: push    ax
  1477.     call    scrprep            ; need to save top line
  1478.     pop    ax
  1479.     test    ourarg.flgs,trnctl    ; debug? if so use Bios tty mode
  1480.     jz    outnp3            ; z = no
  1481.     cmp    al,7fh            ; Ascii Del char or greater?
  1482.     jb    outnp1            ; b = no
  1483.     je    outnp0            ; e = Del char
  1484.     push    ax            ; save the char
  1485.     mov    al,7eh            ; output a tilde for 8th bit
  1486.     int    fastcon
  1487.     pop    ax            ; restore char
  1488.     and    al,7fh            ; strip high bit
  1489. outnp0: cmp    al,7fh            ; is char now a DEL?
  1490.     jne    outnp1            ; ne = no
  1491.     and    al,3fH            ; strip next highest bit (Del --> '?')
  1492.     jmp    outnp2            ; send, preceded by caret
  1493. outnp1: cmp    al,' '            ; control char?
  1494.     jae    outnp3            ; ae = no
  1495.     add    al,'A'-1        ; make visible
  1496. outnp2: push    ax            ; save char
  1497.     mov    al,5eh            ; caret
  1498.     int    fastcon            ; display it
  1499.     pop    ax            ; recover the non-printable char
  1500. outnp3: call    ansbak            ; match answerback sequences
  1501.     test    ourflgs,vtcntp        ; autoprint on?        ;gbs
  1502.     jnz    outnp4            ; if so, don't output to screen
  1503.     push    ax
  1504.     int    fastcon            ; write without intervention
  1505.     pop    ax
  1506. outnp4: pop    es
  1507.     ret
  1508. outtty    endp
  1509.  
  1510. ; enter with current terminal character in al.
  1511. ; calls answerback routine if necessary.
  1512. ; This can be used to make the emulator recognize any sequence.
  1513. ansbak    proc    near
  1514.     push    bx
  1515.     mov    bx,offset ansbk1    ; check 1st answerback
  1516.     call    ansbak0            ; check for answerback
  1517.     mov    bx,offset ansbk2    ; maybe second answerback
  1518.     call    ansbak0            ; should probably loop thru a table
  1519.     mov    bx,offset ansbk3
  1520.     call    ansbak0
  1521.     mov    bx,offset ansbk4
  1522.     call    ansbak0
  1523.     mov    bx,offset ansbk5
  1524.     call    ansbak0
  1525.     mov    bx,offset ansbk6
  1526.     call    ansbak0
  1527.     mov    bx,offset ansbk7
  1528.     call    ansbak0
  1529.     mov    bx,offset ansbk8
  1530.     call    ansbak0
  1531.     mov    bx,offset ansbk9
  1532.     call    ansbak0
  1533.     mov    bx,offset ansbk10
  1534.     call    ansbak0
  1535.     mov    bx,offset ansbk11
  1536.     call    ansbak0
  1537.     mov    bx,offset ansbk12
  1538.     call    ansbak0
  1539.     mov    bx,offset ansbk13
  1540.     call    ansbak0
  1541.     mov    bx,offset ansbk14
  1542.     call    ansbak0
  1543.     pop    bx
  1544.     ret
  1545. ansbak0:            ; worker routine for above
  1546.     push    ax        ; preserve these
  1547.     push    si
  1548.     mov    si,[bx].anspt    ; get current pointer
  1549.     cmp    al,[si]        ; is it correct?
  1550.     jne    ansba1        ; no, reset pointers and go on
  1551.     inc    [bx].anspt    ; increment pointer
  1552.     dec    [bx].ansct    ; decrement counter
  1553.     jnz    ansba2        ; not done, go on
  1554.     push    bx
  1555.     call    [bx].ansrtn    ; send answerback
  1556.     pop    bx
  1557. ansba1: mov    ax,[bx].ansseq    ; get original sequence
  1558.     mov    [bx].anspt,ax
  1559.     mov    al,[bx].anslen    ; and length
  1560.     mov    [bx].ansct,al
  1561. ansba2: pop    si
  1562.     pop    ax
  1563.     ret
  1564. ansbak    endp
  1565.  
  1566. ; send the answerback message.
  1567. sndans    proc    near
  1568.     push    cx
  1569.     mov    si,offset ansret    ; ansi ident message
  1570.     mov    cx,ansrln        ; length of same
  1571.     push    es            ; save seg register
  1572.     mov    ax,nvmseg        ; fetch address of nvm
  1573.     mov    es,ax            ; put in segment reg
  1574.     test    byte ptr es:[vt52mod],1      ; check bit zero
  1575.     pop    es            ; restore the seg register
  1576.     jnz    sndan1            ; nz = ansi mode
  1577.     mov    si,offset VT52ret    ; say VT52
  1578.     mov    cx,VT52ln
  1579. sndan1: cld
  1580.     lodsb                ; get a byte
  1581.     mov    ah,al
  1582.     push    si
  1583.     push    cx
  1584.     call    outchr            ; send ah out the serial port
  1585.     pop    cx
  1586.     pop    si
  1587.     loop    sndan1
  1588.     pop    cx
  1589.     ret
  1590. sndans    endp
  1591.  
  1592. ; enable alternate keypad mode
  1593. enaaky    proc    near
  1594.     mov    akeyflg,1        ; set keypad alternate mode
  1595.     ret
  1596. enaaky    endp
  1597.  
  1598. ; disable alternate keypad mode
  1599. deaaky    proc    near
  1600.     mov    akeyflg,0
  1601.     ret
  1602. deaaky    endp
  1603.  
  1604. cuapp    proc    near
  1605.     mov    ckeyflg,1        ; set cursor keys to applications mode
  1606.     ret
  1607. cuapp    endp
  1608.  
  1609. cunapp    proc    near
  1610.     mov    ckeyflg,0        ; set cursor keys to cursor mode
  1611.     ret
  1612. cunapp    endp
  1613.  
  1614. ; ESC c handler.
  1615. ; Send a space so the firmware doesn't see bad escape sequences. [jrd]
  1616. sndspc    proc    near
  1617.     mov    akeyflg,0        ; reset keypad applications mode
  1618.     mov    ckeyflg,0        ; reset cursor applications mode
  1619.     mov    al,' '            ; space separates the ESC and 'c'
  1620.     int    fastcon            ; send this to upset esc parser
  1621.     push    ax
  1622.     call    nxtbot            ; go to end of screen buffer
  1623.     call    cmblnk            ; clear the screen too
  1624.     pop    ax
  1625.     clc
  1626.     ret
  1627. sndspc    endp
  1628.  
  1629. ; answer a cursor position report
  1630. ansenq    proc    near
  1631.     push    es
  1632.     push    di
  1633.     mov    di,offset rdbuf        ; convenient scratch buffer
  1634.     mov    al,escape
  1635.     cld
  1636.     push    ds
  1637.     pop    es            ; set es to data segment
  1638.     stosb
  1639.     mov    al,'['
  1640.     stosb
  1641.     push    es
  1642.     mov    ax,scrseg
  1643.     mov    es,ax
  1644.     mov    al,es:[csrlin]
  1645.     mov    ah,es:[csrcol]
  1646.     pop    es
  1647.     push    ax
  1648.     xor    ah,ah
  1649.     call    nout
  1650.     mov    al,';'
  1651.     stosb
  1652.     pop    ax
  1653.     xchg    ah,al
  1654.     xor    ah,ah
  1655.     call    nout
  1656.     mov    al,'R'
  1657.     stosb
  1658.     mov    si,offset rdbuf
  1659.     sub    di,si
  1660.     mov    cx,di
  1661. ansen1: lodsb                ; get a byte
  1662.     push    si
  1663.     push    cx
  1664.     mov    ah,al
  1665.     call    outchr            ; send it along
  1666.     pop    cx
  1667.     pop    si
  1668.     loop    ansen1            ; loop thru all
  1669.     pop    di
  1670.     pop    es
  1671.     ret                ; and return
  1672. ansenq    endp
  1673.  
  1674. ; set terminal to vt52 or vt102, based on current flags.vtflg [jrd]
  1675. setterm proc    near
  1676.     push    es            ; save seg register
  1677.     mov    ax,nvmseg        ; fetch address of nvm
  1678.     mov    es,ax            ; put in segment reg
  1679.     test    byte ptr es:[vt52mod],1      ; check bit zero
  1680.     pop    es            ; restore the seg register
  1681.     push    ds
  1682.     pop    es            ; set es to data segment
  1683.     cld
  1684.     jnz    setter1            ; nz = ansi mode
  1685.     cmp    flags.vtflg,ttvt52    ; are we already a VT52?
  1686.     je    setterx            ; e = nothing to do
  1687.     mov    si,offset dovt102    ; change from vt52 to VT102
  1688.     jmp    setter2
  1689. setter1:cmp    flags.vtflg,ttvt100    ; already a VT102?
  1690.     je    setterx            ; e = nothing to do
  1691.     mov    si,offset dovt52    ; change from vt102 to vt52
  1692. setter2:lodsb
  1693.     cmp    al,'$'
  1694.     je    setterx
  1695.     push    es
  1696.     push    si
  1697.     int    fastcon
  1698.     pop    si
  1699.     pop    es
  1700.     jmp    setter2
  1701. setterx:ret
  1702. setterm endp
  1703.  
  1704. ; Handle the print screen key - copy whole screen to printer.
  1705. ; Rewritten 26 June 1986 by [jrd] to avoid confusion over segment addressing
  1706. ;  and line length counting. Based on procedure dumpscr code.
  1707. ; 30-Apr-1990 [gbs] convert line-drawing characters to ".".  Otherwise, they
  1708. ;    output as control characters. (Could shift in/shift out if output
  1709. ;    printer is DEC printer.)
  1710. ; 24-AUG-1990 [rhw-3] added translation table for VT100 graphics to chars
  1711. ;    a normal printer (even non-dec) can swollow.  At least linedraw will
  1712. ;    come out looking like boxes, etc.  See xlat_tab usage below...
  1713. ;    This replaces [gbs] change above.
  1714. ;
  1715. prtscn    proc    near
  1716.     push    ax            ; save some regs
  1717.     push    bx
  1718.     push    cx
  1719.     push    dx
  1720.     push    si
  1721.     push    di
  1722.     push    es
  1723.     call    pntflsh            ; flush printer buffer now
  1724.     xor    bx,bx            ; index for current line pointer
  1725.     mov    cx,slen            ; number of screen lines
  1726. prtsc1: push    cx            ; save outer loop (lines to do) count
  1727.     push    bx            ; save index value for bottom of loop
  1728.     mov    cx,swidth        ; number of screen columns = 132
  1729.     mov    di,offset dumpbuf    ; data segment memory (work buffer)
  1730.     mov    ax,scrseg        ; make es hold screen segment
  1731.     mov    es,ax            ;  for inner read-a-row loop
  1732.     mov    si,es:[latofs+bx]    ; get pointer to current line
  1733.     and    si,0fffh        ; only 12 bits are significant
  1734. prtsc2: mov    al,es:byte ptr [si]    ; inner loop. read text char
  1735.     mov    byte ptr [di],al    ; just store char, don't use es:
  1736.     inc    si            ; update pointers (si needed below)
  1737.     inc    di
  1738.     loop    prtsc2            ; do for all 132 columns, fixed format
  1739.                 ; find end of line, replace nulls with spaces
  1740.     mov    cx,swidth        ; max chars in a line
  1741.     mov    di,offset dumpbuf    ; look at start of line
  1742. prtsc3: mov    al,byte ptr [di]    ; get a byte into al
  1743.     cmp    al,0ffh            ; end of line indicator?
  1744.     je    prtsc5            ; e = yes, exit with count left in cx
  1745. ;;    cmp    al,0            ; is it a nasty null?        x[rhw-3]
  1746. ;;    jne    prtsc4            ; ne = no            x[rhw-3]
  1747. ;;    mov    al,' '            ; replace null with nice space    x[rhw-3]
  1748.  
  1749. prtsc4: cmp    al,' '            ; is it a ctrl (line-draw) char? [gbs]
  1750.     jae    prtsc4a            ; ae = no
  1751. ;;    mov    al,'.'            ; if so, replace with "."[gbs], x[rhw-3]
  1752.     mov    dx,bx            ; [rhw-3] save bx, need to use it
  1753.     mov    bx,offset xlat_tab    ; [rhw-3] get ptr to xlation buffer
  1754.     xlat                ; [rhw-3] lookup & swap old for new char
  1755.     mov    bx,dx            ; [rhw-3] restore bx
  1756.  
  1757. prtsc4a:mov    byte ptr [di],al    ; put back into buffer
  1758.     inc    di            ; look ahead for next char
  1759.     loop    prtsc3            ; scan the rest of the line
  1760. prtsc5: dec    di            ; make di point at eol address
  1761.     mov    ax,swidth        ; max line length
  1762.     sub    ax,cx            ; minus chars scanned = length of line
  1763.     mov    cx,ax            ; remember it here
  1764.                     ; trim line of trailing spaces
  1765.     mov    ax,ds            ; di needs to point to data space
  1766.     mov    es,ax            ; string ops use es:di
  1767.     mov    al,' '            ; thing to scan over
  1768.     std                ; set scan backward
  1769.     repe    scasb            ; scan until non-space, dec's di
  1770.     cld                ; set direction forward
  1771.     jz    prtsc6            ; z = all spaces (count was exhausted)
  1772.     inc    cx            ; go forward over last non-space
  1773.     inc    di            ; ditto for address
  1774. prtsc6: mov    word ptr [di+1],0A0Dh    ; append cr/lf
  1775.     add    cx,2            ; line count + cr/lf
  1776.     mov    dx,offset dumpbuf    ; array to be written
  1777.     mov    bx,prnhand        ; file handle of Connect mode printer
  1778.     mov    ah,write2        ; write the line
  1779.     int    dos
  1780.     pop    bx            ; restore index for line pointer
  1781.     inc    bx            ; add 2 for next pointer's location
  1782.     inc    bx
  1783.     pop    cx            ; get line counter again
  1784.     loop    prtsc1            ; do next line (needs si preset)
  1785.     pop    es
  1786.     pop    di
  1787.     pop    si
  1788.     pop    dx
  1789.     pop    cx
  1790.     pop    bx
  1791.     pop    ax
  1792.     clc
  1793.     ret
  1794. prtscn    endp
  1795.  
  1796. ; toggle print flag. If turning on printing, check for printer ready; skip
  1797. ;  printing if not ready and beep the user. [jrd]
  1798. trnprs    proc    near
  1799.     test    ourflgs,fpscr        ; printing currently?
  1800.     jnz    trnpr1            ; nz = yes, its on and going off
  1801.     call    ckprn            ; see if printer is available
  1802.     jc    trnpr2            ; c = printer not ready
  1803. trnpr1: xor    ourflgs,fpscr        ; flip the flag
  1804. trnpr2: clc
  1805.     ret
  1806. trnprs    endp
  1807.  
  1808. ; autoprint on
  1809. apon    proc    near
  1810.     call    ckprn            ; printer ready?
  1811.     jc    apon1            ; c = printer not ready
  1812.     or    ourflgs,vtautop        ; enable autoprint
  1813. apon1:    clc
  1814.     ret
  1815. apon    endp
  1816.  
  1817. ; autoprint off
  1818. apoff    proc    near
  1819.     and    ourflgs,not vtautop    ; disable autoprint
  1820.     ret
  1821. apoff    endp
  1822.  
  1823. ; print controller on
  1824. prconon proc    near
  1825.     call    ckprn            ; printer ready?
  1826.     jc    pcon1            ; c = printer not ready
  1827.     or    ourflgs,vtcntp        ; enable print controller
  1828. pcon1:    clc
  1829.     ret
  1830. prconon endp
  1831.  
  1832. ; print controller off
  1833. pconoff proc    near
  1834.     and    ourflgs,not vtcntp    ; disable print controller
  1835.     ret
  1836. pconoff endp
  1837.  
  1838. ; check for printer ready -
  1839. ; if not ready, return carry and beep
  1840. ckprn    proc    near
  1841.     push    ax
  1842.     mov    ah,ioctl
  1843.     mov    al,7            ; get output status of printer
  1844.     push    bx
  1845.     mov    bx,prnhand        ; file handle for system printer
  1846.     int    dos
  1847.     pop    bx
  1848.     jc    ckprn1            ; not ready...return carry
  1849.     cmp    al,0ffh            ; Ready status?
  1850.     jnz    ckprn1            ; nz ==> not ready
  1851.     clc                ; show ready
  1852.     jmp    ckprn2
  1853. ckprn1: call    beep            ; let someone know
  1854.     stc                ; indicate not ready
  1855. ckprn2: pop    ax
  1856.     ret
  1857. ckprn    endp
  1858.  
  1859.  
  1860. ; Save the screen to a buffer and then append buffer to a disk file. [jrd]
  1861. ; Default filename is Kermit.scn; actual file can be a device too. Filename
  1862. ; is determined by mssset and is passed as pointer dmpname.
  1863. ; Modified 1 Sept 1986 to do test for dump destination being ready. [jrd]
  1864. ; Modified 24-AUG-90 [rhw-3] added translation table for VT100 graphics
  1865. ;    to normal ascii chars.  This will make the dump file readable &
  1866. ;    printable on any printer (even non-dec).  Now linedraw chars will
  1867. ;    come out looking like boxes, etc.   See xlat_tab usage below...
  1868.  
  1869. dumpscr proc    near            ; global dump-screen procedure
  1870.     push    ax
  1871.     push    bx
  1872.     push    cx
  1873.     push    dx
  1874.     call    savscr            ; first, save screen to memory
  1875.     mov    dmphand,-1        ; preset illegal handle
  1876.     mov    dx,offset dmpname    ; name of disk file, from mssset
  1877.     mov    ax,dx            ; where isfile wants name ptr
  1878.     call    isfile            ; what kind of file is this?
  1879.     jc    dmp5            ; c = no such file, create it
  1880.     test    byte ptr filtst.dta+21,1fh ; file attributes, ok to write?
  1881.     jnz    dmp0            ; nz = no.
  1882.     mov    al,1            ; writing
  1883.     mov    ah,open2        ; open existing file
  1884.     int    dos
  1885.     jc    dmp0            ; c = failure
  1886.     mov    dmphand,ax        ; save file handle
  1887.     mov    bx,ax            ; need handle here
  1888.     mov    cx,0ffffh        ; setup file pointer
  1889.     mov    dx,-1            ; and offset
  1890.     mov    al,2            ; move to eof minus one byte
  1891.     mov    ah,lseek        ; seek the end
  1892.     int    dos
  1893.     jmp    dmp1
  1894.  
  1895. dmp5:    test    filtst.fstat,80h    ; access problem?
  1896.     jnz    dmp0            ; nz = yes
  1897.     mov    ah,creat2        ; file did not exist
  1898.     mov    cx,20h            ; attributes, archive bit
  1899.     int    dos
  1900.     mov    dmphand,ax        ; save file handle
  1901.     jnc    dmp1            ; nc = ok
  1902.  
  1903. dmp0:    mov    dx,offset dmperr    ; say no can do
  1904.     mov    ah,prstr
  1905.     int    dos
  1906.     pop    dx
  1907.     pop    cx
  1908.     pop    bx
  1909.     pop    ax
  1910.     clc
  1911.     ret
  1912.         ; read screen buffer (132 char/line), write lines to file
  1913. dmp1:    mov    ah,ioctl        ; is destination ready for output?
  1914.     mov    al,7            ; test output status
  1915.     mov    bx,dmphand        ; handle
  1916.     int    dos
  1917.     jc    dmp0            ; c = error
  1918.     cmp    al,0ffh            ; ready?
  1919.     jne    dmp0            ; ne = not ready
  1920.     push    di            ; save regs around this work
  1921.     push    si
  1922.     mov    si,ourscr        ; buffer where screen was stored
  1923.     mov    cx,slen            ; number of saved screen lines
  1924. dmp2:    push    cx            ; save outer loop counter
  1925.     mov    di,offset dumpbuf    ; data segement memory (work buffer)
  1926.     mov    cx,swidth        ; number of screen columns = 132
  1927. dmp3:    mov    al,byte ptr [si]    ; read text char
  1928.     mov    byte ptr [di],al    ; store just char, don't use es:
  1929.     inc    si            ; update pointers (si needed below)
  1930.     inc    di
  1931.     loop    dmp3            ; do for all 132 columns, fixed format
  1932.                 ; find end of line, replace nulls with spaces
  1933.     mov    cx,swidth        ; max chars in a line
  1934.     mov    di,offset dumpbuf    ; look at start of line
  1935. dmp7:    mov    al,byte ptr [di]    ; get a byte into al
  1936.     cmp    al,0ffh            ; end of line indicator?
  1937.     je    dmp9            ; e = yes, exit with count left in cx
  1938.  
  1939. ;;    cmp    al,0            ; is it a nasty null?        x[rhw-3]
  1940. ;;    jne    dmp8            ; ne = no            x[rhw-3]
  1941. ;;    mov    al,' '            ; replace null with nice space    x[rhw-3]
  1942.     cmp    al,' '            ; [rhw-3] see if unprintable
  1943.     jae    dmp8            ; [rhw-3] if its >= space then ok
  1944.     mov    dx,bx            ; [rhw-3] save bx, need to use it
  1945.     mov    bx,offset xlat_tab    ; [rhw-3] get ptr to xlation buffer
  1946.     xlat                ; [rhw-3] lookup & swap old for new char
  1947.     mov    bx,dx            ; [rhw-3] restore bx
  1948.  
  1949. dmp8:    mov    byte ptr [di],al    ; put back into buffer
  1950.     inc    di            ; look ahead for next char
  1951.     loop    dmp7            ; scan the rest of the line
  1952. dmp9:    dec    di            ; make di point at eol address
  1953.     mov    ax,swidth        ; max line length
  1954.     sub    ax,cx            ; minus chars scanned = length of line
  1955.     mov    cx,ax            ; remember it here
  1956.                     ; trim line of trailing spaces
  1957.     push    es            ; save register
  1958.     mov    ax,ds            ; di needs to point to data space
  1959.     mov    es,ax            ; string ops use es:di
  1960.     mov    al,' '            ; thing to scan over
  1961.     std                ; set scan backward
  1962.     repe    scasb            ; scan until non-space, dec's di
  1963.     cld                ; set direction forward
  1964.     pop    es            ; restore reg
  1965.     jz    dmp3a            ; z = all spaces (count was exhausted)
  1966.     inc    cx            ; go forward over last non-space
  1967.     inc    di            ; ditto for address
  1968. dmp3a:    mov    word ptr [di+1],0A0Dh    ; append cr/lf
  1969.     add    cx,2            ; line count + cr/lf
  1970.     mov    dx,offset dumpbuf    ; array to be written
  1971.     mov    bx,dmphand        ; need file handle
  1972.     mov    ah,write2        ; write the line
  1973.     int    dos
  1974.     pop    cx            ; get line counter again
  1975.     loop    dmp2            ; do next line (needs si preset)
  1976.     mov    dx,offset dumpsep    ; put in formfeed/cr/lf
  1977.     mov    cx,3            ; three bytes overall
  1978.     mov    ah,write2
  1979.     mov    bx,dmphand
  1980.     int    dos
  1981.     mov    ah,close2        ; close the file now
  1982.     int    dos
  1983.     pop    si
  1984.     pop    di
  1985.     pop    dx
  1986.     pop    cx
  1987.     pop    bx
  1988.     pop    ax
  1989.     clc
  1990.     ret
  1991. dumpscr endp
  1992.  
  1993. ; Send a character to the host, handle local echo
  1994. sndhst    proc    near
  1995.     push    ax           ; save the character
  1996.     mov    ah,al
  1997.     call    outchr           ; send char in ah out the serial port
  1998.     pop    ax
  1999.     test    ourarg.flgs,lclecho ; echoing?
  2000.     jz    sndhs2             ; z = no, exit
  2001.     call    outtty           ; echo to screen
  2002. sndhs2: ret
  2003. sndhst    endp
  2004.  
  2005.  
  2006. ; print a message to the screen.  Returns normally.
  2007. ; also puts the terminal into vt100 mode so our escape sequences work...
  2008. tmsg    proc    near
  2009.     push    es
  2010.     push    bx
  2011.     mov    bx,nvmseg
  2012.     mov    es,bx        ; address firmware
  2013.     mov    bl,0f1h        ; turn on vt100 mode
  2014.     xchg    bl,es:[vt52mod] ; remember old mode
  2015.     mov    ah,prstr
  2016.     int    dos
  2017.     mov    es:[vt52mod],bl ; restore mode
  2018.     pop    bx
  2019.     pop    es
  2020.     ret
  2021. tmsg    endp
  2022.  
  2023. ; save the screen for later
  2024. savscr    proc    near
  2025.     push    es
  2026.     push    ds
  2027.     call    kilcur        ; turn off cursor
  2028.     mov    di,ourscr    ; place to save screen
  2029.     mov    dx,ourattr    ; and to save attributes
  2030.     mov    ax,ds
  2031.     mov    es,ax        ; save buffer is in data space (ds seg)
  2032.     mov    cx,slen        ; # of lines to do
  2033.     mov    ax,scrseg
  2034.     mov    ds,ax
  2035.     mov    bx,0        ; current line #
  2036. savsc1: push    cx        ; save current count
  2037.     mov    si,ds:[latofs+bx] ; get line ptr
  2038.     and    si,0fffh    ; ptr is in 12 bits
  2039.     push    si        ; save pointer
  2040.     mov    cx,swidth/2    ; # of words/line, [RHW-5] swidth always even
  2041.     cld
  2042.     rep    movsw        ; [RHW-4] copy it out by words
  2043.     pop    si        ; restore pointer
  2044.     add    si,attoffs    ; this is where attributes start
  2045.     xchg    dx,di        ; this holds attribute ptr
  2046.     mov    cx,swidth/2    ; # of words of attrs to move, [RHW-5]
  2047.     rep    movsw        ;  [RHW-4] copy words at a time (quicker)
  2048.     xchg    dx,di
  2049.     pop    cx        ; restore counter
  2050.     add    bx,2        ; increment line ptr
  2051.     loop    savsc1        ; save all lines and attributes
  2052.     pop    ds
  2053.     call    rstcur        ; put cursor back
  2054.     call    savpos        ; might as well save cursor pos
  2055.     pop    es
  2056.     ret
  2057. savscr    endp
  2058.  
  2059. ; restore the screen saved by savscr
  2060. rstscr    proc    near
  2061.     call    cmblnk        ; start by clearing screen
  2062.     mov    si,ourscr    ; point to saved screen
  2063.     mov    dx,ourattr    ; and attributes
  2064.     mov    cx,slen        ; # of lines/screen
  2065.     mov    bx,101H        ; start at top left corner
  2066. rstsc1: push    bx
  2067.     push    cx
  2068.     push    si        ; save ptrs
  2069.     push    dx
  2070.     mov    ax,si        ; this is source
  2071.     call    prlina        ; print the line
  2072.     pop    dx
  2073.     pop    si
  2074.     pop    cx
  2075.     pop    bx
  2076.     add    si,swidth    ; point to next line
  2077.     add    dx,swidth    ; and next attributes
  2078.     inc    bx        ; address next line
  2079.     loop    rstsc1        ; keep restore lines
  2080.     call    rstpos        ; don't forget position
  2081.     ret
  2082. rstscr    endp
  2083.  
  2084. ; Put a line into the circular buffer.    Pass the buffer structure in bx.
  2085. ; Source is srcseg:si
  2086. ; Rewritten by [jrd]
  2087. putcirc proc    near
  2088.     push    es
  2089.     push    di
  2090.     push    cx
  2091.     mov    cl,swidth        ; number of columns
  2092.     xor    ch,ch
  2093.     mov    es,[bx].orig        ; get segment of memory area
  2094.     cmp    bx,offset bwnd        ; bottom buffer?
  2095.     je    putci6            ; e = yes
  2096.     mov    di,twnd.pp        ; pick up buffer ptr (offset from es)
  2097.     add    di,cx            ; increment to next available slot
  2098.     add    di,cx            ; char and attribute
  2099.     cmp    di,twnd.bend        ; would line extend beyond buffer?
  2100.     jb    putci1            ; b = not beyond end
  2101.     mov    di,0            ; else start at the beginning
  2102. putci1: mov    twnd.pp,di        ; update ptr
  2103.     cld                ; set direction to forward
  2104.     mov    cx,swidth
  2105.     push    ds            ; save regular data seg reg
  2106.     mov    ds,srcseg        ; use source segment for ds:si
  2107.     rep    movsw            ; copy into buffer
  2108.     pop    ds            ; restore regular data segment
  2109.     mov    cx,twnd.lmax        ; line capacity of buffer
  2110.     dec    cx            ; minus one work space line
  2111.     cmp    twnd.lcnt,cx        ; can we increment line count?
  2112.     jae    putci1b            ; ae = no, keep going
  2113.     inc    twnd.lcnt        ; else count this line
  2114. putci1b:cmp    bwnd.lcnt,0        ; any lines in bottom buffer?
  2115.     je    putci2            ; e = no
  2116.     mov    cx,bwnd.pp        ; see if we overlap bot buf
  2117.     cmp    cx,twnd.pp        ; is this line in bot buf area?
  2118.     jne    putci2            ; ne = no
  2119.     add    cl,swidth        ; move bottom pointer one slot earlier
  2120.     adc    ch,0
  2121.     add    cl,swidth        ; words
  2122.     adc    ch,0
  2123.     cmp    cx,bwnd.bend        ; beyond end of buffer?
  2124.     jb    putci1a            ; b = no
  2125.     mov    cx,0            ; yes, start at beginning of buffer
  2126. putci1a:mov    bwnd.pp,cx        ; new bottom pointer
  2127.     dec    bwnd.lcnt        ; one less line in bottom buffer
  2128. putci2: pop    cx
  2129.     pop    di
  2130.     pop    es
  2131.     ret
  2132. putci6:                    ; bottom buffer
  2133.     add    cx,cx            ; words worth
  2134.     cmp    bwnd.lcnt,0        ; any lines in the buffer yet?
  2135.     jne    putci7            ; ne = yes
  2136.     mov    di,twnd.pp        ; get latest used slot of top buff
  2137.     add    di,cx            ; where first free (?) slot starts
  2138.     cmp    di,bwnd.bend        ; are we now beyond the buffer?
  2139.     jb    putci6a            ; b = no
  2140.     mov    di,0            ; yes, start at beginning of buffer
  2141. putci6a:add    di,cx            ; start of second free (?) slot
  2142.     cmp    di,bwnd.bend        ; are we now beyond the buffer?
  2143.     jb    putci6b            ; b = no
  2144.     mov    di,0            ; yes, start at beginning of buffer
  2145. putci6b:mov    cx,twnd.lmax        ; buffer line capacity
  2146.     sub    cx,twnd.lcnt        ; minus number used by top buffer
  2147.     sub    cx,2            ; minus one work slot and one we need
  2148.     cmp    cx,0            ; overused some slots?
  2149.     jge    putci8            ; ge = enough to share
  2150.     add    twnd.lcnt,cx        ; steal these from top window beginning
  2151.     jmp    short putci8
  2152.  
  2153. putci7: mov    es,bwnd.orig        ; get segment of memory area
  2154.     mov    di,bwnd.pp        ; pick up buffer ptr (offset from es)
  2155.     cmp    di,0            ; would line start before buffer?
  2156.     jne    putci7a            ; ne = after start of buffer
  2157.     mov    di,bwnd.bend        ; else start at the end minus one slot
  2158.     inc    di
  2159. putci7a:sub    di,cx
  2160. putci8: mov    bwnd.pp,di        ; update ptr (this is latest used slot)
  2161.     mov    cl,swidth
  2162.     xor    ch,ch
  2163.     cld                ; set direction to forward
  2164.     push    ds            ; save regular data seg reg
  2165.     mov    ds,srcseg        ; use source segment for ds:si
  2166.     rep    movsw            ; copy into buffer
  2167.     pop    ds            ; restore regular data segment
  2168.     mov    cx,bwnd.lmax        ; line capacity of buffer
  2169.     cmp    bwnd.lcnt,cx        ; can we increment line count?
  2170.     jae    putci8b            ; ae = no, keep going
  2171.     inc    bwnd.lcnt        ; else count this line
  2172. putci8b:cmp    twnd.lcnt,0        ; any lines in top line buf?
  2173.     je    putci9            ; e = no
  2174.     mov    cx,twnd.pp        ; yes, see if we used last top line
  2175.     cmp    cx,bwnd.pp        ; where we just wrote
  2176.     jne    putci9            ; not same place, so all is well
  2177.     dec    twnd.lcnt        ; one less line in top window
  2178.     cmp    cx,0            ; currently at start of buffer?
  2179.     jne    putci8a            ; ne = no
  2180.     mov    cx,twnd.bend        ; yes
  2181.     inc    cx
  2182. putci8a:sub    cl,swidth        ; back up top window
  2183.     sbb    ch,0
  2184.     sub    cl,swidth        ; by one line
  2185.     sbb    ch,0
  2186.     mov    twnd.pp,cx        ; next place to read
  2187. putci9: pop    cx
  2188.     pop    di
  2189.     pop    es
  2190.     ret
  2191.  
  2192. putcirc endp
  2193.  
  2194. ; Get a line from the circular buffer, removing it from the buffer.
  2195. ; returns with carry on if the buffer is empty.
  2196. ; Pass the buffer structure in bx.
  2197. ; Destination preset in es:di.
  2198. ; Rewritten by [jrd]
  2199. getcirc proc    near
  2200.     cmp    [bx].lcnt,0        ; any lines in buffer?
  2201.     jne    getci1            ; ne = yes, ok to take one out
  2202.     stc                ; else set carry
  2203.     ret                ; and return
  2204. getci1: push    cx            ; top and bottom window common code
  2205.     push    si
  2206.     mov    cl,swidth        ; # of chars to copy
  2207.     xor    ch,ch
  2208.     push    di            ; save destintion offset
  2209.     push    cx            ; save around calls
  2210.     mov    si,[bx].pp        ; this is source
  2211.     cld                ; set direction to forward
  2212.     push    ds            ; save original ds
  2213.     mov    ds,[bx].orig        ; use seg address of buffer for si
  2214.     rep    movsw
  2215.     pop    ds            ; recover original data segment
  2216.     pop    cx            ;
  2217.     pop    di            ; recover destination offset
  2218.  
  2219.     push    cx            ; save again
  2220.     mov    si,[bx].pp        ; get ptr again
  2221.     pop    cx
  2222.     add    cx,cx            ; words
  2223.     cmp    bx,offset bwnd        ; bottom window?
  2224.     je    getci6            ; e = yes
  2225.     sub    si,cx            ; top window, move back
  2226.     jnc    getcir2            ; nc = still in buffer, continue
  2227.     mov    si,twnd.bend        ; else use end of buffer
  2228.     sub    si,cx            ; minus length of a piece
  2229.     inc    si
  2230. getcir2:mov    twnd.pp,si        ; update ptr
  2231.     dec    twnd.lcnt        ; decrement # of lines in buffer
  2232.     pop    si
  2233.     pop    cx
  2234.     clc                ; make sure no carry
  2235.     ret
  2236. getci6:                    ; bottom window
  2237.     add    si,cx            ; words, move back (bot buf = reverse)
  2238.     cmp    si,bwnd.bend        ; still in buffer?
  2239.     jb    getci7            ; b = yes
  2240.     mov    si,0            ; else use beginning of buffer
  2241. getci7: mov    bwnd.pp,si        ; update ptr
  2242.     dec    bwnd.lcnt        ; decrement # of lines in buffer
  2243.     pop    si
  2244.     pop    cx
  2245.     clc                ; make sure no carry
  2246.     ret
  2247. getcirc endp
  2248.  
  2249. ; prepares for scrolling by saving the top line in topbuf.
  2250. scrprep proc    near
  2251.     push    ax        ; save regs
  2252.     push    es
  2253.     cmp    al,cr        ; carriage return?
  2254.     je    scrpr3        ; yes, will never change line
  2255.     cmp    al,lf        ; outputting a linefeed?
  2256.     je    scrpr2        ; yes, will change line
  2257.     mov    ax,scrseg
  2258.     mov    es,ax        ; address screen segment
  2259.     test    es:byte ptr [curlin],wrpend ; wrap pending?
  2260.     jz    scrpr3        ; no, forget it
  2261.     mov    ax,nvmseg
  2262.     mov    es,ax
  2263.     test    es:byte ptr [autwrp],1 ; auto-wrap mode?
  2264.     jz    scrpr3        ; no, forget this
  2265.                 ; about to change lines, see if bottom line
  2266. scrpr2: mov    ax,scrseg
  2267.     mov    es,ax
  2268.     cmp    es:byte ptr [csrlin],slen ; are we at the bottom?
  2269.     je    scrpr4        ; yes, have to save line
  2270. scrpr3: pop    es        ; get here if not saving line
  2271.     pop    ax
  2272.     ret
  2273. scrpr4: pop    es        ; restore registers
  2274.     pop    ax
  2275. ; alternate entry that doesn't check if we're on the bottom row.
  2276. savtop: push    ax        ; save ax
  2277.     push    bx
  2278.     push    cx
  2279.     push    si
  2280.     push    di
  2281.     call    kilcur        ; kill cursor
  2282.     push    es
  2283.     push    ds
  2284.     mov    ax,ds
  2285.     mov    es,ax
  2286.     mov    ax,scrseg
  2287.     mov    ds,ax        ; address screen segment
  2288.     mov    si,ds:word ptr [l1ptr] ; get ptr to top line
  2289.     and    si,0fffh    ; only 12 bits are significant
  2290.     push    si
  2291.     mov    di,offset topline ; this is where it goes
  2292.     mov    cx,swidth/2    ; # of words to copy,     [RHW-5]
  2293.     cld
  2294.     rep    movsw        ; [RHW-4] get the top line
  2295.     pop    si        ; restore pointer
  2296.     add    si,attoffs    ; add offset of attributes
  2297.     mov    cx,swidth/2    ; [RHW-5] # words to copy (swidth even)
  2298.     rep    movsw        ; [RHW-4] get the top line's attributes
  2299.     pop    ds
  2300.     pop    es        ; restore segments
  2301.     mov    srcseg,seg topline ; set segment of source
  2302.     mov    si,offset topline  ; set offset of source
  2303.     mov    bx,offset twnd    ; buffer structure pointer
  2304.     call    putcirc        ; put into circular buffer
  2305.     call    rstcur
  2306.     pop    di
  2307.     pop    si
  2308.     pop    cx
  2309.     pop    bx
  2310.     pop    ax        ; restore character in ax
  2311.     ret            ; and return
  2312. scrprep endp
  2313.  
  2314.  
  2315. ; get the screen's bottom line into the buffer in ax.
  2316. getbot    proc    near
  2317.     push    cx
  2318.     push    si
  2319.     push    di
  2320.     push    es
  2321.     push    ds
  2322.     push    ax        ; save destination on the stack
  2323.     call    kilcur        ; kill cursor
  2324.     push    ds
  2325.     pop    es
  2326.     mov    si,scrseg
  2327.     mov    ds,si
  2328.     mov    si,ds:word ptr [llptr] ; get ptr to bottom line
  2329.     and    si,0fffh    ; only 12 bits are pointer
  2330.     pop    di        ; destination is on stack
  2331.     push    si        ; preserve pointer
  2332.     mov    cx,swidth/2    ; # of words to copy         [RHW-5]
  2333.     cld
  2334.     rep    movsw        ; [RHW-4] get the top line
  2335.     pop    si        ; get pointer back
  2336.     add    si,attoffs    ; this is where attributes are
  2337.     mov    cx,swidth/2    ;  [RHW-5] # words to copy
  2338.     rep    movsw        ;  [RHW-4] get the top line
  2339.     pop    ds        ; restore segments
  2340.     pop    es
  2341.     call    rstcur        ; restore cursor
  2342.     pop    di
  2343.     pop    si
  2344.     pop    cx
  2345.     ret
  2346. getbot    endp
  2347.  
  2348. ; handle the previous screen button...
  2349.  
  2350. prvscr    proc    near
  2351.     mov    cx,slen
  2352.     cmp    twnd.lcnt,cx
  2353.     jge    prvs1
  2354.     mov    cx,twnd.lcnt
  2355. prvs1:    jcxz    prvs2
  2356.     call    prvlin
  2357.     loop    prvs1
  2358. prvs2:    clc
  2359.     ret
  2360. prvscr    endp
  2361.  
  2362. ; handle the next screen button...
  2363.  
  2364. nxtscr    proc    near
  2365.     mov    cx,slen
  2366.     cmp    bwnd.lcnt,cx
  2367.     jge    nxts1
  2368.     mov    cx,bwnd.lcnt
  2369. nxts1:    jcxz    nxts2
  2370.     call    nxtlin
  2371.     loop    nxts1
  2372. nxts2:    clc
  2373.     ret
  2374. nxtscr    endp
  2375.  
  2376. ; save a screen by rolling them into a circular buffer.
  2377. ; enter with ax/ circular buffer ptr, bx/ first line to get
  2378. ; dx/ increment
  2379.  
  2380. rolscr    proc    near
  2381.     mov    cx,slen        ; # of lines to save
  2382.     cmp    cx,[bx].lcnt    ; enough space left in this buffer?
  2383.     jbe    rolsc0        ; be = enough
  2384.     mov    cx,[bx].lcnt    ; use only as many as we have
  2385.     jcxz    rolscx        ; z = none, so quit here
  2386. rolsc0: shl    dx,1        ; double increment for word ptr
  2387.     dec    bx        ; ptr starts at 0
  2388.     shl    bx,1        ; convert to word ptr
  2389.     push    es
  2390.     push    ds
  2391.     pop    es        ; set es to data segment
  2392.     mov    temp,0        ; save number of lines done
  2393.  
  2394. rolsc1: push    cx
  2395.     push    dx
  2396.     push    bx
  2397.     push    ax
  2398.     push    ds
  2399.     call    kilcur        ; kill cursor
  2400.     mov    di,offset rlbuf
  2401.     mov    ax,scrseg
  2402.     mov    ds,ax        ; address screen
  2403.     mov    si,ds:[latofs+bx] ; get current line
  2404.     and    si,0fffh    ; ptr is in 12 bits
  2405.     push    si        ; save pointer
  2406.     mov    cx,swidth/2    ; # of words to move,         [RHW-5]
  2407.     rep    movsw        ; [RHW-4] get the line
  2408.     pop    si        ; restore pointer
  2409.     add    si,attoffs    ; where attributes start
  2410.     mov    cx,swidth/2    ; # of bytes to move,         [RHW-5]
  2411.     rep    movsw        ; [RHW-4] move attributes as well
  2412.     pop    ds        ; restore segment
  2413.     call    rstcur        ; restore cursor
  2414.     pop    bx        ; this is desired circ buffer ptr
  2415.     mov    srcseg,seg rlbuf ; segment of source
  2416.     mov    si,offset rlbuf ; offset of source
  2417.     call    putcirc        ; save in circular buffer
  2418.     mov    ax,bx        ; put buffer ptr back where it belongs
  2419.     pop    bx        ; get line pos back
  2420.     pop    dx        ; and increment
  2421.     pop    cx        ; don't forget counter
  2422.     add    bx,dx        ; move to next line
  2423.     inc    temp
  2424.     loop    rolsc1        ; loop thru all lines
  2425.     pop    es
  2426. rolscx: ret            ; and return
  2427. rolscr    endp
  2428.  
  2429. ; move screen down a line, get one previous line back
  2430.  
  2431. prvlin    proc    near        ; get the previous line back
  2432.     push    ax
  2433.     push    bx
  2434.     push    dx
  2435.     cmp    twnd.lcnt,0    ; any lines in top window?
  2436.     je    prvli1        ; e = no, ignore request
  2437.     mov    ax,offset botline ; place for bottom line
  2438.     call    getbot        ; fetch bottom line
  2439.     mov    srcseg,seg botline ; segement of source
  2440.     mov    si,offset botline  ; offset of source
  2441.     mov    bx,offset bwnd    ; buffer structure pointer
  2442.     call    putcirc        ; save in circular buffer
  2443.     mov    bx,offset twnd    ; source structure
  2444.     push    es
  2445.     mov    di,seg topline
  2446.     mov    es,di
  2447.     mov    di,offset topline ; es:di is address of destination
  2448.     call    getcirc        ; try to get a line
  2449.     pop    es
  2450.     jc    prvli1        ; no more, just return
  2451.     call    savpos        ; save cursor position
  2452.     call    kilcur        ; turn off cursor
  2453.     mov    dx,offset topdwn ; home, then reverse index
  2454.     call    tmsg
  2455.     mov    ax,offset topline ; point to data
  2456.     mov    bx,0101H    ; print line at top of screen
  2457.     mov    dx,ax
  2458.     add    dx,swidth
  2459.     call    prlina        ; print the line
  2460.     call    rstcur
  2461.     call    rstpos        ; restore cursor position
  2462. prvli1: pop    dx
  2463.     pop    bx
  2464.     pop    ax
  2465.     clc
  2466.     ret            ; and return
  2467. prvlin    endp
  2468.  
  2469. ; move screen up a line, get one bottom line back
  2470. nxtlin    proc    near
  2471.     push    ax
  2472.     push    bx
  2473.     push    dx
  2474.     cmp    bwnd.lcnt,0    ; any lines in bottom window?
  2475.     je    nxtli1        ; e = no
  2476.     mov    bx,offset bwnd    ; source structure
  2477.     push    es
  2478.     mov    di,seg botline
  2479.     mov    es,di
  2480.     mov    di,offset botline ; es:di is address of destination
  2481.     call    getcirc        ; try to get a line
  2482.     pop    es
  2483.     jc    nxtli1        ; no more, just return
  2484.     call    savtop        ; save one line off of top
  2485.     call    savpos        ; save cursor position
  2486.     call    kilcur        ; turn off cursor
  2487.     mov    dx,offset botup ; go to bottom, then scroll up a line
  2488.     call    tmsg
  2489.     mov    ax,offset botline ; point to data
  2490.     mov    bx,0100H + slen ; print at bottom line
  2491.     mov    dx,ax
  2492.     add    dx,swidth
  2493.     call    prlina        ; print the line
  2494.     call    rstcur        ; turn cursor back on
  2495.     call    rstpos        ; restore cursor position
  2496. nxtli1: pop    dx
  2497.     pop    bx
  2498.     pop    ax
  2499.     clc
  2500.     ret
  2501. nxtlin    endp
  2502.  
  2503. ; move screen up until no more saved in bottom buffer [jrd]
  2504. nxtbot    proc    near
  2505.     push    cx
  2506.     mov    cx,bwnd.lcnt    ; number of pages of scroll back memory
  2507. nxtbot1:push    cx
  2508.     call    nxtlin
  2509.     pop    cx
  2510.     loop    nxtbot1        ; do all pages
  2511.     pop    cx
  2512.     clc
  2513.     ret
  2514. nxtbot    endp
  2515.  
  2516. nxttop    proc    near        ; move to top of screen buffer memory [jrd]
  2517.     push    cx
  2518.     mov    cx,twnd.lcnt    ; number of pages of scroll back memory
  2519. nxttop1:push    cx
  2520.     call    prvlin
  2521.     pop    cx
  2522.     loop    nxttop1        ; do all pages
  2523.     pop    cx
  2524.     clc
  2525.     ret
  2526. nxttop    endp
  2527.  
  2528. ; save cursor position
  2529. savpos    proc    near
  2530.     push    di
  2531.     mov    dx,offset curinq ; where is the cursor?
  2532.     call    tmsg
  2533.     mov    posbuf,escape    ; put an escape in the buffer first
  2534.     mov    di,offset posbuf+1
  2535. savpo1: mov    ah,8        ; read, no echo
  2536.     int    dos
  2537.     cld
  2538.     cmp    al,'R'        ; end of report?
  2539.     je    savpo2        ; yes
  2540.     stosb            ; no, save it
  2541.     jmp    short savpo1    ; and go on
  2542. savpo2: mov    al,'H'        ; this ends the sequence when we send it
  2543.     stosb
  2544.     mov    byte ptr [di],'$' ; need this to print it later
  2545.     pop    di
  2546.     ret
  2547. savpos    endp
  2548.  
  2549. ; restore the position saved by savpos
  2550. rstpos    proc    near
  2551.     mov    dx,offset posbuf
  2552.     call    tmsg        ; just print this
  2553.     ret
  2554. rstpos    endp
  2555.  
  2556. ; kill cursor so it doesn't get saved along with real data
  2557. kilcur    proc    near
  2558.     push    ax
  2559.     push    bx
  2560.     push    cx
  2561.     push    dx
  2562.     push    si
  2563.     push    es
  2564.     push    di
  2565.     mov    di,kcurfn
  2566.     int    firmwr
  2567.     pop    di
  2568.     pop    es
  2569.     pop    si
  2570.     pop    dx
  2571.     pop    cx
  2572.     pop    bx
  2573.     pop    ax
  2574.     ret
  2575. kilcur    endp
  2576.  
  2577. ; restore the cursor
  2578. rstcur    proc    near
  2579.     push    ax
  2580.     push    bx
  2581.     push    cx
  2582.     push    dx
  2583.     push    si
  2584.     push    es
  2585.     push    di
  2586.     mov    di,rcurfn
  2587.     int    firmwr
  2588.     pop    di
  2589.     pop    es
  2590.     pop    si
  2591.     pop    dx
  2592.     pop    cx
  2593.     pop    bx
  2594.     pop    ax
  2595.     ret
  2596. rstcur    endp
  2597.  
  2598. ; print a ff-terminated line at most swidth long...  Pass the line in ax.
  2599. ; cursor position should be in bx.
  2600. ; prlina writes attributes as well, which should be passed in dx.
  2601. prlin    proc    near
  2602.     mov    bp,2        ; print characters only
  2603.     jmp    short prli1
  2604. prlina: xor    bp,bp        ; 0 means print attributes as well
  2605. prli1:    push    es        ; this trashes es!!!
  2606.     push    ax        ; save regs
  2607.     push    cx
  2608.     push    es
  2609.     mov    cx,scrseg
  2610.     mov    es,cx        ; address screen seg for a moment
  2611.     mov    cl,es:byte ptr [rmargin] ; get max line length
  2612.     mov    ch,0
  2613.     pop    es        ; address user's segment again
  2614.     push    cx        ; remember original length
  2615.     mov    si,ax        ; better place for ptr
  2616.     mov    di,ax        ; need it here for scan
  2617.     mov    al,0ffh        ; this marks the end of the line
  2618.     cld
  2619.     repne    scasb        ; look for the end
  2620.     jne    prli2        ; not found
  2621.     inc    cx        ; account for pre-decrement
  2622. prli2:    neg    cx
  2623.     pop    ax        ; get original length back
  2624.     add    cx,ax
  2625. ;    add    cx,swidth    ; figure out length of line
  2626.     jcxz    prli3        ; 0-length line, skip it
  2627.     mov    ax,bp        ; writing characters
  2628.     mov    bp,ds        ; wants segment here
  2629.     push    bx
  2630.     push    dx
  2631.     push    si
  2632.     push    di
  2633.     mov    di,14H        ; fast write to screen
  2634.     int    firmwr
  2635.     pop    di
  2636.     pop    si
  2637.     pop    dx
  2638.     pop    bx
  2639. prli3:    pop    cx        ; restore registers
  2640.     pop    ax
  2641.     pop    es
  2642.     ret
  2643. prlin    endp
  2644.  
  2645. ; action routines for keyboard translator.
  2646. ; These are invoked by a jump instruction. Return carry clear for normal
  2647. ; processing, return carry set for invoking Quit (kbdflg has transfer char).
  2648.  
  2649. uparrw: mov    al,'A'            ; cursor keys
  2650.     jmp    short comarr
  2651. dnarrw: mov    al,'B'
  2652.     jmp    short comarr
  2653. rtarr:    mov    al,'C'
  2654.     jmp    short comarr
  2655. lfarr:    mov    al,'D'
  2656. comarr: push    ax            ; save final char
  2657.     mov    al,escape        ; Output an escape
  2658.     call    sndhst            ; Output, echo permitted
  2659.     push    es            ; save seg register
  2660.     mov    ax,nvmseg        ; fetch address of nvm
  2661.     mov    es,ax            ; put in segment reg
  2662.     test    byte ptr es:[vt52mod],1 ; check bit zero
  2663.     pop    es            ; restore the seg register
  2664.     jnz    comar1            ; nz = ansi mode
  2665.     jmp    comar3            ; VT52 mode
  2666. comar1: mov    al,'['            ; Maybe this next?
  2667.     cmp    ckeyflg,0        ; applications cursor mode?
  2668.     je    comar2            ; e = no
  2669.     mov    al,'O'            ; applications mode
  2670. comar2: call    sndhst            ; Output it (echo permitted)
  2671. comar3: pop    ax            ; recover final char
  2672.     call    sndhst            ; Output to port (echo permitted)
  2673.     clc
  2674.     ret
  2675.  
  2676. pf1:    mov    al,'P'            ; keypad function keys
  2677.     jmp    short compf
  2678. pf2:    mov    al,'Q'
  2679.     jmp    short compf
  2680. pf3:    mov    al,'R'
  2681.     jmp    short compf
  2682. pf4:    mov    al,'S'
  2683. compf:    push    ax            ; save final char
  2684.     mov    al,escape        ; Output an escape
  2685.     call    prtbout
  2686.     push    es            ; save seg register
  2687.     mov    ax,nvmseg        ; fetch address of nvm
  2688.     mov    es,ax            ; put in segment reg
  2689.     test    byte ptr es:[vt52mod],1      ; check bit zero
  2690.     pop    es            ; restore the seg register
  2691.     jz    compf1            ; z = VT52 mode
  2692.     mov    al,'O'            ; send an "O" in ansi mode
  2693.     call    prtbout            ; Output it
  2694. compf1: pop    ax            ; Get the saved char back
  2695.     call    prtbout            ; Output to port
  2696.     clc
  2697.     ret
  2698.  
  2699. kp0:    mov    al,'p'            ; keypad numeric keys
  2700.     jmp    short comkp
  2701. kp1:    mov    al,'q'
  2702.     jmp    short comkp
  2703. kp2:    mov    al,'r'
  2704.     jmp    short comkp
  2705. kp3:    mov    al,'s'
  2706.     jmp    short comkp
  2707. kp4:    mov    al,'t'
  2708.     jmp    short comkp
  2709. kp5:    mov    al,'u'
  2710.     jmp    short comkp
  2711. kp6:    mov    al,'v'
  2712.     jmp    short comkp
  2713. kp7:    mov    al,'w'
  2714.     jmp    short comkp
  2715. kp8:    mov    al,'x'
  2716.     jmp    short comkp
  2717. kp9:    mov    al,'y'
  2718.     jmp    short comkp
  2719. kpminus:mov    al,'m'
  2720.     jmp    short comkp
  2721. kpcoma: mov    al,'l'
  2722.     jmp    short comkp
  2723. kpenter:mov    al,'M'
  2724.     jmp    short comkp
  2725. kpdot:    mov    al,'n'
  2726. comkp:    cmp    akeyflg,0        ; alternate keypad mode?
  2727.     jne    comkp1            ; ne = yes
  2728.     sub    al,'p'-'0'        ; change to numeric codes
  2729.     jmp    comkp3            ; and send just the ascii char
  2730. comkp1: push    ax            ; save final char
  2731.     mov    al,escape        ; Output an escape
  2732.     call    prtbout
  2733.     mov    al,3fh            ; Output the "?" in VT52 mode
  2734.     push    es            ; save seg register
  2735.     mov    cx,nvmseg        ; fetch address of nvm
  2736.     mov    es,cx            ; put in segment reg
  2737.     test    byte ptr es:[vt52mod],1      ; check bit zero
  2738.     pop    es            ; restore the seg register
  2739.     jz    comkp2            ; z = VT52 mode
  2740.     mov    al,'O'            ; Output the "O" in ansi mode
  2741. comkp2: call    prtbout
  2742.     pop    ax            ; recover final char
  2743. comkp3: call    prtbout            ; send it
  2744.     clc
  2745.     ret
  2746.  
  2747. snull    proc    near            ; send a null byte
  2748.     mov    al,0            ; the null
  2749.     call    prtbout            ; send without logging and local echo
  2750.     clc
  2751.     ret
  2752. snull    endp
  2753.  
  2754. chrout: push    es            ; save segment
  2755.     push    bx
  2756.     mov    bx,nvmseg        ; point to nvm
  2757.     mov    es,bx            ; set the segment
  2758.     test    byte ptr es:[newlmod],1 ; check if we are set to new line
  2759.     pop    bx
  2760.     pop    es            ; restore the segment register
  2761.     jz    chrout1            ; just send the cr if bit is off
  2762.     call    sndhst            ; else send the carriage return first
  2763.     mov    al,lf            ; then the line-feed
  2764. chrout1:call    sndhst            ; send char in al to serial port
  2765.     clc                ; for keyboard translator
  2766.     ret                ; can echo and log
  2767.  
  2768.  
  2769. prtbout:mov    ah,al            ; output char with no echo
  2770.     call    outchr            ; outchr works with ah
  2771.     ret
  2772.  
  2773. cdos:    mov    al,'P'            ; Connect mode help screen items
  2774.     jmp    short cmdcom
  2775. cstatus:mov    al,'S'            ; these commands invoke Quit
  2776.     jmp    short cmdcom
  2777. cquit:    mov    al,'C'            ; C = exit connection
  2778.     jmp    short cmdcom
  2779. cquery: mov    al,'?'            ; help
  2780.     jmp    short cmdcom
  2781. chang:    mov    al,'H'            ; Hangup, drop DTR & RTS
  2782.     jmp    short cmdcom
  2783. cmdcom: mov    kbdflg,al        ; pass char to msster.asm via kbdflg
  2784.     stc                ; signal that Quit is needed
  2785.     ret
  2786.  
  2787. klogon    proc    near            ; resume logging (if any)
  2788.     test    flags.capflg,logses    ; session logging enabled?
  2789.     jz    klogn            ; z = no, forget it
  2790.     or    ourarg.flgs,capt    ; turn on capture flag
  2791.     or    argadr.flgs,capt    ; permanent argument array too
  2792. klogn:    clc
  2793.     ret
  2794. klogon    endp
  2795.  
  2796. klogof    proc    near            ; suspend logging (if any)
  2797.     and    argadr.flgs,not capt    ; stop capturing
  2798.     and    ourarg.flgs,not capt    ; stop capturing
  2799. klogo:    clc
  2800.     ret
  2801. klogof    endp
  2802. code    ends
  2803.     end
  2804.  
  2805.