SECTION "Cifer" GET "LIBHDR" GET "SIM3270HDR" MANIFEST $( esc = #X1B cr = #XD bs = 8 lf = #XA $) LET clear.display() BE $( outch(esc); outch('J') FOR i = 0 TO 1920/bytesperword-1 DO $( dba!i := 0 dbb!i := 0 $) // clear field list $( LET ll = la la := -1 UNTIL ll=-1 DO $( LET lll = !ll free.ele(ll) ll := lll $) $) ca, rca := 0, 0 curruat := 0; curruatp := -1 $) AND highlights.off() BE $( outesc('X') outesc('+') highlighting := FALSE $) AND highlights.on() BE $( outesc('Y') outesc('+') highlighting := TRUE $) AND setup.display() BE $( outesc('=') outesc('J') outesc('N') // enable highlighting (model 2605-04) outesc('+') // copy highlight status outesc('X') // half intensity on outesc('+') outesc('M') // inverted video off outesc('+') $) AND unsetup.display() BE $( outesc('7') outesc('O') $) AND outesc(c) BE $( outch(esc) outch(c) $) AND keyboard.lock() BE outesc('"') AND set.cursor(c) BE $( ca := c UNLESS rca=ca DO $( outch(esc) outch('P') outch(c REM 80) outch(c/80) rca := ca $) find.user(ca) $) AND sound.alarm() BE outch(7) AND clear.line(ad) BE $( // clear line on display from address ad UNLESS rca=ad DO $( outesc('P') outch(ad REM 80) outch(ad/80) rca := ad $) outesc('K') // CLEAR TO END OF LINE $) AND keyboard.restore() BE $( aid := #X60 // reset AID byte outch(esc) outch('$') $) /* dispch routine for CIFER terminals (2605). Puts character at given address in dba, also writes it to the screen. Determines a good way to move the cursor. Must also restore cursor to correct address for input if no more.to.display. Cursor address on screen is given by rca, cursor address for user by ca. Cifer should be set up with: esc 8 roll mode, fixed screen esc J clear screen Controls used: esc C cursor right bs backspace esc ! cursor to end of line cr carriage return esc ← cursor bottom (left) lf line feed esc @ cursor down esc A cursor up esc : reverse line feed esc " keyboard lock esc $ keyboard unlock esc P x y move cursor to col x row y Uses cursor position command unless other commands can effect change in 0, 1, 2 or 3 characters. Cursor will often be in correct place if writing a field. */ AND dispch(a, ch) BE $( LET dch = dba%a LET ach = ascii(ch) dba%a := ch UNLESS ((#X20<ach<=#X7E)|(#X20<ascii(dch)<=#X7E))&(ch~=dch) DO // if blank on blank or characters same return RETURN UNLESS a=rca DO // dont bother to move if already OK $( TEST a=0 DO // use cursor home $( outch(esc); outch('H') $) OR $( TEST a=1840 DO // use cursor bottom $( outch(esc); outch('←') $) OR // try others $( LET row = a/80 LET col = a REM 80 LET rowc = rca/80 LET colc = rca REM 80 LET vd = ABS(row-rowc) LET hd = ABS(col-colc) UNLESS hd=0 DO IF col=0 DO hd := 1 UNLESS hd<=1 DO IF col=79 DO hd := 2 UNLESS vd=0 DO IF rowc>row DO vd := vd<<1 // weighted TEST vd+hd<=3 DO $( UNLESS hd=0 DO // move horizontally TEST col=0 DO // use cr outch(cr) OR $( TEST col=79 DO // move to end of line $( outch(esc); outch('!') $) OR $( TEST col>colc DO $( LET bas = rowc*80 FOR i = colc+bas TO col+bas-1 DO $( LET cc = ascii(dba%i) TEST #X20<=cc<=#X7E DO outch(cc) OR outch('*S') $) $) OR FOR i = 1 TO colc-col DO outch(bs) $) $) UNLESS vd=0 DO // move vertically TEST row>rowc DO FOR i = 1 TO row-rowc DO outch(lf) OR FOR i = 1 TO rowc-row DO $( outch(esc); outch(':') $) $) OR // use cursor position command $( outch(esc); outch('P') outch(col); outch(row) $) $) $) $) UNLESS #X20<=ach<=#X7E DO ach := '*S' outch(ach) UNLESS a=1919 DO a := a+1 rca := a UNLESS more.to.display DO set.cursor(a) $) AND handle.ch(ch) BE // handle character typed by the user $( /* The user has the ability to . move the cursor about . enter characters into display . use special function keys to cause data transmission The cifer keyboard has to emulate the 3277 keyboard. Some keys will behave as usual, others have altered functions and others will be ignored. The program has control of the screen at all times, LOCAL mode and ECHO ON are not used. The keys are handled as follows: clear scrn esc B performs clear AID byte, clears buffer and display (esc J) (cursor to 0) cursor down esc @ move cursor down cursor up esc A move cursor up cursor left esc D move cursor left cursor right esc C move cursor right esc ! move cursor to end of line home esc H move cursor to home position esc ← move cursor to bottom left position rev line feed esc : as cursor up esc esc write esc in buffer clear line esc K erase to end of field esc 0 erase input esc 8 insert mode esc 9 cancel insert mode All other escapes are illegal except 1, 2 and 3 (see below). Program attention keys: CLEAR use clear ENTER " return PA1 " esc 1 PA2 " esc 2 PA3 " esc 3 PF1 " ctrl-A PF2 " ctrl-S PF3 " ctrl-D PF4 " ctrl-F PF5 " ctrl-G PF6 " ctrl-H PF7 " ctrl-Z PF8 " ctrl-X PF9 " ctrl-C PF10 " ctrl-V PF11 " ctrl-B PF12 " ctrl-N The following characters behave 'as expected' (printing characters). They are entered at the current cursor position and the cursor moves right. sp ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ↑ ← a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~ any other characters, controls or otherwise are ignored. */ SWITCHON ch INTO // seems like a good idea $( CASE esc: IF escing DO safeprint(esc) escing := ~escing ENDCASE CASE 'A': CASE 'B': CASE 'C': CASE 'D': CASE 'H': CASE '@': CASE '!': CASE '←': CASE ':': CASE 'K': CASE '1': CASE '2': CASE '3': CASE '8': CASE '9': CASE '0': IF escing DO $( escing := FALSE SWITCHON ch INTO $( CASE ':': CASE 'A': outesc('A') // cursor up TEST ca/80=0 DO ca := 23*80 + ca REM 80 OR ca := ca-80 rca := ca find.user(ca) // sets curruat and curruatp ENDCASE CASE 'B': clear.display() aid := #X6D cba := 0; currat := 0 read.modified() ENDCASE CASE 'C': outesc('C') // cursor right ca := ca=1919 -> 0, ca+1 rca := ca find.user(ca) ENDCASE CASE 'D': outch(bs) ca := ca=0 -> 1919, ca-1 rca := ca find.user(ca) ENDCASE CASE '←': outesc('←') // cursor bottom left ca := 1840 rca := ca find.user(ca) ENDCASE CASE '@': TEST ca/80=23 DO $( ca := ca REM 80 outesc('@') $) OR $( ca := ca+80 outch(lf) $) rca := ca find.user(ca) ENDCASE CASE '!': outesc('!') // cursor to end of line ca := (ca/80)*80+79 rca := ca find.user(ca) ENDCASE CASE '1':CASE '2': CASE '3': aid := ch='1' -> #X6C, // PA1 ch='2' -> #X6E, // PA2 #X6B // PA3 read.modified() ENDCASE CASE '8': insert.mode.on := TRUE ENDCASE CASE '9': insert.mode.on := FALSE ENDCASE CASE '0': $( LET fuf = FALSE // unprotected fields found LET fpf = FALSE // protected fields found LET fu = 0 // address of first unprotected field LET a = next.attribute(0) UNTIL a=-1 DO // until no more fields $( LET b = a=1919 -> -1, next.attribute(a+1) LET c = b=-1 -> 1920, b currat := dbb%a TEST bit(currat, 2) DO fpf := TRUE OR // unless protected $( dbb%a := dbb%a & #XFE // reset MDT bit a := a+1 fuf := TRUE IF fu=0 DO fu := a UNTIL a=c DO $( dispch(a, null) a := a+1 $) $) a := b $) UNLESS fpf | fuf DO clear.display() set.cursor(fu) $) ENDCASE CASE 'H': // cursor home outesc('H') ca := 0 rca := 0 find.user(ca) ENDCASE CASE 'K': $( // erase to end of field LET a = next.attribute(ca) // rh limit LET ns = ? LET i = ca LET es = ebcdic('*S') IF curruatp<0 | ca=curruatp ENDCASE IF a=ca | bit(curruat, 2) ENDCASE IF a<0 DO a := 1920 a := a-1 ns := highlight.check() $( outch('*S') dba%i := es i := i+1 $) REPEATUNTIL i>a UNLESS ns=0 DO outesc(ns) dbb%curruatp := curruat | 1 // set modified bit UNLESS ca=1919 DO $( rca := i set.cursor(ca) $) $) $) ENDCASE $) CASE '*S': CASE '*"': CASE '#': CASE '$': CASE '%': CASE '&': CASE '*'': CASE '(': CASE ')': CASE '**': CASE '+': CASE ',': CASE '-': CASE '.': CASE '/': CASE '4': CASE '5': CASE '6': CASE '7': CASE ';': CASE '<': CASE '=': CASE '>': CASE '?': CASE 'E': CASE 'F': CASE 'G': CASE 'I': CASE 'J': CASE 'L': CASE 'M': CASE 'N': CASE 'O': CASE 'P': CASE 'Q': CASE 'R': CASE 'S': CASE 'T': CASE 'U': CASE 'V': CASE 'W': CASE 'X': CASE 'Y': CASE 'Z': CASE '[': CASE '\': CASE ']': CASE '↑': CASE 'a': CASE 'b': CASE 'c': CASE 'd': CASE 'e': CASE 'f': CASE 'g': CASE 'h': CASE 'i': CASE 'j': CASE 'k': CASE 'l': CASE 'm': CASE 'n': CASE 'o': CASE 'p': CASE 'q': CASE 'r': CASE 's': CASE 't': CASE 'u': CASE 'v': CASE 'w': CASE 'x': CASE 'y': CASE 'z': CASE '{': CASE '|': CASE '}': CASE '~': TEST insert.mode.on DO $( LET a = next.attribute(ca) // rh limit LET i = ca LET ns = ? IF curruatp<0 | ca=curruatp ENDCASE IF a=ca | bit(curruat,2) ENDCASE IF a<0 DO a := 1920 a := a-1 ns := highlight.check() $( LET tc = ascii(dba%i) // will go over end of dba! TEST safe.for.terminal(ch) DO outch(ch) OR outch('*S') dba%i := ebcdic(ch) i := i+1 ch := tc $) REPEATUNTIL i>a UNLESS ns=0 DO outesc(ns) dbb%curruatp := curruat | 1 // set modified bit UNLESS ca=1919 DO $( rca := a+1 set.cursor(ca+1) $) $) OR safeprint(ch) ENDCASE CASE tab: // tab key $( LET a1 = ca UNTIL a1=-1 DO $( a1 := next.attribute(a1) UNLESS a1=-1 DO $( a1 := a1+1 IF ~bit(dbb%(a1-1),2) DO BREAK $) $) IF a1=-1 DO $( a1 := 0 UNTIL a1=-1 | a1>ca DO $( a1 := next.attribute(a1) UNLESS a1=-1 DO $( a1 := a1+1 IF ~bit(dbb%(a1-1),2) DO BREAK $) $) IF a1=-1 DO a1 := 0 $) IF a1>1919 DO a1 := 0 set.cursor(a1) ENDCASE $) CASE lf: // newline $( LET line = ca/80 UNLESS line>=23 DO $( LET lina = (line+1)*80 // first address on new line LET a = find.attribute(lina) UNTIL a=-1 | lina=1919 | (lina/80)~=(line+1) DO $( UNLESS bit(dbb%a, 2) DO $( set.cursor(a=lina -> lina+1, lina) ENDCASE $) a := next.attribute(a+1) lina := a $) $) ENDCASE $) CASE del: $( LET a = next.attribute(ca) // rh limit LET i, ch = ca, ? LET ns = ? IF curruatp<0 | ca=curruatp ENDCASE IF a=ca | bit(curruat, 2) ENDCASE UNLESS a/80=ca/80 DO a := -1 a := a=-1 -> (ca/80)*80 + 79, a-1 ns := highlight.check() $( ch := i=a -> 0, dba%(i+1) ch := ascii(ch) TEST safe.for.terminal(ch) DO outch(ch) OR outch('*S') dba%i := ebcdic(ch) i := i+1 $) REPEATUNTIL i>a UNLESS ns=0 DO outesc(ns) dbb%curruatp := curruat | 1 // set modified bit rca := a=1919 -> 1919, a+1 set.cursor(ca) $) ENDCASE CASE ctrl.Q: abort(#X1010, ca) // escape to DEBUG ENDCASE // continue CASE ctrl.W: user.terminate() exstring := "user terminated" ENDCASE CASE cr: aid := #X7D; GOTO rma CASE ctrl.A: aid := #XF1; GOTO rma CASE ctrl.S: aid := #XF2; GOTO rma CASE ctrl.D: aid := #XF3; GOTO rma CASE ctrl.F: aid := #XF4; GOTO rma CASE ctrl.G: aid := #XF5; GOTO rma CASE ctrl.H: aid := #XF6; GOTO rma CASE ctrl.Z: aid := #XF7; GOTO rma CASE ctrl.X: aid := #XF8; GOTO rma CASE ctrl.C: aid := #XF9; GOTO rma CASE ctrl.V: aid := #X7A; GOTO rma CASE ctrl.B: aid := #X7B; GOTO rma CASE ctrl.N: aid := #X7C rma: read.modified() $) $) AND highlight.check() = VALOF $( LET newhi = bit(curruat,4) & ~bit(curruat,5) IF newhi & ~highlighting DO $( outesc('Y');outesc('+'); RESULTIS 'X' $) IF highlighting & ~ newhi DO $( outesc('X'); outesc('+');RESULTIS 'Y' $) RESULTIS 0 $) AND safeprint(ch) BE $( TEST bit(curruat, 2) | dbb%ca~=0 DO sound.alarm() // prot. or attr. OR $( LET ns = highlight.check() TEST safe.for.terminal(ch) & ~[bit(curruat,4) & bit(curruat,5)] DO outch(ch) OR outch('*S') dba%ca := ebcdic(ch) UNLESS ca=1919 DO $( ca := ca+1 rca := ca $) UNLESS curruatp=-1 DO dbb%curruatp := curruat | 1 // set modified bit UNLESS ns=0 DO outesc(ns) $) $) AND safe.for.terminal(ch) = #X20 <= ch <= #X7E