home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / modem / term.zip / TERM.ASM < prev    next >
Assembly Source File  |  1988-02-07  |  34KB  |  1,327 lines

  1. ;
  2. ;   vi:set ts=8:
  3. ;
  4. TITLE   terminal program
  5. ;
  6. ;    This is version 2.2 of TERM. TERM is a terminal program that
  7. ;    emulates a zenith z19 terminal. It's main feature is, that it is
  8. ;    memory-resident. This allows you to run two tasks simultaneouly,
  9. ;    one on your dos machine, the other on the host computer.
  10. ;    You can switch easily back and forth by pressing the hotkey.
  11. ;    TERM has a 2048 character receive buffer, and receives characters 
  12. ;    while you are doing other things under Dos. The characters are
  13. ;    printed on the screen, when you switch back to the host.
  14. ;    When term receives the bell character, while it's in the
  15. ;    background, it will switch immediately to the foreground.
  16. ;    Thus, you are notified if you receive mail (biff) or
  17. ;    someone wants to talk with you
  18. ;
  19. ;      Mail problems, suggestions or bug reports to:
  20. ;
  21. ;          Karl Gegenfurtner
  22. ;
  23. ;arpa:     karl@hipl.psych.nyu.edu
  24. ;uucp      {ihnp4|seismo|allegra}!cmcl2!xp!hipl!karl
  25. ;usps:     New York University
  26. ;          Dept. of Psychology
  27. ;          6 Washington Place 8th floor
  28. ;          New York, NY 10003
  29. ;
  30. ;    In the case, that you make major improvements to term,
  31. ;    like adding file transfer capabilities, I really would
  32. ;    want to get copy of the program, before you sell it.
  33. ;    
  34. ;    History:
  35. ;    - fall 1986: Version 1.0 by Hans Irtel, Uni Regensburg
  36. ;             output is via ansi driver int 29h
  37. ;             send xoff/xon when switching
  38. ;    - spring 87: Version 2.0 by Karl Gegenfurtner, New York University
  39. ;             added z19 emulation
  40. ;             rewrote the comm-initialization routines
  41. ;             made the dos interface well-behaved
  42. ;             put xon/xoff into interrupt routine
  43. ;    - april  87: Version 2.1 Wed Apr 01 18:35:05 1987
  44. ;             added alarm feature
  45. ;              added support for monochrome card
  46. ;    - april  87: Version 2.2 Thu Apr 02 19:12:39 1987
  47. ;             dynamically allocate rxbuffer to reduce prog size
  48. ;             fix cexit bug (restore comm int)
  49. ;             fix the monochrome cursor
  50. ;             add keypad enter pseudo sequences for xp
  51. ;             moved cinit and cexit to non-resident part
  52. ;             made some equates to variables for install
  53. ;             fix the silly bug in kb_int, which caused two
  54. ;            instances of term running simultaneously
  55. ;                Wed Apr 08 20:06:07 1987
  56. ;             fixed init code in enab
  57. ;             
  58. ;
  59. ;    Future:
  60. ;    - write installation program
  61. ;    - add some primitive functions for reinitializing etc.
  62. ;
  63. ;
  64. ;
  65. ;   installation equates
  66. ;
  67. Ifgcolor    equ        74h
  68. Ibgcolor    equ        47h
  69. Iswitchcode equ     3400h   ; 3400h is F12 on an AT
  70.                 ; 4400 is F10 on a PC
  71.                 ; 7000 is alt-f9 on a PC
  72. Itport        equ        2        ; comm port to use
  73. Iline_par   equ     11100011b
  74.                 ; comm line parameters
  75.                 ; 8 data bits, 1 stopbit, no parity
  76. logo        equ     "HI"    ; for Hans Irtel
  77. terminal_page equ   1       ; alternate video page
  78. show_ctrl   equ        0        ; show ctrl chars as ^x
  79. ;
  80. ;   other useful defines
  81. ;
  82. xon         equ     11h
  83. xoff        equ     13h
  84. eoi         equ     20h     ; non-specific eoi
  85. c1mask      equ     0efh
  86. c2mask      equ     0f7h
  87. c1off       equ     10h
  88. c2off       equ     08h
  89. c1base      equ     03f8h
  90. c2base      equ     02f8h
  91. c1int       equ     0ch
  92. c2int       equ     0bh
  93. int_enable  equ     1
  94. line_control    equ     3
  95. modem_control   equ     4
  96. line_status     equ     5
  97. buflen      equ     2048
  98. maxcount    equ     buflen-64
  99. lowcount    equ     128
  100.  
  101. chesc   equ     27
  102. bel     equ     7
  103. cr      equ     13
  104. lf      equ     10
  105. bs      equ     8
  106. tab     equ     9
  107.  
  108. screen  equ     10h                     ; bios screen call
  109. screensize equ  25*80
  110.  
  111. timer   equ     40h                     ; timer port
  112. bel_prt equ     61h                     ; speaker control
  113.  
  114. crt_status equ  3dah                    ; crt status port
  115. disp_enb   equ  8                       ; display enable bit
  116.  
  117. code_seg segment
  118.     assume cs:code_seg, ds:code_seg, es:code_seg
  119.  
  120.     org 100H
  121.  
  122. terminal proc far
  123.     jmp install
  124. terminal endp
  125.  
  126. ;
  127. ;   the first data may be changed by the installation program
  128. ;
  129. fgcolor     DB     Ifgcolor
  130. bgcolor     DB    Ibgcolor
  131. tport        DW  Itport
  132. line_par    DB  Iline_par
  133. switchcode  DW  Iswitchcode
  134. ;
  135. ;   data for routines
  136. ;
  137.  
  138. old_com1    DW  00H
  139. old_com2    DW  00H
  140. kb_bios     label dword
  141. old_kb1     DW  00H
  142. old_kb2     DW  00H
  143. rxbuffer    DW  offset lastbyte
  144. buf_end     DW  offset lastbyte + buflen
  145. head        DW  offset lastbyte
  146. tail        DW  offset lastbyte
  147. tflag       DB  0
  148. alarm        DB  0
  149. bw        DB  0
  150. count       DW  0
  151. txoff       DB  0
  152. rxoff       DB  0
  153. rxfull      DB  0
  154. cbase       DW  0
  155. cmask       DB  0
  156. coff        DB  0
  157. cint        DB  0
  158. freemem     DW  offset lastbyte + buflen
  159. usersave    DW  offset lastbyte + buflen + 2
  160. termsave    DW  offset lastbyte + buflen + 2 + screensize * 2
  161. mofreemem   DW  offset lastbyte + buflen + 2 + screensize * 2 * 2
  162. usercursor  DW  0
  163. termcursor  DW  0
  164.  
  165. ;
  166. ; stuff for screen routines
  167. ;
  168. trnctl  equ     80h
  169. lnwrap  equ     40h                     ; line wrap enabled.
  170. line25  equ     20h
  171. IF    show_ctrl
  172. flags   db    0C0h
  173. ELSE
  174. flags   db      40h                     ; status flags...
  175. ENDIF
  176. cursor  dw      0
  177. esc_ch  db      ?
  178. argadr  dw      ?                       ; address of arg blk
  179.  
  180. spctab  db      chesc, cr, lf, bs, tab, bel
  181. lspctab equ     $-spctab
  182. spcjmp  dw      outesc,outcr,outlf,outbs,outtab,outbel  ; must match spctab
  183. esctab  db      'YABCDEFGHIJKLM'
  184.     db      'NOZ@[pq<vw'
  185.     db      'jk'
  186.     db      'xy'
  187.     db    '>='
  188. lesctab equ     $-esctab
  189. ; escjmp must parallel esctab above
  190. escjmp  dw      movcur,curup,curdwn,currt,outbs,clrscr,outign,outign,curhom
  191.     dw      revind,clreow,clreol,inslin,dellin,delchr,noins
  192.     dw      vtident,entins,doansi
  193.     dw      invvid,nrmvid,outign,dowrap,nowrap
  194.     dw      savecur,restcur
  195.     dw      smarg, rmarg
  196.     dw    escign, escign
  197. coord   dw      ?
  198. insmod  db      ?
  199. wcoord  dw      ?
  200. ttstate dw      offset scrini
  201. curattr db      ?                       ; current attribute
  202. ansarg  db      ?                       ; ansi argument value
  203. igncnt  db      ?                       ; # of chars to ignore
  204. beldiv  dw      2dch                    ; 550 hz?
  205. crt_mode db     ?
  206. crt_cols db     80
  207. crt_lins db     24      
  208. crt_page db     0
  209. low_rgt dw      ?                       ; lower right corner of window
  210. oldcur  dw      0                       ; save'd cursor position
  211.  
  212. ;---------------------------------------------------------------------
  213. ;   communication interface routines:
  214. ;    cinit:     initialize interrupts of port in dx
  215. ;    cgetch:    get next charcacter from buffer to al
  216. ;    cputch:    put character in al out on comm port
  217. ;    cexit:    reset interrupts
  218. ;    rxchar: interrupt service routine
  219. ;----------------------------------------------------------------------
  220. ;
  221. ;   interface routines
  222. ;
  223. ;    cinit moved to non-resident part
  224. ;
  225. ;  second entry point just for a re-init
  226. ;
  227. enab    proc near
  228. ;
  229. ;   set up the serial card
  230. ;
  231.     mov dx, cbase
  232.     add dx, line_control
  233.     mov al, 3
  234.     out dx, al
  235.     mov dl, 0f8h
  236.     in al, dx
  237. ;
  238. ;   start RS232 interrupt
  239. ;
  240.     mov dx, cbase
  241.     add dx, int_enable
  242.     mov al, 1
  243.     out dx, al
  244.     mov dl, 0fch
  245.     mov al, 0fh
  246.     out dx, al
  247. ;
  248. ;   set up 8259 interrupt controller
  249. ;
  250.     cli
  251.     in al, 21H
  252.     and al, cmask
  253.     out 21H, al
  254.     sti
  255. ;
  256. ;   done
  257. ;
  258.     ret
  259. enab    endp
  260.  
  261. ;
  262. ;   cexit moved to the non-resident part
  263. ;
  264.  
  265. cgetch  proc    near
  266.     cmp count, 0
  267.     je  gc3
  268.     mov bx, head
  269.     mov al, [bx]
  270.     inc bx
  271.     cmp bx, buf_end
  272.     jne gc1
  273.     mov bx, rxbuffer
  274. gc1:    mov head, bx
  275.     cli                     ; no interrupts during change of count
  276.     dec count
  277.     sti
  278. ;
  279. ; check for leaving buffer full state
  280. ;
  281.     test rxfull, 80h
  282.     jz gc2
  283. ;
  284. ; we are in rxfull state
  285. ;
  286.     cmp count, lowcount
  287.     ja gc2
  288. ;
  289. ; buffer is free to receive new charcters now
  290. ;
  291.     push ax
  292.     mov ax, xon                 ; send XON protocol
  293.     call txchar
  294.     mov rxfull, 0
  295.     mov rxoff, 0
  296.     pop ax
  297. gc2:    mov ah, 0
  298.     ret
  299. gc3:    mov ax, -1
  300.     ret
  301. cgetch endp
  302.  
  303. cputch  proc    near
  304.     test txoff, 80h
  305.     jnz t0
  306.     call txchar         ; character in al
  307.     jmp t1
  308. ;
  309. ;   in txoff state: return without sending
  310. ;
  311. t0:     mov ax, -1
  312. t1:     ret
  313. cputch endp
  314.  
  315. txchar  proc    near
  316.     mov ah, al; save character
  317.     mov dx, cbase 
  318.     add dx, line_status
  319. tx1:    in al, dx
  320.     test al, 20h; wait for THRE
  321.     jz tx1
  322. ;
  323. ; ready to transmit
  324. ;
  325.     sub dx, line_status; point to THR
  326.     mov al,ah
  327.     out dx, al
  328.     mov ah, 0
  329.     ret
  330. txchar endp
  331.  
  332. rxchar proc far
  333.     push ax
  334.     push bx
  335.     push dx
  336.     push ds
  337.     mov ax, cs
  338.     mov ds, ax
  339.     mov dx, cbase
  340.     in al, dx
  341.     cmp al, xoff
  342.     jne r1
  343. ;
  344. ;   XOFF found
  345. ;
  346.     mov txoff, 80h; set TXOFF state
  347.     jmp short rxreturn
  348. r1:     cmp al, xon
  349.     jne r2
  350. ;
  351. ;   XON found
  352. ;
  353.     mov txoff, 0; clear TXOFF state
  354.     jmp short rxreturn
  355. ;
  356. ; insert character into rxbuffer
  357. ;
  358. r2:     mov bx, tail
  359.     mov [bx], al
  360.     inc bx
  361.     cmp bx, buf_end
  362.     jne r3
  363.     mov bx, rxbuffer
  364. r3:     mov tail, bx
  365.     inc count
  366. ;
  367. ;   check for attention charcter
  368. ;
  369.     test cs:tflag, 80h
  370.     jnz r4
  371. ;
  372. ;   we are in background mode
  373. ;
  374.     and al, 127
  375.     cmp al, 7h
  376.     jnz r4
  377.     mov cs:alarm, 80h
  378. r4:    cmp count, maxcount
  379.     jbe rxreturn
  380.  
  381. ; rxbuffer full
  382.  
  383.     mov rxfull, 80h; set rxfull state
  384.     mov ax, xoff
  385.     call txchar
  386.  
  387. rxreturn:
  388.  
  389. ; clear interrupt controller
  390.  
  391.     cli                 ; int enabled by IRET instruction
  392.     mov al, eoi
  393.     mov dx, 20h
  394.     out dx, al
  395.     pop ds
  396.     pop dx
  397.     pop bx
  398.     pop ax
  399.     iret
  400. rxchar endp
  401.  
  402. ;--------------------------------------------------------------------
  403. ;       screen routines: emulate a zenith z19 terminal
  404. ;    only entry point here is outtty, which outputs the
  405. ;    character given in al
  406. ;---------------------------------------------------------------------
  407. ;
  408. ;   init: called automatically on startup
  409. ;
  410. scrini  proc    near                    ; init screen stuff
  411.     push    ax                      ; save character
  412.     mov     ah,15                   ; read video state...
  413.     int     screen
  414.     mov     crt_mode,al             ; save crt mode
  415.     cmp     ah,crt_cols             ; is real # of cols < passed?
  416.     jge     scrin1                  ; no
  417.     mov     crt_cols,ah             ; yes, save # of cols
  418. scrin1: mov     dl,crt_cols             ; # of cols again
  419.     mov     dh,crt_lins             ; and # of rows
  420.     dec     dl
  421.     dec     dh
  422.     mov     low_rgt,dx              ; save away window address
  423.     mov     insmod,0                ; not in insert mode
  424.     mov     crt_page, bh
  425.     mov    ah, fgcolor
  426.     mov     curattr,ah        ; else set nice screen attribute
  427.     mov     ttstate,offset outtt0   ; normal screen state
  428.     mov     ah,3                    ; figure out where cursor is
  429.     mov     bh, crt_page
  430.     int     screen                  ; read cursor position
  431.     cmp     dh,crt_lins             ; past logical end of screen?
  432.     jb      scrin2                  ; no, keep going
  433.     mov     dh,byte ptr low_rgt+1   ; yes, just use lower right corner
  434. scrin2: cmp     dl,crt_cols             ; maybe past right margin
  435.     jb      scrin3                  ; no, use the way it is
  436.     mov     dl,byte ptr low_rgt
  437. scrin3: mov     cursor,dx               ; init cursor
  438. scrin4: mov     ah,2
  439.     mov     bh, crt_page
  440.     int     screen                  ; set cursor in case it moved
  441.     pop     ax
  442.     jmp     outtty
  443. scrini  endp
  444.  
  445. outtty  proc    near
  446. outnop1:mov     dx,cursor               ; these may need cursor...
  447.     and     al, 127
  448.     cmp     al, 0
  449.     jz      outign
  450.     jmp     ttstate                 ; jump according to current state
  451. outtt0:
  452.     cmp     al,32                   ; special character?
  453.     jb      outtt1                  ; yes, handle specially...
  454.  
  455.     cmp     insmod,0                ; in insert mode?
  456.     je      outnrm                  ; no, output normal
  457.     push    ax                      ; save character
  458.     call    inschr                  ; insert a character
  459.     pop     ax
  460. outnrm: mov     bh, crt_page            ; current page
  461.     mov     cx,1                    ; only one char
  462.     mov     bl,curattr              ; with current attribute
  463.     mov     ah,9
  464.     int     screen                  ; put onto screen
  465.     mov     dx,cursor               ; get cursor pos
  466. currt:  inc     dl                      ; bump col
  467.     cmp     dl,crt_cols             ; see if in range
  468.     jb      setcur                  ; in range, go set cursor
  469.     test    flags,lnwrap            ; in wrap mode?
  470.     jz      outign                  ; no, just return w/out updating cursor
  471. wrap:   xor     dl,dl
  472.     inc     dh                      ; handle wrap
  473. setcur: cmp     dh,crt_lins
  474.     jb      setc1                   ; not off end, keep going
  475.     push    dx                      ; save row/col
  476.     mov     ax,0601h                ; scroll up one line
  477.     xor     cx,cx                   ; from 0,0
  478.     mov     dx,low_rgt              ; to 24,80
  479.     mov     bh,curattr                      ; nice attribute
  480.     int     screen                  ; do the scroll
  481.     pop     dx
  482.     mov     dh,crt_lins             ; go to bottom line again...
  483.     dec     dh
  484. setc1:  mov     bh, crt_page
  485.     mov     cursor,dx               ; save cursor pos
  486.     mov     ah,2
  487.     int     screen                  ; set cursor
  488. outign: ret                             ; and return
  489. ; special character (in al)
  490. outtt1: mov     di,offset spctab                ; special char table
  491.     mov     cx,lspctab              ; length of tbl
  492.     repne   scasb                   ; look for char in tbl
  493.     jz      outtt2                  ; found, go do something with it
  494.     test    flags,trnctl            ; are we allowed to print carets?
  495.     jz      outign                  ; no, just ignore it.
  496.     push    ax                      ; save char
  497.     mov     al,'^'
  498.     call    outtty                  ; print caret
  499.     pop     ax
  500.     add     al,'A'-1                ; make printable
  501.     jmp     outtty                  ; print, then return
  502.  
  503. outtt2: mov     dx,cursor               ; might need cursor pos
  504.     sub     di,offset spctab+1      ; get index of char
  505.     shl     di,1                    ; double for word offset
  506.     jmp     spcjmp[di]              ; and go handle
  507.  
  508. ; special char routines.  cursor is in dx, char in al
  509.  
  510. outlf:  inc     dh                      ; bump row
  511.     jmp     setcur
  512.  
  513. outcr:  xor     dl,dl                   ; set col to 0
  514.     jmp     setcur
  515.  
  516. outbs:  or      dl,dl
  517.     jle     setcur                  ; col 0, can't back up
  518.     dec     dl                      ; back up col
  519.     jmp     setcur                  ; and use if reasonable
  520.  
  521. outtab: mov     dl,byte ptr cursor      ; get initial column
  522.     add     dl,8                    ; tab is at most 8 columns
  523.     and     dl,not 111b             ; round down to a multiple of 8
  524.     cmp     dl,crt_cols             ; out of range?
  525.     jb      setcur                  ; no, go set it
  526.     test    flags,lnwrap            ; in wrap mode?
  527.     jnz     outta1                  ; yes, wrap to next line
  528.     mov     dl,byte ptr low_rgt     ; else just move to right margin
  529.     jmp     setcur
  530. outta1: jmp     wrap
  531.     
  532. ; stolen from bios
  533. outbel: mov     al,10110110b            ; timer initialization
  534.     out     timer+3,al
  535.     mov     ax,beldiv               ; bel divisor
  536.     out     timer+2,al
  537.     mov     al,ah
  538.     out     timer+2,al              ; output divisor
  539.     in      al,bel_prt
  540.     mov     ah,al                   ; remember original value
  541.     or      al,3                    ; turn speaker on
  542.     out     bel_prt,al
  543.     mov     cx,8888h
  544. outbe1: loop    outbe1                  ; wait a while
  545.     mov     al,ah
  546.     out     bel_prt,al              ; turn bell off
  547.     ret                             ; and return
  548.  
  549. outesc: mov     ttstate,offset escseq   ; expect escape sequence.
  550.     ret                             ; and return
  551.  
  552. ; escape-char handling routines
  553. escseq: mov     ttstate,offset outtt0   ; put state back to normal
  554.     mov     di,offset esctab        ; escape char tbl
  555.     mov     cx,lesctab              ; length of tbl
  556.     repne   scasb                   ; look for it in tbl
  557.     jz      escsq1                  ; found, go use it
  558.     jmp     outtty                  ; not there, just print it
  559. escsq1: sub     di,offset esctab+1      ; get offset into tbl
  560.     shl     di,1                    ; convert to word offset
  561.     jmp     escjmp[di]              ; and go dispatch on it
  562.  
  563. ; escape dispatch routines
  564.  
  565. escign: ret
  566.  
  567. revind: cmp     dh,0
  568.     jle     revin1
  569.     dec     dh                      ; back up a row
  570.     jmp     setcur                  ; and go set cursor
  571. revin1: push    dx                      ; save cursor pos
  572.     mov     ax,701h                 ; scroll down one line
  573.     xor     cx,cx                   ; from top
  574.     mov     dx,low_rgt              ; to bottom
  575.     mov     bh,curattr
  576.     int     screen                  ; scroll it down
  577.     pop     dx                      ; restore cursor.
  578.     mov     dh,0                    ; set row back to 0
  579.     jmp     setcur
  580.  
  581. curup:  cmp     dh,0                    ; w/in range?
  582.     jle     curu1                   ; no, skip this
  583.     dec     dh                      ; else back up
  584. curu1:  jmp     setcur                  ; and go set position
  585.  
  586. curdwn: inc     dh
  587.     jmp     setcur                  ; increment row (setcur can scroll!)
  588.  
  589. ; currt is above
  590.  
  591. clrscr: call    curhom                  ; go home cursor
  592.     jmp     clreow                  ; then clear to end of window
  593.  
  594. curhom: xor     dx,dx                   ; move to 0,0
  595.     jmp     setcur
  596.  
  597. clreow: cmp     dl,0                    ; at beginning of line?
  598.     jz      clrw1                   ; yes, skip this part...
  599.     push    dx                      ; remember cursor pos
  600.     call    clreol                  ; clear to end of this line
  601.     pop     dx
  602.     inc     dh                      ; bump row
  603.     xor     dl,dl                   ; start from col 0
  604. clrw1:  cmp     dh,crt_lins             ; last line on screen
  605.     jnb     clrw2                   ; if not in range, forget it
  606.     mov     ax,700h                 ; clear whole window
  607.     mov     cx,dx                   ; this is beginning
  608.     mov     dx,low_rgt
  609.     mov     bh,fgcolor              ; always use foreground
  610. ;    mov     bh,curattr              ; default attribute
  611.     int     screen                  ; go clear it
  612. clrw2:  ret                             ; and return
  613.  
  614. clreol: push    es
  615.     mov     cl,crt_cols             ; last col + 1
  616.     sub     cl,dl                   ; this is # of chars to move
  617.     xor     ch,ch
  618.     jcxz    clrl1
  619.     call    scrloc                  ; compute screen location (to ax)
  620.     mov     di,ax
  621.     call    scrseg
  622.     mov     es,ax                   ; address screen segment
  623.     call    scrwait                 ; wait for retrace
  624.     mov     ah,fgcolor              ; always use foreground
  625. ;    mov     ah,curattr              ; current attribute
  626.     mov     al,' '                  ; fill char
  627.     rep     stosw                   ; fill line with spaces
  628. clrl1:  pop     es
  629.     ret                             ; and return
  630.  
  631. inslin: mov     al,1                    ; scroll one line
  632. ; alternate entry if inserting more then one line
  633. inslin1:mov     ch,dh                   ; start at current row
  634.     xor     cl,cl                   ; column 0
  635.     mov     dx,low_rgt
  636.     mov     ah,7h                   ; scroll down.
  637.     mov     bh,curattr              ; attribute
  638.     cmp     ch,dh                   ; moving last line down?
  639.     jne     insli2                  ; no, keep going
  640.     mov     al,0                    ; yes, just clear it
  641. insli2: int     screen
  642.     ret
  643.  
  644. dellin: mov     al,1                    ; scroll 1 line
  645. ; alternate entry if deleting more than one line
  646. dellin1:mov     ch,dh                   ; start at current row
  647.     xor     cl,cl                   ; column 0
  648.     mov     dx,low_rgt
  649.     mov     ah,6h                   ; scroll up.
  650.     mov     bh,curattr              ; attribute
  651.     cmp     ch,dh                   ; deleting last line?
  652.     jne     delli2                  ; no, go on
  653.     mov     al,0                    ; yes, just blank it
  654. delli2: int     screen
  655.     ret
  656.  
  657. delchr: push    ds
  658.     push    es
  659.     pushf                   ; these may get changed...
  660.     mov     cl,crt_cols
  661.     dec     cl
  662.     sub     cl,dl           ; from what we're fiddling)
  663.     xor     ch,ch
  664.     jcxz    delch1          ; none to move, forget it
  665.     call    scrloc          ; compute location
  666.     mov     di,ax
  667.     mov     si,ax
  668.     add     si,2            ; source is next position over
  669.     call    scrseg          ; pick up screen segment
  670.     push    ax              ; put screen segment onto stack
  671.     mov     es,ax           ; and in destination segment
  672.     call    scrwait         ; wait for retrace
  673.     pop     ds              ; address screen segment
  674.     rep     movsw           ; delete it
  675.     mov     byte ptr [di],' ' ; kill char at end of line
  676. delch1: popf
  677.     pop     es
  678.     pop     ds
  679.     ret
  680.  
  681. inschr: push    ds
  682.     push    es              ; save these as well
  683.     pushf                   ; might as well save flags...
  684.     mov     dx,cursor       ; this is place to do it
  685.     mov     cl,crt_cols
  686.     dec     cl
  687. ;       mov     cl,79           ; this is last col to move, +1 for length
  688.     sub     cl,dl           ; compute distance to end
  689.     xor     ch,ch           ; clear top half of offset
  690.     jcxz    insch1          ; nothing to move...
  691.     mov     dl,crt_cols
  692.     sub     dl,2            ; last col to move
  693. ;       mov     dl,78           ; this is address of last col to move
  694.     call    scrloc          ; compute pos
  695.     mov     si,ax
  696.     mov     di,ax
  697.     add     di,2            ; destination is one byte over...
  698.     std                     ; remember to move us backwards
  699.     call    scrseg          ; find screen segment
  700.     mov     es,ax
  701.     push    ax              ; save screen seg on stack
  702.     call    scrwait         ; wait until save to write
  703.     pop     ds              ; address screen segment
  704.     rep     movsw           ; move each char and attribute
  705. insch1: popf
  706.     pop     es
  707.     pop     ds
  708.     ret                     ; and return
  709.  
  710. noins:  mov     insmod,0                ; turn off insert mode
  711.     ret                             ; and return
  712.  
  713. movcur: mov     wcoord,2                ; want two coordinates...
  714.     mov     ttstate,offset getcoord
  715.     ret                             ; and return
  716.  
  717. vtident: ret
  718. vtid1:   ret
  719.  
  720. entins: mov     insmod,0ffh             ; enter insert mode...
  721.     ret                             ; and return
  722.  
  723. doansi: mov     ansarg,0                ; ansi argument is 0 (default)
  724.     mov     ttstate,offset getaarg  ; state is get ansi argument
  725.     ret
  726.  
  727. getaarg:cmp     al,'0'
  728.     jb      getaa1                  ; in range for digit?
  729.     cmp     al,'9'
  730.     ja      getaa1
  731.     sub     al,'0'                  ; convert to binary
  732.     mov     dl,al                   ; tuck away
  733.     mov     al,ansarg
  734.     mov     dh,10
  735.     mul     dh                      ; shift sum
  736.     add     al,dl                   ; add in this digit (what about ovfl?)
  737.     mov     ansarg,al
  738.     ret                             ; and return
  739.  
  740. getaa1: cmp     al,'?'                  ; the dreaded question mark?
  741.     jne     getaa2
  742.     mov     ttstate,offset ignn     ; we ignore these...
  743.     mov     igncnt,2                ; this is how many chars come after him
  744.     ret
  745.  
  746. getaa2: mov     ttstate,offset outtt0   ; reset state
  747.     mov     dx,cursor               ; this needs cursor position
  748.     mov     bl,ansarg
  749.     xchg    al,bl                   ; put argument in nice place
  750.     cmp     bl,'L'                  ; insert line?
  751.     jne     getaa3
  752.     jmp     inslin1                 ; and go do it
  753.  
  754. getaa3: cmp     bl,'M'                  ; maybe delete line?
  755.     jne     getaa4
  756.     jmp     dellin1
  757.  
  758. getaa4: ret                             ; ignore.
  759.  
  760. invvid: mov    ah, bgcolor
  761.     mov     curattr,ah             ; attribute for inverse video
  762.     ret
  763.  
  764. nrmvid: mov    ah, fgcolor
  765.     mov     curattr,ah        ; attribute for normal video
  766.     ret
  767.  
  768. dowrap: or      flags,lnwrap            ; turn on wrap mode
  769.     ret                             ; and return
  770.  
  771. nowrap: and     flags,not lnwrap        ; turn off wrap mode
  772.     ret                             ; and return
  773.  
  774. smarg:  mov     ttstate, offset setmo 
  775.     ret
  776. rmarg:  mov     ttstate, offset resetmo
  777.     ret
  778.  
  779. setmo:  mov ttstate, offset outtt0
  780.     cmp al, '1'
  781.     je ena25
  782.     cmp al, '4'
  783.     je cblock
  784.     ret
  785.  
  786. resetmo:
  787.     mov ttstate, offset outtt0
  788.     cmp al, '1'
  789.     je disa25
  790.     cmp al, '4'
  791.     je cul
  792.     ret
  793.  
  794. ena25:  test flags, line25
  795.     jnz en0                  ; already set
  796.     mov dx, low_rgt
  797.     inc dh
  798.     mov low_rgt, dx
  799.     inc crt_lins
  800.     or flags, line25
  801. en0:    ret
  802.  
  803. disa25: test flags, line25
  804.     jz d0                   ; aleady disabled
  805.     mov dx, low_rgt
  806.     dec dh
  807.     mov low_rgt, dx
  808.     dec crt_lins
  809.     and flags, not line25
  810. d0:     ret
  811.  
  812. cblock: mov ah, 1
  813.     test bw, 80h
  814.     jnz cbl1
  815.     mov cx, 0007h
  816.     jmp short cbl2
  817. cbl1:    mov cx, 000dh
  818. cbl2:    int screen
  819.     ret
  820.  
  821. cul:    test bw, 80h
  822.     jnz cul1
  823.     mov cx, 0607h
  824.     jmp short cul2
  825. cul1:    mov cx, 0c0dh
  826. cul2:    mov ah, 1
  827.     int screen
  828.     ret
  829.  
  830. ; get a coordinate.
  831. getcoord:
  832.     sub     al,32                   ; coordinates offset by 32
  833.     mov     si,wcoord
  834.     dec     si
  835.     mov     byte ptr coord[si],al   ; fill in appropriate coordinate
  836.     mov     wcoord,si               ; update flag
  837.     jnz     getco1                  ; more needed, can't do anything yet
  838.     mov     ttstate,offset outtt0   ; reset state
  839.     mov     dx,coord                ; get coordinates
  840.     jmp     setcur                  ; and go jump there
  841. getco1: ret
  842.  
  843. ; ignore following igncnt characters
  844. ignn:   dec     igncnt                  ; decrement count
  845.     jnz     ignn1
  846.     mov     ttstate,offset outtt0   ; put state back to normal if done
  847. ignn1:  ret
  848.  
  849. ; save cursor
  850. savecur:
  851.     mov     oldcur,dx
  852.     ret
  853.  
  854. ; restore cursor
  855. restcur:
  856.     mov     dx,oldcur
  857.     jmp     setcur
  858.     
  859. outtty  endp
  860.  
  861. ; computes screen location to ax, given row and col in dx.
  862. ; trashes ax,bx
  863. scrloc  proc    near
  864.     mov     al,dh           ; get row
  865.     mov     bl,crt_cols     ;** row size
  866.     mul     bl              ; multiply by row size
  867.     xor     dh,dh           ; clear col
  868.     add     ax,dx           ; this is current position
  869.     sal     ax,1            ; double for attributes
  870.     ret
  871. scrloc  endp
  872.  
  873. ; puts current screen segment in ax
  874. scrseg  proc    near
  875.     mov    ah, crt_page
  876.     mov    al, 0
  877.     add     ax, 0b000h
  878.     cmp     crt_mode,7              ; 7 is bw (***)
  879.     je      scrse1
  880.     add     ax, 800h                ; color card
  881. scrse1: ret
  882. scrseg  endp
  883.  
  884. ; wait for retrace so can write to screen memory
  885. scrwait proc    near
  886.     cmp     crt_mode,7              ; bw mode?
  887.     je      scrwa3                  ; yes, no waiting
  888.     push    dx
  889.     mov     dx,crt_status
  890. scrwa1: in      al,dx
  891.     test    al,disp_enb             ; display enable?
  892.     jnz     scrwa1                  ; yes, keep waiting
  893. scrwa2: in      al,dx
  894.     test    al,disp_enb             ; now wait for it to go off
  895.     jz      scrwa2                  ; so can have whole cycle
  896.     pop     dx
  897. scrwa3: ret                             ; that was easy...
  898. scrwait endp
  899.  
  900. ;----------------------------------------------------------------------
  901. ;    keyboard interrupt routines: check for alarm flag
  902. ;    and switch-code
  903. ;----------------------------------------------------------------------
  904. ;
  905. ;   start of the main routines
  906. ;
  907. slogo   DW       logo
  908. kb_int  proc    far
  909. ;   first we check for an alarm, in that case we call main immediately
  910. ;     note that alarm only happens when running in background
  911. ;   then we check for a read, the case we don't check for a kb-status
  912. ;     is, that the status uses the flags to return values and
  913. ;     modifying the users flags on the stack would mess up our 
  914. ;     routines (too much overhead)
  915. ;
  916. ;   rearrange these routines in the next version
  917. ;    when a read is interrupted by term, we should check
  918. ;    the keyboard until a key is pressed before actually 
  919. ;    going into the read again.
  920. ;
  921.     sti
  922.     test cs:alarm, 80h
  923.     jz kbx
  924.     mov cs:alarm, 0
  925.     test cs:tflag, 80h    ; there is a silly condition here
  926.     jnz kbx
  927.     call main
  928. kbx:    cmp ah, 0
  929.     jz kb0
  930.     jmp cs:[kb_bios]
  931. kb0:    pushf
  932.     call cs:[kb_bios]
  933.     cmp ax, cs:switchcode
  934.     jne kb1
  935.     test cs:tflag, 80h
  936.     jnz kb1
  937.     call main
  938.     mov ah, 0
  939.     jmp kb0
  940. kb1:    iret
  941. kb_int  endp
  942.  
  943. ;-----------------------------------------------------------------
  944. ;    main program: just loop to get input from the keyboard
  945. ;    and the comm-port, and output it to the other ends
  946. ;-----------------------------------------------------------------
  947.  
  948. main    proc    near
  949. ;
  950. ;   save registers
  951. ;
  952.     push ax
  953.     push bx
  954.     push cx
  955.     push dx
  956.     push ds
  957.     push es
  958.     push di
  959.     push si
  960.     push bp
  961.  
  962.     mov ax, cs
  963.     mov ds, ax
  964.     mov es, ax
  965.     mov tflag, 80h
  966. ;
  967. ;   restore the last environment
  968. ;
  969.     test bw, 80h
  970.     jz e0
  971. ;
  972. ;   first save the users current screen
  973. ;
  974.     mov     di, usersave
  975.     mov    cx, screensize
  976.     mov    ax, 0b000h
  977.     mov    ds, ax
  978.     mov    si, 0
  979.     rep    movsw
  980.     push    cs
  981.     pop    ds
  982. ;
  983. ;   now restore terminals last screen
  984. ;
  985.     mov    si, termsave
  986.     mov    cx, screensize
  987.     mov    ax, 0b000h
  988.     mov    es, ax
  989.     mov    di, 0
  990.     rep    movsw
  991.     push    cs
  992.     pop    es
  993. ;
  994. ;   now also save the cursor
  995. ;
  996.     mov    ah, 3
  997.     mov    bh, 0
  998.     int     screen
  999.     mov     usercursor, dx
  1000.     mov    ah, 2
  1001.     mov     dx, termcursor
  1002.     int    screen
  1003.     jmp    m0
  1004.  
  1005. ;
  1006. ;   switch video page
  1007. ;
  1008. e0:    mov ax, 0500h + terminal_page
  1009.     int screen
  1010. ;
  1011. ;   main loop
  1012. ;
  1013. m0:     mov ah, 1
  1014.     int 16h
  1015.     jz m1
  1016.     mov ah, 0
  1017.     int 16h
  1018. ;
  1019. ;   check keyboard input for switch character
  1020. ;
  1021.     cmp ax, switchcode
  1022.     je mexit
  1023. ;
  1024. ;   translate del into destructive backspace
  1025. ;
  1026.     cmp ah,    83
  1027.     jne m00
  1028.     mov al,    127
  1029. ;
  1030. ;   send character out
  1031. ;
  1032. m00:    call cputch
  1033. ;
  1034. ;   check rxbuffer
  1035. ;
  1036. m1:     cmp count, 0
  1037.     je m0
  1038.     call cgetch
  1039.     call outtty
  1040.     jmp m0
  1041. ;
  1042. ;   return to dos task, first clear rxbuffer
  1043. ;
  1044. mexit:  cmp count, 0
  1045.     je mdone
  1046.     call cgetch
  1047.     call outtty
  1048.     jmp mexit
  1049. mdone:
  1050. ;
  1051. ;   save the current environment
  1052. ;
  1053.     test bw, 80h
  1054.     jz e2
  1055. ;
  1056. ;   first save terms current screen
  1057. ;
  1058.     mov     di, termsave
  1059.     mov    cx, screensize
  1060.     mov    ax, 0b000h
  1061.     mov    ds, ax
  1062.     mov    si, 0
  1063.     rep    movsw
  1064.     push    cs
  1065.     pop    ds
  1066. ;
  1067. ;   now restore the users last screen
  1068. ;
  1069.     mov    si, usersave
  1070.     mov    cx, screensize
  1071.     mov    ax, 0b000h
  1072.     mov    es, ax
  1073.     mov    di, 0
  1074.     rep    movsw
  1075.     push    cs
  1076.     pop    es
  1077. ;
  1078. ;   now also restore the cursor
  1079. ;
  1080.     mov    ah, 3
  1081.     mov    bh, 0
  1082.     int     screen
  1083.     mov     termcursor, dx
  1084.     mov     dx, usercursor
  1085.     mov    ah, 2
  1086.     int    screen
  1087.     jmp    e3
  1088.  
  1089.  
  1090. e2:     mov ax, 0500h
  1091.     int 10h
  1092. ;
  1093. ;   done, restore registers
  1094. ;
  1095. e3:    mov tflag, 0
  1096.     pop bp
  1097.     pop si
  1098.     pop di
  1099.     pop es
  1100.     pop ds
  1101.     pop dx
  1102.     pop cx
  1103.     pop bx
  1104.     pop ax
  1105.     ret
  1106. main    endp
  1107.  
  1108. ;-------------------------------------------------------------------
  1109. ;    installation/uninstallation routines
  1110. ;-------------------------------------------------------------------
  1111. ;
  1112.     even
  1113. lastbyte label byte
  1114. ;
  1115. ;   only once
  1116. ;  
  1117. cinit   proc    near
  1118. ;
  1119. ;   initialize buffer
  1120. ;
  1121.     mov ax, rxbuffer
  1122.     mov head, ax
  1123.     mov tail, ax
  1124.     xor ax, ax
  1125.     mov count, ax
  1126. ;
  1127. ;   clear state flags
  1128. ;
  1129.     mov txoff, al; transmitting allowed
  1130.     mov rxfull, al; buffer empty
  1131.     mov rxoff, al; no XOFF sent
  1132. ;
  1133. ;   set the interrupt vector to our routine
  1134. ;
  1135.     cmp dx, 1
  1136.     jne c0
  1137.     mov cmask, c1mask
  1138.     mov coff, c1off
  1139.     mov cint, c1int
  1140.     mov cbase, c1base
  1141.     jmp c1
  1142. c0:     mov cmask, c2mask
  1143.     mov coff, c2off
  1144.     mov cint, c2int
  1145.     mov cbase, c2base
  1146. c1:     push es
  1147.     mov ah, 35H
  1148.     mov al, cint
  1149.     int 21H
  1150.     mov word ptr old_com1, bx
  1151.     mov word ptr old_com2, es
  1152.     pop es
  1153.     push ds
  1154.     mov dx, offset rxchar
  1155.     mov ah, 25h
  1156.     mov al, cint
  1157.     push cs
  1158.     pop ds
  1159.     int 21h
  1160.     pop ds
  1161.     call enab
  1162.     ret
  1163. cinit    endp
  1164.  
  1165. cexit   proc    near
  1166. ;
  1167. ;   note: ds has to equal old installation segment on call
  1168. ;
  1169. ;   disable rs232 interrupt
  1170. ;
  1171.     mov dx, cbase
  1172.     add dx, modem_control
  1173.     mov al, 3
  1174.     out dx, al
  1175.     mov dx, cbase
  1176.     add dx, int_enable
  1177.     mov al, 0
  1178.     out dx, al
  1179. ;
  1180. ;   disable com interrupts
  1181. ;
  1182.     cli
  1183.     in al, 21h
  1184.     or al, coff
  1185.     out 21h, al
  1186.     sti
  1187. ;
  1188. ;   restore old vector
  1189. ;
  1190.     mov ah, 25h
  1191.     mov al, cint
  1192.     push ds
  1193.     mov dx, old_com1
  1194.     mov bx, old_com2
  1195.     mov ds, bx
  1196.     int 21h
  1197.     pop ds
  1198.     ret
  1199. cexit   endp
  1200.  
  1201. install proc    near
  1202. ;
  1203. ;   hook up program
  1204. ;
  1205.     mov dx, offset copyr
  1206.     mov ah, 09h
  1207.     int 21h
  1208.  
  1209.     mov tflag, 0        ; not running
  1210.     mov ax, 3516h
  1211.     int 21h
  1212.     cmp es:slogo, logo
  1213.     jnz inst1
  1214.     jmp uninstall
  1215. ;
  1216. ;   install
  1217. ;
  1218. inst1:    mov word ptr old_kb1, bx
  1219.     mov word ptr old_kb2, es
  1220. ;
  1221. ;   we have to check some stuff before changing vectors
  1222. ;
  1223. ;
  1224. ;   check for monochrome card
  1225. ;
  1226.     mov ah, 0fh
  1227.     int screen
  1228.     cmp al, 7
  1229.     jz inst2
  1230.     mov dx, 0
  1231.     mov bh, terminal_page
  1232.     mov ah, 2
  1233.     int screen
  1234.     mov ax, 0b800h + terminal_page * 100h
  1235.     mov es, ax
  1236.     mov di, 0
  1237.     jmp inst3
  1238. ;
  1239. ;   only a single page, allocate 2 more pages
  1240. ;
  1241. inst2:    mov bw, 80h
  1242.     push cs
  1243.     pop es
  1244.     mov ax, mofreemem
  1245.     mov freemem, ax
  1246.     mov termcursor, 0
  1247.     mov di, termsave
  1248. inst3:    mov cx, screensize
  1249.     mov ah, fgcolor    
  1250.     mov al, ' '
  1251.     cld
  1252.     rep stosw
  1253.     push cs
  1254.     pop es
  1255. ;
  1256. ;   finally, get going
  1257. ;
  1258.     mov dx, offset kb_int
  1259.     mov ax, 2516h
  1260.     int 21h
  1261. ;
  1262. ;   setup ints ( this should be taken from the command line)
  1263. ;
  1264.     mov ah, 0
  1265.     mov al, line_par
  1266.     mov dx, tport
  1267.     dec dx
  1268.     int 14h
  1269.     inc dx
  1270.     call cinit
  1271. ;
  1272. ;   signon
  1273. ;
  1274.     mov dx, offset signon
  1275.     mov ah, 9h
  1276.     int 21h
  1277.     mov dx, freemem
  1278.     int 27h
  1279. install endp
  1280. ;
  1281.  
  1282.  
  1283. uninstall   proc near
  1284. ;
  1285. ;   note: es holds segment of first installation
  1286. ;
  1287.     mov dx, es:old_kb1
  1288.     mov cx, es:old_kb2
  1289.     mov ax, 2516h
  1290.     mov ds, cx
  1291.     int 21h
  1292.     push es
  1293.     pop ds
  1294.     call cexit
  1295. ;
  1296. ;   free memory
  1297. ;    note: es still holds segment
  1298. ;    we also have to free the environment
  1299. ;
  1300.     push cs
  1301.     pop ds
  1302.     mov ah, 49h
  1303.     int 21h
  1304.     mov ax, word ptr es:[2ch]
  1305.     mov es, ax
  1306.     mov ah, 49h
  1307.     int 21h
  1308. ;
  1309.     mov dx, offset clear
  1310.     mov ah, 9h
  1311.     int 21h
  1312. ;
  1313.     mov ax, 4c00h
  1314.     int 21h
  1315. uninstall   endp
  1316.  
  1317. copyr   DB  "HiTerm   memory resident terminal program"
  1318.     DB  "         Version 2.2   04-09-87", 13, 10
  1319.     DB  "Copyright (c) Hans Irtel & Karl Gegenfurtner"
  1320.     DB  13, 10, 13, 10, "$"
  1321. signon  DB  "Terminal installed", 13, 10, "$"
  1322. clear   DB  "Exit from terminal", 13, 10, "$"
  1323.  
  1324. code_seg ends
  1325. end     terminal
  1326.