home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / extra / nyenhuis3.arc / MSZIBM.ASM < prev   
Assembly Source File  |  1990-01-16  |  182KB  |  5,314 lines

  1.     NAME    mszibm
  2. ; File MSZIBM.ASM
  3.     include mssdef.h
  4. ; Terminal emulator module for IBM PC's and compatibles. Emulates Heath-19,
  5. ; VT52, VT102, and VT320. Original version for VT100 done by James Harvey,
  6. ; Indiana Purdue Univ, for MS Kermit 2.27. Taken from there by Joe Doupnik,
  7. ; Utah State Univ for MS Kermit 2.29 et seq.
  8. ; Edit history
  9. ; Last edit 15 Jan 1990
  10. ; 29 May 1989 Rewrite and expand to DEC VT320 level. [jrd]
  11. ; 5 Oct 1988 Add controls to write from right to left, using bit vswdir in
  12. ;  the setup bytes vtemu.vtflgst and vtemu.vtflgop. The concept was invented
  13. ;  by Baruch Cochavy, IIT, Haifa, Israel; the current code is by [jrd].
  14. ;  If vswdir is non-zero writing is done starting on the visual right side.
  15. ;  Procedures direction and vtsclr accomdate most directional details. The
  16. ;  implementation here retains DX and CURSOR as logical values while the
  17. ;  physical screen coordinates are conditioned via proc direction and
  18. ;  several sections of special code. Screen printing is done full width if
  19. ;  writing right to left. Outside mszibm the logical cursor = physical. [jrd]
  20. ; 1 Jan 1988 version 2.30
  21. ;    [Joe R. Doupnik, Utah State Univ]
  22.  
  23.     public    anstty, ansini, ansrei, ansdsl, anskbi ; Entry points
  24.     public    ans52t, vsinit, tabset, tabclr, istabs
  25.     public    mar_top, mar_bot, anspflg, scroll, video_state ;  for msyibm
  26.     public    dnparam, dparam, dlparam, dninter, dinter, emubufc, emubuf
  27.     public    emubufl, dcsstrf, nrc2cp, cpdecsg
  28.  
  29. ; * Disclaimer *
  30. ;
  31. ; DEC and VT are trademarks of Digital Equipment Corporation.
  32. ;
  33. ; There is a naming convention
  34. ; for the ANSI and VT100 functions and flags; generally, the stuff in the
  35. ; symbol after "ans" or "at" is the function or mode mnemonic used in the
  36. ; VT100 manual.
  37. ; This was the first thing I ever wrote in 8088 assembler (some of it was
  38. ; stolen from MSYIBM), and one of the constraints was that the emulator
  39. ; should work with a vanilla PC with a monochrome monitor. Given these and
  40. ; other constraints, no attempt was made to implement the following VT100
  41. ; features: (1) Smooth scolling, (2) 132 column lines, (3) Auto repeat,
  42. ; (5) Interlace/no interlace, (6) Double-width/double-height lines. The
  43. ; escape sequences to set and reset these are recognized, but ignored.
  44. ;    - James A. Harvey, IUPUI Computing Services, DEC Systems Group
  45. ;
  46. ; * End of Disclamer *
  47. ; ---------------------------------------------------------------------------
  48. ;
  49. ; Description of the global entry points and calls on external routines
  50. ; needed by this emulator.                    [jrd]
  51. ;
  52. ; vsinit - start up routine called as Kermit initializes. Takes no arguments.
  53. ;       Sets up address pointers to tabs, reads default terminal parameters
  54. ;       reads current screen coloring. Examines and updates structure
  55. ;       "vtemu." which is how mssset communicates changed information
  56. ;       about many Set Term parameters; "flags." is a Kermit structure
  57. ;       carrying the other Set Term parameters.
  58. ; anstty - starting point for displaying a character, delivered in AL.
  59. ;       Returns when the display operation is completed and that may
  60. ;       take many many instructions. All normal "characters received by
  61. ;       the terminal" are provided by calling anstty with the char in AL.
  62. ; ansini - entry point to initialize the emulator. It requires information
  63. ;       from msy in four registers: the Kermit terminal routine flags
  64. ;       "yflags" (used mainly to sense debug mode and the mode line toggle)
  65. ;       "low_rgt" (bh = row, bl = column of the lower right display corner)
  66. ;       "lbaudtab" (index into baud rate table, for status reporting)
  67. ;       "lpartab" (index into parity table, for status reporting)
  68. ;       Ansini causes a full reset of the emulator, including screen 
  69. ;       clearing and a beep. Ansini is also called by msy in response to
  70. ;       sensing the Alt = key combination to fully reset the emulator.
  71. ; ansrei - entry point to reinitialize the emulator. Nearly the same as
  72. ;       ansini except operating flags, tabs, etc are retained from the
  73. ;       previous emulator session. Items which can be changed by Set Term
  74. ;       are examined and updated. The msy flags "yflags" are needed.
  75. ;       This is the warm-restart entry point used when connect mode
  76. ;       is reentered gracefully. The screen is cleared only if the coloring
  77. ;       has changed. The starting cursor location is whereever msy puts it.
  78. ; ansdsl - display "led" (status line) information. Invoked by msy when
  79. ;       the mode line is constructed so the emulator can write the 
  80. ;       terminal type and the VT100 led status lights when Connect mode
  81. ;       is started. Requires "yflags" from msy to sense whether the mode
  82. ;       line is to be shown.
  83. ; anskbi - a routine called by msy to notify the emulator that a character
  84. ;       is available from the keyboard. No character is read, just flag
  85. ;       ttkbi is set. This is actually used only to beep when the cursor
  86. ;       goes beyond column 72 and the margin bell flag is on.
  87. ; ans52t - called by msy to change terminal types "on the fly" without
  88. ;       fully updating all operating parameters and without losing setup
  89. ;       information. Msy senses the Alt minus key and calls ans52t with
  90. ;       no arguments. Ans52t cycles among terminal types.
  91. ; other modules in msy are called by this file to handle screen scrolling
  92. ;       mode line on/off, output to the serial port (reports), screen
  93. ;       particulars (location, cursor shape, blanking). The list is
  94. ;       the set of code extrn procedures below; all are in file msy.
  95. ;
  96. ; data exchange is directly with msy to assist in scrolling (varaibles
  97. ;       "mar_top", "mar_bot") and in sensing the non-connect
  98. ;       mode screen coloring ("scbattr"). Screen coloring controlled by
  99. ;       the emulator is not permitted to influence the non-connect mode
  100. ;       screens whereas the emulator attempts to use the regular Kermit
  101. ;       screen colors as defaults. The kind of terminal to emulate is
  102. ;       held in byte "flags.vtflg" which is set by Set Term and by this
  103. ;       module for global information within Kermit.
  104. ;
  105. ; Many things have been added or modified since James Harvey donated this
  106. ;       code to Columbia University for use in Kermit.              [jrd]
  107. ; Character sets in VT320 and VT102 modes:
  108. ;  ASCII ("B"/94)
  109. ;  ISO Latin-1 ("A"/96)
  110. ;  DEC UK-ASCII ("A"/94, available only in VT102 mode)
  111. ;  DEC Supplemental Graphics ("%5"/94),
  112. ;  DEC Technical Graphics (">"/94), an extension taken from the VT340,
  113. ;  DEC Special Graphics ("0"/94 and "2"/94)
  114. ;  ALT-ROM (Kermit specific, "1"/94/96)
  115. ;  DEC National Replacement Chars (all 12 sets)
  116. ;  Startup:
  117. ;   GL = G0 = G1 = ASCII (or ALT-ROM if selected by SET TERM CHAR ALT-ROM),
  118. ;   GR = G2 = G3 = ISO Latin-1.
  119. ;   When an NRC is selected by SET TERM CHAR <country> and enabled by
  120. ;   CSI ? 42 h the NRC table replaces G0..G3 at the time of selection. When
  121. ;   thus designated and selected incoming characters are forced to 7 bits and
  122. ;   8-bit Controls (outgoing) is turned off. No designation means no selection.
  123. ;  Selecting a character set with the wrong sized designator yields no action.
  124. ;
  125. ; References:
  126. ;  "PT200 Programmers Reference Guide", 1984, Prime Computer # DOC 8621-001P
  127. ;  "Video Terminal Model H19, Operation", 1979, Heath Company # 595-2284-05
  128. ;  "VT100 User's Guide", 2nd ed., Jan 1979, DEC # EK-VT100-UG
  129. ;  "Rainbow 100+/100B Terminal Emulation Manual", June 1984, DEC # QV069-GZ
  130. ;  "Installing and Using The VT320 Video Terminal", June 1987,
  131. ;    DEC # EK-VT320-UU-001
  132. ;  "VT320 Programmer Reference Manual", July 1987, DEC # EK-VT320-RM-001
  133. ; ---------------------------------------------------------------------------
  134.  
  135.  
  136. swidth  equ     132            ; assumed max screen width
  137. slen    equ    60            ; assumed max screen length 
  138. maxparam equ    10            ; number of ESC and DCS Parameters
  139. maxinter equ    10            ; number of ESC and DCS Intermediates
  140. gsize    equ    128            ; character set storage size
  141.                     ; anspflg bit field definitions:
  142. ; prtscr equ    1            ; used in msyibm print screen toggle
  143. vtautop    equ    1            ; autoprint enabled (1)
  144. vtcntp    equ    2            ; controller print enabled (1)
  145. vtextp    equ    4            ; printer extent set (1)
  146. vtffp    equ    10h            ; form feed wanted at end of print (1)
  147.  
  148. h19l25    equ    1            ; h19stat, line 25 enabled
  149. h19alf    equ    2            ; h19stat, auto cr/lf when cr seen
  150.                     ; display save-info for dspstate
  151. dsptype    equ    1            ; main (0) or status line (1) flag
  152. dspdecom equ    2            ; remembered origin mode (1=on)
  153.  
  154. ; DEC emulator status flags (bits in words vtemu.vtflgst and vtemu.vtflgop)
  155. ;anslnm  equ    1H            ; ANSI line feed/new line mode
  156. ;decawm  equ    2H            ; DEC autowrap mode
  157. ;decscnm equ    80H            ; DEC screen mode
  158. ;decckm  equ    200H            ; DEC cursor keys mode
  159. ;deckpam equ    400H            ; DEC keypad application mode
  160. ;decom   equ    800H            ; DEC origin mode
  161. ;deccol     equ    1000H            ; DEC column mode (0=80 col)
  162. ;decanm  equ    2000H            ; ANSI mode
  163. ;dececho equ    4000H            ; ANSI local echo on (1 = on)
  164.      
  165. ; Terminal SETUP mode flags (joint with bits above, some name dups)
  166. ;vsnewline    equ    1H        ; ANSI new line (0 = off)
  167. ;vswrap        equ    2H        ; Line wrap around (0 = no wrap)
  168. ;vsnrcm        equ    4H        ; National Rep Char set (0=none)
  169. ;vswdir        equ    8H        ; Writing direction (0=left, 1 right)
  170. ;vskeyclick    equ    10H        ; Keyclick (0 = off)
  171. ;vsmarginbell    equ    20H        ; Margin bell (0 = off)
  172. ;vscursor    equ    40H        ; Cursor (0 = block, 1 = underline)
  173. ;vsscreen    equ    80H        ; Screen (0 = normal, 1 = rev. video)
  174. ;vscntl        equ    100h        ; 8 or 7 bit controls (1 = 8-bit)
  175.  
  176. ;vsdefaults    equ    0+vscursor
  177.  
  178. ; Kinds of terminals available
  179. ;ttgenrc equ    0            ; Type 0: no emulation done by Kermit
  180. ;ttheath equ    1            ; Type 1: Heath-19
  181. ;ttvt52    equ    2            ; Type 2: VT52
  182. ;ttvt100 equ    3            ; Type 3: VT102
  183. ;ttvt320 equ    4            ; Type 4: VT320
  184. ;tttek    equ    5            ; Type 5: Tektronix 4010
  185. ;TTTYPES equ    6            ; Number of terminal types defined
  186.  
  187. ;emulst    struc        ; structure of vtemu.xxx for VTxxx emulator
  188. ;vtflgst dw    0    ; DEC setup flags (from SET)
  189. ;vtflgop dw    0    ; DEC runtime flags, like setup flags (here & STAT)
  190. ;vttbs    dw    0    ; pointer to default tab stops, for SET
  191. ;vttbst    dw    0    ; pointer to active tab stops, for STATUS
  192. ;vtchset db    1    ; value of default character set (1=US-ascii)
  193. ;att_ptr dw    0    ; pointer to normal & reverse video attributes
  194. ;emulst    ends
  195. ;;;;;;;;;;;;;;;;  end references ;;;;;;;;;;;;;;;;;;;;
  196.  
  197. data    segment public 'data'
  198.     extrn    vtemu:byte, scbattr:byte, flags:byte, yflags:byte
  199.     extrn    crt_lins:byte, crt_cols:byte, rxtable:byte, denyflg:word
  200.     extrn    tekflg:byte, vtclear:byte, dosnum:word, chcontrol:byte
  201.     extrn    parstate:word, pardone:word, parfail:word, nparam:word,
  202.     extrn    param:word, lparam:byte, ninter:word, inter:byte
  203.     extrn    L1cp437:byte, L1cp850:byte, L1cp860:byte, L1cp863:byte
  204.     extrn    L1cp865:byte
  205.  
  206.     even                    ; C0 7-bit control code table
  207. ansc0    dw    5 dup (atign)            ; NUL, SOH, STX, ETX, EOT
  208.     dw    atign,atign,vtbell,atbs,atht     ; ENQ, ACK, BEL, BS,  HT
  209.     dw    atlf, atlf, atff, atcr,atls1    ; LF,  VT,  FF,  CR,  SO
  210.     dw    atls0, 4 dup (atign)        ; SI,  DLE, DC1, DC2, DC3
  211.     dw    4 dup (atign), atcan        ; DC4, NAK, SYN, ETB, CAN
  212.     dw    atign, atcan,atesc,atign,atign    ; EM,  SUB, ESC, FS,  GS
  213.     dw    2 dup (atign)            ; RS,  US
  214.  
  215.                         ; C1 8-bit control code table
  216. ansc1    dw    4 dup (atign),atind        ; ignore 4, IND
  217.     dw    atnel,atign,atign,athts,atign    ; NEL, SSA, ESA, HTS, HTJ
  218.     dw    atign,atign,atign,atri, atign    ; VTS, PLD, PLU, RI,  SS2
  219.     dw    atign,atdcs,3 dup (atign)    ; SS3, DCS, PU1, PU2, STS
  220.     dw    5 dup (atign)            ; CCH, MW,  SPA, EPA, ignore
  221.     dw    atign,atign,atcsi,atgotst,atdcsnul; ignore 2, CSI, ST, OSC
  222.     dw    2 dup (atdcsnul)        ; PM,  APC
  223.  
  224. ; Heath-19 mode escape follower table
  225. h19esc    db    36            ; number of entries
  226.     dw    h19ejt            ; address of action routines
  227.     db    '<=>@A','BCDEF','GHIJK','LMNOY','Z[bjk','lnopq','rvwxy','z'
  228.  
  229. ; Dispatch table for Heath-19 escape sequence table h19esc
  230.     even
  231. h19ejt    dw    h19sans, atkpam,  atkpnm,  entins,  atcuu    ; '<=>@A'
  232.     dw    atcud,   atcuf,   atcub,   h19clrs, v52sgm    ; 'BCDEF'
  233.     dw    chrdef,  atcup,   atri,    ated,    atel    ; 'GHIJK'
  234.     dw    inslin,  dellin,  atdelc,  noins,   v52pos    ; 'LMNOY'
  235.     dw    decid,   h19csi,  h19esos, h19sc,   h19rc    ; 'Z[bjk'
  236.     dw    h19erl,  hrcup,   h19ero,  h19herv, h19hxrv    ; 'lnopq'
  237.     dw    atnorm,  h19wrap, h19nowrp,h19smod, h19cmod    ; 'rvwxy'
  238.     dw    atxreset                    ; 'z'
  239.  
  240. h19ans    db    21            ; Heath-19 ANSI style escape sequences
  241.     dw    h19jmp            ; address of action routine table
  242.     db    'ABCDH','JKLMP','fhlmn','pqrsu','z'
  243.  
  244. ; Heath-19 action table for h19ans
  245.     even
  246. h19jmp    dw    atcuu, atcud, atcuf,  atcub,  atcup        ; 'ABCDH'
  247.     dw    h19ed, atel,  inslin, dellin, atdelc        ; 'JKLMP'
  248.     dw    atcup, atsm,  atrm,   atsgr,  rpcup        ; 'fhlmn'
  249.     dw    atign, atign, atign,  h19sc,  h19rc        ; 'pqrsu'
  250.     dw    atxreset                    ; 'z'
  251.  
  252. ; VT52 compatibility mode escape follower table
  253. v52esc    db    23            ; number of entries
  254.     dw    v52ejt            ; address of action routines
  255.     db    '78<=>', 'ABCDF', 'GHIJK', 'VWXYZ'
  256.     db    ']',5eh,5fh        ; 5eh = caret, 5fh = underscore
  257.  
  258. ; Dispatch for v52esc table
  259.     even
  260. v52ejt    dw    atsc,   atrc,   v52ans, atkpam, atkpnm        ; '78<=>'
  261.     dw    atcuu,  atcud,  atcuf,  atcub,  v52sgm        ; 'ABCDF'
  262.     dw    chrdef, atcup,  atri,   ated,   atel        ; 'GHIJK'
  263.     dw    v52pl,  v52pcb, v52pce, v52pos, decid        ; 'VWXYZ'
  264.     dw    v52ps,  v52pcb, v52pce                ; ']^_'
  265.  
  266. ; VT320/VT102 ANSI mode escape follower table
  267. ansesc    db    37            ; number of entries
  268.     dw    ansejt            ; address of action routines
  269.     db    '01234','5678<', '=>?AB', 'DEFGH', 'MNOPZ'
  270.     db    '[\]',5eh,5fh        ; 5eh = caret, 5fh=underscore
  271.     db    'cno',7bh,7ch        ; 7bh=left curly brace,  7ch=vert bar
  272.     db    7dh,7eh            ; 7dh=right curly brace, 7eh=tilde
  273.  
  274. ; Dispatch for ansesc table
  275.     even
  276. ansejt    dw    atdgf0, atdgf1, atdgf0, atsdhl, atsdhl         ; '01234'
  277.     dw    4 dup (atsdhl), atdgfu                ; '5678<'
  278.     dw    atkpam, atdgft, atdgfq, atdgfA, atdgfB         ; '=>?AB'
  279.     dw    atind,  atnel,  ats7c,     ats8c,  athts        ; 'DEFGH'
  280.     dw    atri,   atss2,  atss3,     atdcs,  decid        ; 'MNOPZ'
  281.     dw    atcsi,  atgotst, 3 dup(atdcsnul)        ; '[\]^_'
  282.     dw    atxreset,atls2, atls3,     atpriv, atls3r        ; 'cno{|'
  283.     dw    atls2r, atls1r                    ; '}~'
  284.  
  285. ; Final char table for VT320/VT102 ANSI escape sequences
  286. anstab    db    38            ; number of entries
  287.     dw    ansjmp            ; address of action routines
  288.     db    '@ABCD','EFGHI','JKLMP','RXacd','efghi','lmnpq','ruwxy'
  289.     db    'z',7dh,7eh        ; 7dh=right curly brace, 7eh=tilde
  290.  
  291. ; Dispatch for anstab table
  292.     even
  293. ansjmp    dw    ansich, atcuu,  atcud,  atcuf,  atcub        ; '@ABCD'
  294.     dw    atcnl,  atcpl,  atcha,  atcup,  atcht        ; 'EFGHI'
  295.     dw    ated,   atel,   inslin, dellin, atdelc        ; 'JKLMP'
  296.     dw    rpcup,  atech,  atcuf,  atda,   atcva          ; 'RXacd'
  297.     dw    atcud,  atcup,  attbc,  atsm,   ansprt        ; 'efghi'
  298.     dw    atrm,   atsgr,  atdsr,  decscl, atll        ; 'lmnpq'
  299.     dw    atstbm, atrqtsr,atrqpsr,atreqt, atctst        ; 'ruwxy'
  300.     dw    atxreset,atsasd, atssdt                ; 'z}~'
  301.  
  302. ; Final character table for Device Control Strings (DCS, ESC P)
  303. dcstab    db    5            ; number of entries
  304.     dw    dcsjmp            ; address of action routines
  305.     db    'pqu',7bh,7ch        ; 7bh = left curly brace
  306.  
  307. ; Dispatch for dcstab table
  308.     even
  309. dcsjmp    dw    atcrqq, atcrq, atupss, atdcsnul, atudk        ; 'pqu{|'
  310. ;;; DCS Ps $ p string ST   page 209 restore color palette
  311.  
  312. ; Heath-19 special graphics characters to CP437. Use as offsets from caret
  313. ; (94D)
  314. hgrtab    db    249, 17,179,196,197    ; caret,underscore,accent grave,a,b
  315.     db    191,217,192,218,241    ; c,d,e,f,g
  316.     db     26,177,219, 25,220    ; h,i,j,k,l
  317.     db    220,223,223,223,222    ; m,n,o,p,q
  318.     db     16,194,180,193,195    ; r,s,t,u,v
  319.     db    'X','/','\',223,220    ; w,x,y,z,left curly brace
  320.     db    221,222, 20        ; vertical bar,right curly brace,tilde
  321. hgrtabl    equ ($-hgrtab)
  322.  
  323. ; VT320/VT102 "Special graphics" set translation table for characters 95..126d
  324. ; when the special graphics set is selected. Some characters (98, 99, 100,
  325. ; 101, 104, 105, 111, 112, 114, 115, and 116) do not have exact equivalents
  326. ; in the available set on the IBM, so a close substitution is made.
  327. ; Table is indexed by ASCII char value minus 95 for chars 95..126d.
  328. sgrtab    db     32,  4,177, 26, 23,  27, 25,248,241, 21
  329.     db     18,217,191,218,192, 197,196,196,196,196
  330.     db    196,195,180,193,194, 179,243,242,227,157
  331.     db    156,250
  332. sgrtabl    equ    $-sgrtab
  333.  
  334.     ; DEC National Replacement Char sets, one table for each Code Page
  335.                         ; CP437
  336. ; 12 replacment bytes (keyed by ASCII bytes), NRC number, country, size, ident
  337. nrc437    db    23h,40h,5bh,5ch,5dh,5eh        ; 0, ASCII, "B", dispatch ref
  338.     db    5fh,60h,7bh,7ch,7dh,7eh
  339.     db    94,'B',0            ; 94 byte set, letter pair
  340.     db    9ch,40h,5bh,5ch,5dh,5eh        ; 1, British, "A"
  341.     db    5fh,60h,7bh,7ch,7dh,7eh
  342.     db    94,'A',0
  343.     db    9ch,3fh,98h,0abh,7ch,5eh    ; 2, Dutch, "4"
  344.     db    5fh,60h,22h,9fh,0ach,27h
  345.     db    94,'4',0
  346.     db    23h,40h,8eh,99h,8fh,9ah        ; 3, Finnish, "5"
  347.     db    5fh,82h,84h,94h,86h,81h
  348.     db    94,'5',0
  349.     db    9ch,85h,0f8h,87h,15h,5eh    ; 4, French, "R"
  350.     db    5fh,60h,82h,97h,8ah,22h
  351.     db    94,'R',0
  352.     db    23h,85h,83h,87h,88h,8ch        ; 5, French Canadian, "9"
  353.     db    5fh,93h,82h,97h,8ah,96h
  354.     db    94,'9',0
  355.     db    23h,15h,8eh,99h,9ah,5eh        ; 6, German, "K"
  356.     db    5fh,60h,84h,94h,81h,0e1h
  357.     db    94,'K',0
  358.     db    9ch,15h,0f8h,87h,82h,5eh    ; 7, Italian, "Y"
  359.     db    5fh,97h,85h,95h,8ah,8dh
  360.     db    94,'Y',0
  361.     db    23h,40h,92h,0edh,8fh,5eh    ; 8, Norwegian/Danish, "'"
  362.     db    5fh,60h,91h,0edh,86h,7eh
  363.     db    94,60h,0
  364.     db    23h,40h,8eh,80h,99h,5eh        ; 9, Portugese, "%6"
  365.     db    5fh,60h,0a6h,87h,0a7h,7eh
  366.     db    94,'%','6'
  367.     db    9ch,15h,8ch,0a5h,0a8h,5eh    ; 10, Spanish, "Z"
  368.     db    5fh,60h,60h,0f8h,0a4h,87h
  369.     db    94,'Z',0
  370.     db    23h,90h,8eh,99h,8fh,9ah        ; 11, Swedish, "7"
  371.     db    5fh,82h,84h,94h,86h,81h
  372.     db    94,'7',0
  373.     db    97h,85h,82h,87h,88h,8ch        ; 12, Swiss, "="
  374.     db    8ah,93h,84h,94h,81h,96h
  375.     db    94,'=',0
  376.  
  377.                         ; CP850
  378. ; 12 replacment bytes (keyed by ASCII bytes), NRC number, country, size, ident
  379. nrc850    db    23h,40h,5bh,5ch,5dh,5eh        ; 0, ASCII, "B", dispatch ref
  380.     db    5fh,60h,7bh,7ch,7dh,7eh
  381.     db    94,'B',0            ; 94 byte set, letter pair
  382.     db    9ch,40h,5bh,5ch,5dh,5eh        ; 1, British, "A"
  383.     db    5fh,60h,7bh,7ch,7dh,7eh
  384.     db    94,'A',0
  385.     db    9ch,0f3h,98h,0abh,7ch,5eh    ; 2, Dutch, "4"
  386.     db    5fh,60h,22h,9fh,0ach,27h
  387.     db    94,'4',0
  388.     db    23h,40h,8eh,99h,8fh,9ah        ; 3, Finnish, "5"
  389.     db    5fh,82h,84h,94h,86h,81h
  390.     db    94,'5',0
  391.     db    9ch,85h,0f8h,87h,15h,5eh    ; 4, French, "R"
  392.     db    5fh,60h,82h,97h,8ah,22h
  393.     db    94,'R',0
  394.     db    23h,85h,83h,87h,88h,8ch        ; 5, French Canadian, "9"
  395.     db    5fh,93h,82h,97h,8ah,96h
  396.     db    94,'9',0
  397.     db    23h,15h,8eh,99h,9ah,5eh        ; 6, German, "K"
  398.     db    5fh,60h,84h,94h,81h,0e1h
  399.     db    94,'K',0
  400.     db    9ch,15h,0f8h,87h,82h,5eh    ; 7, Italian, "Y"
  401.     db    5fh,97h,85h,95h,8ah,8dh
  402.     db    94,'Y',0
  403.     db    23h,40h,92h,09dh,8fh,5eh    ; 8, Norwegian/Danish, "'"
  404.     db    5fh,60h,91h,09bh,86h,7eh
  405.     db    94,60h,0
  406.     db    23h,40h,0b5h,80h,0e5h,5eh    ; 9, Portugese, "%6"
  407.     db    5fh,60h,61h,87h,0e4h,7eh
  408.     db    94,'%','6'
  409.     db    9ch,15h,0adh,0a5h,0a8h,5eh    ; 10, Spanish, "Z"
  410.     db    5fh,60h,60h,0f8h,0a4h,87h
  411.     db    94,'Z',0
  412.     db    23h,90h,8eh,99h,8fh,9ah        ; 11, Swedish, "7"
  413.     db    5fh,82h,84h,94h,86h,81h
  414.     db    94,'7',0
  415.     db    97h,85h,82h,87h,88h,8ch        ; 12, Swiss, "="
  416.     db    8ah,93h,84h,94h,81h,96h
  417.     db    94,'=',0
  418.                         ; CP860
  419. ; 12 replacment bytes (keyed by ASCII bytes), NRC number, country, size, ident
  420. nrc860    db    23h,40h,5bh,5ch,5dh,5eh        ; 0, ASCII, "B", dispatch ref
  421.     db    5fh,60h,7bh,7ch,7dh,7eh
  422.     db    94,'B',0            ; 94 byte set, letter pair
  423.     db    9ch,40h,5bh,5ch,5dh,5eh        ; 1, British, "A"
  424.     db    5fh,60h,7bh,7ch,7dh,7eh
  425.     db    94,'A',0
  426.     db    9ch,3fh,79h,0abh,7ch,5eh    ; 2, Dutch, "4"
  427.     db    5fh,60h,22h,3fh,0ach,27h
  428.     db    94,'4',0
  429.     db    23h,40h,41h,4fh,41h,9ah        ; 3, Finnish, "5"
  430.     db    5fh,82h,61h,6fh,61h,81h
  431.     db    94,'5',0
  432.     db    9ch,85h,0f8h,87h,15h,5eh    ; 4, French, "R"
  433.     db    5fh,60h,82h,97h,8ah,22h
  434.     db    94,'R',0
  435.     db    23h,85h,83h,87h,88h,69h        ; 5, French Canadian, "9"
  436.     db    5fh,93h,82h,97h,8ah,75h
  437.     db    94,'9',0
  438.     db    23h,15h,41h,4fh,9ah,5eh        ; 6, German, "K"
  439.     db    5fh,60h,61h,6fh,81h,0e1h
  440.     db    94,'K',0
  441.     db    9ch,15h,0f8h,87h,82h,5eh    ; 7, Italian, "Y"
  442.     db    5fh,97h,85h,95h,8ah,8dh
  443.     db    94,'Y',0
  444.     db    23h,40h,3fh,0edh,41h,5eh    ; 8, Norwegian/Danish, "'"
  445.     db    5fh,60h,3fh,0edh,61h,7eh
  446.     db    94,60h,0
  447.     db    23h,40h,8eh,80h,99h,5eh        ; 9, Portugese, "%6"
  448.     db    5fh,60h,84h,87h,94h,7eh
  449.     db    94,'%','6'
  450.     db    9ch,15h,0adh,0a5h,0a8h,5eh    ; 10, Spanish, "Z"
  451.     db    5fh,60h,60h,0f8h,0a4h,87h
  452.     db    94,'Z',0
  453.     db    23h,90h,41h,4fh,41h,9ah        ; 11, Swedish, "7"
  454.     db    5fh,82h,61h,6fh,61h,75h
  455.     db    94,'7',0
  456.     db    97h,85h,82h,87h,88h,69h        ; 12, Swiss, "="
  457.     db    8ah,93h,61h,6fh,81h,75h
  458.     db    94,'=',0
  459.                         ; CP863
  460. ; 12 replacment bytes (keyed by ASCII bytes), NRC number, country, size, ident
  461. nrc863    db    23h,40h,5bh,5ch,5dh,5eh        ; 0, ASCII, "B", dispatch ref
  462.     db    5fh,60h,7bh,7ch,7dh,7eh
  463.     db    94,'B',0            ; 94 byte set, letter pair
  464.     db    9ch,40h,5bh,5ch,5dh,5eh        ; 1, British, "A"
  465.     db    5fh,60h,7bh,7ch,7dh,7eh
  466.     db    94,'A',0
  467.     db    9ch,0adh,79h,0abh,7ch,5eh    ; 2, Dutch, "4"
  468.     db    5fh,60h,0a4h,9fh,0ach,0a1h
  469.     db    94,'4',0
  470.     db    23h,40h,41h,4fh,41h,55h        ; 3, Finnish, "5"
  471.     db    5fh,82h,61h,6fh,61h,81h
  472.     db    94,'5',0
  473.     db    9ch,85h,0f8h,87h,15h,5eh    ; 4, French, "R"
  474.     db    5fh,60h,82h,97h,8ah,0a4h
  475.     db    94,'R',0
  476.     db    23h,85h,83h,87h,88h,8ch        ; 5, French Canadian, "9"
  477.     db    5fh,93h,82h,97h,8ah,96h
  478.     db    94,'9',0
  479.     db    23h,15h,41h,4fh,9ah,5eh        ; 6, German, "K"
  480.     db    5fh,60h,61h,6fh,81h,0e1h
  481.     db    94,'K',0
  482.     db    9ch,15h,0f8h,87h,82h,5eh    ; 7, Italian, "Y"
  483.     db    5fh,97h,6fh,85h,8ah,69h
  484.     db    94,'Y',0
  485.     db    23h,40h,3fh,0edh,41h,5eh    ; 8, Norwegian/Danish, "'"
  486.     db    5fh,60h,0efh,0edh,61h,7eh
  487.     db    94,60h,0
  488.     db    23h,40h,41h,80h,4fh,5eh        ; 9, Portugese, "%6"
  489.     db    5fh,60h,61h,87h,6fh,7eh
  490.     db    94,'%','6'
  491.     db    9ch,15h,3fh,4eh,3fh,5eh        ; 10, Spanish, "Z"
  492.     db    5fh,60h,60h,0f8h,6eh,87h
  493.     db    94,'Z',0
  494.     db    23h,90h,41h,4fh,41h,9ah        ; 11, Swedish, "7"
  495.     db    5fh,82h,61h,6fh,61h,81h
  496.     db    94,'7',0
  497.     db    97h,85h,82h,87h,88h,8ch        ; 12, Swiss, "="
  498.     db    8ah,93h,61h,6fh,81h,96h
  499.     db    94,'=',0
  500.                         ; CP865
  501. ; 12 replacment bytes (keyed by ASCII bytes), NRC number, country, size, ident
  502. nrc865    db    23h,40h,5bh,5ch,5dh,5eh        ; 0, ASCII, "B", dispatch ref
  503.     db    5fh,60h,7bh,7ch,7dh,7eh
  504.     db    94,'B',0            ; 94 byte set, letter pair
  505.     db    9ch,40h,5bh,5ch,5dh,5eh        ; 1, British, "A"
  506.     db    5fh,60h,7bh,7ch,7dh,7eh
  507.     db    94,'A',0
  508.     db    9ch,3fh,98h,0abh,7ch,5eh    ; 2, Dutch, "4"
  509.     db    5fh,60h,22h,9fh,0ach,27h
  510.     db    94,'4',0
  511.     db    23h,40h,8eh,99h,8fh,9ah        ; 3, Finnish, "5"
  512.     db    5fh,82h,84h,94h,86h,81h
  513.     db    94,'5',0
  514.     db    9ch,85h,0f8h,87h,15h,5eh    ; 4, French, "R"
  515.     db    5fh,60h,82h,97h,8ah,22h
  516.     db    94,'R',0
  517.     db    23h,85h,83h,87h,88h,8ch        ; 5, French Canadian, "9"
  518.     db    5fh,93h,82h,97h,8ah,96h
  519.     db    94,'9',0
  520.     db    23h,15h,8eh,99h,9ah,5eh        ; 6, German, "K"
  521.     db    5fh,60h,84h,94h,81h,0e1h
  522.     db    94,'K',0
  523.     db    9ch,15h,0f8h,87h,82h,5eh    ; 7, Italian, "Y"
  524.     db    5fh,97h,85h,95h,8ah,8dh
  525.     db    94,'Y',0
  526.     db    23h,40h,92h,9dh,8fh,5eh        ; 8, Norwegian/Danish, "'"
  527.     db    5fh,60h,91h,9bh,86h,7eh
  528.     db    94,60h,0
  529.     db    23h,40h,41h,80h,4fh,5eh        ; 9, Portugese, "%6"
  530.     db    5fh,60h,61h,87h,6fh,7eh
  531.     db    94,'%','6'
  532.     db    9ch,15h,0adh,0a5h,0a8h,5eh    ; 10, Spanish, "Z"
  533.     db    5fh,60h,60h,0f8h,0a4h,87h
  534.     db    94,'Z',0
  535.     db    23h,90h,8eh,99h,8fh,9ah        ; 11, Swedish, "7"
  536.     db    5fh,82h,84h,94h,86h,81h
  537.     db    94,'7',0
  538.     db    97h,85h,82h,87h,88h,8ch        ; 12, Swiss, "="
  539.     db    8ah,93h,84h,94h,81h,96h
  540.     db    94,'=',0
  541.  
  542. ;NRC to DEC keyboard codes, North American (ASCII is nrckbd 1),+ALT-ROM+transp
  543. nrckbd    db    1,2,8,6,14,4,7,9,13,16,15,12,11,1,1,1
  544.  
  545. ; Translation tables for byte codes 0a0h..0ffh to map DEC Multinational
  546. ; Character Set (DEC Supplemental Graphic) to Code Pages.
  547. ; Codes 00h-1fh are 7-bit controls (C0), codes 20h..7eh are ASCII, 7fh DEL is
  548. ; considered to be a control code, 80h..9fh are 8-bit controls (C1).
  549. ; Each table is 94 translatable bytes followed by the table size (94), the
  550. ; ISO announcer ident '%5'.
  551.                     ; from DEC Multinational to Code Page
  552.                             ; to CP437
  553. MNcp437    db    80h,81h,82h,83h,   84h,85h,86h,87h    ; column 8
  554.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  555.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 9
  556.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  557.     db    0h,0adh,9bh,9ch,   20h,9dh,20h,15h    ; column 10
  558.     db    0fh,40h,0a6h,0aeh, 20h,20h,20h,20h
  559.     db    0f8h,0f1h,0fdh,33h, 20h,0e6h,14h,0feh    ; column 11
  560.     db    2eh,60h,0a7h,0afh, 0ach,0abh,20h,0a8h
  561.     db    85h,0a0h,83h,83h,  8eh,8fh,92h,80h    ; column 12
  562.     db    8ah,90h,88h,89h,   8dh,0a1h,8ch,8bh
  563.     db    20h,0a5h,95h,0a2h, 93h,94h,94h,4fh    ; column 13
  564.     db    0edh,97h,0a3h,96h, 9ah,59h,20h,0e1h
  565.     db    85h,0a0h,83h,84h,  84h,86h,91h,87h    ; column 14
  566.     db    8ah,82h,88h,89h,   8dh,0a1h,8ch,8bh
  567.     db    20h,0a4h,95h,0a2h, 93h,94h,94h,6fh    ; column 15
  568.     db    0edh,97h,0a3h,96h, 81h,98h,20h,0h
  569.     db    94,'%','5'            ; 94 byte set, letter ident
  570.  
  571.                             ; to CP850
  572. MNcp850    db    80h,81h,82h,83h,   84h,85h,86h,87h    ; column 8
  573.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  574.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 9
  575.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  576.     db    0h,0adh,0bdh,9ch,  20h,0beh,20h,15h    ; column 10
  577.     db    0cfh,0b8h,0a6h,0aeh, 20h,20h,20h,20h
  578.     db    0f8h,0f1h,0fdh,0fch, 20h,0e6h,14h,0feh    ; column 11
  579.     db    2eh,0fbh,0a7h,0afh, 0ach,0abh,20h,0a8h
  580.     db    0b7h,0b5h,0b6h,0b5h, 8eh,8fh,92h,80h    ; column 12
  581.     db    0d4h,90h,0d2h,0d3h, 0deh,0d6h,0d7h,0d8h
  582.     db    20h,0a5h,0e3h,0e0h, 0e2h,0e5h,99h,4fh    ; column 13
  583.     db    9dh,0ebh,0e9h,0eah, 9ah,0edh,20h,0e1h
  584.     db    85h,0a0h,83h,61h,   84h,86h,91h,87h    ; column 14
  585.     db    8ah,82h,88h,89h,    8dh,0a1h,8ch,8bh
  586.     db    20h,0a4h,95h,0a2h,  93h,0e4h,94h,6fh    ; column 15
  587.     db    9bh,97h,0a3h,96h,   81h,0ech,20h,0h
  588.     db    94,'%','5'            ; 94 byte set, letter ident
  589.                             ; to CP860
  590. MNcp860    db    80h,81h,82h,83h,   84h,85h,86h,87h    ; column 8
  591.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  592.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 9
  593.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  594.     db    0h,0adh,9bh,9ch,   20h,59h,20h,15h    ; column 10
  595.     db    0fh,3fh,0a6h,0aeh, 20h,20h,20h,20h
  596.     db    0f8h,0f1h,0fdh,33h, 20h,0e6h,14h,0feh    ; column 11
  597.     db    2eh,60h,0a7h,0afh, 0ach,0abh,20h,0a8h
  598.     db    85h,0a0h,83h,83h,  8eh,8fh,92h,80h    ; column 12
  599.     db    8ah,90h,88h,89h,   8dh,0a1h,8ch,8bh
  600.     db    20h,0a5h,95h,0a2h, 93h,94h,94h,4fh    ; column 13
  601.     db    0edh,97h,0a3h,96h, 9ah,59h,20h,0e1h
  602.     db    85h,0a0h,83h,84h,  84h,86h,91h,87h    ; column 14
  603.     db    8ah,82h,88h,89h,   8dh,0a1h,8ch,8bh
  604.     db    20h,0a4h,95h,0a2h, 93h,94h,94h,6fh    ; column 15
  605.     db    0edh,97h,0a3h,96h, 81h,98h,20h,0h
  606.     db    94,'%','5'            ; 94 byte set, letter ident
  607.                             ; to CP863
  608. MNcp863    db    80h,81h,82h,83h,   84h,85h,86h,87h    ; column 8
  609.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  610.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 9
  611.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  612.     db    0h,0adh,9bh,9ch,   20h,9dh,20h,15h    ; column 10
  613.     db    98h,40h,61h,0aeh,  20h,20h,20h,20h
  614.     db    0f8h,0f1h,0fdh,33h, 20h,0e6h,86h,0feh    ; column 11
  615.     db    2eh,31h,6fh,0afh,  0ach,0abh,20h,3fh
  616.     db    8eh,41h,84h,41h,   41h,41h,3fh,80h    ; column 12
  617.     db    91h,90h,92h,94h,   49h,49h,88h,95h
  618.     db    20h,4eh,4fh,4fh,   99h,4fh,4fh,4fh    ; column 13
  619.     db    0edh,9dh,55h,0aeh, 55h,59h,20h,0e1h
  620.     db    85h,61h,83h,61h,   61h,61h,3fh,87h    ; column 14
  621.     db    8ah,82h,88h,89h,   69h,69h,8ch,8bh
  622.     db    20h,6eh,6fh,0a2h,  93h,6fh,6fh,6fh    ; column 15
  623.     db    0edh,97h,0a3h,96h, 75h,79h,20h,0h
  624.     db    94,'%','5'            ; 94 byte set, letter ident
  625.                             ; to CP865
  626. MNcp865    db    80h,81h,82h,83h,   84h,85h,86h,87h    ; column 8
  627.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  628.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 9
  629.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  630.     db    0h,0adh,3fh,9ch,   20h,3fh,20h,15h    ; column 10
  631.     db    0afh,3fh,0a6h,0aeh, 20h,20h,20h,20h
  632.     db    0f8h,0f1h,0fdh,33h, 20h,0e6h,14h,0feh    ; column 11
  633.     db    2eh,31h,0a7h,03fh, 0ach,0abh,20h,0a8h
  634.     db    41h,41h,41h,41h,   8eh,8fh,92h,80h    ; column 12
  635.     db    45h,90h,45h,45h,   49h,49h,49h,49h
  636.     db    20h,0a5h,4fh,4fh,  4fh,4fh,99h,4fh    ; column 13
  637.     db    0edh,55h,55h,55h,  9ah,59h,20h,0e1h
  638.     db    85h,0a0h,83h,61h,  84h,86h,91h,87h    ; column 14
  639.     db    8ah,82h,88h,89h,   8dh,0a1h,8ch,8bh
  640.     db    20h,0a4h,95h,0a2h, 93h,6fh,94h,6fh    ; column 15
  641.     db    0edh,97h,0a3h,96h, 81h,79h,20h,0h
  642.     db    94,'%','5'            ; 94 byte set, letter ident
  643.  
  644. ; 128 byte translation tables from Code Pages to DEC Multinational char set
  645. ; (DEC Supplemental Graphic). For GRight only (high bit set).
  646.                             ; from Code Page 437
  647. cp437MN    db    0c7h,0fch,0e9h,0e2h, 0e4h,0e0h,0e5h,0e7h ; column 8
  648.     db    0eah,0ebh,0e8h,0efh, 0eeh,0ech,0c4h,0c5h
  649.     db    0c9h,0e6h,0c6h,0f4h, 0f6h,0f2h,0fbh,0f9h ; column 9
  650.     db    0ffh,0d6h,0dch,0a2h, 0a3h,0a5h,3fh,3fh
  651.     db    0e1h,0edh,0f3h,0fah, 0f1h,0d1h,0aah,0bah ; column 10
  652.     db    0bfh,3fh,0ach,0bdh,  0bch,0a1h,0abh,0bbh
  653.     db    16 dup (3fh)                 ; column 11
  654.     db    16 dup (3fh)                 ; column 12
  655.     db    16 dup (3fh)                 ; column 13
  656.     db    3fh,0dfh, 4 dup (3fh),        0b5h,3fh ; column 14
  657.     db    5 dup(3fh),            0f8h,3fh,3fh
  658.     db    3fh,0b1h, 4 dup (3fh),          0h,3fh ; column 15
  659.     db    0b0h, 4 dup (3fh),       0b2h,0b7h,3fh
  660.                              ; from Code Page 850
  661. cp850MN    db    0c7h,0fch,0e9h,0e2h, 0e4h,0e0h,0e5h,0e7h ; column 8
  662.     db    0eah,0ebh,0e8h,0efh, 0eeh,0ech,0c4h,0c5h
  663.     db    0c9h,0e6h,0c6h,0f4h, 0f6h,0f2h,0fbh,0f9h ; column 9
  664.     db    0ffh,0d6h,0dch,0f8h, 0a3h,0d8h,58h,3fh
  665.     db    0e1h,0edh,0f3h,0fah, 0f1h,0d1h,0aah,0bah ; column 10
  666.     db    0bfh,0aeh,0ach,0bdh, 0bch,0a1h,0abh,0bbh
  667.     db    5 dup (3fh),              0c1h,0c2h,0c0h ; column 11
  668.     db    0a9h, 4 dup (3fh),      0a2h,0a5h,0ach
  669.     db    6 dup (3fh),0e3h,0c3h, 7 dup (3fh),0a4h     ; column 12
  670.     db    0f0h,0d0h,0cah,0cbh, 0c8h,0b9h,0cdh,0ceh ; column 13
  671.     db    0cfh, 4 dup (3fh),       7ch,0cch,3fh
  672.     db    0d3h,0dfh,0d4h,0d2h, 0f5h,0d5h,0b5h,0deh ; column 14
  673.     db    0feh,0dah,0dbh,0d9h, 0fdh,0ddh,0afh,0b4h
  674.     db    0adh,0b1h,3dh,0beh,  0b6h,0a7h,00h,22h     ; column 15
  675.     db    0b0h,0a8h,3fh,0b9h,  0b2h,0b3h,0b7h,20h
  676.                              ; from Code Page 860
  677. cp860MN    db    0c7h,0fch,0e9h,0e2h, 0e3h,0e0h,0c1h,0e7h ; column 8
  678.     db    0eah,0cah,0e8h,0cch, 0d4h,0ech,0c3h,0c2h
  679.     db    0c9h,0c0h,0c8h,0f4h, 0f5h,0f2h,0dah,0f9h ; column 9
  680.     db    0cch,0d5h,0dch,0a2h, 0a3h,0d9h,3fh,0d3h
  681.     db    0e1h,0edh,0f3h,0fah, 0f1h,0d1h,0aah,0bah ; column 10
  682.     db    0bfh,0d2h,0ach,0bdh, 0bch,0a1h,0abh,0bbh
  683.     db    16 dup (3fh)                 ; column 11
  684.     db    16 dup (3fh)                 ; column 12
  685.     db    16 dup (3fh)                 ; column 13
  686.     db    3fh,0dfh, 4 dup (3fh),        0b5h,3fh ; column 14
  687.     db    5 dup(3fh),            0f8h,3fh,3fh
  688.     db    3fh,0b1h, 4 dup (3fh),          0h,3fh ; column 15
  689.     db    0b0h, 4 dup (3fh),       0b2h,0b7h,3fh
  690.                              ; from Code Page 863
  691. cp863MN    db    0c7h,0fch,0e9h,0e2h, 0e2h,0e0h,0b6h,0a2h ; column 8
  692.     db    0eah,0ebh,0e8h,0efh, 0eeh,3dh,0c0h,0a7h
  693.     db    0c9h,0c8h,0cah,0f4h, 0cbh,0cfh,0fbh,0fah ; column 9
  694.     db    0a4h,0d4h,0dch,0a2h, 0a3h,0d9h,0dbh,3fh
  695.     db    7ch,0b4h,0f3h,0fah, 0a8h,0a8h,0b3h,0afh ; column 10
  696.     db    0ceh,3fh,0ach,0bdh,  0bch,0beh,0abh,0bbh
  697.     db    16 dup (3fh)                 ; column 11
  698.     db    16 dup (3fh)                 ; column 12
  699.     db    16 dup (3fh)                 ; column 13
  700.     db    3fh,0dfh, 4 dup (3fh),        0b5h,3fh ; column 14
  701.     db    5 dup(3fh),            0f8h,3fh,3fh
  702.     db    3fh,0b1h, 4 dup (3fh),          0h,3fh ; column 15
  703.     db    0b0h, 4 dup (3fh),       0b2h,0b7h,3fh
  704.                                   ; from Code Page 865
  705. cp865MN    db    0c7h,0fch,0e9h,0e2h, 0e4h,0e0h,0e5h,0e7h ; column 8
  706.     db    0eah,0ebh,0e8h,0efh, 0eeh,0ech,0c4h,0c5h
  707.     db    0c9h,0e6h,0c6h,0f4h, 0f6h,0f2h,0fbh,0fah ; column 9
  708.     db    0ffh,0d6h,0dch,0f8h, 0a3h,0d8h,3fh,3fh
  709.     db    0e2h,0edh,0f3h,0fah, 0f1h,0d1h,0aah,0bah ; column 10
  710.     db    0bfh,3fh,0ach,0bdh,  0bch,0a1h,0abh,0a4h
  711.     db    16 dup (3fh)                 ; column 11
  712.     db    16 dup (3fh)                 ; column 12
  713.     db    16 dup (3fh)                 ; column 13
  714.     db    3fh,0dfh, 4 dup (3fh),        0b5h,3fh ; column 14
  715.     db    5 dup(3fh),            0f8h,3fh,3fh
  716.     db    3fh,0b1h, 4 dup (3fh),          0h,3fh ; column 15
  717.     db    0b0h, 4 dup (3fh),       0b2h,0b7h,3fh
  718.  
  719.                ; Dec Technical set to CP437, CP860, CP863, CP865
  720.              ; Note: CP850 lacks the symbols so expect trash
  721. dectech    db    32 dup (0)                ; columns 8 and 9
  722.     db    0h,0fbh,0dah,0c4h, 0f4h,0f5h,0b3h,0dah    ; column 10
  723.     db    0c0h,0bfh,0d9h,28h,28h,29h,29h,0b4h
  724.     db    0c3h,3ch,3eh,5ch,  2fh,0bfh,0d9h,03eh    ; column 11
  725.     db    0a8h,20h,20h,20h,  0f3h,3dh,0f2h,3fh
  726.     db    1eh,0ech,0ech,0f6h,1eh,1fh,0e8h,0e2h    ; column 12
  727.     db    0f7h,0f7h,0e9h,58h,3fh,1dh,1ah,0f0h
  728.     db    0e3h,3fh,20h,0e4h, 20h,20h,0fbh,0eah    ; column 13
  729.     db    3fh,54h,3fh,3fh,   0efh,55h,5eh,76h
  730.     db    0aah,0e0h,0e1h,78h,0ebh,0eeh,0edh,3fh    ; column 14 
  731.     db    6eh,69h,0e9h,6bh,  3fh,20h,76h,3fh
  732.     db    0e3h,3fh,70h,0e5h, 0e7h,0a8h,9fh,77h    ; column 15
  733.     db    45h,76h,3fh,1bh,   18h,1ah,19h,7fh
  734.     db    94,3eh,0            ; 94 byte set, letter ident
  735.  
  736. ; Device attributes response string. A VT100 reports as ESC [ ? 1 ; 2 c 
  737. ; Make strings asciiz.
  738. v32str    db    escape,'[?63;1;2;4;8;9;15c',0; VT320, level 3,
  739.         ; 132 col, printer, Sixel graphics, UDkeys,NRC,DEC Tech Chars
  740. v32sda    db    escape,'[>24;0;0c',0    ; VT320 secondary DA response
  741. v102str    db    escape,'[?6c',0        ; VT102
  742. v52str    db    escape,'/Z',0        ; VT100 in VT52 compatibility mode
  743. h19str    db    escape,'/K',0        ; Heath-19 (says plain VT52)
  744.  
  745.                     ; parity code translation table
  746. partab    db    5,3,1,4,2        ; even, mark, none, odd, space
  747. lpartab equ    $-partab
  748. parcode db    0            ; parity code (0-4)
  749.                     ; baud rate code translation table
  750. ; 45.5 - no VT100 code (call it 50),50,75,110,134.5,150,300,600,1200,
  751. ; 1800,2000,2400,4800,9600,19200,38400,57600,115200  extended beyond DEC
  752. baudtab db    0,0,8,16,24,32,48,56,64,72,80,88,104,112,120,128,128,128
  753. lbaudtab equ    $-baudtab
  754. baudidx db    0            ; index into baud rate table
  755. datbits db    7            ; number of databits (7 or 8)
  756.  
  757. ttstate dw    offset atnrm        ; terminal automata state
  758. ttstateST dw    offset atnorm        ; state for action after ST seen
  759. att_normal db    07H            ; default normal screen coloring
  760. oldterm    db    0            ; terminal type from previous entry
  761. iniflgs    dw    0            ; status flags at entry time
  762. modeset db    0            ; temp for atsm/atrm
  763. anspflg    db    0            ; printer flag bits and definitions
  764. h19stat    db    0            ; H-19 extra status bits
  765. h19ctyp    db    1            ; H-19 cursor type (1=ul, 2=bk, 4=off)
  766. h19cur    dw    0            ; H-19 saved cursor position
  767. atctype    db    1            ; VTxxx cursor type (1=ul,2=bk, 4=off)
  768. insmod    db    0            ; insert mode on (1) or off (0)
  769. belcol    db    72            ; column at which to ring margin bell
  770. kbicsr    dw    0            ; cursor when keyboard input typed
  771. kbiflg    db    0            ; set/reset for keyboard input
  772. ttkbi    db    0            ; flag for keyboard input seen
  773. transflg db    0            ; flag to say TRANSLATE INPUT worked
  774.  
  775. setptr    dw    0            ; hold offset of designated char set
  776. upss    db    96,'A',0,0        ; User Preferred Supplemental Set
  777.                     ; size, ident (DEC Supplemental Gr)
  778.  
  779. ; Start of save cursor material
  780. savelist equ    this byte        ; top of list of things to save
  781. cursor    dw    0            ; cursor position
  782. curattr db    07h            ; cursor attribute
  783. svattr_index    equ $-savelist        ; offset of saved cursor attribute
  784. video_state db    0            ; video state (0=normal, 1=reversed)
  785. atwrap    db    0            ; autowrap flag
  786. GLptr    dw    0            ; pointer to char set for GL
  787. GRptr    dw    0            ; pointer to char set for GR
  788. SSptr    dw    0            ; pointer to char set for single shift
  789. G0set    db    gsize+3 dup (0)        ; make G0..G3 char set space
  790. G1set    db    gsize+3 dup (0)
  791. G2set    db    gsize+3 dup (0)
  792. G3set    db    gsize+3 dup (0)
  793. lsavecu equ    $-savelist        ; length of stuff to save
  794.  
  795. savecu    db    lsavecu dup (0)        ; saved cursor, attr., charset, etc
  796. savflgs dw    0            ; saved flags for atsc/atrc
  797. ; End of save cursor matieral
  798.  
  799. ; tab stops, stored here
  800. tabs    db    (swidth+7)/8 dup (0)    ; active tab stops, one column per bit
  801. deftabs    db    (swidth+7)/8 dup (0)    ; default (setup) tab stops
  802.  
  803. ; byte per line, type of line: 0=normal, 1=double wide, 2=double high
  804. linetype db    slen dup (0)
  805. low_rgt    dw    0            ; text screen dimensions
  806.                     ; byte low_rgt = max column (79)
  807.                     ; byte low_rgt+1 = max row (23)
  808. oldscrn    dw    0            ; old screen. hi=rows-1, low=cols-1
  809.  
  810. ; Scrolling region - do not separate or change order of mar_top & mar_bot
  811. mar_top db    0            ; scrolling region top margin
  812. mar_bot db    23            ; scrolling region bottom margin
  813. scroll    db    1            ; lines to scroll
  814.  
  815. dspstate db    0            ; Display state (mode)line work byte
  816. dspmsave dw    0            ; saved main dsp scrolling margins
  817. dspcstat dw    0            ; saved cursor pos for status line
  818. dspcmain dw    0            ; saved cursor pos for main display
  819.  
  820. led_col equ    65            ; column position for "LEDs" display
  821. led_off equ    '.'            ; "Off" LED
  822. v32leds    db    'VT320     '        ; VT320 mode (all 10 characters)
  823. ansleds db    'VT102 ....'        ; VT102 mode
  824. v52leds db    'VT52      '        ; VT52 mode
  825. h19leds    db    'Heath-19  '        ; Heath-19 mode
  826.  
  827.     even                ; Control sequence storage area
  828. dnparam    dw    0            ; number of parameters for DCS
  829. dparam    dw    maxparam dup (0)    ; Parameters for DCS
  830. dlparam    db    0            ; a single letter Parameter for DCS
  831. dninter    dw    0            ; number of DCS intermediates
  832. dinter    db    maxinter dup (0)    ; Intermediates for DCS
  833. dcsstrf    db    0            ; Final char of DCS
  834. emubufc    dw    0            ; count of chars in string buffer
  835. emubuf    db    66 dup (0)        ; emulator string storage buffer
  836.     db    0            ; safety for string overflow
  837. emubufl    dw    $-emubuf        ; length of emulator buffer
  838. data    ends
  839.  
  840. code2    segment    public 'code2'
  841.     extrn    tekini:far, tekemu:far, tekend:far
  842. code2    ends
  843.  
  844. code    segment public 'code'
  845.     extrn    prtbout:near, prtnout:near, csrtype:near, atsclr:near
  846.     extrn    vtscru:near, vtscrd:near, chgdsp:near, trnprs:near
  847.     extrn    cptchr:near, pntchr:near, pntchk:near, setpos:near
  848.     extrn    pntflsh:near, vtbell:near, vtrmac:near,vtsmac:near
  849.     extrn    getpos:near, setatch:near, getatch:near, putchar:near
  850.     extrn    revideo:near, getbold:near, setbold:near, clrbold:near
  851.     extrn    getblink:near, setblink:near, clrblink:near, getunder:near
  852.     extrn    setunder:near, clrunder:near, revscn:near, setcolor:near
  853.     extrn    clrmod:near, modlin:near, setudk:near, udkclear:near
  854.     extrn    setrev:near, clrrev:near
  855.     extrn    out8bit:near, atparse:near, atpclr:near, atdispat:near
  856.     extrn    insdecom:near, tekinq:near, tekpal:near, dec2di:near
  857.  
  858.     assume    cs:code, ds:data, es:nothing
  859.  
  860. ; ANSI terminal output routine.     Call with character in al.
  861.  
  862. anstty    proc    near            ; ANSI terminal output
  863.     mov    dx,cursor        ; some routines need cursor in dx
  864.     mov    kbiflg,0        ; clear old flag value
  865.     test    yflags,trnctl        ; Debug mode?
  866.     jz    anstt1            ; z = no
  867.     jmp    atdeb            ; yes, just translate control chars
  868. anstt1:    cmp    ttkbi,0            ; new keyboard input?
  869.     je    anstt2            ; e = no, just continue
  870.     mov    kbiflg,1        ; yes, set flag
  871.     mov    kbicsr,dx        ; save old cursor
  872.     mov    ttkbi,0            ; clear this flag
  873.  
  874. anstt2:    test    anspflg,vtcntp        ; print controller on?
  875.     jz    anstt4            ; z = no
  876.     test    yflags,capt        ; capturing output?
  877.     jz    anstt3            ; z = no, forget this part
  878.     push    ax            ; save char
  879.     call    cptchr            ; give it captured character
  880.     pop    ax            ; restore character
  881. anstt3:    jmp    ttstate            ; print transparently
  882.  
  883. anstt4:    or    al,al            ; NUL char?
  884.     jz    atign            ; z = yes, ignore it before logging
  885.     test    yflags,capt        ; capturing output?
  886.     jz    anstt8            ; z = no, forget this part
  887.     push    ax            ; save char
  888.     call    cptchr            ; give it captured character
  889.     pop    ax            ; restore character and keep going
  890.                     ; Direct char to processor module
  891. anstt8:    cmp    vtemu.vtchset,12    ; ASCII (0) or NRC's (1-12) active?
  892.     ja    anstt8b            ; a = no
  893.     cmp    vtemu.vtchset,0        ; ASCII?
  894.     je    anstt8b            ; e = yes
  895.     and    al,7fh            ; yes, NRCs force chars to 7-bits
  896. anstt8b:test    al,not 9fh        ; control chars (0-1fh, 80h-9fh)?
  897.     jnz    anstt9            ; nz = no
  898.     jmp    atctrl            ; process control chars
  899. anstt9:    jmp    ttstate            ; dispatch according to state
  900. anstty    endp
  901.  
  902. atign:    ret                ; something to be ignored
  903.  
  904. atnorm: mov    ttstate,offset atnrm    ; reset state to "normal"
  905.     mov    ttstateST,offset atnorm    ; reset state for ST seen
  906.     ret
  907.             
  908. atnrm    proc    near            ; Normal character (in AL) processor
  909.     cmp    rxtable+256,0        ; TRANSLATION INPUT turned off?
  910.     je    atnrm14            ; e = yes, use ISO mechanisms
  911.     mov    bx,offset rxtable    ; address of translate table
  912.     mov    ah,al            ; copy char
  913.     xlatb                ; new char is in al
  914.     cmp    ah,al            ; different (translation requested)?
  915.     jne    short atnrm13        ; ne = yes, skip ISO-2022 mechanism
  916. atnrm14:cmp    SSptr,0            ; single shift needed?
  917.     je    atnrm10            ; e = no
  918.     and    al,not 80h        ; strip high bit
  919.     mov    bx,SSptr        ; pointer to desired char set
  920.     mov    SSptr,0            ; clear single shift indicator
  921.     jmp    short atnrm12        ; process
  922.  
  923. atnrm10:test    al,80h            ; high bit set for GRight?
  924.     jnz    atnrm11            ; nz = yes
  925.     mov    bx,GLptr        ; GL char set
  926.     jmp    short atnrm12        ; process
  927.  
  928. atnrm11:and    al,not 80h        ; strip high bit
  929.     mov    bx,GRptr        ; GR char set
  930.  
  931. atnrm12:xlatb                ; translate al to new char in al
  932. atnrm13:cmp    al,DEL            ; ANSI Delete char?
  933.     jne    atnrm2            ; ne = no
  934.     ret                ; ignore DEL
  935.                     ; use atnrm2: for debug simple tty dsp
  936. atnrm2:    mov    dx,cursor        ; get cursor virtual position
  937.     push    ax            ; save character
  938.     call    atscur            ; set cursor physical position
  939.     pop    ax
  940.     cmp    insmod,0        ; insert mode off?
  941.     je    atnrm3            ; e = yes
  942.     push    ax
  943.     call    inschr            ; open a char space in this line
  944.     push    bx
  945.     mov    bx,cursor        ; get current row
  946.     mov    bl,bh
  947.     xor    bh,bh
  948.     cmp    linetype [bx],0        ; single width line?
  949.     je    atnrm2a            ; e = yes
  950.     call    inschr            ; open second space for double width
  951. atnrm2a:pop    bx
  952.     pop    ax            ; restore char
  953.                     ; set cursor before writing char
  954. atnrm3:    mov    bl,dh            ; check for double characteristic
  955.     xor    bh,bh            ; bx = row, in bl
  956.     test    anspflg,vtautop        ; printing desired?
  957.     jz    atnrm4d            ; e = no
  958.     call    pntchr            ; print char in al
  959.     cmp    linetype [bx],0        ; normal characteristic?
  960.     je    atnrm4d            ; e = yes
  961.     push    ax            ; save current char
  962.     mov    al,' '            ; add a space for double width
  963.     call    pntchr
  964.     pop    ax            ; recover char to be processed
  965. atnrm4d:
  966.     cmp    linetype [bx],0        ; normal characteristic?
  967.     je    atnrm4a            ; e = yes
  968.     shl    dl,1            ; double the column number
  969.     push    dx
  970.     call    direction        ; set dx to desired position
  971.     call    setpos            ; set cursor position
  972.     pop    dx
  973.     mov    ah,curattr        ; current attribute
  974.     call    setatch            ; write char (al) and attribute (ah)
  975.     inc    dl            ; next column
  976.     push    dx
  977.     call    direction        ; set dx to desired position
  978.     call    setpos            ; set cursor position
  979.     pop    dx
  980.     mov    al,' '            ; use a space for doubling
  981.     mov    ah,curattr        ; current attribute
  982.     call    setatch            ; write char (al) and attribute (ah)
  983.     shr    dl,1            ; keep "cursor" in single units
  984.     jmp    atnrm4b            ; check autowrap in double width mode
  985.  
  986. atnrm4a:mov    ah,curattr        ; current attribute
  987.     call    setatch            ; write char (al) and attribute (ah)
  988.                     ; set physical cursor after this char
  989. atnrm4b:test    vtemu.vtflgop,decawm    ; Autowrap active?
  990.     jz    atnrm5            ; z = no
  991.     mov    cx,low_rgt        ; copy logical cursor margins to cx
  992.     push    bx
  993.     mov    bl,dh            ; get row
  994.     xor    bh,bh
  995.     cmp    linetype[bx],0        ; single width line?
  996.     pop    bx            ; pop preserves flags
  997.     je    atnrm4c            ; e = yes, single
  998.     shr    cl,1            ; halve right column # for wide chars
  999. atnrm4c:cmp    dl,cl            ; wrote in right-most column?
  1000.     jb    atnrm5            ; b = no
  1001.     inc    atwrap            ; turn on wrap flag
  1002.     inc    dl            ; say want to use next column
  1003.     cmp    flags.vtflg,ttheath    ; emulating a H-19? [uci]
  1004.     je    atscur            ; e = yes, show wrap now. [uci]
  1005.     mov    cursor,dx        ; virtual cursor position
  1006.     ret                ; exit without moving cursor from eol
  1007. atnrm5:    mov    dx,cursor        ; restore cursor position
  1008.     inc    dl            ; bump cursor
  1009.     mov    atwrap,0        ; say not about to wrap
  1010.  
  1011. atscur: cmp    dl,250            ; left of column zero? (wide screen)
  1012.     jb    atscu1            ; b = no, continue
  1013.     mov    dl,0            ; set at column zero
  1014. atscu1:    mov    cl,byte ptr low_rgt    ; copy logical margin; cl = right col
  1015.     push    bx
  1016.     mov    bl,dh            ; get row
  1017.     xor     bh,bh
  1018.     cmp    linetype [bx],0        ; single width lines?
  1019.     pop    bx
  1020.     je    atscu1a            ; e = yes, single width
  1021.     shr    cl,1            ; halve column # for double wides
  1022. atscu1a:cmp    dl,cl            ; right of right margin?
  1023.     jbe    atscu3            ; be = no, continue
  1024.     mov    dl,cl            ; assume no autowrap
  1025.     test    vtemu.vtflgop,decawm    ; Autowrap?
  1026.     jz    atscu3            ; z = no
  1027.     mov    dl,0            ; set to column zero
  1028.     cmp    dh,byte ptr low_rgt+1    ; at bottom of screen?
  1029.     je    atscu1b            ; e = yes
  1030.     cmp    dh,mar_bot        ; at bottom of scrolling region?
  1031.     jl    atscu2            ; l = No - bump cursor and continue
  1032. atscu1b:mov    scroll,1        ; scroll count = 1 line
  1033.     call    atscru            ; scroll up
  1034.     dec    dh            ; offset inc dh below
  1035. atscu2: inc    dh            ; just bump it
  1036. atscu3: or    dh,dh            ; constrain row to valid range
  1037.     jge    atscu4            ; ge = non-negative row, ok
  1038.     mov    dh,0
  1039. atscu4: cmp    dh,byte ptr low_rgt+1    ; 25th line?
  1040.     jle    atscu5            ; le = no
  1041.     mov    dh,byte ptr low_rgt+1    ; set to 24th line
  1042.     cmp    flags.vtflg,ttheath    ; emulating a Heath-19?
  1043.     jne    atscu4a            ; ne = no [hlk]
  1044.     test    h19stat,h19l25        ; Heath 25th line enabled?
  1045.     jz    atscu5            ; z = no
  1046. atscu4a:inc    dh            ; go to line 25 [hlk]
  1047.     test    yflags,modoff        ; is mode line off?
  1048.     jnz    atscu4b            ; nz = yes
  1049.     push    dx            ; save cursor position
  1050.     call    clrmod            ; clear the line
  1051.     or    yflags,modoff        ; now say it's off (owned by host)
  1052.     pop    dx
  1053. atscu4b:mov    flags.modflg,2        ; say mode line is owned by host
  1054.  
  1055. atscu5:    mov    cursor,dx        ; Set cursor and return
  1056.     push    dx
  1057.     mov    bl,dh            ; get row
  1058.     xor    bh,bh            ; clear high byte
  1059.     cmp    linetype [bx],0        ; single width line?
  1060.     je    atscu5a            ; e = yes
  1061.     shl    dl,1            ; double the column number
  1062. atscu5a:call    direction        ; set dx to desired position
  1063.     call    setpos            ; set cursor physical position
  1064.     pop    dx
  1065.     test    vtemu.vtflgop,vsmarginbell; do we care about margin bell?
  1066.     jz    atscu6            ; z = no, return if no margin bell
  1067.     cmp    kbiflg,0        ; is keyboard input flag set?
  1068.     je    atscu6            ; e = no, just return
  1069.     mov    bx,kbicsr        ; cursor at previous keyboard input
  1070.     cmp    bh,dh            ; same row as now?
  1071.     jne    atscu6            ; ne = no, just return
  1072.     cmp    bl,belcol        ; old cursor at or left of bell column?
  1073.     ja    atscu6            ; a = no, just return
  1074.     cmp    dl,belcol        ; new cursor past bell column?
  1075.     jbe    atscu6            ; be = no, just return
  1076.     call    vtbell            ; ring the bell
  1077. atscu6:    ret
  1078. atnrm    endp
  1079.  
  1080. ; Control-character dispatcher
  1081. atctrl:    cmp    al,escape        ; an escape sequence starting?
  1082.     je    atctrl1            ; e = yes, don't print it
  1083.     cmp    al,CSI            ; this kind of escape?
  1084.     je    atctrl1            ; e = yes
  1085.     test    anspflg,vtautop+vtcntp    ; printing desired?
  1086.     jz    atctrl1            ; z = no
  1087.     call    pntchr            ; print char in al
  1088. atctrl1:xor    ah,ah            ; clear for word use below
  1089.     test    al,80h            ; high bit set?
  1090.     jnz    atctrl2            ; nz = yes
  1091.     mov    di,ax            ; use AL as a word index
  1092.     shl    di,1
  1093.     jmp    ansc0[di]        ; dispatch on C0 control codes
  1094. atctrl2:and    al,not 80h        ; strip high bit
  1095.     mov    di,ax            ; use AL as a word index
  1096.     shl    di,1
  1097.     jmp    ansc1[di]        ; dispatch on C1 control codes
  1098.  
  1099. ; Control code routines
  1100. atbs:    or    dl,dl            ; Backspace, too far?
  1101.     jz    atbs1            ; z = at column 0 already
  1102.     dec    dl            ; backup cursor
  1103. atbs1:    call    atccpc            ; check range
  1104.     jmp    atscu5            ; set cursor and return
  1105.  
  1106. atht:    cmp    flags.vtflg,ttheath    ; Horizontal Tab, Heath-19 mode?
  1107.     je    atht2            ; e = yes, handle specially
  1108.     xor    ch,ch
  1109.     mov    cl,byte ptr low_rgt
  1110.     cmp    dl,cl            ; at or beyond last column?
  1111.     jae    atbs1            ; ae = yes check range, set cursor
  1112. atht1:    inc    dl            ; tab always moves at least one column
  1113.     push    si
  1114.     mov    si,vtemu.vttbst        ; active buffer
  1115.     call    istabs            ; returns carry set if at a tabstop
  1116.     pop    si
  1117.     jc    atht1a            ; c = at a tabstop
  1118.     loopz    atht1
  1119. atht1a:    jmp    atbs1            ; check range, set cursor, and return
  1120.  
  1121. atht2:    mov    dx,cursor        ; Heath-19. get cursor position
  1122.     add    dl,8            ; tabs are every 8 columns
  1123.     and    dl,not 7        ; do modulo 8
  1124.     cmp    dl,byte ptr low_rgt    ; check against right edge
  1125.     jbe    atht3            ; be = in range
  1126.     mov    dl,byte ptr low_rgt    ; else go to right margin
  1127. atht3:    jmp    atscu5            ; set cursor and return
  1128.  
  1129. atlf:    test    vtemu.vtflgop,anslnm    ; Line Feed, New-line mode?
  1130.     jz    atlf2            ; z = no, just move to next line down
  1131.     xor    dl,dl            ; move to left margin also
  1132. atlf2:    inc    dh            ; index line down
  1133.     call    atccic            ; check indexing
  1134.     call    ax            ; call scrolling routine
  1135.     jmp    atscu5            ; set cursor
  1136.  
  1137. atcr:    xor    dl,dl            ; Carriage Return, go to left margin
  1138.     cmp    flags.vtflg,ttheath    ; Heath-19?
  1139.     jne    atcr1            ; ne = no
  1140.     test    h19stat,h19alf        ; auto line feed on?
  1141.     jnz    atlf2            ; nz = yes, do the LF part above
  1142. atcr1:    jmp    atscu5            ; set cursor and return
  1143.  
  1144. atff:    cmp    ttstate,offset atescf    ; Form Feed, parsing escape sequence?
  1145.     jne    atlf            ; ne = no, do as line feed
  1146.     test    denyflg,tekxflg        ; is auto Tek mode disabled?
  1147.     jnz    atlf            ; nz = yes, treat as line feed
  1148.     call    atsc            ; save cursor and associated data
  1149.     mov    al,escape
  1150.     call    TEKEMU
  1151.     mov    al,FF
  1152.     call    TEKEMU            ; feed to Tektronix Emulator, al=FF
  1153.     jmp    atnorm
  1154.  
  1155. atcan:    mov    ttstate,offset atnrm    ; CAN, say doing normal chars
  1156.     mov    parstate,0        ; clear esc seq parser
  1157.     ret
  1158.  
  1159. atesc:    mov    ttstate,offset atescf    ; ESC, next state is escape follower
  1160.     ret
  1161.  
  1162. ; Respond to character following Escape, dispatch on that char
  1163. atescf:    call    atpclr            ; clear parser argument list
  1164.     mov    bx,offset ansesc    ; ANSI escape table
  1165.     cmp    flags.vtflg,ttvt320    ; VT320?
  1166.     je    atescf2            ; e = yes
  1167.     cmp    flags.vtflg,ttvt100    ; VT100?
  1168.     je    atescf2            ; e = yes
  1169.     mov    bx,offset v52esc    ; VT52 escape table
  1170.     cmp    flags.vtflg,ttvt52    ; VT52?
  1171.     je    atescf1            ; e = yes
  1172.     mov    bx,offset h19esc    ; use Heath-19 table
  1173.     cmp    flags.vtflg,ttheath    ; Heath-19?
  1174.     je    atescf1            ; e = yes
  1175.     ret                ; return on error
  1176. atescf1:mov    ttstate,offset atnrm    ; reset state to "normal"
  1177.     jmp    atdispat        ; perform dispatch via table in BX
  1178.  
  1179. atescf2:mov    bx,offset ansesc    ; ANSI escape table, for atdispat
  1180.     test    al,not (2fh)        ; in intermediates (column 2)?
  1181.     jnz    atescf1            ; nz = no, dispatch on this char
  1182.     mov    ttstate,offset atescf2    ; stay in this state til col 3 or more
  1183.     mov    bx,ninter        ; number of intermediates
  1184.     cmp    bx,maxinter        ; done enough already?
  1185.     jae    atescf3            ; ae = yes, ignore the excess
  1186.     mov    inter[bx],al        ; store this one
  1187.     inc    ninter            ; one more
  1188. atescf3:ret                ; get more input
  1189.  
  1190.                     ; CSI, char 9bh (ANSI CSI == ESC [)
  1191. atcsi:    mov    ttstate,offset atparse    ; next state is parse control seq
  1192.     mov    pardone,offset atcsi1    ; where to jmp when done
  1193.     mov    parfail,offset atnorm    ; where to jmp if failure
  1194.     ret                ; get next char
  1195. atcsi1:    mov    bx,offset anstab    ; ANSI Final character table
  1196.     mov    ttstate,offset atnrm    ; reset state to "normal"
  1197.     jmp    atdispat        ; dispatch on character
  1198.  
  1199. h19csi:    test    vtemu.vtflgop,decanm    ; Heath-19 "ESC [", is ANSI mode on?
  1200.     jnz    h19csi1            ; nz = yes
  1201.     mov    ttstate,offset atnrm    ; else ignore the "[" (kbd lock)
  1202.     ret
  1203. h19csi1:mov    ttstate,offset atparse    ; H-19, ESC [ parser
  1204.     mov    pardone,offset h19csi2     ; where to jmp when done
  1205.     mov    parfail,offset atnorm    ; where to jmp if failure
  1206.     ret                ; get next char
  1207. h19csi2:mov    bx,offset h19ans    ; H-19 ANSI Final character table
  1208.     mov    ttstate,offset atnrm    ; reset state to "normal"
  1209.     jmp    atdispat        ; dispatch on character
  1210.  
  1211. ; Process Device Control Strings (DCS or ESC P lead-in chars, already read).
  1212. atdcs:    mov    ttstate,offset atparse    ; next state is parse control seq
  1213.     mov    pardone,offset atdcs1    ; where to jmp when done
  1214.     mov    parfail,offset atnorm    ; where to jmp if failure
  1215.     ret
  1216. atdcs1:    mov    dcsstrf,al        ; record Final char
  1217.     mov    emubufc,0        ; clear string count
  1218.     mov    cx,maxparam        ; number of DCS parameters
  1219.     push    si            ; copy these to the DCS area so that
  1220.     push    di            ;  they are not lost when an ST is
  1221.     push    es            ;  parsed (parser clears ESC items)
  1222.     push    ds
  1223.     pop    es
  1224.     mov    si,offset param        ; ESC paramater storage area, numeric
  1225.     mov    di,offset dparam    ; DCS parameter storage area, numeric
  1226.     cld
  1227.     rep    movsw            ; copy set to DCS storage area
  1228.     mov    cl,lparam         ; copy letter Paramter
  1229.     mov    dlparam,cl
  1230.     mov    cx,maxinter        ; number of intermediate characters
  1231.     mov    si,offset inter        ; source
  1232.     mov    di,offset dinter    ; destination
  1233.     rep    movsb
  1234.     mov    si,nparam        ; number of parameters
  1235.     mov    dnparam,si
  1236.     mov    si,ninter
  1237.     mov    dninter,si        ; number of intermediates
  1238.     pop    es
  1239.     pop    di
  1240.     pop    si
  1241.     mov    ttstateST,offset atnorm ; default ST completion state
  1242.     mov    emubufc,0        ; clear processed string length
  1243.     mov    al,dcsstrf        ; get DCS Final char
  1244.     mov    bx,offset dcstab    ; DCS dispatch table
  1245.     call    atdispat        ; go to DCS handler
  1246.     ret
  1247.  
  1248. ; Process ST or ESC \  String Terminator.
  1249. atgotst:jmp    ttstateST        ; go to state for ST arrival
  1250.  
  1251. ; Read and discard OSC (ESC ]), PM (ESC ^), APC (ESC _) control sequences
  1252. ; through final ST (ESC \) terminator.
  1253. atdcsnul:mov    dcsstrf,0        ; simulate a null (dummy) Final char
  1254.     mov    emubufc,0        ; clear string count
  1255.     mov    ttstate,offset atdcsnul1 ; keep coming here
  1256.     mov    ttstateST,offset atnorm    ; where to go when ST has been seen
  1257. atdcsnul1:ret                ; consume chars
  1258.  
  1259. ; User Definable Key processor of DCS strings.
  1260. atudk:    cmp    dinter,0        ; no intermediates?
  1261.     je    atudk1            ; e = correct
  1262.     jmp    atdcsnul        ; bad, consume the rest
  1263.  
  1264. atudk1:    cmp    dparam,1        ; is initial Parameter Pc a 1?
  1265.     jae    atudk2            ; ae = yes, clear only this key
  1266.     call    udkclear        ; clear all UDKeys
  1267.     mov    dparam,1        ; and turn off Parameter
  1268. atudk2:    mov    ttstate,offset atudk3    ; next state is get a substring
  1269.     mov    ttstateST, offset atudk6 ; for when ST has been seen
  1270.     ret
  1271.  
  1272. atudk3:    cmp    al,';'            ; string separator?
  1273.     je    atudk5            ; e = yes, process string to-date
  1274.     mov    bx,emubufc        ; count of chars in string buffer
  1275.     cmp    bx,emubufl        ; too many?
  1276.     jae    atudk4            ; ae = too many, ignore extras
  1277.     mov    emubuf[bx],al        ; store the char
  1278.     inc    emubufc            ; count it
  1279. atudk4:    ret
  1280. atudk5:    mov    si,offset emubuf    ; address of string buffer is DS:SI
  1281.     mov    cx,emubufc        ; count of buffer contents
  1282.     call    setudk            ; insert string definition
  1283.     mov    emubufc,0        ; clear string buffer
  1284.     ret
  1285. atudk6:    call    atudk5            ; ST seen, process last string
  1286.     jmp    atnorm            ; reset state to normal
  1287.  
  1288. ; Call this routine to deliver Parameters in succession. Each call points to
  1289. ; a Parameter as param[si], where si is maintained here. If there are no
  1290. ; Parameters the effect is the same as one Parameter with a value of zero.
  1291. ; Enter with di = offset of action routine to be called for each Parameter.
  1292. ; cx, si, and di are preserved over the call to the action routine.
  1293.  
  1294. atreps    proc    near
  1295.     mov    si,0            ; initialize parm index
  1296.     mov    cx,nparam        ; number of Parameters
  1297.     or    cx,cx            ; zero?
  1298.     jnz    atrep1            ; nz = no
  1299.     inc    cx            ; zero parms is same as 1
  1300. atrep1: push    cx            ; save loop counter
  1301.     push    si            ; save parameter index
  1302.     push    di            ; save call vector
  1303.     call    DI            ; call indicated routine
  1304.     pop    di            ; restore registers
  1305.     pop    si
  1306.     pop    cx
  1307.     add    si,2            ; advance to next parameter
  1308.     loop    atrep1            ; loop for all
  1309.     ret
  1310. atreps    endp
  1311.  
  1312.                     ; Action routines
  1313. atind:    inc    dh            ; IND (index), move cursor down one
  1314. atind1: call    atccic            ; check cursor position
  1315.     call    ax            ; scroll if necessary
  1316.     jmp    atscu5            ; set cursor, etc. and return
  1317.  
  1318. atnel:    xor    dl,dl            ; NEL, next line - sort of like CRLF
  1319.     inc    dh            ; ... all in one command
  1320.     jmp    atind1            ; check cursor, etc., and return
  1321.  
  1322. atri:     cmp    flags.vtflg,ttheath    ; Heath-19?
  1323.     jne    atri1            ; ne = no
  1324.     cmp    dh,byte ptr low_rgt+1    ; on 25th line?
  1325.     jbe    atri1            ; be = no
  1326.     ret                ; no vertical for Heath on 25th line
  1327. atri1:    dec    dh            ; RI, reverse index
  1328.     jmp    atind1            ; check cursor, etc., and return
  1329.  
  1330.                     ; HTS, horizontal tab set in this col
  1331. athts:    call    atccpc            ; make column number valid
  1332.     mov    si,vtemu.vttbst        ; active buffer
  1333.     jmp    tabset            ; say set tab in this column (DL)
  1334.                     ; DECSC
  1335. atsc:    mov    si,offset savelist    ; save cursor, attribute, char set etc
  1336.     mov    di,offset savecu    ; place to save the stuff
  1337.     mov    cx,lsavecu        ; length of save area
  1338.     push    es            ; save es
  1339.     push    ds
  1340.     pop    es            ; set es to data segment
  1341.     cld
  1342.     shr    cx,1            ; divide by two for word moves
  1343.     jnc    atsc1            ; nc = even number of bytes
  1344.     movsb                ; do the odd byte
  1345. atsc1:    rep    movsw            ; save it
  1346.     pop    es
  1347.     mov    cx,vtemu.vtflgop    ; save a copy of the flags
  1348.     mov    savflgs,cx
  1349.     ret
  1350.                     ; DECRC
  1351. atrc:    mov    si,offset savecu    ; restore cursor, attributes, etc
  1352.     mov    di,offset savelist    ; where stuff goes
  1353.     mov    cx,lsavecu        ; length of save area
  1354.     push    es            ; save es
  1355.     push    ds
  1356.     pop    es            ; set es to data segment
  1357.     cld
  1358.     shr    cx,1            ; divide by two for word moves
  1359.     jnc    atrc1            ; nc = even number of bytes
  1360.     movsb                ; do the odd byte
  1361. atrc1:    rep    movsw            ; put the stuff back
  1362.     pop    es
  1363.     mov    ax,savflgs        ; get saved flags
  1364.     xor    ax,vtemu.vtflgop    ; exclusive-or with current flags
  1365.     test    ax,vsscreen        ; did screen mode change?
  1366.     jz    atrc3            ; z = no, reset saved flags and leave
  1367.     mov    ah,curattr        ; get cursor attribute that was saved
  1368.     call    revideo            ; get reversed video attributes (AH)
  1369.     mov    curattr,ah        ; store
  1370. atrc3:    mov    ax,vtemu.vtflgop    ; reset flags in case called again
  1371.     and    ax, not(decckm+deckpam+decom)  ; remove old bits [dlk]
  1372.     and    savflgs,(decckm+deckpam+decom) ; remove all but new bits [dlk]
  1373.     or    ax,savflgs        ; restore saved bits [dlk]
  1374.     mov    vtemu.vtflgop,ax    ; update these flags [dlk]
  1375.     mov    savflgs,ax
  1376.     mov    dx,cursor        ; get cursor
  1377.     mov    kbiflg,0        ; don't bother them with beeps here
  1378.     jmp    atscu5            ; set cursor
  1379.  
  1380. atkpam: or    vtemu.vtflgop,deckpam    ; turn on keypad applications mode
  1381.     ret
  1382.  
  1383. atkpnm: and    vtemu.vtflgop,not deckpam ; turn off keypad applications mode
  1384.     ret
  1385.  
  1386.  
  1387. atpriv:    mov    ttstate,offset atnorm    ; ignore next char
  1388.     ret                ; and return to normal afterward
  1389.  
  1390. ; ISO 2022 three byte Announcer Summary    <ESC> <space> <final char>
  1391. ;Esc Sequence  7-Bit Environment          8-Bit Environment
  1392. ;----------    ------------------------   ----------------------------------     
  1393. ;<ESC><SP>A    G0->GL                     G0->GL
  1394. ;<ESC><SP>B    G0-(SI)->GL, G1-(SO)->GL   G0-(LS0)->GL, G1-(LS1)->GL
  1395. ;<ESC><SP>C    (not used)                 G0->GL, G1->GR
  1396. ;<ESC><SP>D    G0-(SI)->GL, G1-(SO)->GL   G0->GL, G1->GR
  1397. ;<ESC><SP>E    Full preservation of shift functions in 7 & 8 bit environments
  1398. ;<ESC><SP>F    C1 represented as <ESC>F   C1 represented as <ESC>F
  1399. ;<ESC><SP>G    C1 represented as <ESC>F   C1 represented as 8-bit quantity
  1400. ;<ESC><SP>H    All graphic character sets have 94 characters
  1401. ;<ESC><SP>I    All graphic character sets have 94 or 96 characters
  1402. ;<ESC><SP>J    In a 7 or 8 bit environment, a 7 bit code is used
  1403. ;<ESC><SP>K    In an 8 bit environment, an 8 bit code is used
  1404. ;<ESC><SP>L    Level 1 of ISO 4873 is used
  1405. ;<ESC><SP>M    Level 2 of ISO 4873 is used
  1406. ;<ESC><SP>N    Level 3 of ISO 4873 is used
  1407. ;<ESC><SP>P    G0 is used in addition to any other sets:
  1408. ;              G0 -(SI)-> GL              G0 -(LS0)-> GL
  1409. ;<ESC><SP>R    G1 is used in addition to any other sets:
  1410. ;              G1 -(SO)-> GL              G1 -(LS1)-> GL
  1411. ;<ESC><SP>S    G1 is used in addition to any other sets:
  1412. ;              G1 -(SO)-> GL              G1 -(LS1R)-> GR
  1413. ;<ESC><SP>T    G2 is used in addition to any other sets:
  1414. ;              G2 -(LS2)-> GL             G2 -(LS2)-> GL
  1415. ;<ESC><SP>U    G2 is used in addition to any other sets:
  1416. ;              G2 -(LS2)-> GL             G2 -(LS2R)-> GR
  1417. ;<ESC><SP>V    G3 is used in addition to any other sets:
  1418. ;              G3 -(LS2)-> GL             G3 -(LS3)-> GL
  1419. ;<ESC><SP>W    G3 is used in addition to any other sets:
  1420. ;              G3 -(LS2)-> GL             G3 -(LS3R)-> GR
  1421. ;<ESC><SP>Z    G2 is used in addition to any other sets:
  1422. ;              SS2 invokes a single character from G2
  1423. ;<ESC><SP>[    G3 is used in addition to any other sets:
  1424. ;              SS3 invokes a single character from G3
  1425. ;
  1426. ; ISO Escape Sequences for Alphabet Designation ("F" = Final char)
  1427. ; Sequence     Function                                         Invoked By
  1428. ;  <ESC>(F     assigns 94-character graphics set "F" to G0.     SI  or LS0
  1429. ;  <ESC>)F     assigns 94-character graphics set "F" to G1.     SO  or LS1
  1430. ;  <ESC>*F     assigns 94-character graphics set "F" to G2.     SS2 or LS2
  1431. ;  <ESC>+F     assigns 94-character graphics set "F" to G3.     SS3 or LS3
  1432. ;  <ESC>-F     assigns 96-character graphics set "F" to G1.     SO  or LS1
  1433. ;  <ESC>.F     assigns 96-character graphics set "F" to G2.     SS2 or LS2
  1434. ;  <ESC>/F     assigns 96-character graphics set "F" to G3.     SS3 or LS3
  1435. ;  <ESC>$(F    assigns multibyte character set "F" to G0.       SI  or LS0
  1436. ;  <ESC>$)F    assigns multibyte character set "F" to G1.       SO  or LS1
  1437. ;  <ESC>$*F    assigns multibyte character set "F" to G2.       SS2 or LS2
  1438. ;  <ESC>$+F    assigns multibyte character set "F" to G3.       SS3 or LS3
  1439. ;     
  1440. ; Designate character sets, AL has final character, inter has all preceeding.
  1441.  
  1442. atdgfA:    call    atdgset            ; 'A' ISO Latin-1, UK-ASCII
  1443.     jc    atdgfA1            ; c = no matching pointer
  1444.     cmp    inter,'+'        ; in the 94 byte set?
  1445.     ja    atdgfA2            ; a = no
  1446.     cmp    flags.vtflg,ttvt100    ; doing a VT102?
  1447.     jne    atdgfA1            ; ne = no
  1448.     call    chrinit            ; UK-ASCII
  1449.     mov    di,setptr        ; get set pointer
  1450.     mov    byte ptr[di+23h],156    ; replace sharp 2/3 with Sterling sign
  1451.     mov    byte ptr[di+gsize],94    ; say this is a 94 byte set
  1452.     mov    byte ptr[di+gsize+1],'A' ; set ident code
  1453.     mov    byte ptr[di+gsize+2],0
  1454. atdgfA1:ret
  1455. atdgfA2:call    latin1            ; set si to Latin-1 table offset
  1456.     jmp    cpyset
  1457.  
  1458. atdgfB:    call    atdgset            ; 'B' ASCII, get setptr from inter
  1459.     jc    atdgfA1            ; c = no matching pointer
  1460.     cmp    inter,'+'        ; in the 94 byte set?
  1461.     ja    atdgfA1            ; a = no, ignore
  1462.     jmp    chrinit            ; init the set to ASCII
  1463.  
  1464. atdgf0:    call    atdgset            ; '0', '2', DEC Special Graphics
  1465.     jc    atdgfA1            ; c = no matching pointer
  1466.     cmp    inter,'+'        ; in the 94 byte set?
  1467.     ja    atdgfA1            ; a = no, ignore
  1468. atdg52:    call    chrinit            ; init set to ASCII
  1469.     push    si
  1470.     push    di
  1471.     push    es
  1472.     push    ds
  1473.     pop    es            ; point es at data segment
  1474.     mov    di,setptr        ; address of char set table
  1475.     add    di,95            ; replace chars 95-126, skip controls
  1476.     mov    si,offset sgrtab    ; special graphics table
  1477.     mov    cx,sgrtabl        ; table length
  1478.     cmp    flags.vtflg,ttheath    ; Heath-19 rather than VT52?
  1479.     jne    atdgf53            ; ne = no, not a Heath
  1480.     mov    si,offset hgrtab    ; use Heath-19 table
  1481.     mov    cx,hgrtabl
  1482.     dec    di            ; replace chars 94-126
  1483. atdgf53:cld
  1484.     rep    movsb            ; replace chars with <s|h>grtab items
  1485.     mov    di,setptr
  1486.     mov    byte ptr[di+gsize],94    ; say this is a 94 byte set
  1487.     mov    byte ptr[di+gsize+1],'0' ; set ident code
  1488.     mov    byte ptr[di+gsize+2],0
  1489.     pop    es
  1490.     pop    di
  1491.     pop    si
  1492.     ret
  1493.  
  1494. atdgf1:    call    atdgset            ; '1' ALT-ROM
  1495.     jc    atdgfA1            ; c = no matching pointer
  1496.     call    chrinit            ; init set to ASCII
  1497.     push    si
  1498.     push    di
  1499.     push    es
  1500.     push    ds
  1501.     pop    es            ; point es at data segment
  1502.     mov    di,setptr
  1503.     add    di,60h            ; replace a..z with 20h + (a..z)
  1504.     mov    si,di            ; special graphics table
  1505.     mov    cx,27            ; number of chars to do (a..z)
  1506.     cld
  1507. atdgf1a:lodsb                ; get a char
  1508.     add    al,20h            ; map up by 20h
  1509.     stosb
  1510.     loop    atdgf1a
  1511.     mov    di,setptr
  1512.     mov    byte ptr[di+gsize],96    ; say this is a 96 byte set
  1513.     mov    byte ptr[di+gsize+1],'1' ; set ident code
  1514.     mov    byte ptr[di+gsize+2],0
  1515.     pop    es
  1516.     pop    di
  1517.     pop    si
  1518.     ret
  1519.  
  1520. atdgft:    call    atdgset            ; '>' Dec Technical Set
  1521.     jc    atdgft1            ; c = no matching pointer
  1522.     cmp    inter,'+'        ; in the 94 byte set?
  1523.     ja    atdgft1            ; a = no
  1524.     mov    si,offset dectech    ; source data
  1525.     jmp    cpyset            ; copy the set
  1526. atdgft1:cmp    ninter,0        ; ESC >  set numeric keypad?
  1527.     jne    atdgft2            ; ne = no
  1528.     and    vtemu.vtflgop,not deckpam ; turn off application keypad bit
  1529. atdgft2:ret
  1530.                     ; '<' User Preferred Supplemental Set
  1531. atdgfu:    call    atdgset            ; get set pointer
  1532.     jc    atdgfu3            ; c = no matching pointer
  1533.     cmp    inter,','        ; designating the 96 char set?
  1534.     jb    atdgfu1            ; b = no, want 94
  1535.     call    latin1            ; set si to Latin-1 table offset
  1536.     cmp    word ptr upss+1,0+'A'    ; is ISO Latin-1 the preferred set?
  1537.     je    atdgfu2            ; e = yes, set it up
  1538.     jmp    atdgfu3            ; else do nothing
  1539. atdgfu1:call    decsupg            ; SI=source data is DEC Supplement Gr.
  1540.     cmp    word ptr upss+1,'5%'    ; DEC Supplemental Graphics?
  1541.     jne    atdgfu3            ; ne = no
  1542. atdgfu2:jmp    cpyset            ; copy the set
  1543. atdgfu3:ret
  1544.  
  1545. atdgfq:    call    atdgset            ; '?' Transparent
  1546.     jc    atdgfu3            ; c = no matching pointer
  1547.     call    chrinit            ; init set to ASCII
  1548.     push    si
  1549.     push    di
  1550.     push    es
  1551.     push    ds
  1552.     pop    es            ; point es at data segment
  1553.     mov    di,setptr        ; point at character set
  1554.     mov    si,di            ; 
  1555.     mov    cx,gsize        ; number of chars to do, 128
  1556.     cld
  1557. atdgfq1:lodsb                ; get a char
  1558.     add    al,80h            ; map up by 80h
  1559.     stosb
  1560.     loop    atdgfq1
  1561.     mov    di,setptr
  1562.     mov    byte ptr[di+gsize],96    ; say this is a 96 byte set
  1563.     mov    byte ptr[di+gsize+1],'?' ; set ident code
  1564.     mov    byte ptr[di+gsize+2],0
  1565.     pop    es
  1566.     pop    di
  1567.     pop    si
  1568.     ret
  1569.  
  1570.                     ; ESC <...> <1-8>  series
  1571. atsdhl:    cmp    ninter,1        ; just one intermediate?
  1572.     jne    atsdh0            ; ne = no
  1573.     cmp    inter,'#'        ; this intermediate?
  1574.     jne    atsdhx            ; ne = no, ignore
  1575.     cmp    al,'3'            ; Double high lines. Top half?
  1576.     je    atsdh2            ; e = yes
  1577.     cmp    al,'4'            ; bottom half?
  1578.     je    atsdh2            ; e = yes
  1579.     cmp    al,'5'            ; restore line to single width?
  1580.     je    atsdh1            ; e = yes
  1581.     cmp    al,'6'            ; double width single height?
  1582.     je    atsdh2            ; e = yes
  1583.     cmp    al,'8'            ; screen alignment?
  1584.     je    atsdh8            ; e = yes
  1585. atsdhx:    ret                ; else ignore
  1586. atsdh1:    jmp    linesgl            ; set line to single width
  1587. atsdh2:    jmp    linedbl            ; expand the line to double width
  1588. atsdh8:    jmp    atalign            ; do screen alignment
  1589.  
  1590. atsdh0:    cmp    ninter,0        ; zero intermediates?
  1591.     jne    atdgf5            ; ne = no, try for more
  1592.     cmp    al,'7'            ; save cursor?
  1593.     jne    atsdh0a            ; ne = no
  1594.     jmp    atsc            ; do save cursor, ESC 7
  1595. atsdh0a:cmp    al,'8'            ; restore cursor?
  1596.     jne    atsdh0b            ; ne = no
  1597.     jmp    atrc            ; do restore cursor, ESC 8
  1598. atsdh0b:ret
  1599.  
  1600. atdgf5:    cmp    ninter,2        ; two intermediates?
  1601.     jne    atdgf5a            ; ne = no, ignore remainder
  1602.     cmp    al,'5'            ; '%5' DEC Supplemental Graphic?
  1603.     jne    atdgf5a            ; ne = no
  1604.     cmp    inter,'+'        ; in the 94 byte set?
  1605.     ja    atdgf5a            ; a = no, ignore
  1606.     cmp    inter[1],'%'        ; '%5'?
  1607.     jne    atdgf5a            ; ne = no
  1608.     mov    ninter,1        ; help atdgset find our set
  1609.     call    atdgset            ; get set pointer
  1610.     jc    atdgf5a            ; c = no matching pointer
  1611.     call    decsupg            ; SI = source data
  1612.     jmp    cpyset            ; copy the set
  1613. atdgf5a:ret
  1614.                           ; worker for atdgf routines
  1615. atdgset:cmp    ninter,2        ; too many intermediates?
  1616.     ja    atdgsex            ; a = yes, ignore
  1617.     cmp    inter,'('        ; 94 char sets, designate G0?
  1618.     je    atdgse0            ; e = yes
  1619.     cmp    inter,')'        ; G1?
  1620.     je    atdgse1
  1621.     cmp    flags.vtflg,ttvt320    ; VT320?
  1622.     jne    atdgsex            ; ne = no, G2 & G3 fixed for VT102
  1623.     cmp    inter,'*'        ; G2?
  1624.     je    atdgse2
  1625.     cmp    inter,'+'        ; G3?
  1626.     je    atdgse3
  1627.     cmp    inter,'-'        ; 96 char sets, designate G1?
  1628.     je    atdgse1
  1629.     cmp    inter,'.'        ; G2?
  1630.     je    atdgse2
  1631.     cmp    inter,'/'        ; G3?
  1632.     je    atdgse3
  1633. atdgsex:stc                ; carry set for failure
  1634.     ret
  1635. atdgse0:mov    setptr,offset G0set    ; designate G0 set
  1636.     clc
  1637.     ret
  1638. atdgse1:mov    setptr,offset G1set    ; designate G1 set
  1639.     clc
  1640.     ret
  1641. atdgse2:mov    setptr,offset G2set    ; designate G2 set
  1642.     clc
  1643.     ret
  1644. atdgse3:mov    setptr,offset G3set    ; designate G3 set
  1645.     clc
  1646.     ret
  1647.                     ; S7C1T/S8C1T select 7/8-bit controls
  1648. ats7c:    cmp    flags.vtflg,ttvt320    ; in VT320 mode?
  1649.     jne    ats7ca            ; ne = no, ignore command
  1650.     cmp    ninter,1
  1651.     jne    ats7ca
  1652.     cmp    inter,' '        ; proper intermediate?
  1653.     jne    ats7ca            ; ne = no
  1654.     and    vtemu.vtflgop,not vscntl ; turn off 8-bit controls bit
  1655. ats7ca:ret                ; done
  1656.  
  1657. ats8c:    cmp    inter,' '        ; proper intermediate?
  1658.     jne    ats8ca            ; ne = no
  1659.     cmp    ninter,1
  1660.     jne    ats8ca
  1661.     or    vtemu.vtflgop,vscntl    ; turn on 8-bit controls bit
  1662. ats8ca:    ret
  1663.  
  1664. ; Designate User Preferred Supplemental Set as
  1665. ;  'A' ISO Latin-1  or  '%5' DEC Supplemental Graphics
  1666. ; Store the selection letters in array upss for later use by ESC <char> '<'
  1667. atupss:    cmp    word ptr dinter,0+'!'    ; "!u" proper intermediate?
  1668.     je    atupss0
  1669.     jmp    atdcsnul        ; consume unknown command
  1670. atupss0:mov    ah,94            ; assume 94 byte set
  1671.     cmp    dparam,1        ; 96 byte char size indicator?
  1672.     jb    atupss1            ; b = no, 94
  1673.     ja    atupss2            ; a = illegal Parameter
  1674.     mov    ah,96            ; say 96
  1675. atupss1:mov    upss,ah            ; store char set size
  1676.     mov    ttstateST,offset atupss4; where to go when ST has been seen
  1677.     mov    emubufc,0        ; clear buffer count
  1678.     mov    ttstate,offset atupss2    ; next state is get string
  1679.     ret
  1680. atupss2:mov    bx,emubufc        ; count of chars in string buffer
  1681.     cmp    bx,emubufl        ; too many?
  1682.     jae    atupss3            ; ae = too many, ignore extras
  1683.     mov    emubuf[bx],al        ; store the char
  1684.     inc    emubufc            ; count it
  1685. atupss3:ret
  1686. atupss4:mov    si,emubufc        ; count of chars in string
  1687.     mov    emubuf[si],0        ; terminate string in null
  1688.     mov    ax,word ptr emubuf    ; copy two chars from string to
  1689.     mov    word ptr upss+1,ax    ;  upss char set ident storage area
  1690.     mov    emubufc,0        ; clear the string count
  1691.     ret
  1692.  
  1693. ; Select/map character sets
  1694. atls0:    mov    GLptr,offset G0set    ; LS0,  map G0 char set into GLeft
  1695.     ret                ; Control-O
  1696. atls1:    mov    GLptr,offset G1set    ; LS1,  map G1 char set into GLeft
  1697.     ret                ; Control-N
  1698. atls1r:    cmp    ninter,0        ; any intermediate chars?
  1699.     jne    atlsx            ; ne = yes, not a Locking Shift
  1700.     mov    GRptr,offset G1set    ; LS1R, map G1 char set into GRight
  1701.     ret
  1702. atss2:    cmp    ninter,0        ; any intermediate chars?
  1703.     jne    atlsx            ; ne = yes, not a Single Shift
  1704.     mov    SSptr,offset G2set    ; SS2,  use G2 for next graphics only
  1705.     ret
  1706. atls2:    cmp    ninter,0        ; any intermediate chars?
  1707.     jne    atlsx            ; ne = yes, not a Locking Shift
  1708.     mov    GLptr,offset G2set    ; LS2,  map G2 char set into GLeft
  1709.     ret
  1710. atls2r:    cmp    ninter,0        ; any intermediate chars?
  1711.     jne    atlsx            ; ne = yes, not a Locking Shift
  1712.     mov    GRptr,offset G2set    ; LS2R, map G2 char set into GRight
  1713.     ret
  1714. atss3:    cmp    ninter,0        ; any intermediate chars?
  1715.     jne    atlsx            ; ne = yes, not a Single Shift
  1716.     mov    SSptr,offset G3set    ; SS3,  use G3 for next graphics only
  1717.     ret
  1718. atls3:    cmp    ninter,0        ; any intermediate chars?
  1719.     jne    atlsx            ; ne = yes, not a Locking Shift
  1720.     mov    GLptr,offset G3set    ; LS3,  map G3 char set into GLeft
  1721.     ret
  1722. atls3r:    cmp    ninter,0        ; any intermediate chars?
  1723.     jne    atlsx            ; ne = yes, not a Locking Shift
  1724.     mov    GRptr,offset G3set    ; LS3R, map G3 char set into GRight
  1725. atlsx:    ret
  1726.  
  1727. ; Initialize a char set to ASCII values 0..127 and ident of 94/B
  1728. ; Enter with setptr holding offset of G0set, G1set, G2set, or G3set char set
  1729. chrinit    proc    near
  1730.     push    ax
  1731.     push    cx
  1732.     push    di
  1733.     push    es
  1734.     mov    di,setptr        ; char set to init (G0..G3)
  1735.     mov    cx,gsize        ; number of bytes to do
  1736.     xor    al,al            ; initial value
  1737.     push    ds
  1738.     pop    es            ; set es to data segment
  1739.     cld
  1740. chrini1:stosb                ; copy value to char set table
  1741.     inc    al
  1742.     loop    chrini1
  1743.     mov    di,setptr
  1744.     mov    byte ptr[di+gsize],94    ; say this is a 94 byte set
  1745.     mov    byte ptr[di+gsize+1],'B' ; set ident code to ASCII "B"
  1746.     mov    byte ptr[di+gsize+2],0
  1747.     pop    es
  1748.     pop    di
  1749.     pop    cx
  1750.     pop    ax
  1751.     ret
  1752. chrinit    endp
  1753.  
  1754. ; copy gsize+3 bytes from (si) to (setptr)
  1755. cpyset    proc    near
  1756.     push    es
  1757.     push    ds
  1758.     pop    es
  1759.     cld
  1760.     mov    cx,gsize+3        ; gsize chars plus three ident bytes
  1761.     mov    di,setptr        ; destination
  1762.     rep    movsb
  1763.     pop    es
  1764.     ret
  1765. cpyset    endp
  1766.  
  1767. ; Move National Replacement Characters into all four tables.
  1768. ; Turns off vscntl (8-bit controls).
  1769. ; Places NRC chars in G0set, G1set, G2set, and G3set tables.
  1770. ; Also allows selection of ALT-ROM the same way, does not turn off vscntl.
  1771. setnrc    proc    near
  1772.     mov    cl,vtemu.vtchset    ; get country number
  1773.     xor    ch,ch
  1774.     or    cl,cl
  1775.     jnz    setnrc7
  1776.     ret                ; 0 is out of range
  1777. setnrc7:cmp    cl,12            ; 1-12 is the range
  1778.     jbe    setnrc1            ; be = in range
  1779.     cmp    vtemu.vtchset,13    ; want ALT-ROM?
  1780.     jne    setnrc8            ; ne = no
  1781.     mov    inter,'('        ; say ALT-ROM in G0 set
  1782.     mov    ninter,1        ; one intermediate char
  1783.     jmp    atdgf1            ; do ALT-ROM setup
  1784.  
  1785. setnrc8:cmp    vtemu.vtchset,14    ; Transparent (14)?
  1786.     jne    setnrc4            ; ne = no, unknown
  1787.     mov    inter,'.'        ; say 96 byte transparent in G2 set
  1788.     mov    ninter,1        ; one intermediate char
  1789.     jmp    atdgfq            ; do Transparent setup
  1790.  
  1791. setnrc1:test    vtemu.vtflgop,vsnrcm    ; doing National Replacement Chars?
  1792.     jz    setnrc4            ; z = no
  1793.     push    bx
  1794.     push    si
  1795.     push    di
  1796.     push    es
  1797.     push    ds
  1798.     pop    es
  1799.     and    vtemu.vtflgop,not vscntl ; turn off 8-bit controls
  1800.     call    nrc2cp            ; set si to table of NRC replacments
  1801.     sub    si,cx            ; minus one
  1802.     shl    cx,1            ; 15 bytes per NRC entry
  1803.     shl    cx,1
  1804.     shl    cx,1
  1805.     shl    cx,1
  1806.     add    si,cx            ; +16, source, point at this entry
  1807.     mov    cx,12            ; do first 12 bytes of them
  1808.     mov    setptr,offset G0set    ; destination, do G0set
  1809.     push    si
  1810.     push    cx
  1811.     call    setnrc5            ; do the setup
  1812.     pop    cx
  1813.     pop    si
  1814.     mov    setptr,offset G1set    ; do G1set
  1815.     push    si
  1816.     push    cx
  1817.     call    setnrc5            ; do the setup
  1818.     pop    cx
  1819.     pop    si
  1820.     cmp    flags.vtflg,ttvt320    ; VT320?
  1821.     jne    setnrc3            ; ne = no, no NRCs to G2 and G3
  1822.     mov    setptr,offset G2set    ; do G2set
  1823.     push    si
  1824.     push    cx
  1825.     call    setnrc5            ; do the setup
  1826.     pop    cx
  1827.     pop    si
  1828.     mov    setptr,offset G3set    ; do G3set
  1829.     call    setnrc5            ; do the setup
  1830. setnrc3:pop    es
  1831.     pop    di
  1832.     pop    si
  1833.     pop    bx
  1834. setnrc4:ret
  1835.  
  1836.                     ; worker routine
  1837. setnrc5:call    chrinit            ; init table to ascii
  1838.         ; copy from NRC table (si) to set pointed at by di, cx chars
  1839.     push    si            ;  plus 3 ident bytes at table end.
  1840.     call    nrc2cp            ; set si to NRC table
  1841.     mov    bx,si            ; bx = location of old chars
  1842.     pop    si
  1843.     cld
  1844.     xor    ah,ah
  1845. setnrc6:mov    al,[bx]            ; get location of new char
  1846.     inc    bx
  1847.     mov    di,setptr        ; start of destination table
  1848.     add    di,ax            ; destination of new char
  1849.     movsb                ; move replacement char from nrc list
  1850.     loop    setnrc6
  1851.     mov    di,setptr
  1852.     add    di,gsize        ; look at end of set, to id bytes
  1853.     movsw                ; copy set size and two ident chars
  1854.     movsb
  1855.     ret
  1856. setnrc    endp
  1857.  
  1858. ; Routine to set default character set.
  1859. chrdef    proc    near
  1860.            mov    GLptr,offset G0set    ; map G0 set to GLeft
  1861.     mov    GRptr,offset G2set    ; map G2 set to GRight
  1862.     mov    SSptr,0            ; clear single shift
  1863.     test    vtemu.vtflgop,vsnrcm    ; NRC's active?
  1864.     jz    chrdef1            ; z = no
  1865.     jmp    setnrc            ; nz = yes, set them
  1866. chrdef1:mov    setptr,offset G0set
  1867.     call    chrinit            ; make ASCII
  1868.     cmp    vtemu.vtchset,13    ; want default of ALT-ROM or Transpar
  1869.     jne    chrdef2            ; ne = no
  1870.     call    setnrc            ; use NRC code to setup G0
  1871. chrdef2:mov    setptr,offset G1set
  1872.     mov    si,offset G0set
  1873.     call    cpyset            ; copy G0set to G1set
  1874.     mov    setptr,offset G2set
  1875.     call    chrinit            ; make G2 = ASCII
  1876.     cmp    flags.vtflg,ttvt320    ; VT320?
  1877.     jne    chrdef3            ; ne = no, make G2 = G3 = ASCII
  1878.     call    latin1            ; set si to Latin-1 table offset
  1879.     cmp    vtemu.vtchset,15    ; SET TERM CHAR LATIN-1?
  1880.     je    chrdef2a        ; e = yes
  1881.     call    decsupg            ; else DEC Supplement Graph (DEC-MCS)
  1882.     cmp    vtemu.vtchset,0        ; SET TERM CHAR ASCII?
  1883.     je    chrdef3            ; e = yes, ascii in both halves
  1884. chrdef2a:call    cpyset            ; copy Latin-1 to G2
  1885. chrdef3:mov    setptr,offset G3set
  1886.     mov    si,offset G2set
  1887.     call    cpyset            ; copy G2set to G3set
  1888.     cmp    vtemu.vtchset,14    ; SET TERM CHAR TRANSPARENT?
  1889.     jne    chrdef4            ; ne = no
  1890.     mov    setptr,offset G2set
  1891.     call    setnrc            ; use NRC code to setup G2
  1892.     mov    setptr,offset G1set
  1893.     mov    si,offset G2set
  1894.     call    cpyset            ; copy G2set to G1set for VT100's
  1895.     ret
  1896. chrdef4:call    decsupg            ; source data is DEC Supplement Gr.
  1897.     cmp    word ptr upss+1,'5%'    ; DEC Supplemental Graphics?
  1898.     jne    chrdef5            ; ne = no
  1899.     mov    setptr,offset G2set    ; G2 to DEC Supp Gr
  1900.     call    cpyset            ; copy the set
  1901.     mov    setptr,offset G3set    ; G3 to DEC Supp Gr
  1902.     call    cpyset
  1903. chrdef5:ret
  1904. chrdef    endp
  1905.  
  1906. ; Set register SI to the offset of the ISO Latin-1 table appropriate to the
  1907. ; currently active Code Page. Defaults to CP437 if no CP found.
  1908. LATIN1    proc    near
  1909.     push    bx
  1910.     push    dx
  1911.     cmp    dosnum,0300h+30        ; DOS version 3.30 or higher?
  1912.     jb    latin1a            ; b = no, no Code Pages
  1913.     mov    ax,6601h        ; get global Code Page
  1914.     int    dos            ; bx=active Code Page, dx=boot CP
  1915.     cmp    bx,437            ; current Code Page is 437?
  1916.     je    latin1a            ; e = yes
  1917.     mov    si,offset L1cp850    ; assume CP850
  1918.     cmp    bx,850            ; current Code Page is 850?
  1919.     je    latin1x            ; e = yes
  1920.     mov    si,offset L1cp860    ; assume CP860
  1921.     cmp    bx,860            ; current Code Page is 860?
  1922.     je    latin1x            ; e = yes
  1923.     mov    si,offset L1cp863    ; assume CP863
  1924.     cmp    bx,863            ; current Code Page is 863?
  1925.     je    latin1x            ; e = yes
  1926.     mov    si,offset L1cp865    ; assume CP865
  1927.     cmp    bx,865            ; current Code Page is 865?
  1928.     je    latin1x            ; e = yes
  1929. latin1a:mov    si,offset L1cp437    ; default to CP437
  1930. latin1x:pop    dx
  1931.     pop    bx
  1932.     ret
  1933. LATIN1    endp
  1934.  
  1935. ; Set register SI to the offset of the DEC Multinational char set (DEC
  1936. ; Supplemental Graphics) table appropriate to the currently active Code Page.
  1937. ; Defaults to CP437 if no CP found.
  1938. DECSUPG    proc    near
  1939.     push    bx
  1940.     push    dx
  1941.     cmp    dosnum,0300h+30        ; DOS version 3.30 or higher?
  1942.     jb    decsu1a            ; b = no, no Code Pages
  1943.     mov    ax,6601h        ; get global Code Page
  1944.     int    dos            ; bx=active Code Page, dx=boot CP
  1945.     cmp    bx,437            ; current Code Page is 437?
  1946.     je    decsu1a            ; e = yes
  1947.     mov    si,offset MNcp850    ; assume CP850
  1948.     cmp    bx,850            ; current Code Page is 850?
  1949.     je    decsu1x            ; e = yes
  1950.     mov    si,offset MNcp860    ; assume CP860
  1951.     cmp    bx,860            ; current Code Page is 860?
  1952.     je    decsu1x            ; e = yes
  1953.     mov    si,offset MNcp863    ; assume CP863
  1954.     cmp    bx,863            ; current Code Page is 863?
  1955.     je    decsu1x            ; e = yes
  1956.     mov    si,offset MNcp865    ; assume CP865
  1957.     cmp    bx,865            ; current Code Page is 865?
  1958.     je    decsu1x            ; e = yes
  1959. decsu1a:mov    si,offset MNcp437    ; default to CP437
  1960. decsu1x:pop    dx
  1961.     pop    bx
  1962.     ret
  1963. DECSUPG    endp
  1964.  
  1965. ; Set reg BX to offset of table for Code Page to DEC Multinational Char Set
  1966. ; (DEC Supplemental Graphics)
  1967. CPDECSG proc    near
  1968.     mov    bx,offset cp437MN    ; assume CP437
  1969.     cmp    flags.chrset,437    ; current Code Page is 437?
  1970.     je    cpdecsx            ; e = yes
  1971.     mov    bx,offset cp850MN    ; assume CP850
  1972.     cmp    flags.chrset,850    ; current Code Page is 850?
  1973.     je    cpdecsx            ; e = yes
  1974.     mov    bx,offset cp860MN    ; assume CP860
  1975.     cmp    flags.chrset,860    ; current Code Page is 860?
  1976.     je    cpdecsx            ; e = yes
  1977.     mov    bx,offset cp863MN    ; assume CP863
  1978.     cmp    flags.chrset,863    ; current Code Page is 863?
  1979.     je    cpdecsx            ; e = yes
  1980.     mov    bx,offset cp865MN    ; assume CP865
  1981.     cmp    flags.chrset,865    ; current Code Page is 865?
  1982.     je    cpdecsx            ; e = yes
  1983.     mov    bx,offset cp437MN    ; default to CP437
  1984. CPDECSX:ret
  1985. CPDECSG endp
  1986. ; Set register SI to the offset of the NRC table appropriate to the
  1987. ; currently active Code Page. Defaults to CP437 if no CP found.
  1988. NRC2CP    proc    near
  1989.     push    bx
  1990.     push    dx
  1991.     cmp    dosnum,0300h+30        ; DOS version 3.30 or higher?
  1992.     jb    nrc2cp1            ; b = no, no Code Pages
  1993.     mov    ax,6601h        ; get global Code Page
  1994.     int    dos            ; bx=active Code Page, dx=boot CP
  1995.     cmp    bx,437            ; current Code Page is 437?
  1996.     je    nrc2cp1            ; e = yes
  1997.     mov    si,offset NRC850    ; assume CP850
  1998.     cmp    bx,850            ; current Code Page is 850?
  1999.     je    nrc2cpx            ; e = yes
  2000.     mov    si,offset NRC860    ; assume CP860
  2001.     cmp    bx,860            ; current Code Page is 860?
  2002.     je    nrc2cpx            ; e = yes
  2003.     mov    si,offset NRC863    ; assume CP863
  2004.     cmp    bx,863            ; current Code Page is 863?
  2005.     je    nrc2cpx            ; e = yes
  2006.     mov    si,offset NRC865    ; assume CP865
  2007.     cmp    bx,865            ; current Code Page is 865?
  2008.     je    nrc2cpx            ; e = yes
  2009. nrc2cp1:mov    si,offset NRC437    ; default to CP437
  2010. nrc2cpx:pop    dx
  2011.     pop    bx
  2012.     ret
  2013. NRC2CP    endp
  2014.  
  2015.  
  2016. ; cursor movements
  2017.  
  2018. atcup:    test    dspstate,dsptype    ; on VT320 status line?
  2019.     jz    atcup0            ; z = no
  2020.     mov    param,0            ; yes, do not change rows
  2021.     mov    param+2,0
  2022. atcup0:    mov    dh,byte ptr param    ; get row,col parameters
  2023.     mov    dl,byte ptr param+2    ; dh is row, dl is column
  2024.     or    dh,dh            ; zero row number?
  2025.     jz    atcup1            ; z = yes, continue
  2026.     dec    dh            ; normalize to 0,0 system
  2027. atcup1:    or    dl,dl            ; ditto for column
  2028.     jz    atcup2
  2029.     dec    dl
  2030. atcup2:    test    vtemu.vtflgop,decom    ; Origin mode?
  2031.     jz    atcup3            ; z = no, skip this stuff
  2032.     add    dh,mar_top        ; yes, it was relative to top margin
  2033.     jno    atcup3            ; if no overflow, continue
  2034.     mov    dh,byte ptr low_rgt+1    ; otherwise just set to screen bottom
  2035. atcup3:    mov    al,byte ptr low_rgt    ; right margin
  2036.     cmp    dl,al            ; too far to the right?
  2037.     jbe    atcup4            ; ne = no
  2038.     mov    dl,al            ; limit to right margin
  2039. atcup4:    mov    ah,byte ptr low_rgt+1    ; last regular text line
  2040.     cmp    dh,ah            ; going to 25th line?
  2041.     jbe    atcup7            ; be = no
  2042.     inc    ah            ; "25th" status line
  2043.     cmp    flags.vtflg,ttheath    ; emulating a Heath-19?
  2044.     je    atcup5            ; e = yes
  2045.     cmp    dh,ah            ; going too far?
  2046.     je    atcup8            ; e = no
  2047.     dec    ah
  2048.     mov    dh,ah            ; last normal row
  2049.     jmp    atcup8            ; set cursor here
  2050. atcup5:    cmp    dh,ah            ; going too far?
  2051.     ja    atcup6            ; a = yes
  2052.     test    h19stat,h19l25        ; Heath 25th mode line enabled?
  2053.     jnz    atcup8            ; nz = yes
  2054. atcup6:    mov    dh,byte ptr cursor+1    ; do not change rows
  2055. atcup7: call    atccpc            ; check position
  2056. atcup8:    jmp    atscu5            ; set cursor position and return
  2057.  
  2058. atcuarg:mov    al,byte ptr param    ; worker, get cursor movement argument
  2059.     or    al,al            ; zero?
  2060.     jnz    atcua1            ; nz = no
  2061.     inc    al            ; default to one
  2062. atcua1: ret
  2063.                     ; cursor up
  2064. atcuu:    cmp    dh,byte ptr low_rgt+1    ; on 25th line?
  2065.     jbe    atcuu1            ; be = no
  2066.     ret                ; no vertical for Heath on 25th line
  2067. atcuu1:    call    atcuarg            ; get cursor move up argument into al
  2068.     sub    dh,al            ; compute new cursor position
  2069.     jnc    atcuu2            ; nc = ok [dlk]
  2070.     xor    dh,dh            ; overflow, restrict range. [dlk]
  2071. atcuu2:    call    atccic            ; check indexing, ignore action in ax
  2072.     jmp    atscu5            ; set the cursor at its new position
  2073.  
  2074. atcud:    call    atcuarg            ; cursor down
  2075.     cmp    dh,byte ptr low_rgt+1    ; on 25th line now?
  2076.     jbe    atcud1            ; be = no
  2077.     ret                ; else leave it on status line
  2078. atcud1:    add    dh,al            ; compute new cursor position
  2079.     jnc    atcud2            ; nc = ok [dlk]
  2080.     mov    dh,byte ptr low_rgt+1    ; default bottom [dlk]
  2081. atcud2:    call    atccic            ; check indexing, ignore action in ax
  2082.     jmp    atscu5            ; set the cursor at its new position
  2083.  
  2084.                     ; Allow horiz movement on 25th line
  2085. atcuf:    call    atcuarg            ; cursor forward
  2086.     add    dl,al            ; compute new cursor position
  2087.     jnc    atcup3            ; nc = no problem
  2088.     mov    dl,byte ptr low_rgt    ; else set to right margin
  2089.     jmp    atcup3            ; check/set cursor, return
  2090.  
  2091. atcub:    call    atcuarg            ; cursor back
  2092.     sub    dl,al            ; compute new cursor position
  2093.     jnc    atcub1            ; nc = no problem
  2094.     xor    dl,dl            ; else set to left margin
  2095. atcub1:    jmp    atcup3            ; check/set cursor, return
  2096.  
  2097. atcha:    call    atcuarg            ; absolute horizontal address
  2098.     mov    dl,al            ; new column, counted from 1
  2099.     sub    al,1            ; column, count from 0 internally
  2100.     jnc    atcha1            ; nc = no problem
  2101.     xor    dl,dl            ; else set to left margin
  2102. atcha1:    jmp    atcup3            ; check/set cursor, return
  2103.  
  2104. atcht:    call    atcuarg            ; move cursor forward # horiz tabs
  2105.     inc    dl            ; next column
  2106.     mov    cl,al            ; number of tabstops to locate
  2107.     xor    ch,ch
  2108.     mov    si,offset tabs        ; active tabs buffer
  2109. atcht1:    cmp    dl,byte ptr low_rgt    ; at end of line?
  2110.     jae    atcht2            ; ae = yes, stop here
  2111.     call    istabs            ; is dl column a tabstop?
  2112.     inc    dl            ; try next column, preserves carry
  2113.     jnc    atcht1            ; nc = no, find one
  2114.     loop    atcht1            ; do cx tabstops
  2115. atcht2:    jmp    atcup3            ; set cursor
  2116.  
  2117. atcva:    mov    byte ptr param+2,dh    ; set column in second parameter
  2118.     mov    param+3,0        ; high byte
  2119.     jmp    atcup            ; do absolute vertical positioning
  2120.  
  2121. atcnl:    call    atcuarg            ; do # Next-Lines
  2122.     cmp    dh,byte ptr low_rgt+1    ; on 25th line now?
  2123.     jbe    atcnl1            ; be = no
  2124.     ret                ; else leave it on status line
  2125. atcnl1:    add    dh,al            ; number to do
  2126.     xor    dl,dl            ; cursor to left margin
  2127.     call    atccic            ; check cursor position
  2128.     call    ax            ; scroll if necessary
  2129.     jmp    atscu5            ; set cursor, etc. and return
  2130.  
  2131. atcpl:    call    atcuarg            ; do # Previous-Lines
  2132.     cmp    dh,byte ptr low_rgt+1    ; on 25th line now?
  2133.     jbe    atcpl1            ; be = no
  2134.     ret                ; else leave it on status line
  2135. atcpl1:    mov    cl,al            ; number to do
  2136.     xor    ch,ch
  2137.     xor    dl,dl            ; set to column zero
  2138. atcpl2:    dec    dh            ; do one line
  2139.     push    cx            ; save counter
  2140.     call    atccic            ; check cursor position
  2141.     call    ax            ; scroll if necessary
  2142.     call    atscu5            ; set cursor
  2143.     pop    cx
  2144.     loop    atcpl2            ; do cx times
  2145.     ret
  2146.  
  2147. ; Screen erasure commands
  2148.                     ; Erase in display
  2149. ated:    cmp    ninter,0        ; zero intermediates?
  2150.     je    ated0            ; e = yes, else quit
  2151.     ret
  2152.  
  2153. ated0:    cmp    param,0            ; was arg zero?
  2154.     jne    ated1            ; ne = no
  2155.     jmp    ereos            ; do erase cursor to end of screen
  2156.  
  2157. ated1:    cmp    param,1            ; was arg one?
  2158.     jne    ated2            ; ne = no
  2159.     jmp    ersos            ; do erase start of screen to cursor
  2160.  
  2161. ated2:    cmp    param,2            ; was arg two?
  2162.     je    ated2a            ; e = yes, erase entire screen
  2163.     ret                ; else ignore
  2164. ated2a:    push    dx            ; save dynamic cursor
  2165.     xor    dx,dx            ; say cursor is at 0,0
  2166.     call    ereos            ; erase cursor to end of screen
  2167.     pop    dx            ; recover cursor
  2168.     ret
  2169.                     ; Erase in current line
  2170. atel:    cmp    ninter,0        ; zero intermediates?
  2171.     je    atel0            ; e = yes, else quit
  2172.     ret
  2173.  
  2174. atel0:    cmp    param,0            ; was arg zero?
  2175.     jne    atel1            ; ne = no
  2176.     mov    al,dl            ; erase from cursor
  2177.     mov    bl,crt_cols        ;  to end of line, inclusive
  2178.     dec    bl            ; physical line
  2179.     jmp    erinline        ; do the erasure
  2180.  
  2181. atel1:    cmp    param,1            ; was arg one?
  2182.     jne    atel2            ; ne = no
  2183.     xor    al,al            ; erase from start of line
  2184.     mov    bl,dl            ;  to cursor, inclusive
  2185.     jmp    erinline        ; do the erasure
  2186.  
  2187. atel2:    cmp    param,2            ; was arg two?
  2188.     jne    atel3            ; ne = no, ignore
  2189.     xor    al,al            ; erase entire line
  2190.     mov    bl,crt_cols
  2191.     dec    bl            ; physical line
  2192.     jmp    erinline        ; clear it
  2193. atel3:    ret
  2194.                     ; ECH, erase chars in this line
  2195. atech:    mov    ax,dx            ; get cursor position
  2196.     mov    bx,ax            ; erase ax to bx
  2197.     add    bl,byte ptr param    ; number of characters
  2198.     jmp    erinline        ; erase in this line
  2199.  
  2200. ; Set Graphics Rendition commands (video attributes)
  2201.  
  2202. atsgr:    cmp    lparam,0        ; any letter parameter?
  2203.     jne    atsgr0            ; ne = yes, fail
  2204.     mov    ah,curattr        ; get current cursor attribute
  2205.     mov    di,offset atsgr1    ; routine to call
  2206.     call    atreps            ; repeat for all parms
  2207.     mov    curattr,ah        ; store new attribute byte
  2208. atsgr0:    ret
  2209.  
  2210. atsgr1: mov    bx,param[si]        ; fetch an argument
  2211.     or    bl,bl            ; 0, clear all attributes?
  2212.     jnz    atsgr2            ; nz = no, do selectively below
  2213.     call    clrbold            ; clear bold attribute
  2214.     call    clrblink        ; clear blink attribute
  2215.     call    clrunder        ; clear underline attribute
  2216.     jmp    clrrev            ; clear reverse video attribute
  2217.  
  2218. atsgr2: cmp    bl,1            ; 1, set bold?
  2219.     jne    atsgr3            ; ne = no
  2220.     jmp    setbold            ; set bold attribute
  2221.  
  2222. atsgr3: cmp    bl,4            ; 4, set underline?
  2223.     jne    atsgr4            ; ne = no
  2224.     jmp    setunder        ; set underline attribute
  2225.  
  2226. atsgr4: cmp    bl,5            ; 5, set blink?
  2227.     jne    atsgr5            ; ne = no
  2228.     jmp    setblink        ; set blink attribute
  2229.  
  2230. atsgr5: cmp    bl,7            ; 7, reverse video for chars?
  2231.     jne    atsgr6            ; ne = no, try coloring
  2232.     jmp    setrev            ; set reversed video attribute (AH)
  2233.  
  2234. atsgr6:    cmp    flags.vtflg,ttheath    ; Heath-19?
  2235.     jne    atsgr9            ; ne = no
  2236.     cmp    bl,10            ; 10, enter graphics mode?
  2237.     jne    atsgr7            ; ne = no
  2238.     push    ax            ; save ah
  2239.     mov    al,'F'            ; simulate final char of 'F'
  2240.     call    v52sgm            ; do character setup like VT52
  2241.     pop    ax
  2242.     ret
  2243. atsgr7:    cmp    bl,11            ; 11, exit graphics mode?
  2244.     jne    atsgr8            ; ne = no, ignore
  2245.     push    ax            ; save ah
  2246.     mov    al,'G'            ; simulate final char of 'G'
  2247.     call    v52sgm            ; do character setup like VT52
  2248.     pop    ax
  2249. atsgr8:    ret
  2250.  
  2251. atsgr9:    cmp    flags.vtflg,ttvt320    ; VT320?
  2252.     jne    atsgr13            ; ne = no, 22-27 are VT320 only
  2253.     cmp    bl,22            ; 22, bold off?
  2254.     jne    atsgr10            ; ne = no
  2255.     jmp    clrbold
  2256. atsgr10:cmp    bl,24            ; 24, underline off?
  2257.     jne    atsgr11            ; ne = no
  2258.     jmp    clrunder
  2259. atsgr11:cmp    bl,25            ; 25, blinking off?
  2260.     jne    atsgr12            ; ne = no
  2261.     jmp    clrblink
  2262. atsgr12:cmp    bl,27            ; 27, reverse video off?
  2263.     jne    atsgr13            ; ne = no
  2264.     jmp    clrrev            ; clear reversed video attribute (AH)
  2265. atsgr13:jmp    setcolor        ; BL = color, AH = attribute byte
  2266.  
  2267. ; Tabulation char commands
  2268. attbc:    call    atccpc            ; make sure cursor is kosher
  2269.     cmp    ninter,0        ; zero intermediates?
  2270.     je    attbc0            ; e = yes, else quit
  2271.     ret
  2272.                     ; Tabstop set/clears
  2273. attbc0: cmp    param,0            ; was argument zero?
  2274.     jne    attbc1            ; ne = no
  2275.     push    si
  2276.     mov    si,vtemu.vttbst        ; active buffer
  2277.     call    tabclr            ; clear tabstop in column DL
  2278.     pop    si
  2279.     ret
  2280.  
  2281. attbc1: cmp    param,3            ; was arg 3 (clear all tab stops)?
  2282.     je    attbc2            ; e = yes
  2283.     ret                ; else ignore
  2284. attbc2:    mov    cx,(swidth+7)/8        ; get ready to zap swidth columns
  2285.     mov    di,offset tabs        ; point to the tab stop table
  2286.     xor    al,al            ; zero indicates no tab stop
  2287.     push    es            ; save es
  2288.     push    ds
  2289.     pop    es            ; use data segment for es:di below
  2290.     cld                ; set direction forward
  2291.     rep    stosb            ; clear all bits
  2292.     pop    es
  2293.     ret
  2294.                     ; set scrolling margins
  2295. atstbm:    test    dspstate,dsptype    ; on status line?
  2296.     jnz    atstb3            ; nz = yes, ignore this command
  2297.     mov    al,byte ptr param    ; get the two line number args
  2298.     mov    ah,byte ptr param+2
  2299.     or    al,al            ; was first zero?
  2300.     jnz    atstb1            ; nz = no, continue
  2301.     inc    al            ; default is one
  2302. atstb1: or    ah,ah            ; was second zero?
  2303.     jnz    atstb2            ; nz = no
  2304.     mov    ah,byte ptr low_rgt+1    ; yes, default is last line on screen
  2305.     inc    ah
  2306. atstb2: dec    al            ; normalize to 0,0 coordinate system
  2307.     dec    ah
  2308.     cmp    ah,al            ; size of region at least two lines?
  2309.     jbe    atstb3            ; be = no, indicate an error
  2310.     cmp    al,0            ; check against screen limits
  2311.     jl    atstb3            ; l = out of range
  2312.     cmp    ah,byte ptr low_rgt+1
  2313.     ja    atstb3            ; a = too far down
  2314.     mov    mar_top,al        ; set the limits
  2315.     mov    mar_bot,ah
  2316.     xor    dx,dx            ; Home cursor
  2317.     call    atccpc            ; check cursor (get it inside window)
  2318.     jmp    atscu5            ; set cursor position and return
  2319. atstb3:    ret                ; ignore bad requests
  2320.  
  2321. ; Device attributes commands
  2322. atda:    cmp    param,0            ; was argument zero?
  2323.     je    decid            ; e = send the i.d. string
  2324.     ret                ; no, only an echo
  2325. decid:    mov    cx,20            ; assumed length of asciiz string
  2326.     mov    si,offset v32str    ; VT320 ident string
  2327.     cmp    flags.vtflg,ttvt320    ; VT320?
  2328.     je    decid2            ; e = yes
  2329.     mov    si,offset v102str
  2330.     cmp    flags.vtflg,ttvt100    ; VT100?
  2331.     je    decid2            ; e = yes
  2332.     mov    si,offset v52str
  2333.     cmp    flags.vtflg,ttvt52    ; Heath-19 mode?
  2334.     je    decid2            ; e = yes
  2335.     mov    si,offset h19str    ; say Heath-19
  2336. decid2:    cmp    lparam,'>'        ; this letter parameter?
  2337.     jne    decid3            ; ne = no
  2338.     cmp    flags.vtflg,ttvt320    ; VT320 mode?
  2339.     jne    decid4            ; ne = no, ignore
  2340.     mov    si,offset v32sda    ; Secondary DA response string
  2341. decid3:    cld
  2342.     lodsb                ; read string
  2343.     or    al,al            ; end of string?
  2344.     jz    decid4            ; z = yes
  2345.     push    cx
  2346.     push    si
  2347.     call    prtbout            ; send it to port with no local echo
  2348.     pop    si
  2349.     pop    cx
  2350.     loop    decid3            ; do all characters
  2351. decid4:    ret
  2352.                     ; Display LED's
  2353. atll:    mov    di,offset atleds    ; get pointer to routine to call
  2354.     call    atreps            ; repeat for selective parameters
  2355.     ret
  2356.  
  2357. atleds: cmp    param[si],0        ; zero argument?
  2358.     jne    atled3            ; ne = no, check further
  2359.     mov    cx,4            ; reset the "LEDs"
  2360.     mov    al,led_off        ; to all off
  2361.     mov    di,offset ansleds+6    ; point to the "LEDs"
  2362.     push    es            ; save es
  2363.     push    ds
  2364.     pop    es            ; make es:di point to data seg
  2365.     cld                ; move forward
  2366.     rep    stosb
  2367.     pop    es
  2368. atled1: call    ansdsl            ; update "LEDs" display and return
  2369. atled2: ret
  2370. atled3: mov    ax,param[si]        ; get the argument
  2371.     cmp    al,1            ; must be 1 to 4
  2372.     jb    atled2            ; b = out of range
  2373.     cmp    al,4
  2374.     ja    atled2            ; a = out of range
  2375.     dec    ax            ; zero base it
  2376.     mov    di,ax
  2377.     add    al,'1'            ; add ascii offset for digit
  2378.     mov    ansleds[di+6],al     ; turn the "LED" on by storing digit
  2379.     jmp    atled1            ; update display and return
  2380.  
  2381.  
  2382. ; Set/Reset mode commands
  2383.                     ; ESC [ ? xxx h/l Set/Reset series
  2384. atrm:    mov    modeset,0        ; say we are resetting modes
  2385.     mov    di,offset atrsm        ; Reset/Set modes
  2386.     call    atreps            ; repeat for all parms
  2387.     test    vtemu.vtflgop,decanm    ; did ansi mode get reset?
  2388.     jnz    atrm1            ; nz = no, return
  2389.     cmp    flags.vtflg,ttheath    ; were we a Heath-19?
  2390.     je    atrm0            ; e = yes, don't change terminal types
  2391.     mov    flags.vtflg,ttvt52    ; say VT52 now
  2392. atrm0:    call    chrdef            ; set default char sets
  2393.     call    atsc            ; save cursor status
  2394.     call    ansdsl            ; update terminal type
  2395. atrm1:    ret
  2396.  
  2397. atsm:    mov    modeset,1        ; say we are setting modes
  2398.     mov    di,offset atrsm        ; Reset/Set modes
  2399.     call    atreps            ; repeat for all parms
  2400.     ret
  2401.  
  2402. atrsm:    mov    ax,param[si]        ; pick up the argument
  2403.     cmp    lparam,'?'        ; DEC private mode? ESC [ ?
  2404.     je    atrsm1            ; e = yes, do DEC specific things
  2405.     cmp    lparam,'>'        ; Heath-19 private mode? ESC [ >
  2406.     jne    atrsma            ; ne = no
  2407.     jmp    htrsm1            ; do Heath specific things
  2408.                     ; ANSI level
  2409. atrsma:    cmp    al,20            ; 20, ANSI new-line mode?
  2410.     jne    atrsm0            ; ne = no, try insert mode
  2411.     and    vtemu.vtflgop,not vsnewline ; assume resetting
  2412.     cmp    modeset,0        ; resetting?
  2413.     je    atrsmb            ; e = yes
  2414.     or    vtemu.vtflgop,vsnewline    ; setting
  2415. atrsmb:    mov    ax,anslnm        ; get the flag bit
  2416.     jmp    atrsflg            ; set or reset it
  2417. atrsm0:    cmp    al,4            ; toggle insert mode?
  2418.     jne    atrsmc            ; ne = no
  2419.     mov    al,modeset        ; set/reset insert mode
  2420.     mov    insmod,al        ; store it
  2421.     ret
  2422. atrsmc:    cmp    al,12            ; 12? Control local echo
  2423.     jne    atrsmx            ; ne = no
  2424.     cmp    modeset,0        ; resetting mode (ESC [ 12 l)?
  2425.     jne    atrsmc1            ; ne = no
  2426.     or    vtemu.vtflgop,dececho    ; remember state here too
  2427.     or    yflags,lclecho        ; (l) turn on local echoing
  2428.     jmp    short atrsmc2
  2429. atrsmc1:and    yflags,not lclecho    ; (h) turn off local echoing
  2430.     and    vtemu.vtflgop,not dececho
  2431. atrsmc2:test    yflags,modoff        ; is mode line off?
  2432.     jnz    atrsmx            ; nz = yes
  2433.     push    dx            ; save cursor position
  2434.     call    modlin            ; write mode line
  2435.     pop    dx
  2436. atrsmx:    ret
  2437.                     ; DEC specifics
  2438. atrsm1: cmp    al,1            ; cursor keys mode?
  2439.     jne    atrsm2            ; ne = no
  2440.     mov    ax,decckm        ; get the bit
  2441.     jmp    atrsflg            ; set or reset it and return
  2442.  
  2443. atrsm2: cmp    al,7            ; Auto-wrap?
  2444.     jne    atrsm3            ; ne = no
  2445.     and    vtemu.vtflgop,not vswrap ; assume resetting line wrap
  2446.     cmp    modeset,0        ; resetting?
  2447.     je    atrsm2a            ; e = yes
  2448.     or    vtemu.vtflgop,vswrap    ; set the bit
  2449. atrsm2a:mov    ax,decawm        ; get the bit
  2450.     jmp    atrsflg            ; set or reset it and return
  2451.  
  2452. atrsm3: cmp    al,6            ; Origin mode?
  2453.     jne    atrsm4            ; ne = no
  2454.     jmp    atrsom            ; change decom and return
  2455.  
  2456. atrsm4: cmp    al,5            ; change the video?
  2457.     jne    atrsm5            ; ne = no
  2458.     jmp    atrsscnm        ; yes, change it if necessary
  2459.  
  2460. atrsm5: cmp    al,2            ; Change VT52 compatibility mode?
  2461.     jne    atrsm6            ; ne = no
  2462.     test    dspstate,dsptype    ; on status line?
  2463.     jnz    atrsm5b            ; nz = yes, ignore switch
  2464.     cmp    flags.vtflg,ttheath    ; Heath-19 mode?
  2465.     jne    atrsm5a            ; ne = no
  2466.     mov    modeset,0        ; Heath  ESC [ ? 2 h  resets ANSI mode
  2467. atrsm5a:mov    ax,decanm        ; get ansi mode flag
  2468.     jmp    atrsflg            ; set or reset it
  2469. atrsm5b:ret
  2470.  
  2471. atrsm6:    cmp    al,3            ; 132/80 column mode change?
  2472.     jne    atrsm7            ; ne = no
  2473.     mov    al,curattr        ; save current video attributes
  2474.     push    ax
  2475.     mov    al,modeset        ; pass set/reset request to chgdsp[dlk]
  2476.     call    chgdsp            ; call Change Display proc in msy [dlk]
  2477.     and    vtemu.vtflgop,not deccol; assume mode is reset
  2478.     cmp    modeset,1        ; want 132 cols?
  2479.     jne    atrsm6n            ; ne = no, so use 80 columns
  2480.     cmp    crt_cols,80        ; see if it worked
  2481.     jbe    atrsm6n            ; be = no, do not set the status bit
  2482.     or    vtemu.vtflgop,deccol    ; set the status bit
  2483.     mov    al,crt_cols        ; get current physical screen width
  2484.     dec    al            ; we count from column 0 here
  2485.     mov    byte ptr low_rgt,al    ; screen capability
  2486.     jmp    short atrsm6e
  2487. atrsm6n:cmp    byte ptr low_rgt,79    ; want 80 cols, is it wider?
  2488.     jbe    atrsm6e            ; be = no
  2489.     mov    byte ptr low_rgt,79    ; narrow down to 80 columns
  2490. atrsm6e:CALL    ATRES2            ; do partial reset of emulator
  2491.     pop    ax
  2492.     mov    curattr,al        ; restore saved items
  2493.     mov    dl,byte ptr low_rgt+1    ; text lines (leave status line intact)
  2494.     mov    mar_top,0
  2495.     mov    mar_bot,dl        ; reset scrolling region
  2496.     xor    dx,dx            ; new cursor position is 0,0
  2497.     mov    cursor,dx
  2498.     jmp    atscu5            ; place it there and return
  2499.  
  2500. atrsm7:    cmp    al,18            ; 18?  18 & 19 = printer support
  2501.     jne    atrsm8            ; ne = no
  2502.     cmp    modeset,0        ; resetting?
  2503.     jne    atrsm7a            ; ne = no, setting
  2504.     and    anspflg,not vtffp    ; no form feed after printing
  2505.     ret
  2506. atrsm7a:or    anspflg,vtffp        ; use form feed after printing
  2507.     ret
  2508.  
  2509. atrsm8:    cmp    al,19            ; 19, print region?
  2510.     jne    atrsm9            ; ne = no
  2511.     cmp    modeset,0        ; resetting?
  2512.     jne    atrsm8a            ; ne = no, setting
  2513.     and    anspflg,not vtextp    ; reset print region to scrolling reg
  2514.     ret
  2515. atrsm8a:or    anspflg,vtextp        ; set print region to whole screen
  2516.     ret
  2517.  
  2518. atrsm9:    cmp    al,25            ; ESC [ ? 25 h/l? cursor on/off
  2519.     jne    atrsm10            ; ne = no
  2520.     mov    al,4            ; assume cursor to be turned off (4)
  2521.     cmp    modeset,0        ; resetting (invisible cursor)?
  2522.     je    atrsm9a            ; e = yes
  2523.     mov    al,1            ; assume underline (1)
  2524.     test    vtemu.vtflgop,vscursor    ; underline?
  2525.     jnz    atrsm9a            ; nz = yes
  2526.     inc    al            ; block (2)
  2527. atrsm9a:mov    atctype,al        ; save VTxxx cursor type here
  2528.     jmp    atsctyp            ; set the cursor type
  2529.  
  2530. atrsm10:cmp    al,34            ; ESC [ ? 34 h/l? Invoke special macro
  2531.     jne    atrsm11            ; ne = no
  2532.     cmp    modeset,0        ; resetting?
  2533.     jne    atrsm10a        ; ne = no, setting
  2534.     jmp    vtrmac            ; jump to perform on-line macro
  2535.                     ;  code is located in file msy
  2536. atrsm10a:jmp    vtsmac            ; do set macro
  2537.  
  2538. atrsm11:cmp    al,38            ; 38? Enter Tek sub-mode. VT340 seq
  2539.     jne    atrsm12            ; ne = no
  2540.     cmp    modeset,1        ; setting mode (ESC [ ? 38 h)?
  2541.     jne    atrsm12            ; ne = no, ignore sequence
  2542.     test    denyflg,tekxflg        ; is auto Tek mode disabled?
  2543.     jnz    atrsm12            ; nz = yes, just ignore command
  2544.     call    atsc            ; save cursor and associated data
  2545.     xor    al,al            ; enter with this received character
  2546.     call    TEKEMU            ; go to Tektronix Emulator, al=null
  2547.     jmp    atnorm
  2548.  
  2549. atrsm12:cmp    al,42            ; 42, use NRC 7-bit command?
  2550.     jne    atrsm15            ; ne = no
  2551.     cmp    flags.vtflg,ttvt320    ; VT320 mode?
  2552.     jne    atrsm14            ; ne = no
  2553.     cmp    vtemu.vtchset,0        ; ASCII?
  2554.     je    atrsm14            ; e = yes, no NRC
  2555.     cmp    vtemu.vtchset,12    ; highest NRC ident?
  2556.     ja    atrsm14            ; a = not NRC
  2557.     cmp    modeset,0        ; resetting?
  2558.     je    atrsm13            ; e = yes
  2559.     or    vtemu.vtflgop,vsnrcm    ; set NRC flag bit
  2560.     jmp    chrdef            ; and set NRC characters
  2561. atrsm13:mov    ax,vtemu.vtflgop    ; run time flags
  2562.     and    vtemu.vtflgop,not vsnrcm ; turn off NRC flag bit
  2563.     or    vtemu.vtflgop,vscntl    ; turn on 8-bit controls
  2564.     jmp    chrdef
  2565. atrsm14:ret
  2566. atrsm15:cmp    al,66            ; 66, keypad to applications mode?
  2567.     jne    atrsm16            ; ne = no
  2568.     cmp    flags.vtflg,ttvt320    ; VT320 mode?
  2569.     jne    atrsm16            ; ne = no
  2570.     mov    ax,deckpam        ; bit to control
  2571.     jmp    atrsflg            ; control the flag and return
  2572. atrsm16:ret
  2573.         ; Heath-19  ESC [ > Ps h or l where Ps = 1, 4, 7, or 9
  2574. htrsm1:    cmp    al,1            ; 25th line?
  2575.     jne    htrsm4            ; ne = no
  2576.     and    h19stat,not h19l25    ; clear 25th line bit
  2577.     cmp    modeset,0        ; clearing?
  2578.     je    htrsm1a            ; e = yes
  2579.     or    h19stat,h19l25        ; set bit
  2580.     jmp    htrsmx            ; we are done
  2581. htrsm1a:mov    ah,byte ptr low_rgt+1    ; point to status (25th) line
  2582.     inc    ah            ;  which is here
  2583.     xor    al,al            ; from column 0
  2584.     mov    bh,ah            ; to same line
  2585.     mov    bl,crt_cols        ; physical width
  2586.     dec    bl            ; we count from 0
  2587.     jmp    vtsclr            ; disabling status line clears it
  2588.  
  2589. htrsm4:    cmp    al,4            ; 4, block/line cursor?
  2590.     jne    htrsm5            ; ne = no
  2591.     and    h19ctyp,4        ; save on/off bit (4)
  2592.     cmp    modeset,0        ; reset?
  2593.     je    htrsm4a            ; e = yes
  2594.     or    h19ctyp,2        ; remember block kind here
  2595.     jmp    atsctyp
  2596. htrsm4a:or    h19ctyp,1        ; remember underline kind here
  2597.     jmp    atsctyp
  2598.      
  2599. htrsm5: cmp     al,5                    ; 5, on/off cursor?
  2600.         jne     htrsm7                  ; ne = no
  2601.         cmp     modeset,0               ; on?
  2602.         je      htrsm5a                 ; e = yes
  2603.     or    h19ctyp,4        ; remember off state in this bit
  2604.         jmp     atsctyp
  2605. htrsm5a:and    h19ctyp,not 4        ; set cursor on
  2606.         jmp     atsctyp
  2607.  
  2608. htrsm7:    cmp    al,7            ; 7, alternate application keypad?
  2609.     jne    htrsm8            ; ne = no
  2610.     mov    ax,deckpam        ; get keypad application mode bit
  2611.     jmp    atrsflg            ; set or reset appl keypad mode
  2612.  
  2613. htrsm8:    cmp    al,8            ; 8, received CR => CR/LF?
  2614.     jne    htrsm9
  2615.     and    h19stat,not h19alf    ; clear autoline feed bit
  2616.     cmp    modeset,0        ; resetting?
  2617.     je    htrsmx            ; yes
  2618.     or    h19stat,h19alf        ; turn on the mode
  2619.     ret
  2620.  
  2621. htrsm9:    cmp    al,9            ; 9, auto newline mode? (add cr to lf)
  2622.     jne    htrsmx            ; ne = no
  2623.     mov    ax,anslnm        ; get the bit
  2624.     jmp    atrsflg            ; set or reset newline mode
  2625. htrsmx:    ret                ; ignore the code
  2626.  
  2627. atrsflg:cmp    modeset,0        ; reset?
  2628.     je    atrsf1            ; e = yes, reset it
  2629.     or    vtemu.vtflgop,ax    ; set, OR in the flag
  2630.     test    ax,decanm        ; changing ansi mode?
  2631.     jz    atrsfx            ; z = no
  2632.     cmp    flags.vtflg,ttheath    ; in Heath-19 mode?
  2633.     je    atrsfx            ; e = yes, don't flip terminal kinds
  2634.     mov    al,oldterm        ; terminal type at startup
  2635.     mov    flags.vtflg,al        ; restore it
  2636.     ret
  2637. atrsf1: not    ax            ; reset bit, complement
  2638.     and    vtemu.vtflgop,ax    ; clear the bit
  2639.     not    ax            ; recover the bit
  2640.     test    ax,decanm        ; changing ansi mode?
  2641.     jz    atrsfx            ; z = no
  2642.     cmp    flags.vtflg,ttheath    ; in Heath-19 mode?
  2643.     je    atrsfx            ; e = yes, don't flip terminal kinds
  2644.     mov    flags.vtflg,ttvt52    ; say VT52 now
  2645. atrsfx:    ret
  2646.                     ; Set/Clear Origin mode
  2647. atrsom:    test    dspstate,dsptype    ; on status line?
  2648.     jz    atrsom1            ; z = no
  2649.     ret                ; else ignore this command
  2650. atrsom1:cmp    modeset,0        ; clearing DEC origin mode?
  2651.     jne    atrsom2            ; ne = no, setting
  2652.     and    vtemu.vtflgop,not decom ; reset Origin mode
  2653.     xor    dx,dx            ; go to the home position
  2654.     jmp    atscu5            ; set cursor and return
  2655. atrsom2:or    vtemu.vtflgop,decom    ; set Origin mode
  2656.     mov    dx,cursor        ; get the cursor
  2657.     xor    dl,dl            ; go to right margin
  2658.     mov    dh,mar_top        ; go to home of scrolling region
  2659.     jmp    atscu5            ; set the cursor and return
  2660.  
  2661. atrsscnm:cmp    modeset,0        ; resetting?
  2662.     je    atrss1            ; e = yes, reset
  2663.     test    vtemu.vtflgop,vsscreen    ; setting, set already?
  2664.     jnz    atrss3            ; nz = yes, don't do it again
  2665.     or    vtemu.vtflgop,vsscreen    ; set and tell Status display
  2666.     jmp    short atrss2        ; do it
  2667.  
  2668. atrss1: test    vtemu.vtflgop,vsscreen    ; resetting, reset already?
  2669.     jz    atrss3            ; z = yes, don't do it again
  2670.     and    vtemu.vtflgop,not vsscreen ; clear and tell Status
  2671.                     ; fall through to atrss2
  2672.  
  2673. ; Note: This is also called from the stblmds initialization routine.
  2674. ; Reverse video the entire screen, update scbattr and curattr to match.
  2675. atrss2:    push    ax
  2676.     mov    ah,scbattr        ; current screen attributes
  2677.     call    revideo            ; reverse them
  2678.     mov    scbattr,ah        ; set screen background attribute
  2679.     mov    ah,curattr        ; get current cursor attribute
  2680.     call    revideo            ; reverse it
  2681.     mov    curattr,ah        ; store it
  2682.     pop    ax
  2683.     call    revscn            ; reverse everything on the screen
  2684. atrss3: ret
  2685.  
  2686.                     ; Self tests
  2687. atctst:    cmp    inter,0            ; any intermediate char?
  2688.     jne    atcts3            ; ne = yes, not a selftest command
  2689.     cmp    param,2            ; VT102 selftest?
  2690.     je    atcts1            ; e = yes
  2691.     cmp    param,4            ; VT320 selftest?
  2692.     jne    atcts3            ; ne = no, ignore
  2693. atcts1:    test    dspstate,dsptype    ; cursor is on status line?
  2694.     jz    atcts2            ; z = no
  2695.     push    param            ; save first parameter
  2696.     mov    ah,inter        ;  and first intermediate char
  2697.     push    ax
  2698.     mov    param,0            ; select main display
  2699.     mov    inter,'$'        ; setup proper intermediate
  2700.     call    atssdt            ; select status line of off
  2701.     call    atsasd            ; select main display
  2702.     pop    ax
  2703.     pop    param            ; restore parameter
  2704.     mov    inter,ah        ;  and intermediate char
  2705. atcts2:    xor    al,al            ; init test weight
  2706.     mov    di,offset atcts4    ; routine to call
  2707.     call    atreps            ; repeat for all parms
  2708.     test    al,80H            ; reset?
  2709.     jz    atcts3            ; z = no, return
  2710.     call    atreset            ; reset everything
  2711. atcts3: ret
  2712.  
  2713. atcts4:    or    si,si            ; initial arg?
  2714.     jz    atcts5            ; z = yes, skip it (examined above)
  2715.     cmp    param[si],0        ; any argument?
  2716.     jne    atcts5            ; ne = no, ignore others
  2717.     or    al,80H            ; say we want reset
  2718. atcts5: ret
  2719.  
  2720. atalign    proc    near            ; Align screen, fill screen with 'E's
  2721.     test    dspstate,dsptype    ; is cursor on status line?
  2722.     jz    atalig1            ; z = no
  2723.     ret                ; yes, ignore the command
  2724. atalig1:cmp    flags.modflg,0        ; is mode line off?
  2725.     je    atalig2            ; e = yes
  2726.     and    yflags,not modoff    ; say it's on
  2727.     mov    flags.modflg,1        ;  and owned by us
  2728. atalig2:call    atreset            ; clear system
  2729.     or    vtemu.vtflgop,decawm    ; set wrap
  2730.     mov    cl,byte ptr low_rgt    ; number of columns-1
  2731.     inc    cl
  2732.     mov    al,byte ptr low_rgt+1    ; number of rows-1
  2733.     inc    al
  2734.     mul    cl            ; ax = number of chars on screen
  2735.     mov    cx,ax
  2736. atalig3:push    cx
  2737.     mov    al,'E'            ; write screen full of E's
  2738.     call    atnrm            ; write the 'E'
  2739.     pop    cx
  2740.     loop    atalig3            ; cx times
  2741.     ret
  2742. atalign    endp
  2743.  
  2744.  
  2745. ; Reports
  2746. atreqt: cmp    param,1            ; want report?
  2747.     jbe    atreq1            ; be = yes
  2748. atreq0:    ret                ; Gee, must have been an echo
  2749.  
  2750. atreq1:    cmp    flags.vtflg,ttvt100    ; VT102?
  2751.     jne    atreq0            ; ne = no, ignore
  2752.     mov    al,CSI
  2753.     call    out8bit            ; send CSI or ESC [
  2754.     mov    al,'3'            ; we report only upon request
  2755.     cmp    param,0            ; was argument a zero?
  2756.     jne    atreq1a            ; ne = no
  2757.     mov    al,'2'            ; yes
  2758. atreq1a:call    prtbout
  2759.     mov    al,';'            ; separate
  2760.     call    prtbout
  2761.     mov    bl,parcode        ; get the parity code
  2762.     xor    bh,bh
  2763.     mov    al,partab[bx]        ; get VT100 parity code
  2764.     push    ax            ; save parity code
  2765.     call    prtnout            ; send number to the port
  2766.     mov    al,';'            ; separate
  2767.     call    prtbout
  2768.     mov    al,'2'            ; assume 7 data bits
  2769.     pop    bx            ; get parity code into bl
  2770.     cmp    bl,1            ; is parity none?
  2771.     jne    atreq2            ; ne = no, so 7 data bits
  2772.     test    flags.remflg,d8bit    ; 8 bit display?
  2773.     jz    atreq2            ; z = no
  2774.     mov    al,'1'            ; must be eight
  2775. atreq2: call    prtbout            ; send it to the port
  2776.     mov    al,';'
  2777.     call    prtbout
  2778.     mov    bl,baudidx        ; baud rate index
  2779.     xor    bh,bh
  2780.     mov    al,baudtab[bx]        ; get DEC baud rate code
  2781.     push    ax
  2782.     call    prtnout            ; send it to the port
  2783.     mov    al,';'
  2784.     call    prtbout
  2785.     pop    ax
  2786.     call    prtnout            ; send baud rate code to the port
  2787.     mov    al,';'
  2788.     call    prtbout
  2789.     mov    al,'1'            ; clock rate multiplier is always 1
  2790.     call    prtbout
  2791.     mov    al,';'
  2792.     call    prtbout
  2793.     mov    al,'0'            ; Flags are always zero (no STP)
  2794.     call    prtbout
  2795.     mov    al,'x'
  2796.     call    prtbout
  2797.     ret
  2798.  
  2799.                     ; Single Controls
  2800. ; Note DEC manual incorrectly says DECSCL's do a hard rather than soft reset
  2801. decscl:    cmp    inter,'!'        ; "CSI ! p" soft reset?
  2802.     jne    decsc0            ; ne = no
  2803.     jmp    atsres            ; do a soft reset
  2804.  
  2805. decsc0:    cmp    inter,'"'        ; "CSI Psc; Ps1 " p"  operating level?
  2806.     je    decsc1            ; e = yes
  2807.     cmp    inter,'$'        ; "CSI Pn $ p"  DECRQM?
  2808.     jne    decsc0a            ; ne = no, ignore others
  2809.     jmp    decsc5            ; do isolated controls report
  2810. decsc0a:ret                ; else ignore
  2811. decsc1:    cmp    param,61        ; Psc, select VT100?
  2812.     jne    decsc2            ; ne = no
  2813.     mov    flags.vtflg,ttvt100    ; set VT100
  2814.     mov    oldterm,ttvt100        ; and remember it
  2815.     and    vtemu.vtflgop,not vscntl ; turn off 8-bit controls
  2816.     jmp    atsres            ; do soft reset of emulator
  2817. decsc2:    cmp    param,62        ; VT2xx level?
  2818.     je    decsc3            ; e = yes
  2819.     cmp    param,63        ; VT3xx level?
  2820.     je    decsc3            ; e = yes
  2821.     ret                ; else ignore
  2822. decsc3:    cmp    param[2],2        ; Ps1, range here is 0, 1, 2
  2823.     ja    decsc4            ; a = out of range, ignore
  2824.     mov    flags.vtflg,ttvt320    ; set VT320 mode
  2825.     mov    oldterm,ttvt320
  2826.     call    atsres            ; do soft reset of emulator
  2827.     and    vtemu.vtflgop,not vscntl ; turn off 8-bit controls
  2828.     cmp    param[2],1        ; select 7-bit controls?
  2829.     je    decsc4            ; e = yes, we have done so
  2830.     or    vtemu.vtflgop,vscntl    ; turn on 8-bit controls
  2831. decsc4:    ret
  2832.                            ; single controls report request
  2833. decsc5:    cmp    lparam,'?'        ; want DEC Private modes?
  2834.     jne    decsc5a            ; ne = no
  2835.     call    decscpre        ; do standard prefix
  2836.     mov    al,'2'            ; assume mode is reset
  2837.     call    decsc20            ; do DEC Private mode report
  2838.     jmp    decscend        ; do end of sequence
  2839. decsc5a:cmp    inter,0            ; intermediate char?
  2840.     je    decsc5b            ; e = no, ignore
  2841.     call    decscpre        ; do standard prefix
  2842.     mov    al,'2'            ; assume mode is reset
  2843.     call    decsc5c            ; do ANSI report
  2844.     jmp    decscend        ; do end of sequence
  2845. decsc5b:ret                ; else return failure
  2846.                     ; ANSI report:
  2847. decsc5c:cmp    param,2            ; 2, Keyboard action?
  2848.     jne    decsc6            ; ne = no
  2849.     ret
  2850. decsc6:    cmp    param,3            ; control representation?
  2851.     jne    decsc7            ; ne = no
  2852.     ret                ; say reset(acting on controls)
  2853. decsc7:    cmp    param,4            ; 4, Insert/Replace mode?
  2854.     jne    decsc8            ; ne = no
  2855.     cmp    insmod,0        ; insert mode off?
  2856.     je    decsc7a            ; e = yes, off
  2857.     dec    al            ; say is on
  2858. decsc7a:ret
  2859. decsc8:    cmp    param,10        ; 10, Horizontal editing?
  2860.     jne    decsc9            ; ne = no
  2861.     mov    al,'4'            ; permanently reset
  2862.     ret
  2863. decsc9:    cmp    param,12        ; 12, Send/Receive (local echo)?
  2864.     jne    decsc11            ; ne = no
  2865.     test    vtemu.vtflgop,dececho    ; set?
  2866.     jz    decsc12            ; z = no
  2867.     dec    al            ; say set
  2868.     ret
  2869. decsc11:cmp    param,20        ; 20, new line mode?
  2870.     jne    decsc13            ; ne = no
  2871.     test    vtemu.vtflgop,anslnm    ; new line set?
  2872.     jz    decsc12            ; z = no, reset
  2873.     dec    al            ; say set
  2874. decsc12:ret
  2875. decsc13:mov    al,'0'            ; say not recognized
  2876.     ret
  2877.  
  2878.                            ; DEC Private mode report
  2879. decsc20:cmp    param,1            ; 1, cursor keys?
  2880.     jne    decsc22            ; ne = no
  2881.     test    vtemu.vtflgop,decckm    ; set?
  2882.     jz    decsc31            ; z = no, reset
  2883.     dec    al
  2884.     ret
  2885. decsc22:cmp    param,2            ; 2, ANSI mode
  2886.     jne    decsc24            ; ne = no
  2887.     test    vtemu.vtflgop,decanm    ; set?
  2888.     jz    decsc31            ; z = no, reset
  2889.     dec    al
  2890.     ret
  2891. decsc24:cmp    param,3            ; 3, column
  2892.     jne    decsc26            ; ne = no
  2893.     test    vtemu.vtflgop,deccol    ; 132 column mode set?
  2894.     jz    decsc31            ; z = no, reset (80 columns)
  2895.     dec    al
  2896.     ret
  2897. decsc26:cmp    param,4            ; 4, scrolling mode
  2898.     je    decsc31            ; e = yes always say reset (jump)
  2899.                     ;
  2900.     cmp    param,5            ; 5, screen
  2901.     jne    decsc28            ; ne = no
  2902.     test    vtemu.vtflgop,decscnm    ; set (light background)?
  2903.     jz    decsc31            ; z = no, reset
  2904.     dec    al
  2905.     ret
  2906. decsc28:cmp    param,6            ; 6, Origin mode?
  2907.     jne    decsc30            ; ne = no
  2908.     test    dspstate,dsptype    ; on status line?
  2909.     jz    decsc29            ; z = no, main display
  2910.     test    dspstate,dspdecom    ; main display Origin mode set?
  2911.     jz    decsc31            ; z = no, reset
  2912.     dec    al
  2913.     ret
  2914. decsc29:test    vtemu.vtflgop,decom    ; Origin mode set?
  2915.     jz    decsc31            ; z = no, reset
  2916.     dec    al
  2917.     ret
  2918. decsc30:cmp    param,7            ; 7, autowrap?
  2919.     jne    decsc32            ; ne = no
  2920.     test    vtemu.vtflgop,decawm    ; set?
  2921.     jz    decsc31            ; z = no, reset
  2922.     dec    al
  2923. decsc31:ret                ; common return point
  2924. decsc32:cmp    param,8            ; 8, autorepeat?
  2925.     jne    decsc34            ; ne = no
  2926.     dec    al
  2927.     ret                ; say set
  2928. decsc34:cmp    param,18        ; 18, print Form Feed?
  2929.     jne    decsc36            ; ne = no
  2930.     test    anspflg,vtffp        ; set?
  2931.     jz    decsc31            ; z = no, reset
  2932.     dec    al
  2933.     ret
  2934. decsc36:cmp    param,19        ; 19, printer extent?
  2935.     jne    decsc38            ; ne = no
  2936.     test    anspflg,vtextp        ; set?
  2937.     jz    decsc31            ; z = no, reset
  2938.     dec    al
  2939.     ret
  2940. decsc38:cmp    param,25        ; 25, text cursor enabled?
  2941.     jne    decsc40            ; ne = no
  2942.     test    atctype,4        ; 4 is off
  2943.     jnz    decsc31            ; nz = off/disabled
  2944.     dec    al            ; say enabled
  2945.     ret
  2946. decsc40:cmp    param,42        ; 42, NRC's
  2947.     jne    decsc42            ; ne = no
  2948.     cmp    flags.vtflg,ttvt320    ; VT320?
  2949.     jne    decsc31            ; ne = no
  2950.     test    vtemu.vtflgop,vsnrcm    ; NRC's active?
  2951.     jz    decsc31            ; z = no
  2952.     dec    al            ; say enabled
  2953.     ret
  2954. decsc42:cmp    param,66        ; 66, numeric keypad?
  2955.     jne    decsc44            ; ne = no
  2956.     test    vtemu.vtflgop,deckpam    ; set?
  2957.     jz    decsc31            ; z = no, reset
  2958.     dec    al            ; say set
  2959.     ret
  2960. decsc44:cmp    param,68        ; 68, keyboard usage?
  2961.     jne    decsc45            ; ne = no
  2962.     mov    al,'4'            ; say always typewriter mode
  2963.     ret
  2964. decsc45:mov    al,'0'            ; say unknown kind
  2965.     ret
  2966.  
  2967. decscpre:mov    al,CSI            ; do standard report beginning
  2968.     call    out8bit
  2969.     mov    al,byte ptr param    ; get parameter
  2970.     call    prtnout            ; send the number
  2971.     mov    al,';'
  2972.     call    prtbout
  2973.     ret
  2974.  
  2975. decscend:call    prtbout            ; do standard rpt end, send char in al
  2976.     mov    al,'$'
  2977.     call    prtbout
  2978.     mov    al,'y'
  2979.     call    prtbout
  2980.     ret
  2981.  
  2982. ; DEC style Soft Reset
  2983. ; Note: graphics rendition is NOT changed by soft reset, DEC manual is wrong.
  2984. atsres    proc    near            ; do soft reset of terminal
  2985.     test    dspstate,dsptype    ; on status line?
  2986.     jz    atsres1            ; z = no, on main display
  2987.     mov    param,0
  2988.     mov    inter,'$'        ; setup entry for atsasd
  2989.     call    atsasd            ; select main display
  2990. atsres1:and    vtemu.vtflgop,not(decawm+decckm+deckpam+decom) ; these go off
  2991.     mov    insmod,0        ; insert mode off
  2992.     mov    mar_top,0        ; reset scrolling margins
  2993.     mov    al,byte ptr low_rgt+1
  2994.     mov    mar_bot,al        ; to full screen
  2995.     mov    anspflg,0        ; clear printer flag
  2996.     mov    al,1            ; restore cursor, assume underline (1)
  2997.     test    vtemu.vtflgop,vscursor    ; underline?
  2998.     jnz    atsres2            ; nz = yes
  2999.     inc    al            ; block (2)
  3000. atsres2:mov    atctype,al        ; save VTxxx cursor type here
  3001.     call    atsctyp            ; set the cursor type
  3002.     push    cursor
  3003.     mov    cursor,0        ; set save cursor to Home
  3004.     call    atsc            ; save attributes
  3005.     pop    cursor            ; restore active cursor
  3006.     call    chrdef            ; set default character set
  3007.     jmp    ansdsl            ; update status line
  3008. atsres    endp
  3009.                     ; DECRQSS/DECRPSS Control Settings
  3010.  
  3011.                     ; Handle DCS ... q string ST
  3012. atcrq:    cmp    ninter,1        ; one intermediate?
  3013.     je    atcrq1            ; e = yes
  3014.     ja    atcrq0            ; a = too many
  3015.     jmp    atcrqq            ; none, do Sixel DCS params q...ST
  3016. atcrq0:    mov    ttstate,offset atdcsnul    ; not understood, consume til ST
  3017.  
  3018. atcrq1:    cmp    inter,'$'        ; correct intermediate?
  3019.     jne    atcrq0            ; ne = no
  3020.     cmp    nparam,0        ; and no parameters?
  3021.     jne    atcrq0            ; ne = have some, not ours
  3022.     mov    ttstateST,offset atcrq4    ; set state for ST arrival
  3023.     mov    ttstate,offset atcrq2    ; next state gets string contents
  3024.     mov    emubufc,0        ; clear buffer counter
  3025.     mov    word ptr emubuf,0    ; empty start of buffer
  3026.     ret
  3027. atcrq2:    mov    bx,emubufc        ; count of chars in string buffer
  3028.     cmp    bx,emubufl        ; too many?
  3029.     jae    atcrq3            ; ae = too many, ignore extras
  3030.     mov    emubuf[bx],al        ; store the char
  3031.     inc    emubufc            ; count it
  3032. atcrq3:    ret
  3033.                     ; here after ST has been seen
  3034. atcrq4:    cmp    emubufc,2        ; max string chars we want
  3035.     jbe    atcrq4a            ; be = ok
  3036.     jmp    atnorm            ; a = too many, ignore
  3037. atcrq4a:mov    ax,word ptr emubuf    ; get first two chars
  3038.     cmp    ax,'}$'            ; select active display?
  3039.     jne    atcrq5            ; ne = no
  3040.     jmp    atcrqd            ; do the routine
  3041. atcrq5:    cmp    ax,'q"'            ; set char attribute?
  3042.     jne    atcrq6            ; ne = no
  3043.     jmp    atcrqxx            ; say we can't do this one
  3044. atcrq6:    cmp    ax,'p"'            ; set conformance level?
  3045.     jne    atcrq7            ; ne = no
  3046.     jmp    atcrqp
  3047. atcrq7:    cmp    ax,'~$'            ; set status line type
  3048.     jne    atcrq8
  3049.     jmp    atcrqt
  3050. atcrq8:    cmp    ax,'r'            ; set top and bottom margins?
  3051.     jne    atcrq9
  3052.     jmp    atcrqr
  3053. atcrq9:    cmp    ax,'m'            ; set graphic rendition?
  3054.     jne    atcrq10
  3055.     jmp    atcrqm
  3056. atcrq10:jmp    atcrqxx            ; unknown command
  3057.                     ; DCS $ q  response routines
  3058. atcrqr:    call    atcrqbeg        ; 'r', top/bottom margins
  3059.     test    dspstate,dsptype    ; doing status line display?
  3060.     jz    atcrqr2            ; z = no
  3061.     mov    al,byte ptr dspmsave    ; get saved top margin
  3062.     inc    al
  3063.     call    prtnout
  3064.     mov    al,';'
  3065.     call    prtbout
  3066.     mov    al,byte ptr dspmsave+1    ; get saved bottom margin
  3067.     jmp    short atcrqr3        ; finish up
  3068. atcrqr2:mov    al,mar_top        ; top margin
  3069.     inc    al            ; move to 1,1 system
  3070.     call    prtnout
  3071.     mov    al,';'
  3072.     call    prtbout
  3073.     mov    al,mar_bot
  3074. atcrqr3:inc    al            ; move to 1,1 system
  3075.     call    prtnout
  3076.     mov    al,'r'            ; final char
  3077.     jmp    atcrqend        ; do epilogue
  3078.  
  3079. atcrqm:    call    atcrqbeg        ; 'm', graphics rendition
  3080.     mov    al,'0'            ; say start with all attributes off
  3081.     call    prtbout
  3082.     mov    ah,scbattr        ; current attribute
  3083.     call    getbold            ; returns ah with bold attr or 0
  3084.     or    ah,ah            ; bold set?
  3085.     je    atcrqm2            ; e = no
  3086.     mov    al,';'
  3087.     call    prtbout
  3088.     mov    al,'1'            ; say bold is on
  3089.     call    prtbout
  3090. atcrqm2:mov    ah,scbattr
  3091.     call    getunder        ; underline
  3092.     or    ah,ah            ; underline on?
  3093.     je    atcrqm3            ; e = no, do next
  3094.     mov    al,';'
  3095.     call    prtbout
  3096.     mov    al,'4'            ; say underlining is on
  3097.     call    prtbout
  3098. atcrqm3:mov    ah,scbattr
  3099.     call    getblink        ; blinking
  3100.     or    ah,ah            ; blinking on?
  3101.     je    atcrqm4            ; e = no
  3102.     mov    al,';'
  3103.     call    prtbout
  3104.     mov    al,'5'            ; say blinking is on
  3105.     call    prtbout
  3106. atcrqm4:cmp    video_state,0        ; chars in reversed video?
  3107.     je    atcrqm5            ; e = no
  3108.     mov    al,';'
  3109.     call    prtbout
  3110.     mov    al,'7'            ; say underlining is on
  3111.     call    prtbout
  3112. atcrqm5:mov    al,'m'            ; final char
  3113.     jmp    atcrqend        ; do epilogue
  3114.  
  3115. atcrqd:    call    atcrqbeg        ; '$}', writing to screen/status line
  3116.     mov    al,'0'            ; assume writing to main display
  3117.     test    dspstate,dsptype    ; get type of display
  3118.     jz    atcrqd2            ; z = main display
  3119.     inc    al            ; say writing to mode line
  3120. atcrqd2:call    prtbout
  3121.     mov    al,'$'            ; final chars
  3122.     call    prtbout
  3123.     mov    al,7dh            ; right curly brace
  3124.     jmp    atcrqend        ; do epilogue
  3125.  
  3126. atcrqt:    call    atcrqbeg        ; '$~', status line
  3127.     mov    al,'0'            ; assume mode line is off
  3128.     test    yflags,modoff        ; is mode line off?
  3129.     jnz    atcrqt2            ; nz = yes
  3130.     mov    al,'2'            ; mode line is on and host writable
  3131. atcrqt2:call    prtbout
  3132.     mov    al,'c'            ; final chars
  3133.     call    prtbout
  3134.     mov    al,7eh            ; tilde
  3135.     jmp    atcrqend        ; do epilogue
  3136.                     ; '"p' set conformance level
  3137. atcrqp:    cmp    oldterm,ttvt100        ; main-mode terminal is VT102?
  3138.     je    atcrqp2            ; e = yes
  3139.     cmp    oldterm,ttvt320        ; how about VT320?
  3140.     je    atcrqp2            ; e = yes
  3141.     jmp    atcrqxx            ; say invalid request
  3142. atcrqp2:mov    al,DCS            ; '"p', conformance level
  3143.     call    out8bit
  3144.     mov    al,'0'            ; valid request
  3145.     call    prtbout
  3146.     mov    al,'$'
  3147.     call    prtbout
  3148.     mov    al,61            ; assume VT102
  3149.     cmp    oldterm,ttvt100        ; are we a VT102?
  3150.     jne    atcrqp3            ; ne = no
  3151.     call    prtnout
  3152.     jmp    short atcrqp5        ; finish the report
  3153.  
  3154. atcrqp3:mov    al,63            ; say VT320
  3155.     call    prtnout
  3156.     mov    al,';'
  3157.     call    prtbout
  3158.     mov    al,'2'            ; assume 8-bit controls are on
  3159.     test    vtemu.vtflgop,vscntl    ; 8-bit controls active?
  3160.     jnz    atcrqp4            ; nz = yes
  3161.     mov    al,'1'            ; else say only 7-bit controls
  3162. atcrqp4:call    prtbout
  3163. atcrqp5:mov    al,'"'            ; final characters
  3164.     call    prtbout
  3165.     mov    al,'p'
  3166.     jmp    atcrqend        ; do epilogue
  3167.  
  3168. atcrqbeg:mov    al,DCS            ; report prologue
  3169.     call    out8bit
  3170.     mov    al,'0'            ; valid request
  3171.     call    prtbout
  3172.     mov    al,'$'
  3173.     jmp    prtbout
  3174.  
  3175. atcrqend:call    prtbout            ; report epilogue, al has char
  3176.     mov    al,STCHR        ; string terminator
  3177.     jmp    out8bit
  3178.  
  3179. atcrqxx:mov    al,DCS            ; report invalid request
  3180.     call    out8bit
  3181.     mov    al,'1'            ; invalid request
  3182.     call    prtbout
  3183.     mov    al,'$'
  3184.     cmp    emubufc,1        ; any first char?
  3185.     jb    atcrqend        ; b = no
  3186.     call    prtbout
  3187.     mov    al,emubuf        ; first string char
  3188.     cmp    emubufc,2        ; two string chars?
  3189.     jne    atcrqend        ; ne = no
  3190.     call    prtbout
  3191.     mov    al,emubuf+1        ; second string char
  3192.     jmp    atcrqend        ; do epilogue
  3193.  
  3194.                     ; DCS P1; P2; P3 <char> Sixel command
  3195. atcrqq:    cmp    dcsstrf,'q'        ; final char of 'q'? Sixel draw
  3196.     je    atcrqq1            ; e = yes
  3197.     cmp    dcsstrf,'p'        ; 'p', restore palette?
  3198.     jne    atcrqq0            ; ne = no
  3199.     cmp    dinter,'$'        ; DCS 2 $ p?
  3200.     jne    atcrqq0            ; ne = no
  3201.     cmp    param,2            ; this too?
  3202.     je    atcrqq1            ; e = yes
  3203. atcrqq0:jmp    atdcsnul        ; consume unknown command
  3204. atcrqq1:test    denyflg,tekxflg        ; is auto Tek mode disabled?
  3205.     jnz    atcrqq0            ; nz = yes, consume
  3206.     mov    di,offset emubuf    ; temp buffer
  3207.     mov    byte ptr [di],escape    ; do ESC ^L to erase screen
  3208.     inc    di
  3209.     mov    byte ptr [di],FF
  3210.     inc    di
  3211.     mov    byte ptr [di],escape    ; start DCS
  3212.     inc    di
  3213.     mov    byte ptr [di],'P'
  3214.     inc    di
  3215.     mov    ax,dparam[0]        ; get first parameter
  3216.     call    dec2di
  3217.     mov    byte ptr [di],';'
  3218.     inc    di
  3219.     mov    ax,dparam[2]        ; get second parameter
  3220.     call    dec2di            ; write ascii value
  3221.     mov    byte ptr [di],';'
  3222.     inc    di
  3223.     mov    ax,dparam[4]        ; get third parameter
  3224.     call    dec2di            ; write ascii value
  3225.     mov    al,dcsstrf
  3226.     mov    byte ptr [di],al    ; final char
  3227.     mov    byte ptr [di+1],0    ; terminator
  3228.     mov    di,offset emubuf
  3229.     mov    al,yflags        ; get yflags
  3230.     and    al,capt            ; save logging bit
  3231.     push    ax
  3232.     and    yflags,not capt        ; turn off logging bit
  3233. atcrqq2:mov    al,[di]
  3234.     inc    di
  3235.     or    al,al            ; at the end?
  3236.     jz    atcrqq3            ; z = yes
  3237.     push    di
  3238.     call    tekemu            ; feed Tek emulator this string
  3239.     pop    di
  3240.     jmp    short atcrqq2        ; do another string member
  3241. atcrqq3:mov    chcontrol,1        ; turn on full cell char writing
  3242.     pop    ax            ; recover logging bit
  3243.     or    yflags,al        ; restate logging bit
  3244.     jmp    atnorm
  3245.  
  3246.                     ; Device Status Reports
  3247. atdsr:    mov    di,offset atdsr1    ; routine to call
  3248.     call    atreps            ; do for all parms
  3249.     ret
  3250.                     ; DSR workers
  3251. atdsr1:    cmp    lparam,0        ; any intermediate?
  3252.     jne    atdsr2            ; ne = yes, an intermediate
  3253.     cmp    param[si],5        ; operating status report?
  3254.     je    rpstat            ; e = yes
  3255.     cmp    param[si],6        ; cursor position report?
  3256.     je    rpcup            ; e = yes
  3257. atdsr2:    cmp    lparam,'?'        ; DEC mode queries for below?
  3258.     jne    atdsr3            ; no, skip them
  3259.     cmp    param[si],15        ; printer status report?
  3260.     je    rpstap            ; e = yes
  3261.     cmp    param[si],25        ; UDK status?
  3262.     jne    atdsr3            ; ne = no
  3263.     jmp    rpudk            ; do udk status rpt
  3264. atdsr3:    cmp    param[si],26        ; keyboard type?
  3265.     jne    atdsr4            ; ne = no
  3266.     jmp    rpkbd            ; do keyboard type report
  3267. atdsr4:    cmp    param[si],256        ; WordPerfect Tek screen query?
  3268.     jne    atdsr5            ; ne = no
  3269.     jmp    tekrpt            ; do Tek report
  3270. atdsr5:    ret                ; must have been an echo
  3271.  
  3272. rpstat:    mov    al,CSI            ; operating status query
  3273.     call    out8bit
  3274.     mov    al,'0'            ; tell them we think we are OK
  3275.     call    prtbout
  3276.     mov    al,'n'
  3277.     call    prtbout
  3278.     ret
  3279.  
  3280. rpcup:    mov    al,CSI            ; cursor position report
  3281.     call    out8bit
  3282.     mov    al,byte ptr cursor+1    ; get row
  3283.     inc    al            ; map to origin at 1,1 system
  3284.     test    vtemu.vtflgop,decom    ; Origin mode set?
  3285.     jz    rpcup1            ; z = no
  3286.     sub    al,mar_top        ; subtract off top margin
  3287. rpcup1: call    prtnout            ; output the number
  3288.     mov    al,';'
  3289.     call    prtbout
  3290.     mov    al,byte ptr cursor    ; column number
  3291.     inc    al            ; map to origin at 1,1 system
  3292.     call    prtnout
  3293.     mov    al,'R'            ; final char
  3294.     call    prtbout
  3295.     ret
  3296.  
  3297. rpstap:    mov    al,CSI            ; printer port query
  3298.     call    out8bit            ; send CSI or ESC [ ? 10 or 13 n 
  3299.     mov    al,'?'            ;  10 = printer ready, 13 = not ready
  3300.     call    prtbout
  3301.     mov    al,'1'
  3302.     call    prtbout
  3303.     mov    ah,ioctl        ; get printer status, via DOS
  3304.     mov    al,7            ; status for output
  3305.     push    bx
  3306.     mov    bx,4            ; std handle for system printer
  3307.     int    dos
  3308.     pop    bx
  3309.     jc    rpstap1            ; c = call failed
  3310.     cmp    al,0ffh            ; code for Ready
  3311.     jne    rpstap1            ; ne = not ready
  3312.     mov    al,'0'            ; ready, send final digit
  3313.     jmp    short rpstap2
  3314. rpstap1:mov    al,'3'            ; not ready, say printer disconnected
  3315. rpstap2:call    prtbout
  3316.     mov    al,'n'            ; final char of response
  3317.     call    prtbout
  3318.     ret
  3319.  
  3320. rpudk:    mov    al,CSI            ; response to UDK locked query
  3321.     call    out8bit
  3322.     mov    al,'?'
  3323.     call    prtbout
  3324.     mov    al,20            ; say keys are unlocked (locked=21)
  3325.     call    prtnout
  3326.     mov    al,'n'            ; final char
  3327.     call    prtbout
  3328.     ret
  3329.  
  3330. rpkbd:    mov    al,CSI            ; response to kbd type query
  3331.     call    out8bit
  3332.     mov    al,'?'
  3333.     call    prtbout
  3334.     mov    al,27            ; keyboard dialect follows
  3335.     call    prtnout
  3336.     mov    al,';'
  3337.     call    prtbout
  3338.     mov    bl,vtemu.vtchset    ; get Kermit NRC code (0-13)
  3339.     xor    bh,bh
  3340.     mov    al,nrckbd[bx]        ; get DEC keyboard code from table
  3341.     call    prtnout
  3342.     mov    al,'n'
  3343.     call    prtbout
  3344.     ret
  3345.  
  3346. tekrpt:    call    tekinq            ; get Tek screen size and num colors
  3347.     push    cx            ; screen colors
  3348.     push    bx            ; screen width
  3349.     push    ax            ; screen height
  3350.     mov    al,CSI            ; response to Tek query
  3351.     call    out8bit
  3352.     mov    al,'?'
  3353.     call    prtbout
  3354.     mov    di,offset emubuf    ; working buffer
  3355.     mov    byte ptr [di],0        ; insert terminator
  3356.     mov    ax,256            ; first parameter
  3357.     call    dec2di            ; write ascii digits
  3358.     mov    byte ptr [di],';'    ; separator
  3359.     inc    di
  3360.     pop    ax            ; get screen height
  3361.     call    dec2di
  3362.     mov    byte ptr [di],';'    ; separator
  3363.     inc    di
  3364.     pop    ax            ; get screen width
  3365.     call    dec2di
  3366.     mov    byte ptr [di],';'    ; separator
  3367.     inc    di
  3368.     pop    ax            ; get number screen color (0, 1 or 16)
  3369.     call    dec2di
  3370.     mov    byte ptr[di],'n'    ; end of sequence
  3371.     inc    di
  3372.     mov    cx,di            ; compute string length
  3373.     mov    di,offset emubuf
  3374.     sub    cx,di
  3375. tekrpt1:mov    al,[di]            ; get a string char
  3376.     inc    di
  3377.     call    prtbout            ; send it
  3378.     loop    tekrpt1
  3379.     ret
  3380.  
  3381. atrqtsr:cmp    flags.vtflg,ttheath    ; Heath-19? ESC [ u
  3382.     jne    atrqts1            ; ne = no
  3383.     cmp    nparam,0        ; ought to have no parameters
  3384.     jne    atrqts2            ; ne = oops, not H-19 command, ignore
  3385.     jmp    atrc            ; H19, restore cursor pos and attrib
  3386.     
  3387. atrqts1:cmp    inter,'$'        ; VT320 Terminal State Rpt DECRQTSR?
  3388.     jne    atrqts2            ; ne = no
  3389.     cmp    param,1            ; report required?
  3390.     je    atrqts4            ; e = yes
  3391.     cmp    param,2            ; VT340 color palette report?
  3392.     jne    atrqts1a        ; ne = no
  3393.     call    tekinq            ; get Tek screen state
  3394.     call    tekpal            ; do palette report in Tek emulator
  3395. atrqts1a:ret
  3396. atrqts2:cmp    inter,'&'        ; DECRQUPSS, User preferred Supp Set?
  3397.     je    atrqts5            ; e = yes
  3398.     ret                ; else ignore
  3399. atrqts4:mov    al,DCS            ; Terminal state report
  3400.     call    out8bit            ; output as 7- or 8-bit quantity
  3401.     mov    al,byte ptr param
  3402.     call    prtnout            ; output as ascii digits, no echo
  3403.     mov    al,'$'
  3404.     call    prtbout            ; output char, no echo
  3405.     mov    al,'s'            ; Final char to main DCS part
  3406.     call    prtbout
  3407.     mov    al,STCHR        ; terminator to empty string
  3408.     call    out8bit
  3409.     ret
  3410.  
  3411. atrqts5:mov    al,DCS            ; User Preferred Supplemental Set
  3412.     call    out8bit            ;  report
  3413.     mov    al,'0'            ; assume 94 byte set
  3414.     cmp    word ptr upss,94    ; 94 byte set?
  3415.     jne    atrqts6            ; ne = no
  3416.     inc    al            ; change to 96 byte size
  3417. atrqts6:call    prtbout
  3418.     mov    al,'!'
  3419.     call    prtbout
  3420.     mov    al,'u'
  3421.     call    prtbout
  3422.     mov    al,upss+1        ; first ident char
  3423.     call    prtbout
  3424.     mov    al,upss+2        ; second char, if any
  3425.     or    al,al
  3426.     jz    atrqts7            ; z = no second char
  3427.     call    prtbout
  3428. atrqts7:mov    al,STCHR
  3429.     call    out8bit
  3430.     ret
  3431.                     ; Request Presentation State Report
  3432. atrqpsr:cmp    inter,'$'        ; proper form?
  3433.     jne    atrqps1            ; ne = no, ignore
  3434.     cmp    param,1            ; cursor report?
  3435.     je    atrqps2            ; e = yes
  3436.     cmp    param,2            ; tabstop report?
  3437.     jne    atrqps1            ; ne = no, ignore
  3438.     jmp    atrqps40        ; do tabstop report
  3439. atrqps1:ret                ; else ignore
  3440.  
  3441. atrqps2:mov    al,DCS            ; cursor report, start
  3442.     call    out8bit
  3443.     mov    al,'1'
  3444.     call    prtbout
  3445.     mov    al,'$'
  3446.     call    prtbout
  3447.     mov    al,'u'
  3448.     call    prtbout
  3449.     mov    al,dh            ; row of cursor
  3450.     inc    al            ; count from 1,1
  3451.     call    prtnout            ; output number
  3452.     mov    al,';'
  3453.     call    prtbout
  3454.     mov    al,dl            ; column of cursor
  3455.     inc    al            ; count from 1,1
  3456.     call    prtnout            ; output number
  3457.     mov    al,';'
  3458.     call    prtbout
  3459.     mov    al,'1'            ; video page, always 1 for VT320
  3460.     call    prtbout
  3461.     mov    al,';'
  3462.     call    prtbout
  3463.     mov    al,40h            ; start bit field template
  3464.     cmp    video_state,1        ; reverse video char writing on?
  3465.     jne    atrqps3            ; ne = no
  3466.     or    al,8            ; set the bit
  3467. atrqps3:call    getblink        ; ah will be non-zero if blinking
  3468.     or    ah,ah            ; blinking?
  3469.     je    atrqps4            ; z = no
  3470.     or    al,4            ; set the bit
  3471. atrqps4:call    getunder        ; ah will be non-zero if underlining
  3472.     or    ah,ah            ; underlining?
  3473.     je    atrqps5            ; z = no
  3474.     or    al,2            ; set the bit
  3475. atrqps5:call    getbold            ; ah will be non-zero if bolding
  3476.     or    ah,ah            ; bold?
  3477.     je    atrqps6            ; z = no
  3478.     or    al,1            ; set the bit
  3479. atrqps6:call    prtbout
  3480.     mov    al,';'
  3481.     call    prtbout
  3482.     mov    al,40h            ; Satt (Selective params), none here
  3483.     call    prtbout            ; output required skeleton
  3484.     mov    al,';'
  3485.     call    prtbout
  3486.     mov    al,40h            ; Sflag (shift/wrap/origin mode)
  3487.     cmp    atwrap,0        ; wrap pending?
  3488.     je    atrqps7            ; e = no
  3489.     or    al,8            ; set the bit
  3490. atrqps7:cmp    SSptr,offset G3set    ; SS3: G3 mapped to GL for next char?
  3491.     jne    atrqps8            ; ne = no
  3492.     or    al,4            ; set the bit
  3493. atrqps8:cmp    SSptr,offset G2set    ; SS2: G2 mapped to GL for next char?
  3494.     jne    atrqps9            ; ne = no
  3495.     or    al,2            ; set the bit
  3496. atrqps9:test    vtemu.vtflgop,decom    ; Origin mode set?
  3497.     jz    atrqps10        ; z = no
  3498.     or    al,1            ; set the bit
  3499. atrqps10:call    prtbout
  3500.     mov    al,';'
  3501.     call    prtbout
  3502.     mov    al,'0'            ; Pgl, say which set is in GL
  3503.     mov    si,GLptr        ; setup for worker
  3504.     call    atrqps30        ; worker returns proper al
  3505.     call    prtbout
  3506.     mov    al,';'
  3507.     call    prtbout
  3508.     mov    al,'0'            ; Pgr, say which set is in GR
  3509.     mov    si,GRptr        ; setup for worker
  3510.     call    atrqps30        ; worker returns proper al
  3511.     call    prtbout
  3512.     mov    al,';'
  3513.     call    prtbout
  3514.     mov    al,40h            ; Scss, char set size bit field
  3515.     call    atrqp15            ; call worker to fill in al
  3516.     call    prtbout    
  3517.     mov    al,';'
  3518.     call    prtbout
  3519.     mov    bx,offset G0set        ; Sdesig, get 1-2 letter ident
  3520.     call    atrqps20        ; G0, let worker fill in response
  3521.     mov    bx,offset G1set
  3522.     call    atrqps20        ; G1, let worker fill in response
  3523.     mov    bx,offset G2set
  3524.     call    atrqps20        ; G2, let worker fill in response
  3525.     mov    bx,offset G3set
  3526.     call    atrqps20        ; G3, let worker fill in response
  3527.     mov    al,STCHR        ; String terminator
  3528.     call    out8bit
  3529.     ret
  3530.  
  3531. ; worker for Character set size reporting
  3532. atrqp15:cmp    G0set+96,gsize        ; is G0 a 96 byte set?
  3533.     jne    atrqp16            ; ne = no
  3534.     or    al,1            ; say 96
  3535. atrqp16:cmp    G1set+96,gsize        ; is G1 a 96 byte set?
  3536.     jne    atrqp17            ; ne = no
  3537.     or    al,2            ; say 96
  3538. atrqp17:cmp    G2set+96,gsize        ; G2 set?
  3539.     jne    atrqp18
  3540.     or    al,4            ; say 96
  3541. atrqp18:cmp    G3set+96,gsize        ; G3 set?
  3542.     jne    atrqp19
  3543.     or    al,8            ; say 96
  3544. atrqp19:ret                ; return with al setup
  3545.  
  3546. ; worker for Character set ident reporting at atrqps16: et seq
  3547. atrqps20:mov    al,[bx+gsize+1]        ; Gn set pointer, first letter
  3548.     call    prtbout
  3549.     mov    al,[bx+gsize+2]        ; second letter
  3550.     or    al,al            ; is there one?
  3551.     jz    atrqps21        ; z = no, nothing there
  3552.     call    prtbout
  3553. atrqps21:ret
  3554.  
  3555. ; worker. Enter with SI holding GLptr or GRptr and al = '0'
  3556. ; Returns al = '0' .. '3' to match set pointed at
  3557. atrqps30:cmp    si,offset G0set        ; si points at G0?
  3558.     je    atrqps31        ; e = yes
  3559.     inc    al            ; try next set
  3560.     cmp    si,offset G1set        ; si points at G1?
  3561.     je    atrqps31
  3562.     inc    al
  3563.     cmp    si,offset G2set        ; si points at G2?
  3564.     je    atrqps31
  3565.     inc    al            ; must be G3
  3566. atrqps31:ret
  3567.  
  3568. atrqps40:mov    al,DCS            ; start tabstop report
  3569.     call    out8bit
  3570.     mov    al,'2'            ; tabs
  3571.     call    prtbout
  3572.     mov    al,'$'
  3573.     call    prtbout
  3574.     mov    al,'u'
  3575.     call    prtbout
  3576.     mov    cl,byte ptr low_rgt    ; right most column number
  3577.     inc    cl            ; number of columns
  3578.     xor    ch,ch
  3579.     push    dx            ; save dx
  3580.     mov    dx,0            ; dh for done one output, dl = column
  3581.     mov    si,offset tabs        ; active tabs buffer
  3582. atrqps41:call    istabs            ; tab inquiry routine, column is in dl
  3583.     jnc    atrqps43        ; nc = no tab
  3584.     or    dh,dh            ; sent one value already?
  3585.     je    atrqps42        ; e = no, so no separator
  3586.     mov    al,';'            ; separator (DEC used '/')
  3587.     call    prtbout
  3588. atrqps42:mov    al,dl            ; get column
  3589.     inc    al            ; count columns from 1 for host
  3590.     call    prtnout            ; output the number
  3591.     inc    dh            ; say sent a number
  3592. atrqps43:inc    dl            ; next column, say sent one output
  3593.     loop    atrqps41        ; do the rest
  3594.     pop    dx            ; recover dx
  3595.     mov    al,STCHR        ; string terminator
  3596.     call    out8bit
  3597.     ret
  3598.     
  3599. ; Process Restore Presentation Reports, for cursor and tab stops
  3600. ; Uses bytes dinter+5 and dinter+6 as internal variables
  3601. atrp:    cmp    dinter,0+'$'        ; correct intermediate?
  3602.     je    atrp1            ; e = yes
  3603.     jmp    atcrqxx            ; send back "illegal restore" response
  3604. atrp1:    cmp    dparam,1        ; cursor info?
  3605.     je    atrp4            ; e = yes
  3606.     mov    modeset,1        ; say setting tabs
  3607.     call    atrpw            ; call worker to do ascii to binary
  3608.     dec    dl            ; count internally from col 0
  3609.     call    tabset            ; set tab in column dl
  3610. atrp3:    mov    emubufc,0        ; clear the string count
  3611.     ret
  3612.                       ; start cursor info report playback
  3613. atrp4:    cmp    dinter+5,0        ; our internal counter in vacant byte
  3614.     jne    atrp5            ; not initial byte
  3615.     inc    dinter+5        ; point to next item next time
  3616.     call    atrpw            ; ascii to binary worker
  3617.     xchg    dh,dl            ; get row to correct byte
  3618.     mov    dl,byte ptr cursor+1    ; get column
  3619.     jmp    atscu5            ; set the cursor
  3620. atrp5:    cmp    dinter+5,1        ; column?
  3621.     jne    atrp6
  3622.     inc    dinter+5        ; point to next item next time
  3623.     call    atrpw            ; ascii to binary worker
  3624.     mov    dh,byte ptr cursor    ; get row
  3625.     jmp    atscu5            ; set the cursor
  3626. atrp6:    cmp    dinter+5,2        ; page?
  3627.     jne    atrp7
  3628.     inc    dinter+5        ; omit page byte
  3629.     ret
  3630. atrp7:    cmp    dinter+5,3
  3631.     jne    atrp8
  3632.     inc    dinter+5        ; Srend
  3633.     mov    al,emubuf        ; string byte
  3634.     mov    ah,curattr        ; attributes field
  3635.                     ; ought to clear attributes first
  3636.     test    al,1            ; set bold?
  3637.     jz    atrp7a            ; z = no
  3638.     call    setbold
  3639. atrp7a:    test    al,2            ; set underline?
  3640.     jz    atrp7b            ; z = no
  3641.     call    setunder
  3642. atrp7b:    test    al,4            ; set blink?
  3643.     jz    atrp7c            ; z = no
  3644.     call    setblink
  3645. atrp7c:    mov    curattr,ah        ; attributes so far
  3646.     test    al,8            ; set per char rev video?
  3647.     jz    atrp7d            ; z = no
  3648.     cmp    video_state,0        ; reversed already?
  3649.     jne    atrp7d            ; ne = yes
  3650.     call    revideo
  3651.     inc    video_state        ; say reversed now
  3652.     mov    curattr,ah
  3653. atrp7d:    ret
  3654. atrp8:    cmp    dinter+5,4
  3655.     jne    atrp9
  3656.     inc    dinter+5        ; Satt, skip it
  3657.     ret
  3658. atrp9:    cmp    dinter+5,5
  3659.     jne    atrp10
  3660.     inc    dinter+5
  3661.     mov    al,emubuf        ; string byte
  3662.     mov    ah,al
  3663.     and    ah,8            ; autowrap bit
  3664.     mov    atwrap,ah        ; set it
  3665.     mov    SSptr,0            ; say no single shift needed
  3666.     test    al,4            ; SS3 bit?
  3667.     jz    atrp9a            ; z = no
  3668.     mov    SSptr,offset G3set    ; set the pointer
  3669. atrp9a:    test    al,2            ; SS2 bit?
  3670.     jz    atrp9b            ; z = no
  3671.     mov    SSptr,offset G2set    ; set the pointer
  3672. atrp9b:    and    vtemu.vtflgop,not decom ; clear origin bit
  3673.     test    al,1            ; origin mode?
  3674.     jz    atrp9c            ; z = no
  3675.     or    vtemu.vtflgop,decom    ; set origin mode
  3676. atrp9c:    ret
  3677. atrp10:    cmp    dinter+5,6        ; Pgl
  3678.     jne    atrp11
  3679.     inc    dinter+5
  3680.     mov    al,emubuf        ; string byte
  3681.     call    atrpw5            ; call worker to setup bx with ptr
  3682.     mov    GLptr,bx
  3683.     ret
  3684. atrp11:    cmp    dinter+5,7        ; Pgr
  3685.     jne    atrp12
  3686.     inc    dinter+5
  3687.     mov    al,emubuf        ; string byte
  3688.     call    atrpw5            ; call worker to setup bx with ptr
  3689.     mov    GRptr,bx
  3690.     ret
  3691. atrp12:    cmp    dinter+5,8        ; Scss
  3692.     jne    atrp13            ; ne = no
  3693.     inc    dinter+5
  3694.     mov    al,emubuf        ; string byte
  3695.     and    al,0fh            ; strip ascii bias
  3696.     mov    dinter+6,al        ; save here for Sdesig byte, next
  3697.     ret
  3698. atrp13:    cmp    dinter+5,9        ; Sdesig
  3699.     jne    atrp14
  3700.     inc    dinter+5
  3701.     mov    si,offset emubuf    ; string
  3702.     xor    cx,cx            ; init loop counter to 0
  3703. atrp13a:mov    al,'('            ; assume G0 is 94 byte set
  3704.     add    al,cl            ; plus loop index to get set pointer
  3705.     shr    dinter+6,1        ; get set size bit
  3706.     jnc    atrp13b            ; e = correct
  3707.     add    al,4            ; map to 96 byte indicator
  3708. atrp13b:mov    inter,al        ; store size byte as intermediate
  3709.     mov    ninter,1        ; one char
  3710.     cld
  3711. atrp13c:lodsb                ; next string byte
  3712.     test    al,not 2fh        ; is there a second intermediate byte?
  3713.     jnz    atrp13d            ; nz = no
  3714.     mov    inter+1,al        ; store intermediate
  3715.     inc    ninter            ; count them
  3716.     jmp    short atrp13c        ; try again for a Final char
  3717. atrp13d:push    si
  3718.     push    cx
  3719.     mov    bx,offset ansesc    ; table to use
  3720.     call    atdispat        ; dispatch on final char to set ptr
  3721.     pop    cx
  3722.     pop    si
  3723.     inc    cx
  3724.     cmp    cx,3            ; doing last one?
  3725.     jbe    atrp13a            ; be = no, do all four
  3726.     ret
  3727. atrp14:    jmp    atcrqxx            ; send back "illegal restore" response
  3728.  
  3729.                     ; worker, ascii string to decimal byte
  3730. atrpw:    mov    cx,emubufc        ; length of this string
  3731.     jcxz    atrpw3            ; nothing there
  3732.     mov    si,offset emubuf    ; address of string
  3733.     xor    dl,dl            ; init final value
  3734.     cld
  3735. atrpw2:    lodsb                ; read a digit
  3736.     sub    al,'0'            ; ascii to numeric
  3737.     jc    atrpw3            ; c = trouble
  3738.     shl    dl,1            ; previous contents times 10
  3739.     mov    dh,dl
  3740.     shl    dl,1
  3741.     shl    dl,1
  3742.     add    dl,dh
  3743.     add    dl,al            ; plus new value
  3744.     loop    atrpw2            ; do all digits
  3745. atrpw3:    ret
  3746.                        ; char set selector worker
  3747. atrpw5:    cmp    al,'0'            ; bx gets G0set...G3set, based on AL
  3748.     jne    atrpw5a
  3749.     mov    bx,offset G0set
  3750.     ret
  3751. atrpw5a:cmp    al,'1'
  3752.     jne    atrpw5b
  3753.     mov    bx,offset G1set
  3754.     ret
  3755. atrpw5b:cmp    al,'2'
  3756.     jne    atrpw5c
  3757.     mov    bx,offset G2set
  3758.     ret
  3759. atrpw5c:mov    bx,offset G3set
  3760.     ret
  3761.  
  3762.  
  3763. ; VT52 compatibility mode routines.
  3764.  
  3765. ; Return to ANSI mode.
  3766.  
  3767. v52ans: or    vtemu.vtflgop,decanm    ; turn on ANSI flag
  3768.     mov    al,oldterm        ; terminal type at startup
  3769.     cmp    al,ttvt52        ; was VT52 the prev kind?
  3770.     jne    v52ans1            ; ne = no
  3771.     mov    al,ttvt320        ; use VT320
  3772. v52ans1:mov    oldterm,al
  3773.     mov    flags.vtflg,al        ; restore it
  3774.     call    chrdef            ; set default char sets
  3775.     call    atsc            ; save cursor status
  3776.     jmp    ansdsl            ; put "LEDs" back
  3777.  
  3778. ; VT52 cursor positioning.
  3779.  
  3780. v52pos: mov    ttstate,offset v52pc1    ; next state
  3781.     ret
  3782. v52pc1: sub    al,' '-1        ; minus offset
  3783.     xor    ah,ah
  3784.     mov    param,ax        ; stash it here
  3785.     mov    ttstate,offset v52pc2    ; next state
  3786.     ret
  3787. v52pc2: sub    al,' '-1        ; minus offset
  3788.     xor    ah,ah
  3789.     mov    param+2,ax        ; stash here
  3790.     mov    ttstate,offset atnrm    ; reset state to "normal"
  3791.     jmp    atcup            ; position and return
  3792.  
  3793. ; VT52 print controls
  3794.  
  3795. v52ps:    mov    param,0            ; print screen
  3796.     mov    lparam,0
  3797.     jmp    ansprt            ; simulate ESC [ 0 i
  3798. v52pl:    mov    param,1            ; print line
  3799.     jmp    short v52pcom        ; simulate ESC [ ? 1 i
  3800. v52pcb:    mov    param,5            ; Enter printer controller on
  3801.     jmp    short v52pcom        ; simulate ESC [ ? 5 i
  3802. v52pce:    mov    param,4            ; Exit printer controller on
  3803. ;    jmp    short v52pcom        ; simulate ESC [ ? 4 i
  3804. v52pcom:mov    lparam,'?'        ; simulate ESC [ ? <number> i
  3805.     jmp    ansprt            ; process command
  3806.  
  3807. v52sgm:    mov    setptr,offset G0set    ; enter/exit special graphics mode
  3808.     jmp    atdg52            ; construct G0set, AL has 'F' or 'G'
  3809.  
  3810. ; Heath-19 special functions
  3811.  
  3812. h19sans:or    vtemu.vtflgop,decanm    ; Turn on ANSI flag. ESC <
  3813.     jmp    chrdef            ; set default char sets
  3814.                     ; clear screen and go home
  3815.  
  3816. h19ed:    cmp    param,0            ; Erase cursor to end of screen?
  3817.     jne    h19ed2            ; ne = no
  3818.     mov    ax,dx            ; start at cursor
  3819.     mov    bh,byte ptr low_rgt+1    ; lower right corner
  3820.     cmp    bh,dh            ; on status line?
  3821.     jae    h19ed1            ; ae = no
  3822.     mov    bh,dh            ; put end on status line
  3823. h19ed1:    mov    bl,crt_cols        ; physical width
  3824.     dec    bl            ; we count from 0
  3825.     jmp    vtsclr            ; clear it
  3826. h19ed2:    cmp    param,1            ; erase start of display to cursor?
  3827.     je    h19esos            ; e = yes
  3828.     cmp    param,2            ; erase entire screen?
  3829.     je    h19clrs            ; e = yes
  3830.     ret                ; else ignore
  3831.  
  3832.                     ; erase entire screen
  3833. h19clrs:cmp    dh,byte ptr low_rgt+1    ; on status line?
  3834.     ja    h19erl            ; a = yes, do just erase in line
  3835.     xor    dx,dx            ; go to upper left corner
  3836.     call    atscu5            ; do it
  3837.     xor    ax,ax            ; clear screen from (0,0)
  3838.     mov    bh,byte ptr low_rgt+1    ; to lower right corner
  3839.     mov    bl,crt_cols        ; physical width
  3840.     dec    bl            ; we count from 0
  3841.     jmp    vtsclr            ; clear it
  3842.  
  3843. h19erl:    xor    al,al            ; erase whole line
  3844.     mov    bl,crt_cols        ; physical width
  3845.     dec    bl            ; we count from 0
  3846.     jmp    erinline        ; erase whole line, cursor stays put
  3847.  
  3848. h19ero:    xor    al,al            ; erase start of line to cursor
  3849.     mov    bl,dl
  3850.     jmp    erinline        ; clear that part of line
  3851.  
  3852.                     ; erase start of screen to cursor
  3853. h19esos:cmp    dh,byte ptr low_rgt+1    ; on status line?
  3854.     ja    h19ero            ; a = yes, do just erase in line
  3855.     jmp    ersos            ; do regular erase start of screen
  3856.  
  3857. h19wrap:or    vtemu.vtflgop,decawm    ; turn on line wrapping
  3858.     ret
  3859. h19nowrp:and    vtemu.vtflgop,not decawm ; turn off line wrapping
  3860.     ret
  3861.  
  3862. h19herv:mov    ah,curattr        ; get current cursor attribute
  3863.     mov    curattr,ah        ; store new attribute byte
  3864.     call    setrev            ; ESC p set reversed video
  3865.     mov    curattr,ah        ; store new attribute byte
  3866.     ret
  3867.  
  3868. h19hxrv:mov    ah,curattr        ; get current cursor attribute
  3869.     call    clrrev            ; ESC q set normal video
  3870.     mov    curattr,ah        ; store new attribute byte
  3871.     ret
  3872.  
  3873. h19sc:    mov    dx,cursor
  3874.     mov    h19cur,dx        ; save cursor position
  3875.     ret
  3876.  
  3877. h19rc:    mov    dx,h19cur        ; saved cursor position
  3878.     jmp    atscu5            ; set cursor and return
  3879.  
  3880.                     ; Heath-19 set mode "ESC x "
  3881. h19smod:mov    ttstate,offset hsmod    ; setup to parse rest of seq
  3882.     ret
  3883. hsmod:    mov    modeset,1        ; say set mode
  3884.     mov    ttstate,offset atnrm
  3885.     sub    al,'0'            ; remove ascii bias
  3886.     jmp    htrsm1            ; perform mode set
  3887.  
  3888. h19cmod:mov    ttstate,offset hcmod    ; setup to parse rest of seq
  3889.     ret
  3890.  
  3891. hcmod:    mov    modeset,0        ; say reset mode
  3892.     mov    ttstate,offset atnrm
  3893.     sub    al,'0'            ; remove ascii bias
  3894.     jmp    htrsm1            ; perform mode reset
  3895.  
  3896. hrcup:    mov    al,escape        ; send "ESC Y row col" cursor report
  3897.     call    prtbout            ; send with no local echo
  3898.     mov    al,'Y'
  3899.     call    prtbout
  3900.     mov    al,byte ptr cursor+1    ; get row
  3901.     add    al,' '            ; add ascii bias
  3902.     call    prtbout            ; send it
  3903.     mov    al,byte ptr cursor    ; get column
  3904.     add    al,' '            ; add ascii bias
  3905.     call    prtbout            ; and send it too
  3906.     ret
  3907.  
  3908. ; Insert/Delete characters and lines
  3909. inslin    proc    near
  3910.     mov    dx,param        ; insert line
  3911.     or    dx,dx            ; any args?
  3912.     jne    insli1            ; ne = yes
  3913.     inc    dx            ; insert one line
  3914. insli1:    mov    scroll,dl        ; lines to scroll
  3915.     mov    dx,cursor        ; current position
  3916.     cmp    dh,mar_bot        ; below bottom margin?
  3917.     ja    insli3            ; a = below bottom margin
  3918.     push    word ptr mar_top
  3919.     mov    mar_top,dh        ; call present position the top
  3920.     call    atscrd            ; scroll down
  3921.     pop    word ptr mar_top    ; restore margins
  3922.     xor    dl,dl            ; go to left margin
  3923.     jmp    atscu5            ; reposition cursor and return
  3924. insli3: ret
  3925. inslin    endp
  3926.  
  3927. dellin    proc    near
  3928.     mov    dx,param        ; delete line(s)
  3929.     or    dx,dx            ; any args?
  3930.     jne    delli1            ; ne = yes
  3931.     inc    dx            ; insert one line
  3932. delli1:    mov    scroll,dl        ; line count
  3933.     mov    dx,cursor        ; where we are presently
  3934.     cmp    dh,mar_bot        ; at or below bottom margin?
  3935.     jae    delli3            ; ae = yes, do not scroll
  3936.     push    word ptr mar_top    ; save current scrolling margins
  3937.     mov    mar_top,dh        ; temp top margin is here
  3938.     call    atscru            ; scroll up
  3939.     pop    word ptr mar_top    ; restore scrolling margins
  3940.     jmp    atscu5            ; restore cursor and return
  3941. delli3: ret
  3942. dellin    endp
  3943.  
  3944. ansich    proc    near            ; ANSI insert characters ESC [ Pn @
  3945.     mov    cx,param
  3946.     or    cx,cx            ; any arguments?
  3947.     jne    ansic1            ; ne = no, ignore
  3948.     inc    cx            ; use one
  3949. ansic1:    push    bx            ; use this as insert/delete flag
  3950.     mov    bh,1            ; do an insert operation
  3951. ansic2:    call    insdel            ; do common insert/delete code
  3952.     pop    bx
  3953.     ret
  3954. ansich    endp
  3955.  
  3956. inschr    proc    near            ; insert open (space) char at cursor
  3957.     push    bx            ; use this as insert/delete flag
  3958.     mov    bh,1            ; do an insert operation
  3959.     mov    cx,1            ; do one character
  3960.     call    insdel            ; do common insert/delete code
  3961.     pop    bx
  3962.     ret
  3963. inschr    endp
  3964.  
  3965. atdelc    proc    near
  3966.     mov    cx,param        ; Delete characters(s)
  3967.     or    cx,cx            ; zero becomes one operation
  3968.     jne    atdelc1
  3969.     inc    cx            ; delete one char. Heath ESC N
  3970. atdelc1:push    bx            ; use this as insert/delete flag
  3971.     mov    bh,-1            ; do a delete operation
  3972. atdelc2:call    insdel            ; do common insert/delete code
  3973.     pop    bx
  3974.     ret
  3975. atdelc    endp
  3976.  
  3977.                     ; Common code for insert/delete char
  3978. insdel    proc    near            ; SI has insert/delete code
  3979.     mov    dx,cursor        ; logical cursor
  3980.     mov    bl,byte ptr low_rgt    ; number of columns on screen - 1
  3981.     push    bx
  3982.     mov    bl,dh            ; cursor row
  3983.     xor    bh,bh            ; bx holds cursor row
  3984.     cmp    linetype [bx],0        ; is line already single width?
  3985.     je    insdel1            ; e = yes
  3986.     add    dl,dl            ; double the cursor column
  3987.     add    cx,cx            ; double repeat count
  3988. insdel1:mov    bl,byte ptr low_rgt    ; physical left margin
  3989.     inc    bl            ; number of screen columns
  3990.     sub    bl,dl            ; width - cursor
  3991.     cmp    cx,bx            ; skipping more than screen width?
  3992.     jbe    insdel2            ; be = no
  3993.     mov    cx,bx            ; limit to screen width please
  3994. insdel2:pop    bx
  3995. ; dh=logical cursor row, dl= logical cursor column, cx has repeat count
  3996. ; bl = logical screen width - 1, bh = +1 for insert, -1 for delete chars.
  3997.     jmp    insdecom        ; do system dependent operation
  3998. insdel    endp
  3999.  
  4000. noins:    mov    insmod,0        ; turn off insert mode
  4001.     ret
  4002.  
  4003. entins:    mov    insmod,0ffh        ; enter insert mode
  4004.     ret
  4005.  
  4006. ; Line type to/from single or double
  4007. linesgl    proc    near            ; convert line to single width char
  4008.     push    ax
  4009.     push    bx
  4010.     push    cx
  4011.     push    dx
  4012.     mov    bx,cursor
  4013.     mov    bl,bh
  4014.     xor    bh,bh            ; bx now holds row
  4015.     cmp    linetype [bx],0        ; is line already single width?
  4016.     je    linsglx            ; e = yes
  4017.     mov    linetype [bx],0        ; say will be single now
  4018.     mov    dh,byte ptr cursor+1    ; row
  4019.     xor    dl,dl            ; start in column 0
  4020.     mov    cl,byte ptr low_rgt    ; number of columns on screen
  4021.     inc    cl
  4022.     shr    cl,1            ; number of columns to do
  4023.     xor    ch,ch
  4024.     push    cx            ; save around loop below
  4025. linsgl1:push    cx            ; save loop counter
  4026.     push    dx
  4027.     shl    dl,1            ; double column number
  4028.     call    direction        ; set dx to desired position
  4029.     call    setpos            ; set cursor position
  4030.     call    getatch            ; read char (al) and attribute (ah)
  4031.     pop    dx
  4032.     push    dx
  4033.     call    direction        ; set dx to desired position
  4034.     call    setpos            ; set cursor position
  4035.     pop    dx
  4036.     call    setatch            ; write char (al) and attribute (ah)
  4037.     inc    dl            ; next column
  4038.     pop    cx
  4039.     loop    linsgl1
  4040.     pop    cx            ; recover column counter
  4041.     mov    dl,cl
  4042. linsgl2:push    cx            ; save counter
  4043.     push    dx
  4044.     call    direction        ; set dx to desired position
  4045.     call    setpos            ; set cursor position
  4046.     mov    ah,scbattr        ; screen background
  4047.     mov    al,' '
  4048.     call    setatch            ; write char
  4049.     pop    dx
  4050.     pop    cx
  4051.     inc    dl            ; next column
  4052.     loop    linsgl2            ; repeat for all characters
  4053. linsglx:pop    dx
  4054.     pop    cx
  4055.     pop    bx
  4056.     pop    ax
  4057.     jmp    atscur            ; update cursor and return
  4058. linesgl    endp
  4059.  
  4060. linedbl    proc    near            ; convert line to double width char
  4061.     push    ax            ; must reset physical cursor
  4062.     push    bx            ; to same char as before expansion
  4063.     push    cx            ; but does not modify variable cursor
  4064.     push    dx
  4065.     mov    bx,cursor
  4066.     mov    bl,bh
  4067.     xor    bh,bh            ; bx now holds row
  4068.     cmp    linetype [bx],0        ; is line single width?
  4069.     jne    lindblx            ; ne = no. nothing to do
  4070.     mov    linetype [bx],1        ; say will be double width now
  4071.     mov    dx,cursor
  4072.     mov    cl,byte ptr low_rgt    ; number of columns on the screen
  4073.     inc    cl
  4074.     xor    ch,ch
  4075.     shr    cl,1            ; number of items to do
  4076.     mov    dl,cl
  4077.     dec    dl
  4078. lindbl1:push    cx            ; save loop counter
  4079.     push    dx
  4080.     call    direction        ; set dx to desired position
  4081.     call    setpos            ; set cursor position
  4082.     call    getatch            ; read char (al) and attribute (ah)
  4083.     pop    dx
  4084.     shl    dl,1            ; double the column number
  4085.     push    dx
  4086.     call    direction        ; set dx to desired position
  4087.     call    setpos            ; set cursor position
  4088.     pop    dx
  4089.     call    setatch            ; write char and attribute
  4090.     inc    dl            ; move to second column of double
  4091.     push    dx
  4092.     call    direction        ; set dx to desired position
  4093.     call    setpos            ; set cursor position
  4094.     pop    dx
  4095.     mov    al,' '            ; space as filler
  4096.     call    setatch            ; write that char
  4097.     dec    dl
  4098.     shr    dl,1
  4099.     dec    dl
  4100.     pop    cx
  4101.     loop    lindbl1
  4102. lindblx:pop    dx
  4103.     pop    cx
  4104.     pop    bx
  4105.     pop    ax
  4106.     jmp    atscur            ; update the cursor and return
  4107. linedbl    endp
  4108.  
  4109. ; Printer support routines
  4110. ansprt    proc near
  4111.     mov    di,offset ansprt0    ; routine to process arguments
  4112.     call    atreps            ; repeat for all parms
  4113.     ret
  4114.  
  4115. ansprt0:mov    ax,param[si]        ; pick up the argument
  4116.     or    ax,ax            ; 0 (print all/part of screen)?
  4117.     jnz    ansprt1            ; nz = no
  4118.     call    pntchk            ; check printer
  4119.     jc    ansprtx            ; c = printer not ready
  4120.     call    pntext            ; do whole screen or scrolling extent
  4121.     jmp    atscu5            ; reposition cursor and return
  4122.  
  4123. ansprt1:cmp    ax,1            ; 1 (print current line)?
  4124.     jne    ansprt4            ; ne = no
  4125.     call    pntchk            ; check for printer ready
  4126.     jc    ansprtx            ; c = printer not ready
  4127.     call    pntlin            ; print current line
  4128.     call    pntflsh            ; flush printer buffer
  4129.     jmp    atscu5            ; reposition cursor and return
  4130.  
  4131. ansprt4:cmp    ax,4            ; 4 (auto print disable)?
  4132.     jne    ansprt5            ; ne = no
  4133.     cmp    lparam,'?'        ; was it ESC [ ? 4 i
  4134.     jne    anspr4a            ; ne = no, so it was ESC [ 4 i
  4135.     test    anspflg,vtautop        ; check state of print flag
  4136.     jz    anspr4a            ; z = off already
  4137.     or    anspflg,vtautop        ; say auto-print enabled to toggle off
  4138.     jmp    trnprs            ; toggle mode line PRN indicator
  4139. anspr4a:ret
  4140.  
  4141. ansprt5:cmp    ax,5            ; 5 (auto print enable)?
  4142.     jne    ansprtx            ; ne = no
  4143.     call    pntchk            ; check printer, ignore carry ret
  4144.     jc    ansprtx            ; c = printer not ready
  4145.     cmp    lparam,'?'        ; was it ESC [ ? 5 i
  4146.     jne    anspr5a            ; ne = no
  4147.     test    anspflg,vtautop        ; is print already enabled?
  4148.     jnz    ansprtx            ; nz = yes, leave trnprs intact
  4149.     and    anspflg,not vtautop    ; say auto-print disabled to toggle on
  4150.     jmp    trnprs            ; toggle on mode line PRN indicator
  4151.  
  4152. anspr5a:test    anspflg,vtcntp        ; controller print already enabled?
  4153.     jnz    ansprtx            ; nz = yes
  4154.     and    anspflg,not vtautop    ; clear single-char flag for toggling
  4155.     or    anspflg,vtcntp        ; controller print enabled
  4156.     mov    emubufc,0        ; clear string buffer
  4157.     mov    ttstate,offset ansmc    ; do transparent print
  4158.     jmp    trnprs            ; toggle on mode line PRN indicator
  4159. ansprtx:ret
  4160. ansprt    endp
  4161.  
  4162. ; State machine active while Media Copy On (Print Controller ON). Copies all
  4163. ; chars to the printer until and excluding Media Copy Off (ESC [ 4 i) or a
  4164. ; repeated Media Copy On (ESC [ 5 i) has been received or the emulator reset.
  4165. ; New char is in al.
  4166. ansmc    proc    near
  4167.     mov    ttstate,offset ansmc    ; stay in this state
  4168.     cmp    al,escape        ; start a new sequence?
  4169.     je    ansmc1            ; e = yes
  4170.     cmp    al,CSI            ; start a new sequence?
  4171.     je    ansmc0a            ; e = yes
  4172.     mov    emubufc,0        ; say no matched chars
  4173.     jmp    pntchr            ; print char in al, ignore errors
  4174.  
  4175.                     ; CSI seen
  4176. ansmc0a:call    ansmc5            ; playback previous matches
  4177.     mov    ttstate,offset ansmc3    ; get numeric arg
  4178.     mov    emubufc,2        ; say matched "ESC ["
  4179.     mov    word ptr emubuf,escape+256*'['    ; store them
  4180.     ret
  4181.                     ; ESC seen
  4182. ansmc1:    call    ansmc5            ; playback previous matches
  4183.     mov    ttstate,offset ansmc2    ; get left square bracket
  4184.     mov    emubufc,1        ; one char matched
  4185.     mov    emubuf,al        ; store it
  4186.     ret
  4187.  
  4188. ansmc2:    cmp    al,'['            ; right square bracket?
  4189.     je    ansmc2a            ; e = yes
  4190.     call    ansmc5            ; playback previous matches
  4191.     jmp    pntchr            ; print char in al, ignore errors
  4192. ansmc2a:inc    emubufc            ; say matched "ESC ["
  4193.     mov    emubuf+1,al        ; store it
  4194.     mov    ttstate,offset ansmc3    ; get numeric arg
  4195.     ret
  4196.                     ; CSI or ESC [ seen
  4197. ansmc3:    inc    emubufc            ; another char
  4198.     mov    emubuf+2,al        ; store it
  4199.     cmp    al,'4'            ; possible MC OFF?
  4200.     je    ansmc3a            ; e = yes
  4201.     cmp    al,'5'            ; possible repeated MC ON?
  4202.     je    ansmc3a            ; e = yes
  4203.     cmp    al,'6'            ; possible CSI 6 i?
  4204.     je    ansmc3a            ; e = yes, keep for a while
  4205.     jmp    ansmc5            ; no, playback previously matched
  4206.  
  4207. ansmc3a:mov    ttstate,offset ansmc4    ; get 'i' Final char
  4208.     ret
  4209.  
  4210. ansmc4:    inc    emubufc            ; last char
  4211.     mov    emubuf+3,al        ; store it
  4212.     cmp    al,'i'            ; correct Final char?
  4213.     je    ansmc4a            ; e = yes
  4214.     jmp    ansmc5            ; playback previous matches
  4215.  
  4216.                     ; CSI 4 i, CSI 5 i, or CSI 6 i seen
  4217. ansmc4a:cmp    emubuf+2,'4'        ; was it CSI 4 i MC OFF?
  4218.     je    ansmc4b            ; e = yes
  4219.     cmp    al,'5'            ; repeated CSI 5 i MC ON?
  4220.     je    ansmc7            ; e = yes, ignore it
  4221.     cmp    flags.vtflg,ttvt100    ; must be CSI 6 i. VT102?
  4222.     jne    ansmc5            ; ne = no, replay it
  4223.     jmp    short ansmc7        ; yes, VT102's absorb CSI 6 i
  4224.                     ; Media OFF found
  4225. ansmc4b:mov    ttstate,offset atnorm    ; return to normal state
  4226.     call    pntflsh            ; flush printer buffer
  4227.     test    anspflg,vtcntp        ; was printing active?
  4228.     jz    ansmc7            ; z = no
  4229.     and    anspflg,not vtcntp    ; yes, disable print controller
  4230.     jmp    trnprs            ; toggle mode line PRN indicator
  4231.  
  4232.                     ; playback emubufc matched chars
  4233. ansmc5:    mov    cx,emubufc        ; matched char count
  4234.     jcxz    ansmc7            ; z = none
  4235.     push    ax            ; save current char in al
  4236.     push    si
  4237.     mov    si,offset emubuf    ; matched sequence, cx chars worth
  4238.     cld
  4239. ansmc6:    lodsb                ; get a char
  4240.     call    pntchr            ; print it, ignore errors
  4241.     loop    ansmc6            ; do all matched chars
  4242.     pop    si
  4243.     pop    ax
  4244. ansmc7:    mov    ttstate,offset ansmc    ; reset state to the beginning
  4245.     ret
  4246. ansmc    endp
  4247.  
  4248. pntlin    proc    near            ; print whole line given by dx
  4249.     push    ax
  4250.     push    bx
  4251.     push    cx
  4252.     push    dx
  4253.     xor    ch,ch
  4254.     mov    cl,byte ptr low_rgt    ; number of columns
  4255.     mov    dl,cl            ; Bios column counter, dh = row
  4256.     inc    cl            ; actual line length, count it down
  4257.     test    vtemu.vtflgop,vswdir    ; writing right to left?
  4258.     jnz    pntlin2            ; nz = yes, do not trim spaces
  4259. pntlin1:call    setpos            ; set cursor
  4260.     call    getatch            ; read char (al) and attribute (ah)
  4261.     cmp    al,' '            ; is this a space?
  4262.     jne    pntlin2            ; no, we have the end of the line
  4263.     dec    dl            ; else move left one column
  4264.     loop    pntlin1            ; and keep looking for non-space
  4265.  
  4266. pntlin2:jcxz    pntlin4            ; z = empty line
  4267.     xor    dl,dl            ; start in column 0, do cl chars
  4268. pntlin3:call    setpos            ; set cursor
  4269.     call    getatch            ; read char (al) and attribute (ah)
  4270.     inc    dl            ; inc to next column
  4271.     call    pntchr            ; print the char (in al)
  4272.     jc    pntlin5            ; c = printer error
  4273.     loop    pntlin3            ; do cx columns
  4274. pntlin4:mov    al,cr            ; add trailing cr/lf for printer
  4275.     call    pntchr
  4276.     jc    pntlin5
  4277.     mov    al,lf
  4278.     call    pntchr
  4279. pntlin5:pop    dx
  4280.     pop    cx
  4281.     pop    bx
  4282.     pop    ax
  4283.     ret                ; C bit controlled by pntchr
  4284. pntlin    endp
  4285.  
  4286. pntext    proc    near            ; print an extent of lines, depending
  4287.     push    ax            ; on flag bit vtextp
  4288.     push    bx
  4289.     push    dx
  4290.     xor    dx,dx            ; assume starting at top left
  4291.     mov    bx,low_rgt        ;  and extending to lower right
  4292.     test    anspflg,vtextp        ; full screen wanted?
  4293.     jnz    pntext1            ; nz = yes, else scrolling region
  4294.     mov    dh,mar_top        ; top of scrolling region
  4295.     mov    bh,mar_bot        ; bottom of scrolling region
  4296. pntext1:call    pntlin            ; print a line
  4297.     jc    pntext2            ; c = printer error
  4298.     inc    dh
  4299.     cmp    dh,bh            ; done all requested lines?
  4300.     jbe    pntext1            ; be = not yet, do another
  4301.     test    anspflg,vtffp        ; form feed needed at end?
  4302.     jz    pntext2            ; z = no
  4303.     mov    al,ff
  4304.     call    pntchr            ; print the form feed char
  4305. pntext2:pop    dx
  4306.     pop    bx
  4307.     pop    ax
  4308.     ret
  4309. pntext    endp
  4310.  
  4311. ; Set cursor coordinate DL (row) with consideration for writing direction.
  4312.  
  4313. direction proc    near
  4314.     test    vtemu.vtflgop,vswdir    ; writing left to right?
  4315.     jz    direct1            ; z = yes, no changes needed
  4316.     sub    dl,byte ptr low_rgt    ; right margin column number
  4317.     neg    dl            ; make a positive value again
  4318. direct1:ret
  4319. direction endp
  4320.  
  4321. ; Erase from cursor (DX, inclusive) to end of screen
  4322. ; sense double width/height
  4323. ereos    proc    near
  4324.     mov    ax,dx            ; erase from cursor to end of screen
  4325.     or    dx,dx            ; cursor at home position?
  4326.     jnz    ereos1            ; nz = no
  4327.                     ; e = yes, roll screen before clear
  4328.     push    word ptr mar_top
  4329.     mov    al,byte ptr low_rgt+1    ; bottom row number
  4330.     mov    mar_bot,al
  4331.     mov    mar_top,0        ; row of cursor
  4332.     inc    al            ; number of lines to scroll
  4333.     mov    scroll,al
  4334.     call    atscru            ; scroll them up before erasure
  4335.     pop    word ptr mar_top
  4336.                     ; removes double w/h lines too
  4337.     xor    ax,ax            ; erase from here (home)
  4338.     mov    bh,byte ptr low_rgt+1    ; bh = bottom row number
  4339.     mov    bl,crt_cols        ; bl = physical columns
  4340.     dec    bl            ; physical width (to here)
  4341.     call    vtsclr            ; clear screen
  4342.     ret
  4343. ereos1:    push    dx            ; save dx
  4344.     mov    bl,dh            ; get row number
  4345.     xor    bh,bh
  4346.     cmp    linetype [bx],0        ; single width line?
  4347.     je    ereos2            ; e = yes
  4348.     shl    dl,1            ; physical column is twice logical
  4349. ereos2:    or    dl,dl            ; starting at left margin?
  4350.     je    ereos3            ; e = yes, this goes to single width
  4351.     inc    bl            ; else start on next line
  4352. ereos3:    cmp    bl,byte ptr low_rgt+1    ; at the end of the screen?
  4353.     ja    ereos4            ; a = yes, stop singling-up
  4354.     mov    byte ptr linetype [bx],0 ; set to single width
  4355.     inc    bx
  4356.     jmp    short ereos3        ; loop, reset lines to end of screen
  4357. ereos4:    mov    bx,low_rgt        ; erase from cursor to end of screen
  4358.     mov    bl,crt_cols
  4359.     dec    bl            ; do physical screen width
  4360.     call    vtsclr            ; clear it
  4361.     pop    dx            ; restore dx
  4362.     ret
  4363. ereos    endp
  4364.  
  4365. ; Erase from start of screen to cursor (inclusive), sense double width/height
  4366. ersos    proc    near
  4367.     xor    ax,ax            ; erase from start of screen
  4368.                     ;  to cursor, inclusive
  4369.     xor    bx,bx            ; start at top row (0)
  4370. ersos1:    cmp    bl,dh            ; check rows from the top down
  4371.     jae    ersos2            ; ae = at or below current line
  4372.     mov    byte ptr linetype [bx],0; set line to single width
  4373.     inc    bx            ; inc row
  4374.     jmp    short ersos1        ; look at next line
  4375. ersos2:    or    dl,dl            ; at left margin of current line?
  4376.     jne    ersos3            ; ne = no, leave line width intact
  4377.     mov    byte ptr linetype [bx],0 ; convert to single width    
  4378. ersos3:    mov    bl,dh            ; get row number
  4379.     xor    bh,bh
  4380.     cmp    linetype [bx],0        ; single width line?
  4381.     je    ersos4            ; e = yes
  4382.     shl    dl,1            ; physical column is twice logical
  4383. ersos4:    mov    bx,dx            ; cursor position to bx
  4384.     call    vtsclr            ; clear it
  4385.     ret
  4386. ersos    endp
  4387.  
  4388. ; Erase in line, from column AL to column BL, in row DH
  4389. erinline proc    near
  4390.     mov    ah,dh            ; set row
  4391.     mov    bh,dh
  4392.     push    bx
  4393.     mov    bl,dh            ; get row
  4394.     xor    bh,bh
  4395.     cmp    linetype [bx],0        ; single width line?
  4396.     pop    bx            ; pop does not affect flags
  4397.     je    erinli1            ; e = yes
  4398.     shl    bl,1            ; physical column is twice logical
  4399. erinli1:call    vtsclr            ; clear it
  4400.     ret
  4401. erinline endp
  4402.  
  4403. ; Clear screen from AX to BX, where AH = row, AL = column, ditto for BX.
  4404. ; This routine accomodates right to left writing. BX >= AX.
  4405. vtsclr    proc    near
  4406.     test    vtemu.vtflgop,vswdir    ; writing left to right?
  4407.     jz    vtsclr4            ; z = yes
  4408.     cmp    bh,ah            ; same row?
  4409.     je    vtsclr2            ; e = yes
  4410.     push    ax            ; multiple lines
  4411.     push    bx            ; save both coordinates
  4412.     mov    bl,byte ptr low_rgt    ; get right most logical column
  4413.     mov    bh,ah            ; pick just top line
  4414.     call    vtsclr2            ; delete fraction of top line
  4415.     pop    bx            ; recover ending position
  4416.     push    bx
  4417.     inc    ah            ; omit top row, now done
  4418.     dec    bh            ; omit last line, could be fractional
  4419.     cmp    bh,ah            ; any whole lines remaining to delete?
  4420.     jb    vtsclr1            ; b = no, finish up
  4421.     mov    bl,byte ptr low_rgt    ; get right most physical column
  4422.     xor    al,al            ; to end of line (on left)
  4423.     call    atsclr            ; clear top line and whole remainders
  4424. vtsclr1:pop    bx            ; setup for last line to be cleared
  4425.     push    bx            ; get last row again
  4426.     xor    al,al            ; start at logical left margin
  4427.     jmp    short vtsclr3        ; ax and bx are already pushed
  4428.  
  4429. vtsclr2:push    ax            ; erase single line, whole or part
  4430.     push    bx
  4431. vtsclr3:mov    ah,byte ptr low_rgt    ; borrow reg ah (same as bh)
  4432.     sub    ah,bl            ; reflect right to left
  4433.     mov    bl,ah
  4434.     or    bl,bl            ; overflow?
  4435.     jns    vtsclr5            ; ns = no, is ok
  4436.     xor    bl,bl            ; limit to logical screen
  4437. vtsclr5:mov    ah,byte ptr low_rgt
  4438.     sub    ah,al
  4439.     mov    al,ah
  4440.     jns    vtsclr6
  4441.     mov    al,byte ptr low_rgt    ; limit to logical screen
  4442. vtsclr6:mov    ah,bh            ; restore ah
  4443.     xchg    al,bl            ; reverse to get physical ax < bx
  4444.     call    atsclr            ; erase part/all of single line
  4445.     pop    bx
  4446.     pop    ax
  4447.     ret
  4448.                     ; for writing left to right
  4449. vtsclr4:jmp    atsclr            ; do normal erasure and return
  4450. vtsclr    endp
  4451.  
  4452. ; routines supporting scrolling and double width/height chars
  4453. ; scroll has number of lines to scroll
  4454. atscru    proc    near            ; scroll screen up one line
  4455.     push    ax            ; assumes dx holds cursor position
  4456.     push    bx            ; returns with dx = old row, new col
  4457.     push    cx
  4458.     push    si
  4459.     xor    bh,bh
  4460.     mov    bl,mar_top        ; top line to move
  4461.     xor    ch,ch
  4462.     mov    cl,scroll        ; number of lines to move
  4463.     mov    al,mar_bot        ; bottom line to scroll
  4464.     sub    al,bl            ; number of lines minus 1
  4465.     inc    al            ; number of lines
  4466.     cmp    al,cl            ; scrolling region smaller than scroll?
  4467.     jge    atscru1            ; ge = no, is ok
  4468.     mov    scroll,al        ; limit to region
  4469.     cmp    al,1            ; at least one line to scroll?
  4470.     jge    atscru1            ; ge = yes
  4471.     mov    scroll,1        ; no, force one
  4472. atscru1:mov    al,scroll
  4473.     mov    ah,byte ptr low_rgt+1    ; last text line on screen
  4474.     inc    ah            ; number of screen lines
  4475.     cmp    al,ah            ; exceeds number of lines on screen?
  4476.     jbe    atscru8            ; be = scrolling not more than that
  4477.     mov    al,ah            ; limit to screen length
  4478.     mov    scroll,al
  4479. atscru8:xor    ah,ah
  4480.     mov    si,ax            ; scroll interval
  4481.     mov    bl,mar_top
  4482.     mov    cl,mar_bot
  4483.     sub    cl,bl
  4484.     inc    cl            ; number  of lines in region
  4485.     sub    cl,scroll        ; cx = those needing movement
  4486.     cmp    cl,0
  4487.     jle    atscru3
  4488. atscru2:mov    al,linetype[bx+si]    ; get old type
  4489.     mov    linetype[bx],al        ; copy to new higher position
  4490.     inc    bx
  4491.     loop    atscru2
  4492. atscru3:mov    bl,mar_bot        ; set fresh lines to single attribute
  4493.     mov    cl,scroll        ; number of fresh lines (qty scrolled)
  4494.     xor    ch,ch
  4495. atscru4:mov    linetype[bx],0
  4496.     dec    bx
  4497.     loop    atscru4            ; clear old bottom lines
  4498.     mov    bl,dh            ; get row of cursor
  4499.     xor    bh,bh
  4500.     cmp    linetype[bx],0        ; single width?
  4501.     je    atscru5            ; e = yes
  4502.     shr    dl,1            ; reindex to single width columns
  4503. atscru5:pop    si
  4504.     pop    cx
  4505.     pop    bx
  4506.     pop    ax
  4507.     test    anspflg,vtcntp        ; controller print active?
  4508.     jz    atscru6            ; z = no, ok to change screen
  4509.     ret                ;  else keep screen intact
  4510. atscru6:jmp    vtscru            ; call & ret the msy scroll routine
  4511. atscru    endp
  4512.  
  4513. atscrd    proc    near            ; scroll screen down scroll lines
  4514.     push    ax            ; assumes dx holds cursor position
  4515.     push    bx            ; returns with dx = old row, new col
  4516.     push    cx
  4517.     push    si
  4518.     xor    ch,ch
  4519.     mov    cl,scroll        ; number of lines to scroll
  4520.     xor    bh,bh
  4521.     mov    bl,mar_bot        ; bottom line to move
  4522.     mov    al,bl
  4523.     xor    ah,ah
  4524.     sub    al,mar_top        ; number of lines minus 1
  4525.     inc    al            ; number of lines
  4526.     cmp    al,cl            ; scrolling region smaller than scroll?
  4527.     jge    atscrd1            ; ge = no, is ok
  4528.     mov    scroll,al        ; limit to region
  4529.     cmp    al,1            ; at least one line to scroll?
  4530.     jge    atscrd1            ; ge = yes
  4531.     mov    scroll,1        ; no, force one
  4532. atscrd1:mov    al,scroll
  4533.     mov    si,ax            ; si = scroll
  4534.     mov    bl,dh            ; get row of cursor
  4535.     xor    bh,bh            ; make into an index
  4536.     sub    bl,scroll        ; si + this bx will be new bottom line
  4537.     mov    cl,bl
  4538.     sub    cl,mar_top
  4539.     inc    cl
  4540.     cmp    cl,0
  4541.     jle    atscrd3
  4542. atscrd2:mov    al,linetype[bx]        ; get old line's type
  4543.     mov    linetype[bx+si],al    ; copy to new lower position
  4544.     dec    bx
  4545.     loop    atscrd2
  4546. atscrd3:mov    bl,mar_top        ; start with this line
  4547.     xor    bh,bh
  4548.     mov    cl,scroll        ; number of lines scrolled
  4549.     xor    ch,ch
  4550. atscrd4:mov    linetype[bx],0        ; clear new top lines
  4551.     inc    bx
  4552.     loop    atscrd4
  4553.     mov    bl,dh            ; get row of cursor
  4554.     xor    bh,bh
  4555.     cmp    linetype[bx],0        ; single width?
  4556.     je    atscrd5            ; e = yes
  4557.     shr    dl,1            ; reindex to single width columns
  4558. atscrd5:pop    si
  4559.     pop    cx
  4560.     pop    bx
  4561.     pop    ax
  4562.     test    anspflg,vtcntp        ; controller print active?
  4563.     jz    atscrd6            ; z = no, ok to change screen
  4564.     ret                ;  else keep screen intact
  4565. atscrd6:jmp    vtscrd            ; call & ret the msy scroll routine
  4566. atscrd    endp
  4567.  
  4568. ; Returns carry set if column in DL is a tab stop, else carry clear.
  4569. ; Enter with column number in DL (starts at column 0, max of swidth-1)
  4570. ; and tabstop buffer offset in SI.
  4571. istabs    proc    near
  4572.     push    bx
  4573.     push    cx
  4574.     mov    cl,dl            ; column number (0 to swidth-1)
  4575.     and    cl,00000111b        ; keep bit in byte (0-7)
  4576.     inc    cl            ; map to 1-8
  4577.     mov    bl,dl            ; column
  4578.     shr    bl,1            ; bl / 8 to get byte
  4579.     shr    bl,1
  4580.     shr    bl,1
  4581.     xor    bh,bh            ; clear high byte
  4582.     mov    bl,[si+bx]        ; get a byte of tab bits
  4583.     ror    bl,cl            ; rotate to put tab-set bit into carry
  4584.     pop    cx
  4585.     pop    bx
  4586.     ret
  4587. istabs    endp
  4588.  
  4589. ; Modify (set/clear) a tabstop. Enter with DL holding column (0 to swidth-1)
  4590. ; Set a tabstop into buffer pointed at by SI.
  4591. tabset    proc    near
  4592.     mov    modeset,1        ; set a tabstop
  4593.     jmp    short modtabs
  4594. tabset    endp
  4595.  
  4596. ; Clear a tabstop
  4597. tabclr    proc    near
  4598.     mov    modeset,0        ; clear a tabstop
  4599.     jmp    short modtabs
  4600. tabclr    endp
  4601.  
  4602. ; Worker for set/clear tabstop, si has pointer to tabstops array
  4603. modtabs:push    bx
  4604.     push    cx
  4605.     mov    cl,dl            ; column number (0 to swidth-1)
  4606.     and    cl,00000111b        ; keep bit in byte (0-7)
  4607.     mov    ch,1            ; tab bit to change
  4608.     shl    ch,cl            ; shift to bit-in-byte position
  4609.     mov    bl,dl            ; column
  4610.     shr    bl,1            ; bl / 8 to get byte
  4611.     shr    bl,1
  4612.     shr    bl,1
  4613.     xor    bh,bh            ; clear high byte
  4614.     mov    cl,[si+bx]        ; get byte of tabs bits
  4615.     not    ch            ; invert bit marker to create hole
  4616.     and    cl,ch            ; clear the tab bit
  4617.     not    ch            ; recover setting pattern
  4618.     cmp    modeset,0        ; clear the tab bit?
  4619.     jz    modtab1            ; z = yes
  4620.     or    cl,ch            ; set the tab bit
  4621. modtab1:mov    [si+bx],cl        ; store tab byte
  4622.     pop    cx
  4623.     pop    bx
  4624.     ret
  4625.  
  4626. ; This routine initializes the VT100 setups at startup.     It is called from
  4627. ; procedure lclyini in module msyibm.
  4628. vsinit    proc    near
  4629.     mov    vtemu.vtflgst,vsdefaults ; Init to defaults in mssdef.h
  4630.     mov    vtemu.vtflgop,vsdefaults ; Init runtime state to setup items
  4631.     mov    savflgs,vsdefaults
  4632.     mov    iniflgs,vsdefaults
  4633.     mov    insmod,0        ; turn off insert mode
  4634.     xor    dl,dl            ; Column 1 has no tab stop
  4635.     mov    si,vtemu.vttbs        ; from the cold-start buffer
  4636.     call    tabclr            ; clear that tabstop
  4637.     mov    cl,crt_cols        ; physical screen width (80)
  4638.     dec    cl            ; we count from column 0
  4639.     mov    ch,crt_lins        ; physical screen length-1
  4640.     dec    ch            ; we count from row 0
  4641.     mov    low_rgt,cx        ; store active text area
  4642.     push    es
  4643.     push    ds
  4644.     pop    es
  4645.     cld
  4646.     mov    al,1            ; set tabs at columns 9, spaced by 8
  4647.     mov    cx,(swidth-1)/8        ; bytes to do, at 8 bits/byte
  4648.     mov    di,offset deftabs+1    ; starting byte for column 9 (1...)
  4649.     rep    stosb
  4650.     mov    cx,slen            ; clear linetype array
  4651.     mov    di,offset linetype
  4652.     rep    stosb
  4653.     pop    es
  4654.     mov    vtemu.vttbst,offset tabs ; addrs of active tabs for STATUS
  4655.     mov    vtemu.vttbs,offset deftabs  ; addrs of tabs for setup (SET)
  4656.     call    cpytabs            ; copy default to active
  4657.     mov    vtemu.att_ptr,offset att_normal  ; ptr to video attributes
  4658.     mov    ah,byte ptr low_rgt    ; right most column (counted from 0)
  4659.     sub    ah,8            ; place marker 9 columns from margin
  4660.     mov    belcol,ah        ; store column number to ring bell
  4661.     ret
  4662. vsinit    endp
  4663.  
  4664. ; Initialization routine.
  4665. ; Enter with dl = index for baud rate table
  4666. ; dh = parity in bits 4-7, number of data bits in bits 0-3
  4667. ansini    proc    near
  4668.     mov    ax,vtemu.vtflgst    ; setup flags
  4669.     mov    vtemu.vtflgop,ax
  4670.     mov    iniflgs,ax
  4671.     mov    savflgs,ax
  4672.     mov    al,flags.vtflg        ; get current terminal type
  4673.     mov    oldterm,al        ; remember it here for soft restarts
  4674.     mov    anspflg,0        ; clear printing flag
  4675.     mov    al,byte ptr low_rgt    ; right most column (counted from 0)
  4676.     sub    al,8            ; place marker 9 columns from margin
  4677.     mov    belcol,al        ; store column number to ring bell
  4678.     cmp    dl,lbaudtab        ; out of range index?
  4679.     jb    ansin1            ; b = no, store it
  4680.     mov    dl,lbaudtab-1        ; yes, make it the maximum
  4681. ansin1: mov    baudidx,dl        ; save baud rate index
  4682.     mov    al,dh            ; get parity/number of databits
  4683.     and    al,0FH            ; isolate number of databits
  4684.     mov    datbits,al        ; save
  4685.     mov    cl,4
  4686.     shr    dh,cl            ; isolate parity code
  4687.     cmp    dh,lpartab        ; out of range code?
  4688.     jb    ansin2            ; b = no, store it
  4689.     mov    dh,lpartab-1        ; make it the maximum
  4690. ansin2: mov    parcode,dh        ; save
  4691.     mov    cl,crt_cols        ; physical screen number columns (80)
  4692.     dec    cl            ; we count from column 0 here
  4693.     mov    ch,crt_lins        ; physical screen number rows-1 (24)
  4694.     dec    ch            ; we count from row 0 here
  4695.     mov    low_rgt,cx        ; save as active text screen size
  4696.     mov    oldscrn,cx        ; remember old screen dimensions
  4697.     jmp    atreset            ; reset everything
  4698. ansini    endp
  4699.  
  4700. atxreset    proc    near        ; Reset via host command
  4701.     cmp    nparam,0        ; need no Parameters, no Intermediates
  4702.     jne    atxres1            ; ne = not a reset
  4703.     cmp    ninter,0
  4704.     je    atreset            ; e = none, it is a reset
  4705. atxres1:ret                ; ignore command
  4706. atxreset endp
  4707.  
  4708. atreset    proc    near            ; Reset-everything routine
  4709.     mov    cursor,0        ; cursor is at 0,0
  4710.     mov    al,1            ; assume underline cursor
  4711.     test    vtemu.vtflgst,vscursor    ; kind of cursor in setup
  4712.     jnz    atres0            ; nz = underline
  4713.     dec    al            ; else say block
  4714. atres0:    mov    atctype,al        ; VTxxx cursor type
  4715.     mov    h19cur,0        ; Heath-19 saved cursor
  4716.     mov    dspstate,0        ; saved modeline state
  4717.     call    udkclear        ; clear User Definable Key contents
  4718.     push    vtemu.vtflgst        ; setup flags
  4719.     pop    vtemu.vtflgop        ; operational flags
  4720.     and    vtemu.vtflgop,not vscntl ; assume no 8-bit controls
  4721.     mov    al,oldterm        ; get terminal at entry time
  4722.     mov    flags.vtflg,al        ; use it again
  4723.     cmp    flags.vtflg,ttvt100    ; VT100?
  4724.     je    atres1            ; e = yes, turn on ansi mode
  4725.     cmp    flags.vtflg,ttvt320    ; VT320?
  4726.     jne    atres1a            ; ne = no, no ansi, no 8-bit controls
  4727.     test    vtemu.vtflgst,vscntl    ; want 8-bit controls?
  4728.     jz    atres1            ; z = no
  4729.     or    vtemu.vtflgop,vscntl    ; turn on 8-bit controls
  4730. atres1:    or    vtemu.vtflgop,decanm    ; turn on ANSI mode
  4731. atres1a:mov    mar_top,0        ; reset scrolling region
  4732.     mov    al,byte ptr low_rgt+1
  4733.     mov    mar_bot,al
  4734.     mov    cx,4            ; initialize the "LEDs"
  4735.     mov    al,led_off        ; turn off all of them
  4736.     mov    di,offset ansleds+6    ; point to the "LEDs"
  4737.     push    es            ; save es
  4738.     push    ds
  4739.     pop    es            ; use data segment for es:di below
  4740.     cld                ; set forward direction
  4741.     rep    stosb
  4742.     pop    es
  4743.     call    ansdsl            ; update mode line
  4744.     call    cpytabs            ; initialize tab stops
  4745.     cmp    flags.vtflg,ttvt320    ; VT320?
  4746.     je    atres1b            ; e = yes
  4747.     cmp    flags.vtflg,ttvt100    ; VT102?
  4748.     jne    atres1c            ; ne = no
  4749. atres1b:mov    al,vtemu.vtchset    ; setup char set
  4750.     cmp    al,1            ; in range for NRCs?
  4751.     jb    atres1c            ; b = no
  4752.     cmp    al,12            ; highest NRC ident?
  4753.     ja    atres1c            ; a = not NRC
  4754.     or    vtemu.vtflgop,vsnrcm    ; set NRC flag bit to activate NRCs
  4755. atres1c:mov    vtemu.vtchop,al        ; remember char set
  4756.     call    chrdef            ; set default character sets
  4757.     call    vtbell            ; ring bell like VT100
  4758.     cmp    flags.modflg,2        ; mode line owned by host?
  4759.     jne    atres2            ; ne = no
  4760.     mov    flags.modflg,1        ; say now owned by us
  4761.                     ; ATRES2 used in 80/132 col resetting
  4762. ATRES2:    mov    cx,slen            ; typically 24 but do max lines
  4763.     mov    di,0
  4764. atres3:    mov    linetype[di],0        ; clear the linetype array to single
  4765.     inc    di            ; width/height characters
  4766.     loop    atres3
  4767.            mov    ah,att_normal        ; get present normal coloring
  4768.     call    clrbold            ; clear attributes
  4769.     call    clrblink
  4770.     call    clrunder
  4771.     mov    scbattr,ah        ; set background attributes
  4772.     mov    curattr,ah        ; and cursor attributes
  4773.     test    vtemu.vtflgop,vsscreen    ; want reverse video?
  4774.     jz    atres4            ; z = no
  4775.     call    atrss2            ; reverse screen and attributes (ah)
  4776. atres4:    mov    video_state,0        ; say normal per char video
  4777.     xor    ax,ax            ; starting location
  4778.     mov    bh,crt_lins        ; number or rows on screen
  4779.     dec    bh            ; count from 0
  4780.     mov    bl,crt_cols        ; number of columns on screen
  4781.     dec    bl            ; count from 0
  4782.     call    atsclr            ; clear the whole screen
  4783.     mov    dx,cursor        ; get cursor
  4784.     call    atscu5            ; set cursor
  4785.     call    atsctyp            ; set right cursor type
  4786.     cmp    flags.modflg,1        ; mode line on and owned by us?
  4787.     jne    atres5            ; ne = no, leave it alone
  4788.     test    yflags,modoff        ; mode line supposed to be off?
  4789.     jnz    atres5            ; nz = yes
  4790.     push    dx
  4791.     call    modlin            ; write normal mode line
  4792.     pop    dx
  4793. atres5:    call    atpclr            ; clear parser work area
  4794.     mov    parstate,0        ; reset parser
  4795.     mov    emubufc,0        ; clear work buffer
  4796.     mov    atwrap,0        ; clear wrap flag
  4797.     mov    SSptr,0            ; clear single shift flag
  4798.     mov    insmod,0        ; reset insert mode
  4799.     mov    h19stat,0        ; clear heath extended status byte
  4800.     mov    h19ctyp,1        ; Heath-19 cursor to underline
  4801.     mov    anspflg,0        ; clear printer flag
  4802.     call    atsc            ; save cursor information
  4803.     mov    ttstate,offset atnrm    ; normal state
  4804.     ret
  4805. atreset    endp
  4806.  
  4807. ; Re-initialization routine. Called when Term was called but screen was
  4808. ; restored from a previously saved screen, etc.
  4809. ansrei    proc    near
  4810.     call    atsctyp            ; set cursor type [rbv]
  4811.     call    getpos            ; get cursor position from msy
  4812.     mov    cursor,dx        ; dh = row, dl = column
  4813.     mov    cl,crt_cols        ; physical screen number columns (80)
  4814.     dec    cl            ; we count from column 0 here
  4815.     mov    ch,crt_lins        ; physical screen number rows-1 (24)
  4816.     dec    ch            ; we count from row 0 here
  4817.     mov    low_rgt,cx        ; save as active text screen size
  4818.     test    vtemu.vtflgop,deccol    ; want 80 columns?
  4819.     jnz    ansre2            ; nz = no
  4820.     cmp    byte ptr low_rgt,79    ; want 80 cols. Is active screen wider?
  4821.     jbe    ansre2            ; be = no
  4822.     mov    byte ptr low_rgt,79    ; narrow down to 80 columns
  4823. ansre2:    call    direction        ; cursor to writing direction column
  4824.     mov    cursor,dx        ; store as logical position
  4825.     push    cx            ; save current physical screen size
  4826.     call    stblmds            ; check settable modes, set flags
  4827.     pop    cx
  4828.     cmp    cx,oldscrn        ; has screen size changed?
  4829.     je    ansre3            ; e = no, same as last time
  4830.     mov    oldscrn,cx        ; remember new size 
  4831.     mov    mar_top,0        ; reset scrolling region
  4832.     mov    al,byte ptr low_rgt+1
  4833.     mov    mar_bot,al
  4834.     jmp    atres2            ; better do soft reset
  4835. ansre3:    ret
  4836. ansrei    endp
  4837.  
  4838. ; This routine checks to see whether any of the settable modes have changed
  4839. ; (things that can be changed in both SETUP and by host commands), and
  4840. ; changes those that need to be changed.  TMPFLAGS has the new VT100 setup
  4841. ; flags, VTFLAGS has the old. This routine also updates VTFLAGS.
  4842. ; Revised by [jrd] to allow MSY to reset scbattr when not in connect mode,
  4843. ; to do "soft reset" if terminal type has changed, and to do a screen clear
  4844. ; reset if the actual screen colors have changed.
  4845.  
  4846. stblmds proc    near
  4847.     mov    al,flags.vtflg        ; get current terminal type
  4848.     cmp    al,oldterm        ; same as before?
  4849.     je    stblm10            ; e = yes, skip over soft reset
  4850.     mov    oldterm,al        ; remember current terminal type
  4851.     mov    insmod,0        ; reset insert mode flag
  4852.     and    iniflgs,not vsnrcm    ; turn off NRC bit from last time
  4853.     mov    mar_top,0        ; reset top scrolling margin
  4854.     mov    al,byte ptr low_rgt+1    ; and scrolling margin
  4855.     mov    mar_bot,al        ; to last normal line on screen
  4856.     mov    ah,byte ptr low_rgt    ; right most column (counted from 0)
  4857.     sub    ah,8            ; place marker 9 columns from margin
  4858.     mov    belcol,ah        ; store column number to ring bell
  4859. ;;;;    and    ansflgs,decckm+deckpam+decom+dececho+vscntl ; save some flags
  4860.     push    bx            ; save this register around loop
  4861.     mov    bx,offset linetype    ; setup to clear double width chars
  4862.     mov    cx,slen            ; number of linetype slots to clear
  4863. stblm0:    mov    byte ptr [bx],0        ; clear the linetype array to single
  4864.     inc    bx            ;  width characters
  4865.     loop    stblm0            ; do each line (1 byte per line)
  4866.     pop    bx            ; restore bx
  4867.     cmp    flags.vtflg,ttvt320    ; VT320?
  4868.     je    stblm0b            ; e = yes
  4869.     cmp    flags.vtflg,ttvt100    ; VT100 now?
  4870.     jne    stblm10            ; ne = no
  4871. stblm0b:or    vtemu.vtflgop,decanm    ; set ansi flag bit
  4872.  
  4873. stblm10:mov    al,vtemu.vtchset    ; setup character set
  4874.     cmp    al,vtemu.vtchop        ; operational character set
  4875.     je    stblm3            ; e = same, no changes needed
  4876.     mov    vtemu.vtchop,al        ; remember this set
  4877.     and    vtemu.vtflgop,not vsnrcm ; clear NRC active bit
  4878.     and    vtemu.vtflgst,not vsnrcm
  4879.     cmp    al,1            ; in range for NRC?
  4880.     jb    stblm11            ; b = no
  4881.     cmp    al,12            ; above NRCs?
  4882.     ja    stblm11            ; a = yes
  4883.     or    vtemu.vtflgop,vsnrcm    ; set NRC active bit
  4884.     or    vtemu.vtflgst,vsnrcm
  4885.     and    vtemu.vtflgop,not vscntl ; no 8-bit controls
  4886. stblm11:call    chrdef            ; init char sets
  4887.  
  4888. stblm3:    cmp    vtclear,1        ; screen need updating?
  4889.     jb    stblm9            ; b = no
  4890.     ja    stblm3a            ; 2 or more means do a reset
  4891.     mov    ah,att_normal        ; 1, get new normal attributes setting
  4892.     mov    scbattr,ah        ; store new values
  4893.     mov    curattr,ah
  4894.     jmp    short stblm9
  4895. stblm3a:mov    cursor,0        ; reset cursor position
  4896.     jmp    atres2            ; go to semi-reset
  4897.  
  4898.                     ; check on screen normal/reversed
  4899. stblm9:    mov    ax,iniflgs        ; flags at last entry
  4900.     xor    ax,vtemu.vtflgst    ; find which setup ones have changed
  4901.     test    ax,vsscreen        ; screen background?
  4902.     jz    stblm8            ; z = no, don't touch it
  4903.     test    vtemu.vtflgop,vsscreen    ; reverse video flag set?
  4904.     jnz    stblm5            ; nz = yes, do it
  4905.     and    vtemu.vtflgop,not vsscreen ; cleared (normal video)
  4906.     jmp    short stblm6        ; reverse everything
  4907. stblm5: or    vtemu.vtflgop,vsscreen    ; set (reverse video)
  4908. stblm6: call    atrss2            ; reverse screen and cursor attribute
  4909.     mov    ah,scbattr        ; reset saved attribute also
  4910.     mov    savecu+svattr_index,ah
  4911. stblm8:    cmp    flags.modflg,2        ; mode line enabled and owned by host?
  4912.     je    stblm9a            ; e = yes, leave it alone
  4913.     call    clrmod            ; clear the mode line
  4914.     test    yflags,modoff        ; mode line supposed to be off?
  4915.     jnz    stblm9a            ; nz = yes
  4916.     call    modlin            ; write normal mode line
  4917.     and    yflags,not modoff    ; say modeline is not toggled off
  4918. stblm9a:mov    dx,cursor        ; logical cursor
  4919.     push    dx
  4920.     call    direction        ; set cursor for writing direction
  4921.     call    setpos            ; set the cursor physical position
  4922.     pop    dx
  4923.     push    vtemu.vtflgst
  4924.     pop    iniflgs            ; remember setup flags at this entry
  4925.     ret
  4926. stblmds endp
  4927.  
  4928. ; Routine called when something is typed on the keyboard
  4929.  
  4930. anskbi    proc    near
  4931.     mov    ttkbi,0FFH        ; just set a flag
  4932.     ret
  4933. anskbi    endp
  4934.  
  4935.  
  4936. ; This routine copies the new tab stops when they have changed.
  4937. ; Copies all 132 columns.
  4938. cpytabs proc    near
  4939.     mov    cx,(swidth+7)/8        ; number of bytes in screen width
  4940.     jcxz    cpytab1            ; z = none to do
  4941.     mov    si,offset deftabs    ; source is setup array
  4942.     mov    di,offset tabs        ; destination is active array
  4943.     push    es            ; save es
  4944.     push    ds
  4945.     pop    es            ; set es to data segment
  4946.     cld
  4947.     rep    movsb            ; do the copy
  4948.     pop    es            ; recover es
  4949. cpytab1:ret
  4950. cpytabs endp
  4951.  
  4952. ; Routine to toggle VT100/VT52/Heath-19 modes. No arguments.
  4953. ; Use & update global byte flags.vtflg for terminal type and update local
  4954. ; bit decanm. Note: shifting to Heath-19 here does Not reset the scrolling
  4955. ; margins mar_top & mar_bot nor reset the double char linetype array.
  4956.  
  4957. ans52t    proc    near
  4958.     cmp    tekflg,0        ; in Tek sub mode?
  4959.     je    ans52h            ; e = no
  4960.     jmp    ans52e            ; yes, get out now
  4961. ans52h:    cmp    flags.vtflg,ttvt320    ; in VT320 mode?
  4962.     jne    ans52a            ; ne = no
  4963.     or    vtemu.vtflgop,decanm    ; set ansi mode
  4964.     mov    flags.vtflg,ttvt100    ; say VT100 now
  4965.     mov    oldterm,ttvt100        ; and remember it
  4966.     jmp    ans52g
  4967.  
  4968. ans52a:    cmp    flags.vtflg,ttvt100    ; in VT100 mode?
  4969.     jne    ans52b            ; ne = no
  4970.     and    vtemu.vtflgop,not decanm ; reset ansi mode
  4971.     mov    flags.vtflg,ttvt52    ; say VT52 now (clears ansi bit)
  4972.     mov    oldterm,ttvt52        ; and remember it
  4973.     jmp    ans52g
  4974.  
  4975. ans52b:    cmp    flags.vtflg,ttvt52    ; in VT52 mode?
  4976.     jne    ans52c            ; ne = no
  4977.     cmp    dspstate,dsptype    ; on status line?
  4978.     jz    ans52b1            ; z = no
  4979.     push    param            ; save these two fellows
  4980.     mov    ah,inter
  4981.     push    ax
  4982.     mov    param,0            ; setup call to atsasd
  4983.     mov    inter,'$'
  4984.     call    atsasd            ; get back to main display screen
  4985.     pop    ax
  4986.     pop    param            ; recover parsing parameters
  4987.     mov    inter,ah
  4988. ans52b1:mov    flags.vtflg,ttheath    ; say Heath-19 now
  4989.     mov    oldterm,ttheath
  4990.     jmp    ans52g
  4991.  
  4992. ans52c:    cmp    flags.vtflg,ttheath    ; in Heath-19 mode?
  4993.     jne    ans52e            ; ne = no
  4994.     test    denyflg,tekxflg        ; is Tek mode disabled?
  4995.     jz    ans52d            ; z = no, enabled
  4996.     mov    flags.vtflg,ttvt320    ; say VT320 now
  4997.     mov    oldterm,ttvt320
  4998.     or    vtemu.vtflgop,decanm    ; set, go to VT320 mode
  4999.     jmp    short ans52f        ; end Tek mode
  5000.  
  5001. ans52d:    call    atsc            ; save cursor and associated data
  5002.     mov    flags.vtflg,tttek    ; set Tek mode
  5003.     mov    tekflg,0        ; not a sub mode
  5004.     call    tekini            ; init Tek to switch screens
  5005.     jmp    atnorm            ; normal state and return
  5006.  
  5007. ans52e:    cmp    flags.vtflg,tttek    ; in Tek mode now?
  5008.     je    ans52f            ; e = yes
  5009.     cmp    tekflg,0        ; doing Tek sub mode?
  5010.     jne    ans52f            ; ne = yes
  5011.     jmp    atnorm            ; else ignore this call
  5012.  
  5013. ans52f:    call    tekend            ; exit Tek graphics mode
  5014.     mov    flags.vtflg,ttvt320    ; say VT320 now
  5015.     mov    oldterm,ttvt320
  5016.     or    vtemu.vtflgop,decanm    ; set, go to VT320 mode
  5017.     call    atrc            ; restore cursor etc
  5018.     cmp    flags.modflg,0        ; is mode line disabled?
  5019.     je    ans52g            ; e = yes, disabled
  5020.     test    yflags,modoff        ; Mode line off?
  5021.     jnz    ans52g            ; nz = yes, return
  5022. ans52g:    call    atsc            ; save cursor etc
  5023.     call    ansdsl            ; remove or redisplay "LEDs"
  5024.     jmp    atnorm            ; set state to "normal" and return
  5025. ans52t    endp
  5026.  
  5027.  
  5028. ; Display "LEDs" routine. yflags from MSYIBM is needed to know if the mode
  5029. ; line is enabled. Display current state of "LEDs" on line 25.
  5030. ansdsl    proc    near            ; display "LEDs"
  5031.     test    yflags,modoff        ; mode line off?
  5032.     jnz    ansdsl2            ; nz = yes, just return
  5033.     cmp    flags.modflg,1        ; mode line on and owned by us?
  5034.     jne    ansdsl2            ; ne = no, leave it intact
  5035.     mov    dh,byte ptr low_rgt+1    ; last screen line - 1
  5036.     inc    dh            ; status line
  5037.     mov    dl,led_col        ; column for led display
  5038.     call    setpos            ; set cursor position at (slen-1),70
  5039.     mov    cx,10            ; length of byte array is ten
  5040.     cld
  5041.     mov    si,offset v32leds    ; VT320 ident
  5042.     cmp    flags.vtflg,ttvt320    ; VT320?
  5043.     je    ansdsl1            ; e = yes
  5044.     mov    si,offset ansleds    ; VT102 ident
  5045.     cmp    flags.vtflg,ttvt100    ; VT100 mode?
  5046.     je    ansdsl1            ; e = yes
  5047.     mov    si,offset v52leds    ; VT52 ident
  5048.     cmp    flags.vtflg,ttvt52    ; VT52?
  5049.     je    ansdsl1            ; e = yes
  5050.     mov    si,offset h19leds    ; Heath-19 ident
  5051. ansdsl1:lodsb                ; get a character
  5052.     call    putchar            ; write character, increment cursor
  5053.     loop    ansdsl1            ; loop for all chars
  5054.     mov    dx,cursor        ; reposition cursor when finished
  5055.     push    dx
  5056.     call    direction        ; set dx to desired position
  5057.     call    setpos            ; set cursor position
  5058.     pop    dx
  5059. ansdsl2:ret
  5060. ansdsl    endp
  5061.  
  5062. ; This routine is called to adjust the cursor for the "indexing" like commands
  5063. ; (e.g., index, reverse index, newline, etc.).    It contrains the cursor, and
  5064. ; indicates if scrolling is necessary, and if so, in which direction.
  5065. ;
  5066. ; Call: cursor = "old" cursor position
  5067. ;    dx =     "new" cursor position
  5068. ;
  5069. ; Return: ax = pointer to scrolling routine to call (or to a ret)
  5070. ;      bx = "old" cursor position
  5071. ;      dx = "new" cursor position adjusted for screen limits or
  5072. ;               scrolling region, depending on whether the original
  5073. ;               cursor position was inside or outside the scrolling region.
  5074. ;
  5075. ; On the VT100, a scroll does not occur unless the original cursor position
  5076. ; was on the top or bottom margin. This routine assumes that when decom is
  5077. ; set the cursor position is set to the new origin, and that no other routine
  5078. ; allows the cursor to be positioned outside the scrolling region as long
  5079. ; as decom is set (which is the way a real VT100 works).  Note that for the
  5080. ; normal case (no limited scrolling region defined) the margins are the same
  5081. ; as the screen limits and scrolling occurs (as on a "normal" terminal) when
  5082. ; an attempt is made to index off the screen. Preserves cx.
  5083.  
  5084. atccic    proc    near
  5085.     push    cx
  5086.     mov    cl,byte ptr low_rgt    ; get right margin
  5087.     mov    bl,dh            ; get row
  5088.     xor    bh,bh
  5089.     cmp    bl,crt_lins        ; below screen?
  5090.     jae    atcci0            ; ae = yes, use single width line
  5091.     cmp    linetype[bx],0        ; single width chars?
  5092.     je    atcci0            ; e = yes, single width
  5093.     shr    cl,1            ; halve margin for double wides
  5094. atcci0:    mov    ax,offset atign        ; assume no scrolling necessary
  5095.     mov    bx,cursor        ; get old cursor
  5096.     cmp    dl,250            ; left of left margin? (wide screen)
  5097.     jb    atcci1            ; b = no, go check right
  5098.     xor    dl,dl            ; set to left margin
  5099. atcci1: cmp    dl,cl            ; right of right margin
  5100.     jbe    atcci2            ; be = yes, go check top
  5101.     mov    dl,cl            ; set to right margin
  5102. atcci2:    pop    cx
  5103.     cmp    bh,mar_top        ; was old pos at scrolling top margin?
  5104.     jne    atcci5            ; ne = no, check other end
  5105.     cmp    dh,mar_top        ; want to go above top margin?
  5106.     jge    atcci5            ; ge = no
  5107.     mov    scroll,1
  5108.     mov    ax,offset atscrd    ; indicate scroll down required
  5109.     mov    dh,mar_top        ; set to top margin
  5110.     jmp    atcci7
  5111.  
  5112. atcci5:    cmp    bh,mar_bot        ; was old position at bottom margin?
  5113.     jne    atcci7            ; ne = no, so don't trap cursor
  5114.     cmp    dh,mar_bot        ; want to go below?
  5115.     jb    atcci7            ; b = no, nothing to worry about
  5116.     mov    scroll,1        ; 1 line
  5117.     mov    ax,offset atscru    ; indicate scroll up required
  5118.     mov    dh,mar_bot        ; set to bottom margin
  5119.     ret
  5120. atcci7:    jmp    atccpc            ; old pos was outside scrolling region
  5121. atccic    endp
  5122.  
  5123. ; This routine is called to check the cursor position after any kind of cursor
  5124. ; positioning command.    Note that cursor positioning does NOT cause scrolling
  5125. ; on a VT100 (hence the need for a routine separate from this for "indexing".
  5126. ; Call:    dx = "new" cursor position (modified cursor)
  5127. ; Return: dx = "new" cursor position adjusted for screen limits (if
  5128. ;        decom is reset), or scrolling region (if decom is set).
  5129. ; Preserves ax, bx, and cx.
  5130.  
  5131. atccpc    proc    near
  5132.     push    bx            ; save bx and cx
  5133.     push    cx
  5134.     mov    cx,low_rgt        ; margins, cl = right margin
  5135.     mov    bl,dh            ; get row
  5136.     xor    bh,bh
  5137.     cmp    linetype [bx],0        ; single width line?
  5138.     je    atccp0            ; e = yes, single width
  5139.     shr    cl,1            ; halve right margin for double wides
  5140. atccp0:    cmp    dl,250            ; to left of left margin?(wide screen)
  5141.     jb    atccp1            ; b = no, go check right
  5142.     xor    dl,dl            ; set to left margin
  5143. atccp1: cmp    dl,cl            ; to right of right margin?
  5144.     jbe    atccp2            ; be = yes, go check top
  5145.     mov    dl,cl            ; set to right margin
  5146. atccp2:    pop    cx
  5147.     pop    bx
  5148.     test    vtemu.vtflgop,decom    ; Origin mode set?
  5149.     jnz    atccp5            ; nz = yes, stay in scrolling region
  5150.     cmp    dh,0            ; above top of screen?
  5151.     jge    atccp3            ; ge = no, check bottom
  5152.     xor    dh,dh            ; stop here
  5153. atccp3: cmp    dh,byte ptr low_rgt+1    ; below bottom of screen?
  5154.     jle    atccp4            ; le = no, return
  5155.     mov    dh,byte ptr low_rgt+1    ; stop at bottom margin
  5156.     cmp    flags.vtflg,ttheath    ; Heath-19 mode?
  5157.     jne    atccp4            ; ne = no
  5158.     test    h19stat,h19l25        ; 25th line enabled?
  5159.     jz    atccp4            ; z = no
  5160.     inc    dh            ; allow 25th line
  5161. atccp4:    ret
  5162.  
  5163. atccp5: cmp    dh,mar_top        ; above top of scrolling region?
  5164.     jge    atccp6            ; ge = no, check bottom
  5165.     mov    dh,mar_top        ; yes, stop there
  5166. atccp6: cmp    dh,mar_bot        ; below bottom perhaps?
  5167.     jle    atccp4            ; le = no, return
  5168.     mov    dh,mar_bot        ; yes, stop at the bottom margin
  5169.     ret
  5170. atccpc    endp
  5171.  
  5172. ; Select Active Display. When selecting the status line make new scrolling
  5173. ; margins be just the status line and force on Origin mode. Save the regular
  5174. ; margins and origin mode for restoration when regular display is re-selected.
  5175. atsasd    proc    near
  5176.     cmp    inter,'$'        ; correct intermediate?
  5177.     jne    atsasd1            ; ne = no
  5178.     cmp    param,1            ; select which display
  5179.     jb    atsasd4            ; b = select main display
  5180.     ja    atsasd1            ; a = illegal value
  5181.     cmp    flags.modflg,2        ; mode line host owned?
  5182.     jne    atsasd1            ; ne = no, ignore command
  5183.     test    dspstate,dsptype    ; was previous display = status line?
  5184.     jz    atsasd2            ; z = no
  5185. atsasd1:ret                ; else do nothing
  5186.  
  5187. atsasd2:push    word ptr mar_top    ; save scrolling margins
  5188.     pop    dspmsave        ; save scrolling margins
  5189.     or    dspstate,dsptype    ; say status line is active
  5190.     mov    al,byte ptr low_rgt+1    ; get last text line
  5191.     inc    al            ; status line
  5192.     mov    mar_top,al
  5193.     mov    mar_bot,al        ; new scrolling margins
  5194.     and    dspstate,not dspdecom    ; clear remembered origin mode
  5195.     test    vtemu.vtflgop,decom    ; was origin mode active?
  5196.     jz    atsasd3            ; z = no
  5197.     or    dspstate,dspdecom    ; remember origin mode was active
  5198. atsasd3:or    vtemu.vtflgop,decom    ; set origin mode
  5199.     push    cursor            ; get current main display cursor
  5200.     pop    dspcmain        ; save it
  5201.     mov    dx,dspcstat        ; get status line cursor
  5202.     mov    dh,mar_top        ; set row
  5203.     jmp    atscu5            ; set cursor
  5204.  
  5205. atsasd4:test    dspstate,dsptype    ; was previous display = status line?
  5206.     jnz    atsasd5            ; nz = yes
  5207.     ret                ; else do nothing    
  5208. atsasd5:push    dspmsave        ; restore scrolling margins
  5209.     pop    word ptr mar_top
  5210.     and    vtemu.vtflgop,not decom    ; clear origin mode bit
  5211.     test    dspstate,dspdecom    ; was origin mode on for main screen?
  5212.     jz    atsasd6            ; z = no
  5213.     or    vtemu.vtflgop,decom    ; set it now
  5214. atsasd6:push    cursor            ; get status line cursor position
  5215.     pop    dspcstat        ; save it
  5216.     mov    dx,dspcmain        ; get saved cursor position
  5217.     mov    dspstate,0        ; say now doing main screen
  5218.     jmp    atscu5            ; set cursor
  5219. atsasd    endp
  5220.  
  5221. atssdt    proc    near            ; Select Status Line Type, DECSSDT
  5222.     cmp    inter,'$'        ; correct intermediate char?
  5223.     je    atssdt1            ; e = yes
  5224.     ret
  5225. atssdt1:test    dspstate,dsptype    ; on mode line already?
  5226.     jnz    atssdt4            ; nz = yes, cannot reselect now
  5227.     cmp    param,0            ; turn off status line?
  5228.     jne    atssdt2            ; ne = no
  5229.     push    dx            ; save cursor position
  5230.     call    clrmod            ; clear the line
  5231.     pop    dx
  5232.     or    yflags,modoff        ; now say it's off
  5233.     mov    flags.modflg,1        ; say mode line is owned by us
  5234.     ret
  5235. atssdt2:cmp    param,1            ; regular status line?
  5236.     jne    atssdt3
  5237.     push    dx
  5238.     call    modlin            ; turn on regular mode line
  5239.     pop    dx
  5240.     and    yflags,not modoff    ; and say it's on
  5241.     mov    flags.modflg,1        ; say mode line is owned by us
  5242.     ret
  5243. atssdt3:cmp    param,2            ; host writable?
  5244.     jne    atssdt4            ; ne = no
  5245.     mov    flags.modflg,2        ; say mode line is owned by host
  5246. atssdt4:ret
  5247. atssdt    endp
  5248.  
  5249. ; Routine to set cursor type (off, block, underline).
  5250.  
  5251. atsctyp:cmp    flags.vtflg,ttheath    ; Heath-19?
  5252.     jne    atsct1            ; ne = no
  5253.     mov    al,h19ctyp        ; get cursor kind and on/off bit
  5254.     test    al,4            ; is cursor to be off?
  5255.     jz    atsct4            ; z = no, al has kind
  5256.     xor    al,al            ; turn off cursor
  5257.     jmp    short atsct4        ; do it
  5258. atsct1:    test    atctype,4        ; VTxxx cursor type, off?
  5259.     jz    atsct2            ; z = no
  5260.     xor    al,al
  5261.     jmp    short atsct4        ; turn it off
  5262. atsct2:    mov    al,1            ; assume underline
  5263.     test    vtemu.vtflgop,vscursor    ; block?
  5264.     jnz    atsct3            ; nz = no, underline
  5265.     mov    al,2
  5266. atsct3:    mov    atctype,al        ; save VTxxx cursor type here
  5267. atsct4:    call    csrtype            ; set the cursor type
  5268.     ret
  5269.  
  5270. atdeb    proc    near            ; Debug, display all chars in tty style
  5271.     test    yflags,capt        ; capturing output?
  5272.     jz    atdeb3            ; z = no, forget this part
  5273.     push    ax            ; save char
  5274.     call    cptchr            ; give it captured character
  5275.     pop    ax            ; restore character and keep going
  5276. atdeb3:    mov    bl,curattr        ; save attribute
  5277.     push    bx
  5278.     push    word ptr mar_top    ; save limited scrolling region
  5279.     push    ax            ; save character for a second
  5280.     mov    ah,curattr        ; get attribute
  5281.     call    clrblink        ; clear blink attribute
  5282.     call    clrunder        ; clear underline attribute
  5283.     mov    curattr,ah        ; store
  5284.     or    vtemu.vtflgop,decawm    ; set autowrap temporarily
  5285.     mov    mar_top,0        ; set scrolling region to entire page
  5286.     mov    al,byte ptr low_rgt+1
  5287.     mov    mar_bot,al
  5288.     pop    ax            ; restore character
  5289.     test    al,80h            ; high bit set?
  5290.     jz    atdeb0            ; z = not set
  5291.     push    ax            ; save the character for a second
  5292.     mov    al,7eh            ; output a tilde
  5293.     call    atnrm2
  5294.     pop    ax            ; restore character
  5295.     and    al,7fh            ; and remove high bit
  5296. atdeb0:    cmp    al,del            ; DELETE?
  5297.     je    atdeb1            ; e = yes, output "^?"
  5298.     cmp    al,20h            ; control character?
  5299.     jnb    atdeb2            ; nb = no, just output char in al
  5300. atdeb1: push    ax            ; save the character for a second
  5301.     mov    al,5eh            ; output a caret
  5302.     call    atnrm2
  5303.     pop    ax            ; restore character
  5304.     add    al,40h            ; make ^letter (or ^? for DELETE)
  5305.     and    al,7fh            ; clear bit 7 (for DELETE)
  5306. atdeb2: call    atnrm2            ; output translated character
  5307.     pop    word ptr mar_top    ; restore scrolling region,
  5308.     pop    bx            ;  flags, and cursor attribute
  5309.     mov    curattr,bl
  5310.     ret
  5311. atdeb    endp
  5312. code    ends
  5313.     end
  5314.