home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / asmutil / stdlib.zip / GETC.ASM < prev    next >
Assembly Source File  |  1991-03-08  |  6KB  |  275 lines

  1. ;
  2. ;
  3. ;
  4. stdlib        segment    para public 'slcode'
  5.         assume    cs:stdlib,ds:nothing
  6. ;
  7. ; Keyboard input routines
  8. ;
  9. ; Released to the public domain
  10. ; Created by: Randall Hyde
  11. ; Date: 7/90
  12. ; Updates:
  13. ;
  14. ;    8/11/90-    Modifications to use DOS 3fh call and handle eof
  15. ;    2/20/91-    Modified routines to eat LFs following CRs after
  16. ;            call to DOS getc routine.
  17. ;    3/6/91-        Modified code to use DOS raw mode for standard
  18. ;            input rather than cooked mode.  Added SetInBIOS,
  19. ;            SetInStd, and SetInRaw routines.
  20. ;
  21. ;
  22. cr        equ    0dh
  23. lf        equ    0ah
  24. CtrlZ        equ    1ah
  25. ;
  26. ;
  27. ; InpVector- Points at the current keyboard input routine.
  28. ;
  29. GetcAdrs    dd    sl_GetcStdIn
  30. GetcStkIndx    dw    0
  31. GetcStk        dd    16 dup (sl_GetcStdIn)
  32. GSIsize        =    $-GetcStk
  33. ;
  34. ; CharBuf- Used to hold character when reading from standard input device.
  35. ;
  36. CharBuf        db    ?
  37. ;
  38. ;
  39. ; LastChar- Used by BIOS keyboard routine to split non-ASCII keypresses
  40. ; into two separate calls.
  41. ;
  42. LastChar    dw    101h
  43. ;
  44. ; LastWasCR gets set to 1 when we read a CR.  If the char read when LastWasCR
  45. ; is one is a LF, this code eats the CR.
  46. ;
  47. LastWasCR    db    1        ;Assume at start last char was CR.
  48. ;
  49. ;
  50. ;
  51.         public    sl_Getc
  52. sl_Getc        proc    far
  53.         jmp    dword ptr stdlib:GetcAdrs
  54. sl_Getc        endp
  55. ;
  56. ;
  57. ; SetInAdrs- Stores ES:DI into InpVector which sets the new keyboard vector.
  58. ;
  59.         public    sl_SetInAdrs
  60. sl_SetInAdrs    proc    far
  61.         mov    word ptr stdlib:GetcAdrs, di
  62.         mov    word ptr stdlib:GetcAdrs+2, es
  63.         ret
  64. sl_SetInAdrs    endp
  65. ;
  66. ;
  67. ; GetInAdrs-    Returns the address of the current output routine in ES:DI.
  68. ;
  69.         public    sl_GetInAdrs
  70. sl_GetInAdrs    proc    far
  71.         les    di, dword ptr stdlib:GetcAdrs
  72.         ret
  73. sl_GetInAdrs    endp
  74. ;
  75. ;
  76. ;
  77. ; PushInAdrs-    Pushes the current input address onto the input stack
  78. ;        and then stores the address in es:di into the input address
  79. ;        pointer.  Returns carry clear if no problems.  Returns carry
  80. ;        set if there is an address stack overflow.  Does NOT modify
  81. ;        anything if the stack is full.
  82. ;
  83.         public    sl_PushInAdrs
  84. sl_PushInAdrs    proc    far
  85.         push    ax
  86.         push    di
  87.         cmp    stdlib:GetcStkIndx, GSIsize
  88.         jae    BadPush
  89.         mov    di, stdlib:GetcStkIndx
  90.         add    stdlib:GetcStkIndx, 4
  91.         mov    ax, word ptr stdlib:GetcAdrs
  92.         mov    word ptr stdlib:GetcStk[di], ax
  93.         mov    ax, word ptr stdlib:GetcAdrs+2
  94.         mov    word ptr stdlib:GetcStk+2[di], ax
  95.         pop    di
  96.         mov    word ptr stdlib:GetcAdrs, di
  97.         mov    word ptr stdlib:GetcAdrs+2, es
  98.         pop    ax
  99.         clc
  100.         ret
  101. ;
  102. BadPush:    pop    di
  103.         pop    ax
  104.         stc
  105.         ret
  106. sl_PushInAdrs    endp
  107. ;
  108. ;
  109. ; PopInAdrs-    Pops an input address off of the stack and stores it into
  110. ;        the GetcAdrs variable.
  111. ;
  112.         public    sl_PopInAdrs
  113. sl_PopInAdrs    proc    far
  114.         push    ax
  115.         mov    di, stdlib:GetcStkIndx
  116.         sub    di, 4
  117.         jns    GoodPop
  118. ;
  119. ; If this guy just went negative, set it to zero and push the address
  120. ; of the stdout routine onto the stack.
  121. ;
  122.         xor    di, di
  123.         mov    word ptr stdlib:GetcStk, offset sl_GetcStdIn
  124.         mov    word ptr stdlib:GetcStk+2, seg sl_GetcStdIn
  125. ;
  126. GoodPop:    mov    stdlib:GetcStkIndx, di
  127.         mov    es, word ptr GetcAdrs+2
  128.         mov    ax, word ptr stdlib:GetcStk+2[di]
  129.         mov    word ptr stdlib:GetcAdrs+2, ax
  130.         mov    ax, word ptr stdlib:GetcStk[di]
  131.         xchg    word ptr stdlib:GetcAdrs, ax
  132.         mov    di, ax
  133.         pop    ax
  134.         ret
  135. sl_PopInAdrs    endp
  136. ;
  137. ;
  138. ;
  139. ; SetInBIOS- Points the input pointer at the GetcBIOS routine.
  140. ;
  141.         public    sl_SetInBIOS
  142. sl_SetInBIOS    proc    far
  143.         mov    word ptr cs:GetcAdrs, offset sl_GetcBIOS
  144.         mov    word ptr cs:GetcAdrs+2, cs
  145.         ret
  146. sl_SetInBIOS    endp
  147. ;
  148. ;
  149. ;
  150. ; SetInStd- Points the input pointer at the GetcStdIn routine.
  151. ;
  152.         public    sl_SetInStd
  153. sl_SetInStd    proc    far
  154.         mov    word ptr cs:GetcAdrs, offset sl_GetcStdIn
  155.         mov    word ptr cs:GetcAdrs+2, cs
  156.         ret
  157. sl_SetInStd    endp
  158. ;
  159. ;
  160. ;
  161. ;
  162. ;
  163. ;
  164. ;
  165. ; GetcBIOS-     Reads a character from the keyboard using the BIOS routines.
  166. ;        Behaves just like DOS call insofar as it returns a zero if
  167. ;        the user presses a non-ASCII key and then returns the scan
  168. ;        code as the next keypress.  Returns 1 in AH signifying that
  169. ;        we haven't reached EOF.
  170. ;
  171.         public    sl_GetcBIOS
  172. sl_GetcBIOS    proc    far
  173.         cmp    byte ptr stdlib:LastChar, 0
  174.         jnz    GetNewChar
  175.         mov    ah, 1
  176.         mov    al, byte ptr stdlib:LastChar+1
  177.         mov    byte ptr stdlib:LastChar, al
  178.         mov    stdlib:LastWasCR, 0            ;BIOS doesn't convert
  179.         ret                    ; CR-> CR/LF.
  180. ;
  181. GetNewChar:    mov    ah, 0
  182.         int    16h
  183.         mov    stdlib:LastChar, ax
  184.         mov    ah, 1            ;Never EOF.
  185.         mov    stdlib:LastWasCR, 0
  186.         ret
  187. sl_GetcBIOS    endp
  188. ;
  189. ;
  190. ;
  191. ; GetcStdIn-     Reads a character from DOS' standard input.
  192. ;
  193. ; On return: ah=0 if eof, 1 if not eof.  AL=character.
  194. ;
  195. ; Modification 2/20/91:
  196. ;
  197. ;    Modified this code to eat any line feeds which immediately follow a
  198. ;    CR on the standard input.
  199. ;
  200. ;        3/8/91:
  201. ;
  202. ;    Modified this code to treat reading data from a file and from a
  203. ;    device as two different operations.  This removed some performance
  204. ;    problems and helped make the code a little "safer".
  205. ;
  206.         public    sl_GetcStdIn
  207.         assume    ds:stdlib
  208. sl_GetcStdIn    proc    far
  209.         push    bx
  210.         push    cx
  211.         push    dx
  212.         push    ds
  213. ;
  214.         mov    ax, 4400h        ;IOCTL read call
  215.         xor    bx, bx            ;Use std in handle.
  216.         int    21h
  217.         test    dl, 80h            ;See if file (0) or device (1).
  218.         jz    GetcAgain
  219. ;
  220.         test    dl, 40h            ;Check for EOF on device.
  221.         jz    DeviceEOF
  222. ;
  223. ; At this point we're reading a character from a device.  Simply call the
  224. ; DOS character input routine so we can avoid buffering and other nasty
  225. ; problems.  Note we have to handle EOF ourselves here.  DOS, however,
  226. ; handles ctrl-C.
  227. ;
  228.         mov    ah, 8
  229.         int    21h
  230.         mov    ah, 1
  231.         cmp    al, CtrlZ
  232.         jne    GoodRead
  233. DeviceEOF:    mov    ah, 0
  234.         jmp    Short GoodRead
  235. ;
  236. ;
  237. ; If we're reading from a file (rather than a device like the keyboard),
  238. ; drop down here to read the character using standard buffered I/O.
  239. ; Make sure to strip off LFs following CRs (since LFs typically follow CRs
  240. ; in a file).
  241. ;
  242. GetcAgain:    mov    ah, 3fh
  243.         mov    dx, cs
  244.         mov    ds, dx
  245.         mov    CharBuf, 0        ;Don't let LF trip us up.
  246.         lea    dx, CharBuf        ;Put char into CharBuf.
  247.         mov    cx, 1            ;Read one character.
  248.         mov    bx, 0            ;StdIn file handle
  249.         int    21h
  250.         jc    BadRead
  251.         mov    ah, al            ;ah=0 if eof, 1 if not eof.
  252.         mov    al, CharBuf        ;Get char if not eof.
  253.         cmp    al, LF            ;Was last char a line feed?
  254.         jne    NotLF
  255.         cmp    LastWasCR, 0
  256.         mov    LastWasCR, 0
  257.         jne    GetcAgain
  258. ;
  259. NotLF:        mov    LastWasCR, 0
  260.         cmp    al, CR
  261.         jne    GoodRead
  262.         mov    LastWasCR,1
  263. ;
  264. GoodRead:    clc
  265. BadRead:    pop    ds
  266.         pop    dx
  267.         pop    cx
  268.         pop    bx
  269.         ret
  270. sl_GetcStdIn    endp
  271. ;
  272. ;
  273. stdlib        ends
  274.         end
  275.