perm filename DISPLY.FAI[S,NET]4 blob sn#845899 filedate 1987-09-11 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00025 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00005 00002	 SUBTTL Display routines, intended to be .INSERTed  history NLINES LINEL DMBUFL NCHARS NWRDLN SCRSIZ NGW DISLIN DMLIN DDDLIN TRUNCA NOEEOL NOEEOB
C00008 00003	 Data area  DPCBEG DDP IIIP DMP HSIZE VSIZE ROLLP VPOS HPOS OVPOS SLUPDP SCUPDP SAUPDP CRUPDP SCRLCT DMCNT DMPNT DPCEND
C00010 00004	 Display commands and programs  IIIHDR SDISP SCP SCREEN SCREND SCPL BOTLIN CDISP SCC SCCL LDISP LNP DMDISP DMPGM
C00012 00005	 DPYINI -- Initialize display package  DPYINI NOTIII
C00014 00006	 CLRSCN -- Clear display screen (does explicit update as well)  CLRSCN SCRIN1 DMCEOF
C00016 00007	 SCSTOR -- Store a character at the current screen V/H position  SCSTOR SCSTO2 SCBYTP
C00018 00008	 CLREOL -- Clear to end of line  CLREOL CLEOL0 CLEOL1
C00019 00009	 CLREOF -- Clear to end of screen  CLREOF CLEOF1
C00020 00010	 CLR1CH -- Delete a character at the cursor  CLR1CH CLR1C0
C00021 00011	 CSRPOS -- position cursor  CSRPOS
C00022 00012	 TERPRI -- CR, LF, CLEOL, scroll if necessary  TERPRI
C00023 00013	 CARRET -- CR  CARRET
C00024 00014	 LINEFD -- LF, CLEOL, scroll if necessary  LINEFD LINFD1
C00025 00015	 LINSRV -- Line starve  LINSRV LINSR1
C00026 00016	 CSRTAB -- Tab cursor  CSRTAB CSRTA0
C00027 00017	 CSRAOS -- Forespace cursor  CSRAOS CSRAO0
C00028 00018	 CSRSOS -- Backspace cursor  CSRSOS CSRSO0
C00029 00019	 INSLIN -- Insert a blank line  INSLIN INSLN0 INSL1A INSLN1 INSLN2
C00031 00020	 DELLIN -- Delete a blank line  DELLIN DELLN0 DELL1A DELLN1
C00033 00021	 INSCHR -- Insert a blank character  INSCHR INSCH0 INSC1A INSCH2 INSCH1
C00036 00022	 DELCHR -- Delete a character  DELCHR DELCH0 DELC1A DELCH2 DELCH1
C00039 00023	 SCNUPD -- Update screen  SCNUPD CSRUPD SCUPD1 SCUP1A SCUPD2
C00042 00024	 GETCSY UDPLIN redisplay subroutines  GETCSY UPDLIN
C00044 00025	 DMCHAR DMOUT Datamedia output routines  DMCHAR DMOUT
C00046 ENDMK
C⊗;
 SUBTTL Display routines, intended to be .INSERTed ;⊗ history NLINES LINEL DMBUFL NCHARS NWRDLN SCRSIZ NGW DISLIN DMLIN DDDLIN TRUNCA NOEEOL NOEEOB

;This is a library of display hacking routines.  Each routine documents its
;calling sequence and what AC's it smashes.  Only AC's 0-6 are used.  A
;pushdown stack is expected in 17.

;Original implementation by Mark Crispin, SU-AI, July 1978

COMMENT ⊗  History (please record changes):

26 Feb 84  JJW	Conversion from MIDAS to FAIL.
28 May 86  ME	Put in tests for HPOS overflowing buffers, to avoid clobbering
		things outside SCREEN array with characters.  Also, SCSTOR
		fixed to wrap around automatically (with CR and LF) if attempt
		to store character beyond right margin (HSIZE).
11 Sep 87  JJW	Changed CAMGE 2,HSIZE to CAMG at SCSTOR+1 since HSIZE is one
		less than the number of columns.

history:  end of comment ⊗ 

	BEGIN DISPLY

; Useful definitions

NLINES←←=40				; lines in screen matrix
LINEL←←=88				; true maximum number of characters/line
DMBUFL←←=100				; size of DM buffer
NCHARS←←<<<LINEL+5>/5>*5>		; characters/line in line array
NWRDLN←←4+NCHARS/5			; number of words in line array
SCRSIZ←←NLINES*NWRDLN			; number of words in screen matrix
NGW←←<<NCHARS*3>+=17>/=16		; number of graphics words

; Line characteristics bits

DISLIN←←<400000,,0>			; III
DMLIN←← <040000,,0>			; DM
DDDLIN←←<020000,,0>			; DD

; DM UPGIOT flags

TRUNCA←←<040000,,0>			; truncate output lines to =80 characters
NOEEOL←←<020000,,0>			; suppress CEOL when moving to a line
NOEEOB←←<010000,,0>			; suppress CEOL on blank line

; Generate a Data Disc/III command

DEFINE DDCMD(O1,D1,O2,D2,O3,D3)<
 BYTE (8)D1,D2,D3(3)O1,O2,O3,4
>;DEFINE

; Insert a command in a DM display program

DEFINE DMCMD(CH)<
 MOVE DMCNT
 CAIGE 10
  PUSHJ 17,DMOUT
 MOVEI 177
 PUSHJ 17,DMCHAR
 MOVEI CH
 PUSHJ 17,DMCHAR
>;DEFINE
; Data area ;⊗ DPCBEG DDP IIIP DMP HSIZE VSIZE ROLLP VPOS HPOS OVPOS SLUPDP SCUPDP SAUPDP CRUPDP SCRLCT DMCNT DMPNT DPCEND

↑DPCBEG←←.				; beginning of core area zeroed at DPYINI

; Terminal characteristics

DDP:	BLOCK 1				; -1 → Data Disc
IIIP:	BLOCK 1				; -1 → III
DMP:	BLOCK 1				; -1 → Datamedia
↑HSIZE:	BLOCK 1				; horizontal size
↑VSIZE:	BLOCK 1				; vertical size
↑ROLLP:	BLOCK 1				; -1 → scrolling permission

; Cursor position pointers

VPOS:	BLOCK 1				; vertical position
HPOS:	BLOCK 1				; horizontal position
OVPOS:	BLOCK 1				; old vertical position

; Screen updating flags

SLUPDP:	BLOCK NLINES			; -1 → this line has changed
SCUPDP:	BLOCK 1				; -1 → some update happened someplace
SAUPDP:	BLOCK 1				; -1 → updated whole screen
CRUPDP:	BLOCK 1				; -1 → updated cursor
SCRLCT:	BLOCK 1				; for forcing update in LINEFD scrolling

; DM display fields

DMCNT:	BLOCK 1				; DM program counter
DMPNT:	BLOCK 1				; DM program counter

DPCEND←←.-1				; end of core data
; Display commands and programs ;⊗ IIIHDR SDISP SCP SCREEN SCREND SCPL BOTLIN CDISP SCC SCCL LDISP LNP DMDISP DMPGM

IIIHDR:	BYTE (11)<-777>,640(3)4,2(2)1,2(4)6

SDISP:	600000,,SCP ↔ SCPL ↔ 0 ↔ SCP	; display screen
SCP:	DDCMD 1,46,4,1,5,10
	DDCMD 3,2,3,2,3,2
SCREEN:	BLOCK SCRSIZ
SCREND←.-1
	0
SCPL←←.-SCP
BOTLIN←←SCREEN+SCRSIZ-NWRDLN+2-1

CDISP:	SCC ↔ SCCL ↔ 0 ↔ SCC+1		; display cursor
SCC:	DDCMD 1,7,1,7,1,7
	DDCMD 3,1,4,0,5,0
	BLOCK NGW
	DDCMD 0,0,1,46,1,46
	0
SCCL←←.-SCC

LDISP:	200000,,LNP ↔ NWRDLN ↔ 0 ↔ LNP	; display line
LNP:	DDCMD 1,46,4,0,5,0
	DDCMD 3,2,3,2,3,2
	BLOCK NWRDLN-3
	0

DMDISP:	TRUNCA!NOEEOL!NOEEOB+DMPGM ↔ 0 ↔ 0; DM display program
DMPGM:	BLOCK DMBUFL
; DPYINI -- Initialize display package ;⊗ DPYINI NOTIII
; Call:	PUSHJ 17,DPYINI
;	<return>
; Smashes 0.

↑DPYRDW:SETOM SAUPDP		;force text to be redrawn
	SETOM CRUPDP		;force cursor to be redrawn
	PPACT
	LEYPOS 2000			; flush page printer and line editor
	POPJ 17,

↑DPYINI:SETZM DPCBEG
	MOVE [DPCBEG,,DPCBEG+1]
	BLT DPCEND			; initialize data area
	HRROI [3000,,]			; real line chars
	TTYSET				; get my line characteristics
	TLNN (DISLIN!DDDLIN!DMLIN)	; display
	 JRST [	OUTSTR [ASCIZ/Not a display!/]
		EXIT]
	TLNE (DISLIN)
	 SETOM IIIP
	TLNE (DDDLIN)
	 SETOM DDP
	TLNE (DMLIN)
	 SETOM DMP
	MOVE [-2,,[6000,,HSIZE ↔ 15000,,VSIZE]]
	TTYSET				; get screen size information
	MOVNI 2 ↔ ADDM VSIZE
	SOS HSIZE
	PPACT
	LEYPOS 2000			; flush page printer and line editor
	MOVE VSIZE
	MOVEM SCRLCT
	SETOM ROLLP			; grant scrolling permission
	SKIPN IIIP
	 JRST NOTIII
	SETZM SCP			; different header for III's
	MOVE IIIHDR
	MOVEM SCP+1
NOTIII:	SETOM OVPOS
	SKIPN DMP
	 POPJ 17,
	MOVEI <5*DMBUFL>-4
	MOVEM DMCNT			; initialize DM counter
	MOVE [440700,,DMPGM]
	MOVEM DMPNT			; initialize DM pointer
	POPJ 17,
; CLRSCN -- Clear display screen (does explicit update as well) ;⊗ CLRSCN SCRIN1 DMCEOF
; Call:	PUSHJ 17,CLRSCN
;	<return>
; Smashes 0, 1, 2, and 3.

↑CLRSCN:SETZM VPOS
	SETZM HPOS
	MOVE [<ASCII/     />+1]
	MOVEM SCREEN
	MOVE [SCREEN,,SCREEN+1]
	BLT SCREND			; initialize screen to spaces
	MOVE [<ASCII/
/>+1]					; terpri
	SETZ 1,				; line address
	DMOVE 2,[1 ↔ NLINES]		; blank word/line counter
SCRIN1:	MOVEM 2,SCREEN(1)
	MOVEM 2,SCREEN+1(1)
	MOVEM SCREEN+NWRDLN-2(1)
	MOVEM 2,SCREEN+NWRDLN-1(1)
	ADDI 1,NWRDLN
	SETZM SLUPDP-1(3)		; clear update necessary state for line
	SOJG 3,SCRIN1
	MOVEI 2
	MOVEM SCC+2
	MOVE [SCC+2,,SCC+3]
	BLT SCC+2+NGW-1			; initialize graphics words
	SETOM SAUPDP			; updated entire screen
	PUSHJ 17,SCNUPD
	SKIPN DMP
	 POPJ 17,

	DMCMD 14			; cursor ← [0,2]
	MOVEI 140
	PUSHJ 17,DMCHAR
	MOVEI 142
	PUSHJ 17,DMCHAR
	MOVE 1,VSIZE
DMCEOF:	DMCMD 27			; clear current line
	DMCMD 15			; move to next line
	SOJG 1,DMCEOF
	DMCMD 14			; cursor ← [0,2]
	MOVEI 140
	PUSHJ 17,DMCHAR
	MOVEI 142
	PUSHJ 17,DMCHAR
	JRST DMOUT
; SCSTOR -- Store a character at the current screen V/H position ;⊗ SCSTOR SCSTO2 SCBYTP
; Call:	MOVE <character>
;	PUSHJ 17,SCSTOR
;	<return>
; Smashes 0, 1, 2, and 3.

↑SCSTOR:MOVE 2,HPOS
	CAMG 2,HSIZE
	JRST SCSTO2
	PUSH 17,0		; save char to be stored
	PUSHJ 17,CARRET		; wrap around with CR
	PUSHJ 17,LINEFD		; and LF
	POP 17,0
	MOVE 2,HPOS		; get new position
SCSTO2:	MOVE 1,VPOS
	SETOM SLUPDP(1)		; updated flags
	SETOM SCUPDP
	IMULI 1,NWRDLN
	IDIVI 2,5		; word position in line
	ADDI 1,SCREEN+2(2)	; offset by lines previous
	DPB 0,SCBYTP(3)		; save character on screen
	AOS HPOS
	SKIPE DMP
	 JRST DMCHAR
	POPJ 17,

; Byte pointer table for insertions

SCBYTP:	350700,,(1)
	260700,,(1)
	170700,,(1)
	100700,,(1)
	010700,,(1)
; CLREOL -- Clear to end of line ;⊗ CLREOL CLEOL0 CLEOL1
; Call:	PUSHJ 17,CLREOL
;	<return>
; Smashes 0, 1, 2, 3, and 4.

↑CLREOL:SKIPN DMP
	 JRST CLEOL0
	DMCMD 27			; clear to end of line
CLEOL0:	MOVE 4,HPOS
	CAIL 4,LINEL
	 POPJ 17,
	MOVE 1,VPOS
	SETOM SLUPDP(1)			; flag this line changed
	SETOM SCUPDP
	IMULI 1,NWRDLN
	MOVE 2,HPOS
	IDIVI 2,5
	ADDI 1,SCREEN+2(2)		; address of word to hack
	MOVE 2,SCBYTP(3)
	MOVEI " "
	DPB 2				; clear character
CLEOL1:	ADDI 4,1			; next character position
	CAIL 4,LINEL
	 POPJ 17,
	IDPB 2
	JRST CLEOL1
; CLREOF -- Clear to end of screen ;⊗ CLREOF CLEOF1
; Call:	PUSHJ 17,CLREOF
;	<return>
; Smashes 0, 1, 2, 3, and 4.

↑CLREOF:PUSH 17,HPOS
	PUSH 17,VPOS
CLEOF1:	PUSHJ 17,CLREOL			; clear to end of line
	DMCMD 15			; next line
	SETZM HPOS
	AOS 1,VPOS
	CAIGE 1,NLINES
	 JRST CLEOF1
	POP 17,VPOS
	POP 17,HPOS
	DMCMD 14			; cursor ← [0,2]
	MOVEI 140
	PUSHJ 17,DMCHAR
	MOVEI 142
	PUSHJ 17,DMCHAR
	POPJ 17,
; CLR1CH -- Delete a character at the cursor ;⊗ CLR1CH CLR1C0
; Call:	PUSHJ 17,CLR1CH
;	<return>
; Smashes 0, 1, 2, and 3.

↑CLR1CH:SKIPN DMP
	 JRST CLR1C0
	DMCMD " "			; space then backspace
	DMCMD 10
CLR1C0:	MOVEI " "			; store space at cursor
	MOVE 1,VPOS
	SETOM SLUPDP(1)
	SETOM SCUPDP
	IMULI 1,NWRDLN
	MOVE 2,HPOS
	CAIL 2,LINEL			; within valid range?
	POPJ 17,			; no
	IDIVI 2,5
	ADDI 1,SCREEN+2(2)
	DPB SCBYTP(3)
	POPJ 17,
; CSRPOS -- position cursor ;⊗ CSRPOS
; Call:	MOVE [xpos,,ypos]
;	PUSHJ 17,CSRPOS
;	<return>
; Smashes 0.

↑CSRPOS:HLRZM HPOS
	HRRZM VPOS
	SETOM CRUPDP
	SKIPN DMP
	 POPJ 17,
	DMCMD 14
	MOVE HPOS
	XORI 140
	PUSHJ 17,DMCHAR
	MOVE VPOS
	ADDI 2
	XORI 140
	JRST DMCHAR
; TERPRI -- CR, LF, CLEOL, scroll if necessary ;⊗ TERPRI
; Call:	PUSHJ 17,TERPRI
;	<return>
; Smashes 0, 1, 2, 3, and 4.

↑TERPRI:PUSHJ 17,CARRET
	PUSHJ 17,LINEFD
	JRST CLREOL
; CARRET -- CR ;⊗ CARRET
; Call:	PUSHJ 17,CARRET
;	<return>
; Smashes 0.

↑CARRET:MOVE VPOS			; move to [0,current y]
	JRST CSRPOS
; LINEFD -- LF, CLEOL, scroll if necessary ;⊗ LINEFD LINFD1
; Call:	PUSHJ 17,CARRET
;	<return>
; Smashes 0, 1, 2, 3, and 4.

↑LINEFD:AOS 1,VPOS			; and to next line
	CAMGE 1,VSIZE
	 JRST LINFD1
	SKIPN ROLLP
	 JRST [	SETZM VPOS ↔ JRST LINFD1]
	MOVE [SCREEN+NWRDLN,,SCREEN]
	BLT SCREEN+SCRSIZ-NWRDLN-1
	MOVE [<ASCII/     />+1]
	MOVEM BOTLIN+1
	MOVE [BOTLIN+1,,BOTLIN+2]
	BLT BOTLIN+<NCHARS/5>
	SETOM SAUPDP
	MOVE VSIZE ↔ SOS ↔ MOVEM VPOS
	SOSG SCRLCT
	 PUSHJ 17,SCNUPD		; update after a screenfull of scrolling
LINFD1:	SETOM CRUPDP
	POPJ 17,
; LINSRV -- Line starve ;⊗ LINSRV LINSR1
; Call:	PUSHJ 17,LINSRV
;	<return>
; Smashes 0.

↑LINSRV:SKIPN DMP
	 JRST LINSR1
	DMCMD 32
LINSR1:	SOSGE VPOS
	 SETZM VPOS
	SETOM CRUPDP
	POPJ 17,
; CSRTAB -- Tab cursor ;⊗ CSRTAB CSRTA0
; Call:	PUSHJ 17,CSRTAB
;	<return>
; Smashes 0.

↑CSRTAB:SKIPE DMP
	 JRST CSRTA0
	DMCMD 11			; tab
CSRTA0:	MOVE HPOS
	TRZ 7
	ADDI 10
	MOVEM HPOS
	SETOM CRUPDP			; cursor updated
	POPJ 17,
; CSRAOS -- Forespace cursor ;⊗ CSRAOS CSRAO0
; Call:	PUSHJ 17,CSRAOS
;	<return>
; Smashes 0.

↑CSRAOS:SKIPE DMP
	 JRST CSRAO0
	DMCMD 34			; forespace
CSRAO0:	AOS HPOS
	SETOM CRUPDP			; cursor updated
	POPJ 17,
; CSRSOS -- Backspace cursor ;⊗ CSRSOS CSRSO0
; Call:	PUSHJ 17,CSRSOS
;	<return>
; Smashes 0.

↑CSRSOS:SKIPE DMP
	 JRST CSRSO0
	DMCMD 10			; backspace
CSRSO0:	SOSGE HPOS
	 SETZM HPOS
	SETOM CRUPDP			; cursor updated
	POPJ 17,
; INSLIN -- Insert a blank line ;⊗ INSLIN INSLN0 INSL1A INSLN1 INSLN2
; Call:	MOVE <number of lines to insert>
;	PUSHJ 17,INSLIN
;	<return>
; Smashes 0, 1, 2, and 3.

↑INSLIN:PUSH 17,				; save argument
	SKIPN DMP
	 JRST INSLN0
	DMCMD 20			; enter i/d mode on DM
INSLN0:	SKIPN DMP
	 JRST INSL1A
	DMCMD 12			; insert a line on DM
INSL1A:	MOVE 3,VPOS
	IMULI 3,NWRDLN
	ADDI 3,SCREEN			; address of first word of cursor line
	CAIN 3,SCREEN+<NLINES-1>*NWRDLN	; skip unless at bottom line
	 JRST INSLN2
	MOVE 1,[SCREEN+<NLINES-2>*NWRDLN,,SCREEN+<NLINES-1>*NWRDLN]
INSLN1:	MOVE 2,1
	BLT 2,NWRDLN-1(1)		; move line down
	ADJSP 1,-NWRDLN
	CAIE 3,(1)
	 JRST INSLN1
INSLN2:	MOVE 1,[<ASCII/     />+1]
	MOVEM 1,2(3)
	MOVEI 1,NWRDLN-3(3)
	ADDI 3,3
	HRLI 3,-1(3)
	BLT 3,(1)
	SOSLE (17)
	 JRST INSLN0
	ADJSP 17,-1			; flush argument
	SETOM SAUPDP
	SKIPN DMP
	 POPJ 17,
	DMCMD 30			; leave i/d mode on DM
	POPJ 17,
; DELLIN -- Delete a blank line ;⊗ DELLIN DELLN0 DELL1A DELLN1
; Call:	MOVE <number of lines to delete>
;	PUSHJ 17,DELLIN
;	<return>
; Smashes 0, 1, 2, and 3.

↑DELLIN:PUSH 17,			; save argument
	SKIPN DMP
	 JRST DELLN0
	DMCMD 20			; enter i/d mode on DM
DELLN0:	SKIPN DMP
	 JRST DELL1A
	DMCMD 32			; delete a line on DM
DELL1A:	MOVE 3,VPOS
	IMULI 3,NWRDLN
	ADDI 3,SCREEN			; address of first word of cursor line
	CAIN 3,SCREEN+<NLINES-1>*NWRDLN	; skip unless at bottom line?
	 JRST DELLN1
	MOVEI 1,(3)
	ADDI 1,NWRDLN
	HRLI 3,(1)
	BLT 3,SCREEN+<NLINES-1>*NWRDLN-1; move the lines up
DELLN1:	MOVE 1,[<ASCII/     />+1]
	MOVEM 1,2(3)
	MOVEI 1,NWRDLN-3(3)
	ADDI 3,3
	HRLI 3,-1(3)
	BLT 3,(1)
	SOSLE (17)
	 JRST DELLN0
	ADJSP 17,-1			; flush argument
	SETOM SAUPDP
	SKIPN DMP
	 POPJ 17,
	DMCMD 30			; leave i/d mode on DM
	POPJ 17,
; INSCHR -- Insert a blank character ;⊗ INSCHR INSCH0 INSC1A INSCH2 INSCH1
; Call:	MOVE <number of spaces to insert>
;	PUSHJ 17,INSCHR
;	<return>
; Smashes 0, 1, 2, 3, 4, 5, and 6.

↑INSCHR:PUSH 17,			; save count
	SKIPN DMP			; is this a DM?
	 JRST INSCH0
	DMCMD 20			; yes, enter i/d mode
INSCH0: SKIPN DMP			; on a DM?
	 JRST INSC1A
	DMCMD 34			; insert a character
INSC1A:	MOVE 1,VPOS			; get vertical position
	IMULI 1,NWRDLN			; now number of words
	MOVE 4,1			; copy it for hacking
	ADDI 4,SCREEN+NWRDLN-3		; address of last text word
	MOVE 2,HPOS			; get horizontal position
	CAIL 2,LINEL			; within valid range?
	JRST [	ADJSP 17,-1		; no
		POPJ 17,]
	IDIVI 2,5			; make it words
	ADDI 1,SCREEN+2(2)		; address of word with cursor
	LDB 2,[010700,,(1)]		; first character in next word
	LDB 5,[	103400,,(1)
		102500,,(1)
		101600,,(1)
		100700,,(1)
		100000,,(1)](3)
	DPB 5,[	013400,,(1)
		012500,,(1)
		011600,,(1)
		010700,,(1)
		010000,,(1)](3)
	MOVEI 5," "			; space in hole
	DPB 5,[	350700,,(1)
		260700,,(1)
		170700,,(1)
		100700,,(1)
		010700,,(1)](3)
	JRST INSCH1			; check for being done

; At each iteration Y has last character, X has next address

INSCH2:	MOVE 3,2			; copy the character
	LDB 2,[010700,,(1)]		; first character in next word
	DPB 3,[000700,,(1)]		; last character here
	MOVE 3,(1)			; get word being hacked
	ROT 3,-7			; put characters in right place
	IORI 3,1			; make sure bit 1.1 is on
	MOVEM 3,(1)			; save character in word
INSCH1:	CAME 1,4			; at last address?
	 AOJA 1,INSCH2
	SETOM SCUPDP			; some update somewhere
	MOVE 1,VPOS			; this line
	SOSLE (17)
	 JRST INSCH0			; loop for more characters
	ADJSP 17,-1
	SETOM SLUPDP(1)			; this line was hacked
	SKIPN DMP			; on a DM?
	 POPJ 17,
	DMCMD 30			; leave i/d mode
	POPJ 17,
; DELCHR -- Delete a character ;⊗ DELCHR DELCH0 DELC1A DELCH2 DELCH1
; Call:	MOVE <number of characters to delete>
;	PUSHJ 17,INSCHR
;	<return>
; Smashes 0, 1, 2, 3, 4, 5, and 6.

↑DELCHR:PUSH 17,			; save argument
	SKIPN DMP			; is this a DM?
	 JRST DELCH0
	DMCMD 20			; yes, enter i/d mode
DELCH0:	SKIPN DMP			; on a DM?
	 JRST DELC1A
	DMCMD 10			; delete a character
DELC1A:	MOVE 1,VPOS			; get current vertical position
	IMULI 1,NWRDLN			; number of words
	MOVE 4,1			; save it for later
	ADDI 4,SCREEN+NWRDLN-3		; address of last text word in line
	MOVE 2,HPOS			; get horizontal position
	CAIL 2,LINEL			; within valid range?
	JRST [	ADJSP 17,-1		; no
		POPJ 17,]
	IDIVI 2,5			; number of words
	ADDI 1,SCREEN+2(2)		; address of word with cursor
	LDB 5,[	013400,,(1)
		012500,,(1)
		011600,,(1)
		010700,,(1)
		010000,,(1)](3)
	DPB 5,[	103400,,(1)
		102500,,(1)
		101600,,(1)
		100700,,(1)
		100000,,(1)](3)
	JRST DELCH1			; check for being done

; Each time around the iteration A had address of next word

DELCH2:	LDB 2,[350700,,(1)]		; last character in previous
	DPB 2,[010700,,-1(1)]		; to previous
	LDB 2,[013400,,(1)]		; get last characters in this word
	DPB 2,[103400,,(1)]		; put back left justified
DELCH1:	CAME 1,4			; done?
	 AOJA 1,DELCH2
	MOVEI 2," "			; get a space
	DPB 2,[010700,,(1)]		; blank out last column
	SETOM SCUPDP			; screen updated someplace
	MOVE 1,VPOS			; get this line
	SOSLE (17)
	 JRST DELCH0			; hack another character
	ADJSP 17,-1
	SETOM SLUPDP(1)			; flag this line hacked
	SKIPN DMP			; on a DM?
	 POPJ 17,
	DMCMD 30			; leave i/d mode
	POPJ 17,
; SCNUPD -- Update screen ;⊗ SCNUPD CSRUPD SCUPD1 SCUP1A SCUPD2
; Call:	PUSHJ 17,SCNUPD
;	<return>
; Smashes 0, 1, 2, 3, and 4.

↑SCNUPD:MOVSI 1,-NLINES
	SETZ 2,
	SKIPE SLUPDP(1)			; does this line need hacking?
	 ADDI 2,1
	AOBJN 1,.-2
	SKIPN IIIP			; III always updates everything
	 CAIL 2,4			; after four lines update entire screen
	  SETOM SAUPDP
	MOVE VSIZE
	MOVEM SCRLCT
	AOSE SAUPDP			; update entire screen?
	 JRST SCUPD1
	SETZM SCUPDP			; clear other update flags
	SETZM SLUPDP
	MOVE [SLUPDP,,SLUPDP+1]
	BLT SLUPDP+NLINES-1
	SKIPE DMP			; is this a DM?
	 JRST [	PUSHJ 17,DMOUT
		JRST CSRUPD]
	UPGIOT SDISP			; output new screen on DD and III

; Update cursor

CSRUPD:	SKIPE DMP			; is this a DM?
	 JRST [	DMCMD 14		; cursor ← [0,2]
		MOVE HPOS
		XORI 140
		PUSHJ 17,DMCHAR
		MOVE VPOS
		ADDI 2
		XORI 140
		PUSHJ 17,DMCHAR
		JRST DMOUT]
	SKIPN DDP			; no cursor stuff yet for III's
	 POPJ 17,
	MOVEI 2
	MOVEM SCC+2
	MOVE [SCC+2,,SCC+3]
	BLT SCC+2+NGW-1			; initialize graphics words
	SKIPGE 1,OVPOS			; got an old position?
	 JRST .+3
	  PUSHJ 17,GETCSY		; get cursor vertical position
	  DDUPG CDISP			; clear cursor
	MOVE 1,HPOS			; horizontal character position
	CAIL 1,LINEL			; within valid range?
	JRST [	SETOM OVPOS		; no, we won't have cursor now
		POPJ 17,]
	IMULI 1,6			; horizontal bit position
	ADDI 1,2			; graphics mode hack
	IDIVI 1,=32
	MOVNS 2
	MOVSI 3,740000
	LSH 3,(2)
	LDB 4,[010300,,3]
	ROT 4,-3
	TRZ 3,17
	IORI 3,2
	IORI 4,2
	DMOVEM 3,SCC+2(1)
	MOVE 1,VPOS			; save vertical position
	MOVEM 1,OVPOS
	PUSHJ 17,GETCSY
	DDUPG CDISP			; draw new cursor
	POPJ 17,

SCUPD1:	AOSE SCUPDP			; did any update happen?
	 JRST SCUPD2
	MOVSI 1,-NLINES
SCUP1A:	SKIPE SLUPDP(1)			; need to hack this line?
	 PUSHJ 17,UPDLIN
	AOBJN 1,SCUP1A
	JRST CSRUPD

SCUPD2:	AOSE CRUPDP			; was cursor hacked?
	 POPJ 17,
	JRST CSRUPD
; GETCSY UDPLIN redisplay subroutines ;⊗ GETCSY UPDLIN

; Set up display program vertical position

GETCSY:	IMULI 1,=12
	ADDI 1,=24+=10
	DPB 1,[140400,,SCC+1]
	LSH 1,-4
	DPB 1,[240500,,SCC+1]
	POPJ 17,

; Display a single line

UPDLIN:	SKIPE DMP
	 POPJ 17,
	SKIPE LDISP+2
	 UPGIOT [0 ↔ 0 ↔ 0 ↔ 0]		; wait for previous
	SETZM SLUPDP(1)
	HRRZ 2,1			; line number
	IMULI 2,NWRDLN			; word position
	MOVSI 2,SCREEN+2(2)		; address of start of line
	HRRI 2,LNP+2
	BLT 2,LNP+NWRDLN-2
	HRRZ 2,1			; get line number again
	IMULI 2,=12
	ADDI 2,=24			; starting raster number
	DPB 2,[140400,,LNP]		; zap in low 4 bits of address
	LSH 2,-4			; throw low bits away
	DPB 2,[240500,,LNP]		; high 5 bits of address
	UPGIOT LDISP			; display the line
	POPJ 17,
; DMCHAR DMOUT Datamedia output routines ;⊗ DMCHAR DMOUT

; Character output to DM

DMCHAR:	SOSG DMCNT			; any room in buffer?
	 PUSHJ 17,DMOUT
	IDPB DMPNT			; save character
	POPJ 17,

; Buffer output to DM; called when DM buffer full or want to force buffer out

↑DMOUT:	SKIPN DMPGM			; any program there?
	 POPJ 17,
	HRRZ DMPNT			; get current value of pointer
	SUBI DMPGM-1			; compute number of words used
	MOVEM DMDISP+1			; set number of words to do
	UPGIOT DMDISP			; output DM program
	MOVS HPOS
	HRR VPOS
	ADDI 2-1			; two lines for who line
	CURSOR				; bop the cursor to last position
	SETZM DMPGM
	MOVE [DMPGM,,DMPGM+1]
	BLT DMPGM+DMBUFL-1		; clear the old program
	MOVEI <5*DMBUFL>-4
	MOVEM DMCNT			; initialize DM counter
	MOVE [440700,,DMPGM]
	MOVEM DMPNT			; initialize DM pointer
	MOVEI 177			; quote
	IDPB DMPNT
	MOVEI 14			; cursor position
	IDPB DMPNT
	MOVE HPOS			; horizontal position
	XORI 140
	IDPB DMPNT
	MOVE VPOS			; vertical position
	ADDI 2				; who line space
	XORI 140
	IDPB DMPNT
	POPJ 17,

	BEND DISPLY