Trailing-Edge
-
PDP-10 Archives
-
bb-m836c-bm_tops20_v6_1_tools
-
tools/sysdpy/dpy.mac
There are 24 other files named dpy.mac in the archive. Click here to see a list.
;TCO 6.1.1427 - Add definitions for VT200.
; UPD ID= 8, SNARK:<6.TOOLS-TAPE>DPY.MAC.2, 14-Dec-82 13:42:07 by PAETZOLD
;TCO 6.1415 - Add definitions for VT102 and VT125
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
;OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) DIGITAL EQUIPMENT CORPORATION 1976, 1985.
;ALL RIGHTS RESERVED.
TITLE DPY MODULE TO MAKE CRT DISPLAYS EASY
SUBTTL DEFINITIONS
;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(VT102,VT102,.TT102,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(VT125,VT125,.TT125,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(VT200,VT200,.TT200,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 l