Google
 

Trailing-Edge - PDP-10 Archives - BB-M836B-BM - tools/sysdpy/dpy.mac
There are 24 other files named dpy.mac in the archive. Click here to see a list.
	TITLE	DPY	MODULE TO MAKE CRT DISPLAYS EASY
	SUBTTL	DEFINITIONS



;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
;  OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) 1976,1977,1978,1979 BY DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.



;THIS MODULE IS USED TO PRODUCE A CONSTANTLY UPDATING DISPLAY.
;COMMUNICATION BETWEEN IT AND THE CALLING PROGRAM IS BY LUUOS.  THIS
;MODULE CAN RUN ON VARIOUS KINDS OF TERMINALS.  THE FILE DPYDEF.MAC
;CONTAINS ALL OF THE NECESSARY DEFINITIONS.



	TWOSEG	400000		;ALWAYS MAKE PROGRAM TWO SEGMENTS
	SALL			;MAKE GOOD LOOKING MACROS
	ENTRY	DPYUUO		;DEFINE ENTRY POINT
	INTERN	DPYTAB		;AND THE TABLE
	SEARCH	DPYDEF		;GET BIT DEFINITIONS



	VERSION==3		;THIRD VERSION OF DPY
	EDIT==171		;EDIT NUMBER


	IFNDEF	FTDEC20,<FTDEC20==1>	;ON FOR TOPS-20, OFF FOR TOPS-10



	DEFINE	IF10,<IFE FTDEC20>	;SHORTHAND CONDITIONALS
	DEFINE	IF20,<IFN FTDEC20>



	IF10,<	SEARCH	UUOSYM	>	;IF TOPS-10, GET SYMBOLS
	IF20,<	SEARCH	MONSYM	>	;IF TOPS-20, GET SYMBOLS
	SUBTTL	ACCUMULATORS AND FLAGS




;ACCUMULATORS.  THE USER AC'S ARE ALWAYS PRESERVED.  AC "U" IS ASSUMED
;TO BE THE LAST NON-STACK AC ALWAYS.  IF ANOTHER AC IS EVER DEFINED,
;THEN ALSO CHANGE THE AC SAVING AREAS AT THE END OF THE PROGRAM.


	F=0		;FLAG BITS
	T1=1		;TEMPORARY USE
	T2=2
	T3=3
	T4=4
	X=5		;INDEX TO DATA TABLE
	C=6		;CHARACTER HOLDING
	A=7		;USER'S LUUO AND ADDRESS TO GET WORDS FROM
	L=10		;PRESENT LINE NUMBER BEING OUTPUT TO
	N=11		;PRESENT COLUMN NUMBER BEING OUTPUT TO
	B=12		;BYTE POINTER INTO SCREEN ARRAY
	U=13		;ADDRESS OF TERMINAL BLOCK
	P=17		;STACK POINTER



;FLAGS IN RIGHT HALF OF AC F.  ALL OF THESE BITS ARE TERMINAL
;CHARACTERISTIC FLAGS, SET WHEN INITIALIZING THE TERMINAL TYPE.


	FR.XBY==1	;IN ADDRESSING, X COORDINATE GOES BEFORE Y
	FR.TAB==2	;TERMINAL HAS NORMAL TAB STOPS
	FR.ELC==4	;TERMINAL DOES CRLF WHEN LAST COLUMN IS REACHED
	FR.RAI==10	;LOWER CASE IS SAME AS UPPER CASE
	FR.ANS==20	;THIS IS AN ANSI STANDARD TERMINAL
	FR.TTY==40	;THIS IS A NON-VIDEO TERMINAL


;FLAGS IN THE LEFT HALF OF AC F.  THESE BITS ARE STATUS BITS.


	FL.OUT==1	;THERE HAS BEEN OUTPUT IN CURRENT WINDOW
	FL.PNT==2	;TERMINAL NEEDS TO HAVE OUTPUT FORCED LATER
	FL.ACR==4	;WE ARE IN AUTO-CARRIAGE RETURN MODE
	FL.AC2==10	;SAME AS FL.ACR, BUT TEMPORARY
	FL.INI==20	;INI$ FUNCTION HAS BEEN DONE
	FL.OKU==40	;IT IS OK TO UPDATE THE SAME LOCATION TWICE
	FL.NZP==100	;DON'T CLEAR REST OF WINDOWS
	FL.NOS==200	;DON'T SAVE USER ACS WHEN GIVING CHARS TO HIM
;USEFUL CHARACTER DEFINITIONS:


	LF==12			;LINE FEED
	CR==15			;CARRIAGE RETURN
	TAB==11			;TAB
	ALT==33			;STANDARD ALTMODE
	SP==40			;SPACE
	RUB==177		;RUBOUT
	NUL==0			;NULL



;OTHER DEFINITIONS:



	DEFINE	CL(CHAR),<"CHAR"-100>	;TO DEFINE CONTROL CHARACTERS
	OPDEF	PJRST	[JRST]		;USUAL


	TTYLEN==^D20		;SIZE OF TERMINAL BUFFER
	UPDATE==200		;FLAG MEANING CHARACTER NEEDS UPDATING
	PRETTY==3		;NUMBER OF CHARS EXTRA FOR GOOD LOOKS
	DFTTRM==.ASR33		;DEFAULT TERMINAL TYPE
	SUBTTL	MACRO USED TO DEFINE TERMINAL TYPES



;THE FOLLOWING MACRO IS USED TO DEFINE THE PARAMETERS OF EACH TERMINAL
;WHICH WE CAN RUN ON.  IT EXPANDS INTO A BLOCK OF WORDS WHICH CONTAIN
;THE CONSTANTS APPLICABLE TO EACH PARTICULAR TERMINAL.


DEFINE	TTY(NAME,TYP10,TYP20,LENGTH,WIDTH,FLAGS,MAXCHR,EATCHR,LFTSEQ,
RHTSEQ,UPSEQ,DWNSEQ,CRSEQ,HOMSEQ,CLRSEQ,EOLSEQ,EOFSEQ,ADRSEQ,AD2SEQ,
AD3SEQ,XOFFV,YOFFV),<


.'NAME:	ADDR==.				;;DEFINE DATA BLOCK ADDRESS

XX	TYP,<TYPNUM TYP10,TYP20>	;;TERMINAL TYPE NUMBER
XX	FLAG,<FLG <FLAGS>>		;;FLAGS
XX	LEN,<DFT ^D<LENGTH-1>,^D23>	;;LENGTH OF SCREEN

	IFG <VAL+1-MAXLEN>,<MAXLEN==VAL+1>	;;REMEMBER NEW MAX
	VAL2==VAL+1			;;REMEMBER VALUE

XX	WID,<DFT ^D<WIDTH-1>,^D79>	;;WIDTH OF SCREEN

	VAL==<VAL+4>/4			;;GET WORDS PER LINE

XX	WRDS,<EXP VAL>			;;NUMBER OF WORDS PER LINE

	IFG <VAL-MAXWID>,<MAXWID==VAL>	;;REMEMBER NEW MAX
	VAL==VAL*VAL2			;;COMPUTE STORAGE NEEDED
	IFG <VAL-MAXARE>,<MAXARE==VAL>	;REMEMBER NEW MAX

XX	MAXC,<DFT MAXCHR,176>	;;HIGHEST PRINTING CHARACTER
XX	EATC,<DFT EATCHR," ">	;;CHAR WHICH EATS
XX	LEFT,SEQ <LFTSEQ>	;;SEQUENCE TO MOVE LEFT
XX	RHT,SEQ <RHTSEQ>	;;SEQUENCE TO MOVE RIGHT
XX	UP,SEQ <UPSEQ>		;;SEQUENCE TO MOVE UP
XX	DOWN,SEQ <DWNSEQ>	;;SEQUENCE TO MOVE DOWN
XX	CR,SEQ <CRSEQ>		;;SEQ TO DO A CARRIAGE RETURN
XX	HOM,SEQ <HOMSEQ>	;;SEQUENCE TO HOME UP
XX	CLR,SEQ <CLRSEQ>	;;SEQUENCE TO HOME UP AND CLEAR
XX	EOL,SEQ <EOLSEQ>	;;SEQUENCE TO ERASE END OF LINE
XX	EOF,SEQ <EOFSEQ>	;;SEQUENCE TO ERASE END OF FORM
XX	ADR,SEQ <ADRSEQ>	;;SEQUENCE TO START ADDRESSING
XX	ADR2,SEQ <AD2SEQ>	;;SEQUENCE FOR FILLS BETWEEN X AND Y
XX	ADR3,SEQ <AD3SEQ>	;;SEQUENCE FOR FILLS AFTER ADDRESSING
XX	XOFF,<DFT XOFFV,40>	;;OFFSET FOR X COORDINATE
XX	YOFF,<DFT YOFFV,40>	;;OFFSET FOR Y COORDINATE

	APPEND	<	XWD	[ASCIZ/NAME/],.'NAME
>				;;ADD THIS TERMINAL TO CONCATENATED TEXT
>
;DEFINITION OF EMBEDDED XX MACRO.  FIRST ARGUMENT DEFINES THE
;OFFSET INTO THE BLOCK.  SECOND ARGUMENT DEFINES THE DATA FOR
;THIS LOCATION.


DEFINE XX(OFFSET,DATA),<

	T.'OFFSET==.-ADDR	;;DEFINE OFFSET INTO BLOCK
	DATA			;;THEN STORE THE DATA
>


;NOW DEFINE THE IMBEDDED DFT MACRO, TO GENERATE AN OCTAL WORD.
;THE FIRST ARGUMENT IS THE SYMBOL NAME, THE SECOND ARGUMENT IS
;THE DEFAULT VALUE IF NO SYMBOL WAS GIVEN.  THE SYMBOL VAL IS
;DEFINED AS THE RESULT OF THE MACRO.



DEFINE DFT(SYMBOL,VALUE),<

	VAL==VALUE		;;FIRST USE THE DEFAULT VALUE

  IFNB <SYMBOL>,<		;;IF A SYMBOL WAS GIVEN
	VAL==SYMBOL		;;THEN USE IT INSTEAD
  >
	EXP	VAL		;;THEN DUMP THE VALUE
>
;NOW DEFINE THE IMBEDDED FLG MACRO, TO GENERATE THE FLAG BITS
;FOR THE TERMINAL.  IT TAKES ONE ARGUMENT, MADE UP OF A SEQUENCE
;OF FLAGS.


DEFINE FLG(BITS),<

	BIT==0			;;INITIALIZE BITS

  IRP <BITS>,<			;;LOOP OVER ALL BITS
	BIT==BIT!FR.'BITS	;;ADD IN NEW BIT TO PREVIOUS ONES
  >
	EXP	BIT		;;DUMP THE FINAL RESULT
>




;NOW DEFINE THE TYPNUM MACRO, USED TO GENERATE THE PROPER TTY TYPE.
;THE FIRST ARGUMENT IS USED IF WE ARE RUNNING ON TOPS-10, THE SECOND
;ONE IF WE ARE RUNNING ON TOPS-20.



DEFINE TYPNUM(VAL10,VAL20),<

IF10,<	EXP	SIXBIT/VAL10/>	;IF TOPS-10, GENERATE THIS
IF20,<	DFT	VAL20,377777>	;;IF TOPS-20, GENERATE THIS
>
;NOW DEFINE THE IMBEDDED SEQ MACRO.  IT TAKES ONE ARGUMENT,
;MADE UP OF A SEQUENCE OF CHARACTERS.  A WORD IS GENERATED IN THE
;FORM ADDR,,N WHERE N IS THE NUMBER OF CHARACTERS, AND ADDRESS IS
;THE ADDRESS OF THE STRING OF CHARACTERS.


DEFINE SEQ(CHARS),<

	CNT==0				;;START COUNT AT ZERO
	IRP	<CHARS>,<CNT==CNT+1>	;;LOOP OVER CHARS COUNTING THEM

  IFE CNT,<				;;IF NO CHARACTERS
	EXP	0			;;THEN PRODUCE JUST A ZERO WORD
  >

  IFN CNT,<				;;IF ANY CHARACTERS
	XWD	[			;;START LITERAL
	WORD==0				;;INITIALIZE WORD TO ZERO
	SHIFT==^D29			;;INITIALIZE SHIFT VALUE

    IRP <CHARS>,<			;;LOOP OVER ALL CHARS AGAIN
	WORD==WORD+<<CHARS>_SHIFT>	;;ADD NEW CHAR INTO WORD
	SHIFT==SHIFT-7			;;LESSEN SHIFT BY A CHAR

      IFL SHIFT,<			;;IF THE WORD IS FULL
	EXP	WORD			;;DUMP COMPLETED WORD OF CHARS
	WORD==0				;;RESET THE WORD
	SHIFT==^D29			;;AND THE SHIFT VALUE
      >
    >					;;END OF LOOP OVER CHARS

    IFN <SHIFT-^D29>,<			;;SEE IF ANY PARTIAL WORD LEFT
	EXP	WORD			;;IF SO, DUMP IT TOO
    >
	],CNT				;;END LITERAL AND STORE COUNT
  >					;;END OF IFN CNT CONDITIONAL
>
;THE FOLLOWING MACRO IS USED TO APPEND STRINGS TOGETHER.  THE USE OF
;THIS IS IN GENERATING THE TTYTYP TABLE AFTER EACH TERMINAL HAS BEEN
;DEFINED.



DEFINE	CONCAT(TEXT),<			;;MACRO TO APPEND NEW TEXT TO OLD

	DEFINE	APPEND(NEWTXT),<	;;REDEFINE OTHER MACRO
	CONCAT	(<TEXT''NEWTXT>)	;;WHICH DOES THE WORK
	>

	DEFINE	STRING,<		;;AND DEFINE MACRO FOR WHOLE TEXT
TEXT
>
>


	CONCAT				;INITIALIZE CONCATENATION MACROS






;FINALLY, INITIALIZE THE MAXIMUM VALUES OF THE WIDTH, LENGTH, AND AREA
;USED FOR ANY SCREEN.  NEEDED TO ALLOCATE DATA FOR WORST CASE.


	MAXLEN==0		;INITIALIZE MAXIMUM LENGTH
	MAXWID==0		;INITIALIZE MAXIMUM WIDTH
	MAXARE==0		;INITIALIZE MAXIMUM AREA
;NOW DEFINE ALL THE TERMINALS WHICH WE CAN RUN ON.  THE FOLLOWING TERMINAL
;NAMES MUST BE IN ALPHABETICAL ORDER!!!




TTY(ADM3A,,,24,80,,176,SP,CL(H),CL(L),CL(K),LF,CR,CL(^),CL(Z),,,
<ALT,"=">,,,SP,SP)


TTY(ASR33,ASR33,.TT33,25,71,TTY,176,SP,,SP,,LF,CR,
<CR,LF,LF>,<CR,LF,LF>,,,,,)


TTY(ASR35,ASR35,.TT35,25,71,<TAB,TTY>,176,SP,,SP,,LF,CR,
<CR,LF,LF>,<CR,LF,LF>,,,,,)


TTY(VT05,VT05,.TTV05,20,72,<TAB,RAI>,176,SP,CL(H),CL(X),
<CL(Z),RUB,RUB,RUB,RUB>,<LF,RUB,RUB,RUB,RUB>,CR,<CL(]),RUB,RUB,RUB,RUB>,
<CL(]),RUB,RUB,RUB,RUB,CL(_),RUB,RUB,RUB,RUB>,<CL(^),RUB,RUB,RUB,RUB>,
<CL(_),RUB,RUB,RUB,RUB>,CL(N),<NUL,NUL,NUL,NUL>,,SP,SP)


TTY(VT06,VT06,,25,72,RAI,176,SP,CL(H),CL(X),CL(Z),LF,CR,CL(]),
<CL(]),CL(_)>,CL(^),CL(_),,,,SP,SP)


TTY(VT100,VT100,.TT100,24,80,<TAB,ANSI>,176,SP,CL(H),<ALT,"[","C">,
<ALT,"[","A">,LF,CR,<ALT,"[","H">,<ALT,"[","H",ALT,"[","J">,
<ALT,"[","K">,<ALT,"[","J">,<ALT,"[">,,,,)


TTY(VT50,VT50,.TTV50,12,80,<TAB,RAI>,176,SP,CL(H),<ALT,"C">,<ALT,"A">,
LF,CR,<ALT,"H">,<ALT,"H",ALT,"J">,<ALT,"K">,<ALT,"J">,,,,SP,SP)


TTY(VT52,VT52,.TTV52,24,80,TAB,176,SP,CL(H),<ALT,"C">,<ALT,"A">,LF,CR,
<ALT,"H">,<ALT,"H",ALT,"J">,<ALT,"K">,<ALT,"J">,<ALT,"Y">,,,SP,SP)
;NOW DEFINE THE TERMINAL TYPE TABLE, WHICH POINTS OFF TO EACH OF THE
;TERMINAL BLOCKS.  THIS DATA TABLE IS IN THE FORMAT NEEDED FOR
;THE TBLUK JSYS.



	XALL			;SHOW THE EXPANSION


TTYTYP:	XWD	TYPMAX,TYPMAX	;HEADER WORD FOR TABLE
	STRING			;THE TERMINAL TYPES


	TYPMAX==.-TTYTYP-1	;NUMBER OF TERMINAL TYPES


	SALL			;RETURN TO NORMAL LISTING
;THE FOLLOWING SIMPLE MACROS ARE USED TO DEFINE THE ERROR HANDLING
;INSTRUCTIONS.  THE AC FIELD OF THE XCT INSTRUCTION IS THE ERROR
;CODE.  THE INSTRUCTION XCT'D IS A SUBROUTINE CALLING INSTRUCTION.


DEFINE	DIE(CODE),<
	XCT	<E..'CODE-ERRTAB>,DIEBIG	;;GO TO ERROR ROUTINE
>



DEFINE	ERR(CODE,TEXT),<
E..'CODE:	[ASCIZ/TEXT/]	;;THE MESSAGE FOR THE ERROR
>
	SUBTTL	DISPATCH ROUTINE


;HERE ON AN LUUO, TO SAVE THE AC'S, DISPATCH TO THE PROPER ROUTINE,
;RESTORE THE AC'S, AND GO BACK TO THE USER.



DPYUUO:	MOVEM	P,SAVEP		;SAVE PUSH-DOWN AC IN CASE OF ERRORS
	MOVEM	F,SAVEF		;SAVE AN AC
	MOVE	F,[T1,,SAVET1]	;SET UP FOR BLT
	BLT	F,SAVEU		;SAVE REST OF AC'S WE USE
	MOVE	A,.JBUUO##	;GRAB HIS UUO
	LDB	T1,[POINT 4,A,12]	;GRAB THE AC FIELD
	CAILE	T1,MAXUUO	;SEE IF LEGAL LUUO WAS GIVEN
	  DIE	ILR		;NO, DIE
	JUMPE	T1,DOUUO	;IF INITIALIZATION, SKIP ON
	MOVE	X,@DP+$DPADR	;GET POINTER TO DATA AREA
	DMOVE	L,OURLN(X)	;RESTORE AC'S L AND N
	DMOVE	B,OURBU(X)	;RESTORE AC'S B AND U
	MOVE	F,OURF(X)	;GET OUR FLAGS
	TLNN	F,FL.INI	;HAVE WE BEEN INITIALIZED?
	  DIE	ING		;NO, LOSE
DOUUO:	PUSHJ	P,@DSPTAB(T1)	;CALL SUBROUTINE
	SKIPE	OUTADR(X)	;PROGRAM INTERCEPTING OUTPUT?
	PUSHJ	P,USRLST	;YES, INDICATE THIS IS END OF IT
	TLZE	F,FL.PNT	;NEED TO FORCE OUTPUT?
	PUSHJ	P,PUNT		;YES, SEND OUT REMAINING STUFF

RETURN:	MOVEM	F,OURF(X)	;SAVE FLAGS
	DMOVEM	L,OURLN(X)	;SAVE AC'S L AND N
	DMOVEM	B,OURBU(X)	;SAVE AC'S B AND U
	MOVSI	U,SAVEF		;SET UP FOR BLT
	BLT	U,U		;RESTORE HIS AC'S
CPOPJ:	POPJ	P,		;RETURN
;TABLE OF FUNCTION CODES.  THESE FUNCTIONS ARE DETERMINED BY THE
;AC FIELD OF THE LUUO.


DSPTAB:	EXP	FUNINI		;(0) INITIALIZE
	EXP	FUNSTR		;(1) STRING OUTPUT
	EXP	FUNCHR		;(2) CHARACTER OUTPUT
	EXP	FUNCHI		;(3) IMMEDIATE CHARACTER OUTPUT
	EXP	FUNSIZ		;(4) SET WINDOW SIZE
	EXP	FUNTAB		;(5) SET TABS
	EXP	FUNREF		;(6) REFRESH SCREEN
	EXP	FUNDPY		;(7) UPDATE SCREEN
	EXP	FUNSET		;(10) SET VARIOUS PARAMETERS
	EXP	FUNTTY		;(11) OUTPUT THINGS TO TTY
	EXP	FUNLOC		;(12) RETURN LOCATION OF NEXT OUTPUT
	EXP	FUNADR		;(13) MOVE TO GIVEN POSITION ON SCREEN

	MAXUUO==.-DSPTAB-1	;MAXIMUM LUUO ALLOWED
	SUBTTL	FUNCTION TO INITIALIZE


;FUNCTION WHICH SETS UP EVERYTHING SO THAT ON THE NEXT CALL TO OUR
;DPY ROUTINES, WE DO CORRECT THINGS.  I.E., WE CLEAR ALL FLAGS, SET
;UP DEFAULT TABS, CLEAR THE STORED SCREEN, AND MAYBE ERASE SCREEN.
;CALL TO INITIALIZE IS:
;
;	INI$	[FLAGS,,COUNT
;		ARGS]		;INITIALIZE DPY



FUNINI:	MOVSI	F,FL.INI	;SET INITIALIZATION FLAG
	PUSHJ	P,INIUSR	;READ USER ARGUMENTS AND PROCESS THEM
	HRR	F,T.FLAG(U)	;SET UP FLAGS FOR TERMINAL
	MOVE	T1,T.LEN(U)	;GET LENGTH OF SCREEN
	MOVEM	T1,@DP+$DPLEN	;SAVE IT
	MOVE	T1,T.WID(U)	;GET WIDTH OF SCREEN
	MOVEM	T1,@DP+$DPWID	;SAVE IT TOO
	MOVE	T1,[POINT 7,TTYBUF(X)] ;GET TERMINAL POINTER
	MOVEM	T1,BUFPTR(X)	;INITIALIZE IT
	SETZM	BUFCNT(X)	;CLEAR COUNT OF CHARACTERS
	PUSHJ	P,DFTTAB	;SET UP DEFAULT TAB STOPS
	PUSHJ	P,SIZINI	;SET UP THE DEFAULT WINDOW
	SETZM	ZERBLK(X)	;GET SET
	HRLI	T1,ZERBLK(X)	;MAKE BLT POINTER...
	HRRI	T1,ZERBLK+1(X)	;TO CLEAR ALL PARAMETERS
	BLT	T1,ZEREND(X)	;DO IT
	MOVE	T1,[BYTE (9)SP,SP,SP,SP]	;SET UP SPACES
	MOVEM	T1,SCREEN(X)	;STORE IN SCREEN
	HRRZM	T1,TTYN(X)	;SET CURSER WAY OFF OF SCREEN
	HRRZM	T1,TTYL(X)	;SO IF NOT CLEARED, WILL ADDRESS OR HOME
	HRLI	T1,SCREEN(X)	;SET UP...
	HRRI	T1,SCREEN+1(X)	;BLT POINTER
	BLT	T1,SCREEN+MAXARE-1(X)	;MAKE WHOLE SCREEN SPACES
	MOVE	A,INIFLG	;GET BACK USER FLAGS
	TRNN	A,IN$NCL	;SHOULD WE CLEAR THE SCREEN?
	  JRST	DOCLR		;YES, GO DO IT
	POPJ	P,		;NO, JUST RETURN
	SUBTTL	ROUTINE TO PROCESS USER ARGUMENTS FOR INI$ FUNCTION




;CALLED TO LOOK AT THE USER'S ARGUMENTS FOR THE INI$ FUNCTION, AND
;PROCESS THEM.  THE MOST IMPORTANT FUNCTION DONE IS SETTING WHICH
;TERMINAL TYPE WE ARE RUNNING ON.



INIUSR:	TRNN	A,-1		;WERE ARGUMENTS SUPPLIED?
	MOVEI	A,ZERO		;NO, THEN POINT TO DEFAULT ONE
	MOVSI	B,-ININUM	;GET READY FOR LOOP

INILP1:	PUSHJ	P,GETWRD	;READ ARGUMENT FOR NEXT ROUTINE
INILP2:	PUSHJ	P,@INITAB(B)	;THEN CALL ROUTINE
	AOBJP	B,CPOPJ		;RETURN IF DONE
	SOSL	INICNT		;USER HAVE ANY MORE ARGS?
	  JRST	INILP1		;YES, GET READ IT AND PROCESS IT
	SETZ	T1,		;NO, THEN DEFAULT TO ZERO
	JRST	INILP2		;GO BACK FOR NEXT ROUTINE



INITAB:	EXP	INIHDR		;(0) THE HEADER WORD
	EXP	INIADR		;(1) THE ADDRESS OF THE RELOCATABLE DATA
	EXP	INIERR		;(2) ROUTINE TO GO TO ON ERROR
	EXP	INITTY		;(3) TERMINAL STRING
	EXP	INIJFN		;(4) THE JFN OR CHANNEL FOR OUTPUT

	ININUM==.-INITAB	;NUMBER OF ARGUMENTS TOTAL
;HERE TO PROCESS THE HEADER WORD.  THIS CONTAINS FLAGS AND THE COUNT
;OF REMAINING ARGUMENTS TO BE PROCESSED.


INIHDR:	HLRZM	T1,INIFLG	;SAVE THE FLAGS
	HRRZM	T1,INICNT	;AND THE COUNT OF ARGUMENTS
	POPJ	P,		;DONE




;HERE TO PROCESS THE ADDRESS OF THE RELOCATABLE DATA.  THE USER CAN
;TELL US WHERE IN CORE TO STORE OUR DATA.


INIADR:	SKIPN	X,T1		;DID HE GIVE AN ADDRESS?
	MOVEI	X,DATBEG	;NO, THEN USE OUR OWN
	MOVEM	X,DATADR	;REMEMBER THE LOCATION FOR LATER
	POPJ	P,		;DONE




;HERE TO PROCESS THE ERROR ADDRESS.  THIS IS SO THAT IF THE INI$
;FUNCTION FAILS SOMEHOW, THE CALLER CAN RECOVER FROM THE ERROR.


INIERR:	MOVEM	T1,ERRADR(X)	;REMEMBER THE ERROR ADDRESS
	POPJ	P,		;DONE





;HERE TO PROCESS THE JFN (OR BUFFER,,CHANNEL) FOR OUTPUT.  IF ZERO,
;WE HAVE TO ALLOCATE OUR OWN JFN (OR USE IONEOU).  OTHERWISE, WE ARE
;TO USE THE SPECIFIED JFN FOR OUTPUT.


INIJFN:	MOVEM	T1,TTYJFN(X)	;SET UP JFN
	POPJ	P,		;RETURN
;HERE TO INITIALIZE THE TERMINAL TYPE.  ZERO MEANS USE OUR CURRENT
;TERMINAL TYPE.  FOR TOPS-20, 5B2 MEANS TERMINAL TYPE IS IN RIGHT HALF,
;OTHERWISE WE HAVE A POINTER TO AN ASCIZ STRING.  FOR TOPS-10, THE
;SIXBIT TERMINAL NAME IS SUPPLIED IF NONZERO.



INITTY:	IF20,<

	JUMPE	T1,FNDTYP	;ASK MONITOR FOR TYPE IF NOTHING GIVEN
	HRRZ	T2,T1		;GET RIGHT HALF BY ITSELF
	HLRZ	T1,T1		;AND LEFT HALF BY ITSELF TOO
	CAIN	T1,(5B2)	;IS THIS A TERMINAL TYPE NUMBER?
	JRST	FNDTTY		;YES, GO USE IT
	CAIE	T1,0		;IS THIS AN ADDRESS?
	CAIN	T1,-1		;OR THE DEFAULT POINTER?
	TLOA	T2,(POINT 7,)	;YES, GET STANDARD POINTER
	HRL	T2,T1		;OTHERWISE RESTORE POINTER
	MOVEI	T1,TTYTYP	;POINT TO TABLE
	TBLUK			;SEARCH FOR GIVEN STRING
	TLNN	T2,(TL%ABR!TL%EXM)	;FIND UNIQUE MATCH?
	SKIPA	U,[DFTTRM]	;NO, USE DEFAULT TERMINAL TYPE
	HRRZ	U,(T1)		;YES, SET UP POINTER FOR THIS TERMINAL
	POPJ	P,		;RETURN


FNDTYP:	MOVEI	T1,.PRIOU	;WANT TO FIND OUTPUT TERMINAL TYPE
	GTTYP			;READ IT
				;THEN FALL INTO SEARCH CODE
>
IF10,<	SKIPE	T2,T1		;SEE IF WE WERE GIVEN A NAME
	JRST	FNDTTY		;YES, GO SEARCH FOR IT
	MOVE	T2,[2,,T3]	;GET READY
	MOVEI	T3,.TOTRM	;TO READ TERMINAL TYPE
	SETO	T4,		;FOR OUR CONTROLLING TTY
	TRMOP.	T2,		;READ TYPE
	JRST	USEDFT		;FAILED, GO USE DEFAULT TERMINAL
>



;HERE WHEN T2 CONTAINS THE TERMINAL TYPE FOR TOPS-20, OR THE TERMINAL
;NAME FOR TOPS-10, TO SEARCH OUR TERMINAL DATA FOR THE RIGHT BLOCK.


FNDTTY:	MOVSI	T1,-TYPMAX	;GET READY FOR LOOP
	HRRZ	T3,TTYTYP+1(T1)	;GET ADDRESS OF NEXT TTY BLOCK
	CAME	T2,T.TYP(T3)	;FOUND THE RIGHT TYPE?
	AOBJN	T1,.-2		;NO, KEEP LOOKING
	SKIPL	T1		;FOUND IT?
USEDFT:	SKIPA	U,[DFTTRM]	;NO, GET DEFAULT TERMINAL BLOCK
	HRRZ	U,TTYTYP+1(T1)	;YES, THEN USE THAT BLOCK
	POPJ	P,		;RETURN
	SUBTTL	THE CHARACTER STORING ROUTINES



;THE FOLLOWING THREE CALLS ARE USED TO GIVE DPY THE CHARACTERS THE
;USER PROGRAM WANTS TO DISPLAY.  STR$ PROCESSES A STRING, CHR$ PROCESSES
;A CHARACTER, AND CHI$ PROCESSES AN IMMEDIATE CHARACTER.




FUNSTR:	ANDI	A,-1		;KEEP ONLY ADDRESS OF STRING
	CAIG	A,U		;REFERENCING THE STORED AC'S?
	ADDI	A,SAVEF		;YES, RELOCATE TO THEM
STRUNS:	TLOA	A,(POINT 7,)	;MAKE BYTE POINTER AND SKIP INTO LOOP
STRLOP:	PUSHJ	P,STORE1	;STORE THIS CHARACTER
	ILDB	C,A		;GRAB THE NEXT CHARACTER
	JUMPN	C,STRLOP	;LOOP OVER WHOLE STRING
	CAME	A,[POINT 7,ZERO,6]	;WENT OFF THE SAVED AC'S?
	  POPJ	P,		;NO, THEN ALL DONE
	MOVEI	A,U+1		;YES, POINT TO UNSAVED AC'S
	JRST	STRUNS		;AND PROCEED



FUNCHR:	PUSHJ	P,GETWRD	;GO GET THE DESIRED WORD
	SKIPA	C,T1		;AND FALL INTO OTHER ROUTINE

FUNCHI:	MOVEI	C,(A)		;GRAB THE CHARACTER
	ANDI	C,177		;REMOVE ALL JUNK
;	PJRST	STORE		;AND FALL INTO STORE ROUTINE
;HERE WHEN HAVE THE CHARACTER IN AC C.  NULLS ARE IGNORED, AS ARE ALL
;NON-USEFUL CONTROL CHARACTERS, AND CHARACTERS HIGHER THAN THE TERMINAL
;CAN TYPE.   THE ONLY CONTROL CHARACTERS THAT ARE HANDLED ARE TAB
;AND LINE FEED.



STORE:	JUMPE	C,CPOPJ		;QUIT NOW IF HAVE A NULL
STORE1:	TLO	F,FL.OUT	;REMEMBER THAT WE HAVE OUTPUT IN THIS WINDOW
	CAMLE	L,MAXL(X)	;IS OUR LINE OFF OF THE BOTTOM?
	  JRST	OVERFL		;YES, GO SEE IF WE MOVE WINDOWS
	CAIL	C,SP		;IS THIS A CONTROL CHAR?
	CAMLE	C,T.MAXC(U)	;OR IS CHAR BEYOND PRINTING RANGE?
	  JRST	CONTRL		;YES, HANDLE SPECIAL
	SKIPLE	EATNUM(X)	;EATING UP CERTAIN NUMBER OF LINES?
	  POPJ	P,		;YES, JUST RETURN
	CAMLE	N,MAXN(X)	;ARE WE OFF RIGHT SIDE OF WINDOW?
	  JRST	OFFRHT		;YES
	TRNN	F,FR.RAI	;LOWER CASE ACTS LIKE UPPER CASE?
	  JRST	NORAIS		;NOPE, SKIP ON
	CAIL	C,"A"+40	;IS THIS A LOWER CASE CHARACTER?
	CAILE	C,176		;WELL?
	  JRST	NORAIS		;NO, DON'T CHANGE IT
	SUBI	C,40		;YES, CONVERT TO UPPER CASE
NORAIS:	ILDB	T1,B		;GRAB THE OLD CHARACTER AT THIS LOCATION
	TRZE	T1,UPDATE	;IS IT ALREADY TO BE UPDATED?
	PUSHJ	P,CKOKUP	;YES, SEE IF IT IS LEGAL TO DO SO
	CAMN	T1,C		;IS NEW CHAR SAME AS OLD ONE?
	  AOJA	N,CPOPJ		;YES, THEN COUNT POSITION AND RETURN
	TRNE	F,FR.ELC	;DOES TERMINAL DO CRLFS AT LAST CHAR?
	CAME	N,T.WID(U)	;AND ARE WE AT LAST COLUMN?
	  JRST	NOKLG		;NO, GO ON
	CAMN	L,T.LEN(U)	;ARE WE AT LAST LINE ALSO?
	  AOJA	N,CPOPJ		;YES, NEVER DIDDLE THE LAST CHAR THEN
NOKLG:	MOVEI	T1,UPDATE(C)	;NO, GET CHAR WITH "MUST UPDATE" BIT
	DPB	T1,B		;STORE IT AWAY
	MOVEI	T1,LINCHG(X)	;GET ADDRESS WE WANT...
	ADD	T1,L		;TO SET TO -1
	SETOM	(T1)		;REMEMBER THAT CHANGES HAVE BEEN DONE
	AOJA	N,CPOPJ		;THEN COUNT POSITION AND RETURN



;ROUTINE TO SEE IF UPDATING THE SAME PLACE ON THE SCREEN TWICE IS
;OK.  WE RETURN IF SO, GIVE AN ERROR IF NOT.


CKOKUP:	TLNN	F,FL.OKU	;DID USER TELL US IT'S OK?
	  DIE	USL		;NO, THEN GIVE THE ERROR
	POPJ	P,		;IT'S OK, JUST IGNORE IT
;HERE TO PROCESS A CONTROL CHARACTER.  THE ONLY CONTROL CHARACTERS WE
;WILL ALLOW ARE <TAB>  OR  <LF>.  ALL OTHER CHARACTERS ARE EATEN, FOR WE
;DON'T KNOW WHAT THE TERMINAL MAY DO WITH THEM.


CONTRL:	CAIE	C,LF		;IS A LINEFEED?
	  JRST	CHKCTL		;NO, GO LOOK FOR A TAB
	SOSL	EATNUM(X)	;DECREMENT NUMBER OF LINES TO EAT
	  POPJ	P,		;STILL HAVE TO EAT MORE, RETURN
	MOVEI	T1,SP+UPDATE	;GET A "MUST UPDATE HERE" SPACE
	MOVEI	T2,LINCHG(L)	;GET OFFSET OF FLAG WORD FOR THIS LINE
	ADD	T2,X		;RELOCATE IT

ZAPLIN:	CAMLE	N,MAXN(X)	;REACHED THE RIGHT LIMIT YET?
	  JRST	NEWLIN		;YES, GO MOVE TO NEXT LINE NOW
	ILDB	T3,B		;NO, THEN GRAB OLD CHARACTER
	TRZE	T3,UPDATE	;HAVE THE "MUST UPDATE" BIT ON?
	PUSHJ	P,CKOKUP	;YES, SEE IF IT'S OK FOR THAT TO HAPPEN
	CAIN	T3,SP		;IS CHAR A SPACE?
	  AOJA	N,ZAPLIN	;YES, LOOK AT NEXT CHAR
	DPB	T1,B		;NO, PUT IN A "MUST UPDATE" SPACE
	SETOM	(T2)		;REMEMBER CHANGES HAVE BEEN DONE
	AOJA	N,ZAPLIN	;AND LOOP TO FINISH OFF LINE



;HERE TO PROCESS A TAB, IF THAT IS WHAT WE HAVE.  IF NOT A TAB HERE,
;WE EAT IT, FOR IT IS A RANDOM CONTROL CHARACTER (INCLUDING CR)


CHKCTL:	CAIN	C,TAB		;IS IT A TAB?
	SKIPLE	EATNUM(X)	;AND DO WE HAVE NO LINES TO IGNORE?
	  POPJ	P,		;NO, JUST RETURN THEN
	MOVEI	T4,(N)		;GET POSITION ON THE LINE
	ADJBP	T4,[POINT 1,TABS(X),0]	;MAKE BYTE POINTER TO BIT
	MOVEI	C,SP		;AND CHANGE TAB TO A SPACE

TABLOP:	PUSHJ	P,STORE1	;GO STORE A SPACE
	CAME	N,MINN(X)	;AT BEGINNING OF NEXT LINE?
	CAMLE	N,MAXN(X)	;OR OUTSIDE THE WINDOW?
	  POPJ	P,		;YES, RETURN THEN
	ILDB	T1,T4		;NO, GET BIT FOR NEXT POSITION
	JUMPE	T1,TABLOP	;IF NOT AT TAB STOP GIVE ANOTHER SPACE
	POPJ	P,		;OTHERWISE ARE THERE



;HERE TO SET UP TO DO NEXT LINE


NEWLIN:	MOVE	N,MINN(X)	;GET LEFT WINDOW VALUE
	AOJA	L,MAKEBP	;INCREMENT LINE, MAKE BYTE POINTER, RETURN
;THESE ARE THE "FIXIT" ROUTINES WHICH SEE WHAT WE DO WHEN WE
;OVERFLOW A LINE, OR THE WHOLE WINDOW.  THE CHOICES DEPEND ON WHAT
;THE USER WANTS.  IF WE OVERFLOW A LINE, WE CAN EITHER IGNORE THE
;CHARACTER, OR DO AN AUTOMATIC CARRIAGE RETURN.  IF WE OVERFLOW
;THE WHOLE WINDOW, WE EITHER INGORE THE CHARACTER, OR WE MOVE THE WINDOW
;TO THE RIGHT SOME, AND CONTINUE OUTPUTTING IN THE NEW WINDOW.
;NOTE THESE ROUTINES ARE CALLED FROM THE  FUNLOC  ROUTINE, ALSO.


;HERE IF WE HAVE GONE OFF THE RIGHT OF THE WINDOW, TO SEE WHETHER WE
;JUST IGNORE THE CHARACTER, OR PRETEND IT WAS A <LF> CHAR


OFFRHT:	TLNN	F,FL.ACR!FL.AC2	;ARE WE DOING AUTO-CRLFS?
	  POPJ	P,		;NO, THEN IGNORE THE CHARACTER
	PUSHJ	P,NEWLIN	;GO MOVE TO THE NEXT LINE
	JRST	STORE		;THEN STORE THE CHARACTER




;HERE IF WE HAVE GONE OFF THE BOTTOM OF THE WINDOW.  WE MUST SEE IF THE
;USER TOLD US TO FLICK IN THE CHARS, OR TO MOVE THE WINDOW FOR HIM.


OVERFL:	SKIPLE	T1,OVFVAL(X)	;DID USER SET UP HOW WE MOVE WINDOWS?
	TRNN	T1,-1		;AND ARE THERE ANY WINDOWS LEFT IN COUNT?
	  JRST	CLROVF		;NO, GO CLEAR WORD FOR SURE AND RETURN
	SOS	OVFVAL(X)	;SUBTRACT 1 FROM COUNT OF WINDOWS LEFT
	HLRZ	T1,T1		;GET DISTANCE BETWEEN WINDOWS
	ADD	T1,MAXN(X)	;ADD TO CURRENT RIGHT MARGIN
	ADDI	T1,1		;AND THEN ONE MORE
	CAMLE	T1,T.WID(U)	;WOULD NEW LEFT MARGIN BE ON SCREEN?
	  JRST	CLROVF		;NO, CLEAR WORD AND IGNORE THIS CHAR
	EXCH	T1,MINN(X)	;SAVE NEW LEFT MARGIN, GET OLD ONE
	MOVE	T2,MAXN(X)	;GET OLD RIGHT MARGIN
	SUB	T2,T1		;SUBTRACT OLD LEFT MARGIN
	ADD	T2,MINN(X)	;AND ADD NEW LEFT MARGIN TO GET NEW RIGHT ONE
	CAMLE	T2,T.WID(U)	;DOES WINDOW GO OFF OF SCREEN?
	MOVE	T2,T.WID(U)	;YES, TRUNCATE IT TO FIT
	MOVEM	T2,MAXN(X)	;SAVE NEW RIGHT MARGIN
	MOVE	L,MINL(X)	;SET OUR LOCATION AT TOP OF WINDOW
	PUSHJ	P,MAKEBP	;CREATE A NEW POINTER
	JRST	STORE		;AND GO PUT THE CHAR IN THE NEW WINDOW


;HERE WHEN CAN'T MAKE A NEW WINDOW, TO CLEAR THE OVFVAL WORD

CLROVF:	SETZM	OVFVAL(X)	;ZERO SO NOT TO BOTHER US AGAIN
	POPJ	P,		;AND RETURN
	SUBTTL	FUNCTION TO REFRESH THE SCREEN


;THIS FUNCTION IS CALLED WHENEVER THE USER WANTS TO MAKE SURE THE
;SCREEN IS CORRECT,  THAT IS WHEN HE THINKS THERE ARE GLITCHES ON THE
;SCREEN AND WANTS THEM FIXED.  CALL IS:
;
;	REF$	FLAGS



FUNREF:	PUSHJ	P,ZAPEND	;FIRST MUNCH ON REST OF WINDOW
	PUSHJ	P,CLRCHG	;CLEAR THE CHANGE TABLE
	TRNE	F,FR.TTY	;IS THIS ON A NON-VIDEO TERMINAL
	  JRST	REFTTY		;YES, GO DO IT STRAIGHT
	TRNN	A,RE$CLR	;SHOULD WE CLEAR SCREEN FIRST?
	  JRST	REFHRD		;NO, GO DO IT THE HARD WAY


REFTTY:	PUSHJ	P,DOCLR		;YES, CLEAR THE SCREEN

REFLOP:	SETZ	N,		;START AT FRONT OF LINE
	PUSHJ	P,MAKEBP	;GET A BYTE POINTER TO IT

REFLIN:	ILDB	C,B		;GET NEXT CHAR OF LINE
	TRZE	C,UPDATE	;CLEAR UPDATE BIT
	DPB	C,B		;AND STORE CHAR BACK WITHOUT THE BIT
	CAIN	C,SP		;IS THIS A SPACE?
	  JRST	REFSPC		;YES, SKIP ON
	PUSH	P,C		;NO, SAVE THIS CHAR
	PUSHJ	P,MOVE		;GET TO THIS LOCATION
	POP	P,C		;RESTORE THE CHAR
	PUSHJ	P,DOONE		;OUTPUT IT

REFSPC:	CAMGE	N,T.WID(U)	;DONE WITH THIS LINE?
	  AOJA	N,REFLIN	;NO, LOOP
	CAMGE	L,T.LEN(U)	;DONE WITH ALL LINES?
	  AOJA	L,REFLOP	;NO, KEEP LOOPING
	PJRST	DPYFIN		;YES, GO FINISH UP
;HERE IN CASE WHERE WE DID NOT HOME UP AND CLEAR THE SCREEN.



REFHRD:	PUSHJ	P,DOHOM		;MAKE SURE WE ARE HOMED UP
	MOVE	T1,T.WID(U)	;GET LAST COLUMN
	MOVEM	T1,LSTNON	;AND SAVE SO EOL WILL TYPE WHOLE LINE


RFHLOP:	SETZ	N,		;START AT FRONT OF LINE
	PUSHJ	P,MAKEBP	;MAKE A BYTE POINTER FOR THIS LINE
	MOVE	T1,B		;GET A COPY
	SETOM	LSTCHG		;INITIALIZE TEMPORARY VARIABLE

RFHLIN:	ILDB	C,T1		;GET NEXT CHAR ON LINE
	TRZE	C,UPDATE	;CLEAR UPDATE BIT
	DPB	C,T1		;AND STORE IT BACK WITHOUT BIT
	CAIE	C,SP		;IS IT A SPACE?
	MOVEM	N,LSTCHG	;NO, REMEMBER LAST NONSPACE
	CAMGE	N,T.WID(U)	;SCANNED WHOLE LINE?
	  AOJA	N,RFHLIN	;NO, KEEP GOING
	SETZ	N,		;BACK UP TO FRONT AGAIN
	PUSHJ	P,MOVE		;GO THERE

RFHTYP:	CAMLE	N,LSTCHG	;DONE WITH ALL NONSPACES ON LINE?
	  JRST	RFHDNL		;YES
	ILDB	C,B		;NO, GET CHAR AT THIS SPOT
	PUSHJ	P,DOONE		;OUTPUT IT
	AOJA	N,RFHTYP	;AND CONTINUE

RFHDNL:	CAMG	N,T.WID(U)	;IF NOT AT END OF SCREEN
	PUSHJ	P,DOEOL		;THEN CLEAR THE REST OF THE LINE
	CAMGE	L,T.LEN(U)	;DID ALL LINES?
	  AOJA	L,RFHLOP	;NO, LOOP OVER THEM
	PJRST	DPYFIN		;YES, FINISH UP
	SUBTTL	FUNCTION TO UPDATE THE SCREEN


;THIS FUNCTION IS WHAT DPY IS ALL ABOUT!!!!  AFTER THE USER HAS OUTPUT
;WHATEVER PARTS OF THE SCREEN HE WISHES TO SHOW, HE CALLS THIS ROUTINE, AND
;THE CHANGES ARE SHOWN WITH MINIMUM EFFORT.  CALL IS SIMPLY:
;
;	DPY$	FLAGS




FUNDPY:	PUSHJ	P,ZAPEND	;CLEAR REST OF LAST WINDOW USED
	SETZB	L,N		;BEGIN SEARCH AT TOP LEFT
	TRNE	F,FR.TTY	;NON-VIDIO TERMINAL?
	  JRST	TTYDPY		;YES, HANDLE SPECIAL

FNDLIN:	CAMLE	L,T.LEN(U)	;LOOKED AT ALL THE LINES?
	  JRST	DPYFIN		;YES, GO FINISH UP
	PUSHJ	P,MINMAX	;LOOK FOR CHANGES ON THIS LINE
	  AOJA	L,FNDLIN	;IF NONE, GO TO NEXT LINE
	SKIPN	T.ADR(U)	;CAN TERMINAL ADDRESS?
	  JRST	NODPY		;NO, GO DO DIFFERENTLY

UPDLIN:	MOVE	N,FSTCHG	;YES, GET COLUMN OF FIRST CHANGE
	PUSHJ	P,MOVE		;GO THERE
	PUSHJ	P,SLURP		;DO ALL CHANGES ON THE LINE
	AOJA	L,FNDLIN	;THEN LOOK AT NEXT LINE



;HERE WHEN ALL DONE, TO RESET WINDOWS AND POSSIBLY HOME UP:


DPYFIN:	SETZM	EATNUM(X)	;NO LONGER WANT TO EAT LINES
	SETZB	N,L		;SET AT TOP LEFT CORNER
	TRNN	A,DP$NOH	;WANT TO HOME UP WHEN DONE?
	PUSHJ	P,MOVE		;YES, DO IT
	MOVE	L,MINL(X)	;SET LOCATION TO TOP LINE OF WINDOW
	MOVE	N,MINN(X)	;AND LEFTMOST COLUMN OF WINDOW
	TLZ	F,FL.OUT	;CLEAR OUTPUT IN WINDOW FLAG
	PJRST	MAKEBP		;MAKE A BYTE POINTER AND RETURN
;HERE IF THIS TERMINAL CANNOT ADDRESS.  WE MUST SEE IF IT IS BETTER
;TO GO TO THE RIGHT FIRST, OR TO DO A CARRIAGE RETURN FIRST.



NODPY:	MOVE	N,TTYN(X)	;GET CURRENT COLUMN NUMBER
	CAMLE	N,FSTCHG	;IS CURSER TO LEFT OF FIRST CHANGE?
	CAMLE	N,LSTCHG	;OR IS IT TO RIGHT OF LAST CHANGE?
	  JRST	UPDLIN		;YES, UPDATE LINE FROM LEFT TO RIGHT
	CAMLE	N,LSTNON	;ONLY SPACES BEYOND WHERE WE ARE?
	SKIPN	T.EOL(U)	;AND CAN WE DO ERASE END OF LINES?
	SKIPA	T1,LSTCHG	;NO, GET LAST CHANGE AND SKIP
	  JRST	UPDLIN		;YES, START AT FRONT OF LINE THEN
	PUSH	P,TTYN(X)	;SAVE CURRENT POSITION
	MOVEM	T1,TTYN(X)	;CHANGE WHERE WE THINK WE ARE
	MOVE	N,FSTCHG	;AND WE WANT TO GET TO FIRST CHANGE
	MOVEI	T2,-1		;GET A LARGE NUMBER
	MOVEM	T2,BEST		;SET IT
	PUSHJ	P,CHKDL		;SEE HOW MANY CHARS TO BACK UP
	PUSHJ	P,CHKCDR	;OR HOW MANY TO CR, THEN FORWARD
	POP	P,TTYN(X)	;RESTORE TRUE POSITION
	PUSH	P,BEST		;SAVE NUMBER OF CHARS NEEDED
	MOVEI	T2,-1		;GET LARGE NUMBER AGAIN
	MOVEM	T2,BEST		;AND SET IT AGAIN
	PUSHJ	P,CHKDL		;SEE HOW MANY CHARS TO GET TO FIRST CHANGE
	PUSHJ	P,CHKCDR	;ALSO BY CR FIRST
	POP	P,T1		;RESTORE OTHER COUNT
	MOVE	T2,TTYN(X)	;GET CURRENT POSITION
	SUB	T2,PRECHG	;SUBTRACT NEAREST CHANGE
	ADD	T2,BEST		;ADD IN OTHER COUNT
	ADDI	T1,PRETTY	;ADD IN PRETTYNESS FACTOR
	CAML	T1,T2		;IS IT BETTER TO CRLF FIRST OR NOT?
	  JRST	UPDLIN		;YES, JUST UPDATE LINE
	MOVE	N,TTYN(X)	;START SEARCH AT CURRENT POSITION
	PUSHJ	P,MOVE		;GO TO RIGHT LINE
	PUSHJ	P,SLURP		;UPDATE END OF THE LINE
	MOVE	T1,PRECHG	;GET LAST CHANGE PRIOR TO MOVEMENT
	MOVEM	T1,LSTCHG	;SET IT AS LAST CHANGE
	JRST	UPDLIN		;THEN UPDATE FIRST PART OF LINE
;HERE IF THIS IS A NON-VIDIO TERMINAL.  WE SEE IF ANY CHANGES HAVE
;OCCURED ON THE SCREEN.  IF NOT, WE DO NOTHING.  OTHERWISE WE TYPE
;THE WHOLE SCREEN AGAIN.



TTYDPY:	HRLZ	T1,T.LEN(U)	;GET NUMBER OF LINES TO CHECK
	MOVN	T1,T1		;MAKE AOBJN POINTER
	HRRI	T1,LINCHG(X)	;GET ADDRESS OF THE TABLE
	SKIPN	(T1)		;CHANGES ON THIS LINE?
	AOBJN	T1,.-1		;NO, SEARCH ALL LINES
	JUMPGE	T1,DPYFIN	;JUST RETURN IF NO CHANGES
	PUSHJ	P,CLRCHG	;CLEAR THE CHANGE TABLE
	PUSHJ	P,MOVE		;GO "MOVE" TO HOME POSITION
	JRST	REFLOP		;THEN JOIN REFRESH CODE



CLRCHG:	HRLI	T1,LINCHG(X)	;GET SET
	HRRI	T1,LINCHG+1(X)	;FOR BLT
	MOVE	T2,T.LEN(U)	;GET NUMBER OF LINES
	SETZB	L,LINCHG(X)	;CLEAR LINE NUMBER AND CHANGE FLAG
	ADDI	T2,LINCHG(X)	;GET ADDRESS WE WANT
	BLT	T1,(T2)		;ZERO WHOLE CHANGE TABLE
	POPJ	P,		;DONE
	SUBTTL	ROUTINE TO OUTPUT THE CHANGES ON A LINE



;THIS ROUTINE IS CALLED ONCE WE ARE AT A CHANGE ON A LINE, TO FOLLOW
;THE LINE LOOKING FOR REST OF THE CHANGES.  THIS ROUTINE ALSO TAKES
;CARE OF THE ERASE-END-OF-LINE CHECKS.  CALL IS:
;
;	(CALL MINMAX)		;COLLECT FSTCHG, LSTCHG, ETC.
;	MOVE	N,COLUMN	;SET UP COLUMN OF CHANGE
;	MOVE	L,LINE		;AND LINE OF CHANGE
;	PUSHJ	P,SLURP		;PROCESS THE CHANGES ON THE LINE
;	(RETURN)		;WE TOOK CARE OF ALL CHANGES ON LINE





SLURP:	PUSHJ	P,MAKEBP	;GET A BYTE POINTER TO THIS PLACE
SLPLOP:	CAMLE	N,LSTCHG	;BEYOND THE LAST CHANGE ON THE LINE?
	  POPJ	P,		;YES, RETURN
SLPSCN:	ILDB	C,B		;GET CHARACTER AT THIS POSITION
	TRZN	C,UPDATE	;DOES IT NEED UPDATING?
	  AOJA	N,SLPSCN	;NO, LOOK SOME MORE
	DPB	C,B		;YES, STORE CHAR BACK WITHOUT BIT
	CAME	N,TTYN(X)	;CURSER NOT AT CURRENT COLUMN?
	PUSHJ	P,MOVE		;NO, THEN MOVE THERE
	SKIPE	T.EOL(U)	;CAN THIS TERMINAL ERASE END OF LINE?
	CAMG	N,LSTNON	;AND LINE CONTAINS ONLY SPACES?
	SKIPA			;NO, THEN DO NOTHING SPECIAL
	  JRST	SLPEOL		;YES, GO DO END OF LINE
	LDB	C,B		;GET BACK CHAR IN CASE WE HAD TO MOVE
	PUSHJ	P,DOONE		;THEN OUTPUT THIS CHARACTER
	AOJA	N,SLPLOP	;LOOK AT NEXT CHAR


SLPEOL:	PUSHJ	P,DOEOL		;ERASE REST OF LINE
	MOVEI	C,SP		;GET A SPACE
SLPELL:	CAML	N,LSTCHG	;DID ALL CHARS ON LINE?
	  POPJ	P,		;YES, RETURN
	IDPB	C,B		;STORE A SPACE IN THE ARRAY
	AOJA	N,SLPELL	;AND LOOP
	SUBTTL	FUNCTION WHICH SETS THE "WINDOW" FOR OUTPUT


;THIS FUNCTION IS USED TO SET A "WINDOW" IN WHICH THE USER WANTS TO
;OUTPUT IN.  THE PURPOSE OF THIS IS SO THE USER CAN SPLIT UP THE
;SCREEN IN PIECES, AND OUTPUT HIS STUFF ONE HUNK AT A TIME, AND
;THEREFORE NOT HAVE TO WORRY ABOUT FORMATTING EVERYTHING.  HE JUST
;CALLS THIS ROUTINE EACH TIME HE OUTPUTS A DIFFERENT PIECE.
;USER CALLS THIS ROUTINE WITH:
;
;	SIZE$	[MINLIN,,MAXLIN		;MIN AND MAX LINE NUMBER
;		 MINCHR,,MAXCHR]	;MIN AND MAX CHARACTER POSITION
;
;WHERE THE NUMBERS ARE THE MINIMUM AND MAXIMUM VALUES THE USER WISHES
;TO RANGE BETWEEN.  ZERO IS THE TOP LEFT CORNER OF THE PHYSICAL SCREEN.
;A NEGATIVE MAXIMUM ARGUMENT (I.E., BIT 18 IS SET) IMPLIES TO USE THE
;MAXIMUM VALUE ALLOWED, THE FULL WIDTH OR LENGTH OF THE SCREEN.
;WE ALSO SET THE POSITION TO OUTPUT TO TO THE TOP LEFT OF THE WINDOW,
;TO SAVE THE USER THE TROUBLE, SINCE HE USUALLY WANTS THAT ANYWAY.
;IF THE UUO CONTAINS ZERO AS THE ADDRESS, WE ASSUME HE WANTS TO HAVE
;THE WHOLE SCREEN AS THE WINDOW, AND SO DO IT THAT WAY.


FUNSIZ:	PUSHJ	P,ZAPEND	;CLEAR OUT REST OF PREVIOUS WINDOW FIRST
	TRNN	A,-1		;GIVE US A REASONABLE ADDRESS?
SIZINI:	MOVEI	A,T.LEN(U)	;NO, SET UP USUAL SCREEN THEN
	PUSHJ	P,GETWRD	;GRAB FIRST USER WORD
	HLRZ	L,T1		;SET MINIMUM LINE NUMBER
	TRNE	T1,400000	;IS THE MAXIMUM VALUE NEGATIVE?
	SKIPA	T1,T.LEN(U)	;YES, GRAB LARGEST POSSIBLE VALUE
	MOVEI	T1,(T1)		;NO, ISOLATE MAXIMUM LINE NUMBER
	CAIG	L,(T1)		;MINIMUM SMALLER THAN MAXIMUM?
	CAMLE	T1,T.LEN(U)	;AND MAXIMUM LESS THAN SCREEN?
	DIE	IWS		;NO, IS WRONG, DIE
	MOVEM	L,MINL(X)	;SAVE THE MINIMUM AWAY
	MOVEM	T1,MAXL(X)	;AND THE MAXIMUM
	PUSHJ	P,GETWRD	;GET USER'S SECOND ARGUMENT
	HLRZ	N,T1		;GET MINIMUM CHARACTER POSITION
	TRNE	T1,400000	;IS MAXIMUM VALUE NEGATIVE?
	SKIPA	T1,T.WID(U)	;YES, USE LARGEST LEGAL VALUE
	MOVEI	T1,(T1)		;NO, ISOLATE MAXIMUM POSITION
	CAIG	N,(T1)		;MINIMUM SMALLER THAN MAXIMUM?
	CAMLE	T1,T.WID(U)	;AND MAXIMUM WITHIN SCREEN BOUNDARY?
	DIE	IWS		;NO
	MOVEM	N,MINN(X)	;OK, SAVE AWAY MINIMUM POSITION
	MOVEM	T1,MAXN(X)	;AND MAXIMUM POSITION
	TLO	F,FL.OUT	;ACT LIKE WE HAVE OUTPUT IN WINDOW
	PJRST	MAKEBP		;NOW MAKE BYTE POINTER AND RETURN
	SUBTTL	FUNCTION WHICH SETS TABS


;THIS FUNCTION IS USED TO SET WHERE TABS ARE ON THE SCREEN, SO THAT
;WHEN A TAB CHARACTER IS OUTPUT, WE JUMP TO THE NEXT TAB SETTING.
;BY LETTING HIM CHANGE THE TABS, WE ALLOW VERSATILITY IN HIS OUTPUT.
;NOTE THAT TABS ARE SET ALWAYS WITH RESPECT TO THE SCREEN, NEVER TO
;A WINDOW.  USER CALLS THIS ROUTINE WITH:
;
;	TAB$	ADDR		;LOCATION OF THE TABS
;
;WHERE ADDR CONTAINS A BIT TABLE OF WHERE THE TABS ARE, STARTING WITH
;THE FIRST BIT OF THE FIRST WORD BEING THE LEFT HAND EDGE OF THE SCREEN.
;IF THE ADDRESS GIVEN IS ZERO, WE SUPPLY DEFAULT TABS.



FUNTAB:	TRNN	A,-1		;DOES HE HAVE HIS OWN TABS?
DFTTAB:	MOVEI	A,REGTAB	;NO, THEN USE DEFAULT ONES
	MOVSI	T4,-4		;GET READY FOR LOOP
	HRR	T4,X		;POINT AT DATA

TABPUT:	PUSHJ	P,GETWRD	;GRAB THE NEXT WORD OF BITS
	MOVEM	T1,TABS(T4)	;SAVE THEM AWAY
	AOBJN	T4,TABPUT	;AND LOOP FOR ALL OF THEM
	POPJ	P,		;THEN RETURN



;THE DEFAULT TABS FOLLOW (EVERY EIGHT POSITIONS ON THE SCREEN)


	TAB%%==401002004010	;STARTING POINT OF MAKING TAB TABLE


REGTAB:	REPEAT	4,<

	EXP	TAB%%			;;PUT IN THE TABS FOR SOME LOCATIONS
	TAB%%==<TAB%%_4>!<TAB%%_-4>	;;AND GENERATE NEW TABS FOR NEXT ONE
>
	SUBTTL	FUNCTION WHICH SETS PARAMETERS


;THIS FUNCTION IS CALLED TO SET PARAMETERS WHICH CONTROL EXACTLY HOW
;WE DO CERTAIN THINGS.  THIS ALLOWS THE USER TO CONTROL WHAT HAPPENS MORE
;EXACTLY THAN OTHERWISE.  CALL IS:
;
;	SET$	[FUNCTION,,VALUE]	;SET DESIRED THING
;	(RETURN)			;ALL DONE
;OR:
;	SET$	[0,,NUMBER OF FUNCTIONS
;		 FUNCTION1,,VALUE1
;		 FUNCTION2,,VALUE2
;			...
;		 FUNCTIONN,VALUEN]	;SET BUNCH OF VALUES
;
;WE USE AC'S  T1, T2, AND T4



FUNSET:	PUSHJ	P,GETWRD	;GRAB THE USER'S ARGUMENT
	TLNN	T1,-1		;LEFT HALF ZERO?
	SKIPA	T4,T1		;YES, GET COUNT OF THINGS TO SET
	TDZA	T4,T4		;NO, THEN SET COUNT TO JUST 1 THING

SETLOP:	PUSHJ	P,GETWRD	;GRAB THE NEXT THING TO GRUNGE ON
	HLRE	T2,T1		;GET FUNCTION
	SKIPLE	T2		;OUT OF RANGE?
	CAILE	T2,MAXSET	;MAYBE
	DIE	ISF		;YES, DIE
	XCT	SETTAB-1(T2)	;SET THE PARAMETER
	SOJG	T4,SETLOP	;AND DO NEXT ONE
	POPJ	P,		;UNTIL DID ALL
;TABLE OF INSTRUCTIONS FOR THE VARIOUS FUNCTIONS.


SETTAB:	DPB	T1,[POINT 1,F,^L<(FL.ACR)>] ;(1)  AUTOMATIC CRLFS
	DPB	T1,[POINT 1,F,^L<(FL.NZP)>] ;(2)  DON'T CLEAR REST OF WINDOWS
	DPB	T1,[POINT 1,F,^L<(FL.NOS)>] ;(3)  CALL USER DIRECTLY
	HRRZM	T1,OUTADR(X)		    ;(4)  SET CHARACTER ROUTINE
	HRRZM	T1,ERRADR(X)		    ;(5)  SET ERROR ROUTINE
	PUSHJ	P,WNDSET		    ;(6)  SET WINDOW MOVEMENT
	DPB	T1,[POINT 1,F,^L<(FL.OKU)>] ;(7)  UPDATING SAME PLACE IS OK
	HRRZM	T1,EATNUM(X)		    ;(10) SET NUMBER OF LINES TO EAT

	MAXSET==.-SETTAB		;MAXIMUM FUNCTION



;HERE TO SET WORD WITH WINDOW MOVING INFORMATION.


WNDSET:	PUSH	P,A		;SAVE UUO SINCE MAYBE MORE FUNCTIONS
	MOVE	A,T1		;SET UP ADDRESS OF DATA WE WANT
	PUSHJ	P,GETWRD	;OBTAIN THE REAL ARGUMENT
	MOVEM	T1,OVFVAL(X)	;SAVE IT
	POP	P,A		;RESTORE THE UUO
	POPJ	P,		;RETURN
	SUBTTL	FUNCTION TO RETURN LOCATION IN WINDOW


;THIS FUNCTION IS USED TO GET THE PRESENT LOCATION OF WHERE WE ARE
;OUTPUTTING ON THE SCREEN.  THIS WAY, USER PROGS CAN SEE IF THEY ARE
;OVERFLOWING WINDOWS, OR THEY CAN MAKE THEIR OUTPUT BETTER.  WE
;ALSO RETURN WHETHER OR NOT THE USER HAS OVERFLOWED THE WINDOW HE
;IS OUTPUTTING IN.  CALL IS:
;
;	LOC$	ADDRESS		;RETURN LOCATION ON SCREEN WE ARE AT
;	(RETURN)		;GOT IT IN LOCATION ADDRESS
;
;ADDRESS WILL CONTAIN    LINE,,POSITION    NORMALLY.  BUT IF THE
;PRESENT LINE HAS BEEN OVERFLOWED, POSITION = -1.  IF THE WHOLE
;WINDOW HAS BEEN OVERFLOWED,  THE WHOLE RESULT IS -1.




FUNLOC:	SETZ	C,		;MAKE A NULL, SO STORE ROUTINE RETURNS
	CAMLE	N,MAXN(X)	;ARE WE PAST RIGHT MARGIN?
	PUSHJ	P,OFFRHT	;MAYBE, GO MAKE SURE !!
	CAMLE	L,MAXL(X)	;SIMILARLY, ARE WE OFF END OF LAST WINDOW?
	PUSHJ	P,OVERFL	;MAYBE, MAKE ABSOLUTELY SURE !!
	CAMG	N,MAXN(X)	;ARE WE OFF THE RIGHT OF THE WINDOW?
	SKIPA	T1,N		;NO, GET POSITION IN T1
	MOVEI	T1,-1		;YES, SET RH TO -1 THEN
	CAMG	L,MAXL(X)	;NOW, HAVE WE OVERFLOWED ALL THE WINDOWS?
	TLOA	T1,(L)		;NO, SET LINE NUMBER IN LEFT HALF
	SETO	T1,		;YES, SET WHOLE RESULT TO -1
	PJRST	PUTWRD		;GO STORE VALUE AND RETURN
	SUBTTL	FUNCTION TO ADDRESS TO PARTICULAR SPOT ON SCREEN



;THIS FUNCTION IS USED IF THE USER WANTS TO MOVE THE CURSOR TO
;A PARTICULAR PLACE ON THE SCREEN.  WE REMEMBER THIS LOCATION
;FOR OURSELF TOO, SO THAT WE CAN MOVE FROM THERE TO WHERE WE
;WANT TO UPDATE THE SCREEN.  CALL IS:
;
;	ADR$	[FLAG+LINE,,COLUMN]	;GO TO GIVEN LOCATION
;
;IF THE FLAG BIT IS SET, WE DON'T ACTUALLY MOVE THERE, SO THE
;USER CAN INFORM US HE MOVED AROUND HIMSELF.



FUNADR:	PUSHJ	P,GETWRD	;READ USER'S WORD
	PUSH	P,N		;SAVE AC'S
	PUSH	P,L		;THAT WE DON'T WANT CHANGED
	HLRZ	L,T1		;GET LINE NUMBER
	ANDCMI	L,AD$NOM	;CLEAR THE FLAG BIT
	HRRZ	N,T1		;GET COLUMN NUMBER
	CAMG	L,T.LEN(U)	;ILLEGAL LINE NUMBER GIVEN?
	CAMLE	N,T.WID(U)	;OR ILLEGAL COLUMN POSITION?
	  DIE	IPG		;YES, LOSE
	TLNN	T1,AD$NOM	;WANTS TO ACTUALLY MOVE THERE?
	PUSHJ	P,MOVE		;YES, DO SO
	DMOVEM	L,TTYL(X)	;SAVE LOCATION WE ARE NOW AT
	POP	P,L		;RESTORE AC'S
	POP	P,N		;THAT WE DIDN'T WANT HURT
	POPJ	P,		;AND RETURN
	SUBTTL	FUNCTION TO OUTPUT SPECIAL THINGS STRAIGHT TO TTY


;THIS FUNCTION IS SO USER PROG CAN OUTPUT CERTAIN THINGS TO THE TTY
;WHILE NOT KNOWING HOW TO GO ABOUT IT.  THE THINGS WE CAN OUTPUT ARE
;PRETTY LIMITED, BUT THAT IS BECAUSE NOT EVERYTHING CAN BE DONE FOR
;A PARTICULAR TERMINAL.  CALL IS:
;
;	TTY$	FUNCTION	;OUTPUT SOMETHING
;	(RETURN)		;OK
;



FUNTTY:	MOVEI	A,(A)		;GET ARGUMENT BY ITSELF
	CAILE	A,TTYMAX	;TOO LARGE?
	DIE	ITF		;YES, DIE BIG
	PJRST	@TTYTAB(A)	;NO, OUTPUT IT AND RETURN




;THE THINGS WE OUTPUT FOLLOW



TTYTAB:	EXP	DOHOM		;(0) TO HOME UP
	EXP	DOCLR		;(1) TO HOME UP AND CLEAR THE SCREEN


	TTYMAX==.-TTYTAB-1	;MAXIMUM FUNCTION
	SUBTTL	SUBROUTINE TO SCAN A LINE FOR CHANGES


;THIS SUBROUTINE IS CALLED TO SCAN A LINE OF THE SCREEN, RETURN NICE
;THINGS ABOUT THE LINE WHICH NEED CHANGING.  CALL IS:
;
;	MOVE	L,LINE NUMBER		;SET UP LINE TO LOOK AT
;	PUSHJ	P,MINMAX		;FIND OUT ABOUT LINE CHANGES
;	(NO CHANGES)			;THIS LINE NEEDS NO CHANGING
;	(CHANGES NEEDED)		;CHANGES ARE TO BE DONE
;
;ON A SKIP RETURN, THE FOLLOWING INFORMATION IS KNOWN:
;
;	FSTCHG	-  FIRST COLUMN ON LINE WHICH NEEDS CHANGING
;	LSTCHG	-  LAST COLUMN ON LINE TO NEED CHANGING
;	PRECHG	-  LAST COLUMN PREVIOUS TO CURRENT COLUMN TO NEED CHANGING
;	LSTNON	-  LAST COLUMN ON LINE WHICH WASN'T A SPACE, -1 IF NONE




MINMAX:	MOVEI	T4,LINCHG(X)	;POINT AT LINE CHANGES
	HRLI	T4,L		;INSERT INDEX ACCUMULATOR
	SKIPE	@T4		;ANY CHANGES INDICATED FOR THIS LINE?
	AOSA	(P)		;YES, SET UP SKIP RETURN
	  POPJ	P,		;NO, NON-SKIP RETURN
	SETZM	@T4		;CLEAR CHANGE FLAG SINCE NOW ON LINE
	MOVE	T1,T.WRDS(U)	;GET NUMBER OF WORDS OF STORAGE PER LINE
	IMULI	T1,(L)		;MAKE OFFSET INTO SCREEN FOR THIS LINE
	ADD	T1,[POINT 9,SCREEN(X)] ;MAKE POINTER TO START OF LINE
	SETZB	T2,PRECHG	;INITIALIZE FOR LOOP
	SETOM	LSTNON		;MORE
	SETOM	LSTCHG		;MORE
	SETOM	FSTCHG		;AND MORE


;HERE TO LOOK AT NEXT CHARACTER ON THE LINE


MINNXT:	ILDB	T3,T1		;GRAB NEXT CHAR ON LINE
	TRZN	T3,UPDATE	;THIS POSITION CHANGED?
	  JRST	MINNOU		;NO, GO DO NEXT ONE
	SKIPGE	FSTCHG		;SAVED FIRST CHANGE COLUMN YET?
	MOVEM	T2,FSTCHG	;NO, THEN THIS IS FIRST
	MOVEM	T2,LSTCHG	;COLUMN IS LAST TO NEED CHANGING SO FAR
	CAMGE	T2,TTYN(X)	;BEFORE CURRENT TTY POSITION?
	MOVEM	T2,PRECHG	;YES, REMEMBER POSITION THEN
MINNOU:	CAIE	T3,SP		;IS THIS CHARACTER A SPACE?
	MOVEM	T2,LSTNON	;NO, REMEMBER LAST NON-SPACE COLUMN
	CAMGE	T2,T.WID(U)	;MORE CHARACTERS TO LOOK AT?
	AOJA	T2,MINNXT	;YES, KEEP GOING
	POPJ	P,		;NO, THEN RETURN ALL DONE
	SUBTTL	ROUTINE TO CLEAR THE REST OF A WINDOW


;THIS ROUTINE IS CALLED WHENEVER WE ARE DONE WITH A WINDOW.  THIS
;MEANS WHEN WINDOWS ARE CHANGED, OR WE UPDATE OR REFRESH THE SCREEN.
;THE PURPOSE OF THIS IS SO WHEN A USER DOESN'T FINISH FILLING THE
;WINDOW WITH DATA, THEN WINDOW DOESN'T HAVE OLD JUNK LEFT, IT IS
;EATEN AS IF HE TYPED INFINITE SPACES.



ZAPEND:	SETZM	EATNUM(X)	;CLEAR NUMBER OF LINES TO EAT
	TLNE	F,FL.OUT	;NOTHING BEEN OUTPUT IN WINDOW YET?
	TLNE	F,FL.NZP	;OR USER NOT WANT WINDOW CLEARED?
	  JRST	CLROVF		;YES, JUST CLEAR  OVFVAL AND RETURN
	TLO	F,FL.AC2	;SET SO WILL DO AUTO-CRLFS
	MOVEI	C,SP		;GET A SPACE

ZAPLOP:	PUSHJ	P,STORE1	;STUFF IT AWAY IN THE SCREEN
	CAMLE	L,MAXL(X)	;NOT DONE WITH WINDOW YET?
	SKIPE	OVFVAL(X)	;OR MORE WINDOWS LEFT TO CLEAR?
	JRST	ZAPLOP		;YES, THEN KEEP GIVING SPACES
	TLZ	F,FL.AC2	;CLEAR SPECIAL FLAG
	POPJ	P,		;AND RETURN
	SUBTTL	ROUTINES TO READ AND STORE WORDS FROM THE USER




;THESE ROUTINES ARE CALLED TO READ OR WRITE THE USER'S CORE.  THE
;REASON A STRAIGHT MOVE OR MOVEM IS IMPOSSIBLE IS BECAUSE THE ADDRESS
;TO USE MIGHT BE IN THE SAVED AC AREA, AND WE HAVE TO RELOCATE THE
;ADDRESS IN THIS CASE.



;HERE TO READ INTO T1 THE WORD POINTED TO BY AC A.  THE AC IS INCREMENTED
;ALSO, SO THAT SUCCESSIVE CALLS WILL READ SUCCESSIVE WORDS.


GETWRD:	MOVEI	A,1(A)		;CLEAR LEFT HALF AND INCREMENT
	CAIG	A,U+1		;IS THE WORD IN A SAVED AC?
	SKIPA	T1,SAVEF-1(A)	;YES, GET IT
	MOVE	T1,-1(A)	;NO, GET DIRECTLY THEN
	POPJ	P,		;AND RETURN




;HERE TO STORE THE CONTENTS OF AC T1 INTO THE ADDRESS GIVEN
;IN RIGHT HALF OF AC A.


PUTWRD:	ANDI	A,-1		;ONLY KEEP THE ADDRESS HALF
	CAIG	A,U		;IS IT ONE OF HIS AC'S WE SAVED?
	ADDI	A,SAVEF		;YES, OFFSET TO SAVED AREA
	MOVEM	T1,(A)		;SAVE THE WORD AWAY
	POPJ	P,		;AND RETURN
	SUBTTL	ROUTINE TO MAKE A BYTE POINTER


;ROUTINE TO TAKE THE PRESENT LINE AND CHARACTER POSITION (AS GIVEN IN
;AC'S L AND N) AND CONSTRUCT A BYTE POINTER WHICH POINTS TO THE BYTE
;JUST PRIOR TO THAT LOCATION.  POINTER IS RETURNED IN AC B.  CALL IS:
;
;	MOVEI	L,LINE		;SET UP DESIRED LINE NUMBER
;	MOVEI	N,CHAR		;AND DESIRED CHARACTER POSITION
;	PUSHJ	P,MAKEBP	;GENERATE BYTE POINTER
;	(RETURN)		;GOT IT IN AC B
;
;USES AC'S  T1, T2, AND B


MAKEBP:	MOVE	B,L		;GET LINE NUMBER
	IMUL	B,T.WRDS(U)	;MULTIPLY BY WORDS PER LINE
	MOVE	T1,N		;GET POSITION ON LINE
	IDIVI	T1,4		;DIVIDE BY CHARACTERS IN A WORD
	ADD	B,T1		;ADD IN WORDS IN THIS LINE WE ARE ON
	ADD	B,PNTTAB(T2)	;AND ADD WHICH BYTE, SCREEN LOCATION
	POPJ	P,		;AND RETURN




;THE LIST OF BYTE POINTERS FOR USE IN THE ABOVE ROUTINE


PNTTAB:	POINT	9,SCREEN-1(X),35	;LAST BYTE IN PREVIOUS WORD
	POINT	9,SCREEN(X),8		;FIRST BYTE IN THE WORD
	POINT	9,SCREEN(X),17		;SECOND BYTE IN THE WORD
	POINT	9,SCREEN(X),26		;THIRD BYTE IN THE WORD
	SUBTTL	ROUTINE TO MOVE TO A LOCATION ON THE SCREEN



;THIS ROUTINE IS CALLED WITH THE DESIRED POSITION TO MOVE TO IN
;AC'S L AND N, AND THE CURRENT TERMINAL CURSER POSITION IN LOCATIONS
;TTYL AND TTYN.  THE BEST WAY TO MOVE TO THE NEW POSITION IS CALCULATED,
;AND THE CURSER IS MOVED THERE THAT WAY.



MOVE:	CAMN	L,TTYL(X)	;SEE IF ALREADY AT DESIRED LOCATION
	CAME	N,TTYN(X)	;TO SAVE SOME WORK
	TROA	T1,-1		;NO, SET UP A LARGE NUMBER
	  POPJ	P,		;YES, THEN RETURN NOW
	HRRZM	T1,BEST		;SAVE LARGE NUMBER
	MOVEI	T1,[DIE	CDS]	;SET UP ERROR ROUTINE IN CASE CAN'T MOVE
	PUSHJ	P,CHKADR	;SEE HOW MANY CHARACTERS ADDRESSING TAKES
	CAML	L,TTYL(X)	;IS NEW LOCATION LOWER ON SCREEN?
	TDZA	T2,T2		;YES, CLEAR AC
	MOVEI	T2,1		;NO, SET LOW ORDER BIT
	CAMGE	N,TTYN(X)	;IS NEW LOCATION TO LEFT OF OLD?
	IORI	T2,2		;YES, SET BIT
	PJRST	@[ EXP	MOVDR		;DISPATCH FOR DOWN AND RIGHT
		   EXP	MOVUR		;UP AND RIGHT
		   EXP	MOVDL		;DOWN AND LEFT
		   EXP	MOVUL ](T2)	;UP AND LEFT



MOVDR:	PUSHJ	P,CHKDR		;SEE IF JUST MOVING IS BETTER
	PJRST	(T1)		;DISPATCH TO BEST ROUTINE

MOVDL:	PUSHJ	P,CHKDL		;SEE HOW GOOD DIRECT MOTION IS
	PUSHJ	P,CHKCDR	;SEE IF CR, DOWN, RIGHT IS BEST
	SKIPN	T.CR(U)		;CAN TERMINAL DO CR?
	PUSHJ	P,CHKHDR	;NO, THEN CHECK HOMING UP
	PJRST	(T1)		;DISPATCH TO BEST ROUTINE

MOVUR:	PUSHJ	P,CHKUR		;SEE HOW GOOD THE DIRECT ROUTE IS
	PUSHJ	P,CHKHDR	;SEE IF HOMING UP HELPS ANY
	PJRST	(T1)		;GO TO BEST ROUTINE

MOVUL:	PUSHJ	P,CHKUL		;CHECK OUT THE DIRECT MOTION
	PUSHJ	P,CHKHDR	;SEE HOW HOMING UP WORKS
	PUSHJ	P,CHKCUR	;SEE IF CR, UP AND RIGHT IS GOOD
	PJRST	(T1)		;DISPATCH TO BEST ROUTINE
;FOLLOWING ARE THE ROUTINES TO SEE IF A PARTICULAR WAY OF MOVING
;TAKES FEWER CHARACTERS THAN THE PRECEEDING WAYS.  LOWEST NUMBER OF
;CHARS IS IN ADDRESS BEST, AND ROUTINE WHICH DOES THAT ACTION IS IN T1.



;ROUTINE TO COMPUTE THE COST OF ADDRESSING.
;THIS ROUTINE KNOWS IT IS THE FIRST ROUTINE CALLED.


CHKADR:	SKIPN	T2,T.ADR(U)	;SEE IF ADDRESSING IS POSSIBLE
	  POPJ	P,		;NO, THEN RETURN
	TRNE	F,FR.ANS	;ANSI MODE ADDRESSING?
	JRST	ANSICK		;YES, DIFFERENT COMPUTATIONS
	ADD	T2,T.ADR2(U)	;ADD IN MORE CHARACTERS
	ADD	T2,T.ADR3(U)	;AND ADD IN MORE CHARS
	MOVEI	T2,2(T2)	;THEN ADD 2 CHARS FOR COORDINATES
CHKADF:	MOVEM	T2,BEST		;REMEMBER NUMBER OF CHARS NEEDED
	MOVEI	T1,DOADR	;SET UP ADDRESS FOR ADDRESSING
	POPJ	P,		;RETURN


ANSICK:	MOVEI	T1,1(N)		;GET COLUMN NUMBER
	PUSHJ	P,COLADD	;ADD IN DEPENDING ON SIZE
	MOVEI	T1,1(L)		;GET LINE NUMBER
	PUSHJ	P,COLADD	;ADD IN DEPENDING ON SIZE
	SKIPE	N		;ANY COLUMN?
	ADDI	T2,1		;YES, WILL NEED A SEMICOLON
	MOVEI	T2,1(T2)	;ACCOUNT FOR ENDING CHAR AND CLEAR JUNK
	JRST	CHKADF		;FINISH UP


COLADD:	CAIL	T1,^D100	;THREE DIGITS?
	ADDI	T2,1		;YES, COUNT IT
	CAIL	T1,^D10		;TWO DIGITS?
	ADDI	T2,1		;YES, COUNT IT
	CAIL	T1,2		;NEED ANY DIGITS?
	ADDI	T2,1		;YES, COUNT IT
	POPJ	P,		;DONE
;ROUTINE TO COMPUTE COST OF MOVING UP AND LEFT.


CHKUL:	SKIPE	T3,T.UP(U)	;CAN WE MOVE UP?
	SKIPN	T4,T.LEFT(U)	;AND CAN WE MOVE LEFT?
	  POPJ	P,		;NO, CAN'T DO THIS THEN
	MOVE	T2,TTYL(X)	;GET CURRENT LINE
	SUB	T2,L		;SUBTRACT DESIRED LINE
CHKANL:	IMULI	T2,(T3)		;COMPUTE CHARS NEEDED TO MOVE UP
	MOVE	T3,TTYN(X)	;GET CURRENT COLUMN
	SUB	T3,N		;AND SUBTRACT DESIRED COLUMN
CHKANY:	IMULI	T3,(T4)		;COMPUTE CHARS NEEDED TO MOVE LEFT
	MOVEI	T4,DOANY	;SET UP ROUTINE TO DO ACTION

CHKALL:	ADD	T2,T3		;ADD TOGETHER
	CAML	T2,BEST		;BETTER THAN OLD BEST?
	  POPJ	P,		;NO, RETURN
	MOVEM	T2,BEST		;YES, SAVE NUMBER
	MOVE	T1,T4		;AND ROUTINE TO DO IT
	MOVE	T4,TABNUM	;GET NUMBER OF TABS THAT WILL BE USED
	MOVEM	T4,TABUSE	;AND SET IT
	POPJ	P,		;RETURN
;ROUTINE TO COMPUTE COST OF MOVING DOWN AND LEFT.


CHKDL:	SKIPN	T3,T.DOWN(U)	;CAN WE MOVE DOWN?
	CAMN	L,TTYL(X)	;NO, BUT OK IF DON'T HAVE TO
	SKIPN	T4,T.LEFT(U)	;CAN WE MOVE LEFT TOO?
	  POPJ	P,		;NO, RETURN
	MOVE	T2,L		;GET DESIRED LINE NUMBER
	SUB	T2,TTYL(X)	;SUBTRACT PRESENT LINE
	JRST	CHKANL		;JOIN OTHER CODE




;ROUTINE TO COMPUTE COST OF MOVING DOWN AND RIGHT.


CHKDR:	SKIPN	T.DOWN(U)	;SEE IF CAN MOVE DOWN
	CAMN	L,TTYL(X)	;OR SEE IF DON'T NEED TO
	JRST	.+2		;OK, PROCEED
	  POPJ	P,		;CAN'T DO THIS, RETURN
	PUSHJ	P,CHKTAB	;COMPUTE COUNT FOR MOVING RIGHT
	MOVE	T3,L		;GET LINE TO MOVE TO
	SUB	T3,TTYL(X)	;SUBTRACT CURRENT LINE
	MOVE	T4,T.DOWN(U)	;GET NUMBER NEEDED TO GO DOWN
	JRST	CHKANY		;JOIN COMMON CODE




;ROUTINE TO COMPUTE COST OF MOVING UP AND RIGHT.


CHKUR:	SKIPN	T.UP(U)		;SEE IF WE CAN MOVE UP
	  POPJ	P,		;NO, RETURN
	PUSHJ	P,CHKTAB	;YES, COMPUTE COUNT FOR MOVING RIGHT
	MOVE	T3,TTYL(X)	;GET CURRENT LINE
	SUB	T3,L		;SUBTRACT DESTINATION LINE
	MOVE	T4,T.UP(U)	;GET CHARS NEEDED TO GO UP
	JRST	CHKANY		;JOIN OTHER CODE
;ROUTINE TO COMPUTE COST OF HOMING UP, THEN MOVING DOWN AND RIGHT.


CHKHDR:	SKIPN	T.DOWN(U)	;MAKE SURE WE CAN MOVE DOWN
	CAMN	L,TTYL(X)	;OR THAT WE DON'T HAVE TO
	SKIPN	T.HOM(U)	;AND MAKE SURE WE CAN HOME UP
	  POPJ	P,		;NO, THEN CAN'T DO THIS
	PUSH	P,TTYN(X)	;SAVE CURRENT POSITION
	SETZM	TTYN(X)		;CLEAR POSITION AS IF HOME WAS DONE
	PUSHJ	P,CHKTAB	;SEE HOW MANY TO MOVE RIGHT
	POP	P,TTYN(X)	;RESTORE TRUE COLUMN NUMBER
	MOVE	T3,T.HOM(U)	;GET CHARS NEEDED FOR CARRIAGE RETURN
	ADDI	T2,(T3)		;ADD INTO TOTAL
	HRRZ	T3,T.DOWN(U)	;GET CHARS NEEDED TO DO DOWN
	IMULI	T3,(L)		;MULTIPLY BY DESTINATION LINE
	MOVEI	T4,DOHDR	;GET ROUTINE FOR THIS ACTION
	JRST	CHKALL		;GO SEE IF THIS IS BEST



;ROUTINE TO COMPUTE COST OF DOING CR, THEN MOVING DOWN AND RIGHT.


CHKCDR:	SKIPN	T.DOWN(U)	;CAN WE MOVE DOWN?
	CAMN	L,TTYL(X)	;OR WE DON'T HAVE TO?
	SKIPN	T.CR(U)		;AND CAN WE DO A CARRIAGE RETURN?
	  POPJ	P,		;NO, RETURN
	PUSH	P,TTYN(X)	;SAVE CURRENT POSITION
	SETZM	TTYN(X)		;CLEAR POSITION AS IF A CR WAS DONE
	PUSHJ	P,CHKTAB	;AND COMPUTE COUNT FOR MOVING RIGHT
	POP	P,TTYN(X)	;RESTORE TRUE COLUMN NUMBER
	MOVE	T3,T.CR(U)	;GET CHARS USED FOR CARRIAGE RETURN
	ADDI	T2,(T3)		;ADD IT IN
	MOVE	T3,L		;GET DESTINATION LINE
	SUB	T3,TTYL(X)	;AND SUBTRACT CURRENT ONE
	MOVE	T4,T.DOWN(U)	;GET CHARS NEEDED TO MOVE DOWN
	IMULI	T3,(T4)		;FIND TOTAL CHARS TO MOVE DOWN
	MOVEI	T4,DOCDR	;GET ROUTINE TO DO ACTION
	JRST	CHKALL		;SEE IS THIS IS BEST METHOD
;ROUTINE TO COMPUTE COST OF DOING CARRIAGE RETURN, THEN UP AND RIGHT.


CHKCUR:	SKIPE	T.CR(U)		;SEE IF CAN DO CARRIAGE RETURN
	SKIPN	T.UP(U)		;AND SEE IF CAN GO UP
	  POPJ	P,		;NO, RETURN
	PUSH	P,TTYN(X)	;SAVE CURRENT COLUMN
	SETZM	TTYN(X)		;ASSUME WE DID A CARRIAGE RETURN
	PUSHJ	P,CHKTAB	;SEE HOW MANY TO MOVE RIGHT
	POP	P,TTYN(X)	;RESTORE TRUE COLUMN
	MOVE	T3,T.CR(U)	;GET CHARS NEEDED FOR CR
	ADDI	T2,(T3)		;ADD IN
	MOVE	T3,TTYL(X)	;GET CURRENT LINE NUMBER
	SUB	T3,L		;SUBTRACT DESTINATION LINE
	MOVE	T4,T.UP(U)	;GET COUNT TO MOVE UP
	IMULI	T3,(T4)		;FIND TOTAL CHARS NEEDED TO MOVE DOWN
	MOVEI	T4,DOCDR	;GET ROUTINE TO DO ACTION
	JRST	CHKALL		;AND SEE IF THIS IS BEST
;ROUTINE TO COMPUTE COST OF MOVING RIGHT.
;THIS IS A SUBROUTINE CALLED BY THE PREVIOUS ROUTINES.
;IT SAVES THE NUMBER OF TABS NEEDED FOR LATER.
;RETURNS WITH TOTAL CHARS NEEDED IN AC T2.


CHKTAB:	SETZB	T2,TABNUM	;CLEAR NUMBER OF TABS NEEDED
	CAMN	N,TTYN(X)	;ALREADY AT CORRECT COLUMN?
	  POPJ	P,		;YES, RETURN NOW
	TRNN	F,FR.TAB	;DOES THIS TERMINAL HAVE TABS?
	  JRST	CHKSPS		;NO, JUST MOVE RIGHT
	MOVE	T2,N		;GET COLUMN WE DESIRE TO GET TO
	IORI	T2,7		;MOVE TO FAR RIGHT OF TAB COLUMN
	SUB	T2,TTYN(X)	;SUBTRACT CURRENT POSITION
	LSH	T2,-3		;COMPUTE NUMBER OF TABS NEEDED
	MOVEM	T2,TABNUM	;SAVE NUMBER OF TABS NECESSARY
	TRNN	N,7		;GOING TO EXACT TAB STOP?
	  POPJ	P,		;YES, ALL DONE
	JUMPE	T2,CHKTBN	;JUMP SOME IF USING NO TABS
	MOVE	T3,N		;GET COLUMN MOVING TO
	TRZA	T3,7		;BACK UP TO PREVIOUS TAB STOP
CHKTBN:	MOVE	T3,TTYN(X)	;IF NO TABS, GET CURRENT POSITION
	MOVE	T2,N		;GET COPY OF POSITION
	SUB	T2,T3		;COMPUTE NUMBER OF SPACES NEEDED
	SKIPN	T4,T.LEFT(U)	;CAN WE GO LEFT?
	  JRST	CHKSPT		;NO, THEN ALWAYS MOVE RIGHT
	MOVEI	T3,^D10(N)	;GET COLUMN POSITION PLUS SOME
	CAMLE	T3,T.WID(U)	;GETTING NEAR END OF SCREEN?
	  JRST	CHKSPT		;YES, THEN CAN'T TAB AND BACK UP
	MOVE	T3,N		;GET COLUMN TO MOVE TO
	IORI	T3,7		;MOVE TO FAR RIGHT OF COLUMN
	SUBI	T3,-1(N)	;COMPUTE COLUMNS TO BACK UP BY
	IMULI	T3,(T4)		;MULTIPLY BY CHARS TO BACK UP 1 PLACE
	ADDI	T3,1		;ADD A CHAR DUE TO THE TAB
	CAML	T3,T2		;TAKES LESS CHARS TO BACK UP?
	  JRST	CHKSPT		;NO, GO USE SPACES
	AOS	T2,TABNUM	;YES, INCREMENT TAB COUNT
	ADDI	T2,-1(T3)	;ADD CHARS NEEDED TO BACKSPACE
	POPJ	P,		;AND RETURN


CHKSPS:	MOVE	T2,N		;GET COLUMN TO MOVE TO
	SUB	T2,TTYN(X)	;SUBTRACT COLUMN WE ARE AT
CHKSPT:	ADD	T2,TABNUM	;ADD IN TABS NEEDED
	POPJ	P,		;THEN RETURN
	SUBTTL	ROUTINES TO MOVE SLOWLY TO A LOCATION



;THESE ROUTINES ARE CALLED WITH THE COLUMN AND LINE NUMBERS IN N AND L,
;AND THE CURRENT POSITION IN TTYN AND TTYL.  THE ROUTINE MOVES THE
;CURSOR LEFT, RIGHT, UP, OR DOWN TO GET THERE.



DOHDR:	PUSHJ	P,DOHOM		;HOME UP
	JRST	DOANY		;THEN GO TO NORMAL CODE

DOCDR:	PUSHJ	P,DOCR		;DO A CARRIAGE RETURN FIRST
				;THEN FALL INTO NORMAL CODE



DOANY:	CAMN	L,TTYL(X)	;ALREADY AT RIGHT LINE?
	  JRST	MOVCOL		;YES, GO CHECK COLUMN
	CAMG	L,TTYL(X)	;WANT TO MOVE DOWN?
	  JRST	MOVUP		;NO, GO MOVE UP

MOVDWN:	PUSHJ	P,DODOWN	;YES, MOVE THAT WAY
	CAME	L,TTYL(X)	;AT RIGHT COLUMN YET?
	  JRST	MOVDWN		;NO, KEEP GOING
	JRST	MOVCOL		;YES, NOW CHECK COLUMN

MOVUP:	PUSHJ	P,DOUP		;MOVE UP
	CAME	L,TTYL(X)	;AT RIGHT LINE YET?
	  JRST	MOVUP		;NO, KEEP LOOKING





MOVCOL:	CAMLE	N,TTYN(X)	;WANT TO MOVE TO RIGHT?
	  JRST	MOVRHT		;YES, GO DO IT
MOVLFT:	CAMN	N,TTYN(X)	;AT RIGHT COLUMN YET?
	  POPJ	P,		;YES, RETURN
	PUSHJ	P,DOLEFT	;NO, GO LEFT
	JRST	MOVLFT		;AND CHECK AGAIN
MOVRHT:	SKIPN	T3,TABUSE	;ANY TABS USED TO MOVE RIGHT?
	  JRST	MOVSPS		;NO, GO USE SPACES
	PUSHJ	P,DOTAB		;YES, OUTPUT A TAB
	SOJG	T3,.-1		;LOOP UNTIL DID THEM ALL
	CAML	N,TTYN(X)	;DID WE TAB BEYOND DESTINATION?
	  JRST	MOVSPS		;NO, GO FINISH WITH SPACES

MOVBCK:	PUSHJ	P,DOLEFT	;YES, MOVE LEFT
	CAMN	N,TTYN(X)	;REACHED DESTINATION?
	  POPJ	P,		;YES, ALL DONE
	JRST	MOVBCK		;NO, KEEP GOING


MOVSPS:	CAMN	N,TTYN(X)	;AT DESTINATION YET?
	  POPJ	P,		;YES, RETURN
	MOVE	T1,TTYL(X)	;GET CURRENT LINE
	IMUL	T1,T.WRDS(U)	;MULTIPLY BY WORDS PER LINE
	MOVE	T2,TTYN(X)	;GET CURRENT COLUMN
	IDIVI	T2,4		;DIVIDE BY CHARS TO A WORD
	ADD	T2,T1		;ADD IN WORDS INTO THIS LINE
	ADD	T2,PNTTAB(T3)	;MAKE A BYTE POINTER
MOVSPL:	ILDB	C,T2		;GET CHAR AT THIS POSITION
	PUSHJ	P,DOONE		;OUTPUT IT
	CAME	N,TTYN(X)	;REACHED RIGHT PLACE YET?
	  JRST	MOVSPL		;NO, KEEP GOING
	POPJ	P,		;YES, DONE
	SUBTTL	SUBROUTINE TO ADDRESS



;CALLED WITH NEW X AND Y COORDINATES IN AC'S N AND L, TO ADDRESS TO
;THAT POSITION.  CAN ONLY BE CALLED FOR TERMINALS CAPABLE OF DOING
;ADDRESSING.





DOADR:	DMOVEM	L,TTYL(X)	;SET NEW TERMINAL CURSOR POSITION
	MOVE	T1,T.ADR(U)	;GET SEQUENCE TO START
	PUSHJ	P,SEQOUT	;OUTPUT IT
	TRNE	F,FR.ANS	;ANSI STYLE TERMINAL?
	JRST	ANSIAD		;YES, ADDRESSING DIFFERS
	HRRZ	T3,N		;GET POSITION ON LINE TO GO TO
	ADD	T3,T.XOFF(U)	;ADD IN OFFSET FOR OUTPUT
	HRRZ	C,L		;GET LINE NUMBER TO GO TO
	ADD	C,T.YOFF(U)	;ADD IN ITS OFFSET ALSO
	TRNE	F,FR.XBY	;SHOULD X COORDINATE BE FIRST?
	EXCH	C,T3		;YES, SWAP THE COORDINATES
	PUSHJ	P,TTYOUT	;OUTPUT THE FIRST COORDINATE
	SKIPE	T1,T.ADR2(U)	;ANY FILLER BETWEEN COORDINATES?
	PUSHJ	P,SEQOUT	;YES, OUTPUT THAT
	MOVE	C,T3		;GET SECOND COORDINATE
	PUSHJ	P,TTYOUT	;OUTPUT IT
	SKIPE	T1,T.ADR3(U)	;ANY FILLS AFTER COORDINATE?
	JRST	SEQOUT		;YES, GO GIVE IT AND RETURN
	POPJ	P,		;NO, ALL DONE



ANSIAD:	SKIPE	T1,L		;ANY LINE POSITION?
	PUSHJ	P,DECOU1	;YES, OUTPUT IT
	JUMPE	N,ANSIAE	;SKIP SOME IF AT FIRST COLUMN
	MOVEI	C,";"		;GET SEPARATOR CHAR
	PUSHJ	P,TTYOUT	;OUTPUT IT
	MOVE	T1,N		;GET COLUMN
	PUSHJ	P,DECOU1	;OUTPUT IT
ANSIAE:	MOVEI	C,"H"		;GET ENDING CHAR
	JRST	TTYOUT		;OUTPUT IT
	SUBTTL	SPECIAL SEQUENCE OUTPUT ROUTINES




;HERE TO OUTPUT SPECIAL SEQUENCES OF CHARACTERS FOR A TERMINAL.
;THESE ROUTINES KEEP THE VALUES OF TTYN AND TTYL CORRECT.
;THESE ROUTINE CAN USE T1, T2, AND C.




DOTAB:	MOVEI	C,7		;GET SET
	IORM	C,TTYN(X)	;SET TO FAR RIGHT OF CURRENT COLUMN
	AOS	TTYN(X)		;THEN MOVE TO NEXT TAB STOP
	MOVEI	C,TAB		;GET A TAB CHARACTER
	PJRST	TTYOUT		;OUTPUT IT AND RETURN



DOEOL:	MOVE	T3,LSTNON	;GET LOCATION OF LAST NONSPACE
	CAMGE	T3,LSTCHG	;IS LAST CHANGE BEYOND THAT?
	MOVE	T3,LSTCHG	;YES, GET THAT LOCATION
	SUB	T3,TTYN(X)	;GET NUMBER OF SPACES TO CLEAR LINE
	ADDI	T3,1		;ADD ONE MORE
	SKIPE	T1,T.EOL(U)	;GET SEQUENCE TO DO END OF LINE
	CAIGE	T3,(T1)		;AND SEE IF FASTER TO TYPE SPACES
	SKIPA	C,[SP]		;YES, GET A SPACE
	  PJRST	SEQOUT		;NO, FASTER TO DO END OF LINE SEQUENCE
	PUSHJ	P,DOONE		;OUTPUT A SPACE
	SOJG	T3,.-1		;LOOP REQUIRED TIMES
	POPJ	P,		;THEN RETURN


DOUP:	SOSA	TTYL(X)		;DECREMENT TERMINAL'S LINE NUMBER
DODOWN:	AOSA	TTYL(X)		;OR INCREMENT LINE NUMBER
	SKIPA	T1,T.UP(U)	;THEN GET SEQUENCE TO MOVE UP
	MOVE	T1,T.DOWN(U)	;OR SEQUENCE TO MOVE DOWN
	JRST	SEQOUT		;GO OUTPUT IT


DOCR:	SETZM	TTYN(X)		;CLEAR COLUMN USER SEES CURSER AT
	MOVE	T1,T.CR(U)	;GET SEQUENCE TO DO CR
	JRST	SEQOUT		;GO OUTPUT IT
DOLEFT:	SOSA	TTYN(X)		;DECREMENT COLUMN NUMBER
DORHT:	AOSA	TTYN(X)		;OR INCREMENT IT
	SKIPA	T1,T.LEFT(U)	;GET SEQUENCE TO MOVE LEFT
	MOVE	T1,T.RHT(U)	;OR SEQUENCE TO MOVE RIGHT
	JRST	SEQOUT		;OUTPUT IT AND RETURN



DOONE:	CAIN	C,SP		;OUTPUTTING A SPACE?
	MOVE	C,T.EATC(U)	;YES, CONVERT TO EATING CHAR
	AOS	T1,TTYN(X)	;INCREMENT COLUMN NUMBER
	CAMG	T1,T.WID(U)	;AT LAST COLUMN ON LINE?
	  JRST	TTYOUT		;NO, JUST OUTPUT CHAR AND RETURN
	SOS	TTYN(X)		;YES, BACK UP POSITION
	TRNN	F,FR.ELC	;GET A CRLF TYPING LAST COLUMN?
	  JRST	TTYOUT		;NO, THEN TYPE THE CHAR AND RETURN
	MOVE	T1,TTYL(X)	;GET CURRENT LINE
	CAML	T1,T.LEN(U)	;ON LAST LINE?
	  POPJ	P,		;YES, DON'T TYPE CHAR OR ELSE SCREEN SCROLLS!
	SETZM	TTYN(X)		;NO, CLEAR COLUMN
	AOS	TTYL(X)		;INCREMENT LINE NUMBER
	PJRST	TTYOUT		;THEN OUTPUT CHARACTER



DOCLR:	SKIPA	T1,T.CLR(U)	;GET SEQUENCE TO HOME AND CLEAR
DOHOM:	MOVE	T1,T.HOM(U)	;OR GET SEQUENCE TO JUST HOME
	SETZM	TTYL(X)		;RESET LINE POSITION USER SEES
	SETZM	TTYN(X)		;AND THE COLUMN POSITION
;	PJRST	SEQOUT		;GO OUTPUT IT
	SUBTTL	ROUTINES TO OUTPUT SEQUENCES OF CHARACTERS




;THIS ROUTINE IS CALLED WITH THE STANDARD POINTER TO A SEQUENCE OF
;CHARACTERS TO BE OUTPUT IN AC T1.  SUCH A POINTER IS OF THE FORM
; ADDR,,N  WHERE N IS THE NUMBER OF CHARACTERS IN THE STRING, AND
;ADDR IS THE ADDRESS OF THE STRING.




SEQOUT:	HLRZ	T2,T1		;GET ADDRESS OF STRING
	HRLI	T2,(POINT 7,)	;AND MAKE BYTE POINTER TO IT
	ANDI	T1,-1		;KEEP ONLY COUNT
	JUMPE	T1,[DIE CDS]	;IF NO CHARS, DIE

SEQOUL:	ILDB	C,T2		;GET NEXT CHARACTER IN SEQUENCE
	SOJLE	T1,TTYOUT	;IF LAST CHAR, GO OUTPUT AND RETURN
	PUSHJ	P,TTYOUT	;OUTPUT TO TERMINAL
	JRST	SEQOUL		;LOOP





;CALLED TO OUTPUT A DECIMAL NUMBER IN T1.  USED FOR ANSI MODE ADDRESSING,
;WHERE COORDINATES ARE DECIMAL INTEGERS.


DECOU1:	ADDI	T1,1		;COORDINATES ARE OFFSET BY ONE
DECOUT:	IDIVI	T1,^D10		;SPLIT OFF A DIGIT
	JUMPE	T1,DECFIN	;JUMP IF DONE
	HRLM	T2,(P)		;SAVE DIGIT
	PUSHJ	P,DECOUT	;LOOP UNTIL HAVE ALL DIGITS
	HLRZ	T2,(P)		;GET BACK A DIGIT
DECFIN:	MOVEI	C,"0"(T2)	;MAKE INTO ASCII
	JRST	TTYOUT		;OUTPUT IT AND RETURN
	SUBTTL	ROUTINES TO CLEAR OR SET IMAGE STATE FOR TERMINAL




;CALLED TO SET THE MODE OF THE TERMINAL TO BE IMAGE MODE.  THIS MODE
;IS NECESSARY TO PREVENT THE CONVERSION OF OUR OUTPUT CHARACTERS TO
;DIFFERENT ONES.  IN ADDITION, THE TERMINAL OUTPUT BUFFER IS SET UP.
;NO AC'S ARE CHANGED.  THIS ROUTINE IS NOT NECESSARY FOR TOPS-10.




	IF20,<

SETIMG:	PUSH	P,[POINT 7,TTYBUF(X)] ;GET BYTE POINTER
	POP	P,BUFPTR(X)	;INITIALIZE IT
	SKIPE	TTYJFN(X)	;NEED TO GET A JFN?
	  POPJ	P,		;NO, THEN ALL SET
	PUSH	P,T1		;SAVE SOME AC'S
	PUSH	P,T2		;THAT WE USE
	MOVSI	T1,(GJ%SHT+GJ%ACC)	;SHORT FORM, RESTRICTED
	HRROI	T2,[ASCIZ/TTY:/]	;OUR TERMINAL
	GTJFN			;GET THE JFN
	  DIE	IFF		;CAN'T
	MOVEM	T1,TTYJFN(X)	;SAVE THE JFN
	MOVE	T2,[8B5+OF%WR+OF%RD]	;SET FOR BINARY
	OPENF			;OPEN THE TERMINAL
	  DIE	IFF		;FAILED
	POP	P,T2		;RESTORE THE ACS
	POP	P,T1		;THAT WERE USED
	POPJ	P,		;RETURN
>
	SUBTTL	ROUTINE TO OUTPUT CHARS TO TTY OR TO USER PROGRAM



;SUBROUTINE TO SEND CHARACTERS OUT.  OUTPUT CAN BE SENT TO THE PROGRAM
;IF DESIRED.  OTHERWISE WE BUFFER UP CHARACTERS AND SEND THEM OUT
;OURSELVES.  CHARACTER TO BE OUTPUT IS IN AC C.




TTYOUT:	SKIPE	OUTADR(X)	;OUTPUT BEING INTERCEPTED?
	  JRST	USROUT		;YES, GO GIVE IT TO PROGRAM

IF20,<	TLON	F,FL.PNT	;FIRST OUTPUT?
	PUSHJ	P,SETIMG	;YES, SET UP BUFFERS AND JFN
	IDPB	C,BUFPTR(X)	;STORE CHAR IN BUFFER
	PUSH	P,T1		;SAVE AN AC
	AOS	T1,BUFCNT(X)	;INCREMENT COUNT OF STORED CHARACTERS
	CAIL	T1,<TTYLEN*5>-1	;IS BUFFER FULL YET?
	PUSHJ	P,PUNT		;YES, FORCE OUT BUFFER
	POP	P,T1		;RESTORE AC
	POPJ	P,		;RETURN
>


IF10,<	SKIPN	TTYJFN(X)	;HAVE ANY CHANNEL TO OUTPUT TO?
	IONEOU	C		;NO, OUTPUT STRAIGHT
	SKIPN	TTYJFN(X)	;WELL?
	  POPJ	P,		;NO, DONE
	PUSH	P,T1		;SAVE AN AC
	HLRZ	T1,TTYJFN(X)	;GET BUFFER HEADER ADDRESS
	SOSG	2(T1)		;ANY MORE ROOM LEFT IN BUFFER?
	PUSHJ	P,PUNT		;NO, FORCE OUTPUT NOW
	IDPB	C,1(T1)		;STORE THE CHARACTER
	TLO	F,FL.PNT	;REMEMBER OUTPUT EXISTS
	POP	P,T1		;RESTORE AC
	POPJ	P,		;DONE
>
	SUBTTL	ROUTINE TO FORCE OUT ALL OF TERMINAL OUTPUT SO FAR




;ROUTINE TO FORCE OUT TO THE TERMINAL ALL STORED CHARACTERS.
;NO AC'S ARE CHANGED.



PUNT:	IF20,<
	TLZ	F,FL.PNT	;NO LONGER NEED TO PUNT OUTPUT
	SKIPN	BUFCNT(X)	;ANY CHARACTERS TO BE OUTPUT?
	  POPJ	P,		;NO, JUST RETURN
	PUSH	P,T1		;YES, SAVE AN AC
	PUSH	P,T2		;SAVE SOME MORE AC'S
	PUSH	P,T3		;THAT WE NEED
	MOVE	T1,TTYJFN(X)	;GET JFN FOR OUTPUT
	HRROI	T2,TTYBUF(X)	;FROM TEXT BUFFER
	MOVN	T3,BUFCNT(X)	;GET COUNT OF CHARACTERS
	SOUT			;OUTPUT THE CHARS
	SETZM	BUFCNT(X)	;CLEAR COUNT
	MOVE	T1,[POINT 7,TTYBUF(X)] 	;GET A NEW BYTE POINTER
	MOVEM	T1,BUFPTR(X)	;AND RESET IT
	POP	P,T3		;RESTORE AC'S
	POP	P,T2		;THAT WERE SAVED
	POP	P,T1		;RESTORE THE AC
	POPJ	P,		;AND RETURN
>



	IF10,<

	TLZ	F,FL.PNT	;NO LONGER NEED TO PUNT OUTPUT
	SKIPN	TTYJFN(X)	;ANY OUTPUT CHANNEL SET UP?
	  POPJ	P,		;NO, DO NOTHING
	MOVEM	T1,TEMP		;SAVE AN AC
	HRLZ	T1,TTYJFN(X)	;GET CHANNEL
	LSH	T1,5		;POSITION TO AC FIELD
	TLO	T1,(<OUT 0,>)	;FINISH THE INSTRUCTION
	EXCH	T1,TEMP		;RESTORE AC AND STORE INSTRUCTION
	XCT	TEMP		;DO THE I/O
	  POPJ	P,		;DONE
	DIE	OPF		;FAILED
>
	SUBTTL	ROUTINE TO GIVE CHARS TO USER'S PROGRAM



;HERE WHEN USER WANTS TO GET OUTPUT WE WOULD NORMALLY GIVE TO THE
;TERMINAL.  THE USER HAS THE CHOICE OF HAVING HIS ORIGINAL AC'S, OR
;TO BE FASTER, IF FLAG FL.NZP  IS SET, WE JUMP DIRECTLY TO
;HIS ROUTINE, ASSUMING HE DOESN'T HURT ANY AC'S.  WE GIVE HIM ONE
;CHARACTER AT A TIME.  THE USER DOES THE FOLLOWING:
;
;	POP	P,AC		;BRING THE CHARACTER OFF OF THE STACK
;	   .
;	   .			; (THE USER'S RANDOM CODE)
;	   .
;	POPJ	P,		;RETURN TO DPY AND CONTINUE AS BEFORE
;
;CALL AT USRLST WHEN ALL OUTPUT FOR THIS UUO IS FINISHED, TO NOTIFY
;THE PROGRAM THAT WE ARE DONE BY SENDING A CHARACTER WITH 1B0 SET.




USRLST:	MOVSI	C,(1B0)		;FLAG THIS AS LAST OUTPUT
USROUT:	TLNN	F,FL.NZP	;DOES USER WANT HIS OWN ACS?
	  JRST	USRPAI		;YES, GO DO WORK
	PUSH	P,C		;NO, THEN JUST PUSH THE CHAR
	PJRST	@OUTADR(X)	;AND GO TO USER'S ROUTINE


;HERE IF WE MUST SAVE THE AC'S BEFORE CALLING USER


USRPAI:	PUSH	P,[USRRET]	;PUT THE RETURN ADDRESS ON THE STACK
	PUSH	P,C		;AND PUT THE CHARACTER ON TOO
	MOVEM	F,OURF(X)	;SAVE AN AC OF OURS
	MOVEI	F,@OUTADR(X)	;GET ADDRESS OF ROUTINE TO GO TO
	MOVEM	F,TEMP		;SAVE IT
	HRLI	F,T1		;SET UP
	HRRI	F,OURT1(X)	;BLT POINTER
	BLT	F,OURBU+1(X)	;SAVE ALL OF OUR AC'S
	MOVSI	U,SAVEF		;NOW GET SET
	BLT	U,U		;RESTORE ALL THE USER'S AC'S
	JRST	@TEMP		;AND GO TO THE USER'S ROUTINE


USRRET:	MOVEM	F,SAVEF		;SAVE A USER'S AC
	MOVE	F,[T1,,SAVET1]	;GET SET
	BLT	F,SAVEU		;SAVE ALL OF USER'S AC'S WE USE
	MOVE	X,@DP+$DPADR	;RESTORE RELOCATION AC
	MOVSI	U,OURF(X)	;GET SET
	BLT	U,U		;RESTORE OUR OWN AC'S
	POPJ	P,		;AND RETURN FROM THIS BIG MESS
	SUBTTL	THE ERROR ROUTINE


;WE GET HERE FROM ONE OF THE  DIE  CALLS, TO DIE.  WE EITHER OUTPUT A
;MESSAGE AND EXIT, OR GO BACK TO THE USER WITH AN ERROR CODE.  THE CALL IS:
;
;	XCT	CODE,DIEBIG	;GO DIE, AND GIVE ERROR CODE IN AC FIELD
;
;THERE IS NO RETURN.  IF THE USER TRAPPED THE ERROR, HE CAN DO THE FOLLOWING:
;
;	POP	P,LOCATION	;RESTORE THE ERROR CODE
;	POPJ	P,		;RETURN TO LOCATION AFTER DPY
;				;CALL WHICH FAILED


DIEBIG:	JSP	T2,.+1		;REMEMBER PC SO CAN GET ERROR CODE
	LDB	T2,[POINT 4,-1(T2),12]	;GRAB THE CODE
	CAILE	T2,MAXERR	;IS IT ILLEGAL !!!!????
	SETZ	T2,		;YES, TAME IT SOMEWHAT
	SKIPE	ERRADR(X)	;DID USER GIVE US A TRAP ADDRESS?
	  JRST	TRAP		;YES, GO TO HIM THEN


IF10,<	OUTSTR	[ASCIZ/
? DPY - /]			;NO, THEN GIVE SOME OF MESSAGE
	OUTSTR	@ERRTAB(T2)	;AND REST
	EXIT	1,		;THEN EXIT
	JRST	.-1		;AND STAY THAT WAY
>


IF20,<	HRROI	T1,[ASCIZ/
? DPY - /]			;GET SOME OF MESSAGE
	PSOUT			;OUTPUT IT
	HRROI	T1,@ERRTAB(T2)	;GET REST OF TEXT
	PSOUT			;OUTPUT IT TOO
	HALTF			;QUIT
	JRST	.-1		;AND STAY THAT WAY
>



;HERE TO RETURN TO THE USER WITH THE ERROR CODE


TRAP:	MOVE	P,SAVEP		;RESTORE A POINTER WE KNOW IS GOOD
	PUSH	P,T2		;SAVE THE ERROR CODE ON IT
	MOVE	T1,ERRADR(X)	;GET ADDRESS WHERE TO TRAP TO
	MOVEM	T1,TEMP		;SAVE IN KNOWN PLACE
	PUSHJ	P,RETURN	;RESTORE THE USER'S AC'S
	JRST	@TEMP		;JUMP BACK TO USER
;HERE ARE THE POSSIBLE ERRORS




ERRTAB:	ERR	UKE,Unknown error
	ERR	ILR,Illegal luuo received
	ERR	USL,Updated same location twice
	ERR	IWS,Illegal window size given
	ERR	ISF,Illegal set function given
	ERR	ITF,Illegal tty function given
	ERR	CDS,Cannot output desired sequence
	ERR	OPF,Output error occurred
	ERR	IPG,Illegal terminal address given
	ERR	ING,Initialize function not given
	ERR	IFF,Initialize function failed


	MAXERR==.-ERRTAB-1	;THE MAXIMUM ERROR
	SUBTTL	CONSTANTS AVAILABLE TO USER PROGRAM


;THE FOLLOWING TABLE IS INCLUDED SO THAT THE USER PROGRAM
;CAN READ SOME PARAMETERS WHICH DPY USES.  THESE ARE REFERENCED
;BY THEIR OFFSET INTO THE DPYTAB TABLE.




DP:				;ALTERNATIVE LABEL
DPYTAB:	EXP	DATBEG+TERSIZ	;(0)  POINTER TO TERMINAL LENGTH
	EXP	DATBEG+TERSIZ+1	;(1)  POINTER TO TERMINAL WIDTH
	EXP	DATBEG+MINL	;(2)  POINTER TO PRESENT WINDOW SIZE
	EXP	DATBEG+OVFVAL	;(3)  POINTER TO CURRENT WINDOW COUNTER
	EXP	DATLEN		;(4)  LENGTH OF IMPORTANT DATA
	EXP	DATADR		;(5)  POINTER TO ADDRESS OF THE DATA
	EXP	DATBEG+SCREEN	;(6)  ADDRESS OF STORAGE FOR SCREEN
	XWD	MAXERR,ERRTAB	;(7)  ERROR TABLE -- NOTE NOT RELOCATABLE
	EXP	TTYTYP		;(10) POINTER TO TERMINAL TYPE TABLE
	EXP	DATBEG+TTYJFN	;(11) POINTER TO JFN USING FOR TTY
	EXP	DATBEG+EATNUM	;(12) POINTER TO NUMBER OF LINES TO EAT
	SUBTTL	LOW SEGMENT STORAGE


;FIRST, DUMP OUT ALL THE HIGH-SEG LITERALS

	XLIST		;LITERALS
	LIT
	LIST



;HERE IS THE ACTUAL DATA REQUIRED BY THE PROGRAM.  THESE ARE IN THE
;LOW SEGMENT SO THAT THE PROGRAM CAN BE PURE.


	RELOC	0		;MOVE TO LOW SEGMENT NOW


SAVEF:	BLOCK	1		;STORAGE OF THE USER'S AC'S
SAVET1:	BLOCK	1
SAVET2:	BLOCK	1
SAVET3:	BLOCK	1
SAVET4:	BLOCK	1
SAVEX:	BLOCK	1
SAVEC:	BLOCK	1
SAVEA:	BLOCK	1
SAVEL:	BLOCK	1
SAVEN:	BLOCK	1
SAVEB:	BLOCK	1
SAVEU:	BLOCK	1
ZERO:	BLOCK	1		;CONTAINS ZERO
SAVEP:	BLOCK	1		;PUSH-POINTER STORED IN CASE OF ERROR
TEMP:	BLOCK	1		;TEMPORARY STORAGE
DATADR:	BLOCK	1		;ADDRESS OF THE RELOCATABLE DATA
INIFLG:	BLOCK	1		;FLAGS FROM INI$ FUNCTION
INICNT:	BLOCK	1		;NUMBER OF ARGUMENTS IN INI$ FUNCTION
BEST:	BLOCK	1		;LOWEST NUMBER OF CHARS TO MOVE CURSER
TABNUM:	BLOCK	1		;NUMBER OF TABS NEEDED TO MOVE TO RIGHT
TABUSE:	BLOCK	1		;TABS NEEDED IN BEST CASE
FSTCHG:	BLOCK	1		;FIRST PLACE ON A LINE NEEDING CHANGING
LSTCHG:	BLOCK	1		;LAST PLACE ON A LINE TO NEED CHANGING
PRECHG:	BLOCK	1		;LAST PLACE TO CHANGE PRECEEDING PRESENT
				;LOCATION ON A LINE
LSTNON:	BLOCK	1		;THE LOCATION OF THE LAST NON-SPACE
;THE FOLLOWING DATA IS REFERENCED BY INDEXING OFF OF AC X.  THUS THE ACTUAL
;ADDRESS OF THE DATA IS VARIABLE, AND CAN BE SET BY THE USER.


	DEFINE	WD(SYM,LEN<1>),<	;;MACRO TO DEFINE OFFSETS
SYM:!	BLOCK	LEN
>


DATBEG:	PHASE 0			;THIS DATA IS PHASED SINCE INDEXED OFF OF X

	WD	OURF		;STORAGE FOR OUR AC'S
	WD	OURT1
	WD	OURT2
	WD	OURT3
	WD	OURT4
	WD	OURX
	WD	OURC
	WD	OURA
	WD	OURLN,2		;STORAGE FOR ACS L AND N
	WD	OURBU,2		;STORAGE FOR ACS B AND U
	WD	MINL		;LOWEST LINE NUMBER IN CURRENT WINDOW
	WD	MAXL		;HIGHEST LINE NUMBER IN WINDOW
	WD	MINN		;LOWEST COLUMN NUMBER IN WINDOW
	WD	MAXN		;HIGHEST COLUMN NUMBER IN WINDOW
	WD	TTYL		;LINE NUMBER THE TTY CURSER IS AT NOW
	WD	TTYN		;COLUMN NUMBER THE TTY CURSER IS AT NOW
	WD	BUFPTR		;BYTE POINTER INTO TTY BUFFER
	WD	BUFCNT		;NUMBER OF CHARACTERS IN TTY BUFFER
	WD	TTYBUF,TTYLEN	;TTY BUFFER
	WD	TERSIZ,2	;TERMINAL'S LENGTH AND WIDTH
	WD	TTYJFN		;JFN OR BUFFER,,CHANNEL FOR OUTPUT
	WD	TABS,4		;BIT TABLE FOR TAB STOPS
	WD	SCREEN,MAXARE	;SCREEN STORAGE


;THE REMAINING LOCATIONS ARE CLEARED ON INITIALIZATION:


ZERBLK:	WD	OUTADR		;ADDRESS OF ROUTINE TO GIVE OUTPUT CHARS TO
	WD	ERRADR		;ADDRESS OF ROUTINE TO GO TO ON FATAL ERRORS
	WD	OVFVAL		;WINDOW MOVING INFORMATION WHEN ONE FILLS UP
	WD	EATNUM		;NUMBER OF LINES TO IGNORE FROM USER
	WD	LINCHG,MAXLEN	;FLAGS TO KNOW IF A LINE HAS BEEN CHANGED

	ZEREND==.-1		;LAST LOCATION TO ZERO


DATLEN:	DEPHASE			;LENGTH OF RELOCATABLE DATA


	END