home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / pc / source / pcmail2.lzh / pcmail.10 < prev    next >
Encoding:
Text File  |  1990-01-31  |  38.1 KB  |  1,207 lines

  1.  
  2. #! /bin/sh
  3. # This is a shell archive.  Remove anything before this line, then unpack
  4. # it by saving it into a file and typing "sh file".  To overwrite existing
  5. # files, type "sh file -c".  You can also feed this as standard input via
  6. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  7. # will see the following message at the end:
  8. #        "End of archive 10 (of 11)."
  9. # Contents:  main/comport.asm main/kbdinp.c
  10. # Wrapped by wswietse@tuewsa on Mon Jan 22 17:27:22 1990
  11. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  12. if test -f main/comport.asm -a "${1}" != "-c" ; then 
  13.   echo shar: Will not over-write existing file \"main/comport.asm\"
  14. else
  15. echo shar: Extracting \"main/comport.asm\" \(20373 characters\)
  16. sed "s/^X//" >main/comport.asm <<'END_OF_main/comport.asm'
  17. Xtitle IBM PC Communications I/O Routines 
  18. X;
  19. X; @(#) comport.asm      Version hoptoad-1.3     87/03/24
  20. X;
  21. X; Orginal code -- Curt Klinsing
  22. X;
  23. X; Changes and updates -- Copyright (c) 1987 Tim Pozar
  24. X; Anyone can use this code for anything, but it is copyright by Tim
  25. X; and you must leave his copyright in the code.
  26. X;
  27. X; ver: 0
  28. X; rev: 2
  29. X; March 13th 1987
  30. X; This code is in a very early stage and should not be let out.
  31. X; Several other extensive functions are planned as well as changes
  32. X; to the current code.
  33. X;
  34. X; 2/20/87 
  35. X;   Changed segment declarations and function names (eg. _function)
  36. X; to fit Microsoft C 4.0 and linker requirements.
  37. X;
  38. X; FUNCTIONS CHANGED/ADDED --
  39. X; set_tty(port_number)
  40. X;   Function to find current settings of the port and set up serial 
  41. X; port for 'baud' and 'lcbyte', and enable DTR.  This will set up the
  42. X; port number base addressed passed to it (eg. 3F8h) and all functions
  43. X; will use this port until the function is used again. (NOT READY FOR USE)
  44. X;
  45. X; reset_tty()
  46. X;   Function to put the port back into the state it was when it was 
  47. X; first found by set_tty().  If set_tty() was not called it will not 
  48. X; change the settings of the port. (NOT READY FOR USE)
  49. X;
  50. X; 3/13/87
  51. X; get_msr()
  52. X;   Function to read (get) the byte located in the Modem Status 
  53. X; Register (3FEh).  The table below describes the byte returned.
  54. X;   bit  description
  55. X;    0   Delta Clear to Send (DCTS)
  56. X;        Indicates that the !CTS input to the chip has changed state
  57. X;        since the last time it was read by the processor.
  58. X;    1   Delta Data Set Ready (DDSR)
  59. X;        Indicates that the !DRS input to the chip has changed since 
  60. X;        last time it was read by the processor.
  61. X;    2   Trailing Edge Ring Indicator (TERI)
  62. X;        Indicates that the !RI input to the chip has changed from
  63. X;        an on (logical 1) to an off (logical 0) condition.
  64. X;    3   Delta Rx Line Signal detect (DRLSD)
  65. X;        Indicates that the !RLSD input to the chip has changed state.
  66. X; NOTE: Whenever bit 0, 1, 2, or 3 is set to a logical 1, a modem status
  67. X;       interrupt is generated.
  68. X;
  69. X;    4   Clear to Send (CTS)
  70. X;        This bit is the complement of the clear to send (!CTS) input.
  71. X;        If bit 4 (LOOP) of the MCR is set to a logical 1, this is 
  72. X;        equivalent to RTS in the MCR.
  73. X;    5   Data Set Ready (DSR)
  74. X;        This bit is the complement of the data set ready (!DSR) input.
  75. X;        If bit 4 (LOOP) of the MCR is set to a logical 1, this is 
  76. X;        equivalent to DTR in the MCR.
  77. X;    6   Ring Indicator (RI)
  78. X;        This bit is the complement of the ring indicator (!RI) input.
  79. X;        If bit 4 (LOOP) of the MCR is set to a logical 1, this is 
  80. X;        equivalent to OUT 1 in the MCR.
  81. X;    7   Receive Line Signal Detect (RLSD).
  82. X;        This bit is the complement of the received line signal detect
  83. X;        (!RLSD) input. If bit 4 (LOOP) of the MCR is set to a logical 1,
  84. X;        this is equivalent to OUT 2 in the MCR.
  85. X;
  86. X;   Currently this driver is set up for COM1 (3f8h).
  87. X;   If you are using the interupt driven buffer, take out the code 
  88. X; that enables the DTR so that it doesn't get raised until the vectors
  89. X; are initilized. 
  90. X;
  91. X; 22/04/1987 W.Z. Venema 
  92. X;       set_tty()       baud rate parameter (values as the "baud" macro below)
  93. X;
  94. X; 19/05/1987 W.Z. Venema
  95. X;       outp_char()     made it check for Xon/Xoff from other system
  96. X
  97. X_TEXT   SEGMENT BYTE PUBLIC 'CODE'
  98. X_TEXT   ENDS
  99. X_DATA   SEGMENT BYTE PUBLIC 'DATA'
  100. X_DATA   ENDS
  101. XCONST   SEGMENT BYTE PUBLIC 'CONST'
  102. XCONST   ENDS
  103. X_BBS    SEGMENT BYTE PUBLIC 'BBS'
  104. X_BBS    ENDS
  105. X
  106. XDGROUP  GROUP   CONST, _BBS, _DATA
  107. X      ASSUME    CS: _TEXT, DS: DGROUP, SS: DGROUP, ES: DGROUP
  108. X
  109. X_TEXT      SEGMENT
  110. X;
  111. X;A set of Lattice C and MSC callable functions to support
  112. X;interrupt driven character I/O on the  IBM PC. Input
  113. X;is buffered, output is polled.
  114. X;
  115. X;added functions (TMP) --
  116. Xpublic  _set_tty        ;find current settings, and initialize 
  117. X                        ;comm port to 8 bits and set DTR
  118. Xpublic  _reset_tty      ;reset to settings that set_tty() found
  119. Xpublic  _get_msr        ;get MSR byte from port.
  120. X;
  121. X;original functions --
  122. Xpublic  _init_comm      ;initialize the comm port interupts,
  123. Xpublic  _uninit_comm    ;remove initialization,
  124. Xpublic  _set_xoff       ;enable/disable XON/XOFF,
  125. Xpublic  _get_xoff       ;read XON/XOFF state,
  126. Xpublic  _rcvd_xoff      ;returns true if XOFF rcvd,
  127. Xpublic  _sent_xoff      ;true if XOFF sent,
  128. Xpublic  _inp_cnt        ;returns count of rcv chars,
  129. Xpublic  _inp_char       ;get one char from buffer,
  130. Xpublic  _inp_flush      ;flush input buffer,
  131. Xpublic  _outp_char      ;output a character,
  132. X;
  133. X;A better description can be found in the comment
  134. X;block  in each function.
  135. X;
  136. X;       assume  cs:pgroup
  137. X;
  138. XFALSE   EQU     0
  139. XTRUE    EQU     NOT FALSE
  140. X;
  141. XBASE    EQU     03F8H   ;BASE FOR SERIAL BOARD
  142. X;
  143. XLCR     equ     BASE+3  ; Line control register
  144. XIER     equ     BASE+1  ; Interrup Enable Register
  145. XMCR     EQU     BASE+4  ;modem control register
  146. XMDMSTA  EQU     BASE+5  ;line status register
  147. XMDMMSR  EQU     BASE+6  ;modem status register
  148. XMDMBAD  EQU     BASE    ;lsb baud resgister
  149. XEnblDRdy equ    01H     ; enable 'data-ready' interrupt bit
  150. XIntCtlr  EQU    21H     ;OCW 1 FOR 8259 CONTROLLER
  151. XEnblIRQ4 EQU    0EFH    ;Enable COMMUNICATIONS (IRQ4)
  152. Xdataport EQU    BASE    ;transmit/receive data port
  153. XMaskIRQ4 EQU    10H     ;BIT TO DISABLE COMM INTERRUPT (IRQ4)
  154. X
  155. XMDMCD   EQU     80H     ;mask for carrier dectect
  156. XSETBAU  EQU     80H     ;code for Divisor Latch Access Bit
  157. XMDMTBE  EQU     20H     ;8250 tbe flag
  158. XMDMBRK  EQU     40H     ;command code for 8250 break
  159. XLINMOD  EQU     03H     ;line mode=8 bit, no parity
  160. XMDMMOD  EQU     0BH     ;modem mode = DTR and RTS HIGH
  161. XSTOP2   EQU     04H     ;BIT FOR TWO STOP BITS IF BAUD<300
  162. XRS8259  EQU     20H     ;OCW 3 FOR 8259
  163. XRSTINT  EQU     64H     ;SPECIFIC EOI FOR COMM INTERRUPT 
  164. XXOFF    EQU     13H     ;XOFF character
  165. XXON     EQU     11H     ;XON character
  166. X;
  167. X;       MISCELLANEOUS EQUATES
  168. X;
  169. XCR      EQU     13
  170. XLF      EQU     10
  171. XDosCall EQU     33      ;INTERRUPT NUMBER FOR DOS CALL  
  172. XCNSTAT  EQU     11      ;FUNCTION NUMBER FOR CONSOLE STATUS
  173. XCNIN    EQU     1       ;FUNCTION NUMBER FOR CONSOLE INPUT
  174. XBUFSIZ  EQU     512     ;Max NUMBER OF CHARS
  175. XSetIntVect  EQU 25H     ;SET INTERRUPT VECTOR FUNCTION NUMBER
  176. X
  177. X;
  178. X; Communication parameters --
  179. X;
  180. Xbaud    equ     12      ; 1047 =  110 (are you kidding?)
  181. X                        ;  384 =  300
  182. X                        ;   96 = 1200
  183. X                        ;   48 = 2400
  184. X                        ;   24 = 4800
  185. X                        ;   12 = 9600
  186. Xparity  equ     00000b  ;00000 = none
  187. X                        ;01000 = odd
  188. X                        ;11000 = even
  189. Xstopbit equ     000b    ;  000 = 1 bit
  190. X                        ;  100 = 2 bits
  191. Xwordlth equ     11b     ;   10 = 7 bits
  192. X                        ;   11 = 8 bits
  193. Xlcbyte  equ     parity+stopbit+wordlth      ;line control byte
  194. Xdiv_on  equ     80h     ;divisor latch access bit (DLAB)
  195. X
  196. X;
  197. X;       DUMP BUFFER, COUNT AND POINTER.  
  198. X;
  199. XCIRC_BUF DB     BUFSIZ DUP(?)   ;ALLOW 512 MaxIMUM BUFFERED CHARACTERS
  200. XBUF_TOP EQU     $ - 1           ;KEEP TRACK OF THE TOP OF THE BUFFER
  201. XCIRC_TOP DW     BUF_TOP         ;
  202. X;
  203. XCIRC_IN DW      OFFSET CIRC_BUF ;POINTER TO LAST CHAR. PLACED IN BUFFER
  204. XCIRC_CUR DW     OFFSET CIRC_BUF ;POINTER TO NEXT CHAR. TO BE RETRIEVED FROM
  205. X                                ; BUFFER
  206. XCIRC_CT DW      0               ;COUNT OF CHARACTERS USED IN BUFFER
  207. XSNT_XOFF DB     FALSE           ;FLAG TO CHECK IF AN XOFF HAS BEEN SEND
  208. XGOT_XOFF  DB    FALSE           ;FLAG TO CHECK IF AN XOFF HAS BEEN RECEIVED
  209. XSEE_XOFF  DB    FALSE           ;FLAT TO SEE IF WE ARE INTERESTED IN XON/XOFF
  210. X;
  211. X;
  212. X; set_tty()
  213. X;
  214. X_set_tty proc near
  215. X        push    bp
  216. X        mov     bp,sp           ; wzv C calling standard
  217. X;        mov     dx,mcr
  218. X;        in      al,dx           ; get modem parameters
  219. X;        mov     MCR_BYTE,al     ; save them
  220. X        mov     dx,lcr
  221. X;        in      al,dx           ; get line parameters
  222. X;        mov     LCR_BYTE,al     ; save them
  223. X        mov     al,div_on
  224. X        out     dx,al           ; set 8250 for baud rate selection
  225. X        ; can the baud rate divisor be read to save the settings?
  226. X        ; if so, stick the code here.
  227. X        mov     ax,[bp+4]       ; was mov ax,baud /wzv
  228. X        mov     dx,mdmbad
  229. X        out     dx,al           ; low byte divisor
  230. X        mov     al,ah
  231. X        inc     dx
  232. X        out     dx,al           ; high byte divisor
  233. X        mov     dx,lcr
  234. X        mov     al,lcbyte
  235. X        out     dx,al           ; set line control reg.
  236. X        mov     dx,mcr
  237. X        in      al,dx
  238. X        or      al,mdmmod
  239. X        out     dx,al           ; set DTR high
  240. Xflsh:   mov     dx,dataport
  241. X        in      al,dx
  242. X        mov     dx,mdmsta
  243. X        in      al,dx
  244. X        and     al,1
  245. X        jnz     flsh
  246. X      
  247. X        pop     bp
  248. X        ret
  249. X
  250. X_set_tty endp
  251. X
  252. X
  253. X_reset_tty proc near
  254. X        push    bp
  255. X
  256. X        pop     bp
  257. X        ret
  258. X
  259. X_reset_tty endp
  260. X
  261. X_get_msr proc near
  262. X        push    bp
  263. X        push    ds              ; save data segment
  264. X        push    cs
  265. X        pop     ds
  266. X
  267. X        xor     ax,ax
  268. X        mov     dx,MDMMSR
  269. X        in      al,dx
  270. X
  271. X        pop     ds
  272. X        pop     bp
  273. X        ret
  274. X
  275. X_get_msr endp
  276. X
  277. X;
  278. X; set_xoff(flag)         Enable (flag != 0) or disable
  279. X;int flag;              (flag == 0) XON/ XOFF protocol
  280. X;                       for the character input stream.
  281. X;If enabled, an XOFF will be sent when  the buffer
  282. X;reaches 3/4 full. NOTE: an XON will not be sent auto-
  283. X;matically. Your program must do it when it sees
  284. X;the _rcvd_xoff() flag,  and ready for more chars.
  285. X;
  286. X_set_xoff proc near
  287. X        push    bp
  288. X        mov     bp,sp           ; wzv C calling standard
  289. X        PUSH    DS              ;SAVE DATA SEGMENT
  290. X        mov     bx,[bp+4]       ; wzv C calling standard
  291. X        push    cs
  292. X        pop     ds              ; move code seg addr to data seg reg.
  293. X        cmp     bx,0
  294. X        jnz     to_on
  295. X        mov     see_xoff,FALSE
  296. X        jmp     done1
  297. Xto_on:  mov     see_xoff,TRUE
  298. Xdone1:  pop     ds
  299. X        pop     bp
  300. X        ret
  301. X_set_xoff endp
  302. X;
  303. X;flag = get_xoff()      Returns the current setting
  304. X;                       of the XON/ XOFF flag set
  305. X;by set_xoff(), above.
  306. X;
  307. X_get_xoff proc near
  308. X        push    bp
  309. X        push    ds              ; save data reg
  310. X        push    cs
  311. X        pop     ds              ; move code seg addr to data seg reg.
  312. X        xor     ax,ax
  313. X        mov     al,see_xoff
  314. X        pop     ds
  315. X        pop     bp
  316. X        ret
  317. X_get_xoff endp
  318. X;
  319. X;flag = sent_xoff();    Returns true if an XOFF
  320. X;                       character was sent, indicating
  321. X;the receive buffer is  3/4 full.
  322. X;
  323. X_sent_xoff proc  near
  324. X        push    bp
  325. X        push    ds              ; save data reg
  326. X        push    cs
  327. X        pop     ds              ; move code seg addr to data seg reg.
  328. X        xor     ax,ax
  329. X        mov     al,snt_xoff
  330. X        pop     ds
  331. X        pop     bp
  332. X        ret
  333. X_sent_xoff endp
  334. X;
  335. X; rcvd_xoff()            Returns true if an XOFF was
  336. X;                       received; will return false as
  337. X;soon as an XON is received. Does not effect data output,
  338. X;only indicates the above. (Obviously useless for binary
  339. X;data.)
  340. X;
  341. X_rcvd_xoff proc  near
  342. X        push    bp
  343. X        push    ds              ; save data reg
  344. X        push    cs
  345. X        pop     ds              ; move code seg addr to data seg reg.
  346. X        xor     ax,ax
  347. X        mov     al,got_xoff
  348. X        pop     ds              ; restore data reg
  349. X        pop     bp
  350. X        ret
  351. X_rcvd_xoff endp
  352. X;
  353. X;count = inp_cnt()       Returns the number of characters
  354. X;                       available in the input buffer.
  355. X;
  356. X
  357. X_inp_cnt proc near       
  358. X        push    bp
  359. X        push    ds              ; save data segment
  360. X        push    cs
  361. X        pop     ds              ; move code seg addr to data seg reg
  362. X        mov     ax,circ_ct
  363. X        pop     ds
  364. X        pop     bp
  365. X        ret
  366. X_inp_cnt endp
  367. X;
  368. X; inp_flush()    Flush the input buffer.
  369. X;
  370. X_inp_flush proc  near    
  371. X        push    bp
  372. X        push    ds              ; save data reg
  373. X        push    cs
  374. X        pop     ds              ; move code seg addr to data seg reg.
  375. X        mov     bx,offset circ_buf
  376. X        mov     circ_in,bx      
  377. X        mov     circ_cur,bx
  378. X        xor     ax,ax
  379. X        mov     circ_ct,ax
  380. X        pop     ds
  381. X        pop     bp
  382. X        ret
  383. X_inp_flush endp
  384. X
  385. X; --------- Init -----------------------------------
  386. X; Program initialization:
  387. X;   --  Set up vector for RS232 interrupt (0CH)
  388. X;   --  Enbl IRQ4
  389. X;   --  Enbl RS232 interrupt on data ready
  390. X;
  391. X; ---------------------------------------------------
  392. X
  393. X_init_comm proc  near
  394. X        push    bp
  395. X        cli
  396. X
  397. X;  ---- Set up  INT x'0C' for IRQ4
  398. X
  399. X        push    ds
  400. X        push    cs
  401. X        pop     ds              ;cs to ds
  402. X        mov     dx,offset IntHdlr ;relative adddres of interrupt handler
  403. X        mov     al,0cH          ;interrupt number for comm.
  404. X        mov     ah,SetIntVect   ;function number for setting int vector
  405. X        int     DosCall         ;set interrupt in 8086 table
  406. X        pop     ds              ;restore DS
  407. X
  408. X;  ---- Enbl IRQ4 on 8259 interrupt controller
  409. X
  410. X        cli
  411. X
  412. X        in      al,IntCtlr      ; get current masks 
  413. X        and     al,EnblIRQ4     ; Reset IRQ4 mask
  414. X        out     IntCtlr,al      ; And restore to IMR
  415. X
  416. X;  ---   Enbl 8250 data ready interrupt
  417. X
  418. X        mov     dx,LCR          ; DX ==> LCR
  419. X        in      al,dx           ; Reset DLAB for IER access
  420. X        and     al,7FH
  421. X        out     dx,al
  422. X        mov     dx,IER          ; Interrupt Enbl Register
  423. X        mov     al,EnblDRdy     ; Enable 'data-ready' interrupt
  424. X        out     dx,al
  425. X
  426. X;  ---   Enbl OUT2 on 8250
  427. X
  428. X        mov     dx,MCR          ; modem control register        
  429. X        in      al,dx           ; Enable OUT2
  430. X        or      al,08h            ; find out what is in there and
  431. X        out     dx,al            ; enable the DTR
  432. X
  433. X        sti
  434. X
  435. X        pop     bp
  436. X        ret
  437. X_init_comm endp
  438. X;
  439. X; uninit_comm()          Removes the interrupt structure
  440. X;                       installed by _init_comm(). Must be
  441. X;done before passing control to the DOS, else chars received
  442. X;will be stored into the next program loaded!
  443. X;
  444. X_uninit_comm proc near
  445. X        push    bp
  446. X; ---   Disable IRQ4 on 8259
  447. X
  448. X        cli
  449. X        in      al,IntCtlr      ;GET OCW1 FROM 8259
  450. X        or      al,MaskIRQ4     ;DISABLE COMMUNICATIONS INTERRUPT
  451. X        out     IntCtlr,al
  452. X
  453. X; ---   Disable 8250 data ready interrupt
  454. X        
  455. X        mov     dx,LCR          ; DX ==> LCR
  456. X        in      al,dx           ; Reset DLAB for IER access
  457. X        and     al,7FH
  458. X        out     dx,al
  459. X        mov     dx,IER          ; Interrupt Enbl Register
  460. X        mov     al,0            ; Disable all 8250 interrupts
  461. X        out     dx,al
  462. X
  463. X;  ---   Disable OUT2 on 8250
  464. X
  465. X        mov     dx,MCR          ; modem control register        
  466. X        mov     al,0            ; drop DTR
  467. X        out     dx,al
  468. X
  469. X        sti
  470. X        pop     bp
  471. X        ret
  472. X_uninit_comm endp
  473. X;
  474. X;char  inp_char()      Return a character from the input
  475. X;                      buffer. Assumes you have called
  476. X;inp_cnt() to see if theres any characters to get.
  477. X;
  478. X_inp_char proc near      
  479. X        push    bp
  480. X        push    ds              ; save data reg
  481. X        push    cs
  482. X        pop     ds              ; move code seg addr to data seg reg.
  483. X        mov     bx,circ_cur
  484. X        xor     ax,ax
  485. X        mov     al,[bx]         ;get next char from circ_buf
  486. X        DEC     circ_ct         ;decrement circ_buf COUNT
  487. X        CMP     bx,circ_top     ;ARE WE AT THE TOP OF THE circ_buf?
  488. X        JZ      reset_cur       ;JUMP IF SO
  489. X        INC     bx              ;ELSE, BUMP PTR
  490. X        JMP SHORT upd_cur
  491. Xreset_cur:
  492. X        mov     bx,OFFSET circ_buf      ;RESET circ_in TO BOTTOM OF BUF.
  493. Xupd_cur:
  494. X        mov     circ_cur,bx             ;SAVE NEW PTR
  495. X        xor     cx,cx
  496. X        mov     cl,see_xoff     ;check if interested in xon/xoff
  497. X        cmp     cl,TRUE
  498. X        jnz     clnup2          ;not interested, so goto return
  499. X        cmp     snt_xoff,TRUE   ;have we sent an xoff?
  500. X        jnz     clnup2          ;no, so return
  501. X        cmp     circ_ct,80h     ;yes, so see in buf is now emptying
  502. X        jg      clnup2          ;not empty enuf to send xon, jump to ret
  503. X        mov     snt_xoff,FALSE
  504. X        mov     cl,XON
  505. X        push    ax              ; save char
  506. X        call    comout
  507. X        pop     ax
  508. Xclnup2: pop     DS              ;GET BACK ENTERING DS
  509. X        pop     bp
  510. X        ret
  511. X_inp_char endp
  512. X;
  513. X; outp_char(c)           Output the character to the
  514. X;char c;                serial port. This is not buffered
  515. X;                       or interrupt driven.
  516. X;
  517. X_outp_char proc  near
  518. X        push    bp
  519. X        mov     bp,sp
  520. X    push    ds        ; save data segment register /wzv
  521. X    push    cs        ; copy code segment register /wzv
  522. X    pop    ds        ; to data segment register /wzv
  523. Xw_Xon:  test    got_Xoff,TRUE    ; shut up if Xoff received / wzv
  524. X        jnz     w_Xon
  525. X        mov     cl,[bp+4]
  526. X        sti
  527. X        call    comout
  528. X    pop    ds        ; restore data segment register / wzv
  529. X        pop     bp
  530. X        ret
  531. X_outp_char endp
  532. X;
  533. X;Local  subroutine: output CL to the port.
  534. X;
  535. Xcomout: mov     dx,MDMSTA       
  536. X        in      al,dx           ; get 8250 status
  537. X        and     al,MDMTBE       ; check for transmitter ready
  538. X        jz      comout          ; jump if not to wait
  539. X        mov     al,cl           ; get char to al
  540. X        mov     dx,dataport     
  541. X        out     dx,al           ; output char to 8251
  542. X        ret
  543. X;
  544. X;       RECEIVE INTERRUPT HANDLER (CHANGED TO PLACE CHARACTERS IN A
  545. X;        CIRCULAR circ_buf AND TO SEND AN XOFF IF THE circ_buf IS MORE THAN
  546. X;        3/4 FULL - S.G.)
  547. X;
  548. XIntHdlr:
  549. X        CLI
  550. X        push    cx
  551. X        push    dx
  552. X        push    bx
  553. X        push    ax
  554. X        push    ds
  555. X        mov     ax,cs           ;get cur code segment
  556. X        mov     ds,ax           ;and set it as data segment
  557. X        mov     bx,circ_in      ;GET circ_buf IN PTR
  558. X        mov     DX,dataport     ;GET DATA PORT NUMBER
  559. X        IN      AL,DX           ;GET RECEIVED CHARACTER
  560. X;       push    ax
  561. X;       push    dx   
  562. X;       xor     ax,ax
  563. X;       xor     dx,dx
  564. X;       mov     dl,al
  565. X;       mov     ah,2
  566. X;       int     DosCall
  567. X;       pop     dx
  568. X;       pop     ax
  569. X        xor     cx,cx
  570. X        mov     cl,see_xoff     ;check if interested in xon/xoff
  571. X        cmp     cl,TRUE
  572. X        jnz     ck_full         ;not interested goto ck if buf full
  573. X        mov     cl,al           ;put char in cl for testing
  574. X        and     cl,7fh          ;turn off any parity bits 
  575. X        cmp     cl,XOFF         ;see if we got an xoff
  576. X        jnz     ck_xon
  577. X        mov     got_Xoff,TRUE   ; code for handling xon/xoff from remote
  578. X        jmp     clnup
  579. Xck_xon: cmp     cl,XON
  580. X        jnz     reg_ch
  581. X        mov     got_Xoff,FALSE
  582. X        jmp     clnup
  583. X;
  584. X;Normal character; not  XON/XOFF, or XON/XOFF disabled.
  585. X;
  586. Xreg_ch: test    snt_Xoff,TRUE   ;SEE IF sentXoff IS SET
  587. X        jnz     ck_full         ;IF SO, DON'T SEND ANOTHER XOFF
  588. X        CMP     circ_ct,(BUFSIZ * 3)/4  ;ALLOW BUF TO BECOME 3/4 FULL BEFORE
  589. X                                        ; SENDING XOFF
  590. X        jb      savch           ;IF IT'S OK, CONTINUE
  591. X        push    ax              ;SAVE CHARACTER
  592. X        mov     CL,XOFF         ;GET XOFF CHARACTER
  593. X        mov     snt_Xoff,TRUE  ;RESET sentXoff
  594. X        call    comout          ; AND SEND IT
  595. X        pop     ax              ;RETRIEVE CHARACTER
  596. X        JMP SHORT savch         ;IF WE'RE HERE, THE circ_buf HAS BUFSIZ-80H
  597. X                                ;  CHARACTERS
  598. Xck_full:
  599. X        CMP     circ_ct,BUFSIZ  ;SEE IF circ_buf ALREADY FULL
  600. X        JZ      clnup           ; JUMP IF SO, DO NOT PLACE CHARACTER IN BFR
  601. Xsavch:                          
  602. X        mov     [bx],AL         ;SAVE NEW CHARACTER IN circ_buf
  603. X        inc     circ_ct         ;BUMP circ_buf COUNT
  604. X        CMP     bx,circ_top     ;ARE WE AT THE TOP OF THE circ_buf?
  605. X        JZ      reset_in        ;JUMP IF SO
  606. X        inc     bx              ;ELSE, BUMP PTR
  607. X        JMP SHORT into_buf
  608. Xreset_in:
  609. X        mov     bx,OFFSET circ_buf      ;RESET circ_in TO BOTTOM OF BUF.
  610. Xinto_buf:
  611. X        mov     circ_in,bx              ;SAVE NEW PTR
  612. Xclnup:
  613. X        mov     AL,RSTINT
  614. X        OUT     RS8259,AL       ;ISSUE SPECIFIC EOI FOR 8259
  615. X        pop     ds              ;GET BACK ENTERING DS
  616. X        pop     ax
  617. X        pop     bx
  618. X        pop     dx
  619. X        pop     cx
  620. X        sti
  621. X        iret
  622. X
  623. X_TEXT   ENDS
  624. X
  625. Xend
  626. END_OF_main/comport.asm
  627. if test 20373 -ne `wc -c <main/comport.asm`; then
  628.     echo shar: \"main/comport.asm\" unpacked with wrong size!
  629. fi
  630. # end of overwriting check
  631. fi
  632. if test -f main/kbdinp.c -a "${1}" != "-c" ; then 
  633.   echo shar: Will not over-write existing file \"main/kbdinp.c\"
  634. else
  635. echo shar: Extracting \"main/kbdinp.c\" \(15738 characters\)
  636. sed "s/^X//" >main/kbdinp.c <<'END_OF_main/kbdinp.c'
  637. X/*++
  638. X/* NAME
  639. X/*    kbdinp 3
  640. X/* SUMMARY
  641. X/*    keyboard interpreter
  642. X/* PROJECT
  643. X/*    pc-mail
  644. X/* PACKAGE
  645. X/*    mail
  646. X/* SYNOPSIS
  647. X/*    void kbdinp(screen)
  648. X/*    Screen *screen;
  649. X/*
  650. X/*    void kbdinit()
  651. X/*
  652. X/*    void kbdrest()
  653. X/*
  654. X/*    int getkey()
  655. X/* DESCRIPTION
  656. X/*    The keyboard interpreter is the machine that executes the program
  657. X/*    that is recorded in the form of Screen data structures.
  658. X/*    Its task is to interpret keyboard input and to
  659. X/*    invoke the appropriate action functions.
  660. X/*
  661. X/*    Depending on the return value of an action function
  662. X/*    the keyboard interpreter i) returns (S_BREAK), ii) repaints the
  663. X/*    screen (S_REDRAW), or iii) just waits for more keyboard
  664. X/*    input. Error handling is entirely up to the action functions.
  665. X/*
  666. X/*    The routines in this module are responsible for what appears in the
  667. X/*    top (function-key labels) and bottom sections (command dialogue)
  668. X/*    of the tty screen.
  669. X/*
  670. X/*    The middle screen section is handled by the pager (except when
  671. X/*    help info is displayed).
  672. X/*
  673. X/*    kbdinit() sets the tty driver and keypad modes (no echo,
  674. X/*    punctual input).
  675. X/*
  676. X/*    kbrest() restores the modes to what they were when kbdinit() was
  677. X/*    invoked.
  678. X/*
  679. X/*    getkey() returns the next keypress (see screen.h for function-key
  680. X/*    codes) and maps lower case to upper case.
  681. X/*
  682. X/*    Terminal-specific codes for function keys and keypad are borrowed
  683. X/*    from window.c.
  684. X/* FUNCTIONS AND MACROS
  685. X/*    printcl(), printat(), wputc(), wputs(), beep(), winout()
  686. X/* SEE ALSO
  687. X/*    window(3)       window management routines, function key codes
  688. X/*    window(5)       window definitions
  689. X/*    screen(3)       command key tables for each screen
  690. X/*    screen(5)       structure of command key tables
  691. X/* DIAGNOSTICS
  692. X/*    It beeps when an illegal key is pressed. Otherwise, no error
  693. X/*    handling at all.
  694. X/* AUTHOR(S)
  695. X/*    W.Z. Venema
  696. X/*    Eindhoven University of Technology
  697. X/*    Department of Mathematics and Computer Science
  698. X/*    Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
  699. X/* CREATION DATE
  700. X/*    Thu Apr  2 18:43:12 GMT+1:00 1987
  701. X/* LAST MODIFICATION
  702. X/*    90/01/22 13:01:51
  703. X/* VERSION/RELEASE
  704. X/*    2.1
  705. X/*--*/
  706. X
  707. X#include <stdio.h>
  708. X#include <signal.h>
  709. X#include <ctype.h>
  710. X
  711. X#include "defs.h"
  712. X#include "mail.h"
  713. X#include "screen.h"
  714. X#include "window.h"
  715. X
  716. X#ifdef  unix
  717. X#if (SIII||SYSV)            /* AT&T */
  718. X#include <termio.h>
  719. Xstruct termio oldmode;
  720. X#else                    /* V7 or Berkeley */
  721. X#include <sgtty.h>
  722. Xstruct sgttyb oldmode;
  723. X# endif
  724. X#endif
  725. X
  726. X/* How to generate a brief delay when the user presses ESC */
  727. X
  728. X#ifdef    MSDOS
  729. X#define    sleep(x)    { unsigned i; for (i = 1; i > 0; i++) ; }
  730. X#endif
  731. X
  732. X/* Forward declarations */
  733. X
  734. Xhidden void kb_help();            /* Display context-sensitive help */
  735. Xhidden void kb_pause();            /* Press any key to continue */
  736. Xhidden int kb_paint();            /* Screen update routine */
  737. Xhidden int kb_str();            /* Read an arbitrary string */
  738. Xhidden int kb_key();            /* Read single-key input */
  739. Xhidden int kb_cr();            /* Allow ESC or ENTER as input */
  740. Xhidden int kb_edt();            /* String input with default */
  741. Xhidden int kb_yn();            /* Yes/no input */
  742. Xhidden char *kb_read();            /* Basic input function */
  743. Xhidden int input();            /* Read one key stroke */
  744. Xhidden int isempty();            /* String is all blanks */
  745. X
  746. X/* Various strings */
  747. X
  748. X#define QUEST   "? "            /* prompt for input */
  749. Xhidden char sect[] = "=========================================================\
  750. X======================";
  751. X
  752. X/* The maximal length of string input; depends on the window size */
  753. X
  754. Xhidden int maxstr;
  755. X
  756. X/* kbdinp - recursively interpret screen descriptions */
  757. X
  758. Xpublic int kbdinp(screen)
  759. XScreen *screen;
  760. X{
  761. X    kb_paint(screen);
  762. X
  763. X    if (iskey(screen->key))
  764. X    return (kb_key(screen));        /* single-key commands */
  765. X    else if (screen->key == STRING)
  766. X    return (kb_str(screen));        /* string input screen */
  767. X    else if (screen->key == EDIT)
  768. X    return (kb_edt(screen));        /* string edit screen */
  769. X    else if (screen->key == YESNO)
  770. X    return (kb_yn(screen));            /* yes/no screen */
  771. X    else if (screen->key == ESCCR)
  772. X    return (kb_cr(screen));            /* confirm/cancel screen */
  773. X    else
  774. X    fatal("kbdinp");            /* unexpected screen type */
  775. X    /* NOTREACHED */
  776. X}
  777. X
  778. X/* kb_paint - paint the screen (clean up this function) */
  779. X
  780. Xhidden int kb_paint(p)
  781. Xregister Screen *p;
  782. X{
  783. X    char    topline[BUFSIZ];        /* key label line */
  784. X    register int k;            /* loop control variable */
  785. X    int     stat = 0;            /* status from mid window */
  786. X    int     promptloc;            /* where prompt "?" goes */
  787. X
  788. X    /*
  789. X     * The top section of the screen consists of one line with key labels (in
  790. X     * case of single-key input screen) and a bar that separates this section
  791. X     * from the middle screen section.
  792. X     * 
  793. X     * We always add a Help and ? label. Thus, the interpreter preempts the 
  794. X     * use of the H and ? characters.
  795. X     */
  796. X
  797. X    for (topline[0] = 0; p->key; p++) {        /* start top window */
  798. X    if (iskey(p->key)) {            /* keystroke input ? */
  799. X        strcat(topline, p->name);        /* append key label */
  800. X        strcat(topline, "  ");        /* and some blanks */
  801. X    } else if (topline[0]) {        /* leak if first entry */
  802. X        fatal("mixed single-key and string input");
  803. X    }
  804. X    }
  805. X    printcl(topwin, 0, topline);        /* display key labels */
  806. X    if (topline[0])                /* if there are labels */
  807. X    wputs("Help ?");            /* display help key labels */
  808. X    printcl(topwin, 1, sect);            /* finish top window with bar */
  809. X
  810. X    /*
  811. X     * The bottom section of the screen consists of a bar that separates us
  812. X     * from the middle section, followed by the "help" string in the last
  813. X     * entry of the current screen definition, followed by (if not a
  814. X     * single-key input screen) a prompting question mark.
  815. X     */
  816. X
  817. X    printcl(botwin, 0, sect);            /* start lower window */
  818. X    promptloc = printcl(botwin, 1, p->help ? p->help : "") + 1;
  819. X    for (k = promptloc; k < botwin->size; k++)    /* clear rest of lower window */
  820. X    printcl(botwin, k, "");            /* lower window done */
  821. X
  822. X    if (p->action)                /* fill middle window */
  823. X    stat = CALL(p->action) ();        /* middle window done */
  824. X
  825. X    /* 
  826. X     * We leave the focus on the middle window, in case of single-key input,
  827. X     * and move the focus to the bottom window in case of prompted input.
  828. X     */
  829. X
  830. X    if (topline[0] == 0)            /* prompted input screen? */
  831. X    printat(botwin, promptloc, QUEST);    /* output "?" prompt */
  832. X
  833. X    /* Determine maximal length of string input */
  834. X
  835. X    maxstr = MAX(((botwin->size - 1) * CO - sizeof(QUEST) - 2), BUFSIZ - 1);
  836. X
  837. X    return (stat);                /* from middle window filler */
  838. X}
  839. X
  840. X/* kb_str - handle string input without defaults */
  841. X
  842. Xhidden int kb_str(p)
  843. Xregister Screen *p;
  844. X{
  845. X    char    string[BUFSIZ];        /* a character buffer */
  846. X    register int stat;
  847. X
  848. X    for (;;) {
  849. X    string[0] = '\0';            /* no default input */
  850. X    if (kb_read(string) == 0) {        /* command cancelled? */
  851. X        return (0);                /* quit */
  852. X    } else if ((stat = CALL(p->action) (string)) & S_BREAK) {
  853. X        return (stat);            /* we're done here */
  854. X    } else if (stat & S_REDRAW) {        /* screen was changed */
  855. X        kb_paint(p);            /* restore display */
  856. X    }
  857. X    }
  858. X}
  859. X
  860. X/* kb_yn - handle yes/no input */
  861. X
  862. Xhidden int kb_yn(p)
  863. Xregister Screen *p;
  864. X{
  865. X    char    string[BUFSIZ];        /* a character buffer */
  866. X    register int stat;            /* return status */
  867. X    static char yn[] = "nNyY";        /* input is not mapped to upper case */
  868. X    char   *in;
  869. X
  870. X    for (string[0] = '\0';;) {            /* clear input */
  871. X    if (kb_read(string) == 0) {        /* command cancelled? */
  872. X        return (0);                /* quit */
  873. X    } else if ((in = index(yn, string[0])) == 0) {    /* validate */
  874. X        beep();                /* complain */
  875. X        kb_paint(p);            /* restore display */
  876. X    } else if ((stat = CALL(p->action) (in - yn > 1)) & S_BREAK) {
  877. X        return (stat);            /* we're done here */
  878. X    } else if (stat & S_REDRAW) {        /* screen was changed */
  879. X        kb_paint(p);            /* restore display */
  880. X        string[0] = '\0';            /* clear input */
  881. X    }
  882. X    }
  883. X}
  884. X
  885. X/* kb_edt - handle string input with default */
  886. X
  887. Xhidden int kb_edt(p)
  888. Xregister Screen *p;
  889. X{
  890. X    char    string[BUFSIZ];        /* user input */
  891. X    register int stat;            /* return status */
  892. X
  893. X    for (;;) {
  894. X    (void) strncpy(string, p->help, BUFSIZ);/* stuff default input */
  895. X    if (kb_read(string) == 0) {        /* command cancelled */
  896. X        return (0);                /* quit */
  897. X    } else if ((stat = CALL(p->action) (string)) & S_BREAK) {
  898. X        return (stat);            /* we're done here */
  899. X    } else if (stat & S_REDRAW) {        /* screen was changed */
  900. X        kb_paint(p);            /* restore display */
  901. X    }
  902. X    }
  903. X}
  904. X
  905. X/* kb_read - general string edit/input routine */
  906. X
  907. Xhidden char *kb_read(string)
  908. Xchar    string[BUFSIZ];
  909. X{
  910. X    register char *cp;            /* a character pointer */
  911. X    register int c;            /* a character */
  912. X
  913. X    cp = string + strlen(string);        /* update buffer pointer */
  914. X    wputs(string);                /* show input to be edited */
  915. X
  916. X    for (;;) {
  917. X    if (!isascii(c = input())) {        /* ignore non-ascii codes */
  918. X        beep();                /* complain */
  919. X    } else if (c == ESC) {            /* ESC means don't do it */
  920. X        wputs(" (ESC)");            /* confirm input */
  921. X        sleep(1);
  922. X        return (0);                /* nothing left here to do */
  923. X    } else if (c == ENTER && (*cp = 0, !isempty(string))) {
  924. X        wputc(c);                /* echo */
  925. X        return (string);            /* we're done here */
  926. X    } else if (c == BS || c == DEL) {
  927. X        if (cp > string)
  928. X        cp--, wputs("\b \b");        /* remove one character */
  929. X    } else if (c == CTLU) {            /* line erase */
  930. X        while (cp > string)
  931. X        cp--, wputs("\b \b");
  932. X    } else if ((c == ' ' || isprint(c)) && (cp - string) < maxstr) {
  933. X        wputc(*cp++ = c);            /* accept and echo */
  934. X    } else {
  935. X        beep();                /* complain */
  936. X    }
  937. X    }
  938. X}
  939. X
  940. X/* kb_key - handle single-key input */
  941. X
  942. Xhidden int kb_key(p)
  943. XScreen *p;
  944. X{
  945. X    register int c;            /* a character */
  946. X    register Screen *q;            /* a screen (eh?) */
  947. X    register int stat;            /* a status */
  948. X
  949. X    for (;;) {
  950. X    if ((c = getkey()) == '?' || c == 'H') {/* is it a help request */
  951. X        kb_help(p);                /* yes, display key info */
  952. X        continue;                /* skip rest of loop */
  953. X    }
  954. X    for (q = p; q->key && q->key != c; q++)    /* look key up in table */
  955. X        /* void */
  956. X        ;
  957. X    if (q->key == 0) {            /* unrecognized key */
  958. X        beep();                /* complain */
  959. X    } else if (q->action == 0) {        /* action-less key */
  960. X        return (0);                /* we are done here */
  961. X    } else if ((stat = CALL(q->action) ()) & S_BREAK) {    /* do action */
  962. X        return (stat);            /* we are done here */
  963. X    } else if (stat & S_REDRAW) {        /* screen was changed */
  964. X        kb_paint(p);            /* restore screen */
  965. X    }
  966. X    }
  967. X}
  968. X
  969. X/* kb_cr - handle escape/enter input */
  970. X
  971. Xhidden int kb_cr(p)
  972. XScreen *p;
  973. X{
  974. X    register int c;
  975. X    register int stat;
  976. X
  977. X    for (;;) {
  978. X    if ((c = input()) == ESC) {        /* don't do it */
  979. X        wputs(" (ESC)");            /* confirm input */
  980. X        sleep(1);
  981. X        return (0);                /* we are done */
  982. X    } else if (c == ENTER) {        /* do the action */
  983. X        stat = CALL(p->action) ();        /* execute action */
  984. X        if (stat & S_BREAK) {        /* child kills parent */
  985. X        return (stat);            /* we are done */
  986. X        } else if (stat & S_REDRAW) {    /* screen was changed */
  987. X        kb_paint(p);            /* restore screen */
  988. X        }
  989. X    } else {                /* unacceptable input */
  990. X        beep();                /* complain */
  991. X    }
  992. X    }
  993. X}
  994. X
  995. X/* kb_help - display per-key help info; redraw screen when done */
  996. X
  997. Xhidden void kb_help(p)
  998. Xregister Screen *p;
  999. X{
  1000. X    register int k;
  1001. X
  1002. X    for (k = 0; k < midwin->size; k++)        /* erase middle window */
  1003. X    printcl(midwin, k, "");
  1004. X    for (k = 0; p[k].key; k++)            /* display key info */
  1005. X    printcl(midwin, k + 1, strcons("   %-10s %s", isascii(p[k].key) && 
  1006. X        isprint(p[k].key) ? p[k].name[1] ? strcons("%c(%s)", p[k].key, 
  1007. X        p[k].name + 1) : strcons("%c", p[k].key) : p[k].name, p[k].help));
  1008. X    for (k = 1; k < botwin->size - 1; k++)    /* erase bottom window */
  1009. X    printcl(botwin, k, "");
  1010. X    printcl(botwin, 1, anykey);            /* press any key to continue */
  1011. X    getkey();
  1012. X    kb_paint(p);                /* redraw screen */
  1013. X}
  1014. X
  1015. X/* structure that associates token value with function-key strings */
  1016. X
  1017. Xstruct keydef {
  1018. X    char  **strval;            /* key string */
  1019. X    int     tokval;            /* key value */
  1020. X};
  1021. X
  1022. Xhidden struct keydef keys[] = {
  1023. X    &KU, UP,                /* key strings are set */
  1024. X    &KD, DOWN,                /* in window.c */
  1025. X    &KL, LEFT,
  1026. X    &KR, RIGHT,
  1027. X    &PU, PGUP,
  1028. X    &PD, PGDN,
  1029. X    0, 0,
  1030. X};
  1031. X
  1032. X/* getkey - get key stroke, detect function keys, ignore case otherwise */
  1033. X
  1034. Xpublic int getkey()
  1035. X{
  1036. X    register int c;
  1037. X    register struct keydef *kp;
  1038. X    char    kstr[BUFSIZ];
  1039. X    register int len;
  1040. X
  1041. X    /*
  1042. X     * We assume that all function keys produce strings that start with the
  1043. X     * same lead-in character, and that those strings all have the same
  1044. X     * length. This is a reasonable assumption for cursor-control keys on
  1045. X     * most terminals.
  1046. X     */
  1047. X
  1048. X    if ((c = input()) == **(keys->strval)) {    /* lead-in character */
  1049. X
  1050. X    /*
  1051. X     * Read a number of characters equal to the length of the strings
  1052. X     * generated by function keys.
  1053. X     */
  1054. X
  1055. X    for (len = 1; len < strlen(*(keys[0].strval)); len++)
  1056. X        kstr[len] = c = input();
  1057. X    kstr[len] = '\0';
  1058. X
  1059. X    /* Compare what we just read with known function-key strings. */
  1060. X
  1061. X    for (kp = keys; kp->tokval; kp++)
  1062. X        if (strcmp(*(kp->strval) + 1, kstr + 1) == 0)
  1063. X        return (kp->tokval);        /* return token value */
  1064. X    }
  1065. X    /* Return the last read character. */
  1066. X
  1067. X    return ((isascii(c) && islower(c)) ? toupper(c) : c);
  1068. X}
  1069. X
  1070. X/* input - read one character without echoing or waiting for carriage return */
  1071. X
  1072. Xhidden int input()
  1073. X{
  1074. X
  1075. X#ifdef    unix
  1076. X
  1077. X    /*
  1078. X     * On unix systems, the terminal driver has been instructed to not echo
  1079. X     * and to return one character as soon as it comes available. Also the
  1080. X     * stdio routines have been instructed to process input in an unbuffered
  1081. X     * fashion. See kbdinit().
  1082. X     */
  1083. X
  1084. X    return (getchar());
  1085. X#endif
  1086. X
  1087. X#ifdef    MSDOS
  1088. X
  1089. X    /*
  1090. X     * On IBM-PC machines a function key produces a null character followed
  1091. X     * by a scan code. We translate the null prefix to an escape character
  1092. X     * since that is more like normal terminals do. The trick is to find out
  1093. X     * when we read a null character whether it was produced by pressing a
  1094. X     * real function-key or by pressing ctrl-@.
  1095. X     */
  1096. X
  1097. X    register int c;
  1098. X
  1099. X    return ((c = getch()) ? c : kbhit() ? ESC : 0);
  1100. X#endif
  1101. X
  1102. X#if (!defined(unix) && !defined(MSDOS))
  1103. X    "You should either define unix or MSDOS, or add support for another OS"
  1104. X#endif
  1105. X}
  1106. X
  1107. X/* kbdinit - set input mode, turn keypad on */
  1108. X
  1109. Xpublic void kbdinit()
  1110. X{
  1111. X
  1112. X#ifdef    MSDOS
  1113. X    (void) signal(SIGINT, SIG_IGN);    /* ignore control-c */
  1114. X#endif
  1115. X
  1116. X#ifdef  unix
  1117. X
  1118. X    /*
  1119. X     * On unix systems, instruct the terminal driver to not echo terminal
  1120. X     * input, and to return from a read as soon as one character comes
  1121. X     * available.
  1122. X     */
  1123. X
  1124. X# if (SIII||SYSV)
  1125. X    struct termio newmode;        /* AT&T */
  1126. X
  1127. X    (void) ioctl(0, TCGETA, &oldmode);        /* save terminal mode */
  1128. X    (void) ioctl(0, TCGETA, &newmode);        /* get terminal mode */
  1129. X    newmode.c_iflag &= ~(ICRNL | BRKINT);
  1130. X    newmode.c_oflag &= ~OPOST;
  1131. X    newmode.c_lflag &= ~(ICANON | ISIG | ECHO);
  1132. X    newmode.c_cc[VMIN] = 1;
  1133. X    newmode.c_cc[VTIME] = 0;
  1134. X    (void) ioctl(0, TCSETAF, &newmode);        /* set terminal mode */
  1135. X# else
  1136. X    struct sgttyb newmode;        /* V7 or Berkeley */
  1137. X
  1138. X    (void) gtty(0, &oldmode);            /* save terminal mode */
  1139. X    (void) gtty(0, &newmode);            /* get terminal mode */
  1140. X    newmode.sg_flags |= RAW;
  1141. X    newmode.sg_flags &= ~(ECHO | CRMOD);
  1142. X    (void) stty(0, &newmode);            /* set terminal mode */
  1143. X# endif
  1144. X
  1145. X    setbuf(stdin, (char *) 0);            /* select unbuffered input */
  1146. X
  1147. X    if (KS && *KS)                /* if there is a keypad */
  1148. X    tputs(KS, 1, fputchar);            /* enable it */
  1149. X#endif
  1150. X}
  1151. X
  1152. X/* kbdrest - reset terminal driver to previous state, turn keypad off */
  1153. X
  1154. Xpublic void kbdrest()
  1155. X{
  1156. X#ifdef  unix
  1157. X
  1158. X    /* Restore tty modes, either the AT&T way or the BSD+V7 way */
  1159. X
  1160. X# if (SIII||SYSV)
  1161. X    ioctl(0, TCSETAF, &oldmode);
  1162. X# else
  1163. X    stty(0, &oldmode);
  1164. X# endif
  1165. X
  1166. X    /* Disable keypad if there is one */
  1167. X
  1168. X    if (KE && *KE)
  1169. X    tputs(KE, 1, fputchar);
  1170. X#endif
  1171. X}
  1172. X
  1173. X/* isempty - check a string is all blanks or empty */
  1174. X
  1175. Xhidden int isempty(s)
  1176. Xregister char *s;
  1177. X{
  1178. X    while (*s && isspace(*s))
  1179. X    s++;
  1180. X    return (*s == 0);
  1181. X}
  1182. END_OF_main/kbdinp.c
  1183. if test 15738 -ne `wc -c <main/kbdinp.c`; then
  1184.     echo shar: \"main/kbdinp.c\" unpacked with wrong size!
  1185. fi
  1186. # end of overwriting check
  1187. fi
  1188. echo shar: End of archive 10 \(of 11\).
  1189. cp /dev/null ark10isdone
  1190. MISSING=""
  1191. for I in 1 2 3 4 5 6 7 8 9 10 11 ; do
  1192.     if test ! -f ark${I}isdone ; then
  1193.     MISSING="${MISSING} ${I}"
  1194.     fi
  1195. done
  1196. if test "${MISSING}" = "" ; then
  1197.     echo You have unpacked all 11 archives.
  1198.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1199. else
  1200.     echo You still need to unpack the following archives:
  1201.     echo "        " ${MISSING}
  1202. fi
  1203. ##  End of shell archive.
  1204. exit 0
  1205.  
  1206.  
  1207.