Google
 

Trailing-Edge - PDP-10 Archives - bb-k345a-sb - dpypak.mac
There are 5 other files named dpypak.mac in the archive. Click here to see a list.
TITLE	DPYPAK  --  VIDEO DISPLAY PACKAGE
SUBTTL	C.D. OTOOLE/CDO  16-APR-80

;*** COPYRIGHT (C) 1977, 1978, 1979, 1980,
;	DIGITAL EQUIPMENT CORP., MARLBORO, MASS. ***

	SALL			;CLEAN UP LISTING

	SYN	IFE,IF		;DEFINE NEW PSEUDO OP FOR PRETTY CONDITIONALS

	IFNDEF	TOPS,<TOPS==10>	;BUILD TOPS10 DPYPAK



;DEFINE SOME AC'S FIRST

	CHAR==0			;CHARACTER HOLDER ( NEED NOT BE SAVED )
	SCR==CHAR+1		;A SCRATCH REG ( NEED NOT BE SAVED )

	TYP==6			;TYPE OF TERMINAL FOR CONTROL INDEX
	CUR==7			;CURRENT POSITION ON SCREEN
	NEW==10			;NEW DISPLAY ARRAY
	OLD==11			;OLD DISPLAY ARRAY
	NL==12			;LINE CURRENTLY EXAMINING
	NC==13			;COLUMN   "         "
	POSL==14		;LINE OF CURSOR
	POSC==15		;COLUMN "   "
	ARGS==16		;DPSS ARGUMENT POINTER
	P==17			;A PUSH-DOWN LIST
IF TOPS-10,<

		;TERMINAL SUPPORT DESIRED (TYPES FROM TRMOP. .TOTRM)

		%VT05==<SIXBIT/VT05/>
		%VT06==<SIXBIT/VT06/>
		%VT50==<SIXBIT/VT50/>
		%VT52==<SIXBIT/VT52/>
		%VT100==<SIXBIT/VT100/>

		TTYBYT==7		;7 BIT BYTES
		TTYCPW==5		;5 CHARACTERS PER WORD
		TTYFIL==177		;CHARACTER USED FOR FILLER

		;TRMOP. FUNCTIONS

		.TOSET==1000		;ADDON TO SET RATHER THAN READ
		.TONFC==1010		;NO FREE CRLF
		.TOPSZ==1023		;PAGE SIZE
		.TOTSP==1031		;TRANSMIT SPEED
		.TOTRM==1041		;TERMINAL TYPE

> ;END IF TOPS-10

IF TOPS-20,<

		;TERMINAL SUPPORT DESIRED (TYPES FROM GTTYP)

		%VT05==12
		%VT50==13
		%VT52==17
		%VT100==20

		TTYBYT==8		;8 BIT BYTES
		TTYCPW==4		;4 CHARACTERS PER WORD
		TTYFIL==200		;CHARACTER USED FOR FILL
		.MORSP==27		;MTOPR - RETURN BAUD RATES
		.PRIOU==101		;PRIMARY OUTPUT JFN

		;JSYS DEFINITIONS

		OPDEF	JSYS	[104000,,0]
		OPDEF	GTJFN	[JSYS 20]
		OPDEF	OPENF	[JSYS 21]
		OPDEF	SOUT	[JSYS 53]
		OPDEF	PSOUT	[JSYS 76]
		OPDEF	MTOPR	[JSYS 77]
		OPDEF	DISMS	[JSYS 167]
		OPDEF	HALTF	[JSYS 170]
		OPDEF	GTTYP	[JSYS 303]
		OPDEF	SFPOS	[JSYS 526]

> ;END IF TOPS-20
;ENTRY POINTS IN DPYPAK

;	DPYINI		INITIALIZE A SCREEN FOR A TERMINAL TYPE
;	DPYCLR		FORCE A REFRESH CYCLE NEXT TIME THROUGH "DPYOUT"
;	DPYREF		FORCE A REFRESH NOW
;	DPYZAP		CLEAR SCREEN NOW (ERASE)
;	DPYWAT		WAIT FOR READER TO SEE THE SCREEN
;	DPYLSH		SHIFT LEFT JUSTIFIED CHARACTER TO RIGHT JUSTIFIED
;	DPYROL		SCROLL THE SCREEN ( SEE "RACE" )
;	DPYSIZ		RETURN MAX COLUMN AND MAX LINE NUMBERS

;	DPYCHR		PUT A SINGLE CHARACTER ON THE SCREEN
;	DPYCRM		SAME AS DPYCHR BUT REMEMBERS WHERE CURSOR WAS LEFT

;	DPYOUT		MAKE A SCREEN CHANGE
;	DPYREM		SAME AS DPYOUT BUT REMEMBERS WHERE CURSOR WAS LEFT

;	DPYSEC		OUTPUT A SCREEN SECTION
;	DPYRSC		SAVE AS DPYSEC BUT REMEMBERS WHERE CURSOR WAS LEFT
;	DPYCSC		CLEAR A SCREEN SECTION

;	DPYSAV		RETURN THE CURRENT SCREEN CONTENTS
;	DPYRST		RESTORE SCREEN ( OUTPUT FROM DPYSAV )

;	DPYCRM, DPYREM, AND DPYRSC ARE USED WHEN ONLY A SMALL NUMBER OF THINGS
;		CHANGE AND SAVES LOTS OF CURSOR MOVEMENTS ( SEE "PONG" ).
;		HOWEVER, CALLER GUARANTEES THAT HE DIDN'T MOVE IT BETWEEN
;		CALLS.  ( LIKE SET NO ECHO ON TERMINAL )
;TERMINAL SPECIFICS
;ARGUMENTS ARE:

;	NAME	name of the terminal
;	LINES	number of lines on the screen
;	COLUMNS	number of columns
;	HOME	encoded character for cursor home
;	ERSEOL	   "        "      "    "    erase-to-end-of-line
;	ERSEOS	   "        "      "    "    erase-to-end-of-screen
;	DIRADR	   "        "      "    "    enter direct addressing mode
;	TRANSL	instruction to execute to convert line/column to commands
;	CURUP	encoded character for cursor up
;	CURLEFT	   "        "      "    "    left
;	REVLF	   "        "      "    "    reverse line feed (scroll backwards)
;	CURDOWN	   "        "      "    "    down


;	FOR CONTROL SEQUENCES, CHARACTER IS ENCODED AS FOLLOWS

;	   CHAR < 0		;EXTRA SPECIAL HANDLING FOR THIS SEQUENCE
				;CURRENTLY ONLY USED FOR CURSOR ADDRESSING:
				;IF POSITIVE, TERMINAL WANTS LINE# THEN COLUMN#
				;IF NEGATIVE, TERMINAL WANTS COLUMN# THEN LINE#
;	   0			;TERMINAL CAN'T DO THIS FUNCTION
;	   0 < CHAR < 177	;ONLY NEED CHARACTER
;	1000 < CHAR < 1777	;CHARACTER THEN FILLERS
;	2000 < CHAR < 2777	;FILLERS THEN CHARACTER
;	3000 < CHAR < 3777	;ESCAPE CHARACTER
;	4000 < CHAR < 4777	;ESCAPE, "[", CHARACTER (VT100)

DEFINE	DPYTYP,<

	TRMNAL	(VT05,^D20,^D72,1035,1036,1037,16,<ADDI CHAR,40>,1032,10,0,1012)
	TRMNAL	(VT06,^D25,^D72,1035,1036,1037,0,0,2032,2010,0,12)
	TRMNAL	(VT50,^D12,^D80,3110,3113,3112,0,0,3101,10,0,12)
	TRMNAL	(VT52,^D24,^D80,3110,3113,3112,3131,<ADDI CHAR,40>,3101,10,3111,12)
	TRMNAL	(VT100,^D24,^D80,4110,4113,4112,4000,0,4101,10,3115,12)
	TRMNAL	(DM,^D24,^D80,2,27,0,-14,<XORI CHAR,140>,32,10,0,12)
	TRMNAL	(TEC,^D24,^D80,151,143,163,-154,<TRC CHAR,177>,170,167,0,150)
	TRMNAL	(IMLAC,^D40,^D80,3,20,13,-1,<TRC CHAR,177>,4,10,0,12)

>  ;END OF DEFINED TERMINAL TYPES

DOFILL==0		;ASSUME NO TERMINALS NEED FILLERS
DEFINE	CONTRL(CHAR),<
	..B35==0
	..T0==CHAR
	IFL	..T0,<..B35==1
			..T0==-..T0>
	..T1==..T0&177
	..T2==..T0-..T1
	IFE	..T2,<..ANS==<BYTE (7)..T1>>
	IFE	..T2-1000,<DOFILL==1
			..ANS==<BYTE (7)..T1,177,0>>
	IFE	..T2-2000,<DOFILL==1
			..ANS==<BYTE (7)177,..T1,0>>
	IFE	..T2-3000,<..ANS==<BYTE (7)33,..T1,0>>
	IFE	..T2-4000,<..ANS==<BYTE (7)33,"[",..T1,0>>
	EXP	<..ANS!..B35>
>  ;END OF CONTRL

DEFINE	TRMNAL(A,B,C,D,E,F,G,INS,H,I,J,K),<IFDEF %'A,<.'A==<.-TYPNAM>
							<ASCII/A    />>>

TYPNAM:	DPYTYP
MAXTYP==.-TYPNAM

DEFINE	TRMNAL(A,B,C,D,E,F,G,INS,H,I,J,K),<IFDEF %'A,<EXP %'A>>

TYPTAB:	DPYTYP

DEFINE	TRMNAL(A,B,C,D,E,F,G,INS,H,I,J,K),<IFDEF %'A,<IFG <B-NLMAX>,<NLMAX==B>
							EXP B>>

NLMAX==0	;PRIME COUNTER FOR MAXIMUM LINES
NLINES:	DPYTYP

DEFINE	TRMNAL(A,B,C,D,E,F,G,INS,H,I,J,K),<IFDEF %'A,<EXP C>>

NCMAX==^D80	;CAN'T REALLY CHANGE THIS WITHOUT BREAKING LOTS OF OLD PROGRAMS
WDPLIN==<NCMAX/^D5>
NCOLS:	DPYTYP

DEFINE	TRMNAL(A,B,C,D,E,F,G,INS,H,I,J,K),<IFDEF %'A,<CONTRL(D)>>

HOMEUP:	DPYTYP

DEFINE	TRMNAL(A,B,C,D,E,F,G,INS,H,I,J,K),<IFDEF %'A,<CONTRL(E)>>

ERAEOL:	DPYTYP

DEFINE	TRMNAL(A,B,C,D,E,F,G,INS,H,I,J,K),<IFDEF %'A,<CONTRL(F)>>

ERAEOS:	DPYTYP

DEFINE	TRMNAL(A,B,C,D,E,F,G,INS,H,I,J,K),<IFDEF %'A,<CONTRL(G)
							REVDIR==REVDIR!..B35>>

REVDIR==0	;ASSUME NO TERMINALS WANT X,Y REVERSED
DIRADR:	DPYTYP

DEFINE	TRMNAL(A,B,C,D,E,F,G,INS,H,I,J,K),<IFDEF %'A,<INS>>

COMPXY:	DPYTYP

DEFINE	TRMNAL(A,B,C,D,E,F,G,INS,H,I,J,K),<IFDEF %'A,<CONTRL(H)>>

CURUP:	DPYTYP

DEFINE	TRMNAL(A,B,C,D,E,F,G,INS,H,I,J,K),<IFDEF %'A,<CONTRL(I)>>

CLEFT:	DPYTYP

DEFINE	TRMNAL(A,B,C,D,E,F,G,INS,H,I,J,K),<IFDEF %'A,<CONTRL(J)>>

REVLF:	DPYTYP

DEFINE	TRMNAL(A,B,C,D,E,F,G,INS,H,I,J,K),<IFDEF %'A,<CONTRL(K)>>

LINEFD:	DPYTYP
;ENTRY TO INITIALIZE A DISPLAY..
;
;	CALL DPYINI(BYTE-SIZE,TERMINAL-TYPE)
;
;TERMINAL-TYPE IS ASCII NAME OF A SUPPORTED TERMINAL (VT05,VT06)
;	IF DPYPAK CAN FIGURE OUT WHAT KIND OF TERMINAL (TOPS20 OR 7.01)
;	IT WILL OVER RIDE CALLERS ARGUMENT AND RETURN TYPE (SEE BELOW)
;BYTE-SIZE IS 7 FOR ENCODE'ED ARRAYS ( "DIMENSION ARRAY(16,25)" )
;	   IS 36 FOR RIGHT JUSTIFIED CHARACTERS ( "DIMENSION ARRAY(80,25)" )
;	   IS <0 FOR LEFT JUSTIFIED CHARACTERS ( "DIMENSION ARRAY(80,25)" )
;		BUT READ WITH A1 FORMAT ( AVOID DPYLSH )
;CALLER MUST ACCOUNT FOR ALL 80 POSSIBLE COLUMNS (EVEN IF ONLY 72 FOR TERMINAL)
;	ALTHOUGH THAT'S NOT TRUE FOR LINES. E.G. FOR A VT05 SPECIFIC PROGRAM
;	USE "DIMENSION ARRAY(80,20)" OR "DIMENSION ARRAY(16,20)"

;DPYINI CAN ALSO BE CALLED AS A FUNCTION RATHER THAN A SUBROUTINE
;
;	FOO = DPYINI ( SAME-ARGUMENTS-AS-OTHER-CALL )
;
;FOO GETS THE TERMINAL ACTUALLY USED (ASCII) OR -1 IF IT WAS INVALID

DPYINI:: MOVE	CHAR,@0(ARGS)	;GET BYTE SIZE ( 7 OR 36 )
	JUMPLE	CHAR,[MOVEI CHAR,^D36	;NEGATIVE IS LEFT JUSTIFIED ARRAY
		      SETOM LJUST	;REMEMBER THAT
		      JRST .+1]		;RESUME IN LINE CODE
	DPB	CHAR,[POINT 6,NEWPTR,11] ;INSERT INTO ARRAY BYTE POINTER
	PUSHJ	P,DPYCLR	;CLEAR THE INTERNAL BUFFER
	PUSHJ	P,GETTYP	;TRY TO FIGURE OUT TERMINAL TYPE
	MOVE	CHAR,@1(ARGS)	;GET TERMINAL TYPE
	SKIPE	SCR		;DO I KNOW IT FROM GETTYP
	  MOVE	CHAR,SCR	;YES, OVERRIDE CALLER
	MOVSI	SCR,-MAXTYP	;FORM AOBJN FOR KNOWN TYPES
	CAME	CHAR,TYPNAM(SCR);FOUND IT
	  AOBJN	SCR,.-1		;NO, TRY AGAIN
	JUMPGE	SCR,[SETOB CHAR,VIDEOT ;DIDN'T FIND ONE, RETURN -1, ZAP TYPE
		POPJ P,]	;AND RETURN
	HRRZM	SCR,VIDEOT	;REMEMBER VIDEO TERMINAL TYPE
	JRST	SETINI		;SET INITIAL TERMINAL CHARACTERISTICS

;ENTRY TO RETURN SCREEN SIZES
;
;	CALL DPYSIZ(MAX-COLUMN,MAX-LINE)
;
;SIMPLY RETURNS THOSE VALUES

DPYSIZ:: JSP	CHAR,SAVREG	;REALLY FOR EVER INITIALIZED CHECK
	MOVE	CHAR,NCOLS(TYP)	;MAXIMUM COLUMN NUMBER FOR THIS TYPE
	MOVEM	CHAR,@0(ARGS)	;STORE FOR USER
	MOVE	CHAR,NLINES(TYP) ;MAXIMUM LINE NUMBER
	MOVEM	CHAR,@1(ARGS)	;SO CALLER CAN FIND END OF SCREEN FOR DPYCHR
	JSP	CHAR,RESREG	;RESTORE REGS
	POPJ	P,		;ALL DONE
;ENTRY TO ALLOW CALLER TO FORCE A REFRESH OF THE ENTIRE SCREEN..
;
;	CALL DPYCLR

DPYCLR:: SETZM	SCREEN		;CLEAR CURRENT SCREEN
DPYCL1:	MOVE	CHAR,[SCREEN,,SCREEN+1] ;THE ENTIRE SCREEN
	BLT	CHAR,ENDSCR	;TO THE END OF THE SCREEN
	POPJ	P,		;RETURN, WE'LL CLEAR ON NEXT SWEEP

;ENTRY TO ALLOW WATCHER TO READ THE SCREEN..
;
;	CALL DPYWAT(NUMBER-OF-SECONDS)
;		IF NUMBER-OF-SECONDS .GT. 60 THEN ITS NUMBER-OF-MILLISECONDS
;
;SIMPLY SLEEPS FOR THAT MANY SECONDS

DPYW.1:	SKIPA	SCR,[^D500]	;1.5 SECONDS
DPYWAT:: MOVE	SCR,@0(ARGS)	;GET TIMER
	CAIG	SCR,^D60	;SECONDS OR MILLISECONDS
	  IMULI	SCR,^D1000	;CONVERT SECONDS TO MILLISECONDS
IF TOPS-10,<
	HIBER	SCR,		;WAIT THE SPECIFIED AMOUNT
	  JFCL			;IGNORE FAILURE
>  ;END OF IF TOPS-10
IF TOPS-20,<DISMS>		;WAIT THE SPECIFIED AMOUNT
	POPJ	P,		;THEN RETURN

;ENTRY TO FORCE CLEAR OF ENTIRE SCREEN ( REAL CLEAR, NOT REFRESH )..
;
;	CALL DPYZAP

DPYZAP:: MOVE	CHAR,[ASCII/     /] ;LOAD BLANKS
	MOVEM	CHAR,SCREEN	;STORE THE BLANKS
	PUSHJ	P,DPYCL1	;NOW BLT ENTIRE ARRAY
	JSP	CHAR,SAVREG	;SAVE CALLERS REGISTERS
	PUSHJ	P,HOME		;SEND HOME SEQUENCE
	SKIPE	ERAEOS(TYP)	;CAN THE TERMINAL ERASE TO END OF SCREEN
	  JRST	[MOVEI CHAR,ERAEOS(TYP) ;YES, GET ERASE SEQUENCE
		PUSHJ P,PUTCTL	;OUTPUT IT
		JRST FORGET]	;FORCE OUT, FORGET TRACKS, RETURN
	MOVEI	NC,1		;WANT TO GET TO COLUMN 1
	MOVEI	NL,1		;ON LINE 1
	PUSHJ	P,ERSLIN	;ERASE LINE N, INCREMENT TO NEXT
	CAMG	NL,NLINES(TYP)	;OFF THE END OF THE SCREEN
	  JRST	.-2		;NO, CLEAR ANOTHER LINE
	JRST	FORGET		;FORCE OUT, FORGET TRACKS, RETURN

;ENTRY TO CONVERT LEFT-JUSTIFIED CHARACTER TO RIGHT-JUSTIFIED BINARY
;
;	BIN = DPYLSH(THING-READ-WITH-A1-FORMAT)

DPYLSH:: MOVE	CHAR,@0(ARGS)	;GET CHARACTER ( ASCII /X    / )
	LSH	CHAR,-^D29	;MOVE TO LOW 7 BITS
	POPJ	P,		;RETURN WITH IT IN AC 0
;ENTRY TO SCROLL THE SCREEN SO MANY LINES..
;
;	CALL DPYROL(NUMBER-OF-LINES-TO-ROLL)
;
;MOVES SCREEN FOR NEW OUTPUT ACCORDING TO SIGN OF NUMBER-OF-LINES-TO-ROLL
;	IF POSITIVE, BRING IN "N" BLANK LINES ON THE BOTTOM OF THE SCREEN
;	IF NEGATIVE, BRING IN "ABS(N)" BLANK LINES FROM THE TOP
;	IF ZERO, WHY DID YOU CALL THIS ROUTINE

DPYROL:: JSP	CHAR,SAVREG		;SAVE CALLERS
	SKIPN	NEW,@0(ARGS)		;ANY LINES TO ROLL
	  JRST	FORGET			;NO, RETURN
	PUSHJ	P,GOHOME		;GOTO HOME POSITION (MAYBE)
	JUMPL	NEW,ROL.03		;GO IF ROLLING BACKWARDS
	MOVE	NL,NLINES(TYP)		;FIND LAST LINE OF THIS SCREEN
	IMULI	NL,WDPLIN		;FIRST WORD NOT INVOLVED IN THE MOVE
	MOVE	OLD,NEW			;NUMBER OF LINES TO ROLL
	IMULI	OLD,WDPLIN		;COMPUTE NEW TOP OF SCREEN
	ADDI	OLD,SCREEN		;...
	HRL	CHAR,OLD		;SOURCE = NEW HOME POSITION
	HRRI	CHAR,SCREEN		;DESTINATION = HOME IN INTERNAL SCREEN
	MOVNS	OLD			;COMPUTE LAST COLUMNS TO APPEAR ON NEW SCREEN
	ADDI	OLD,SCREEN-1(NL)	;...
	JUMPLE	OLD,[JSP CHAR,RESREG	;ROLLING ENOUGH TO ACTUALLY CLEAR SCREEN
		     JRST DPYZAP]	;SO ZAP IT INSTEAD
	BLT	CHAR,SCREEN(OLD)	;MOVE THE NEW SCREEN TO HOME POSITION
	MOVE	CHAR,[ASCII/     /]	;LOAD SOME BLANKS
	MOVEM	CHAR,SCREEN+1(OLD)	;CLEAR LINES ROLLED UP
	HRLI	CHAR,SCREEN+1(OLD)	;SET UP FOR BLT
	HRRI	CHAR,SCREEN+2(OLD)	;...
	BLT	CHAR,SCREEN-1(NL)	;CLEAR IT ALL
	MOVE	NL,NLINES(TYP)		;WHERE TO START ROLLING FROM
	PUSH	P,LINEFD(TYP)		;CONTROL SEQUENCE TO USE

;COMMON RETURN POINT FOR FORWARD OR BACKWARD SCROLL

ROL.01:	MOVEI	NC,1			;WANT COLUMN 1
	PUSHJ	P,CURMOV		;GET TO CORRECT POSITION
ROL.02:	MOVEI	CHAR,0(P)		;SAVED CONTROL SEQUENCE
	PUSHJ	P,PUTCTL		;OUTPUT THAT
	SOJG	NEW,ROL.02		;CONTINUE FOR ALL LINES
	POP	P,(P)			;CLEAN STACK
	JRST	FORGET			;FORGET TRACKS, RETURN
;HERE IF ROLLING BACKWARDS

ROL.03:	MOVE	OLD,NEW			;GET - NUMBER OF LINES TO ROLL
	IMULI	OLD,WDPLIN		;COMPUTE NEW LOWER RIGHT CORNER
	ADDI	OLD,ENDSCR		;...
	CAIGE	OLD,SCREEN		;HOW FAR ARE WE BACKING UP
	  JRST	[JSP CHAR,RESREG	;ENOUGH TO ACTUALLY CLEAR THE SCREEN
		 JRST DPYZAP]		;SO ZAP THE SCREEN INSTEAD
	MOVEI	NL,ENDSCR		;LOWER RIGHT IN INCORE SCREEN
ROL.04:	CAIGE	NL,SCREEN		;OFF THE TOP OF THE SCREEN YET
	  JRST	ROL.05			;YES, DONE MOVING THE INCORE SCREEN
	CAIL	OLD,SCREEN		;STILL USING REAL DATA
	 SKIPA	SCR,0(OLD)		;YES, GET SCREEN CONTENTS
	  MOVE	SCR,[ASCII/     /]	;NO, BRING BLANKS IN ON THE TOP LINES
	MOVEM	SCR,0(NL)		;RIPPLE DATA DOWN
	SOS	OLD			;STEP DOWN TO NEXT LOCATION
	SOJA	NL,ROL.04		;GET THE ENTIRE SCREEN
ROL.05:	SKIPN	SCR,REVLF(TYP)		;CAN TERMINAL REVERSE SCROLL
	  JRST	[JSP CHAR,RESREG	;NO, RESTORE CALLERS REGISTERS
		 JRST DPYREF]		;AND REFRESH FROM INTERNAL SCREEN
	PUSH	P,SCR			;SAVE CONTROL SEQUENCE FOR REVERSE LF
	MOVMS	NEW			;NUMBER OF LINES TO ROLL
	MOVEI	NL,1			;STARTING AT HOME POSITION
	JRST	ROL.01			;SCROLL, RETURN
;ENTRY TO PLACE A SINGLE RIGHT JUSTIFIED CHARACTER ON THE SCREEN
;
;	CALL DPYCHR(RIGHT-JUSTIFIED-CHAR,COLUMN-DESIRED,LINE-DESIRED)
;
;LEAVES CURSOR TO THE RIGHT ( 1 COLUMN ) OF THE POSITION SPECIFIED
;	UNLESS CHARACTER.LT.0 ( IN 36 BITS ) THEN CURSOR IS AT THE POSITION
;DPYCRM REMEMBERS THAT FACT FOR LATER USE

DPYCRM:: SETOM	REMEMB		;MARK REMEMBERING
DPYCHR:: JSP	CHAR,SAVREG	;SAVE CALLERS REGISTERS
	SKIPLE	NC,@1(ARGS)	;GET COLUMN DESIRED, RANGE CHECK IT
	 CAMLE	NC,NCOLS(TYP)	;...
	  JRST	FORGET		;INVALID, RETURN
	SKIPLE	NL,@2(ARGS)	;DO THE SAME FOR NEW LINE
	 CAMLE	NL,NLINES(TYP)	;...
	  JRST	FORGET		;THAT'S INVALID
	PUSHJ	P,GOHOME	;MOVE TO HOME POSITION (MAYBE)
	PUSHJ	P,CURMOV	;MOVE TO NEW POSITION
	PUSHJ	P,SETCUR	;COMPUTE BYTE POINTER TO SCREEN
	MOVE	CHAR,@0(ARGS)	;GET DISPLAY CHARACTER
	JUMPL	CHAR,CHRRET	;QUIT NOW IF JUST POSITION WITH NO DATA
	CAIGE	CHAR," "	;A CONTROL CHARACTER
	  MOVEI	CHAR," "	;YES, CONVERT TO A BLANK
	IDPB	CHAR,CUR	;STORE INTO CURRENT SCREEN
	PUSHJ	P,DPYPUT	;TYPE IT OUT
	AOS	POSC		;ACCOUNT FOR TYPEOUT
CHRRET:	SKIPN	REMEMB		;WANT TO REMEMBER WE LEFT IT HERE
	  JRST	FORGET		;NO, FORGET TRACKS
	JRST	FRCRET		;YES, JUST RETURN

;ENTRY TO CLEAR A SELECTED SECTION OF THE SCREEN
;
;	CALL DPYCSC(1ST-COL,1ST-LINE,END-COL,END-LINE)
;
;FAKES OUT A CALL TO DPYSEC

DPYCSC:: SETOM	CLRING		;MARK CLEARING THE SECTION
	SOS	ARGS		;ARGS ARE IN SAME ORDER AS DPYSEC BUT
	PUSHJ	P,DPYSEC	; OFF BY ONE
	SETZM	CLRING		;MAKE OTHER ENTRIES WORK AGAIN
	AOJA	ARGS,CPOPJ	;JUST FOR GRINS, PUT ARGS BACK AGAIN
;ENTRIES TO SAVE/RESTORE A SCREEN..
;
;	CALL DPYSAV(HOLDING-ARRAY)
;	CALL DPYRST(THAT-SAME-ARRAY)
;
;THESE ENTRIES ARE USEFUL WHEN CALLER REALLY WANTS TO "PUSH" A SCREEN, FLASH
;	SOME OTHER OUTPUT, AND THEN "POP" THE OLD ONE.  ESPECIALLY USEFUL WHEN
;	CURRENT SCREEN HAS BEEN FILLED WITH DATA THAT IS NOT EASILY RE-CONSTRUCTED
;	( USED "DPYSEC" TO DO LINE AT A TIME OUTPUT OF "ENCODE"D DATA )
;
;	CALLERS ARRAY MUST BE LARGE ENOUGH TO CONTAIN THE SCREEN FOR THE
;	TERMINAL TYPE THAT IS CURRENTLY BEING USED.  400 (DECIMAL) WORDS IS
;	SAFE FOR DEC TERMINALS AND MOST OTHERS BUT SOME HAVE MORE THAT 25 LINES
;	AND REQUIRE MORE SPACE.  CAVEAT: THE ARRAY IS NOT CHECKED AS TO LENGTH.

DPYSAV:: JSP	CHAR,SAVREG	;SAVE REGS, GET TYPE
	HRLI	CHAR,SCREEN	;SOURCE = CURRENT SCREEN
	HRRI	CHAR,@0(ARGS)	;DESTINATION = USERS ARRAY
	MOVE	SCR,NLINES(TYP)	;NUMBER OF LINES ON THE SCREEN
	IMULI	SCR,WDPLIN	;NUMBER OF WORDS NEEDED
	ADDI	SCR,@0(ARGS)	;PLUS ARRAY START
	BLT	CHAR,-1(SCR)	;MOVE TO CALLERS BUFFER
	JSP	CHAR,RESREG	;PUT THE REGS BACK
	POPJ	P,		;RETURN NOW

DPYRST:: PUSH	P,NEWPTR	;SAVE CURRENT BYTE POINTER INFO
	PUSH	P,LJUST		;AND JUSTIFICATION FLAG
	MOVSI	CHAR,(POINT 7,0) ;GET NEW BYTE POINTER
	MOVEM	CHAR,NEWPTR	;FAKE OUT DPYOUT
	SETZM	LJUST		;...
	PUSHJ	P,DPYOUT	;FLASH THE SCREEN BACK
	POP	P,LJUST		;RESTORE ORIGINAL PARAMETERS
	POP	P,NEWPTR	;...
	POPJ	P,

;ENTRY TO FORCE A REFRESH OF THE SCREEN RIGHT NOW USING THE CURRENT
;	SCREEN CONTENTS.  BETTER THAN CALLING "DPYCLR" THEN "DPYOUT" OF SCREEN
;	OR "DPYSAV", "DPYCLR", "DPYRST".
;
;	CALL DPYREF

DPYREF:: SETOM	REFING		;MARK REFRESHING
	PUSH	P,ARGS		;SAVE CALLERS
	MOVEI	ARGS,[Z SCREEN]	;ARGUMENT IS OLD SCREEN
	PUSHJ	P,DPYRST	;PRETEND THIS IS A RESTORE
	POP	P,ARGS		;RESTORE CALLERS
	SETZM	REFING		;CLEAR FLAG
	POPJ	P,		;RETURN
;ENTRY TO DISPLAY A SCREEN SECTION..
;
;	CALL DPYSEC(NEW-SECTION-ARRAY,1ST-COL,1ST-LINE,END-COL,END-LINE)
;
;THIS ENTRY IS USED TO PARTITION A SCREEN INTO MANY RECTANGULAR SECTIONS.
;	THE BOX DEFINED BY THE LAST 4 ARGUMENTS WILL BE THE ONLY SECTION OF THE
;	SCREEN AFFECTED.  SEE THE SIZE DEFINITIONS IN "DPYINI" AND NOTE THE
;	FOLLOWING RESTRICTION.  THE NUMBER OF COLUMNS THAT MUST BE ALLOCATED IN
;	THE SECTION ARRAY MUST ACCOUNT FOR FULL WORD ALIGNMENT OF THE NEXT
;	LINE TO BE DISPLAYED EVEN THOUGH THE DISPLAY WILL STOP AT THE MARGIN
;	DEFINED BY "END-COL".  AN EXAMPLE:
;
;		CALL DPYINI(7,TTTYPE)	;USE ASCII DATA
;		CALL DPYSEC(ARRAY,6,2,13,5) ;DISPLAY 8-COL BY 4-LINE AREA
;
;	THE ARRAY DIMENSION MUST BE  (2,4)  .  NOTICE 2 FULL WORDS ARE 10 CHARS
;	BUT ONLY 8 WILL BE DISPLAYED.
;ENTER AT DPYRSC TO LEAVE CURSOR AT LAST POSITION AND REMEMBER THAT

DPYRSC:: SETOM	REMEMB		;MARK REMEMBERING
DPYSEC:: JSP	CHAR,SAVREG	;SAVE CALLERS
	SETZM	BOUNDS		;DPYOUT MUST RESET ITS BOUNDRIES
	SKIPLE	NC,@1(ARGS)	;GET 1ST-COLUMN
	 CAMLE	NC,NCOLS(TYP)	;RANGE CHECK IT
	  JRST	FORGET		;BAD ARGUMENT
	MOVEM	NC,NCPRIM	;SAVE STARTING COLUMN NUMBER
	SKIPLE	NL,@2(ARGS)	;GET 1ST-LINE
	 CAMLE	NL,NLINES(TYP)	;RANGE CHECK THIS TOO
	  JRST	FORGET		;ANOTHER BAD ARGUMENT
	MOVEM	NL,NLPRIM	;SAVE STARTING LINE NUMBER
	MOVE	CUR,@3(ARGS)	;GET END COLUMN
	MOVE	OLD,@4(ARGS)	;AND END LINE
	CAML	CUR,NC		;END .LT. BEGINNING
	 CAILE	CUR,NCMAX	;BEYOND LEGAL VAULE
	  JRST	FORGET		;STRANGE REQUEST
	CAMLE	OLD,NLINES(TYP) ;DON'T DISPLAY OFF THE BOTTOM
	  MOVE	OLD,NLINES(TYP) ;SET LOWER MARGIN
	MOVEM	OLD,NLEND	;STORE LOWER BOUND
	MOVE	OLD,NCOLS(TYP)	;GET RIGHT MARGIN FOR THIS TERMINAL
	CAMGE	CUR,OLD		;END COLUMN INVISIBLE
	  MOVE	OLD,CUR		;NO, USE IT
	MOVEM	OLD,NCEND	;STORE RIGHT MARGIN
	LDB	SCR,[POINT 6,NEWPTR,11] ;FETCH SIZE FROM DPYINI
	MOVEI	NEW,^D36	;COMPUTE BYTES PER WORD
	IDIVI	NEW,(SCR)	;FOR WORD ALIGNMENT OF LINES
	MOVE	CHAR,CUR	;COPY FOR LATER DIVIDES
	SUB	CHAR,NC		;COMPUTE NUMBER OF COLUMNS REQUESTED
	ADDI	CHAR,(NEW)	;ROUND UP
	IDIVI	CHAR,(NEW)	;NUMBER OF FULL WORDS NEEDED
	IMULI	CHAR,(NEW)	;BACK TO NUMBER OF CHARACTERS
	SOS	CHAR		;NOW COMPUTE END COLUMN
	ADD	CHAR,NCPRIM	;AS START+NUMBER OF COLUMNS-1
	MOVEM	CHAR,ENDUSR	;...
	JRST	DPYO.1		;ENTER DPYOUT FOR THE REST
;ENTRY TO DISPLAY A CHANGING SCREEN..
;
;	CALL DPYOUT(NEW-SCREEN-ARRAY)
;
;SEE SIZE DEFINITIONS FOR "DPYINI"
;ENTER AT DPYREM TO LEAVE CURSOR AT LAST POSITION AND REMEMBER THAT

DPYREM:: SETOM	REMEMB		;MARK REMEMBERING
DPYOUT:: JSP	CHAR,SAVREG	;SAVE CALLERS REGISTERS
	SKIPE	BOUNDS		;BOUNDRIES SET UP
	  JRST	DPYO.1		;YES, NO NEED TO DO IT TWICE
	MOVEI	CHAR,1		;GET A 1
	MOVEM	CHAR,NLPRIM	;AS 1ST LINE OF SWEEP
	MOVEM	CHAR,NCPRIM	;AS 1ST COLUMN
	MOVE	CHAR,NLINES(TYP);GET LOWER BOUND
	MOVEM	CHAR,NLEND	;MARK END
	MOVE	CHAR,NCOLS(TYP)	;GET RIGHT BOUNDARY
	MOVEM	CHAR,NCEND	;MARK IT
	MOVEI	CHAR,NCMAX	;HIGHEST COLUMN REPRESENTED BY USERS ARRAY
	MOVEM	CHAR,ENDUSR	;FOR KEEPING BYTE POINTERS STRAIGHT
	SETOM	BOUNDS		;FLAG BOUNDS ARE SET NOW
DPYO.1:	HLL	NEW,NEWPTR	;INSERT SIZE AND POSITION FOR BYTE POINTER
	SKIPE	CLRING		;CLEARING THE SPECIFIED SECTION
	 TDZA	NEW,NEW		;YES, GENERATE A NULL BYTE POINTER
	  HRRI	NEW,@0(ARGS)	;POINT TO NEW SCREEN
	PUSHJ	P,GOHOME	;MAYBE SET TO HOME POSITION

;START OUTER ( PER LINE ) LOOP

	MOVE	NL,NLPRIM	;GET 1ST LINE OF SWEEP
	MOVEI	NC,1		;SET COLUMN TO 1 FOR FIXOLD
	PUSHJ	P,FIXOLD	;SET "OLD" CORRECTLY
M1:	SKIPE	WHERA		;IS AN ERASE TO END OF LINE POSSIBLE
	  PUSHJ	P,CLRLIN	;YES, TRY TO CLEAR IT NOW
	CAMLE	NL,NLEND	;OFF THE BOTTOM OF THE SCREEN
	  JRST	REMRET		;YES, ALL DONE WITH THE SWEEP

;START INNER ( PER COLUMN ) LOOP

M1.1:	MOVE	NC,NCPRIM	;GET 1ST COLUMN OF SWEEP
	CAIE	NC,1		;STARTING AT THE LEFT MARGIN
	  PUSHJ	P,FIXOLD	;NO, BYTE POINTER MUST BE RE-COMPUTED
M2:	CAILE	NC,NCMAX	;OFF THE RIGHT HAND SIDE
	  AOJA	NL,M1		;YES, GO TO NEXT LINE
	CAMG	NC,ENDUSR	;OFF THE EDGE OF THE USERS ARRAY
	  ILDB	CHAR,NEW	;NO, GET NEW CHARACTER
	SKIPE	LJUST		;LEFT JUSTIFIED A1 FORMAT
	  LSH	CHAR,-^D29	;YES, MOVE IT OVER
	ANDI	CHAR,177	;DOWN TO ASCII
	ILDB	SCR,OLD		;AND CURRENT SCREEN ENTRY
	SKIPE	REFING		;DOING SCREEN REFRESH
	  SETZ	SCR,		;YES, OLD SCREEN CONTENTS = NULL
	CAMLE	NC,NCEND	;OFF THE END OF THE DISPLAY
	  MOVE	CHAR,SCR	;YES, DISPLAY SELF TO KEEP POINTERS STRAIGHT
	CAIGE	CHAR," "	;DISPLAYING A CONTROL CHARACTER
	  MOVEI	CHAR," "	;YES, TURN THEM INTO BLANKS
	CAIE	CHAR," "	;SHOWING A BLANK
	  JRST	M2.1		;NO, LOOK SOME MORE
	SKIPN	WHERA		;ALREADY FIND FIRST BLANK
	  MOVEM	NC,WHERA	;REMEMBER FIRST BLANK
	CAIN	SCR," "		;WAS COLUMN ALREADY BLANKED
	  AOJA	NC,M2		;YES, TRY NEXT COLUMN
	DPB	CHAR,OLD	;STORE INTO CURRENT SCREEN NOW
	SKIPN	WHCHR		;THIS THE FIRST CHANGE TO A BLANK
	  MOVEM	NC,WHCHR	;REMEMBER FIRST CHANGE
	MOVEM	NC,WHLST	;REMEMBER LAST CHANGE TO A BLANK TOO
	AOJA	NC,M2		;AND GO LOOK AT THE NEXT

M2.1:	SETZM	WHERA		;CAN'T ERASE NOW
	SKIPN	WHCHR		;DID A CHANGE TO A BLANK OCCUR
	  JRST	M2.2		;NO, WE DON'T OWE IT ANY CHANGES
	PUSH	P,NC		;SAVE CURRENT COLUMN
	MOVE	NC,WHCHR	;GET WHERE THE FIRST CHANGE OCCURED
	PUSHJ	P,CURMOV	;POSITION CURSOR THERE
	AOS	NC,WHLST	;FIND BEYOND LAST CHANGE TO A BLANK
	SETOM	FRCRTY		;FORCE RE-TYPE OF LINE
	PUSHJ	P,CURMOV	;GET THERE BY RE-TYPING
	SETZM	WHCHR		;AND NOW, NO CHANGES
	POP	P,NC		;RESTORE CURRENT
	SKIPE	REFING		;DOING A REFRESH CYCLE
	 TDZA	SCR,SCR		;YES, OLD SCREEN = A NULL
	  LDB	SCR,OLD		;GET OLD SCREEN CONTENTS BACK AFTER MOVING
M2.2:	CAMN	CHAR,SCR	;DISPLAYING THE SAME CHARACTER
	  AOJA	NC,M2		;YES, FORGET OUTPUT
	PUSHJ	P,CURMOV	;MOVE FROM "POSL,POSC" TO "NL,NC"
	DPB	CHAR,OLD	;STORE INTO CURRENT SCREEN NOW
	PUSHJ	P,DPYPUT	;OUTPUT IT
	MOVE	CUR,OLD		;REMEMBER WHERE WE ARE NOW
	AOS	POSC		;AND ADJUST CURSOR POSITION
	AOJA	NC,M2		;AND GET NEXT COLUMN
REMRET:	SKIPN	REMEMB		;WANT TO REMEMBER POSITION
FORGET:	SETO	POSL,		;AND FORGET POSITION INFO
FRCRET:	SETZM	REMEMB		;CLEAR REMEMBER FLAG
	JSP	CHAR,RESREG	;RESTORE CALLERS REGISTERS
	SKIPN	LINPTR		;AVOID OUTSTR IF NO CHANGES THIS SWEEP
	  POPJ	P,		;RETURN, NO OUTPUT TO DO
FRCOUT:	SETZM	LINPTR		;CLEAR CURRENT LINE IN CORE
IF TOPS-10,<OUTSTR LINBUF>	;OUTPUT THE LINE BUFFER
IF TOPS-20,<
	PUSH	P,SCR		;SAVE CALLERS
	PUSH	P,SCR+1		;...
	PUSH	P,SCR+2		;...
	PUSH	P,SCR+3		;...
	MOVE	SCR,TTYJFN	;IMAGE MODE OUTPUT JFN
	MOVE	SCR+1,[POINT TTYBYT,LINBUF]
	SETZB	SCR+2,SCR+3	;STOP ON A NULL
	SOUT			;OUTPUT IT
	MOVE	SCR+1,[1,,1]	;HACK FOR NOW, SET POS TO 1,,1
	SFPOS			;EVENTUALLY I'LL SET TO WHERE CURSOR IS
	POP	P,SCR+3		;RESTORE CALLERS
	POP	P,SCR+2		;...
	POP	P,SCR+1		;...
	POP	P,SCR		;...
>  ;END IF IF TOPS-20
CPOPJ:	POPJ	P,		;AND RETURN
;SUBROUTINE TO MOVE THE CURSOR
;
;	POSL = LINE WHERE CURSOR IS
;	POSC = COLUMN "     "    "
;
;	NL = LINE WHERE WE WANT TO BE
;	NC = COLUMN "   "    "  "  "

CURMOV:	PUSH	P,CHAR		;SAVE CALLERS CHARACTER
	SKIPE	FRCRTY		;FORCED TO RE-TYPE IN RIGHT MOVEMENT
	  JRST	[SETZM FRCRTY	;YES, CLEAR INDICATOR
		 JRST MOV.3]	;AND MOVE IT ( ALREADY ON THE SAME LINE )
MOV.0:	CAMN	POSL,NL		;AT THE CORRECT LINE
	  JRST	MOV.1		;YES, END OF VERTICAL POSITIONING
	SKIPE	DIRADR(TYP)	;CAN TERMINAL DIRECT ADDRESS
	  JRST	MOVDIR		;YES, DO IT NOW SINCE NOT ON RIGHT LINE
	CAML	POSL,NL		;MOVING UP
	  JRST	MOV.01		;YES, DO THAT
	MOVEI	CHAR,LINEFD(TYP);LINE FEED
	PUSHJ	P,PUTCTL	;OUTPUT THE DOWN SEQUENCE
	TLO	CUR,77		;BYTE POINTER IS INVALID NOW
	AOJA	POSL,MOV.0	;ADJUST AND GET THE NEXT COLUMN
MOV.01:	MOVE	SCR,POSL	;GET CURRENT POSITION
	SUB	SCR,NL		;DIFFERENCE = NUMBER OF UP MOVES
	CAILE	SCR,-1(NL)	;IS HOME POSITION CLOSER
	  JRST	[PUSHJ P,HOME	;GET TO THE HOME POSITION
		 JRST MOV.0]	;NOW GOING THE OTHER WAY
	MOVEI	CHAR,CURUP(TYP)	;GET UP SEQUENCE
	PUSHJ	P,PUTCTL	;OUTPUT THAT
	TLO	CUR,77		;BYTE POINTER IS INVALID NOW
	SOJA	POSL,MOV.0	;CONTINUE MOVING

MOV.1:	CAMN	POSC,NC		;AT THE CORRECT COLUMN
	  JRST	MOVEND		;YES, WE ARE THERE
	CAIN	NC,1		;WANT BACK AT THE LEFT MARGIN
	  JRST	MOV.2		;YES, GO DO THAT NOW
	MOVE	SCR,POSC	;GET CURRENT
	SUB	SCR,NC		;HOW MANY AWAY FROM TARGET
	MOVMS	SCR		;IGNORE SIGN PROBLEMS
	SKIPE	DIRADR(TYP)	;CAN TERMINAL DIRECT CURSOR ADDRESS
	 CAIG	SCR,4		;YES, BUT IS MOVEMENT SLIGHT
	  SKIPA			;DO IT THE HARD WAY
	   JRST	MOVDIR		;GO DIRECT MOVE
	CAMGE	NC,POSC		;WANT LEFT OF CURRENT
	 CAMG	SCR,NC		;AND CLOSER TO THE LEFT MARGIN
	  JRST	MOV.3		;NO, CANNOT USE CARRIAGE RETURN
MOV.2:	MOVEI	CHAR,15		;A CARRIAGE RETURN
	PUSHJ	P,DPYPUT	;OUTPUT IT
	TLO	CUR,77		;MARK UNKNOWN POSITION
	MOVEI	POSC,1		;NOW AT COLUMN 1
MOV.3:	CAMLE	POSC,NCOLS(TYP)	;BUMPED AGAINST THE RIGHT MARGIN
	  JRST	[MOVE POSC,NCOLS(TYP) ;YES, THEN WE ARE THERE
		 TLO CUR,77	;BYTE POINTER IS INVALID NOW
		 JRST .+1]	;RESUME IN-LINE CODE
	MOVE	SCR,POSC	;GET CURRENT COLUMN
MOV.4:	CAMG	SCR,NC		;HIT SPOT YET
	  JRST	MOV.5		;YES, NOW LOOK THE OTHER WAY
	MOVEI	CHAR,CLEFT(TYP)	;GET CURSOR LEFT SEQUENCE
	PUSHJ	P,PUTCTL	;OUTPUT THE STRING
	TLO	CUR,77		;MARK UNKNOWN POSITION
	MOVE	POSC,NC		;IN CASE THIS IS THE LAST ITERATION
	SOJA	SCR,MOV.4	;DRIVE THIS LOOP BACKWARDS
MOV.5:	CAMN	POSC,NC		;AT THE CORRECT SPOT
	  JRST	MOVEND		;YES, WE ARE FINALLY THERE
	TLNE	CUR,77		;BYTE POINTER CORRECT
	  PUSHJ	P,SETCUR	;NO, GO FIX IT
	ILDB	CHAR,CUR	;GET WHAT IS ALREADY THERE
	PUSHJ	P,DPYPUT	;OUTPUT IT
	AOJA	POSC,MOV.5	;AND CONTINUE MOVING RIGHT BY RE-TYPING
MOVDIR:	MOVEI	CHAR,DIRADR(TYP);POINT TO ADDRESSING SEQUENCE
	PUSHJ	P,PUTCTL	;OUTPUT START SEQUENCE
IFDEF %VT100,<
	CAIN	TYP,.VT100	;VT100 TAKES ASCII CHARACTER POSITIONS
	  JRST	VT100M		;SO GO OUTPUT THEM
>
	MOVEI	CHAR,-1(NL)	;GET LINE NUMBER ( 0 TO NLINES-1 )
IFN REVDIR,<			;IF SOME TERMINAL WANTS COLUMN THEN LINE
	MOVE	POSC,DIRADR(TYP);GET ADDRESSING SEQUENCE (BIT 35 IS FLAG)
	TRNE	POSC,1		;TERMINAL TAKE COLUMN FIRST
	  MOVEI	CHAR,-1(NC)	;YES, COLUMN INSTEAD
>
	XCT	COMPXY(TYP)	;COMPUTE CHARACTER FOR TERMINAL
	PUSHJ	P,DPYPUT	;OUTPUT IT
IFDEF %VT05,<			;IF SUPPORTING VT05'S
	CAIN	TYP,.VT05	;VT05 NEEDS SPECIAL HANDLING
	  PUSHJ	P,VT05FL	;OUTPUT NULLS FOR FILLER
>
	MOVEI	CHAR,-1(NC)	;GET COLUMN NUMBER ( 0 TO NCOLS-1 )
IFN REVDIR,<			;DOES SOMEBODY TAKE LINE SECOND
	TRNE	POSC,1		;TERMINAL WANT LINE LAST
	  MOVEI	CHAR,-1(NL)	;YES, GET LINE INSTEAD
>
	XCT	COMPXY(TYP)	;COMPUTE CHARACTER FOR TERMINAL
MOVXIT:	PUSHJ	P,DPYPUT	;OUTPUT THAT
	MOVE	POSC,NC		;RESET CURRENT POINTS
	MOVE	POSL,NL		;...
	TLO	CUR,77		;BYTE POINTER IS NOW INVALID
MOVEND:	POP	P,CHAR		;RESTORE CALLERS AFTER MOVING
	POPJ	P,		;AND RETURN
;SUBROUTINE TO TRY AN ERASE TO END OF LINE

CLRLIN:	SOS	NL		;ALWAYS CALLED FOR PREVIOUS LINE
	SETZ	SCR,		;CLEAR A REG
	EXCH	SCR,WHCHR	;ANYTHING GET TURNED INTO A BLANK
	JUMPE	SCR,CLRL.2	;NO, THEN NO NEED FOR ERASE
	MOVE	NC,WHERA	;COLUMN WHERE FIRST BLANK APPEARED
	CAML	NC,POSC		;FIRST BLANK RIGHT OF CURSOR
	  JRST	CLRL.1		;YES, CLEAR FROM THERE
	CAML	SCR,POSC	;FIRST CHANGE RIGHT OF CURSOR
	  JRST	[MOVE NC,POSC	;YES, JUST NEED TO MOVE DOWN
		 JRST CLRL.1]	;GO CLEAR
	MOVE	CHAR,POSC	;FIND CLOSEST POINT
	SUB	CHAR,NC		;SAME AS MOV.1
	CAMLE	CHAR,NC		;WOULD <CR> BE CLOSER THAN BACKSPACE
	  MOVE	CHAR,NC		;YES, REMEMBER THAT
	MOVEM	CHAR,WHERA	;STORE IN A TEMP FOR NOW
	MOVE	CHAR,POSC	;WHERE DID FIRST CHANGE TO A BLANK OCCUR
	SUB	CHAR,SCR	;AND WHERE WE ARE NOW
	MOVMS	CHAR		;WANT .ABS. OF THAT
	CAMG	CHAR,WHERA	;WHICH IS CLOSER TO CURRENT POINT
	  MOVE	NC,SCR		;FIRST BLANK
CLRL.1:	CAMLE	NC,NCOLS(TYP)	;OFF THE RIGHT HAND SIDE ANYWAY
	  JRST	CLRL.2		;YES, WON'T SEE IT
ERSLIN:	PUSHJ	P,CURMOV	;MOVE THE CURSOR TO THE SPOT FOR ERASE
	MOVEI	CHAR,ERAEOL(TYP);ERASE SEQUENCE
	PUSHJ	P,PUTCTL	;OUTPUT CONTROL SEQUENCE
CLRL.2:	SETZM	WHERA		;MARK CLEAR DONE
	AOJA	NL,CPOPJ	;RESTORE THIS LINE AND RETURN

;SUBROUTINE TO BUILD BYTE POINTER TO REFLECT "POSL,POSC"

SETCUR:	MOVEI	CHAR,-1(POSL)	;CURRENT LINE ON SCREEN
	IMULI	CHAR,NCMAX	;COMPUTE DOUBLE SUBSCRIPT
	ADDI	CHAR,-1(POSC)	;INCLUDE COLUMN
	IDIVI	CHAR,5		;NOW FIND CORRECT WORD AND BYTE
	MOVEI	CUR,SCREEN	;BASE OF THE SCREEN
	ADD	CUR,CHAR	;MOVE ENOUGH WORDS
	HLL	CUR,CURPTR(SCR)	;AND INSERT POSITION INFORMATION
	POPJ	P,		;RETURN FOR "ILDB/IDPB"

;SUBROUTINE TO SET "OLD" TO REFLECT "NL,NC"

FIXOLD:	MOVEI	CHAR,-1(NL)	;SAME CODE AS SETCUR
	IMULI	CHAR,NCMAX	; BUT CAN'T USE THAT SUBROUTINE
	ADDI	CHAR,-1(NC)	; CAUSE I HAVE TO SAVE POSL,POSC
	IDIVI	CHAR,5		; AND IT WORKS OUT TO THE SAME NUMBER
	MOVEI	OLD,SCREEN	; OF INSTRUCTIONS, SO.....
	ADD	OLD,CHAR	;...
	HLL	OLD,CURPTR(SCR)	;AT LEAST I CAN USE THE SAME TABLE
	POPJ	P,
;SUBROUTINE TO OUTPUT CONTROL SEQUENCES TO TERMINALS

;SUBROUTINE TO PLACE CURSOR AT THE HOME POSITION ( MAYBE )

GOHOME:	TLO	CUR,77		;BYTE POINTER IS INVALID
	JUMPG	POSL,CPOPJ	;RETURN IF REMEMBERED POINT
	SKIPN	DIRADR(TYP)	;CAN TERMINAL DIRECT ADDRESS
	  JRST	HOME		;NO, DO IT THE HARD WAY
	MOVEI	POSL,^D32768	;FOR DIRECT MOVEMENT IN CURMOV
	POPJ	P,		;RETURN

HOME:	MOVEI	POSL,1		;CURSOR IS AT LINE 1
	MOVEI	POSC,1		;COLUMN 1
	MOVEI	CHAR,HOMEUP(TYP);GOTO TOP OF SCREEN
PUTCTL:	HRLI	CHAR,(POINT 7,0);INSERT BYTE INFO
	MOVEM	CHAR,PUTPTR	;SAVE POINTER
PUTC.1:	ILDB	CHAR,PUTPTR	;GET CHARACTER IN SEQUENCE
	JUMPE	CHAR,CPOPJ	;STOP AT A NULL
IFN DOFILL,<			;IF SOME TERMINAL NEEDS FILLERS
	CAIN	CHAR,177	;REQUEST FOR FILLERS
	  JRST	PUTC.2		;DO THEM
>
	PUSHJ	P,DPYPUT	;OUTPUT THE CHARACTER
	JRST	PUTC.1		;RESUME LOOP
IFN DOFILL,<
PUTC.2:	MOVE	CHAR,FILLRS	;GET -NUMBER OF FILLERS,,0
	JUMPE	CHAR,PUTC.1	;NONE AT THIS SPEED
	HRRI	CHAR,TTYFIL	;GET FILLER CHARACTER
	PUSHJ	P,DPYPUT	;OUTPUT IT
	AOBJN	CHAR,.-2	;DO AS MANY AS NEEDED
	JRST	PUTC.1		;AND RESUME FROM THE CONTROL STRING
>

;SUBROUTINE TO STUFF "CHAR" INTO INTERMEDIATE BUFFER FOR DISPLAY

DPYPUT:	SKIPE	LINPTR		;ANY CURRENT LINE
	  JRST	DPYP.1		;YES, GO INCLUDE CHARACTER
	PUSH	P,CHAR		;NO, SAVE CURRENT
	MOVE	CHAR,[POINT TTYBYT,LINBUF] ;GET BUFFER POINTER
	MOVEM	CHAR,LINPTR	;INITIALIZE POINTER
	MOVEI	CHAR,^D199	;CHARACTERS IN THE BUFFER
	MOVEM	CHAR,LINCNT	;AS THE LINE COUNTER
	SETZM	LINBUF		;CLEAR THE INCORE BUFFER NOW
	MOVE	CHAR,[LINBUF,,LINBUF+1]
	BLT	CHAR,LBUFND
	POP	P,CHAR		;RESTORE CHARACTER
DPYP.1:	SOSL	LINCNT		;ROOM IN THE BUFFER
	  JRST	[IDPB CHAR,LINPTR ;YES, ADD THE CHARACTER
		 POPJ P,]	;AND RETURN
	PUSHJ	P,FRCOUT	;NO, FORCE OUT THE BUFFER
	JRST	DPYPUT		;AND START AGAIN
;HERE TO HANDLE SPECIAL VT05 FILLERS FOR CURSOR ADDRESSING
;VT05 NEEDS FILLERS BETWEEN LINE NUMBER AND COLUMN NUMBER

IFDEF %VT05,<
VT05FL:
IF TOPS-10,<
	MOVE	CHAR,FILLRS	;DO IT THE HARD WAY HERE CAUSE I REALLY NEED NULLS
	JUMPE	CHAR,CPOPJ	;NOT NEEDED AT THIS SPEED
	PUSHJ	P,FRCOUT	;FORCE OUT THE CURRENT BUFFER
	SETZ	SCR,		;GET A NULL
	IONEOU	SCR		;IMAGE OUTPUT A NULL
	AOBJN	CHAR,.-1	;OUTPUT AS MANY AS NEEDED
	POPJ	P,		;THEN RETURN
> ;END IF TOPS-10
IF TOPS-20,<
	MOVEI	CHAR,[BYTE (7)177] ;ASK FOR FILLERS (WILL BE IMAGE NULLS LATER)
	JRST	PUTCTL		;OUTPUT FILLERS
> ;END IF TOPS-20
> ;END IFDEF

;VT100 TAKES ASCII LINE AND COLUMN SEQUENCE, OUTPUT IT HERE

IFDEF %VT100,<
VT100M:	PUSH	P,CHAR+1	;SAVE AC FROM DIVIDES
	MOVEI	CHAR,(NL)	;GET LINE
	PUSHJ	P,VT100D	;OUTPUT LINE NUMBER
	MOVEI	CHAR,";"	;SEPARATE WITH SEMICOLON
	PUSHJ	P,DPYPUT	;STUFF THAT IN
	MOVEI	CHAR,(NC)	;NOW COLUMN NUMBER
	PUSHJ	P,VT100D	;INCLUDE THAT
	POP	P,CHAR+1	;RESTORE AC
	MOVEI	CHAR,"H"	;END OF SEQUENCE
	JRST	MOVXIT		;SEND IT AND CLEAN UP

VT100D:	IDIVI	CHAR,^D10	;CONVERT TO DECIMAL LINE/COLUMN NUMBERS
	HRLM	CHAR+1,(P)	;STANDARD STUFF HERE
	SKIPE	CHAR		;DONE YET
	  PUSHJ	P,VT100D	;NO, RECURSE A LITTLE
	HLRZ	CHAR,(P)	;GET DIGIT
	ADDI	CHAR,"0"	;TO ASCII
	JRST	DPYPUT		;INCLUDE IN BUFFER, GET ANOTHER (MAYBE)
>
;SAVE AND RESTORE SEQUENCES

SAVREG:	PUSH	P,CUR		;SAVE CALLERS REGS
	PUSH	P,NEW		;...
	PUSH	P,OLD		;...
	PUSH	P,NL		;...
	PUSH	P,NC		;...
	EXCH	POSL,CURL	;SAVE OLD, GET NEW
	EXCH	POSC,CURC	;...
	EXCH	TYP,VIDEOT	;...
	JUMPL	TYP,INIERR	;ERROR IF NEVER DEFINED TERMINAL TYPE
	JRST	@CHAR		;RETURN TO CODE

RESREG:	EXCH	POSL,CURL	;SAVE COMPUTED, RESTORE OLD
	EXCH	POSC,CURC	;...
	EXCH	TYP,VIDEOT	;...
	POP	P,NC		;RESTORE CALLERS REGISTERS
	POP	P,NL		;...
	POP	P,OLD		;...
	POP	P,NEW		;...
	POP	P,CUR		;...
	JRST	@CHAR		;RETURN TO CODE

;TABLE OF BYTE POINTERS FOR "SETCUR" AND "FIXOLD"

CURPTR:	440700,,0		;FOR CHARACTER 1
	350700,,0		; "     "      2
	260700,,0		; "     "      3
	170700,,0		; "     "      4
	100700,,0		; "     "      5
IF TOPS-10,<

NOCRLF:	.TOSET+.TONFC		;SET NO FREE CRLF
UDX:	EXP	0,1		;UDX FILLED IN, SET TO 1 = NOCRLF

GTTYP:	.TOTRM			;GET TERMINAL TYPE
UDX1:	EXP	0,0		;UDX FILLED IN, DUMMY

NOPAGE:	EXP	.TOSET+.TOPSZ	;SET PAGE SIZE 0
UDX2:	EXP	0,0		;UDX FILLED IN, PAGE 0

IFN DOFILL,<
GETSPD:	.TOTSP			;GET TERMINAL OUTPUT SPEED
UDX3:	EXP	0,0		;UDX FILLED IN, DUMMY
>

TRMERR:	OUTSTR	[ASCIZ/?CANNOT SET TTY NO CRLF IN "DPYINI"/]
	JRST	ERRXIT

IONERR:	OUTSTR	[ASCIZ/?CANNOT FIND TERMINAL INDEX IN "DPYINI"/]
	JRST	ERRXIT

INIERR:	OUTSTR	[ASCIZ/?DPYPAK NEVER INITIALIZED/]
ERRXIT:	EXIT	1,		;REMOVE AND RETURN ERROR = -1 WHEN
	JRST	.-1		;DPYINI RETURNS TERMINAL HANDLES

>  ;END OF IF TOPS-10


IF TOPS-20,<
NOTTY:	SKIPA	SCR,[-1,,[ASCIZ\?DPYPAK COULDN'T GTJFN/OPENF THE TTY\]]
INIERR:	HRROI	SCR,[ASCIZ/?DPYPAK NEVER INITIALIZED/]
	PSOUT			;OUTPUT THE ERROR
	HALTF			;REMOVE AND RETURN ERROR = -1 WHEN
	JRST	.-1		;DPYINI RETURNS TERMINAL HANDLES

>  ;END OF IF TOPS-20
;SUBROUTINE TO SET JOBS TTY THE WAY DPYPAK WANTS THEM
;RETURNS SCR = THE TERMINAL TYPE IF THIS MONITOR KNOWS IT

GETTYP:
IF TOPS-10,<
	MOVSI	CHAR,'TTY'	;GET CALLERS TTY NUMBER
	IONDX.	CHAR,		;ASK THE MONITOR
	  JRST	IONERR		;CAN'T FIND OUT
	MOVEM	CHAR,UDX	;STUFF INTO ARG BLOCK
	MOVEM	CHAR,UDX1	;STUFF AGAIN
	MOVEM	CHAR,UDX2	;STUFF AGAIN
IFN DOFILL,<MOVEM CHAR,UDX3>	;STUFF AGAIN
	MOVE	CHAR,[3,,GTTYP]	;GET ARGUMENT POINTERS
	TRMOP.	CHAR,		;ASK FOR SET TERMINAL TYPE
	  SETZ	CHAR,		;NONE, SET UNKNOWN TYPE
>  ;END OF IF TOPS-10
IF TOPS-20,<
	PUSH	P,SCR+1		;KEEP SAFE FROM JSYS'ES
	MOVEI	SCR,.PRIOU	;FOR CURRENT TERMINAL
	GTTYP			;GET TERMINAL TYPE
	MOVE	CHAR,SCR+1	;WANT IT IN CHAR
	POP	P,SCR+1		;RESTORE AC'S
>  ;END OF IF TOPS-20
	MOVSI	SCR,-MAXTYP	;NUMBER OF KNOWN TYPES
	CAME	CHAR,TYPTAB(SCR) ;FOUND IT
	  AOBJN	SCR,.-1		;NO, KEEP LOOKING
	SKIPL	SCR		;DID WE FIND ONE
	 TDZA	SCR,SCR		;NO, CLEAR TERMINAL TYPE
	  MOVE	SCR,TYPNAM(SCR)	;YES, GET ITS REAL NAME
	POPJ	P,		;RETURN TO DPYINI


SETINI:
IF TOPS-10,<
	PUSH	P,CHAR		;SAVE CALLERS
	MOVE	CHAR,[3,,NOCRLF] ;GET ARGUMENT POINTERS
	TRMOP.	CHAR,		;SET TTY NO CRLF ( MONITOR COUNTS CHARS )
	  JRST	TRMERR		;CAN'T DO THAT ??
	MOVE	CHAR,[3,,NOPAGE] ;CLEAR PAGE COUNTER
	TRMOP.	CHAR,		;TRY IT
	  JFCL			;USER WILL JUST HAVE TO TYPE ^Q
IFN DOFILL,<			;ONLY IF SOME TERMINALS NEED FILLERS
	MOVE	SCR,[3,,GETSPD]	;GET OUTPUT SPEED
	TRMOP.	SCR,		;GET ENCODED SPEED
	  SETZ	SCR,		;OH WELL
	SKIPG	SCR		;DID I GET ONE
	 TDZA	CHAR,CHAR	;NO, CLEAR SPEED
	  MOVE	CHAR,[EXP ^D50,^D75,^D110,^D134,^D150,^D200,^D300,^D600
		     EXP ^D1200,^D1800,^D2400,^D4800,^D9600,^D9600,^D9600]-1(SCR)
	MOVEM	CHAR,BAUD	;STORE INTERESTING NUMBER
	IDIVI	CHAR,^D600	;RECOMMENDED CONVERSION
	MOVNS	CHAR		;GET - NUMBER NEEDED
	HRLZM	CHAR,FILLRS	;REMEMBER NUMBER OF FILLERS NEEDED
	POP	P,CHAR		;RESTORE
	POPJ	P,		;RETURN
> ;END IFN DOFILL
> ;END IF TOPS-10
IF TOPS-20,<
	PUSH	P,SCR+1		;KEEP SAFE FROM JSYS'ES
	MOVSI	SCR,1		;SHORT GTJFN
	HRROI	SCR+1,[ASCIZ/TTY:/]
	GTJFN			;GET HANDLE FOR THE TERMINAL
	  JRST	NOTTY		;CAN'T GET THE TTY?
	HRRZM	SCR,TTYJFN	;SAVE JFN ACQUIRED
	MOVE	SCR+1,[100000,,100000] ;8 BIT MODE, WRITE
	OPENF			;OPEN THE TTY
	  JRST	NOTTY		;WHAT?
IFN DOFILL,<			;ONLY IF SOME TERMINALS NEED FILLERS
	PUSH	P,SCR+2		;KEEP SAFE FROM JSYS'ES
	MOVEI	SCR,.PRIOU	;FOR CURRENT TERMINAL
	MOVEI	SCR+1,.MORSP	;FUNCTION RETURN BAUD RATES
	MTOPR			;GET THEM
	SKIPGE	SCR+2		;RATE KNOWN
	 SKIPA	SCR,[^D2400]	;NO, SAY 2400 (PROBABLY A PTY)
	  HRRI	SCR,(SCR+2)	;YES, GET OUTPUT SPEED
	HRRZM	SCR,BAUD	;STORE INTERESTING NUMBER
	IDIVI	SCR,^D600	;RECOMMENDED CONVERSION
	MOVNS	SCR		;GET - NUMBER NEEDED
	HRLZM	SCR,FILLRS	;REMEMBER NUMBER OF FILLERS NEEDED
	POP	P,SCR+2		;RESTORE AC'S
> ;END IFN DOFILL
	POP	P,SCR+1		;RESTORE AC'S
	POPJ	P,		;RETURN
> ;END IF TOPS-20
;SCRATCH STORAGE
IF TOPS-20,<
TTYJFN:	.PRIOU			;JFN FOR TTY: (STARTS AS TTY, FILLED IN BY OPEN)
>
BAUD:	0			;BAUD RATE FOR TERMINAL
FILLRS:	0			;NUMBER OF FILLERS NEEDED IF REQUESTED
REFING:	0			;FLAG FOR REFRESHING A SCREEN
CLRING:	0			;FLAG FOR CLEARING A SECTION
REMEMB:	0			;FLAG FOR REMEMBERING
WHERA:	0			;COLUMN OF FIRST BLANK ON A LINE
WHLST:	0			;COLUMN OF LAST CHANGE TO A BLANK ON A LINE
WHCHR:	0			;COLUMN OF FIRST CHANGE TO A BLANK
PUTPTR:	0			;BYTE POINTER DURING PUTCTL
FRCRTY:	0			;-1 IF FORCED TO RE-TYPE DURING RIGHT MOVEMENT
LINPTR:	0			;POINTER FOR INCORE LINE
LINCNT:	0			;AMOUNT OF ROOM LEFT IN BUFFER
LINBUF:	BLOCK	<^D200/TTYCPW>	;ROOM FOR 199 CHARACTERS + 1 NULL
LBUFND==.-1			;END OF THE LINE BUFFER

;SCREEN SPECIFIC INFORMATION

BOUNDS:	0			;NEED TO SET BOUNDRIES
NLPRIM:	0			;1ST LINE OF SCREEN SWEEP
NCPRIM:	0			;1ST COLUMN
NLEND:	0			;LAST LINE OF SCREEN SWEEP
NCEND:	0			;LAST COLUMN
ENDUSR:	0			;LAST COLUMN (ROUNDED) OF USERS ARRAY
LJUST:	0			;-1 FOR LEFT JUSTIFIED ( A1 ) FORMAT
CURL:	-1			;WHERE WE LEFT THE CURSOR
CURC:	0			;  "   "    "   "    "
VIDEOT:: -1			;VIDEO TERMINAL TYPE
NEWPTR:	POINT	0,0		;SIZE FILLED IN DURING "DPYINI"
SCREEN:	BLOCK	<WDPLIN*NLMAX>	;ROOM FOR A SCREEN
ENDSCR==.-1			;LAST LOC OF THE SCREEN

	END			;END OF DPYPAK