1
0
mirror of https://github.com/PDP-10/its.git synced 2026-01-22 10:32:13 +00:00
PDP-10.its/src/syseng/rubout.3
Eric Swenson 7ed0d1d8ce Added SRCCOM program and documentation.
SRCCOM is a source/binary comparison program.
SRCCOM also support source merges.
2016-11-27 08:48:36 +01:00

788 lines
22 KiB
Groff
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

.BEGIN RUBOUT ;Rubout processor routine for -*-MIDAS-*- programs.
.AUXIL ;Don't mention all my symbols in crefs of programs that use me.
;PRINT VERSION NUMBER
.TYO6 .IFNM1
.TYO 40
.TYO6 .IFNM2
PRINTX/ INCLUDED IN THIS ASSEMBLY.
/
;The main entry points of the RUBOUT package are INIT and READ.
;Each time you want to start reading one object, you should call INIT.
;After that, you call READ one or more times until you have enough
;input to act on. When you wish to start reading a "new" object -- and not
;allow the old one to be rubbed out any longer -- call INIT again.
;There are also subsidiary entry points called character service routines.
;These handle the display updating for one input character. The
;rubout-processing significance of all characters is determined by
;a routine which you supply, called DISPATCH, which examines the
;character and goes to the appropriate service routines.
;We supply a default definition of DISPATCH for you to use as
;all or part of your dispatch routine, and also as a guide to what
;dispatch routines should do.
;Calling Conventions:
;All subroutines herein are called by PUSHJ P,. They normally do NOT skip-return.
;Character service routines skip, with a return code in A,
;to tell READ to return with that code.
;Arguments are passed in ACs A,B,C and D. D must be C+1.
;Subroutines may alter A-D as documented with each routine.
;These switches may be set by the caller to request optional features.
;They may be defined local to the block RUBOUT.
IFNDEF $$MULTI,$$MULTI==0 ;Be efficient for CRs, BSs and TABs in the text.
;$$MULTI==1 makes the code larger but makes
;rubbing out these characters do less display.
IFNDEF $$FCI,$$FCI==1 ;Handle full char set input
;(distinguish Alpha from C-B).
;$$FCI==1 works for ASCII input streams too.
IFNDEF $$PROMPT,$$PROMPT==0 ;1 => call PROMPT to type a prompt string when needed.
IFNDEF $$HELP,$$HELP==0 ;1 => call HELP when the user types Top-H.
IFNDEF $$CTLBRK,$$CTLBRK==0 ;1 => the default dispatch routine
;makes all random control characters break.
IFNDEF $$CTLECH,$$CTLECH==1 ;1 => control chars that perform editing functions
;also echo, and must be erased. Doesn't include Rubout.
IFNDEF $$BRKINS,$$BRKINS==1 ;1 => break characters insert themselves first,
;in the default dispatch routine.
IFNDEF $$FFCLR,$$FFCLR==1 ;1 => ^L echoes as clear screen.
;0 => it echoes as uparrow-L, and we re-use the same lines.
;These exits must be defined by the user. They may be defined local
;to the block RUBOUT:
;INCHR reads a character, returning it in A.
;OUTCHR outputs the character in A. --MORE-- should, for
; most applications, be inhibited
; by having %TJMOR set in the channel used for output,
; if it is a terminal. If you want to do --MORE--,
; you should make sure that when the --MORE-- is proceeded
; its line is re-used so that the screen is as if
; the --MORE-- had never been.
;DISPLAY outputs the character in A in display mode (%TJDIS).
; It can be any stream that knows the meaning of ^P.
; If outputting to a terminal, set %TJMOR.
;PROMPT types a prompt-string. Called at appropriate times.
; Needed only if $$PROMPT==1. Not called when READ is
; entered; if you want that, do it yourself.
;HELP types a help-string when the user typed Top-H.
; Needed only if $$HELP==1. On displays,
; HELP may wish to wait for input to be available
; and then jump to REDISP without reading it.
;DISPATCH takes a character in A, and jumps off to the service
; routine for it, which may be one of those provided
; by RUBOUT (such as RUBOUT, INSERT, BREAK, etc.).
; A sample dispatch routine is called RB$DSP.
; You can use it, if it is right, by doing
; RUBOUT"DISPATCH==RUBOUT"RB$DSP
; after the .INSRT SYSENG;RUBOUT, or your dispatch
; can jump off to it, after handling a few cases specially.
;Service routines provided in this file include
;INSERT, BREAK, BRKCR, BRKINS, INSCR, QUOTE, QUIT, CANCEL, RUBOUT,
;IGNORE, REDISP, CLRLIN, CTLU.
;Each call to the rubout processor must give the address of an argument
;block, called the rubout processor block, in B.
;This block enables you to carry on several transactions with
;RUBOUT at the same time (or one inside another). If you wish,
;you can make your DISPATCH, OUTCHR, etc. entries jump through
;extra words at the end of the rubout processor block (words which
;normally are not used), and thus have different routines for
;each transaction.
;These are the words in the rubout processor argument block
;that are used by this package:
RB.==777777 ;Bit typeout mode prefix.
RB.POS==0 ;Vpos,,Hpos of 1st character in buffer.
RB.WID==1 ;Width of line on terminal.
RB.TYP==2 ;TTY characteristics.
;positive => printing terminal.
RB%FIL==2 ; bit 3.2 => not even that, just reading from a file.
;0 => glass teletype (character erase only, no move up).
;negative => full display.
RB%CID==1 ; bit 3.1 => can insert/delete as well.
RB%SAI==2 ; BIT 3.2 => SAIL mode on, ctl chars echo as one pos.
RB.BEG==3 ;B.P. to ILDB start of buffer.
RB.END==4 ;B.P. to ILDB 1st character after end buffer.
;Actually, you should leave space for two characters
;to be stored past RB.END.
RB.PTR==5 ;B.P. for storing into buffer.
RB.PRS==6 ;B.P. to last character parsed at next level up.
RB.STAT==7 ;Word of flags indicating temporary state of editing
RB.LEN==10 ;Number of words in the rubout block
;The caller should set up RB.BEG and RB.END, then call INIT which will
;initialize RB.TYP, RB.WID, and RB.POS and RB.PTR.
;The use of RB.PRS:
;Complicated break-conditions do not need to be expressed in the DISPATCH routine.
;If you use $$BRKINS==1 (Insert break characters in the buffer), then
;if the higher level parser decides it needs more characters it can just call
;READ again to get more. It could then re-parse the whole input string.
;To save time, it can put in RB.PRS the pointer to the last character that
;it actually parsed. On return from READ, if RB.PRS is unchanged, all
;characters up to that point were not changed (ie, not rubbed out)
;and the parser can continue from where it left off.
;Otherwise, RB.PRS will be zero, to indicate that the parser must
;rescan the entire string as returned by READ.
;If you like, you can keep the parser's fetch-pointer in RB.PRS,
;calling READ when it reaches RB.PTR, and noticing when it is zeroed.
DEFINE SYSCAL NAME,ARGS
.CALL [SETZ ? SIXBIT/NAME/ ? ARGS ((SETZ))]
TERMIN
;Get a character's graphic type. Takes character in A, returns type in A.
;Type codes are:
;0 - 1-POSITION CHARACTER.
;1 - ORDINARY CTL CHAR - USUALLY 2-POSITION, BUT 1-POSITION IN SAIL MODE.
;2 - BACKSPACE.
;3 - CR
;4 - LF
;5 - TAB.
;6 - SPECIAL CTL CHARACTER - 2-POSITION EVEN IN SAIL MODE.
;7 - ^G
CHRTYP:
IFN $$FCI,[
PUSH P,C ;If storing 9-bit bytes in the buffer,
LDB C,[300600,,RB.PTR(B)]
CAIN C,7
JRST CHRTY1
CAIGE A,177 ;assume that anything
JRST [ SETZ A, ;below 177 is either an ASCII graphic or a SAIL graphic.
JRST POPCJ]
CHRTY1: PUSHJ P,CHRASC ;Other things were echoed by converting them to ASCII.
POP P,C
];IFN $$FCI
CAIN A,177
JRST [ MOVEI A,6 ;Assume rubout is a 2-position character,
POPJ P,] ;even though we shouldn't be echoing them.
PUSH P,C
PUSH P,D
MOVE C,A
IDIVI C,6
CAIL A,40
TDZA A,A
LDB A,RRCHBP(D)
JRST POPDCJ
;TABLES USED BY CHRTYP THE ENTRY FOR EACH
;CHARACTER IS AN INDEX INTO RRFORT OR RRBACT.
RRCHBP: REPEAT 6,<360600-<6*.RPCNT>_12.>,,RRCHTB(C)
RRCHTB: .BYTE 6
6 ;^@
1 ;^A
1 ;^B
1 ;^C
1 ;^D
1 ;^E
1 ;^F
7 ;^G
2 ;^H
5 ;^I
4 ;^J
1 ;^K
1 ;^L
3 ;^M
1 ;^N
1 ;^O
1 ;^P
1 ;^Q
1 ;^R
1 ;^S
1 ;^T
1 ;^U
1 ;^V
1 ;^W
1 ;^X
1 ;^Y
1 ;^Z
0 ;ALTMODE, 1 POSITION.
1 ;^^
1 ;[ ;^]
1 ;^\
1 ;^_
.BYTE
;INIT empties the buffer and also tells RUBOUT about
;the characteristics of the output stream used
;for echoing of output during rubout processing.
;If it is a terminal, the capabilities of it are also remembered for use
;in chosing display strategies. If it is not a terminal, or if -1 is
;passed as the channel number, we assume that no echoing of input or rubbed
;out characters is desired.
;INIT takes the output channel in A and the rubout processing block address in B.
;It sets RB.TYP, RB.WID and RB.POS. It also initializes the buffer to be empty.
INIT: PUSHJ P,INITB
;Learn about a new output source, without marking the buffer empty.
INITO: PUSH P,C
PUSH P,D
SYSCAL CNSGET,[A ? MOVEM D ? MOVEM RB.WID(B) ;Read tty width into RB.WID.
REPEAT 3,[ ? MOVEM D]] ;Read TTYOPT of TTY into D.
JRST INIT1 ;Jump if not really a TTY.
SETZ C, ;First assume it's a glass TTY.
TLNN D,%TOMVU
TLNE D,%TOOVR ;If it isn't one, try a printing TTY.
MOVSI C,200000 ;RB.TYP should be positive.
TLNE D,%TOERS
MOVSI C,600000 ;For erasable display, it should be negative.
TLNE D,%TOCID
TLO C,RB%CID ;If we can insert/delete chars, remember that.
MOVEM C,RB.TYP(B)
SYSCAL RCPOS,[A ? MOVEM RB.POS(B)]
.LOSE %LSFIL
POPDCJ: POP P,D
POPCJ: POP P,C
CPOPJ: POPJ P,
INIT1: MOVSI C,200000+RB%FIL
MOVEM C,RB.TYP(B)
JRST POPDCJ
;Set up to do some rubout processing. Takes the Rubout processing block addr in B
;and marks the buffer empty.
INITB: PUSH P,C
MOVE C,RB.BEG(B)
MOVEM C,RB.PTR(B)
JRST POPCJ
IFN $$FCI,[
;Normalize a 9-bit character so we can do comparisons on it.
CHRNRM: ;ANDCMI A,%TXSFT+%TXSFL
TRNE A,%TXCTL+%TXMTA ;Convert lower case controls/metas to upper case,
TRNN A,100
JRST CHRNR1
TRC A,177
TRCN A,177 ;but don't turn Control-Rubout into Control-_.
TRZ A,40
CHRNR1: TRNE A,%TXTOP+%TXCTL+140 ;ASCII control chars must be turned into %TXCTL+char.
POPJ P,
CAIE A,33 ;except for altmode.
ADDI A,%TXCTL+100
POPJ P,
;Convert a 9-bit character in A to ASCII, if necessary for insertion in the buffer
;(that is, if the buffer is 7-bit).
CHRASI: PUSH P,C
LDB C,[300600,,RB.PTR(B)]
CAIE C,7
JRST POPCJ
POP P,C
;Convert a 9-bit character in A to ASCII.
CHRASC: ANDI A,%TXCTL+%TXASC
TRZN A,%TXCTL
POPJ P,
CAIN A,177
POPJ P,
CAIE A,40
CAIL A,140
SUBI A,40
ANDCMI A,100
POPJ P,
];IFN $$FCI
SUBTTL Main rubout processing routine
;The main function of the rubout package is READ.
;It takes the pointer to a rubout processor argument block in B.
;It reads characters and processes them until either a break character
;is read, the buffer becomes full, or an attempt is made to rub out
;past the beginning of the buffer.
;On return, A contains -1 if the buffer is full; -2, in case of
;over-rubout; otherwise, it contains the break character that caused
;the exit. No other accumulator is clobbered.
READ: PUSH P,C
PUSH P,D
RBLOOP: PUSHJ P,INCHR ;Read next character into A.
SKIPLE RB.TYP(B) ;After a CR coming form a file, flush the LF.
CAIE A,^M
JRST RBLOO2
PUSHJ P,INCHR
MOVEI A,^M
RBLOO2:
IFN $$HELP,[
CAIN A,%TXTOP+"H ;If user supplied a HELP routine, call it for Top-H.
JRST [ PUSHJ P,HELP ;Must check for Top-H before the CHRNRM, which makes it H.
JRST RBLOOP]
];IFN $$HELP
IFN $$FCI,PUSHJ P,CHRNRM
PUSHJ P,DISPATCH ;Let user decide what to do with the character.
JRST RBLOO1
JRST POPDCJ ;His routine skips => it wants to exit.
;It should have put the return code in A.
RBLOO1: MOVE C,RB.PTR(B) ;User didn't ask to return,
CAME C,RB.END(B) ;but return anyway if the buffer has become full.
JRST RBLOOP
MOVNI A,1
JRST POPDCJ
IFE $$FCI,[
;Here is the default RB.DSP character dispatch routine which we provide.
RB$DSP: CAIN A,177
JRST RUBOUT
CAIN A,^U
JRST CTLU
CAIN A,^D
JRST CANCEL
CAIN A,^G
JRST QUIT
CAIN A,^M
IFN $$BRKINS, JRST BRKCR
IFE $$BRKINS, JRST BREAK
CAIE A,^_
CAIN A,^C
IFN $$BRKINS, JRST BRKINS
IFE $$BRKINS, JRST BREAK
CAIN A,^Q
JRST QUOTE
CAIN A,^L
JRST REDISP
IFN $$CTLBRK,[
CAIGE A,40
IFN $$BRKINS, JRST BRKINS
IFE $$BRKINS, JRST BREAK
]
JRST INSECH
];IFE $$FCI
IFN $$FCI,[
;Default dispatch for 9-bit characters.
RB$DSP: CAIN A,177
JRST RUBOUT
CAIN A,%TXCTL+"U
JRST CTLU
CAIN A,%TXCTL+"D
JRST CANCEL
CAIN A,%TXCTL+"G
JRST QUIT
CAIN A,%TXCTL+"M
IFN $$BRKINS, JRST BRKCR
IFE $$BRKINS, JRST BREAK
CAIE A,%TXCTL+"_
CAIN A,%TXCTL+"C
IFN $$BRKINS, JRST BRKINS
IFE $$BRKINS, JRST BREAK
CAIN A,%TXCTL+"Q
JRST QUOTE
CAIN A,%TXCTL+"L
JRST REDISP
IFN $$CTLBRK,[
TRNE A,%TXCTL+%TXMTA
IFN $$BRKINS, JRST BRKINS
IFE $$BRKINS, JRST BREAK
]
JRST INSECH
];IFN $$FCI
SUBTTL Various action routines for input characters.
;Dispatch here for a character that quotes the next one (eg, ^Q).
;The quoting character goes in the buffer so that it can quote
;the next character at the next level of parsing.
QUOTE:
IFE $$CTLECH,PUSHJ P,OUTECH
IFN $$FCI,PUSHJ P,CHRASI
IDPB A,RB.PTR(B) ;Store the ^Q.
PUSHJ P,INCHR ;Read the quoted character.
;Insert a character, echoing it if it was a non-echoed control-character.
INSECH: CAIE A,177
IFN $$CTLECH,CAIA
.ELSE [
IFN $$FCI, TRNE A,%TXCTL
.ELSE CAIGE A,40
]
PUSHJ P,OUTECH
JRST INSERT
;Insert char followed by a LF. For CR, when it isn't a break.
INSCR: MOVEI A,^M
IDPB A,RB.PTR(B)
MOVEI A,^J
MOVE C,RB.END(B) ;Note that the buffer may become full
CAMN C,RB.PTR(B) ;after just the CR.
JRST [ MOVEI B,1
AOS (P)
POPJ P,]
;Dispatch here for an ordinary character, that should just be inserted,
;and has already been echoed.
INSERT:
IFN $$FCI,PUSHJ P,CHRASI ;If char is 9-bit and buffer is 7-bit, convert.
IDPB A,RB.PTR(B)
POPJ P,
;Insert char and a LF, then break.
BRKCR: PUSH P,A
MOVEI A,^M
IDPB A,RB.PTR(B)
MOVEI A,^J
IDPB A,RB.PTR(B)
POP P,A
JRST BREAK
;Dispatch here for a break character. We store it and a null,
;then signal READ to return the break character.
;If the character is a control char which didn't echo, we echo it.
BRKINS: PUSH P,A
PUSHJ P,INSECH ;Insert, maybe echoing or converting 9-bit to 7-bit.
POP P,A
;Dispatch here for a break character that should not be stored
;in the buffer.
BREAK: SETZ C, ;Store a 0 to make it ASCIZ,
MOVE D,RB.PTR(B) ;but don't make RB.PTR point after it.
IDPB C,D
AOS (P)
POPJ P,
;Here to "quit". Acts like too many rubouts, flushing any amount of input.
QUIT: MOVE C,RB.BEG(B) ;Mark the buffer empty.
MOVEM C,RB.PTR(B)
SETZM RB.PRS(B) ;Tell user his old parsing work is no use.
MOVNI A,2 ;Make READ return -2.
AOS (P)
POPJ P,
;Empty the entire buffer. The same as exactly enough rubouts
;but types out differently.
CANCEL: SETZM RB.PRS(B) ;Tell user his old parsing is no longer any use.
SKIPGE D,RB.TYP(B) ;On a display, clear the display window first,
JRST CANCE1 ;while we can still tell how long it is.
MOVE C,RB.BEG(B) ;Empty the buffer.
MOVEM C,RB.PTR(B)
TLNE D,RB%FIL
POPJ P, ;If reading from file, don't type anything.
MOVEI A,40 ;Printing terminal, type "XXX?" and CRLF.
PUSHJ P,OUTCHR
MOVEI A,"X
PUSHJ P,OUTCHR
PUSHJ P,OUTCHR
PUSHJ P,OUTCHR
MOVEI A,"?
PUSHJ P,OUTCHR
JRST WCLEAR ;CRLF, and prompt if appropriate.
CANCE1: PUSHJ P,WCLEAR ;Clear out the display window.
MOVE C,RB.BEG(B) ;Empty the buffer.
MOVEM C,RB.PTR(B)
POPJ P,
CTLU:
IFN $$CTLECH,PUSHJ P,IGNORE ; If the ^U echoed, must erase it too.
;Delete one line backwards. Deletes at least one character.
CLRLIN: PUSHJ P,RUBOUT ; DELETE AT LEAST ONE CHAR, STOPPING ONLY AT LINE BEG.
CAIA
JRST POPJ1 ; Beginning of buffer => propagate the skip.
MOVE C,RB.PTR(B)
CAMN C,RB.BEG(B) ; Else stop rubbing if now at start of line.
POPJ P,
LDB A,C
CAIE A,^J
JRST CLRLIN
POPJ P,
;Dispatch here to ignore a character. On a display, erase it if it echoed.
IGNORE:
IFE $$CTLECH,[
IFE $$FCI,CAIGE A,40
IFN $$FCI,TRNE A,%TXCTL
POPJ P,
]
SKIPL RB.TYP(B)
POPJ P,
JRST RUBOU1
SUBTTL Various display operations
;Here to retype the entire contents of the buffer.
REDISP:
IFN $$FFCLR,IFN $$PROMPT, PUSHJ P,PROMPT ;If ^L clears the screen, just re-prompt.
IFE $$FFCLR,PUSHJ P,WCLEAR ;Else, erase all the lines that are in use
;and put cursor after the previous prompt.
MOVE C,RB.BEG(B)
REDIS1: CAMN C,RB.PTR(B)
POPJ P,
ILDB A,C
PUSHJ P,OUTECH
JRST REDIS1
;Clear the display window. On printing terminal, just CRLF and prompt.
WCLEAR: SKIPL RB.TYP(B)
JRST [ PUSHJ P,CRLF
IFN $$PROMPT, PUSHJ P,PROMPT
POPJ P,]
;Here for clearing buffer on a display.
IFN $$MULTI,[
PUSHJ P,RESYNCH ;Compute vpos,,hpos of end of buffer in D.
PUSH P,D
PUSHJ P,CRSHOME ;Move cursor to beginning of rubout processor area.
MOVEI A,"L
PUSHJ P,DISP2 ;Clear rest of that line.
HLRZS (P)
POP P,D ;Then CRLF down thru the lines that were occupied.
HLRZ C,RB.POS(B)
CAMN C,D
POPJ P,
WCLEA1: CAMN C,D
JRST CRSHOM ;Then move cursor to beginning of area again.
MOVEI A,"D
PUSHJ P,DISP2 ;Move down one line
MOVEI A,"L
PUSHJ P,DISP2 ;and clear the one we get to.
AOJA C,WCLEA1
];IFN $$MULTI
.ELSE [
PUSHJ P,CRSHOME ;Move cursor to beginning of rubout processor area.
MOVEI A,"L
JRST DISP2 ;Clear rest of that line.
];IFN $$MULTI
;On a display only, move the cursor to the beginning of the window area.
CRSHOM: MOVEI A,"V
PUSHJ P,DISP2
HLRZ A,RB.POS(B)
ADDI A,10
PUSHJ P,DISPLAY
MOVEI A,"H
PUSHJ P,DISP2
HRRZ A,RB.POS(B)
ADDI A,10
PUSHJ P,DISPLAY
POPJ P,
;Output a ^P followed by the character in A, using DISPLAY supplied by user.
DISP2:
PUSH P,A
MOVEI A,^P
PUSHJ P,DISPLAY
POP P,A
PUSHJ P,DISPLAY
POPJ P,
;Output the character in A as it should be echoed, preserving A.
OUTECH: PUSH P,A
PUSHJ P,OUTEC1
POP P,A
POPJ P,
OUTEC1: CAIGE A,177
JRST OUTPUT
IFN $$FCI,PUSHJ P,CHRASC
CAIN A,177
JRST OUTRUB
CAIN A,^M
JRST CRLF
JRST OUTPUT
OUTRUB: MOVEI A,"^
PUSHJ P,OUTPUT
MOVEI A,"?
JRST OUTPUT
;Type a CRLF via the output 1 character instruction.
CRLF: MOVEI A,^M
PUSHJ P,OUTCHR
MOVEI A,^J
PUSHJ P,OUTCHR
POPJ P,
SUBTTL The operation of rubbing out one character
;This is the character action routine for Rubout, which we assume
;was not echoed.
RUBOUT: PUSHJ P,DBPPTR ;Back up RB.PTR one byte.
JRST QUIT ;It was at beginning => return -2 ("overrrubout") from READ.
MOVE A,C
ILDB A,A ;What character are we rubbing out?
LDB D,C
CAIN A,^J ;If rubbing out a ^J which follows a ^M,
CAIE D,^M
JRST RUBOU3
CAMN C,RB.BEG(B)
JRST RUBOU3
SKIPG RB.TYP(B) ;Rub out the ^M too.
JRST RUBOU4 ;On display, just call rubout again after this call is done.
PUSHJ P,DBPPTR ;On printing TTY, type a CRLF and flush both characters.
JRST CRLF
RUBOU4: PUSH P,[RUBOUT]
RUBOU3: SKIPLE RB.TYP(B) ;Printing terminal?
OUTPUT: JRST OUTCHR ;on printing terminal, just echo the character.
;Here to rub the character in A out on a display screen.
RUBOU1: PUSHJ P,CHRTYP
XCT RUBTAB(A)
RUBOU2: MOVEI A,"X
JRST DISP2
RUBTAB: JFCL ;Normal character; fall through to RUBOU2 and send ^PX.
JRST RUBCTL ;Control char may be one position or two.
JRST RUBBS ;Backspace rubs out by moving forward.
JRST RUBCR ;CR rubs out requiring redisplay.
JRST RUBLF ;LF is simple, but maybe also rub preceding CR
JRST RUBHT ;Tab is hard to rub out.
PUSHJ P,RUBOU2 ;Rubout and ^@ take two positions always.
JRST OUTPUT ;^G takes no positions; echo it to rub it out.
RUBCTL: MOVSI D,RB%SAI ;Control chars are one pos or two according to sail mode.
TDNN D,RB.TYP(B)
PUSHJ P,RUBOU2
JRST RUBOU2
RUBBS: RUBCR: RUBHT:
IFN $$MULTI,[
PUSHJ P,RESYNCH ;Compute current vpos,,hpos in D.
MOVEI A,"H
PUSHJ P,DISP2 ;Move cursor to that position.
MOVEI A,10(D)
PUSHJ P,DISPLAY
POPJ P,
]
.ELSE JRST REDISP
RUBLF: MOVEI A,"U ;Rubbing out LF: move up one line.
JRST DISP2
;Decrement RB.PTR by one byte, updating RB.PRS as necessary.
;Skips unless RB.PTR was pointing at the beginning of the buffer,
;in which case it was not changed. RB.PTR is left in C, either way.
DBPPTR: MOVE C,RB.PTR(B)
CAMN C,RB.BEG(B)
POPJ P,
CAMN C,RB.PRS(B)
SETZM RB.PRS(B)
PUSHJ P,DBPC
MOVEM C,RB.PTR(B)
POPJ1: AOS (P)
POPJ P,
;Decrement the byte pointer in C. If $$FCI, we handle 7-bit and 9-bit byte pointers.
;Otherwise, we handle only 7-bit byte pointers.
DBPC:
IFN $$FCI,[
LDB D,[300600,,C]
CAIE D,7
JRST DBP9
]
ADD C,[070000,,]
SKIPGE C
SUB C,[430000,,1] ;Decrement byte pointer.
POPJ P,
IFN $$FCI,[
DBP9: ADD C,[110000,,]
SKIPGE C
SUB C,[440000,,1]
POPJ P,
]
IFN $$MULTI,[
;Compute current Vpos,,hpos at RB.PTR and return it in D,
;by assuming that RB.POS is valid for beginning of buffer
;and scanning through the buffer, seeing what the characters do to the cursor.
;Clobbers A and C.
RESYNCH:
HRRZI C,1(P) ;C points to 3-word block on stack.
MOVE D,RB.BEG(B) ;(C) holds b.p. to scan with.
PUSH P,D
HRRZ D,RB.POS(B) ;1(C) holds HPOS.
PUSH P,D
HLRZ D,RB.POS(B) ;2(C) holds VPOS.
PUSH P,D
RBCRS1: MOVE D,(C)
CAMN D,RB.PTR(B) ;Scan till reach end of occupied region.
JRST RBCRS2
PUSHJ P,RBFORW
JRST RBCRS1
RBCRS2: HRRZ D,1(C) ;D gets the new Vpos,,Hpos.
HRL D,2(C) ;Flush the block of temporary variables.
SUB P,[3,,3]
POPJ P,
;Cursor position calculating routines.
;Move pointer in (C) one character forward, adjusting VPOS in 2(C)
;and HPOS in 1(C) for the character moved over.
RBFORW: ILDB A,(C)
PUSHJ P,CHRTYP ;Get the character's "type code".
XCT RRFORT(A) ;DISPATCH ON TYPE OF CHAR.
RRFOR1: AOS A,1(C)
RRFOR3: CAMGE A,RB.WID(B) ;HAVE WE MOVED PAST RIGHT MARGIN?
POPJ P,
CAMN A,RB.WID(B) ;CHECK FOR JUST REACHING THE RIGHT MARGIN.
JRST RRCNTN
RRCNT1: SUB A,RB.WID(B)
MOVEM A,1(C)
RRFORV: AOS 2(C)
POPJ P,
RRCNTN: MOVE D,(C)
ILDB D,D
CAIN D,^M
POPJ P,
JRST RRCNT1
RRFORT: AOSA A,1(C) ;ORDINARY CHAR, MOVE FWD 1 POS.
JRST RRFORC ;NON-FORMATTING CONTROLS.
JRST RRFORH ;MOVE FWD OVER ^H - CHECK ^HPRINT FLAG.
JRST RRFWCR ;^M, SPECIAL.
JRST RRFORL ;^J, DOWN 1 LINE.
JRST RRFOTB ;^I
JRST RRFOR2 ;2-POS CTL CHRS NOT AFFECTED BY FS SAIL (Rubout and ^@)
POPJ P, ;^G takes up no space.
RRFOTB: MOVE D,1(C)
MOVEI A,10(D)
ANDCMI A,7 ;A HAS NEXT TAB STOP'S POSITION.
CAMLE A,RB.WID(B) ;BUT IF THAT'S OFF THE SCREEN, TAB STOP IS RIGHT MARGIN,
CAMN D,RB.WID(B) ;UNLESS WE'RE ALREADY AT THE MARGIN, IN WHICH CASE
CAIA ;WE CAN TAB 8 SPACES INTO NEXT LINE VIA CONTINUATION.
MOVE A,RB.WID(B)
MOVEM A,1(C)
JRST RRFOR3
RRFORL: AOS 2(C)
POPJ P,
RRFWCR: SETZM 1(C)
POPJ P,
RRFORH: SKIPN 1(C)
JRST RRFOR2
SOS 1(C)
POPJ P,
;NON-FORMATTING CONTROLS, CHECK FS SAIL FLAG.
RRFORC: MOVE D,RB.TYP(B)
TLNN D,RB%SAI ;SAIL mode => it is a one-position character.
RRFOR2: AOS 1(C) ;Else treat as 2-pos ctl char.
JRST RRFOR1
] ;IFN $$MULTI
.END RUBOUT