File getchlib.icn

Summary

###########################################################################

	File:     getchlib.icn

	Subject:  Procedures for getch for UNIX

	Author:   Richard L. Goerwitz

	Date:     May 2, 2001

###########################################################################

   This file is in the public domain.

###########################################################################

	Version:  1.14

###########################################################################

  Implementing getch() is a much, much more complex affair under UNIX
  than it is under, say, MS-DOS.  This library represents one,
  solution to the problem - one which can be run as a library, and
  need not be compiled into the run-time system.  Note that it will
  not work on all systems.  In particular, certain Suns (with a
  screwy stty command) and the NeXT 1.0 OS (lacking the -g option for
  stty) do not run getchlib properly.  See the bugs section below for
  workarounds.

  Four basic utilities are included here:

	getch()		- waits until a keystroke is available &
	    returns it without displaying it on the screen
	getche()	- same as getch() only with echo
	getse(s)	- like getche() only for strings.  The optional
	    argument s gives getse() something to start with.  Use this
           if, say, you want to read single characters in cbreak mode,
           but get more input if the character read is the first part
           of a longer command.  If the user backspaces over everything
           that has been input, getse() fails.  Returns on \r or \n.
	reset_tty()	- absolutely vital routine for putting the cur-
           rent tty line back into cooked mode; call it before exiting
           or you will find yourself with a locked-up terminal; use it
           also if you must temporarily restore the terminal to cooked
           mode

  Note that getse() *must* be used in place of read(&input) if you
  are planning on using getch() or getche(), since read(&input)
  assumes a tty with "sane" settings.

  Warning:  The routines below do not do any sophisticated output
  processing.  As noted above, they also put your tty line in raw
  mode.  I know, I know:  "Raw is overkill - use cbreak."  But in
  a world that includes SysV, one must pick a lowest common denomi-
  nator.  And no, icanon != cbreak.

  BUGS: These routines will not work on systems that do not imple-
  ment the -g option for the stty command.  The NeXT workstation is
  an example of such a system.  Tisk, tisk.  If you are on a BSD
  system where the network configuration makes stty | more impossible,
  then substitute /usr/5bin/stty (or whatever your system calls the
  System V stty command) for /bin/stty in this file.  If you have no
  SysV stty command online, then you can try replacing every instance
  of "stty -g 2>&1" below with "stty -g 2>&1 1> /dev/tty" or
  something similar.

###########################################################################

  Example program:

      The following program is a simple file viewer.  To run, it
  needs to be linked with itlib.icn, iscreen.icn, and this file
  (getchlib.icn).

  procedure main(a)

      # Simple pager/file searcher for UNIX systems.  Must be linked
      # with itlib.icn and iscreen.icn.
  
      local intext, c, s
  
      # Open input file
      intext := open(a[1],"r") | {
  	write(&errout,"Can't open input file.")
  	exit(1)
      }
  
      # Initialize screen
      clear()
      print_screen(intext) | exit(0)
  
      # Prompt & read input
      repeat {
  	iputs(igoto(getval("cm"), 1, getval("li")))
  	emphasize()
  	writes("More? (y/n or /search):")
  	write_ce(" ")
  	case c := getche() of {
  	    "y" : print_screen(intext) | break
  	    " " : print_screen(intext) | break
  	    "n" : break
  	    "q" : break
  	    "/" : {
  		iputs(igoto(getval("cm"), 1, getval("li")))
  		emphasize()
  		writes("Enter search string:")
  		write_ce(" ")
  		pattern := GetMoreInput()
  		/pattern | "" == pattern & next
  		# For more complex patterns, use findre() (IPL findre.icn)
  		if not find(pattern, s := !intext) then {
  		    iputs(igoto(getval("cm"), 1, getval("li")))
  		    emphasize()
  		    write_ce("String not found.")
  		    break
  		}
  		else print_screen(intext, s) | break
  	    }
  	}
      }
  
      reset_tty()
      write()
      exit(0)

  end
  
  procedure GetMoreInput(c)
  
      local input_string
      static BS
      initial BS := getval("bc") | "\b"
  
      /c := ""
      if any('\n\r', chr := getch())
      then return c
      else {
  	chr == BS & fail
  	writes(chr)
  	input_string := getse(c || chr) | fail
  	if any('\n\r', input_string)
  	then fail else (return input_string)
      }
  
  end
  
  procedure print_screen(f,s)
  
      if /s then
  	begin := 1
      # Print top line, if one is supplied
      else {
  	iputs(igoto(getval("cm"), 1, 1))
  	write_ce(s ? tab(getval("co") | 0))
  	begin := 2
      }
  
      # Fill the screen with lines from f; clear and fail on EOF.
      every i := begin to getval("li") - 1 do {
  	iputs(igoto(getval("cm"), 1, i))
  	if not write_ce(read(f) ? tab(getval("co") | 0)) then {
  	    # Clear remaining lines on the screen.
  	    every j := i to getval("li") do {
  		iputs(igoto(getval("cm"), 1, j))
  		iputs(getval("ce"))
  	    }
  	    iputs(igoto(getval("cm"), 1, i))
  	    fail
  	}
      }
      return
  
  end
  
  procedure write_ce(s)
  
      normal()
      iputs(getval("ce")) |
  	writes(repl(" ",getval("co") - *s))
      writes(s)
      return

  end

###########################################################################

  Requires: UNIX

###########################################################################

  Links: itlib

###########################################################################
Procedures:
change_tty_mode, getch, getche, getse, reset_tty, setup_tty

Records:
termio_struct

Global variables:
c_cc, current_mode

Links:
itlib.icn

This file is part of the (main) package.

Source code.

Details
Procedures:

change_tty_mode(switch)


getch()


getche()


getse(s)


reset_tty()


setup_tty()


Records:

termio_struct(vintr, vquit, verase, vkill)


Global variables:
c_cc

current_mode -- what mode are we in, raw or cooked?


This page produced by UniDoc on 2021/04/15 @ 23:59:54.