home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume10 / pcmail2 / part10 < prev    next >
Encoding:
Text File  |  1990-01-24  |  38.4 KB  |  1,214 lines

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