itlib part 2 of 3
Richard L. Goerwitz
goer at ellis.uchicago.edu
Fri Dec 21 16:56:54 AEST 1990
---- Cut Here and feed the following to sh ----
#!/bin/sh
# this is itlib.02 (part 2 of a multipart archive)
# do not concatenate these parts, unpack them in order with /bin/sh
# file itlib.icn continued
#
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck
if test "$Scheck" != 2; then
echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping itlib.icn'
else
echo 'x - continuing file itlib.icn'
sed 's/^X//' << 'SHAR_EOF' >> 'itlib.icn' &&
X
Xend
X
X
X
Xprocedure Decode(s)
X
X # Does things like turn ^ plus a letter into a genuine control
X # character.
X
X new_s := ""
X
X s ? {
X
X while new_s ||:= tab(upto('\\^')) do {
X chr := move(1)
X if chr == "\\" then {
X new_s ||:= {
X case chr2 := move(1) of {
X "\\" : "\\"
X "^" : "^"
X "E" : "\e"
X "b" : "\b"
X "f" : "\f"
X "n" : "\n"
X "r" : "\r"
X "t" : "\t"
X default : {
X if any(&digits,chr2) then {
X char(integer("8r"||chr2||move(2 to 0 by -1))) |
X er("Decode","bad termcap entry",3)
X }
X else chr2
X }
X }
X }
X }
X else new_s ||:= char(ord(map(move(1),&lcase,&ucase)) - 64)
X }
X new_s ||:= tab(0)
X }
X
X return new_s
X
Xend
X
X
X
Xprocedure igoto(cm,col,line)
X
X local colline, range, increment, str, outstr, chr, x, y
X
X if col > (tc_table["co"]) | line > (tc_table["li"]) then {
X colline := string(\col) || "," || string(\line) | string(\col|line)
X range := "(" || tc_table["co"]-1 || "," || tc_table["li"]-1 || ")"
X er("igoto",colline || " out of range " || (\range|""),9)
X }
X
X # Use the Iconish 1;1 upper left corner & not the C-ish 0 offsets
X increment := -1
X outstr := ""
X
X cm ? {
X while outstr ||:= tab(find("%")) do {
X tab(match("%"))
X chr := move(1)
X if case chr of {
X "." : outstr ||:= char(line + increment)
X "+" : outstr ||:= char(line + ord(move(1)) + increment)
X "d" : {
X str := string(line + increment)
X outstr ||:= right(str, integer(tab(any('23'))), "0") | str
X }
X }
X then line :=: col
X else {
X case chr of {
X "n" : line := ixor(line,96) & col := ixor(col,96)
X "i" : increment := 0
X "r" : line :=: col
X "%" : outstr ||:= "%"
X "B" : line := ior(ishift(line / 10, 4), line % 10)
X ">" : {
X x := move(1); y := move(1)
X line > ord(x) & line +:= ord(y)
X &null
X }
X } | er("goto","bad termcap entry",5)
X }
X }
X return outstr || tab(0)
X }
X
Xend
X
X
X
Xprocedure iputs(cp, affcnt)
X
X local baud_rates, char_rates, i, delay, PC
X static num_chars, char_times
X # global tty_speed
X
X initial {
X num_chars := &digits ++ '.'
X char_times := table()
X # Baud rates in decimal, not octal (as in termio.h)
X baud_rates := [0,7,8,9,10,11,12,13,14,15]
X char_rates := [0,333,166,83,55,41,20,10,10,10]
X every i := 1 to *baud_rates do {
X char_times[baud_rates[i]] := char_rates[i]
X }
X }
X
X type(cp) == "string" |
X er("iputs","you can't iputs() a non-string value!",10)
X
X cp ? {
X delay := tab(many(num_chars))
X if ="*" then {
X delay *:= \affcnt |
X er("iputs","affected line count missing",6)
X }
X writes(tab(0))
X }
X
X if (\delay, tty_speed ~= 0) then {
X PC := tc_table["pc"] | "\000"
X char_time := char_times[tty_speed] | (return "speed error")
X delay := (delay * char_time) + (char_time / 2)
X every 1 to delay by 10
X do writes(PC)
X }
X
X return
X
Xend
X
X
X
Xprocedure getspeed()
X
X local stty_g, stty_output, c_cflag, o_speed
X
X stty_g := open("/bin/stty -g 2>&1","pr") |
X er("getspeed","Can't access your stty command.",4)
X stty_output := !stty_g
X close(stty_g)
X
X \stty_output ? {
X # tab to the third field of the output of the stty -g cmd
X tab(find(":")+1) & tab(find(":")+1) &
X c_cflag := integer("16r"||tab(find(":")))
X } | er("getspeed","Unable to unwind your stty -g output.",4)
X
X o_speed := iand(15,c_cflag)
X return o_speed
X
Xend
SHAR_EOF
echo 'File itlib.icn is complete' &&
true || echo 'restore of itlib.icn failed'
rm -f _shar_wnt_.tmp
fi
# ============= iscreen.icn ==============
if test -f 'iscreen.icn' -a X"$1" != X"-c"; then
echo 'x - skipping iscreen.icn (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting iscreen.icn (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'iscreen.icn' &&
X############################################################################
X#
X# Name: iscreen.icn
X#
X# Title: Icon screen functions
X#
X# Author: Richard L. Goerwitz
X#
X# Version: 1.12
X#
X############################################################################
X#
X# This and future version of iscreen are placed in the public domain - RLG
X#
X############################################################################
X#
X# This file contains some rudimentary screen functions for use with
X# itlib.icn (termlib-like routines for Icon).
X#
X# clear() - clears the screen (tries several methods)
X# emphasize() - initiates emphasized mode
X# normal(mode) - resets to normal mode; if mode is null,
X# or "b," normal() assumes you were in emphasize mode,
X# otherwise you are assumed to have been in underline mode
X# message(s) - displays message s on 2nd-to-last line
X# underline() - initiates underline mode
X# status_line(s,s2,p) - draws status line s on the 3rd-to-last
X# screen line; if s is too short for the terminal, s2 is used;
X# if p is nonnull then it either centers, left-, or right-justi-
X# fies, depending on the value, "c," "l," or "r."
X#
X############################################################################
X#
X# Requires: UNIX
X#
X# Links: itlib.icn (or your OS-specific port of itlib)
X#
X# See also: boldface.icn
X#
X############################################################################
X
X
Xprocedure clear()
X
X # Clears the screen. Tries several methods.
X
X if not iputs(getval("cl"))
X then iputs(igoto(getval("cm"),1,1))
X if not iputs(getval("cd"))
X then {
X every i := 1 to getval("li") do {
X iputs(igoto(getval("cm"),1,i))
X iputs(getval("ce"))
X }
X iputs(igoto(getval("cm"),1,1))
X }
X return
X
Xend
X
X
X
Xprocedure emphasize()
X
X static bold_str, cookie_str
X initial {
X if bold_str := getval("so")
X then cookie_str := repl(getval("bc") | "\b", getval("sg"))
X else {
X if bold_str := getval("us")
X then cookie_str := repl(getval("bc") | "\b", getval("ug"))
X }
X }
X
X iputs(\bold_str)
X iputs(\cookie_str)
X return
X
Xend
X
X
X
Xprocedure underline()
X
X static underline_str, cookie_str
X initial {
X if underline_str := getval("us")
X then cookie_str := repl(getval("bc") | "\b", getval("sg"))
X }
X
X iputs(\underline_str)
X iputs(\cookie_str)
X return
X
Xend
X
X
X
Xprocedure normal(mode)
X
X static UN_bold_str, bold_cookie_str,
X UN_underline_str, underline_cookie_str
X initial {
X
X if UN_bold_str := getval("se") then
X bold_cookie_str := repl(getval("bc") | "\b", getval("sg"))
X else {
X UN_bold_str := getval("ue")
X bold_cookie_str := repl(getval("bc")|"\b", getval("ug"))
X }
X if UN_underline_str := getval("ue") then
X underline_cookie_str := repl(getval("bc")|"\b", getval("ug"))
X }
X
X if /mode | (mode == "b") then {
X iputs(\UN_bold_str)
X iputs(\bold_cookie_str)
X return
X }
X
X iputs(\UN_underline_str)
X iputs(\underline_cookie_str)
X return
X
Xend
X
X
X
Xprocedure status_line(s,s2,p)
X
X # Writes a status line on the terminal's third-to-last line
X # The only necessary argument is s. S2 (optional) is used
X # for extra narrow screens. In other words, by specifying
X # s2 you give status_line an alternate, shorter status string
X # to display, in case the terminal isn't wide enough to sup-
X # port s. If p is nonnull, then the status line is either
X # centered (if equal to "c"), left justified ("l"), or right
X # justified ("r").
X
X local width
X
X /s := ""
X width := getval("co")
X if *s > width then {
X (*s2 < width, s := \s2) |
X er("status_line","Your terminal is too narrow.",4)
X }
X case \p of {
X "c" : s := center(s,width-1)
X "l" : s := left(s,width-1)
X "r" : s := right(s,width-1)
X default: stop("status_line: Unknown option "||string(p),4)
X }
X
X iputs(igoto(getval("cm"), 1, getval("li")-2))
X emphasize(); writes(s); iputs(getval("ce"))
X normal()
X return
X
Xend
X
X
X
Xprocedure message(s)
X
X # Display prompt s on the second-to-last line of the screen.
X # I hate to use the last line, due to all the problems with
X # automatic scrolling.
X
X /s := ""
X normal()
X iputs(igoto(getval("cm"), 1, getval("li")-1))
X writes(s[1:getval("co")] | s)
X iputs(getval("ce"))
X return
X
Xend
SHAR_EOF
true || echo 'restore of iscreen.icn failed'
rm -f _shar_wnt_.tmp
fi
# ============= itlibdos.icn ==============
if test -f 'itlibdos.icn' -a X"$1" != X"-c"; then
echo 'x - skipping itlibdos.icn (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting itlibdos.icn (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'itlibdos.icn' &&
X##########################################################################
X#
X# Name: itlibdos.icn
X#
X# Title: Icon termlib-type tools (MS-DOS version)
X#
X# Author: Richard L. Goerwitz
X#
X# Version: 1.12
X#
X###########################################################################
X#
X# I place this and future versions of itlibdos in the public domain - RLG
X#
X###########################################################################
X#
X# The following library represents a series of rough functional
X# equivalents to the standard Unix low-level termcap routines. They
X# are not meant as exact termlib clones. Nor are they enhanced to
X# take care of magic cookie terminals, terminals that use \D in their
X# termcap entries, or, in short, anything I felt would not affect my
X# normal, day-to-day work with ANSI and vt100 terminals.
X#
X# Requires: An MS-DOS platform & co-expressions. The MS-DOS version
X# is a port of the Unix version. Software you write for this library
X# can be made to run under Unix simply by substituting the Unix ver-
X# sion of this library. See below for additional notes on how to use
X# this MS-DOS port.
X#
X# setname(term)
X# Use only if you wish to initialize itermlib for a terminal
X# other than what your current environment specifies. "Term" is the
X# name of the termcap entry to use. Normally this initialization is
X# done automatically, and need not concern the user.
X#
X# getval(id)
X# Works something like tgetnum, tgetflag, and tgetstr. In the
X# spirit of Icon, all three have been collapsed into one routine.
X# Integer valued caps are returned as integers, strings as strings,
X# and flags as records (if a flag is set, then type(flag) will return
X# "true"). Absence of a given capability is signalled by procedure
X# failure.
X#
X# igoto(cm,destcol,destline) - NB: default 1 offset (*not* zero)!
X# Analogous to tgoto. "Cm" is the cursor movement command for
X# the current terminal, as obtained via getval("cm"). Igoto()
X# returns a string which, when output via iputs, will cause the
X# cursor to move to column "destcol" and line "destline." Column and
X# line are always calculated using a *one* offset. This is far more
X# Iconish than the normal zero offset used by tgoto. If you want to
X# go to the first square on your screen, then include in your program
X# "iputs(igoto(getval("cm"),1,1))."
X#
X# iputs(cp,affcnt)
X# Equivalent to tputs. "Cp" is a string obtained via getval(),
X# or, in the case of "cm," via igoto(getval("cm"),x,y). Affcnt is a
X# count of affected lines. It is only relevant for terminals which
X# specify proportional (starred) delays in their termcap entries.
X#
X# Notes on the MS-DOS version:
X# There are two basic reasons for using the I/O routines
X# contained in this package. First, by using a set of generalized
X# routines, your code will become much more readable. Secondly, by
X# using a high level interface, you can avoid the cardinal
X# programming error of hard coding things like screen length and
X# escape codes into your programs.
X# To use this collection of programs, you must do two things.
X# First, you must add the line "device=ansi.sys" (or the name of some
X# other driver, like zansi.sys, nansi.sys, or nnansi.sys [=new
X# nansi.sys]) to your config.sys file. Secondly, you must add two
X# lines to your autoexec.bat file: 1) "set TERM=ansi-mono" and 2)
X# "set TERMCAP=\location\termcap." The purpose of setting the TERM
X# variable is to tell this program what driver you are using. If you
X# have a color system, use "ansi-color" instead of "ansi-mono," and
X# if you are using nansi or zansi instead of vanilla ansi, use one of
X# these names instead of the "ansi" (e.g. "zansi-mono"). The purpose
X# of setting TERMCAP is to make it possible to determine where the
X# termcap file is located. The termcap file (which should have been
X# packed with this library as termcap.dos) is a short database of all
X# the escape sequences used by the various terminal drivers. Set
X# TERMCAP so that it reflects the location of this file (which should
X# be renamed as termcap, for the sake of consistency with the Unix
X# version). Naturally, you must change "\location\" above to reflect
X# the correct path on your system.
X# Although I make no pretense here of providing here a complete
X# introduction to the format of the termcap database file, it will be
X# useful, I think, to explain a few basic facts about how to use this
X# program in conjunction with it. If, say, you want to clear the
X# screen, add the line,
X#
X# iputs(getval("cl"))
X#
X# to your program. The function iputs() outputs screen control
X# sequences. Getval retrieves a specific sequence from the termcap
X# file. The string "cl" is the symbol used in the termcap file to
X# mark the code used to clear the screen. By executing the
X# expression "iputs(getval("cl"))," you are 1) looking up the "cl"
X# (clear) code in the termcap database entry for your terminal, and
X# the 2) outputting that sequence to the screen.
X# Some other useful termcap symbols are "ce" (clear to end of
X# line), "ho" (go to the top left square on the screen), "so" (begin
X# standout mode), and "se" (end standout mode). To output a
X# boldfaced string, str, to the screen, you would write -
X#
X# iputs(getval("so"))
X# writes(str)
X# iputs(getval("se"))
X#
X# You could write "iputs(getval("so") || str || getval("se")), but
X# this would only work for DOS. Some Unix terminals require padding,
X# and iputs() handles them specially. Normally you should not worry
X# about Unix quirks under DOS. It is in general wise, though, to
X# separate out screen control sequences, and output them via iputs().
X# It is also heartily to be recommended that MS-DOS programmers
X# try not to assume that everyone will be using a 25-line screen.
X# Some terminals are 24-line. Some 43. Some have variable window
X# sizes. If you want to put a status line on, say, the 2nd-to-last
X# line of the screen, then determine what that line is by executing
X# "getval("li")." The termcap database holds not only string-valued
X# sequences, but numeric ones as well. The value of "li" tells you
X# how many lines the terminal has (compare "co," which will tell you
X# how many columns). To go to the beginning of the second-to-last
X# line on the screen, type in:
X#
X# iputs(igoto(getval("cm"), 1, getval("li")-1))
X#
X# The "cm" capability is a special capability, and needs to be output
X# via igoto(cm,x,y), where cm is the sequence telling your computer
X# to move the cursor to a specified spot, x is the column, and y is
X# the row. The expression "getval("li")-1" will return the number of
X# the second-to-last line on your screen.
X#
X##########################################################################
X#
X# Requires: MS-DOS, coexpressions
X#
X# See also: iscreen.icn (a set of companion utilities)
X#
X##########################################################################
X
X
Xglobal tc_table
Xrecord true()
X
X
Xprocedure check_features()
X
X local in_params, line
X
X initial {
X find("ms-dos",map(&features)) |
X er("check_features","MS-DOS system required",1)
X find("o-expres",&features) |
X er("check_features","co-expressions not implemented - &$#!",1)
X }
X
X return
X
Xend
X
X
X
Xprocedure setname(name)
X
X # Sets current terminal type to "name" and builds a new termcap
X # capability database (residing in tc_table). Fails if unable to
X # find a termcap entry for terminal type "name." If you want it
X # to terminate with an error message under these circumstances,
X # comment out "| fail" below, and uncomment the er() line.
X
X #tc_table is global
X
X check_features()
X
X tc_table := maketc_table(getentry(name)) | fail
X # er("setname","no termcap entry found for "||name,3)
X return
X
Xend
X
X
X
Xprocedure getname()
X
X # Getname() first checks to be sure we're running under DOS, and,
X # if so, tries to figure out what the current terminal type is,
X # checking the value of the environment variable TERM, and if this
X # is unsuccessful, defaulting to "mono."
X
X local term, tset_output
X
X check_features()
X term := getenv("TERM") | "mono"
X
X return \term |
X er("getname","can't seem to determine your terminal type",1)
X
Xend
X
X
X
Xprocedure er(func,msg,errnum)
X
X # short error processing utility
X write(&errout,func,": ",msg)
X exit(errnum)
X
Xend
X
X
X
Xprocedure getentry(name, termcap_string)
X
X # "Name" designates the current terminal type. Getentry() scans
X # the current environment for the variable TERMCAP. If the
X # TERMCAP string represents a termcap entry for a terminal of type
X # "name," then getentry() returns the TERMCAP string. Otherwise,
X # getentry() will check to see if TERMCAP is a file name. If so,
X # getentry() will scan that file for an entry corresponding to
X # "name." If the TERMCAP string does not designate a filename,
X # getentry() will look through ./termcap for the correct entry.
X # Whatever the input file, if an entry for terminal "name" is
X # found, getentry() returns that entry. Otherwise, getentry()
X # fails.
X
X local f, getline, line, nm, ent1, ent2
X
X /termcap_string := getenv("TERMCAP")
X
X if \termcap_string ? (not match("\\"), pos(0) | tab(find("|")+1), =name)
X then return termcap_string
X else {
X
X # The logic here probably isn't clear. The idea is to try to use
X # the termcap environment variable successively as 1) a termcap en-
X # try and then 2) as a termcap file. If neither works, 3) go to
X # the ./termcap file. The else clause here does 2 and, if ne-
X # cessary, 3. The "\termcap_string ? (not match..." expression
X # handles 1.
X
X if find("\\",\termcap_string)
X then f := open(termcap_string)
X /f := open("termcap") |
X er("getentry","I can't access your termcap file",1)
X
X getline := create read_file(f)
X
X while line := @getline do {
X if line ? (pos(1) | tab(find("|")+1), =name, any(':|')) then {
X entry := ""
X while (\line | @getline) ? {
X if entry ||:= 1(tab(find(":")+1), pos(0))
SHAR_EOF
true || echo 'restore of itlibdos.icn failed'
fi
echo 'End of part 2'
echo 'File itlibdos.icn is continued in part 3'
echo 3 > _shar_seq_.tmp
exit 0
More information about the Alt.sources
mailing list