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