aboutsummaryrefslogtreecommitdiff
path: root/sys/tty/ttysubi.x
diff options
context:
space:
mode:
Diffstat (limited to 'sys/tty/ttysubi.x')
-rw-r--r--sys/tty/ttysubi.x194
1 files changed, 194 insertions, 0 deletions
diff --git a/sys/tty/ttysubi.x b/sys/tty/ttysubi.x
new file mode 100644
index 00000000..870dce59
--- /dev/null
+++ b/sys/tty/ttysubi.x
@@ -0,0 +1,194 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <chars.h>
+include <ctype.h>
+include "tty.h"
+
+.help ttysubi
+.nf ___________________________________________________________________________
+TTYSUBI -- Argument substitution on a control string.
+
+ Process a capability string containing arguments. Examples of such
+capability strings are cursor motion to [x,y], and set scrolling region to
+[line1,line2]. Note that arguments in the termcap database are zero-indexed
+by default, while the TTYSUBI arguments are one-indexed. The control string
+given as input has already been processed to reduce all escape sequences to
+single characters.
+
+Various output formats are supported (some of these are completely off the
+wall, very special case, but that's how termcap does it):
+
+ %d print decimal integer, zero origin.
+ %2 like %2d.
+ %3 like %3d.
+ %. put binary value of x,y arg as a character
+ %+x like %., but add value of char X first
+ %% print a single %.
+
+The following format codes affect the arguments, but do not directly cause
+any output:
+
+ %>xy if next arg value > char x add char y.
+ %r reverses order of arguments.
+ %i increments arg values by one, for 1 origin.
+ %n exlusive-or args with 0140B. (DM2500)
+ %B BCD next arg, (16*(x/10))+(mod(x,10).
+ %D Reverse coding (x-2*(mod(x,16))). (Delta Data)
+
+We have generalized the termcap formats somewhat to permit a greater range
+of %n formats (%1-%4), as well as %o and %x formats, in case a terminal
+comes along which likes octal or hex numbers.
+
+The %. format causes special problems. If the terminal requires coordinates
+in binary in the range zero or one to 40B, we can expect problems trying to
+push such chars through the OS driver and any other software (networks, etc.),
+since system software likes to map control characters on output. To get around
+this we have defined a set of reserved codes which are not to be generated.
+This set is defined in tty.h, and includes newline, tab, etc. When asked to
+output one of these chars, we output a char with a somewhat larger value
+and return the delta to our caller, which does whatever is appropriate to
+complete the function.
+.endhelp ______________________________________________________________________
+
+int procedure ttysubi (ctrlstr, outstr, maxch, coords, ncoords)
+
+char ctrlstr[ARB] # control string containing % formats
+char outstr[ARB] # receives processed string
+int maxch
+int coords[ncoords] # on input, coords; on output, deltas
+int ncoords
+
+bool reverse # reverse deltas on output
+int revstart # first arg/coord reversed
+int args[MAX_COORDS] # processed values of arguments
+int argnum # arg being processed
+int nargs # number of args (min(MAX_COORDS,ncoords))
+char driver_chars[NDCHARS]
+char ch, format_char
+int i, ip, op, field_width, left, right, temp
+int stridx(), strlen(), xor()
+data driver_chars /DRIVER_CHARS/
+errchk sprintf, pargi
+
+begin
+ # Make a local copy of the arguments to make reversal etc. easy.
+ # Also switch to zero-indexing internally, since the termcap entry
+ # is zero-indexed.
+
+ nargs = min (MAX_COORDS, ncoords)
+ do i = 1, nargs {
+ args[i] = coords[i] - 1 # make zero-indexed
+ coords[i] = 0 # init delta
+ }
+ argnum = 1 # output x first by default
+ reverse = false
+
+ op = 1
+ for (ip=1; ctrlstr[ip] != EOS && op <= maxch; ip=ip+1) {
+ ch = ctrlstr[ip]
+
+ # If normal char, we do not get past this if statement.
+ if (ch != '%') {
+ outstr[op] = ch
+ op = op + 1
+ next
+ } else {
+ ip = ip + 1 # fetch format-type char
+ ch = ctrlstr[ip]
+ }
+
+ # Get here only if processing a %x format specification.
+ switch (ch) {
+ case '%': # %% --> %
+ outstr[op] = ch
+ op = op + 1
+
+ case 'd', 'o', 'x', '1', '2', '3', '4':
+ # Output next argument according to the format given.
+ if (IS_DIGIT(ch)) {
+ field_width = TO_INTEG(ch)
+ format_char = 'd'
+ } else {
+ field_width = 0
+ format_char = ch
+ }
+
+ call sprintf (outstr[op], maxch-op+1, "%0*.0*")
+ call pargi (field_width)
+ call pargc (format_char)
+ call pargi (args[argnum])
+
+ argnum = min (nargs, argnum + 1)
+ op = op + strlen (outstr[op])
+
+ case '.', '+':
+ # Binary output format. Coordinate output in binary is a
+ # problem because the OS driver may see a tab, newline, or
+ # whatever and map it into something else. If the value of
+ # args[argnum] corresponds to a special control character,
+ # we increment it until we have an acceptable value, leaving
+ # it up to our caller to do the rest.
+
+ if (ch == '+') {
+ ip = ip + 1
+ args[argnum] = args[argnum] + ctrlstr[ip]
+ }
+
+ repeat {
+ ch = char (args[argnum])
+ if (stridx (ch, driver_chars) > 0) {
+ args[argnum] = args[argnum] + 1
+ coords[argnum] = coords[argnum] + 1
+ } else
+ break
+ }
+
+ outstr[op] = args[argnum]
+ op = op + 1
+ argnum = min (nargs, argnum + 1)
+
+ # The remaining cases are used to change the values of the
+ # remaining arguments, and do not cause any output.
+
+ case '>': # %>xy
+ if (args[argnum] > ctrlstr[ip+1])
+ args[argnum] = args[argnum] + ctrlstr[ip+2]
+ ip = ip + 2
+ case 'r': # swap remaining args
+ do left = argnum, (nargs - argnum + 1) / 2 {
+ right = nargs - (left - argnum)
+ temp = args[left]
+ args[left] = args[right]
+ args[right] = temp
+ }
+ reverse = !reverse
+ revstart = argnum
+ case 'i': # increment by one
+ do i = argnum, nargs
+ args[i] = args[i] + 1
+ case 'n': # exclusive or with 140B
+ do i = argnum, nargs
+ args[i] = xor (args[i], 140B)
+ case 'B': # BCD encode next arg
+ temp = args[argnum]
+ args[argnum] = 16 * (temp / 10) + mod (temp, 10)
+ case 'D': # Reverse code next arg
+ temp = args[argnum]
+ args[argnum] = temp - 2 * mod (temp, 16)
+ }
+ }
+
+ # If the input coordinates were reversed, we must reverse the
+ # correction deltas, too.
+
+ if (reverse)
+ do left = revstart, (nargs - revstart + 1) / 2 {
+ right = nargs - (left - revstart)
+ temp = coords[left]
+ coords[left] = coords[right]
+ coords[right] = temp
+ }
+
+ outstr[op] = EOS
+ return (op - 1)
+end